From ffa9a7df29008d66b4173835f0b1785eeaeb7e99 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Wed, 22 Oct 2025 14:42:31 +0800 Subject: [PATCH 01/22] test: add e2e for evm ref cmd wait 2 blks --- .gitignore | 5 + tests/integration_tests/__init__.py | 0 .../integration_tests/configs/chains.jsonnet | 34 + .../integration_tests/configs/default.jsonnet | 185 ++ .../configs/enable-indexer.jsonnet | 16 + tests/integration_tests/conftest.py | 86 + tests/integration_tests/cosmoscli.py | 127 + tests/integration_tests/network.py | 170 + tests/integration_tests/poetry.lock | 2867 +++++++++++++++++ tests/integration_tests/pyproject.toml | 40 + tests/integration_tests/shell.nix | 16 + tests/integration_tests/test_account.py | 14 + tests/integration_tests/utils.py | 1046 ++++++ tests/nix/default.nix | 18 + tests/nix/sources.json | 63 + tests/nix/sources.nix | 232 ++ tests/nix/testenv.nix | 39 + tests/scripts/env.template | 19 + tests/scripts/export_envs.sh | 41 + tests/scripts/restore_envs.sh | 35 + tests/scripts/run-integration-tests.sh | 49 + 21 files changed, 5102 insertions(+) create mode 100644 tests/integration_tests/__init__.py create mode 100644 tests/integration_tests/configs/chains.jsonnet create mode 100644 tests/integration_tests/configs/default.jsonnet create mode 100644 tests/integration_tests/configs/enable-indexer.jsonnet create mode 100644 tests/integration_tests/conftest.py create mode 100644 tests/integration_tests/cosmoscli.py create mode 100644 tests/integration_tests/network.py create mode 100644 tests/integration_tests/poetry.lock create mode 100644 tests/integration_tests/pyproject.toml create mode 100644 tests/integration_tests/shell.nix create mode 100644 tests/integration_tests/test_account.py create mode 100644 tests/integration_tests/utils.py create mode 100644 tests/nix/default.nix create mode 100644 tests/nix/sources.json create mode 100644 tests/nix/sources.nix create mode 100644 tests/nix/testenv.nix create mode 100644 tests/scripts/env.template create mode 100755 tests/scripts/export_envs.sh create mode 100755 tests/scripts/restore_envs.sh create mode 100755 tests/scripts/run-integration-tests.sh diff --git a/.gitignore b/.gitignore index 4d3b9e835..65ed582ad 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,8 @@ build/ tests/systemtests/binaries tests/systemtests/testnet .testnets + +# Environments +*.env +.envrc +.venv diff --git a/tests/integration_tests/__init__.py b/tests/integration_tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/integration_tests/configs/chains.jsonnet b/tests/integration_tests/configs/chains.jsonnet new file mode 100644 index 000000000..6461d4b4c --- /dev/null +++ b/tests/integration_tests/configs/chains.jsonnet @@ -0,0 +1,34 @@ +{ + evmd: { + 'account-prefix': 'cosmos', + evm_denom: 'atest', + cmd: 'evmd', + evm_chain_id: 262144, + bank: { + denom_metadata: [{ + description: 'Native 18-decimal denom metadata for Cosmos EVM chain', + denom_units: [ + { + denom: 'atest', + exponent: 0, + }, + { + denom: 'test', + exponent: 18, + }, + ], + base: 'atest', + display: 'test', + name: 'Cosmos EVM', + symbol: 'ATOM', + }], + }, + evm: {}, + feemarket: { + params: { + base_fee: '1000000000', + min_gas_price: '0', + }, + }, + }, +} diff --git a/tests/integration_tests/configs/default.jsonnet b/tests/integration_tests/configs/default.jsonnet new file mode 100644 index 000000000..47ca6325e --- /dev/null +++ b/tests/integration_tests/configs/default.jsonnet @@ -0,0 +1,185 @@ +local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; + +{ + dotenv: '../../scripts/.env', + 'evm-canary-net-1': { + cmd: chain.cmd, + 'start-flags': '--trace', + config: { + mempool: { + version: 'v1', + }, + }, + 'app-config': { + evm: { + 'evm-chain-id': chain.evm_chain_id, + }, + grpc: { + 'skip-check-header': true, + }, + 'minimum-gas-prices': '0' + chain.evm_denom, + 'index-events': ['ethereum_tx.ethereumTxHash'], + 'iavl-lazy-loading': true, + 'json-rpc': { + enable: true, + address: '127.0.0.1:{EVMRPC_PORT}', + 'ws-address': '127.0.0.1:{EVMRPC_PORT_WS}', + api: 'eth,net,web3,debug,txpool', + 'feehistory-cap': 100, + 'block-range-cap': 10000, + 'logs-cap': 10000, + 'gas-cap': 30000000, + 'allow-unprotected-txs': true, + }, + mempool: { + 'max-txs': 5000, + }, + }, + validators: [{ + 'coin-type': 60, + coins: '100000000000000000000' + chain.evm_denom, + staked: '10000000000000000000' + chain.evm_denom, + gas_prices: '0.01' + chain.evm_denom, + mnemonic: '${VALIDATOR1_MNEMONIC}', + }, { + 'coin-type': 60, + coins: '100000000000000000000' + chain.evm_denom, + staked: '10000000000000000000' + chain.evm_denom, + gas_prices: '0.01' + chain.evm_denom, + mnemonic: '${VALIDATOR2_MNEMONIC}', + config: { + db_backend: 'pebbledb', + }, + 'app-config': { + 'app-db-backend': 'pebbledb', + }, + }, { + 'coin-type': 60, + coins: '100000000000000000000' + chain.evm_denom, + staked: '10000000000000000000' + chain.evm_denom, + gas_prices: '0.01' + chain.evm_denom, + mnemonic: '${VALIDATOR3_MNEMONIC}', + config: { + db_backend: 'goleveldb', + }, + 'app-config': { + 'app-db-backend': 'goleveldb', + }, + }], + accounts: [{ + 'coin-type': 60, + name: 'community', + coins: '100000000000000000000' + chain.evm_denom + ',1000000000000atoken', + mnemonic: '${COMMUNITY_MNEMONIC}', + }, { + 'coin-type': 60, + name: 'signer1', + coins: '100000000000000000000' + chain.evm_denom, + mnemonic: '${SIGNER1_MNEMONIC}', + }, { + 'coin-type': 60, + name: 'signer2', + coins: '100000000000000000000' + chain.evm_denom, + mnemonic: '${SIGNER2_MNEMONIC}', + }, { + 'coin-type': 60, + name: 'reserve', + coins: '100000000000000000000' + chain.evm_denom, + mnemonic: '${RESERVE_MNEMONIC}', + vesting: '60s', + }], + genesis: { + consensus: { + params: { + block: { + max_bytes: '1048576', + max_gas: '81500000', + }, + abci: { + vote_extensions_enable_height: '1', + }, + }, + }, + app_state: { + evm: chain.evm { + params+: { + evm_denom: chain.evm_denom, + active_static_precompiles: [ + '0x0000000000000000000000000000000000000800', + '0x0000000000000000000000000000000000000807', + ], + }, + }, + erc20: { + native_precompiles: [ + '0x4200000000000000000000000000000000000006', + ], + token_pairs: [{ + erc20_address: '0x4200000000000000000000000000000000000006', + denom: chain.evm_denom, + enabled: true, + contract_owner: 1, + }], + }, + feemarket: chain.feemarket { + params+: { + min_gas_multiplier: '0', + }, + }, + gov: { + params: { + expedited_voting_period: '1s', + voting_period: '10s', + max_deposit_period: '10s', + min_deposit: [ + { + denom: chain.evm_denom, + amount: '1', + }, + ], + expedited_min_deposit: [ + { + denom: chain.evm_denom, + amount: '2', + }, + ], + }, + }, + crisis: { + constant_fee: { + denom: chain.evm_denom, + }, + }, + mint: { + params: { + mint_denom: chain.evm_denom, + }, + }, + staking: { + params: { + bond_denom: chain.evm_denom, + unbonding_time: '10s', + }, + }, + bank: chain.bank { + denom_metadata+: [{ + denom_units+: [ + { + denom: 'atoken', + exponent: 0, + }, + { + denom: 'token', + exponent: 18, + }, + ], + base: 'atoken', + display: 'token', + name: 'Test Coin', + symbol: 'ATOKEN', + }], + }, + }, + }, + }, +} diff --git a/tests/integration_tests/configs/enable-indexer.jsonnet b/tests/integration_tests/configs/enable-indexer.jsonnet new file mode 100644 index 000000000..4a2bbc875 --- /dev/null +++ b/tests/integration_tests/configs/enable-indexer.jsonnet @@ -0,0 +1,16 @@ +local config = import 'default.jsonnet'; + +config { + 'evm-canary-net-1'+: { + config+: { + tx_index+: { + indexer: 'null', + }, + }, + 'app-config'+: { + 'json-rpc'+: { + 'enable-indexer': true, + }, + }, + }, +} diff --git a/tests/integration_tests/conftest.py b/tests/integration_tests/conftest.py new file mode 100644 index 000000000..5ee7c48f1 --- /dev/null +++ b/tests/integration_tests/conftest.py @@ -0,0 +1,86 @@ +import pytest + +from .network import setup_evm + + +def pytest_addoption(parser): + parser.addoption( + "--chain-config", + default="evmd", + action="store", + metavar="CHAIN_CONFIG", + required=False, + help="Specify chain config to test", + ) + + +def pytest_configure(config): + config.addinivalue_line("markers", "unmarked: fallback mark for unmarked tests") + config.addinivalue_line("markers", "slow: marks tests as slow") + config.addinivalue_line("markers", "asyncio: marks tests as asyncio") + config.addinivalue_line("markers", "connect: marks connect related tests") + config.addinivalue_line("markers", "skipped: marks skipped not supported tests") + + +def pytest_collection_modifyitems(items, config): + keywordexpr = config.option.keyword + markexpr = config.option.markexpr + skip_connect = pytest.mark.skip(reason="Skipping connect tests by default") + skip_rollback = pytest.mark.skip( + reason="Skipping tests not supported for inveniemd" + ) + chain_config = config.getoption("chain_config") + + for item in items: + # add "unmarked" marker to tests that have no markers + if not any(item.iter_markers()): + item.add_marker("unmarked") + + # skip connect-marked tests unless explicitly requested + if "connect" in item.keywords: + if not ( + (keywordexpr and "connect" in keywordexpr) + or (markexpr and "connect" in markexpr) + ): + item.add_marker(skip_connect) + + if "skipped" in item.keywords: + if chain_config != "evmd" and not ( + (keywordexpr and "skipped" in keywordexpr) + or (markexpr and "skipped" in markexpr) + ): + item.add_marker(skip_rollback) + + +@pytest.fixture(scope="session") +def suspend_capture(pytestconfig): + """ + used to pause in testing + + Example: + ``` + def test_simple(suspend_capture): + with suspend_capture: + # read user input + print(input()) + ``` + """ + + class SuspendGuard: + def __init__(self): + self.capmanager = pytestconfig.pluginmanager.getplugin("capturemanager") + + def __enter__(self): + self.capmanager.suspend_global_capture(in_=True) + + def __exit__(self, _1, _2, _3): + self.capmanager.resume_global_capture() + + yield SuspendGuard() + + +@pytest.fixture(scope="session", params=[True]) +def evm(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("evm") + yield from setup_evm(path, 26650, chain) diff --git a/tests/integration_tests/cosmoscli.py b/tests/integration_tests/cosmoscli.py new file mode 100644 index 000000000..bc722c776 --- /dev/null +++ b/tests/integration_tests/cosmoscli.py @@ -0,0 +1,127 @@ +import json +import subprocess + +import requests +from pystarport.cosmoscli import CosmosCLI as PystarportCosmosCLI +from pystarport.utils import build_cli_args_safe, interact + +from .utils import ( + DEFAULT_DENOM, + DEFAULT_GAS, + DEFAULT_GAS_PRICE, + MNEMONICS, +) + + +class ChainCommand: + def __init__(self, cmd): + self.cmd = cmd + + def __call__(self, cmd, *args, stdin=None, stderr=subprocess.STDOUT, **kwargs): + "execute evmd" + args = " ".join(build_cli_args_safe(cmd, *args, **kwargs)) + return interact(f"{self.cmd} {args}", input=stdin, stderr=stderr) + + +class CosmosCLI(PystarportCosmosCLI): + "the apis to interact with wallet and blockchain" + + def __init__( + self, + data_dir, + node_rpc, + cmd, + chain_id=None, + gas=DEFAULT_GAS, + gas_prices=DEFAULT_GAS_PRICE, + ): + super().__init__(data_dir, node_rpc, chain_id, cmd, gas, gas_prices) + self.raw = ChainCommand(cmd) + genesis_path = self.data_dir / "config" / "genesis.json" + if genesis_path.exists(): + self._genesis = json.loads(genesis_path.read_text()) + if chain_id is None: + self.chain_id = self._genesis["chain_id"] + else: + self._genesis = {} + if chain_id is not None: + # avoid client.yml overwrite flag in textual mode + self.raw( + "config", "set", "client", "chain-id", chain_id, home=self.data_dir + ) + self.raw( + "config", "set", "client", "node", node_rpc, home=self.data_dir + ) + + @property + def node_rpc_http(self): + url = self.node_rpc.removeprefix("tcp") + if not url.startswith(("http://", "https://")): + url = "http" + url + return url + + @classmethod + def init(cls, moniker, data_dir, node_rpc, cmd, chain_id): + "the node's config is already added" + ChainCommand(cmd)( + "init", + moniker, + chain_id=chain_id, + home=data_dir, + ) + return cls(data_dir, node_rpc, cmd) + + def balance(self, addr, denom=DEFAULT_DENOM, height=0): + return super().balance(addr, denom=denom, height=height) + + def address(self, name, bech="acc", field="address", skip_create=False): + try: + output = self.raw( + "keys", + "show", + name, + f"--{field}", + home=self.data_dir, + keyring_backend="test", + bech=bech, + ) + except AssertionError as e: + if skip_create: + raise + if "not a valid name or address" in str(e): + self.create_account(name, mnemonic=MNEMONICS[name], home=self.data_dir) + output = self.raw( + "keys", + "show", + name, + f"--{field}", + home=self.data_dir, + keyring_backend="test", + bech=bech, + ) + else: + raise + return output.strip().decode() + + def debug_addr(self, eth_addr, bech="acc"): + output = self.raw("debug", "addr", eth_addr).decode().strip().split("\n") + if bech == "val": + prefix = "Bech32 Val" + elif bech == "hex": + prefix = "Address hex:" + else: + prefix = "Bech32 Acc" + for line in output: + if line.startswith(prefix): + return line.split()[-1] + return eth_addr + + def tx_search_rpc(self, events: str): + rsp = requests.get( + f"{self.node_rpc_http}/tx_search", + params={ + "query": f'"{events}"', + }, + ).json() + assert "error" not in rsp, rsp["error"] + return rsp["result"]["txs"] diff --git a/tests/integration_tests/network.py b/tests/integration_tests/network.py new file mode 100644 index 000000000..5b6d9b2d1 --- /dev/null +++ b/tests/integration_tests/network.py @@ -0,0 +1,170 @@ +import json +import os +import signal +import subprocess +from pathlib import Path + +import _jsonnet +import web3 +from pystarport import cluster, ports +from pystarport.expansion import expand +from pystarport.utils import ( + wait_for_block, + wait_for_port, +) +from requests.exceptions import ( + HTTPError, + Timeout, + TooManyRedirects, +) +from web3 import AsyncHTTPProvider, AsyncWeb3, HTTPProvider, WebSocketProvider +from web3.middleware import ExtraDataToPOAMiddleware +from web3.providers.rpc.utils import ExceptionRetryConfiguration + +from .cosmoscli import CosmosCLI +from .utils import ( + CHAIN_ID, + CMD, + supervisorctl, +) + +RETRY_CONFIG = ExceptionRetryConfiguration( + errors=(ConnectionError, HTTPError, Timeout, TooManyRedirects), + retries=10, +) + + +class Evm: + def __init__(self, base_dir, chain_binary=CMD): + self._w3 = None + self._async_w3 = None + self.base_dir = base_dir + self.config = json.loads((base_dir / "config.json").read_text()) + self.chain_binary = chain_binary + self._use_websockets = False + + def copy(self): + return Evm(self.base_dir) + + def w3_http_endpoint(self, i=0): + port = ports.evmrpc_port(self.base_port(i)) + return f"http://localhost:{port}" + + def w3_ws_endpoint(self, i=0): + port = ports.evmrpc_ws_port(self.base_port(i)) + return f"ws://localhost:{port}" + + @property + def w3(self): + if self._w3 is None: + self._w3 = self.node_w3(0) + return self._w3 + + @property + def async_w3(self, i=0): + if self._async_w3 is None: + self._async_w3 = self.async_node_w3(0) + return self._async_w3 + + def node_w3(self, i=0): + if self._use_websockets: + return web3.Web3( + WebSocketProvider( + self.w3_ws_endpoint(i), exception_retry_configuration=RETRY_CONFIG + ) + ) + else: + return web3.Web3( + HTTPProvider( + self.w3_http_endpoint(i), exception_retry_configuration=RETRY_CONFIG + ) + ) + + def async_node_w3(self, i=0): + return AsyncWeb3( + AsyncHTTPProvider( + self.w3_http_endpoint(i), + cache_allowed_requests=True, + exception_retry_configuration=RETRY_CONFIG, + ), + ) + + def base_port(self, i): + return self.config["validators"][i]["base_port"] + + def node_rpc(self, i): + return "tcp://127.0.0.1:%d" % ports.rpc_port(self.base_port(i)) + + def cosmos_cli(self, i=0) -> CosmosCLI: + return CosmosCLI(self.node_home(i), self.node_rpc(i), self.chain_binary) + + def node_home(self, i=0): + return self.base_dir / f"node{i}" + + def use_websocket(self, use=True): + self._w3 = None + self._use_websockets = use + + def supervisorctl(self, *args): + return supervisorctl(self.base_dir / "../tasks.ini", *args) + + +def setup_evm(path, base_port, chain): + cfg = Path(__file__).parent / ("configs/enable-indexer.jsonnet") + yield from setup_custom_evm(path, base_port, cfg, chain=chain) + + +def setup_custom_evm( + path, + base_port, + config, + post_init=None, + chain_binary=None, + wait_port=True, + relayer=cluster.Relayer.HERMES.value, + genesis=None, + chain=None, +): + assert config.suffix == ".jsonnet" + + # expand jsonnet with ext vars + data = json.loads( + _jsonnet.evaluate_file(str(config), ext_vars={"CHAIN_CONFIG": chain}) + ) + data = expand(data, None, config) + config = path / "expanded_config.json" + config.write_text(json.dumps(data, indent=2)) + + cmd = [ + "pystarport", + "init", + "--config", + config, + "--data", + path, + "--base_port", + str(base_port), + "--no_remove", + ] + if relayer == cluster.Relayer.RLY.value: + cmd = cmd + ["--relayer", str(relayer)] + if chain_binary is not None: + cmd = cmd[:1] + ["--cmd", chain_binary] + cmd[1:] + print(*cmd) + subprocess.run(cmd, check=True) + if post_init is not None: + post_init(path, base_port, config, genesis) + proc = subprocess.Popen( + ["pystarport", "start", "--data", path, "--quiet"], + preexec_fn=os.setsid, + ) + try: + if wait_port: + wait_for_port(ports.rpc_port(base_port)) + c = Evm(path / CHAIN_ID, chain_binary=chain_binary or chain) + wait_for_block(c.cosmos_cli(), 2) + yield c + finally: + os.killpg(os.getpgid(proc.pid), signal.SIGTERM) + # proc.terminate() + proc.wait() diff --git a/tests/integration_tests/poetry.lock b/tests/integration_tests/poetry.lock new file mode 100644 index 000000000..253400c53 --- /dev/null +++ b/tests/integration_tests/poetry.lock @@ -0,0 +1,2867 @@ +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. + +[[package]] +name = "aiohappyeyeballs" +version = "2.4.4" +description = "Happy Eyeballs for asyncio" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, + {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, +] + +[[package]] +name = "aiohttp" +version = "3.11.18" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "aiohttp-3.11.18-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:96264854fedbea933a9ca4b7e0c745728f01380691687b7365d18d9e977179c4"}, + {file = "aiohttp-3.11.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9602044ff047043430452bc3a2089743fa85da829e6fc9ee0025351d66c332b6"}, + {file = "aiohttp-3.11.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5691dc38750fcb96a33ceef89642f139aa315c8a193bbd42a0c33476fd4a1609"}, + {file = "aiohttp-3.11.18-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:554c918ec43f8480b47a5ca758e10e793bd7410b83701676a4782672d670da55"}, + {file = "aiohttp-3.11.18-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a4076a2b3ba5b004b8cffca6afe18a3b2c5c9ef679b4d1e9859cf76295f8d4f"}, + {file = "aiohttp-3.11.18-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:767a97e6900edd11c762be96d82d13a1d7c4fc4b329f054e88b57cdc21fded94"}, + {file = "aiohttp-3.11.18-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0ddc9337a0fb0e727785ad4f41163cc314376e82b31846d3835673786420ef1"}, + {file = "aiohttp-3.11.18-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f414f37b244f2a97e79b98d48c5ff0789a0b4b4609b17d64fa81771ad780e415"}, + {file = "aiohttp-3.11.18-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fdb239f47328581e2ec7744ab5911f97afb10752332a6dd3d98e14e429e1a9e7"}, + {file = "aiohttp-3.11.18-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f2c50bad73ed629cc326cc0f75aed8ecfb013f88c5af116f33df556ed47143eb"}, + {file = "aiohttp-3.11.18-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a8d8f20c39d3fa84d1c28cdb97f3111387e48209e224408e75f29c6f8e0861d"}, + {file = "aiohttp-3.11.18-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:106032eaf9e62fd6bc6578c8b9e6dc4f5ed9a5c1c7fb2231010a1b4304393421"}, + {file = "aiohttp-3.11.18-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:b491e42183e8fcc9901d8dcd8ae644ff785590f1727f76ca86e731c61bfe6643"}, + {file = "aiohttp-3.11.18-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ad8c745ff9460a16b710e58e06a9dec11ebc0d8f4dd82091cefb579844d69868"}, + {file = "aiohttp-3.11.18-cp310-cp310-win32.whl", hash = "sha256:8e57da93e24303a883146510a434f0faf2f1e7e659f3041abc4e3fb3f6702a9f"}, + {file = "aiohttp-3.11.18-cp310-cp310-win_amd64.whl", hash = "sha256:cc93a4121d87d9f12739fc8fab0a95f78444e571ed63e40bfc78cd5abe700ac9"}, + {file = "aiohttp-3.11.18-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:427fdc56ccb6901ff8088544bde47084845ea81591deb16f957897f0f0ba1be9"}, + {file = "aiohttp-3.11.18-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c828b6d23b984255b85b9b04a5b963a74278b7356a7de84fda5e3b76866597b"}, + {file = "aiohttp-3.11.18-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c2eaa145bb36b33af1ff2860820ba0589e165be4ab63a49aebfd0981c173b66"}, + {file = "aiohttp-3.11.18-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d518ce32179f7e2096bf4e3e8438cf445f05fedd597f252de9f54c728574756"}, + {file = "aiohttp-3.11.18-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0700055a6e05c2f4711011a44364020d7a10fbbcd02fbf3e30e8f7e7fddc8717"}, + {file = "aiohttp-3.11.18-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8bd1cde83e4684324e6ee19adfc25fd649d04078179890be7b29f76b501de8e4"}, + {file = "aiohttp-3.11.18-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73b8870fe1c9a201b8c0d12c94fe781b918664766728783241a79e0468427e4f"}, + {file = "aiohttp-3.11.18-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25557982dd36b9e32c0a3357f30804e80790ec2c4d20ac6bcc598533e04c6361"}, + {file = "aiohttp-3.11.18-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7e889c9df381a2433802991288a61e5a19ceb4f61bd14f5c9fa165655dcb1fd1"}, + {file = "aiohttp-3.11.18-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9ea345fda05bae217b6cce2acf3682ce3b13d0d16dd47d0de7080e5e21362421"}, + {file = "aiohttp-3.11.18-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9f26545b9940c4b46f0a9388fd04ee3ad7064c4017b5a334dd450f616396590e"}, + {file = "aiohttp-3.11.18-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:3a621d85e85dccabd700294494d7179ed1590b6d07a35709bb9bd608c7f5dd1d"}, + {file = "aiohttp-3.11.18-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9c23fd8d08eb9c2af3faeedc8c56e134acdaf36e2117ee059d7defa655130e5f"}, + {file = "aiohttp-3.11.18-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9e6b0e519067caa4fd7fb72e3e8002d16a68e84e62e7291092a5433763dc0dd"}, + {file = "aiohttp-3.11.18-cp311-cp311-win32.whl", hash = "sha256:122f3e739f6607e5e4c6a2f8562a6f476192a682a52bda8b4c6d4254e1138f4d"}, + {file = "aiohttp-3.11.18-cp311-cp311-win_amd64.whl", hash = "sha256:e6f3c0a3a1e73e88af384b2e8a0b9f4fb73245afd47589df2afcab6b638fa0e6"}, + {file = "aiohttp-3.11.18-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:63d71eceb9cad35d47d71f78edac41fcd01ff10cacaa64e473d1aec13fa02df2"}, + {file = "aiohttp-3.11.18-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d1929da615840969929e8878d7951b31afe0bac883d84418f92e5755d7b49508"}, + {file = "aiohttp-3.11.18-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d0aebeb2392f19b184e3fdd9e651b0e39cd0f195cdb93328bd124a1d455cd0e"}, + {file = "aiohttp-3.11.18-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3849ead845e8444f7331c284132ab314b4dac43bfae1e3cf350906d4fff4620f"}, + {file = "aiohttp-3.11.18-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e8452ad6b2863709f8b3d615955aa0807bc093c34b8e25b3b52097fe421cb7f"}, + {file = "aiohttp-3.11.18-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b8d2b42073611c860a37f718b3d61ae8b4c2b124b2e776e2c10619d920350ec"}, + {file = "aiohttp-3.11.18-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40fbf91f6a0ac317c0a07eb328a1384941872f6761f2e6f7208b63c4cc0a7ff6"}, + {file = "aiohttp-3.11.18-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ff5625413fec55216da5eaa011cf6b0a2ed67a565914a212a51aa3755b0009"}, + {file = "aiohttp-3.11.18-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7f33a92a2fde08e8c6b0c61815521324fc1612f397abf96eed86b8e31618fdb4"}, + {file = "aiohttp-3.11.18-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:11d5391946605f445ddafda5eab11caf310f90cdda1fd99865564e3164f5cff9"}, + {file = "aiohttp-3.11.18-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3cc314245deb311364884e44242e00c18b5896e4fe6d5f942e7ad7e4cb640adb"}, + {file = "aiohttp-3.11.18-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0f421843b0f70740772228b9e8093289924359d306530bcd3926f39acbe1adda"}, + {file = "aiohttp-3.11.18-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e220e7562467dc8d589e31c1acd13438d82c03d7f385c9cd41a3f6d1d15807c1"}, + {file = "aiohttp-3.11.18-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ab2ef72f8605046115bc9aa8e9d14fd49086d405855f40b79ed9e5c1f9f4faea"}, + {file = "aiohttp-3.11.18-cp312-cp312-win32.whl", hash = "sha256:12a62691eb5aac58d65200c7ae94d73e8a65c331c3a86a2e9670927e94339ee8"}, + {file = "aiohttp-3.11.18-cp312-cp312-win_amd64.whl", hash = "sha256:364329f319c499128fd5cd2d1c31c44f234c58f9b96cc57f743d16ec4f3238c8"}, + {file = "aiohttp-3.11.18-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:474215ec618974054cf5dc465497ae9708543cbfc312c65212325d4212525811"}, + {file = "aiohttp-3.11.18-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ced70adf03920d4e67c373fd692123e34d3ac81dfa1c27e45904a628567d804"}, + {file = "aiohttp-3.11.18-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2d9f6c0152f8d71361905aaf9ed979259537981f47ad099c8b3d81e0319814bd"}, + {file = "aiohttp-3.11.18-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a35197013ed929c0aed5c9096de1fc5a9d336914d73ab3f9df14741668c0616c"}, + {file = "aiohttp-3.11.18-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:540b8a1f3a424f1af63e0af2d2853a759242a1769f9f1ab053996a392bd70118"}, + {file = "aiohttp-3.11.18-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9e6710ebebfce2ba21cee6d91e7452d1125100f41b906fb5af3da8c78b764c1"}, + {file = "aiohttp-3.11.18-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8af2ef3b4b652ff109f98087242e2ab974b2b2b496304063585e3d78de0b000"}, + {file = "aiohttp-3.11.18-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28c3f975e5ae3dbcbe95b7e3dcd30e51da561a0a0f2cfbcdea30fc1308d72137"}, + {file = "aiohttp-3.11.18-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c28875e316c7b4c3e745172d882d8a5c835b11018e33432d281211af35794a93"}, + {file = "aiohttp-3.11.18-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:13cd38515568ae230e1ef6919e2e33da5d0f46862943fcda74e7e915096815f3"}, + {file = "aiohttp-3.11.18-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0e2a92101efb9f4c2942252c69c63ddb26d20f46f540c239ccfa5af865197bb8"}, + {file = "aiohttp-3.11.18-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e6d3e32b8753c8d45ac550b11a1090dd66d110d4ef805ffe60fa61495360b3b2"}, + {file = "aiohttp-3.11.18-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ea4cf2488156e0f281f93cc2fd365025efcba3e2d217cbe3df2840f8c73db261"}, + {file = "aiohttp-3.11.18-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d4df95ad522c53f2b9ebc07f12ccd2cb15550941e11a5bbc5ddca2ca56316d7"}, + {file = "aiohttp-3.11.18-cp313-cp313-win32.whl", hash = "sha256:cdd1bbaf1e61f0d94aced116d6e95fe25942f7a5f42382195fd9501089db5d78"}, + {file = "aiohttp-3.11.18-cp313-cp313-win_amd64.whl", hash = "sha256:bdd619c27e44382cf642223f11cfd4d795161362a5a1fc1fa3940397bc89db01"}, + {file = "aiohttp-3.11.18-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:469ac32375d9a716da49817cd26f1916ec787fc82b151c1c832f58420e6d3533"}, + {file = "aiohttp-3.11.18-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3cec21dd68924179258ae14af9f5418c1ebdbba60b98c667815891293902e5e0"}, + {file = "aiohttp-3.11.18-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b426495fb9140e75719b3ae70a5e8dd3a79def0ae3c6c27e012fc59f16544a4a"}, + {file = "aiohttp-3.11.18-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad2f41203e2808616292db5d7170cccf0c9f9c982d02544443c7eb0296e8b0c7"}, + {file = "aiohttp-3.11.18-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5bc0ae0a5e9939e423e065a3e5b00b24b8379f1db46046d7ab71753dfc7dd0e1"}, + {file = "aiohttp-3.11.18-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe7cdd3f7d1df43200e1c80f1aed86bb36033bf65e3c7cf46a2b97a253ef8798"}, + {file = "aiohttp-3.11.18-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5199be2a2f01ffdfa8c3a6f5981205242986b9e63eb8ae03fd18f736e4840721"}, + {file = "aiohttp-3.11.18-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ccec9e72660b10f8e283e91aa0295975c7bd85c204011d9f5eb69310555cf30"}, + {file = "aiohttp-3.11.18-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1596ebf17e42e293cbacc7a24c3e0dc0f8f755b40aff0402cb74c1ff6baec1d3"}, + {file = "aiohttp-3.11.18-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:eab7b040a8a873020113ba814b7db7fa935235e4cbaf8f3da17671baa1024863"}, + {file = "aiohttp-3.11.18-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:5d61df4a05476ff891cff0030329fee4088d40e4dc9b013fac01bc3c745542c2"}, + {file = "aiohttp-3.11.18-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:46533e6792e1410f9801d09fd40cbbff3f3518d1b501d6c3c5b218f427f6ff08"}, + {file = "aiohttp-3.11.18-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c1b90407ced992331dd6d4f1355819ea1c274cc1ee4d5b7046c6761f9ec11829"}, + {file = "aiohttp-3.11.18-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a2fd04ae4971b914e54fe459dd7edbbd3f2ba875d69e057d5e3c8e8cac094935"}, + {file = "aiohttp-3.11.18-cp39-cp39-win32.whl", hash = "sha256:b2f317d1678002eee6fe85670039fb34a757972284614638f82b903a03feacdc"}, + {file = "aiohttp-3.11.18-cp39-cp39-win_amd64.whl", hash = "sha256:5e7007b8d1d09bce37b54111f593d173691c530b80f27c6493b928dabed9e6ef"}, + {file = "aiohttp-3.11.18.tar.gz", hash = "sha256:ae856e1138612b7e412db63b7708735cff4d38d0399f6a5435d3dac2669f558a"}, +] + +[package.dependencies] +aiohappyeyeballs = ">=2.3.0" +aiosignal = ">=1.1.2" +attrs = ">=17.3.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +propcache = ">=0.2.0" +yarl = ">=1.17.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] + +[[package]] +name = "aiosignal" +version = "1.3.2" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.9" +files = [ + {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, + {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "attrs" +version = "24.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, +] + +[package.extras] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] + +[[package]] +name = "bech32" +version = "1.2.0" +description = "Reference implementation for Bech32 and segwit addresses." +optional = false +python-versions = ">=3.5" +files = [ + {file = "bech32-1.2.0-py3-none-any.whl", hash = "sha256:990dc8e5a5e4feabbdf55207b5315fdd9b73db40be294a19b3752cde9e79d981"}, + {file = "bech32-1.2.0.tar.gz", hash = "sha256:7d6db8214603bd7871fcfa6c0826ef68b85b0abd90fa21c285a9c5e21d2bd899"}, +] + +[[package]] +name = "bitarray" +version = "3.4.2" +description = "efficient arrays of booleans -- C extension" +optional = false +python-versions = "*" +files = [ + {file = "bitarray-3.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:42b552f885c5629182928c79237b375a92bcf1bc1e725b1c8a5e8eab28ea300d"}, + {file = "bitarray-3.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3e16d6184f349587b6a5045bcf073baf763a86273aab454485ba437d0bca82e8"}, + {file = "bitarray-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ecf456f0dee61bd818011e290d922e3e3b1aeb0544f6f19c4da9c5fc2e52818"}, + {file = "bitarray-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8bbe8249ae90dc0cd78b21d5d5d27a614e15bf30737ae6e8a0e2e60cc492acc"}, + {file = "bitarray-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe7706f75f3b86e7afa516452bed9757ee301b59aea580c551c32a5e1cef082c"}, + {file = "bitarray-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c60c8d30bb6efd2c04cf82d077df6449964234aeca996f6f1df317a08feffc0"}, + {file = "bitarray-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b4cb5c22706d411010c7ce5efc0a4cc99f755a30fc7f6770eb1b1a0c0962bbb"}, + {file = "bitarray-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0fd60137a9474ce53bdace68c718a7c538f9df01d390452cc984f1ee78d7bcdb"}, + {file = "bitarray-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:cd514a8e27d0751f0254861df60335edabacccfcb2457793ff30c8b2ed8f799d"}, + {file = "bitarray-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6c8f7447cdf2faff1d176c5dd207f0134f05cfa2a238d3d3944dc5019dc41593"}, + {file = "bitarray-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:75040a2a1abe4ccd40236f4ba0d39abde981d23f3ce7691b3b3f2137f134b99b"}, + {file = "bitarray-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ba15725cd9040b9b1b2650edb33253cb2ba7b68d087974e296e5ff082198952f"}, + {file = "bitarray-3.4.2-cp310-cp310-win32.whl", hash = "sha256:2959dfc61d963546e97220cfcaab7dfc489276c6e00092b57710522e68712b28"}, + {file = "bitarray-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:97077fa0ec3b7eed57cd8d1cb0eb75d670423d20b7e4901482347a81efe2f6fd"}, + {file = "bitarray-3.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90ca8e260b75a7ac0c542093e5f29154e51fd0d2d0fa5041c038cb2b58415eeb"}, + {file = "bitarray-3.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549dabcae78fb8f9133e3138b9473c7648d6054bb6fec84d28d3861aaec5ddd1"}, + {file = "bitarray-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a3da536ac84e6911cbc8e86be0baf1cab0d4f4ccb80c0f39b4fa28509f2db1a"}, + {file = "bitarray-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7a5e84d6b737de2d773ab1bd538e6f37fa7f667ea734f00a48d9a973b181c751"}, + {file = "bitarray-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e265c5eede8316ba64bb6029832f282f6284a557b625bb3207a7680fd5da7925"}, + {file = "bitarray-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63fb45c60c7ab7a724aa64203305e56f344489e12d41619bdc9d7887d6562e01"}, + {file = "bitarray-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:083c2a9234dacf3e4e166a5844256da2a397941d3f6397e5b919bffca638f6ef"}, + {file = "bitarray-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e72606adb2438002873cb0e8e81c3fce926386a59bbafa82fea07cdb2a6d8a05"}, + {file = "bitarray-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dc994d22a3a563e1d402dc2f64c61e60605a1a3e66dd8aea7636f607b99f03cb"}, + {file = "bitarray-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:214468391680ba1c831872a7949f1b563ab3cd832d10adc52df4f36e0af24446"}, + {file = "bitarray-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c7483b97807bb018a7cd7f9741800c714c9c56ba4e5a7e962c5f956c4b858f3c"}, + {file = "bitarray-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5774bf14ec451d5ac311cfcfe0b0cf2a1a9fa74b6ca81dfbc4f56a98872a5541"}, + {file = "bitarray-3.4.2-cp311-cp311-win32.whl", hash = "sha256:e6f35567347ddb8b9e8b6bf6ab7d64be88bdb6b6c107b8edbb2c3d426c1590a0"}, + {file = "bitarray-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:ae5b0a8d3caf6284220232738dc7c05af81ec3a9f93d4a462295462dd0a492b2"}, + {file = "bitarray-3.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a0e498563e0eefa96a1b92461d083de11256f6510b7706d5f2e6473cd9b7137a"}, + {file = "bitarray-3.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:114870ab71a0ebdac211aa0a120a54206c333b74b99fdf4b58fbe904979e1fef"}, + {file = "bitarray-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fbf6121978cba4313c31f7cc5961e481242def2b8ddfea34ca27ba9da52c9c1"}, + {file = "bitarray-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:423bb4e1bec0bc5d63969e12bcc5cc0081cc5aec4d7b62a6cd8240342aa36107"}, + {file = "bitarray-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ef80a96487c82477e8def69a58a218491794f7989b3e191cbaaa7b450315a5c"}, + {file = "bitarray-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35f5c69a79047e50bc1d54a777541b0a86b213e23559b1ac3d76fa9a42cc5522"}, + {file = "bitarray-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:002f7b128ed9d18d3ecb51ca78aeea5afffbe8e80d6be4ff2984d045b1c4b937"}, + {file = "bitarray-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:999bccc72704afcf4a3d9868db4d149c032cdf910f9f7d91e30166978530af7f"}, + {file = "bitarray-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2e44cfe2bc161cde3b11604f279e3048ef7bd3413837aadbd2ca30b5233c82cb"}, + {file = "bitarray-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f408ba3e6f706a0eabae405d1906ceb539f34a318562a91ab9799c5e1712e18c"}, + {file = "bitarray-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bf94513ae559b2525e6218e41b03790f866d75df5404490420f2c25e42cf55e7"}, + {file = "bitarray-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f2c88c792815d2755c49a3a1fca256e142c4adfadf1a2142b5a3a37e4d4b871"}, + {file = "bitarray-3.4.2-cp312-cp312-win32.whl", hash = "sha256:f4dac6b942c4d7ae5f6eb555ee3993de1432bf9c8f46e3caf74b6671ac5571a3"}, + {file = "bitarray-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:6c37e6814633041307f0df281651a86372b0ccdb1e4768247a87e83e2b68f9b9"}, + {file = "bitarray-3.4.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:16263bdbb05ce379e7b8e9a9f3e0a61a9204a06a037bbc91322d2939b3079fd5"}, + {file = "bitarray-3.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:41fdc6fb8c3aabfcfe0073302c69fef0c74d6499491f133ba58755c3f2afb3d0"}, + {file = "bitarray-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c2571337b11c69206e339170516f3e72b4ec16250876c4f2bbb6e82b9caa15"}, + {file = "bitarray-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c0e3d5f37217dde9b206418c37c4d86e173f072a892670e9714e6bb20b228e95"}, + {file = "bitarray-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83202735f21fc781f27228daeae94b6c7df1a9f673b9dd6a1c0b3764d92b8e50"}, + {file = "bitarray-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53b3f8c35812d85a299d6c0ff097f93e18dfb7a324c129e20a4ec0ecfc4ba995"}, + {file = "bitarray-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3f2e8ba5d6e0f38b57960d1bfb72aa9e2115f7cdca48561fadced652798d49"}, + {file = "bitarray-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:508ec6547bdd9f0c435c322fbb127a3dfd74c943a6c7f77fa5dfcb3e9ce1de66"}, + {file = "bitarray-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1a3a08cc920f601258ea33d97b4454cd7cb04d17930e0a3bc7328ba3d732f8b0"}, + {file = "bitarray-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:60189130ae1ebaadbab27e3ad0a7d7ed44f5d9456bbfae07c72138501ce59053"}, + {file = "bitarray-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9e425eaf21a8d7b76531630029441c6d61f6064cbf4dd592af1607c79eb2e4d0"}, + {file = "bitarray-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:952cc40c593f663ba083be76d1ccdb6dc9dafab8fb6d949056405636b2e720f3"}, + {file = "bitarray-3.4.2-cp313-cp313-win32.whl", hash = "sha256:158f6b1a315eaf971f88e66f9b93431c3b580b46d2121c6a1166e7b761408fdf"}, + {file = "bitarray-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:2d24658ac96a82beb4da2f5c71bef9790f3dcabadbe8ead8dda742ab207fe2f9"}, + {file = "bitarray-3.4.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3098722521db7dcc716ffdccb26655dd12884febbf3ed479b430f46c2d81a7ce"}, + {file = "bitarray-3.4.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be4c18bcd4146891f9f5758eadddd20c32dff8defa1ceba0114245393c7ce17"}, + {file = "bitarray-3.4.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66dabfaf151a107d51e5b7f0e78cf015f8f90102b64504100aca6f876e64d83d"}, + {file = "bitarray-3.4.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dc827b7fd1c754afc9a05cfd6c506577c1383ca39e2a338d0c9137edf74fa64"}, + {file = "bitarray-3.4.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b816e1ad8f0c4717265b0b22806807be085ed4a3b3a1314228f45c0321efcdfe"}, + {file = "bitarray-3.4.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:708e586b5b6688038e5ecd44cd39381eb360917e1fb78a75efbd1fdc259cbe62"}, + {file = "bitarray-3.4.2-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:46f487ec9d8d3c43a40e4fcafb8f731bc825707326bb7d2a9223d957541b176c"}, + {file = "bitarray-3.4.2-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:fc30c3879ffe626ad44bc41c88f42a67ba66680b9649ddccc9adf74034ddaf20"}, + {file = "bitarray-3.4.2-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:a6063e803212802d52aa7a384d001f9008ff407a2eca5a380b48883e012e5615"}, + {file = "bitarray-3.4.2-cp36-cp36m-musllinux_1_2_s390x.whl", hash = "sha256:8d64c1f94f0a2f02d056466da67e60ecf66ba0c9e9237eff67d68742b9509f80"}, + {file = "bitarray-3.4.2-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:79f3bd0cfb1950585dabb528a3402c92f6ce6955302fb13334373621b5873fc2"}, + {file = "bitarray-3.4.2-cp36-cp36m-win32.whl", hash = "sha256:863ada3e0531f79b39659ca6178cbe29afae1df0085cd4cf35b7f5d8f35468fe"}, + {file = "bitarray-3.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:b52ea280392650da7fadd991bdcb9a914cc885e771fdb16f3e5a3b8ab28cda73"}, + {file = "bitarray-3.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:86c507024d8307a19f747c450766294efdfb212a29ef142ccc33b986e91cc14f"}, + {file = "bitarray-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c20cd30c8ee0a30f13d9755ddbedf4387d25dd3fcaad923c51a09a091052990d"}, + {file = "bitarray-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d49e54b6c7778b9b500ed6e2e05cfa9c4983a624b99e7ef9c12d9fd3a1274990"}, + {file = "bitarray-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4454881de8a4b417fe704adab7983dfb8b9c9b97d26d10deb1a8c5e95ac9150"}, + {file = "bitarray-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bbb179d981fd05631c4068a56327541978378f82b5b3d82a571e1f3e459c46"}, + {file = "bitarray-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:783e19b7c0b58afc54d416fea1c0527e1d6afc7af98700c0032f4b3e199f4fb0"}, + {file = "bitarray-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:c31ebf0311bd73ef2ecd2ad016f2c6c10e95801e82dfe7508b1f926b285daed4"}, + {file = "bitarray-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:0c997446bb42314bb7758edb51e39c99fdfa967ff48dcd11ec048e47517f0d5d"}, + {file = "bitarray-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:50893e03ee37d82dc81449a2cfcc959c58e2f1eb87b961d57c55744bd11f4c15"}, + {file = "bitarray-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:a89a3dd32dae555e1361d7c1ea3f30097f6d655f9a92ba592df173b44126bd73"}, + {file = "bitarray-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:8e0b0446a071e88283af3508613d65f58ac8e04ac40cb22de75eca4bb4a9665a"}, + {file = "bitarray-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:90d8fce4287da47a635f9e620e92f26916bacfb8edfa3cbb7a55bc50f5d3033a"}, + {file = "bitarray-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7c9fd487c7dc21e0112cbf8e689cd09ea68b3776b2de513a6517913182eb0cc1"}, + {file = "bitarray-3.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a9cc7b6dfc0b778e0ab4f6c602770b03d1238970bacc759046597499432e537d"}, + {file = "bitarray-3.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:df92619765e90c32c7f37e5a7437d22b7720b69543c3f7384cd8482ba76d9b1a"}, + {file = "bitarray-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebc9786ea35353324bb46c9c1ef44ab4f66f3c397ace9ed84c2c16ba191526ed"}, + {file = "bitarray-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e748c794960d811746ec7353f3f9056ffc0502fcf971836b4b6c6e20126b25b4"}, + {file = "bitarray-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b85e8f103f21ac3a725066f4abfb3ca27731c5cb2cb14087e0e014d4178f865d"}, + {file = "bitarray-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61f362d2a53f3fb237a0ab4581c22ed2b733c293d2b90dd9b90983636e8eb40d"}, + {file = "bitarray-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c69fc4325bdb40e9d71129fc3d869f18e7c5ec7cd9cf972a2270a32481de71e"}, + {file = "bitarray-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ac1b00a2c687f9fc45fd6bec63a4a2f01c11664ed6632cb8a91e5cf6e260503b"}, + {file = "bitarray-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:b24dabacfd56c55a861f14568b8654e984f31067aec4c4bb6b04d1af29c689c2"}, + {file = "bitarray-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc569c2c880a3c16ab0ed07d7b709f0c9af23568de8b5f599b934d4b639f9b1"}, + {file = "bitarray-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b2c4aa3a9134bbfb439bd48e805b2bf9a0873e56c1110f0c7bd0a9b0ee4f4ced"}, + {file = "bitarray-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b4d10c74b145f025ab37de6b503118d3f92718921595434f23e8280ff46ddaa8"}, + {file = "bitarray-3.4.2-cp38-cp38-win32.whl", hash = "sha256:cff080acfce06f304c87a73d77d286f792baaf61e6af34560788bb951365fb60"}, + {file = "bitarray-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:001d4005336ca2c8fdecbe2a278bc58e71b1f8ca8ce5c09f9c73482fa4ce065b"}, + {file = "bitarray-3.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:549c730e91b8b2a7b4502b573e333c77196bb163109c87ab19ddcd3196183c7f"}, + {file = "bitarray-3.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dd48009c478cf10f15238a808c0412e0f2b70ab8f2b753466d4f425974cbf6c6"}, + {file = "bitarray-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e0f3bb202db0235ff7698a288c7ee732a5b73736257da89af26f3975386ce02"}, + {file = "bitarray-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b2041a1f4087df044ad82f239e9bf253d9c3d21474078f496a07f26398084ea"}, + {file = "bitarray-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5211bb084b7c7b7087f8d5af0b67b283ea9519c7595d9b19ef1b52065e5853dd"}, + {file = "bitarray-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83e9df7d83ee4997e5fea3a356ba075b9112931375be97f307c9bc6344b10b8c"}, + {file = "bitarray-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c025f13e27a0596c4d3ff9e80c31b26bdda526959bbfecdb0989f3007ec4f56c"}, + {file = "bitarray-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d4359490ee83184911a35aa9959d7ce02e00d7c1208f300ccf946f161652e962"}, + {file = "bitarray-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:b7ec66b0735ee5b264b3c6adb3e05187f523b2c7f875a40dcd4c167b735c292d"}, + {file = "bitarray-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:829cd725444811eb57dd01679c245cdc994259f1ae9685298268e8267bc23637"}, + {file = "bitarray-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2b26ec3aa15163c5233dfaf67f76f9933d4e9273166830ca5f3cf3ec9d883767"}, + {file = "bitarray-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bcbe07cf0e863a98468ed2bbba674932a6eaa9fa4cbc716f9b0f0b267927b990"}, + {file = "bitarray-3.4.2-cp39-cp39-win32.whl", hash = "sha256:f1cc27aa74da3a0ec157a41fae07af34103dd5b337e92514eb9d3923d721e9d7"}, + {file = "bitarray-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:a7ffc3939371af5581e77a0529e1b90bdfb112f2d9c9e5cb065618a522ec4e77"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9c02f3234b1ec391aa235b265a3649e8078d814cdd6b42bc5aee267cc370b0c8"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:e19e5a35f53c0eaf4516cfa3f80de110eb831fd3d9785aa8b8f4a8a8c0d99523"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f633d1e92fdc6a039b118d67f23d17b9ac4046a629bde04e178b770fe83a618f"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c08bc2ec3f15fbb3a99923ef1b16b621af45ab9d5146a06f970c0f0d7cab22ba"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eed46fa39af8440b1cff09a9805d65449583d524006efa29e5262bea9e08787e"}, + {file = "bitarray-3.4.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9cf23c13c84c1559ed28bd211a6290b7326c2011f6c30c82cee052b254ac09f0"}, + {file = "bitarray-3.4.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e4dd654d6a789e23abc65cc8e193c309b0d304a74d343c4e7d18f3796e452c13"}, + {file = "bitarray-3.4.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:481e87458b4a855d905f5139fbf0717d701e9d3cbd9b9f7f033cd4af76a2a587"}, + {file = "bitarray-3.4.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6650077087b7d5953a70c46bbb9ac6004daf6d76d75f8bc10b776cfa1cd178c1"}, + {file = "bitarray-3.4.2-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ab5688d22d9e70ceac58b5ffde29bbd38767da0cea34c923cffdb2abf674a18"}, + {file = "bitarray-3.4.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6ff474b96cefcf55003eae55fd4af9df27e892008f689435a60b8d5b5c22824b"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:83850b34897be3eb13ea7a1148f92284e8f66e059c7bd3381915858b4264c16d"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:5fdbf326369a6d527be12946b19521e5a9cf9243d1a3f63510b06a848e30c424"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc4b304afc23bdeec34f3d442a5d1edcaa49fa33310dfdf1be4997d2b80947d1"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08e4a319ffc2973c4610c218fc0153d19a5866deafd0d0c87c6cbfa41add48a9"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:940c8cd97d109dd0696e6b4f6d140e37701b440a9c7ca50ef0a6f547d6b95812"}, + {file = "bitarray-3.4.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:0020522d3e865e3afd001fefcc17361f4dc86f14253fd897e28a4883d4f951b7"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1f050ba6dbea65fe490c33cebb656c721b27989fd0fee2e497c13485415a2016"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:533f02e4c815b8b40285ee8e89119a55117ca2e2e08502cfef31e6218d89b165"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b8da5f00a8daf4e64c47a65f4aa8a821269211f99525f09053b9ec701e04f34"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55d42e7b501f6ce31eed56e7d187a057aa30e8eed832806f06aa7e29dd07482a"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d7dd21f594b372bf9169e37e793a1356ecf2d0e25068c37bba16a3ef4e00299"}, + {file = "bitarray-3.4.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c5e51200bc9120e072db0f87e38047032e37f5699f9ad8c57c14263439a5a8b1"}, + {file = "bitarray-3.4.2.tar.gz", hash = "sha256:78ed2b911aabede3a31e3329b1de8abdc8104bd5e0545184ddbd9c7f668f4059"}, +] + +[[package]] +name = "black" +version = "25.1.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.9" +files = [ + {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, + {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, + {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, + {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, + {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, + {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, + {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, + {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, + {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, + {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, + {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, + {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, + {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, + {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, + {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, + {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, + {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, + {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, + {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, + {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, + {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, + {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.10)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "certifi" +version = "2025.1.31" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, + {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.1" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7" +files = [ + {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, + {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, + {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, +] + +[[package]] +name = "ckzg" +version = "2.1.1" +description = "Python bindings for C-KZG-4844" +optional = false +python-versions = "*" +files = [ + {file = "ckzg-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b9825a1458219e8b4b023012b8ef027ef1f47e903f9541cbca4615f80132730"}, + {file = "ckzg-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e2a40a3ba65cca4b52825d26829e6f7eb464aa27a9e9efb6b8b2ce183442c741"}, + {file = "ckzg-2.1.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1d753fbe85be7c21602eddc2d40e0915e25fce10329f4f801a0002a4f886cc7"}, + {file = "ckzg-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d76b50527f1d12430bf118aff6fa4051e9860eada43f29177258b8d399448ea"}, + {file = "ckzg-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44c8603e43c021d100f355f50189183135d1df3cbbddb8881552d57fbf421dde"}, + {file = "ckzg-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:38707a638c9d715b3c30b29352b969f78d8fc10faed7db5faf517f04359895c0"}, + {file = "ckzg-2.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:52c4d257bdcbe822d20c5cd24c8154ec5aac33c49a8f5a19e716d9107a1c8785"}, + {file = "ckzg-2.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1507f7bfb9bcf51d816db5d8d0f0ed53c8289605137820d437b69daea8333e16"}, + {file = "ckzg-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:d02eaaf4f841910133552b3a051dea53bcfe60cd98199fc4cf80b27609d8baa2"}, + {file = "ckzg-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:465e2b71cf9dc383f66f1979269420a0da9274a3a9e98b1a4455e84927dfe491"}, + {file = "ckzg-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ee2f26f17a64ad0aab833d637b276f28486b82a29e34f32cf54b237b8f8ab72d"}, + {file = "ckzg-2.1.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99cc2c4e9fb8c62e3e0862c7f4df9142f07ba640da17fded5f6e0fd09f75909f"}, + {file = "ckzg-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773dd016693d74aca1f5d7982db2bad7dde2e147563aeb16a783f7e5f69c01fe"}, + {file = "ckzg-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af2b2144f87ba218d8db01382a961b3ecbdde5ede4fa0d9428d35f8c8a595ba"}, + {file = "ckzg-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8f55e63d3f7c934a2cb53728ed1d815479e177aca8c84efe991c2920977cff6"}, + {file = "ckzg-2.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ecb42aaa0ffa427ff14a9dde9356ba69e5ae6014650b397af55b31bdae7a9b6e"}, + {file = "ckzg-2.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5a01514239f12fb1a7ad9009c20062a4496e13b09541c1a65f97e295da648c70"}, + {file = "ckzg-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:6516b9684aae262c85cf7fddd8b585b8139ad20e08ec03994e219663abbb0916"}, + {file = "ckzg-2.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c60e8903344ce98ce036f0fabacce952abb714cad4607198b2f0961c28b8aa72"}, + {file = "ckzg-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4299149dd72448e5a8d2d1cc6cc7472c92fc9d9f00b1377f5b017c089d9cd92"}, + {file = "ckzg-2.1.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:025dd31ffdcc799f3ff842570a2a6683b6c5b01567da0109c0c05d11768729c4"}, + {file = "ckzg-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b42ab8385c273f40a693657c09d2bba40cb4f4666141e263906ba2e519e80bd"}, + {file = "ckzg-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1be3890fc1543f4fcfc0063e4baf5c036eb14bcf736dabdc6171ab017e0f1671"}, + {file = "ckzg-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b754210ded172968b201e2d7252573af6bf52d6ad127ddd13d0b9a45a51dae7b"}, + {file = "ckzg-2.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b2f8fda87865897a269c4e951e3826c2e814427a6cdfed6731cccfe548f12b36"}, + {file = "ckzg-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:98e70b5923d77c7359432490145e9d1ab0bf873eb5de56ec53f4a551d7eaec79"}, + {file = "ckzg-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:42af7bde4ca45469cd93a96c3d15d69d51d40e7f0d30e3a20711ebd639465fcb"}, + {file = "ckzg-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7e4edfdaf87825ff43b9885fabfdea408737a714f4ce5467100d9d1d0a03b673"}, + {file = "ckzg-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:815fd2a87d6d6c57d669fda30c150bc9bf387d47e67d84535aa42b909fdc28ea"}, + {file = "ckzg-2.1.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c32466e809b1ab3ff01d3b0bb0b9912f61dcf72957885615595f75e3f7cc10e5"}, + {file = "ckzg-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f11b73ccf37b12993f39a7dbace159c6d580aacacde6ee17282848476550ddbc"}, + {file = "ckzg-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de3b9433a1f2604bd9ac1646d3c83ad84a850d454d3ac589fe8e70c94b38a6b0"}, + {file = "ckzg-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b7d7e1b5ea06234558cd95c483666fd785a629b720a7f1622b3cbffebdc62033"}, + {file = "ckzg-2.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9f5556e6675866040cc4335907be6c537051e7f668da289fa660fdd8a30c9ddb"}, + {file = "ckzg-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:55b2ba30c5c9daac0c55f1aac851f1b7bf1f7aa0028c2db4440e963dd5b866d6"}, + {file = "ckzg-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:10d201601fc8f28c0e8cec3406676797024dd374c367bbeec5a7a9eac9147237"}, + {file = "ckzg-2.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:5f46c8fd5914db62b446baf62c8599da07e6f91335779a9709c554ef300a7b60"}, + {file = "ckzg-2.1.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:60f14612c2be84f405755d734b0ad4e445db8af357378b95b72339b59e1f4fcf"}, + {file = "ckzg-2.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:929e6e793039f42325988004a90d16b0ef4fc7e1330142e180f0298f2ed4527c"}, + {file = "ckzg-2.1.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2beac2af53ea181118179570ecc81d8a8fc52c529553d7fd8786fd100a2aa39b"}, + {file = "ckzg-2.1.1-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:2432d48aec296baee79556bfde3bddd2799bcc7753cd1f0d0c9a3b0333935637"}, + {file = "ckzg-2.1.1-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:4c2e8180b54261ccae2bf8acd003ccee7394d88d073271af19c5f2ac4a54c607"}, + {file = "ckzg-2.1.1-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:c44e36bd53d9dd0ab29bd6ed2d67ea43c48eecd57f8197854a75742213938bf5"}, + {file = "ckzg-2.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:10befd86e643d38ac468151cdfb71e79b2d46aa6397b81db4224f4f6995262eb"}, + {file = "ckzg-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:138a9324ad8e8a9ade464043dc3a84afe12996516788f2ed841bdbe5d123af81"}, + {file = "ckzg-2.1.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:635af0a33a10c9ac275f3efc142880a6b46ac63f4495f600aae05266af4fadff"}, + {file = "ckzg-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:360e263677ee5aedb279b42cf54b51c905ddcac9181c65d89ec0b298d3f31ec0"}, + {file = "ckzg-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f81395f77bfd069831cbb1de9d473c7044abe9ce6cd562ef6ccd76d23abcef43"}, + {file = "ckzg-2.1.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:db1ff122f8dc10c9500a00a4d680c3c38f4e19b01d95f38e0f5bc55a77c8ab98"}, + {file = "ckzg-2.1.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:1f82f539949ff3c6a5accfdd211919a3e374d354b3665d062395ebdbf8befaeb"}, + {file = "ckzg-2.1.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:5bc8ae85df97467e84abb491b516e25dbca36079e766eafce94d1bc45e4aaa35"}, + {file = "ckzg-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:e749ce9fcb26e37101f2af8ba9c6376b66eb598880d35e457890044ba77c1cf7"}, + {file = "ckzg-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b00201979a64fd7e6029f64d791af42374febb42452537933e881b49d4e8c77"}, + {file = "ckzg-2.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c61c437ba714ab7c802b51fb30125e8f8550e1320fe9050d20777420c153a2b3"}, + {file = "ckzg-2.1.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8bd54394376598a7c081df009cfde3cc447beb640b6c6b7534582a31e6290ac7"}, + {file = "ckzg-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67d8c6680a7b370718af59cc17a983752706407cfbcace013ee707646d1f7b00"}, + {file = "ckzg-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55f6c57b24bc4fe16b1b50324ef8548f2a5053ad76bf90c618e2f88c040120d7"}, + {file = "ckzg-2.1.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f55fc10fb1b217c66bfe14e05535e5e61cfbb2a95dbb9b93a80984fa2ab4a7c0"}, + {file = "ckzg-2.1.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:2e23e3198f8933f0140ef8b2aeba717d8de03ec7b8fb1ee946f8d39986ce0811"}, + {file = "ckzg-2.1.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2f9caf88bf216756bb1361b92616c750a933c9afb67972ad05c212649a9be520"}, + {file = "ckzg-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:30e0c2d258bbc0c099c2d1854c6ffa2fd9abf6138b9c81f855e1936f6cb259aa"}, + {file = "ckzg-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a6239d3d2e30cb894ca4e7765b1097eb6a70c0ecbe5f8e0b023fbf059472d4ac"}, + {file = "ckzg-2.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:909ebabc253a98d9dc1d51f93dc75990134bfe296c947e1ecf3b7142aba5108e"}, + {file = "ckzg-2.1.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0700dace6559b288b42ca8622be89c2a43509881ed6f4f0bfb6312bcceed0cb9"}, + {file = "ckzg-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a36aeabd243e906314694b4a107de99b0c4473ff1825fcb06acd147ffb1951a"}, + {file = "ckzg-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d884e8f9c7d7839f1a95561f4479096dce21d45b0c5dd013dc0842550cea1cad"}, + {file = "ckzg-2.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:338fdf4a0b463973fc7b7e4dc289739db929e61d7cb9ba984ebbe9c49d3aa6f9"}, + {file = "ckzg-2.1.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c594036d3408eebdcd8ab2c7aab7308239ed4df3d94f3211b7cf253f228fb0b7"}, + {file = "ckzg-2.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b0912ebb328ced510250a2325b095917db19c1a014792a0bf4c389f0493e39de"}, + {file = "ckzg-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:5046aceb03482ddf7200f2f5c643787b100e6fb96919852faf1c79f8870c80a1"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:375918e25eafb9bafe5215ab91698504cba3fe51b4fe92f5896af6c5663f50c6"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:38b3b7802c76d4ad015db2b7a79a49c193babae50ee5f77e9ac2865c9e9ddb09"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:438a5009fd254ace0bc1ad974d524547f1a41e6aa5e778c5cd41f4ee3106bcd6"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ce11cc163a2e0dab3af7455aca7053f9d5bb8d157f231acc7665fd230565d48"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b53964c07f6a076e97eaa1ef35045e935d7040aff14f80bae7e9105717702d05"}, + {file = "ckzg-2.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cf085f15ae52ab2599c9b5a3d5842794bcf5613b7f58661fbfb0c5d9eac988b9"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4b0c850bd6cad22ac79b2a2ab884e0e7cd2b54a67d643cd616c145ebdb535a11"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:26951f36bb60c9150bbd38110f5e1625596f9779dad54d1d492d8ec38bc84e3a"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe12445e49c4bee67746b7b958e90a973b0de116d0390749b0df351d94e9a8c"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71c5d4f66f09de4a99271acac74d2acb3559a77de77a366b34a91e99e8822667"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42673c1d007372a4e8b48f6ef8f0ce31a9688a463317a98539757d1e2fb1ecc7"}, + {file = "ckzg-2.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:57a7dc41ec6b69c1d9117eb61cf001295e6b4f67a736020442e71fb4367fb1a5"}, + {file = "ckzg-2.1.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:22e4606857660b2ffca2f7b96c01d0b18b427776d8a93320caf2b1c7342881fe"}, + {file = "ckzg-2.1.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b55475126a9efc82d61718b2d2323502e33d9733b7368c407954592ccac87faf"}, + {file = "ckzg-2.1.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5939ae021557c64935a7649b13f4a58f1bd35c39998fd70d0cefb5cbaf77d1be"}, + {file = "ckzg-2.1.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad1ec5f9726a9946508a4a2aace298172aa778de9ebbe97e21c873c3688cc87"}, + {file = "ckzg-2.1.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93d7edea3bb1602b18b394ebeec231d89dfd8d48fdd06571cb7656107aa62226"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c450d77af61011ced3777f97431d5f1bc148ca5362c67caf516aa2f6ef7e4817"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fc8df4e17e08974961d6c14f6c57ccfd3ad5aede74598292ec6e5d6fc2dbcac"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93338da8011790ef53a68475678bc951fa7b337db027d8edbf1889e59691161c"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4889f24b4ff614f39e3584709de1a3b0f1556675b33e360dbcb28cda827296d4"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7b58fbb1a9be4ae959feede8f103e12d80ef8453bdc6483bfdaf164879a2b80"}, + {file = "ckzg-2.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6136c5b5377c7f7033323b25bc2c7b43c025d44ed73e338c02f9f59df9460e5b"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fa419b92a0e8766deb7157fb28b6542c1c3f8dde35d2a69d1f91ec8e41047d35"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:95cd6c8eb3ab5148cd97ab5bf44b84fd7f01adf4b36ffd070340ad2d9309b3f9"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:848191201052b48bdde18680ebb77bf8da99989270e5aea8b0290051f5ac9468"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4716c0564131b0d609fb8856966e83892b9809cf6719c7edd6495b960451f8b"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c399168ba199827dee3104b00cdc7418d4dbdf47a5fcbe7cf938fc928037534"}, + {file = "ckzg-2.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:724f29f9f110d9ef42a6a1a1a7439548c61070604055ef96b2ab7a884cad4192"}, + {file = "ckzg-2.1.1.tar.gz", hash = "sha256:d6b306b7ec93a24e4346aa53d07f7f75053bc0afc7398e35fa649e5f9d48fcc4"}, +] + +[[package]] +name = "click" +version = "8.1.8" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, + {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "cprotobuf" +version = "0.1.11" +description = "Cython bindings for cprotobuf" +optional = false +python-versions = "*" +files = [] +develop = false + +[package.dependencies] +cython = "^3.0.12" + +[package.source] +type = "git" +url = "https://github.com/yihuang/cprotobuf.git" +reference = "master" +resolved_reference = "62d5870c6d89b12290d539fe5362e965db21ad61" + +[[package]] +name = "cython" +version = "3.1.1" +description = "The Cython compiler for writing C extensions in the Python language." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cython-3.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7adff5b42d2556d073e9f321c2faa639a17fb195ec1de130327f60ec209d8"}, + {file = "cython-3.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b61b99205308c96b1162de59bd67ecadcad3d166a4a1f03a3d9e826c39cd375"}, + {file = "cython-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d14186bd96783d13b8fd0e5b289f2e137a8a25479638b73a1c7e4a99a8d70753"}, + {file = "cython-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e3ccec55e2a534a712db14c6617b66f65ad149c014fad518fc3920f6edde770"}, + {file = "cython-3.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a585796939b09b3205b1980e4a55e745c0251e45a5c637afbcac3c6cc9ad6f90"}, + {file = "cython-3.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3fa4bd840de63509c74867b4b092541720a01db1e07351206011c34e0777dc96"}, + {file = "cython-3.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b68f1bc80387554eb43f2b62795c173bed9e37201f39dc5084ac437c90a79c9f"}, + {file = "cython-3.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e851ab66a31794e40df1bc6f649cdc56c998c637f5a1b9410c97a90f6b6cb855"}, + {file = "cython-3.1.1-cp310-cp310-win32.whl", hash = "sha256:64915259276482fa23417b284d1fdc7e3a618ee2f819bb6ea7f974c075633df6"}, + {file = "cython-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dee554f0a589377bdaea0eb70e212bf3f35dc6a51a2aa86c9351345e21fd2f07"}, + {file = "cython-3.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c360823e1063784efc2335617e0f28573d7a594c5a8a05d85e850a9621cccb1f"}, + {file = "cython-3.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:12e00b88147b03c148a95365f89dc1c45a0fc52f9c35aa75ff770ef65b615839"}, + {file = "cython-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab644415458d782c16ba7252de9cec1e3125371641cafea2e53a8c1cf85dd58d"}, + {file = "cython-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5cb6c054daadaf01a88c8f49f3edd9e829c9b76a82cbb4269e3f9878254540b"}, + {file = "cython-3.1.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af8f62cc9339b75fe8434325083e6a7cae88c9c21efd74bbb6ba4e3623219469"}, + {file = "cython-3.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:689c1aad373556bd2ab1aa1c2dad8939a2891465a1fbd2cbbdd42b488fb40ec8"}, + {file = "cython-3.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:953046c190fa9ab9a09a546a909b847cdbb4c1fe34e9bfa4a15b6ee1585a86aa"}, + {file = "cython-3.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:755a991601b27dd3555310d0f95b19a05e622a80d7b4e7a91fa6f5f3ef3f3b80"}, + {file = "cython-3.1.1-cp311-cp311-win32.whl", hash = "sha256:83b2af5c327f7da4f08afc34fddfaf6d24fa0c000b6b70a527c8125e493b6080"}, + {file = "cython-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:141ffd6279411c562f6b707adc56b63e965a4fd7f21db83f5d4fcbd8c50ac546"}, + {file = "cython-3.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9d7dc0e4d0cd491fac679a61e9ede348c64ca449f99a284f9a01851aa1dbc7f6"}, + {file = "cython-3.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fd689910002adfac8734f237cdea1573e38345f27ed7fd445482813b65a29457"}, + {file = "cython-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10f0434916994fe213ea7749268b88d77e3ebcbd1b99542cf64bb7d180f45470"}, + {file = "cython-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:873aac4ac0b0fb197557c0ac15458b780b9221daa4a716881cbd1a9016c8459f"}, + {file = "cython-3.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23b886a6c8a50b1101ccef2f2f3dc9c699b77633ef5bb5007090226c2ad3f9c2"}, + {file = "cython-3.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:dff0e7dd53a0ca35b64cda843253d5cac944db26663dc097b3a1adf2c49514ad"}, + {file = "cython-3.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f7954b0b4b3302655d3caa6924261de5907a4e129bc22ace52fe9ae0cd5a758"}, + {file = "cython-3.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dfa500fd7ae95ca152a5f8062b870532fa3e27efcef6d00612e1f28b9f72615f"}, + {file = "cython-3.1.1-cp312-cp312-win32.whl", hash = "sha256:cd748fab8e4426dbcb2e0fa2979558333934d24365e0de5672fbabfe337d880c"}, + {file = "cython-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:307f216ed319ea07644f2ef9974406c830f01bc8e677e2147e9bfcdf9e3ca8ad"}, + {file = "cython-3.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb5661941707bd41ec7a9c273d698113ac50392444f785088e9d9706c6a5937b"}, + {file = "cython-3.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:28b174f41718a7041cfbe0f48913020875ff1aaa4793942b2451ac6d2baf3f07"}, + {file = "cython-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c740a10cd0f50321d048c8ca318eefb4c42b8bffef982dcd89c946d374192702"}, + {file = "cython-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7da069ca769903c5dee56c5f7ab47b2b7b91030eee48912630db5f4f3ec5954a"}, + {file = "cython-3.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24c640c0746d984789fe2787a098f06cda456ef2dd78b90164d17884b350839a"}, + {file = "cython-3.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:426d78565eb91d3366569b20e92b8f14bffef5f57b2acd05b60bbb9ce5c056a1"}, + {file = "cython-3.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b181158b5761bdaf40f6854f016ab7ddff64d3db4fca55cb3ca0f73813dd76d6"}, + {file = "cython-3.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7489559e6c5ecbba49d535c2e03cf77c2594a3190b6aca7da5b508ba1664a89a"}, + {file = "cython-3.1.1-cp313-cp313-win32.whl", hash = "sha256:263cb0e497910fb5e0a361ad1393b6d728b092178afecc56e8a786f3739960c3"}, + {file = "cython-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:e000f0533eedf3d6dfbe30bb3c58a054c58f0a7778390342fa577a0dc47adab3"}, + {file = "cython-3.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdf53dc4b2a13bd072d6c2c18ac073dbf0f798555bc27ba4f7546a275eb16a0f"}, + {file = "cython-3.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ce82070ccf92c3599d331b9eaaefd9d4562976fb86a8d6bccf05c4a0b8389f2a"}, + {file = "cython-3.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:020089f9c9f10269181f17660a2cada7d4577bd8eea24b7d2b14e6b64b6996be"}, + {file = "cython-3.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:402f86c00b08f875cd0990f0c4dc52eb3e0bc5d630066cdf3c798631976f1937"}, + {file = "cython-3.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54a8934cb3bf13b1f8f6cbdae8e382e25a26e67de08ea6ebfd0a467131b67227"}, + {file = "cython-3.1.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6ea77ad1e649cec38f8622ba28dcdfbe7bf519bc132abbcf5df759b3975b5a73"}, + {file = "cython-3.1.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:7e5cad896af896482240979b996bf4136b0d18dc40c56c72c5641bf0ea085dfb"}, + {file = "cython-3.1.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:16d9870654946375b28280371d370d541641d1071da123d0d64d2c7ebba0cc56"}, + {file = "cython-3.1.1-cp38-cp38-win32.whl", hash = "sha256:8aaa29e763adf3496ab9d371e3caed8da5d3ce5ff8fb57433e2a2f2b5036e5c8"}, + {file = "cython-3.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:011cdcbf7725f0cfc1abc55ec83d326e788050711272131daf3cc24a19c34bb2"}, + {file = "cython-3.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:40f50b07c479eaf33981d81cad274c68cf9fb81dbe79cbf991f59491c88a4705"}, + {file = "cython-3.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a92f6bd395eadea6eed722a8188d3bdd49db1c9fa3c38710456d6148ab71bad7"}, + {file = "cython-3.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:268420b92307ae6c5a16e3cf0e2ba1ae3c861650e992893922a0ce08db07cfdb"}, + {file = "cython-3.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a19188ecd385cdc649e3fec370f38d5fd7f1651aeed0b3fb403180f38fc88e8a"}, + {file = "cython-3.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fff6526bb6f4eea615663117b86de6ede0d17c477b600d3d8302be3502bd3c3"}, + {file = "cython-3.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3192a61c2a532d3faccdff508bc8427de9530b587888218bfc0226eb33a84e11"}, + {file = "cython-3.1.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:56c6768a6f601f93daab7c2487f9f110548a896a91e00a6e119445ada2575323"}, + {file = "cython-3.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:50ad80e2f438e9127a87c10927e6ac16a987df39c248b19ab2cd31330129be3c"}, + {file = "cython-3.1.1-cp39-cp39-win32.whl", hash = "sha256:b194a65a0fd91f305d2d1e7010f44111774a28533e1e44dd2a76e7de81a219b9"}, + {file = "cython-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:c8b8be01fd40b3e38a76c60a524f956548a3a7566e5530a833a48a695f3d6c12"}, + {file = "cython-3.1.1-py3-none-any.whl", hash = "sha256:07621e044f332d18139df2ccfcc930151fd323c2f61a58c82f304cffc9eb5280"}, + {file = "cython-3.1.1.tar.gz", hash = "sha256:505ccd413669d5132a53834d792c707974248088c4f60c497deb1b416e366397"}, +] + +[[package]] +name = "cytoolz" +version = "1.0.1" +description = "Cython implementation of Toolz: High performance functional utilities" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cytoolz-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cec9af61f71fc3853eb5dca3d42eb07d1f48a4599fa502cbe92adde85f74b042"}, + {file = "cytoolz-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:140bbd649dbda01e91add7642149a5987a7c3ccc251f2263de894b89f50b6608"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e90124bdc42ff58b88cdea1d24a6bc5f776414a314cc4d94f25c88badb3a16d1"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e74801b751e28f7c5cc3ad264c123954a051f546f2fdfe089f5aa7a12ccfa6da"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:582dad4545ddfb5127494ef23f3fa4855f1673a35d50c66f7638e9fb49805089"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd7bd0618e16efe03bd12f19c2a26a27e6e6b75d7105adb7be1cd2a53fa755d8"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d74cca6acf1c4af58b2e4a89cc565ed61c5e201de2e434748c93e5a0f5c541a5"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:823a3763828d8d457f542b2a45d75d6b4ced5e470b5c7cf2ed66a02f508ed442"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:51633a14e6844c61db1d68c1ffd077cf949f5c99c60ed5f1e265b9e2966f1b52"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f3ec9b01c45348f1d0d712507d54c2bfd69c62fbd7c9ef555c9d8298693c2432"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1855022b712a9c7a5bce354517ab4727a38095f81e2d23d3eabaf1daeb6a3b3c"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9930f7288c4866a1dc1cc87174f0c6ff4cad1671eb1f6306808aa6c445857d78"}, + {file = "cytoolz-1.0.1-cp310-cp310-win32.whl", hash = "sha256:a9baad795d72fadc3445ccd0f122abfdbdf94269157e6d6d4835636dad318804"}, + {file = "cytoolz-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:ad95b386a84e18e1f6136f6d343d2509d4c3aae9f5a536f3dc96808fcc56a8cf"}, + {file = "cytoolz-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2d958d4f04d9d7018e5c1850790d9d8e68b31c9a2deebca74b903706fdddd2b6"}, + {file = "cytoolz-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0f445b8b731fc0ecb1865b8e68a070084eb95d735d04f5b6c851db2daf3048ab"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f546a96460a7e28eb2ec439f4664fa646c9b3e51c6ebad9a59d3922bbe65e30"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0317681dd065532d21836f860b0563b199ee716f55d0c1f10de3ce7100c78a3b"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c0ef52febd5a7821a3fd8d10f21d460d1a3d2992f724ba9c91fbd7a96745d41"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5ebaf419acf2de73b643cf96108702b8aef8e825cf4f63209ceb078d5fbbbfd"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f7f04eeb4088947585c92d6185a618b25ad4a0f8f66ea30c8db83cf94a425e3"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f61928803bb501c17914b82d457c6f50fe838b173fb40d39c38d5961185bd6c7"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d2960cb4fa01ccb985ad1280db41f90dc97a80b397af970a15d5a5de403c8c61"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2b407cc3e9defa8df5eb46644f6f136586f70ba49eba96f43de67b9a0984fd3"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8245f929144d4d3bd7b972c9593300195c6cea246b81b4c46053c48b3f044580"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e37385db03af65763933befe89fa70faf25301effc3b0485fec1c15d4ce4f052"}, + {file = "cytoolz-1.0.1-cp311-cp311-win32.whl", hash = "sha256:50f9c530f83e3e574fc95c264c3350adde8145f4f8fc8099f65f00cc595e5ead"}, + {file = "cytoolz-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:b7f6b617454b4326af7bd3c7c49b0fc80767f134eb9fd6449917a058d17a0e3c"}, + {file = "cytoolz-1.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fcb8f7d0d65db1269022e7e0428471edee8c937bc288ebdcb72f13eaa67c2fe4"}, + {file = "cytoolz-1.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:207d4e4b445e087e65556196ff472ff134370d9a275d591724142e255f384662"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21cdf6bac6fd843f3b20280a66fd8df20dea4c58eb7214a2cd8957ec176f0bb3"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a55ec098036c0dea9f3bdc021f8acd9d105a945227d0811589f0573f21c9ce1"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a13ab79ff4ce202e03ab646a2134696988b554b6dc4b71451e948403db1331d8"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e2d944799026e1ff08a83241f1027a2d9276c41f7a74224cd98b7df6e03957d"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88ba85834cd523b91fdf10325e1e6d71c798de36ea9bdc187ca7bd146420de6f"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a750b1af7e8bf6727f588940b690d69e25dc47cce5ce467925a76561317eaf7"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:44a71870f7eae31d263d08b87da7c2bf1176f78892ed8bdade2c2850478cb126"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c8231b9abbd8e368e036f4cc2e16902c9482d4cf9e02a6147ed0e9a3cd4a9ab0"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:aa87599ccc755de5a096a4d6c34984de6cd9dc928a0c5eaa7607457317aeaf9b"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:67cd16537df51baabde3baa770ab7b8d16839c4d21219d5b96ac59fb012ebd2d"}, + {file = "cytoolz-1.0.1-cp312-cp312-win32.whl", hash = "sha256:fb988c333f05ee30ad4693fe4da55d95ec0bb05775d2b60191236493ea2e01f9"}, + {file = "cytoolz-1.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:8f89c48d8e5aec55ffd566a8ec858706d70ed0c6a50228eca30986bfa5b4da8b"}, + {file = "cytoolz-1.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6944bb93b287032a4c5ca6879b69bcd07df46f3079cf8393958cf0b0454f50c0"}, + {file = "cytoolz-1.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e027260fd2fc5cb041277158ac294fc13dca640714527219f702fb459a59823a"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88662c0e07250d26f5af9bc95911e6137e124a5c1ec2ce4a5d74de96718ab242"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:309dffa78b0961b4c0cf55674b828fbbc793cf2d816277a5c8293c0c16155296"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:edb34246e6eb40343c5860fc51b24937698e4fa1ee415917a73ad772a9a1746b"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a54da7a8e4348a18d45d4d5bc84af6c716d7f131113a4f1cc45569d37edff1b"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:241c679c3b1913c0f7259cf1d9639bed5084c86d0051641d537a0980548aa266"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5bfc860251a8f280ac79696fc3343cfc3a7c30b94199e0240b6c9e5b6b01a2a5"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c8edd1547014050c1bdad3ff85d25c82bd1c2a3c96830c6181521eb78b9a42b3"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b349bf6162e8de215403d7f35f8a9b4b1853dc2a48e6e1a609a5b1a16868b296"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1b18b35256219b6c3dd0fa037741b85d0bea39c552eab0775816e85a52834140"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:738b2350f340ff8af883eb301054eb724997f795d20d90daec7911c389d61581"}, + {file = "cytoolz-1.0.1-cp313-cp313-win32.whl", hash = "sha256:9cbd9c103df54fcca42be55ef40e7baea624ac30ee0b8bf1149f21146d1078d9"}, + {file = "cytoolz-1.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:90e577e08d3a4308186d9e1ec06876d4756b1e8164b92971c69739ea17e15297"}, + {file = "cytoolz-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f3a509e4ac8e711703c368476b9bbce921fcef6ebb87fa3501525f7000e44185"}, + {file = "cytoolz-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a7eecab6373e933dfbf4fdc0601d8fd7614f8de76793912a103b5fccf98170cd"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e55ed62087f6e3e30917b5f55350c3b6be6470b849c6566018419cd159d2cebc"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43de33d99a4ccc07234cecd81f385456b55b0ea9c39c9eebf42f024c313728a5"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:139bed875828e1727018aa0982aa140e055cbafccb7fd89faf45cbb4f2a21514"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22c12671194b518aa8ce2f4422bd5064f25ab57f410ba0b78705d0a219f4a97a"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79888f2f7dc25709cd5d37b032a8833741e6a3692c8823be181d542b5999128e"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:51628b4eb41fa25bd428f8f7b5b74fbb05f3ae65fbd265019a0dd1ded4fdf12a"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:1db9eb7179285403d2fb56ba1ff6ec35a44921b5e2fa5ca19d69f3f9f0285ea5"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:08ab7efae08e55812340bfd1b3f09f63848fe291675e2105eab1aa5327d3a16e"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e5fdc5264f884e7c0a1711a81dff112708a64b9c8561654ee578bfdccec6be09"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:90d6a2e6ab891043ee655ec99d5e77455a9bee9e1131bdfcfb745edde81200dd"}, + {file = "cytoolz-1.0.1-cp38-cp38-win32.whl", hash = "sha256:08946e083faa5147751b34fbf78ab931f149ef758af5c1092932b459e18dcf5c"}, + {file = "cytoolz-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:a91b4e10a9c03796c0dc93e47ebe25bb41ecc6fafc3cf5197c603cf767a3d44d"}, + {file = "cytoolz-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:980c323e626ba298b77ae62871b2de7c50b9d7219e2ddf706f52dd34b8be7349"}, + {file = "cytoolz-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:45f6fa1b512bc2a0f2de5123db932df06c7f69d12874fe06d67772b2828e2c8b"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93f42d9100c415155ad1f71b0de362541afd4ac95e3153467c4c79972521b6b"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a76d20dec9c090cdf4746255bbf06a762e8cc29b5c9c1d138c380bbdb3122ade"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:239039585487c69aa50c5b78f6a422016297e9dea39755761202fb9f0530fe87"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c28307640ca2ab57b9fbf0a834b9bf563958cd9e038378c3a559f45f13c3c541"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:454880477bb901cee3a60f6324ec48c95d45acc7fecbaa9d49a5af737ded0595"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:902115d1b1f360fd81e44def30ac309b8641661150fcbdde18ead446982ada6a"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e68e6b38473a3a79cee431baa22be31cac39f7df1bf23eaa737eaff42e213883"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:32fba3f63fcb76095b0a22f4bdcc22bc62a2bd2d28d58bf02fd21754c155a3ec"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0724ba4cf41eb40b6cf75250820ab069e44bdf4183ff78857aaf4f0061551075"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c42420e0686f887040d5230420ed44f0e960ccbfa29a0d65a3acd9ca52459209"}, + {file = "cytoolz-1.0.1-cp39-cp39-win32.whl", hash = "sha256:4ba8b16358ea56b1fe8e637ec421e36580866f2e787910bac1cf0a6997424a34"}, + {file = "cytoolz-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:92d27f84bf44586853d9562bfa3610ecec000149d030f793b4cb614fd9da1813"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:83d19d55738ad9c60763b94f3f6d3c6e4de979aeb8d76841c1401081e0e58d96"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f112a71fad6ea824578e6393765ce5c054603afe1471a5c753ff6c67fd872d10"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a515df8f8aa6e1eaaf397761a6e4aff2eef73b5f920aedf271416d5471ae5ee"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92c398e7b7023460bea2edffe5fcd0a76029580f06c3f6938ac3d198b47156f3"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3237e56211e03b13df47435b2369f5df281e02b04ad80a948ebd199b7bc10a47"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba0d1da50aab1909b165f615ba1125c8b01fcc30d606c42a61c42ea0269b5e2c"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25b6e8dec29aa5a390092d193abd673e027d2c0b50774ae816a31454286c45c7"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36cd6989ebb2f18fe9af8f13e3c61064b9f741a40d83dc5afeb0322338ad25f2"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47394f8ab7fca3201f40de61fdeea20a2baffb101485ae14901ea89c3f6c95d"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d00ac423542af944302e034e618fb055a0c4e87ba704cd6a79eacfa6ac83a3c9"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a5ca923d1fa632f7a4fb33c0766c6fba7f87141a055c305c3e47e256fb99c413"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:058bf996bcae9aad3acaeeb937d42e0c77c081081e67e24e9578a6a353cb7fb2"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69e2a1f41a3dad94a17aef4a5cc003323359b9f0a9d63d4cc867cb5690a2551d"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67daeeeadb012ec2b59d63cb29c4f2a2023b0c4957c3342d354b8bb44b209e9a"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:54d3d36bbf0d4344d1afa22c58725d1668e30ff9de3a8f56b03db1a6da0acb11"}, + {file = "cytoolz-1.0.1.tar.gz", hash = "sha256:89cc3161b89e1bb3ed7636f74ed2e55984fd35516904fc878cae216e42b2c7d6"}, +] + +[package.dependencies] +toolz = ">=0.8.0" + +[package.extras] +cython = ["cython"] + +[[package]] +name = "docker" +version = "7.1.0" +description = "A Python library for the Docker Engine API." +optional = false +python-versions = ">=3.8" +files = [ + {file = "docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0"}, + {file = "docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c"}, +] + +[package.dependencies] +pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""} +requests = ">=2.26.0" +urllib3 = ">=1.26.0" + +[package.extras] +dev = ["coverage (==7.2.7)", "pytest (==7.4.2)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.1.0)", "ruff (==0.1.8)"] +docs = ["myst-parser (==0.18.0)", "sphinx (==5.1.1)"] +ssh = ["paramiko (>=2.4.3)"] +websockets = ["websocket-client (>=1.3.0)"] + +[[package]] +name = "durations" +version = "0.3.3" +description = "UNKNOWN" +optional = false +python-versions = "*" +files = [ + {file = "durations-0.3.3.tar.gz", hash = "sha256:820ffe09c390469dc621b6a0aa46d3a624b6dadf09b439e175696b6f6b77ef2f"}, +] + +[[package]] +name = "eth-abi" +version = "5.2.0" +description = "eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "eth_abi-5.2.0-py3-none-any.whl", hash = "sha256:17abe47560ad753f18054f5b3089fcb588f3e3a092136a416b6c1502cb7e8877"}, + {file = "eth_abi-5.2.0.tar.gz", hash = "sha256:178703fa98c07d8eecd5ae569e7e8d159e493ebb6eeb534a8fe973fbc4e40ef0"}, +] + +[package.dependencies] +eth-typing = ">=3.0.0" +eth-utils = ">=2.0.0" +parsimonious = ">=0.10.0,<0.11.0" + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "eth-hash[pycryptodome]", "hypothesis (>=6.22.0,<6.108.7)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["eth-hash[pycryptodome]", "hypothesis (>=6.22.0,<6.108.7)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)"] +tools = ["hypothesis (>=6.22.0,<6.108.7)"] + +[[package]] +name = "eth-account" +version = "0.13.7" +description = "eth-account: Sign Ethereum transactions and messages with local private keys" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "eth_account-0.13.7-py3-none-any.whl", hash = "sha256:39727de8c94d004ff61d10da7587509c04d2dc7eac71e04830135300bdfc6d24"}, + {file = "eth_account-0.13.7.tar.gz", hash = "sha256:5853ecbcbb22e65411176f121f5f24b8afeeaf13492359d254b16d8b18c77a46"}, +] + +[package.dependencies] +bitarray = ">=2.4.0" +ckzg = ">=2.0.0" +eth-abi = ">=4.0.0-b.2" +eth-keyfile = ">=0.7.0,<0.9.0" +eth-keys = ">=0.4.0" +eth-rlp = ">=2.1.0" +eth-utils = ">=2.0.0" +hexbytes = ">=1.2.0" +pydantic = ">=2.0.0" +rlp = ">=1.0.0" + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "coverage", "hypothesis (>=6.22.0,<6.108.7)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["coverage", "hypothesis (>=6.22.0,<6.108.7)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + +[[package]] +name = "eth-bloom" +version = "3.1.0" +description = "A python implementation of the bloom filter used by Ethereum" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "eth_bloom-3.1.0-py3-none-any.whl", hash = "sha256:c96b2dd6cafa407373bca1a9d74b650378ba672d5b17f2771bf7d3c3aaa7651c"}, + {file = "eth_bloom-3.1.0.tar.gz", hash = "sha256:4bc918f6fde44334e92b23cfb345db961e2e3af620535cbc872444f7a143cb88"}, +] + +[package.dependencies] +eth-hash = {version = ">=0.4.0", extras = ["pycryptodome"]} + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "hypothesis (>=3.31.2)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["towncrier (>=24,<25)"] +test = ["hypothesis (>=3.31.2)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + +[[package]] +name = "eth-contract" +version = "0.3.0" +description = "Add your description here" +optional = false +python-versions = ">=3.9" +files = [] +develop = false + +[package.dependencies] +web3 = ">=7.12.0" + +[package.source] +type = "git" +url = "https://github.com/yihuang/eth-contract.git" +reference = "main" +resolved_reference = "818d39d43a150cd2c36ea1a5c89db3461f80a8fa" + +[[package]] +name = "eth-hash" +version = "0.7.1" +description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "eth_hash-0.7.1-py3-none-any.whl", hash = "sha256:0fb1add2adf99ef28883fd6228eb447ef519ea72933535ad1a0b28c6f65f868a"}, + {file = "eth_hash-0.7.1.tar.gz", hash = "sha256:d2411a403a0b0a62e8247b4117932d900ffb4c8c64b15f92620547ca5ce46be5"}, +] + +[package.dependencies] +pycryptodome = {version = ">=3.6.6,<4", optional = true, markers = "extra == \"pycryptodome\""} + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +pycryptodome = ["pycryptodome (>=3.6.6,<4)"] +pysha3 = ["pysha3 (>=1.0.0,<2.0.0)", "safe-pysha3 (>=1.0.0)"] +test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + +[[package]] +name = "eth-keyfile" +version = "0.8.1" +description = "eth-keyfile: A library for handling the encrypted keyfiles used to store ethereum private keys" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "eth_keyfile-0.8.1-py3-none-any.whl", hash = "sha256:65387378b82fe7e86d7cb9f8d98e6d639142661b2f6f490629da09fddbef6d64"}, + {file = "eth_keyfile-0.8.1.tar.gz", hash = "sha256:9708bc31f386b52cca0969238ff35b1ac72bd7a7186f2a84b86110d3c973bec1"}, +] + +[package.dependencies] +eth-keys = ">=0.4.0" +eth-utils = ">=2" +pycryptodome = ">=3.6.6,<4" + +[package.extras] +dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["towncrier (>=21,<22)"] +test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + +[[package]] +name = "eth-keys" +version = "0.7.0" +description = "eth-keys: Common API for Ethereum key operations" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "eth_keys-0.7.0-py3-none-any.whl", hash = "sha256:b0cdda8ffe8e5ba69c7c5ca33f153828edcace844f67aabd4542d7de38b159cf"}, + {file = "eth_keys-0.7.0.tar.gz", hash = "sha256:79d24fd876201df67741de3e3fefb3f4dbcbb6ace66e47e6fe662851a4547814"}, +] + +[package.dependencies] +eth-typing = ">=3" +eth-utils = ">=2" + +[package.extras] +coincurve = ["coincurve (>=17.0.0)"] +dev = ["asn1tools (>=0.146.2)", "build (>=0.9.0)", "bump_my_version (>=0.19.0)", "coincurve (>=17.0.0)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["towncrier (>=24,<25)"] +test = ["asn1tools (>=0.146.2)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)"] + +[[package]] +name = "eth-rlp" +version = "2.2.0" +description = "eth-rlp: RLP definitions for common Ethereum objects in Python" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "eth_rlp-2.2.0-py3-none-any.whl", hash = "sha256:5692d595a741fbaef1203db6a2fedffbd2506d31455a6ad378c8449ee5985c47"}, + {file = "eth_rlp-2.2.0.tar.gz", hash = "sha256:5e4b2eb1b8213e303d6a232dfe35ab8c29e2d3051b86e8d359def80cd21db83d"}, +] + +[package.dependencies] +eth-utils = ">=2.0.0" +hexbytes = ">=1.2.0" +rlp = ">=0.6.0" + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "eth-hash[pycryptodome]", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["eth-hash[pycryptodome]", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + +[[package]] +name = "eth-typing" +version = "5.2.1" +description = "eth-typing: Common type annotations for ethereum python packages" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "eth_typing-5.2.1-py3-none-any.whl", hash = "sha256:b0c2812ff978267563b80e9d701f487dd926f1d376d674f3b535cfe28b665d3d"}, + {file = "eth_typing-5.2.1.tar.gz", hash = "sha256:7557300dbf02a93c70fa44af352b5c4a58f94e997a0fd6797fb7d1c29d9538ee"}, +] + +[package.dependencies] +typing_extensions = ">=4.5.0" + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + +[[package]] +name = "eth-utils" +version = "5.3.0" +description = "eth-utils: Common utility functions for python code that interacts with Ethereum" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "eth_utils-5.3.0-py3-none-any.whl", hash = "sha256:ac184883ab299d923428bbe25dae5e356979a3993e0ef695a864db0a20bc262d"}, + {file = "eth_utils-5.3.0.tar.gz", hash = "sha256:1f096867ac6be895f456fa3acb26e9573ae66e753abad9208f316d24d6178156"}, +] + +[package.dependencies] +cytoolz = {version = ">=0.10.1", markers = "implementation_name == \"cpython\""} +eth-hash = ">=0.3.1" +eth-typing = ">=5.0.0" +pydantic = ">=2.0.0,<3" +toolz = {version = ">0.8.2", markers = "implementation_name == \"pypy\""} + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "eth-hash[pycryptodome]", "hypothesis (>=4.43.0)", "ipython", "mypy (==1.10.0)", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["hypothesis (>=4.43.0)", "mypy (==1.10.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + +[[package]] +name = "fire" +version = "0.7.0" +description = "A library for automatically generating command line interfaces." +optional = false +python-versions = "*" +files = [ + {file = "fire-0.7.0.tar.gz", hash = "sha256:961550f07936eaf65ad1dc8360f2b2bf8408fad46abbfa4d2a3794f8d2a95cdf"}, +] + +[package.dependencies] +termcolor = "*" + +[[package]] +name = "flake8" +version = "7.1.2" +description = "the modular source code checker: pep8 pyflakes and co" +optional = false +python-versions = ">=3.8.1" +files = [ + {file = "flake8-7.1.2-py2.py3-none-any.whl", hash = "sha256:1cbc62e65536f65e6d754dfe6f1bada7f5cf392d6f5db3c2b85892466c3e7c1a"}, + {file = "flake8-7.1.2.tar.gz", hash = "sha256:c586ffd0b41540951ae41af572e6790dbd49fc12b3aa2541685d253d9bd504bd"}, +] + +[package.dependencies] +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.12.0,<2.13.0" +pyflakes = ">=3.2.0,<3.3.0" + +[[package]] +name = "flake8-black" +version = "0.3.6" +description = "flake8 plugin to call black as a code style validator" +optional = false +python-versions = ">=3.7" +files = [ + {file = "flake8-black-0.3.6.tar.gz", hash = "sha256:0dfbca3274777792a5bcb2af887a4cad72c72d0e86c94e08e3a3de151bb41c34"}, + {file = "flake8_black-0.3.6-py3-none-any.whl", hash = "sha256:fe8ea2eca98d8a504f22040d9117347f6b367458366952862ac3586e7d4eeaca"}, +] + +[package.dependencies] +black = ">=22.1.0" +flake8 = ">=3" + +[package.extras] +develop = ["build", "twine"] + +[[package]] +name = "flake8-isort" +version = "6.1.2" +description = "flake8 plugin that integrates isort" +optional = false +python-versions = ">=3.9" +files = [ + {file = "flake8_isort-6.1.2-py3-none-any.whl", hash = "sha256:549197dedf0273502fb74f04c080beed9e62a7eb70244610413d27052e78bd3b"}, + {file = "flake8_isort-6.1.2.tar.gz", hash = "sha256:9d0452acdf0e1cd6f2d6848e3605e66b54d920e73471fb4744eef0f93df62d5d"}, +] + +[package.dependencies] +flake8 = "*" +isort = ">=5.0.0,<7" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "flaky" +version = "3.8.1" +description = "Plugin for pytest that automatically reruns flaky tests." +optional = false +python-versions = ">=3.5" +files = [ + {file = "flaky-3.8.1-py2.py3-none-any.whl", hash = "sha256:194ccf4f0d3a22b2de7130f4b62e45e977ac1b5ccad74d4d48f3005dcc38815e"}, + {file = "flaky-3.8.1.tar.gz", hash = "sha256:47204a81ec905f3d5acfbd61daeabcada8f9d4031616d9bcb0618461729699f5"}, +] + +[[package]] +name = "frozenlist" +version = "1.6.2" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.9" +files = [ + {file = "frozenlist-1.6.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:92836b9903e52f787f4f4bfc6cf3b03cf19de4cbc09f5969e58806f876d8647f"}, + {file = "frozenlist-1.6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3af419982432a13a997451e611ff7681a4fbf81dca04f70b08fc51106335ff0"}, + {file = "frozenlist-1.6.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1570ba58f0852a6e6158d4ad92de13b9aba3474677c3dee827ba18dcf439b1d8"}, + {file = "frozenlist-1.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0de575df0135949c4049ae42db714c43d1693c590732abc78c47a04228fc1efb"}, + {file = "frozenlist-1.6.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2b6eaba27ec2b3c0af7845619a425eeae8d510d5cc83fb3ef80569129238153b"}, + {file = "frozenlist-1.6.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af1ee5188d2f63b4f09b67cf0c60b8cdacbd1e8d24669eac238e247d8b157581"}, + {file = "frozenlist-1.6.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9179c5186eb996c0dd7e4c828858ade4d7a8d1d12dd67320675a6ae7401f2647"}, + {file = "frozenlist-1.6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38814ebc3c6bb01dc3bb4d6cffd0e64c19f4f2d03e649978aeae8e12b81bdf43"}, + {file = "frozenlist-1.6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dbcab0531318fc9ca58517865fae63a2fe786d5e2d8f3a56058c29831e49f13"}, + {file = "frozenlist-1.6.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7472e477dc5d6a000945f45b6e38cbb1093fdec189dc1e98e57f8ab53f8aa246"}, + {file = "frozenlist-1.6.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:17c230586d47332774332af86cc1e69ee095731ec70c27e5698dfebb9db167a0"}, + {file = "frozenlist-1.6.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:946a41e095592cf1c88a1fcdd154c13d0ef6317b371b817dc2b19b3d93ca0811"}, + {file = "frozenlist-1.6.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d90c9b36c669eb481de605d3c2da02ea98cba6a3f5e93b3fe5881303026b2f14"}, + {file = "frozenlist-1.6.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8651dd2d762d6eefebe8450ec0696cf3706b0eb5e46463138931f70c667ba612"}, + {file = "frozenlist-1.6.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:48400e6a09e217346949c034105b0df516a1b3c5aa546913b70b71b646caa9f5"}, + {file = "frozenlist-1.6.2-cp310-cp310-win32.whl", hash = "sha256:56354f09082262217f837d91106f1cc204dd29ac895f9bbab33244e2fa948bd7"}, + {file = "frozenlist-1.6.2-cp310-cp310-win_amd64.whl", hash = "sha256:3016ff03a332cdd2800f0eed81ca40a2699b2f62f23626e8cf81a2993867978a"}, + {file = "frozenlist-1.6.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eb66c5d48b89701b93d58c31a48eb64e15d6968315a9ccc7dfbb2d6dc2c62ab7"}, + {file = "frozenlist-1.6.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8fb9aee4f7b495044b868d7e74fb110d8996e8fddc0bfe86409c7fc7bd5692f0"}, + {file = "frozenlist-1.6.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:48dde536fc4d8198fad4e211f977b1a5f070e6292801decf2d6bc77b805b0430"}, + {file = "frozenlist-1.6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91dd2fb760f4a2c04b3330e0191787c3437283f9241f0b379017d4b13cea8f5e"}, + {file = "frozenlist-1.6.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f01f34f8a5c7b4d74a1c65227678822e69801dcf68edd4c11417a7c83828ff6f"}, + {file = "frozenlist-1.6.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f43f872cc4cfc46d9805d0e71302e9c39c755d5ad7572198cd2ceb3a291176cc"}, + {file = "frozenlist-1.6.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f96cc8ab3a73d42bcdb6d9d41c3dceffa8da8273ac54b71304b891e32de8b13"}, + {file = "frozenlist-1.6.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c0b257123320832cce9bea9935c860e4fa625b0e58b10db49fdfef70087df81"}, + {file = "frozenlist-1.6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23dc4def97ccc0232f491836050ae664d3d2352bb43ad4cd34cd3399ad8d1fc8"}, + {file = "frozenlist-1.6.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fcf3663463c040315f025bd6a5f88b3748082cfe111e90fd422f71668c65de52"}, + {file = "frozenlist-1.6.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:16b9e7b59ea6eef876a8a5fac084c95fd4bac687c790c4d48c0d53c6bcde54d1"}, + {file = "frozenlist-1.6.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:308b40d32a98a8d0d09bc28e4cbc13a0b803a0351041d4548564f28f6b148b05"}, + {file = "frozenlist-1.6.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:baf585d8968eaad6c1aae99456c40978a9fa822ccbdb36fd4746b581ef338192"}, + {file = "frozenlist-1.6.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4dfdbdb671a6af6ea1a363b210373c8233df3925d9a7fb99beaa3824f6b99656"}, + {file = "frozenlist-1.6.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:94916e3acaeb8374d5aea9c37db777c9f0a2b9be46561f5de30064cbbbfae54a"}, + {file = "frozenlist-1.6.2-cp311-cp311-win32.whl", hash = "sha256:0453e3d2d12616949cb2581068942a0808c7255f2abab0676d2da7db30f9ea11"}, + {file = "frozenlist-1.6.2-cp311-cp311-win_amd64.whl", hash = "sha256:fb512753c4bbf0af03f6b9c7cc5ecc9bbac2e198a94f61aaabd26c3cf3229c8c"}, + {file = "frozenlist-1.6.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:48544d07404d7fcfccb6cc091922ae10de4d9e512c537c710c063ae8f5662b85"}, + {file = "frozenlist-1.6.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ee0cf89e7638de515c0bb2e8be30e8e2e48f3be9b6c2f7127bca4a1f35dff45"}, + {file = "frozenlist-1.6.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e084d838693d73c0fe87d212b91af80c18068c95c3d877e294f165056cedfa58"}, + {file = "frozenlist-1.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84d918b01781c6ebb5b776c18a87dd3016ff979eb78626aaca928bae69a640c3"}, + {file = "frozenlist-1.6.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e2892d9ab060a847f20fab83fdb886404d0f213f648bdeaebbe76a6134f0973d"}, + {file = "frozenlist-1.6.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbd2225d7218e7d386f4953d11484b0e38e5d134e85c91f0a6b0f30fb6ae25c4"}, + {file = "frozenlist-1.6.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b679187cba0a99f1162c7ec1b525e34bdc5ca246857544d16c1ed234562df80"}, + {file = "frozenlist-1.6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bceb7bd48849d4b76eac070a6d508aa3a529963f5d9b0a6840fd41fb381d5a09"}, + {file = "frozenlist-1.6.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b1b79ae86fdacc4bf842a4e0456540947abba64a84e61b5ae24c87adb089db"}, + {file = "frozenlist-1.6.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6c5c3c575148aa7308a38709906842039d7056bf225da6284b7a11cf9275ac5d"}, + {file = "frozenlist-1.6.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:16263bd677a31fe1a5dc2b803b564e349c96f804a81706a62b8698dd14dbba50"}, + {file = "frozenlist-1.6.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2e51b2054886ff7db71caf68285c2cd936eb7a145a509965165a2aae715c92a7"}, + {file = "frozenlist-1.6.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ae1785b76f641cce4efd7e6f49ca4ae456aa230383af5ab0d4d3922a7e37e763"}, + {file = "frozenlist-1.6.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:30155cc481f73f92f47ab1e858a7998f7b1207f9b5cf3b3cba90ec65a7f224f5"}, + {file = "frozenlist-1.6.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e1a1d82f2eb3d2875a8d139ae3f5026f7797f9de5dce44f53811ab0a883e85e7"}, + {file = "frozenlist-1.6.2-cp312-cp312-win32.whl", hash = "sha256:84105cb0f3479dfa20b85f459fb2db3b0ee52e2f84e86d447ea8b0de1fb7acdd"}, + {file = "frozenlist-1.6.2-cp312-cp312-win_amd64.whl", hash = "sha256:eecc861bd30bc5ee3b04a1e6ebf74ed0451f596d91606843f3edbd2f273e2fe3"}, + {file = "frozenlist-1.6.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2ad8851ae1f6695d735f8646bf1e68675871789756f7f7e8dc8224a74eabb9d0"}, + {file = "frozenlist-1.6.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cd2d5abc0ccd99a2a5b437987f3b1e9c265c1044d2855a09ac68f09bbb8082ca"}, + {file = "frozenlist-1.6.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15c33f665faa9b8f8e525b987eeaae6641816e0f6873e8a9c4d224338cebbb55"}, + {file = "frozenlist-1.6.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3e6c0681783723bb472b6b8304e61ecfcb4c2b11cf7f243d923813c21ae5d2a"}, + {file = "frozenlist-1.6.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:61bae4d345a26550d0ed9f2c9910ea060f89dbfc642b7b96e9510a95c3a33b3c"}, + {file = "frozenlist-1.6.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:90e5a84016d0d2fb828f770ede085b5d89155fcb9629b8a3237c960c41c120c3"}, + {file = "frozenlist-1.6.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55dc289a064c04819d669e6e8a85a1c0416e6c601782093bdc749ae14a2f39da"}, + {file = "frozenlist-1.6.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b79bcf97ca03c95b044532a4fef6e5ae106a2dd863875b75fde64c553e3f4820"}, + {file = "frozenlist-1.6.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e5e7564d232a782baa3089b25a0d979e2e4d6572d3c7231fcceacc5c22bf0f7"}, + {file = "frozenlist-1.6.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6fcd8d56880dccdd376afb18f483ab55a0e24036adc9a83c914d4b7bb5729d4e"}, + {file = "frozenlist-1.6.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4fbce985c7fe7bafb4d9bf647c835dbe415b465a897b0c79d1bdf0f3fae5fe50"}, + {file = "frozenlist-1.6.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3bd12d727cd616387d50fe283abebb2db93300c98f8ff1084b68460acd551926"}, + {file = "frozenlist-1.6.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:38544cae535ed697960891131731b33bb865b7d197ad62dc380d2dbb1bceff48"}, + {file = "frozenlist-1.6.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:47396898f98fae5c9b9bb409c3d2cf6106e409730f35a0926aad09dd7acf1ef5"}, + {file = "frozenlist-1.6.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d10d835f8ce8571fd555db42d3aef325af903535dad7e6faa7b9c8abe191bffc"}, + {file = "frozenlist-1.6.2-cp313-cp313-win32.whl", hash = "sha256:a400fe775a41b6d7a3fef00d88f10cbae4f0074c9804e282013d7797671ba58d"}, + {file = "frozenlist-1.6.2-cp313-cp313-win_amd64.whl", hash = "sha256:cc8b25b321863ed46992558a29bb09b766c41e25f31461666d501be0f893bada"}, + {file = "frozenlist-1.6.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:56de277a0e0ad26a1dcdc99802b4f5becd7fd890807b68e3ecff8ced01d58132"}, + {file = "frozenlist-1.6.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9cb386dd69ae91be586aa15cb6f39a19b5f79ffc1511371eca8ff162721c4867"}, + {file = "frozenlist-1.6.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:53835d8a6929c2f16e02616f8b727bd140ce8bf0aeddeafdb290a67c136ca8ad"}, + {file = "frozenlist-1.6.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc49f2277e8173abf028d744f8b7d69fe8cc26bffc2de97d47a3b529599fbf50"}, + {file = "frozenlist-1.6.2-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:65eb9e8a973161bdac5fa06ea6bd261057947adc4f47a7a6ef3d6db30c78c5b4"}, + {file = "frozenlist-1.6.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:301eb2f898d863031f8c5a56c88a6c5d976ba11a4a08a1438b96ee3acb5aea80"}, + {file = "frozenlist-1.6.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:207f717fd5e65fddb77d33361ab8fa939f6d89195f11307e073066886b33f2b8"}, + {file = "frozenlist-1.6.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f83992722642ee0db0333b1dbf205b1a38f97d51a7382eb304ba414d8c3d1e05"}, + {file = "frozenlist-1.6.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12af99e6023851b36578e5bcc60618b5b30f4650340e29e565cd1936326dbea7"}, + {file = "frozenlist-1.6.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6f01620444a674eaad900a3263574418e99c49e2a5d6e5330753857363b5d59f"}, + {file = "frozenlist-1.6.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:82b94c8948341512306ca8ccc702771600b442c6abe5f8ee017e00e452a209e8"}, + {file = "frozenlist-1.6.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:324a4cf4c220ddb3db1f46ade01e48432c63fa8c26812c710006e7f6cfba4a08"}, + {file = "frozenlist-1.6.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:695284e51458dabb89af7f7dc95c470aa51fd259207aba5378b187909297feef"}, + {file = "frozenlist-1.6.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:9ccbeb1c8dda4f42d0678076aa5cbde941a232be71c67b9d8ca89fbaf395807c"}, + {file = "frozenlist-1.6.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cbbdf62fcc1864912c592a1ec748fee94f294c6b23215d5e8e9569becb7723ee"}, + {file = "frozenlist-1.6.2-cp313-cp313t-win32.whl", hash = "sha256:76857098ee17258df1a61f934f2bae052b8542c9ea6b187684a737b2e3383a65"}, + {file = "frozenlist-1.6.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c06a88daba7e891add42f9278cdf7506a49bc04df9b1648be54da1bf1c79b4c6"}, + {file = "frozenlist-1.6.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99119fa5ae292ac1d3e73336ecbe3301dbb2a7f5b4e6a4594d3a6b2e240c31c1"}, + {file = "frozenlist-1.6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:af923dbcfd382554e960328133c2a8151706673d1280f55552b1bb914d276267"}, + {file = "frozenlist-1.6.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:69e85175df4cc35f2cef8cb60a8bad6c5fc50e91524cd7018d73dd2fcbc70f5d"}, + {file = "frozenlist-1.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97dcdffe18c0e35ce57b3d7c1352893a3608e7578b814abb3b2a3cc15907e682"}, + {file = "frozenlist-1.6.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:cc228faf4533327e5f1d153217ab598648a2cd5f6b1036d82e63034f079a5861"}, + {file = "frozenlist-1.6.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ee53aba5d0768e2c5c6185ec56a94bab782ef002429f293497ec5c5a3b94bdf"}, + {file = "frozenlist-1.6.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3214738024afd53434614ee52aa74353a562414cd48b1771fa82fd982cb1edb"}, + {file = "frozenlist-1.6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5628e6a6f74ef1693adbe25c0bce312eb9aee82e58abe370d287794aff632d0f"}, + {file = "frozenlist-1.6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad7678d3e32cb3884879f10c679804c08f768df55078436fb56668f3e13e2a5e"}, + {file = "frozenlist-1.6.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b776ab5217e2bf99c84b2cbccf4d30407789c0653f72d1653b5f8af60403d28f"}, + {file = "frozenlist-1.6.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:b1e162a99405cb62d338f747b8625d6bd7b6794383e193335668295fb89b75fb"}, + {file = "frozenlist-1.6.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2de1ddeb9dd8a07383f6939996217f0f1b2ce07f6a01d74c9adb1db89999d006"}, + {file = "frozenlist-1.6.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2dcabe4e7aac889d41316c1698df0eb2565ed233b66fab6bc4a5c5b7769cad4c"}, + {file = "frozenlist-1.6.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:06e28cd2ac31797e12ec8c65aa462a89116323f045e8b1930127aba9486aab24"}, + {file = "frozenlist-1.6.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:86f908b70043c3517f862247bdc621bd91420d40c3e90ede1701a75f025fcd5f"}, + {file = "frozenlist-1.6.2-cp39-cp39-win32.whl", hash = "sha256:2647a3d11f10014a5f9f2ca38c7fadd0dd28f5b1b5e9ce9c9d194aa5d0351c7e"}, + {file = "frozenlist-1.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:e2cbef30ba27a1d9f3e3c6aa84a60f53d907d955969cd0103b004056e28bca08"}, + {file = "frozenlist-1.6.2-py3-none-any.whl", hash = "sha256:947abfcc8c42a329bbda6df97a4b9c9cdb4e12c85153b3b57b9d2f02aa5877dc"}, + {file = "frozenlist-1.6.2.tar.gz", hash = "sha256:effc641518696471cf4962e8e32050133bc1f7b2851ae8fd0cb8797dd70dc202"}, +] + +[[package]] +name = "grpcio" +version = "1.75.1" +description = "HTTP/2-based RPC framework" +optional = false +python-versions = ">=3.9" +files = [ + {file = "grpcio-1.75.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:1712b5890b22547dd29f3215c5788d8fc759ce6dd0b85a6ba6e2731f2d04c088"}, + {file = "grpcio-1.75.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:8d04e101bba4b55cea9954e4aa71c24153ba6182481b487ff376da28d4ba46cf"}, + {file = "grpcio-1.75.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:683cfc70be0c1383449097cba637317e4737a357cfc185d887fd984206380403"}, + {file = "grpcio-1.75.1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:491444c081a54dcd5e6ada57314321ae526377f498d4aa09d975c3241c5b9e1c"}, + {file = "grpcio-1.75.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ce08d4e112d0d38487c2b631ec8723deac9bc404e9c7b1011426af50a79999e4"}, + {file = "grpcio-1.75.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5a2acda37fc926ccc4547977ac3e56b1df48fe200de968e8c8421f6e3093df6c"}, + {file = "grpcio-1.75.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:745c5fe6bf05df6a04bf2d11552c7d867a2690759e7ab6b05c318a772739bd75"}, + {file = "grpcio-1.75.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:259526a7159d39e2db40d566fe3e8f8e034d0fb2db5bf9c00e09aace655a4c2b"}, + {file = "grpcio-1.75.1-cp310-cp310-win32.whl", hash = "sha256:f4b29b9aabe33fed5df0a85e5f13b09ff25e2c05bd5946d25270a8bd5682dac9"}, + {file = "grpcio-1.75.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf2e760978dcce7ff7d465cbc7e276c3157eedc4c27aa6de7b594c7a295d3d61"}, + {file = "grpcio-1.75.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:573855ca2e58e35032aff30bfbd1ee103fbcf4472e4b28d4010757700918e326"}, + {file = "grpcio-1.75.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:6a4996a2c8accc37976dc142d5991adf60733e223e5c9a2219e157dc6a8fd3a2"}, + {file = "grpcio-1.75.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b1ea1bbe77ecbc1be00af2769f4ae4a88ce93be57a4f3eebd91087898ed749f9"}, + {file = "grpcio-1.75.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:e5b425aee54cc5e3e3c58f00731e8a33f5567965d478d516d35ef99fd648ab68"}, + {file = "grpcio-1.75.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0049a7bf547dafaeeb1db17079ce79596c298bfe308fc084d023c8907a845b9a"}, + {file = "grpcio-1.75.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b8ea230c7f77c0a1a3208a04a1eda164633fb0767b4cefd65a01079b65e5b1f"}, + {file = "grpcio-1.75.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:36990d629c3c9fb41e546414e5af52d0a7af37ce7113d9682c46d7e2919e4cca"}, + {file = "grpcio-1.75.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b10ad908118d38c2453ade7ff790e5bce36580c3742919007a2a78e3a1e521ca"}, + {file = "grpcio-1.75.1-cp311-cp311-win32.whl", hash = "sha256:d6be2b5ee7bea656c954dcf6aa8093c6f0e6a3ef9945c99d99fcbfc88c5c0bfe"}, + {file = "grpcio-1.75.1-cp311-cp311-win_amd64.whl", hash = "sha256:61c692fb05956b17dd6d1ab480f7f10ad0536dba3bc8fd4e3c7263dc244ed772"}, + {file = "grpcio-1.75.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:7b888b33cd14085d86176b1628ad2fcbff94cfbbe7809465097aa0132e58b018"}, + {file = "grpcio-1.75.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:8775036efe4ad2085975531d221535329f5dac99b6c2a854a995456098f99546"}, + {file = "grpcio-1.75.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb658f703468d7fbb5dcc4037c65391b7dc34f808ac46ed9136c24fc5eeb041d"}, + {file = "grpcio-1.75.1-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4b7177a1cdb3c51b02b0c0a256b0a72fdab719600a693e0e9037949efffb200b"}, + {file = "grpcio-1.75.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d4fa6ccc3ec2e68a04f7b883d354d7fea22a34c44ce535a2f0c0049cf626ddf"}, + {file = "grpcio-1.75.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3d86880ecaeb5b2f0a8afa63824de93adb8ebe4e49d0e51442532f4e08add7d6"}, + {file = "grpcio-1.75.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a8041d2f9e8a742aeae96f4b047ee44e73619f4f9d24565e84d5446c623673b6"}, + {file = "grpcio-1.75.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3652516048bf4c314ce12be37423c79829f46efffb390ad64149a10c6071e8de"}, + {file = "grpcio-1.75.1-cp312-cp312-win32.whl", hash = "sha256:44b62345d8403975513af88da2f3d5cc76f73ca538ba46596f92a127c2aea945"}, + {file = "grpcio-1.75.1-cp312-cp312-win_amd64.whl", hash = "sha256:b1e191c5c465fa777d4cafbaacf0c01e0d5278022082c0abbd2ee1d6454ed94d"}, + {file = "grpcio-1.75.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:3bed22e750d91d53d9e31e0af35a7b0b51367e974e14a4ff229db5b207647884"}, + {file = "grpcio-1.75.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:5b8f381eadcd6ecaa143a21e9e80a26424c76a0a9b3d546febe6648f3a36a5ac"}, + {file = "grpcio-1.75.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5bf4001d3293e3414d0cf99ff9b1139106e57c3a66dfff0c5f60b2a6286ec133"}, + {file = "grpcio-1.75.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:9f82ff474103e26351dacfe8d50214e7c9322960d8d07ba7fa1d05ff981c8b2d"}, + {file = "grpcio-1.75.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0ee119f4f88d9f75414217823d21d75bfe0e6ed40135b0cbbfc6376bc9f7757d"}, + {file = "grpcio-1.75.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:664eecc3abe6d916fa6cf8dd6b778e62fb264a70f3430a3180995bf2da935446"}, + {file = "grpcio-1.75.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c32193fa08b2fbebf08fe08e84f8a0aad32d87c3ad42999c65e9449871b1c66e"}, + {file = "grpcio-1.75.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5cebe13088b9254f6e615bcf1da9131d46cfa4e88039454aca9cb65f639bd3bc"}, + {file = "grpcio-1.75.1-cp313-cp313-win32.whl", hash = "sha256:4b4c678e7ed50f8ae8b8dbad15a865ee73ce12668b6aaf411bf3258b5bc3f970"}, + {file = "grpcio-1.75.1-cp313-cp313-win_amd64.whl", hash = "sha256:5573f51e3f296a1bcf71e7a690c092845fb223072120f4bdb7a5b48e111def66"}, + {file = "grpcio-1.75.1-cp314-cp314-linux_armv7l.whl", hash = "sha256:c05da79068dd96723793bffc8d0e64c45f316248417515f28d22204d9dae51c7"}, + {file = "grpcio-1.75.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:06373a94fd16ec287116a825161dca179a0402d0c60674ceeec8c9fba344fe66"}, + {file = "grpcio-1.75.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4484f4b7287bdaa7a5b3980f3c7224c3c622669405d20f69549f5fb956ad0421"}, + {file = "grpcio-1.75.1-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:2720c239c1180eee69f7883c1d4c83fc1a495a2535b5fa322887c70bf02b16e8"}, + {file = "grpcio-1.75.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:07a554fa31c668cf0e7a188678ceeca3cb8fead29bbe455352e712ec33ca701c"}, + {file = "grpcio-1.75.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:3e71a2105210366bfc398eef7f57a664df99194f3520edb88b9c3a7e46ee0d64"}, + {file = "grpcio-1.75.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8679aa8a5b67976776d3c6b0521e99d1c34db8a312a12bcfd78a7085cb9b604e"}, + {file = "grpcio-1.75.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:aad1c774f4ebf0696a7f148a56d39a3432550612597331792528895258966dc0"}, + {file = "grpcio-1.75.1-cp314-cp314-win32.whl", hash = "sha256:62ce42d9994446b307649cb2a23335fa8e927f7ab2cbf5fcb844d6acb4d85f9c"}, + {file = "grpcio-1.75.1-cp314-cp314-win_amd64.whl", hash = "sha256:f86e92275710bea3000cb79feca1762dc0ad3b27830dd1a74e82ab321d4ee464"}, + {file = "grpcio-1.75.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:c09fba33327c3ac11b5c33dbdd8218eef8990d78f83b1656d628831812a8c0fb"}, + {file = "grpcio-1.75.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:7e21400b037be29545704889e72e586c238e346dcb2d08d8a7288d16c883a9ec"}, + {file = "grpcio-1.75.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c12121e509b9f8b0914d10054d24120237d19e870b1cd82acbb8a9b9ddd198a3"}, + {file = "grpcio-1.75.1-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:73577a93e692b3474b1bfe84285d098de36705dbd838bb4d6a056d326e4dc880"}, + {file = "grpcio-1.75.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e19e7dfa0d7ca7dea22be464339e18ac608fd75d88c56770c646cdabe54bc724"}, + {file = "grpcio-1.75.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4e1c28f51c1cf67eccdfc1065e8e866c9ed622f09773ca60947089c117f848a1"}, + {file = "grpcio-1.75.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:030a6164bc2ca726052778c0cf8e3249617a34e368354f9e6107c27ad4af8c28"}, + {file = "grpcio-1.75.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:67697efef5a98d46d5db7b1720fa4043536f8b8e5072a5d61cfca762f287e939"}, + {file = "grpcio-1.75.1-cp39-cp39-win32.whl", hash = "sha256:52015cf73eb5d76f6404e0ce0505a69b51fd1f35810b3a01233b34b10baafb41"}, + {file = "grpcio-1.75.1-cp39-cp39-win_amd64.whl", hash = "sha256:9fe51e4a1f896ea84ac750900eae34d9e9b896b5b1e4a30b02dc31ad29f36383"}, + {file = "grpcio-1.75.1.tar.gz", hash = "sha256:3e81d89ece99b9ace23a6916880baca613c03a799925afb2857887efa8b1b3d2"}, +] + +[package.dependencies] +typing-extensions = ">=4.12,<5.0" + +[package.extras] +protobuf = ["grpcio-tools (>=1.75.1)"] + +[[package]] +name = "hexbytes" +version = "1.3.1" +description = "hexbytes: Python `bytes` subclass that decodes hex, with a readable console output" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "hexbytes-1.3.1-py3-none-any.whl", hash = "sha256:da01ff24a1a9a2b1881c4b85f0e9f9b0f51b526b379ffa23832ae7899d29c2c7"}, + {file = "hexbytes-1.3.1.tar.gz", hash = "sha256:a657eebebdfe27254336f98d8af6e2236f3f83aed164b87466b6cf6c5f5a4765"}, +] + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "eth_utils (>=2.0.0)", "hypothesis (>=3.44.24)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["eth_utils (>=2.0.0)", "hypothesis (>=3.44.24)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + +[[package]] +name = "idna" +version = "3.10" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "isort" +version = "6.0.1" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.9.0" +files = [ + {file = "isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615"}, + {file = "isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450"}, +] + +[package.extras] +colors = ["colorama"] +plugins = ["setuptools"] + +[[package]] +name = "jsonmerge" +version = "1.9.2" +description = "Merge a series of JSON documents." +optional = false +python-versions = "*" +files = [ + {file = "jsonmerge-1.9.2-py3-none-any.whl", hash = "sha256:cab93ee7763fb51a4a09bbdab2eacf499ffb208ab94247ae86acea3e0e823b05"}, + {file = "jsonmerge-1.9.2.tar.gz", hash = "sha256:c43757e0180b0e19b7ae4c130ad42a07cc580c31912f61f4823e8eaf2fa394a3"}, +] + +[package.dependencies] +jsonschema = ">2.4.0" + +[[package]] +name = "jsonnet" +version = "0.20.0" +description = "Python bindings for Jsonnet - The data templating language" +optional = false +python-versions = "*" +files = [ + {file = "jsonnet-0.20.0.tar.gz", hash = "sha256:7e770c7bf3a366b97b650a39430450f77612e74406731eb75c5bd59f3f104d4f"}, +] + +[[package]] +name = "jsonschema" +version = "4.23.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, + {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] + +[[package]] +name = "jsonschema-specifications" +version = "2024.10.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.9" +files = [ + {file = "jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf"}, + {file = "jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "multidict" +version = "6.4.4" +description = "multidict implementation" +optional = false +python-versions = ">=3.9" +files = [ + {file = "multidict-6.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8adee3ac041145ffe4488ea73fa0a622b464cc25340d98be76924d0cda8545ff"}, + {file = "multidict-6.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b61e98c3e2a861035aaccd207da585bdcacef65fe01d7a0d07478efac005e028"}, + {file = "multidict-6.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:75493f28dbadecdbb59130e74fe935288813301a8554dc32f0c631b6bdcdf8b0"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc3c6a37e048b5395ee235e4a2a0d639c2349dffa32d9367a42fc20d399772"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:87cb72263946b301570b0f63855569a24ee8758aaae2cd182aae7d95fbc92ca7"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bbf7bd39822fd07e3609b6b4467af4c404dd2b88ee314837ad1830a7f4a8299"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1f7cbd4f1f44ddf5fd86a8675b7679176eae770f2fc88115d6dddb6cefb59bc"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb5ac9e5bfce0e6282e7f59ff7b7b9a74aa8e5c60d38186a4637f5aa764046ad"}, + {file = "multidict-6.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4efc31dfef8c4eeb95b6b17d799eedad88c4902daba39ce637e23a17ea078915"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9fcad2945b1b91c29ef2b4050f590bfcb68d8ac8e0995a74e659aa57e8d78e01"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:d877447e7368c7320832acb7159557e49b21ea10ffeb135c1077dbbc0816b598"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:33a12ebac9f380714c298cbfd3e5b9c0c4e89c75fe612ae496512ee51028915f"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0f14ea68d29b43a9bf37953881b1e3eb75b2739e896ba4a6aa4ad4c5b9ffa145"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0327ad2c747a6600e4797d115d3c38a220fdb28e54983abe8964fd17e95ae83c"}, + {file = "multidict-6.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d1a20707492db9719a05fc62ee215fd2c29b22b47c1b1ba347f9abc831e26683"}, + {file = "multidict-6.4.4-cp310-cp310-win32.whl", hash = "sha256:d83f18315b9fca5db2452d1881ef20f79593c4aa824095b62cb280019ef7aa3d"}, + {file = "multidict-6.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:9c17341ee04545fd962ae07330cb5a39977294c883485c8d74634669b1f7fe04"}, + {file = "multidict-6.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4f5f29794ac0e73d2a06ac03fd18870adc0135a9d384f4a306a951188ed02f95"}, + {file = "multidict-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c04157266344158ebd57b7120d9b0b35812285d26d0e78193e17ef57bfe2979a"}, + {file = "multidict-6.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bb61ffd3ab8310d93427e460f565322c44ef12769f51f77277b4abad7b6f7223"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e0ba18a9afd495f17c351d08ebbc4284e9c9f7971d715f196b79636a4d0de44"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9faf1b1dcaadf9f900d23a0e6d6c8eadd6a95795a0e57fcca73acce0eb912065"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a4d1cb1327c6082c4fce4e2a438483390964c02213bc6b8d782cf782c9b1471f"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:941f1bec2f5dbd51feeb40aea654c2747f811ab01bdd3422a48a4e4576b7d76a"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5f8a146184da7ea12910a4cec51ef85e44f6268467fb489c3caf0cd512f29c2"}, + {file = "multidict-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:232b7237e57ec3c09be97206bfb83a0aa1c5d7d377faa019c68a210fa35831f1"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:55ae0721c1513e5e3210bca4fc98456b980b0c2c016679d3d723119b6b202c42"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:51d662c072579f63137919d7bb8fc250655ce79f00c82ecf11cab678f335062e"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0e05c39962baa0bb19a6b210e9b1422c35c093b651d64246b6c2e1a7e242d9fd"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5b1cc3ab8c31d9ebf0faa6e3540fb91257590da330ffe6d2393d4208e638925"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:93ec84488a384cd7b8a29c2c7f467137d8a73f6fe38bb810ecf29d1ade011a7c"}, + {file = "multidict-6.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b308402608493638763abc95f9dc0030bbd6ac6aff784512e8ac3da73a88af08"}, + {file = "multidict-6.4.4-cp311-cp311-win32.whl", hash = "sha256:343892a27d1a04d6ae455ecece12904d242d299ada01633d94c4f431d68a8c49"}, + {file = "multidict-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:73484a94f55359780c0f458bbd3c39cb9cf9c182552177d2136e828269dee529"}, + {file = "multidict-6.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dc388f75a1c00000824bf28b7633e40854f4127ede80512b44c3cfeeea1839a2"}, + {file = "multidict-6.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:98af87593a666f739d9dba5d0ae86e01b0e1a9cfcd2e30d2d361fbbbd1a9162d"}, + {file = "multidict-6.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aff4cafea2d120327d55eadd6b7f1136a8e5a0ecf6fb3b6863e8aca32cd8e50a"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:169c4ba7858176b797fe551d6e99040c531c775d2d57b31bcf4de6d7a669847f"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b9eb4c59c54421a32b3273d4239865cb14ead53a606db066d7130ac80cc8ec93"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7cf3bd54c56aa16fdb40028d545eaa8d051402b61533c21e84046e05513d5780"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f682c42003c7264134bfe886376299db4cc0c6cd06a3295b41b347044bcb5482"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920f9cf2abdf6e493c519492d892c362007f113c94da4c239ae88429835bad1"}, + {file = "multidict-6.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:530d86827a2df6504526106b4c104ba19044594f8722d3e87714e847c74a0275"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ecde56ea2439b96ed8a8d826b50c57364612ddac0438c39e473fafad7ae1c23b"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:dc8c9736d8574b560634775ac0def6bdc1661fc63fa27ffdfc7264c565bcb4f2"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7f3d3b3c34867579ea47cbd6c1f2ce23fbfd20a273b6f9e3177e256584f1eacc"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:87a728af265e08f96b6318ebe3c0f68b9335131f461efab2fc64cc84a44aa6ed"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9f193eeda1857f8e8d3079a4abd258f42ef4a4bc87388452ed1e1c4d2b0c8740"}, + {file = "multidict-6.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be06e73c06415199200e9a2324a11252a3d62030319919cde5e6950ffeccf72e"}, + {file = "multidict-6.4.4-cp312-cp312-win32.whl", hash = "sha256:622f26ea6a7e19b7c48dd9228071f571b2fbbd57a8cd71c061e848f281550e6b"}, + {file = "multidict-6.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:5e2bcda30d5009996ff439e02a9f2b5c3d64a20151d34898c000a6281faa3781"}, + {file = "multidict-6.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:82ffabefc8d84c2742ad19c37f02cde5ec2a1ee172d19944d380f920a340e4b9"}, + {file = "multidict-6.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6a2f58a66fe2c22615ad26156354005391e26a2f3721c3621504cd87c1ea87bf"}, + {file = "multidict-6.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5883d6ee0fd9d8a48e9174df47540b7545909841ac82354c7ae4cbe9952603bd"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9abcf56a9511653fa1d052bfc55fbe53dbee8f34e68bd6a5a038731b0ca42d15"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6ed5ae5605d4ad5a049fad2a28bb7193400700ce2f4ae484ab702d1e3749c3f9"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbfcb60396f9bcfa63e017a180c3105b8c123a63e9d1428a36544e7d37ca9e20"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0f1987787f5f1e2076b59692352ab29a955b09ccc433c1f6b8e8e18666f608b"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d0121ccce8c812047d8d43d691a1ad7641f72c4f730474878a5aeae1b8ead8c"}, + {file = "multidict-6.4.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83ec4967114295b8afd120a8eec579920c882831a3e4c3331d591a8e5bfbbc0f"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:995f985e2e268deaf17867801b859a282e0448633f1310e3704b30616d269d69"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d832c608f94b9f92a0ec8b7e949be7792a642b6e535fcf32f3e28fab69eeb046"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d21c1212171cf7da703c5b0b7a0e85be23b720818aef502ad187d627316d5645"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:cbebaa076aaecad3d4bb4c008ecc73b09274c952cf6a1b78ccfd689e51f5a5b0"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:c93a6fb06cc8e5d3628b2b5fda215a5db01e8f08fc15fadd65662d9b857acbe4"}, + {file = "multidict-6.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8cd8f81f1310182362fb0c7898145ea9c9b08a71081c5963b40ee3e3cac589b1"}, + {file = "multidict-6.4.4-cp313-cp313-win32.whl", hash = "sha256:3e9f1cd61a0ab857154205fb0b1f3d3ace88d27ebd1409ab7af5096e409614cd"}, + {file = "multidict-6.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:8ffb40b74400e4455785c2fa37eba434269149ec525fc8329858c862e4b35373"}, + {file = "multidict-6.4.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:6a602151dbf177be2450ef38966f4be3467d41a86c6a845070d12e17c858a156"}, + {file = "multidict-6.4.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0d2b9712211b860d123815a80b859075d86a4d54787e247d7fbee9db6832cf1c"}, + {file = "multidict-6.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d2fa86af59f8fc1972e121ade052145f6da22758f6996a197d69bb52f8204e7e"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50855d03e9e4d66eab6947ba688ffb714616f985838077bc4b490e769e48da51"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5bce06b83be23225be1905dcdb6b789064fae92499fbc458f59a8c0e68718601"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66ed0731f8e5dfd8369a883b6e564aca085fb9289aacabd9decd70568b9a30de"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:329ae97fc2f56f44d91bc47fe0972b1f52d21c4b7a2ac97040da02577e2daca2"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c27e5dcf520923d6474d98b96749e6805f7677e93aaaf62656005b8643f907ab"}, + {file = "multidict-6.4.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:058cc59b9e9b143cc56715e59e22941a5d868c322242278d28123a5d09cdf6b0"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:69133376bc9a03f8c47343d33f91f74a99c339e8b58cea90433d8e24bb298031"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:d6b15c55721b1b115c5ba178c77104123745b1417527ad9641a4c5e2047450f0"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:a887b77f51d3d41e6e1a63cf3bc7ddf24de5939d9ff69441387dfefa58ac2e26"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:632a3bf8f1787f7ef7d3c2f68a7bde5be2f702906f8b5842ad6da9d974d0aab3"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:a145c550900deb7540973c5cdb183b0d24bed6b80bf7bddf33ed8f569082535e"}, + {file = "multidict-6.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc5d83c6619ca5c9672cb78b39ed8542f1975a803dee2cda114ff73cbb076edd"}, + {file = "multidict-6.4.4-cp313-cp313t-win32.whl", hash = "sha256:3312f63261b9df49be9d57aaa6abf53a6ad96d93b24f9cc16cf979956355ce6e"}, + {file = "multidict-6.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:ba852168d814b2c73333073e1c7116d9395bea69575a01b0b3c89d2d5a87c8fb"}, + {file = "multidict-6.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:603f39bd1cf85705c6c1ba59644b480dfe495e6ee2b877908de93322705ad7cf"}, + {file = "multidict-6.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc60f91c02e11dfbe3ff4e1219c085695c339af72d1641800fe6075b91850c8f"}, + {file = "multidict-6.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:496bcf01c76a70a31c3d746fd39383aad8d685ce6331e4c709e9af4ced5fa221"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4219390fb5bf8e548e77b428bb36a21d9382960db5321b74d9d9987148074d6b"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef4e9096ff86dfdcbd4a78253090ba13b1d183daa11b973e842465d94ae1772"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49a29d7133b1fc214e818bbe025a77cc6025ed9a4f407d2850373ddde07fd04a"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e32053d6d3a8b0dfe49fde05b496731a0e6099a4df92154641c00aa76786aef5"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc403092a49509e8ef2d2fd636a8ecefc4698cc57bbe894606b14579bc2a955"}, + {file = "multidict-6.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5363f9b2a7f3910e5c87d8b1855c478c05a2dc559ac57308117424dfaad6805c"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e543a40e4946cf70a88a3be87837a3ae0aebd9058ba49e91cacb0b2cd631e2b"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:60d849912350da557fe7de20aa8cf394aada6980d0052cc829eeda4a0db1c1db"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:19d08b4f22eae45bb018b9f06e2838c1e4b853c67628ef8ae126d99de0da6395"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d693307856d1ef08041e8b6ff01d5b4618715007d288490ce2c7e29013c12b9a"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fad6daaed41021934917f4fb03ca2db8d8a4d79bf89b17ebe77228eb6710c003"}, + {file = "multidict-6.4.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c10d17371bff801af0daf8b073c30b6cf14215784dc08cd5c43ab5b7b8029bbc"}, + {file = "multidict-6.4.4-cp39-cp39-win32.whl", hash = "sha256:7e23f2f841fcb3ebd4724a40032d32e0892fbba4143e43d2a9e7695c5e50e6bd"}, + {file = "multidict-6.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:4d7b50b673ffb4ff4366e7ab43cf1f0aef4bd3608735c5fbdf0bdb6f690da411"}, + {file = "multidict-6.4.4-py3-none-any.whl", hash = "sha256:bd4557071b561a8b3b6075c3ce93cf9bfb6182cb241805c3d66ced3b75eff4ac"}, + {file = "multidict-6.4.4.tar.gz", hash = "sha256:69ee9e6ba214b5245031b76233dd95408a0fd57fdb019ddcc1ead4790932a8e8"}, +] + +[[package]] +name = "multitail2" +version = "1.5.2" +description = "Enables following multiple files for new lines at once, automatically handling file creation/deletion/rotation" +optional = false +python-versions = "*" +files = [ + {file = "multitail2-1.5.2.tar.gz", hash = "sha256:7086598c1cd1901ec79ce3c1eda9420299e3778f6c18464958c1f74ffd1950c9"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "packaging" +version = "24.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, +] + +[[package]] +name = "parsimonious" +version = "0.10.0" +description = "(Soon to be) the fastest pure-Python PEG parser I could muster" +optional = false +python-versions = "*" +files = [ + {file = "parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f"}, + {file = "parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c"}, +] + +[package.dependencies] +regex = ">=2022.3.15" + +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + +[[package]] +name = "platformdirs" +version = "4.3.6" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "propcache" +version = "0.3.1" +description = "Accelerated property cache" +optional = false +python-versions = ">=3.9" +files = [ + {file = "propcache-0.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f27785888d2fdd918bc36de8b8739f2d6c791399552333721b58193f68ea3e98"}, + {file = "propcache-0.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4e89cde74154c7b5957f87a355bb9c8ec929c167b59c83d90654ea36aeb6180"}, + {file = "propcache-0.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:730178f476ef03d3d4d255f0c9fa186cb1d13fd33ffe89d39f2cda4da90ceb71"}, + {file = "propcache-0.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:967a8eec513dbe08330f10137eacb427b2ca52118769e82ebcfcab0fba92a649"}, + {file = "propcache-0.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b9145c35cc87313b5fd480144f8078716007656093d23059e8993d3a8fa730f"}, + {file = "propcache-0.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e64e948ab41411958670f1093c0a57acfdc3bee5cf5b935671bbd5313bcf229"}, + {file = "propcache-0.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:319fa8765bfd6a265e5fa661547556da381e53274bc05094fc9ea50da51bfd46"}, + {file = "propcache-0.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c66d8ccbc902ad548312b96ed8d5d266d0d2c6d006fd0f66323e9d8f2dd49be7"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2d219b0dbabe75e15e581fc1ae796109b07c8ba7d25b9ae8d650da582bed01b0"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:cd6a55f65241c551eb53f8cf4d2f4af33512c39da5d9777694e9d9c60872f519"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9979643ffc69b799d50d3a7b72b5164a2e97e117009d7af6dfdd2ab906cb72cd"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4cf9e93a81979f1424f1a3d155213dc928f1069d697e4353edb8a5eba67c6259"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2fce1df66915909ff6c824bbb5eb403d2d15f98f1518e583074671a30fe0c21e"}, + {file = "propcache-0.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4d0dfdd9a2ebc77b869a0b04423591ea8823f791293b527dc1bb896c1d6f1136"}, + {file = "propcache-0.3.1-cp310-cp310-win32.whl", hash = "sha256:1f6cc0ad7b4560e5637eb2c994e97b4fa41ba8226069c9277eb5ea7101845b42"}, + {file = "propcache-0.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:47ef24aa6511e388e9894ec16f0fbf3313a53ee68402bc428744a367ec55b833"}, + {file = "propcache-0.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5"}, + {file = "propcache-0.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371"}, + {file = "propcache-0.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da"}, + {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744"}, + {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0"}, + {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5"}, + {file = "propcache-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256"}, + {file = "propcache-0.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a"}, + {file = "propcache-0.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9"}, + {file = "propcache-0.3.1-cp311-cp311-win32.whl", hash = "sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005"}, + {file = "propcache-0.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7"}, + {file = "propcache-0.3.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f78eb8422acc93d7b69964012ad7048764bb45a54ba7a39bb9e146c72ea29723"}, + {file = "propcache-0.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:89498dd49c2f9a026ee057965cdf8192e5ae070ce7d7a7bd4b66a8e257d0c976"}, + {file = "propcache-0.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09400e98545c998d57d10035ff623266927cb784d13dd2b31fd33b8a5316b85b"}, + {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa8efd8c5adc5a2c9d3b952815ff8f7710cefdcaf5f2c36d26aff51aeca2f12f"}, + {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2fe5c910f6007e716a06d269608d307b4f36e7babee5f36533722660e8c4a70"}, + {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a0ab8cf8cdd2194f8ff979a43ab43049b1df0b37aa64ab7eca04ac14429baeb7"}, + {file = "propcache-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:563f9d8c03ad645597b8d010ef4e9eab359faeb11a0a2ac9f7b4bc8c28ebef25"}, + {file = "propcache-0.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb6e0faf8cb6b4beea5d6ed7b5a578254c6d7df54c36ccd3d8b3eb00d6770277"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1c5c7ab7f2bb3f573d1cb921993006ba2d39e8621019dffb1c5bc94cdbae81e8"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:050b571b2e96ec942898f8eb46ea4bfbb19bd5502424747e83badc2d4a99a44e"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e1c4d24b804b3a87e9350f79e2371a705a188d292fd310e663483af6ee6718ee"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e4fe2a6d5ce975c117a6bb1e8ccda772d1e7029c1cca1acd209f91d30fa72815"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:feccd282de1f6322f56f6845bf1207a537227812f0a9bf5571df52bb418d79d5"}, + {file = "propcache-0.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ec314cde7314d2dd0510c6787326bbffcbdc317ecee6b7401ce218b3099075a7"}, + {file = "propcache-0.3.1-cp312-cp312-win32.whl", hash = "sha256:7d2d5a0028d920738372630870e7d9644ce437142197f8c827194fca404bf03b"}, + {file = "propcache-0.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:88c423efef9d7a59dae0614eaed718449c09a5ac79a5f224a8b9664d603f04a3"}, + {file = "propcache-0.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f1528ec4374617a7a753f90f20e2f551121bb558fcb35926f99e3c42367164b8"}, + {file = "propcache-0.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc1915ec523b3b494933b5424980831b636fe483d7d543f7afb7b3bf00f0c10f"}, + {file = "propcache-0.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a110205022d077da24e60b3df8bcee73971be9575dec5573dd17ae5d81751111"}, + {file = "propcache-0.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d249609e547c04d190e820d0d4c8ca03ed4582bcf8e4e160a6969ddfb57b62e5"}, + {file = "propcache-0.3.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ced33d827625d0a589e831126ccb4f5c29dfdf6766cac441d23995a65825dcb"}, + {file = "propcache-0.3.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4114c4ada8f3181af20808bedb250da6bae56660e4b8dfd9cd95d4549c0962f7"}, + {file = "propcache-0.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:975af16f406ce48f1333ec5e912fe11064605d5c5b3f6746969077cc3adeb120"}, + {file = "propcache-0.3.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a34aa3a1abc50740be6ac0ab9d594e274f59960d3ad253cd318af76b996dd654"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9cec3239c85ed15bfaded997773fdad9fb5662b0a7cbc854a43f291eb183179e"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:05543250deac8e61084234d5fc54f8ebd254e8f2b39a16b1dce48904f45b744b"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5cb5918253912e088edbf023788de539219718d3b10aef334476b62d2b53de53"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f3bbecd2f34d0e6d3c543fdb3b15d6b60dd69970c2b4c822379e5ec8f6f621d5"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aca63103895c7d960a5b9b044a83f544b233c95e0dcff114389d64d762017af7"}, + {file = "propcache-0.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a0a9898fdb99bf11786265468571e628ba60af80dc3f6eb89a3545540c6b0ef"}, + {file = "propcache-0.3.1-cp313-cp313-win32.whl", hash = "sha256:3a02a28095b5e63128bcae98eb59025924f121f048a62393db682f049bf4ac24"}, + {file = "propcache-0.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:813fbb8b6aea2fc9659815e585e548fe706d6f663fa73dff59a1677d4595a037"}, + {file = "propcache-0.3.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a444192f20f5ce8a5e52761a031b90f5ea6288b1eef42ad4c7e64fef33540b8f"}, + {file = "propcache-0.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0fbe94666e62ebe36cd652f5fc012abfbc2342de99b523f8267a678e4dfdee3c"}, + {file = "propcache-0.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f011f104db880f4e2166bcdcf7f58250f7a465bc6b068dc84c824a3d4a5c94dc"}, + {file = "propcache-0.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e584b6d388aeb0001d6d5c2bd86b26304adde6d9bb9bfa9c4889805021b96de"}, + {file = "propcache-0.3.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a17583515a04358b034e241f952f1715243482fc2c2945fd99a1b03a0bd77d6"}, + {file = "propcache-0.3.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5aed8d8308215089c0734a2af4f2e95eeb360660184ad3912686c181e500b2e7"}, + {file = "propcache-0.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d8e309ff9a0503ef70dc9a0ebd3e69cf7b3894c9ae2ae81fc10943c37762458"}, + {file = "propcache-0.3.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b655032b202028a582d27aeedc2e813299f82cb232f969f87a4fde491a233f11"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f64d91b751df77931336b5ff7bafbe8845c5770b06630e27acd5dbb71e1931c"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:19a06db789a4bd896ee91ebc50d059e23b3639c25d58eb35be3ca1cbe967c3bf"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:bef100c88d8692864651b5f98e871fb090bd65c8a41a1cb0ff2322db39c96c27"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:87380fb1f3089d2a0b8b00f006ed12bd41bd858fabfa7330c954c70f50ed8757"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e474fc718e73ba5ec5180358aa07f6aded0ff5f2abe700e3115c37d75c947e18"}, + {file = "propcache-0.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:17d1c688a443355234f3c031349da69444be052613483f3e4158eef751abcd8a"}, + {file = "propcache-0.3.1-cp313-cp313t-win32.whl", hash = "sha256:359e81a949a7619802eb601d66d37072b79b79c2505e6d3fd8b945538411400d"}, + {file = "propcache-0.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e7fb9a84c9abbf2b2683fa3e7b0d7da4d8ecf139a1c635732a8bda29c5214b0e"}, + {file = "propcache-0.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ed5f6d2edbf349bd8d630e81f474d33d6ae5d07760c44d33cd808e2f5c8f4ae6"}, + {file = "propcache-0.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:668ddddc9f3075af019f784456267eb504cb77c2c4bd46cc8402d723b4d200bf"}, + {file = "propcache-0.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0c86e7ceea56376216eba345aa1fc6a8a6b27ac236181f840d1d7e6a1ea9ba5c"}, + {file = "propcache-0.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83be47aa4e35b87c106fc0c84c0fc069d3f9b9b06d3c494cd404ec6747544894"}, + {file = "propcache-0.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:27c6ac6aa9fc7bc662f594ef380707494cb42c22786a558d95fcdedb9aa5d035"}, + {file = "propcache-0.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64a956dff37080b352c1c40b2966b09defb014347043e740d420ca1eb7c9b908"}, + {file = "propcache-0.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82de5da8c8893056603ac2d6a89eb8b4df49abf1a7c19d536984c8dd63f481d5"}, + {file = "propcache-0.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c3c3a203c375b08fd06a20da3cf7aac293b834b6f4f4db71190e8422750cca5"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b303b194c2e6f171cfddf8b8ba30baefccf03d36a4d9cab7fd0bb68ba476a3d7"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:916cd229b0150129d645ec51614d38129ee74c03293a9f3f17537be0029a9641"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a461959ead5b38e2581998700b26346b78cd98540b5524796c175722f18b0294"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:069e7212890b0bcf9b2be0a03afb0c2d5161d91e1bf51569a64f629acc7defbf"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ef2e4e91fb3945769e14ce82ed53007195e616a63aa43b40fb7ebaaf907c8d4c"}, + {file = "propcache-0.3.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8638f99dca15b9dff328fb6273e09f03d1c50d9b6512f3b65a4154588a7595fe"}, + {file = "propcache-0.3.1-cp39-cp39-win32.whl", hash = "sha256:6f173bbfe976105aaa890b712d1759de339d8a7cef2fc0a1714cc1a1e1c47f64"}, + {file = "propcache-0.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:603f1fe4144420374f1a69b907494c3acbc867a581c2d49d4175b0de7cc64566"}, + {file = "propcache-0.3.1-py3-none-any.whl", hash = "sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40"}, + {file = "propcache-0.3.1.tar.gz", hash = "sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf"}, +] + +[[package]] +name = "py-ecc" +version = "8.0.0" +description = "py-ecc: Elliptic curve crypto in python including secp256k1, alt_bn128, and bls12_381" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "py_ecc-8.0.0-py3-none-any.whl", hash = "sha256:c0b2dfc4bde67a55122a392591a10e851a986d5128f680628c80b405f7663e13"}, + {file = "py_ecc-8.0.0.tar.gz", hash = "sha256:56aca19e5dc37294f60c1cc76666c03c2276e7666412b9a559fa0145d099933d"}, +] + +[package.dependencies] +eth-typing = ">=3.0.0" +eth-utils = ">=2.0.0" + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + +[[package]] +name = "pycodestyle" +version = "2.12.1" +description = "Python style guide checker" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycodestyle-2.12.1-py2.py3-none-any.whl", hash = "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3"}, + {file = "pycodestyle-2.12.1.tar.gz", hash = "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521"}, +] + +[[package]] +name = "pycryptodome" +version = "3.23.0" +description = "Cryptographic library for Python" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "pycryptodome-3.23.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a176b79c49af27d7f6c12e4b178b0824626f40a7b9fed08f712291b6d54bf566"}, + {file = "pycryptodome-3.23.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:573a0b3017e06f2cffd27d92ef22e46aa3be87a2d317a5abf7cc0e84e321bd75"}, + {file = "pycryptodome-3.23.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:63dad881b99ca653302b2c7191998dd677226222a3f2ea79999aa51ce695f720"}, + {file = "pycryptodome-3.23.0-cp27-cp27m-win32.whl", hash = "sha256:b34e8e11d97889df57166eda1e1ddd7676da5fcd4d71a0062a760e75060514b4"}, + {file = "pycryptodome-3.23.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:7ac1080a8da569bde76c0a104589c4f414b8ba296c0b3738cf39a466a9fb1818"}, + {file = "pycryptodome-3.23.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6fe8258e2039eceb74dfec66b3672552b6b7d2c235b2dfecc05d16b8921649a8"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625"}, + {file = "pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39"}, + {file = "pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27"}, + {file = "pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843"}, + {file = "pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490"}, + {file = "pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575"}, + {file = "pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b"}, + {file = "pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a"}, + {file = "pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f"}, + {file = "pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa"}, + {file = "pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886"}, + {file = "pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2"}, + {file = "pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c"}, + {file = "pycryptodome-3.23.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:350ebc1eba1da729b35ab7627a833a1a355ee4e852d8ba0447fafe7b14504d56"}, + {file = "pycryptodome-3.23.0-pp27-pypy_73-win32.whl", hash = "sha256:93837e379a3e5fd2bb00302a47aee9fdf7940d83595be3915752c74033d17ca7"}, + {file = "pycryptodome-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddb95b49df036ddd264a0ad246d1be5b672000f12d6961ea2c267083a5e19379"}, + {file = "pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e95564beb8782abfd9e431c974e14563a794a4944c29d6d3b7b5ea042110b4"}, + {file = "pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e15c081e912c4b0d75632acd8382dfce45b258667aa3c67caf7a4d4c13f630"}, + {file = "pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7fc76bf273353dc7e5207d172b83f569540fc9a28d63171061c42e361d22353"}, + {file = "pycryptodome-3.23.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:45c69ad715ca1a94f778215a11e66b7ff989d792a4d63b68dc586a1da1392ff5"}, + {file = "pycryptodome-3.23.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:865d83c906b0fc6a59b510deceee656b6bc1c4fa0d82176e2b77e97a420a996a"}, + {file = "pycryptodome-3.23.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89d4d56153efc4d81defe8b65fd0821ef8b2d5ddf8ed19df31ba2f00872b8002"}, + {file = "pycryptodome-3.23.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3f2d0aaf8080bda0587d58fc9fe4766e012441e2eed4269a77de6aea981c8be"}, + {file = "pycryptodome-3.23.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64093fc334c1eccfd3933c134c4457c34eaca235eeae49d69449dc4728079339"}, + {file = "pycryptodome-3.23.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ce64e84a962b63a47a592690bdc16a7eaf709d2c2697ababf24a0def566899a6"}, + {file = "pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef"}, +] + +[[package]] +name = "pydantic" +version = "2.11.7" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b"}, + {file = "pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db"}, +] + +[package.dependencies] +annotated-types = ">=0.6.0" +pydantic-core = "2.33.2" +typing-extensions = ">=4.12.2" +typing-inspection = ">=0.4.0" + +[package.extras] +email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata"] + +[[package]] +name = "pydantic-core" +version = "2.33.2" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, + {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, + {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, + {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, + {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, + {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, + {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, + {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, + {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, + {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, + {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, + {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, + {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pyflakes" +version = "3.2.0" +description = "passive checker of Python programs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"}, + {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, +] + +[[package]] +name = "pystarport" +version = "0.2.5" +description = "Spawn local devnets for cosmos-sdk chains" +optional = false +python-versions = "^3.9" +files = [] +develop = false + +[package.dependencies] +bech32 = "^1.1" +docker = "^7.0" +durations = "^0" +fire = "^0" +grpcio = "^1.75.1" +jsonmerge = "^1.7" +jsonnet = "^0" +multitail2 = "^1.5" +python-dateutil = "^2.8" +python-dotenv = "^1.0" +pyyaml = "^6.0" +pyyaml-include = "^1.3" +supervisor = "^4.2" +tomlkit = "^0" + +[package.source] +type = "git" +url = "https://github.com/MANTRA-Chain/pystarport.git" +reference = "ref_cmd" +resolved_reference = "e3fecb361b4a6c5a8ab41fc89b8df10705b8df2c" + +[[package]] +name = "pytest" +version = "8.3.5" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, + {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.5,<2" + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-asyncio" +version = "0.25.3" +description = "Pytest support for asyncio" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3"}, + {file = "pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a"}, +] + +[package.dependencies] +pytest = ">=8.2,<9" + +[package.extras] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] + +[[package]] +name = "pytest-github-actions-annotate-failures" +version = "0.3.0" +description = "pytest plugin to annotate failed tests with a workflow command for GitHub Actions" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_github_actions_annotate_failures-0.3.0-py3-none-any.whl", hash = "sha256:41ea558ba10c332c0bfc053daeee0c85187507b2034e990f21e4f7e5fef044cf"}, + {file = "pytest_github_actions_annotate_failures-0.3.0.tar.gz", hash = "sha256:d4c3177c98046c3900a7f8ddebb22ea54b9f6822201b5d3ab8fcdea51e010db7"}, +] + +[package.dependencies] +pytest = ">=6.0.0" + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "pyunormalize" +version = "16.0.0" +description = "Unicode normalization forms (NFC, NFKC, NFD, NFKD). A library independent of the Python core Unicode database." +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyunormalize-16.0.0-py3-none-any.whl", hash = "sha256:c647d95e5d1e2ea9a2f448d1d95d8518348df24eab5c3fd32d2b5c3300a49152"}, + {file = "pyunormalize-16.0.0.tar.gz", hash = "sha256:2e1dfbb4a118154ae26f70710426a52a364b926c9191f764601f5a8cb12761f7"}, +] + +[[package]] +name = "pywin32" +version = "308" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +files = [ + {file = "pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e"}, + {file = "pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e"}, + {file = "pywin32-308-cp310-cp310-win_arm64.whl", hash = "sha256:a5ab5381813b40f264fa3495b98af850098f814a25a63589a8e9eb12560f450c"}, + {file = "pywin32-308-cp311-cp311-win32.whl", hash = "sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a"}, + {file = "pywin32-308-cp311-cp311-win_amd64.whl", hash = "sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b"}, + {file = "pywin32-308-cp311-cp311-win_arm64.whl", hash = "sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6"}, + {file = "pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897"}, + {file = "pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47"}, + {file = "pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091"}, + {file = "pywin32-308-cp313-cp313-win32.whl", hash = "sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed"}, + {file = "pywin32-308-cp313-cp313-win_amd64.whl", hash = "sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4"}, + {file = "pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd"}, + {file = "pywin32-308-cp37-cp37m-win32.whl", hash = "sha256:1f696ab352a2ddd63bd07430080dd598e6369152ea13a25ebcdd2f503a38f1ff"}, + {file = "pywin32-308-cp37-cp37m-win_amd64.whl", hash = "sha256:13dcb914ed4347019fbec6697a01a0aec61019c1046c2b905410d197856326a6"}, + {file = "pywin32-308-cp38-cp38-win32.whl", hash = "sha256:5794e764ebcabf4ff08c555b31bd348c9025929371763b2183172ff4708152f0"}, + {file = "pywin32-308-cp38-cp38-win_amd64.whl", hash = "sha256:3b92622e29d651c6b783e368ba7d6722b1634b8e70bd376fd7610fe1992e19de"}, + {file = "pywin32-308-cp39-cp39-win32.whl", hash = "sha256:7873ca4dc60ab3287919881a7d4f88baee4a6e639aa6962de25a98ba6b193341"}, + {file = "pywin32-308-cp39-cp39-win_amd64.whl", hash = "sha256:71b3322d949b4cc20776436a9c9ba0eeedcbc9c650daa536df63f0ff111bb920"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, +] + +[[package]] +name = "pyyaml-include" +version = "1.4.1" +description = "Extending PyYAML with a custom constructor for including YAML files within YAML files" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyyaml-include-1.4.1.tar.gz", hash = "sha256:1a96e33a99a3e56235f5221273832464025f02ff3d8539309a3bf00dec624471"}, + {file = "pyyaml_include-1.4.1-py3-none-any.whl", hash = "sha256:323c7f3a19c82fbc4d73abbaab7ef4f793e146a13383866831631b26ccc7fb00"}, +] + +[package.dependencies] +PyYAML = ">=6.0,<7.0" + +[package.extras] +toml = ["toml"] + +[[package]] +name = "referencing" +version = "0.35.1" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, + {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[package]] +name = "regex" +version = "2024.11.6" +description = "Alternative regular expression module, to replace re." +optional = false +python-versions = ">=3.8" +files = [ + {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, + {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, + {file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"}, + {file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"}, + {file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}, + {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}, + {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}, + {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}, + {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"}, + {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"}, + {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"}, + {file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"}, + {file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"}, + {file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"}, + {file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"}, + {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"}, +] + +[[package]] +name = "requests" +version = "2.32.3" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "rlp" +version = "4.1.0" +description = "rlp: A package for Recursive Length Prefix encoding and decoding" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "rlp-4.1.0-py3-none-any.whl", hash = "sha256:8eca394c579bad34ee0b937aecb96a57052ff3716e19c7a578883e767bc5da6f"}, + {file = "rlp-4.1.0.tar.gz", hash = "sha256:be07564270a96f3e225e2c107db263de96b5bc1f27722d2855bd3459a08e95a9"}, +] + +[package.dependencies] +eth-utils = ">=2" + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "hypothesis (>=6.22.0,<6.108.7)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +rust-backend = ["rusty-rlp (>=0.2.1)"] +test = ["hypothesis (>=6.22.0,<6.108.7)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + +[[package]] +name = "rpds-py" +version = "0.22.3" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "rpds_py-0.22.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967"}, + {file = "rpds_py-0.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec"}, + {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00"}, + {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf"}, + {file = "rpds_py-0.22.3-cp310-cp310-win32.whl", hash = "sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652"}, + {file = "rpds_py-0.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8"}, + {file = "rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f"}, + {file = "rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1"}, + {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74"}, + {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a"}, + {file = "rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64"}, + {file = "rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c"}, + {file = "rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e"}, + {file = "rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15"}, + {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61"}, + {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7"}, + {file = "rpds_py-0.22.3-cp312-cp312-win32.whl", hash = "sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627"}, + {file = "rpds_py-0.22.3-cp312-cp312-win_amd64.whl", hash = "sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4"}, + {file = "rpds_py-0.22.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84"}, + {file = "rpds_py-0.22.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518"}, + {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16"}, + {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f"}, + {file = "rpds_py-0.22.3-cp313-cp313-win32.whl", hash = "sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de"}, + {file = "rpds_py-0.22.3-cp313-cp313-win_amd64.whl", hash = "sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9"}, + {file = "rpds_py-0.22.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3"}, + {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b"}, + {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333"}, + {file = "rpds_py-0.22.3-cp313-cp313t-win32.whl", hash = "sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730"}, + {file = "rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf"}, + {file = "rpds_py-0.22.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:378753b4a4de2a7b34063d6f95ae81bfa7b15f2c1a04a9518e8644e81807ebea"}, + {file = "rpds_py-0.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3445e07bf2e8ecfeef6ef67ac83de670358abf2996916039b16a218e3d95e97e"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b2513ba235829860b13faa931f3b6846548021846ac808455301c23a101689d"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eaf16ae9ae519a0e237a0f528fd9f0197b9bb70f40263ee57ae53c2b8d48aeb3"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:583f6a1993ca3369e0f80ba99d796d8e6b1a3a2a442dd4e1a79e652116413091"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4617e1915a539a0d9a9567795023de41a87106522ff83fbfaf1f6baf8e85437e"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c150c7a61ed4a4f4955a96626574e9baf1adf772c2fb61ef6a5027e52803543"}, + {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fa4331c200c2521512595253f5bb70858b90f750d39b8cbfd67465f8d1b596d"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:214b7a953d73b5e87f0ebece4a32a5bd83c60a3ecc9d4ec8f1dca968a2d91e99"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f47ad3d5f3258bd7058d2d506852217865afefe6153a36eb4b6928758041d831"}, + {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f276b245347e6e36526cbd4a266a417796fc531ddf391e43574cf6466c492520"}, + {file = "rpds_py-0.22.3-cp39-cp39-win32.whl", hash = "sha256:bbb232860e3d03d544bc03ac57855cd82ddf19c7a07651a7c0fdb95e9efea8b9"}, + {file = "rpds_py-0.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfbc454a2880389dbb9b5b398e50d439e2e58669160f27b60e5eca11f68ae17c"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe"}, + {file = "rpds_py-0.22.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bb47271f60660803ad11f4c61b42242b8c1312a31c98c578f79ef9387bbde21c"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:70fb28128acbfd264eda9bf47015537ba3fe86e40d046eb2963d75024be4d055"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44d61b4b7d0c2c9ac019c314e52d7cbda0ae31078aabd0f22e583af3e0d79723"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0e260eaf54380380ac3808aa4ebe2d8ca28b9087cf411649f96bad6900c728"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b25bc607423935079e05619d7de556c91fb6adeae9d5f80868dde3468657994b"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb6116dfb8d1925cbdb52595560584db42a7f664617a1f7d7f6e32f138cdf37d"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a63cbdd98acef6570c62b92a1e43266f9e8b21e699c363c0fef13bd530799c11"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b8f60e1b739a74bab7e01fcbe3dddd4657ec685caa04681df9d562ef15b625f"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2e8b55d8517a2fda8d95cb45d62a5a8bbf9dd0ad39c5b25c8833efea07b880ca"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2de29005e11637e7a2361fa151f780ff8eb2543a0da1413bb951e9f14b699ef3"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:666ecce376999bf619756a24ce15bb14c5bfaf04bf00abc7e663ce17c3f34fe7"}, + {file = "rpds_py-0.22.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5246b14ca64a8675e0a7161f7af68fe3e910e6b90542b4bfb5439ba752191df6"}, + {file = "rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d"}, +] + +[[package]] +name = "setuptools" +version = "75.8.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.9" +files = [ + {file = "setuptools-75.8.2-py3-none-any.whl", hash = "sha256:558e47c15f1811c1fa7adbd0096669bf76c1d3f433f58324df69f3f5ecac4e8f"}, + {file = "setuptools-75.8.2.tar.gz", hash = "sha256:4880473a969e5f23f2a2be3646b2dfd84af9028716d398e46192f84bc36900d2"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"] +core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] + +[[package]] +name = "six" +version = "1.17.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, +] + +[[package]] +name = "supervisor" +version = "4.2.5" +description = "A system for controlling process state under UNIX" +optional = false +python-versions = "*" +files = [ + {file = "supervisor-4.2.5-py2.py3-none-any.whl", hash = "sha256:2ecaede32fc25af814696374b79e42644ecaba5c09494c51016ffda9602d0f08"}, + {file = "supervisor-4.2.5.tar.gz", hash = "sha256:34761bae1a23c58192281a5115fb07fbf22c9b0133c08166beffc70fed3ebc12"}, +] + +[package.dependencies] +setuptools = "*" + +[package.extras] +testing = ["pytest", "pytest-cov"] + +[[package]] +name = "termcolor" +version = "2.5.0" +description = "ANSI color formatting for output in terminal" +optional = false +python-versions = ">=3.9" +files = [ + {file = "termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8"}, + {file = "termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f"}, +] + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "tomlkit" +version = "0.13.2" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, + {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, +] + +[[package]] +name = "toolz" +version = "1.0.0" +description = "List processing tools and functional utilities" +optional = false +python-versions = ">=3.8" +files = [ + {file = "toolz-1.0.0-py3-none-any.whl", hash = "sha256:292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236"}, + {file = "toolz-1.0.0.tar.gz", hash = "sha256:2c86e3d9a04798ac556793bced838816296a2f085017664e4995cb40a1047a02"}, +] + +[[package]] +name = "types-requests" +version = "2.32.0.20250328" +description = "Typing stubs for requests" +optional = false +python-versions = ">=3.9" +files = [ + {file = "types_requests-2.32.0.20250328-py3-none-any.whl", hash = "sha256:72ff80f84b15eb3aa7a8e2625fffb6a93f2ad5a0c20215fc1dcfa61117bcb2a2"}, + {file = "types_requests-2.32.0.20250328.tar.gz", hash = "sha256:c9e67228ea103bd811c96984fac36ed2ae8da87a36a633964a21f199d60baf32"}, +] + +[package.dependencies] +urllib3 = ">=2" + +[[package]] +name = "typing-extensions" +version = "4.12.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, +] + +[[package]] +name = "typing-inspection" +version = "0.4.0" +description = "Runtime typing introspection tools" +optional = false +python-versions = ">=3.9" +files = [ + {file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"}, + {file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"}, +] + +[package.dependencies] +typing-extensions = ">=4.12.0" + +[[package]] +name = "urllib3" +version = "2.3.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.9" +files = [ + {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, + {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "web3" +version = "7.12.0" +description = "web3: A Python library for interacting with Ethereum" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "web3-7.12.0-py3-none-any.whl", hash = "sha256:c7e2b9c1db5a379ef53b45fe8a19bdc2d47ad262039fbf6675794bc40f74bf06"}, + {file = "web3-7.12.0.tar.gz", hash = "sha256:08fbe79a2e2503c9820132ebad24ba0372831588cabac5f467999c97ace7dda3"}, +] + +[package.dependencies] +aiohttp = ">=3.7.4.post0" +eth-abi = ">=5.0.1" +eth-account = ">=0.13.6" +eth-hash = {version = ">=0.5.1", extras = ["pycryptodome"]} +eth-typing = ">=5.0.0" +eth-utils = ">=5.0.0" +hexbytes = ">=1.2.0" +pydantic = ">=2.4.0" +pyunormalize = ">=15.0.0" +pywin32 = {version = ">=223", markers = "platform_system == \"Windows\""} +requests = ">=2.23.0" +types-requests = ">=2.0.0" +typing-extensions = ">=4.0.1" +websockets = ">=10.0.0,<16.0.0" + +[package.extras] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "eth-tester[py-evm] (>=0.13.0b1,<0.14.0b1)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "py-geth (>=5.1.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1,<0.23)", "pytest-mock (>=1.10)", "pytest-xdist (>=2.4.0)", "setuptools (>=38.6.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "tqdm (>4.32)", "twine (>=1.13)", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] +test = ["eth-tester[py-evm] (>=0.13.0b1,<0.14.0b1)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "py-geth (>=5.1.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1,<0.23)", "pytest-mock (>=1.10)", "pytest-xdist (>=2.4.0)", "tox (>=4.0.0)"] +tester = ["eth-tester[py-evm] (>=0.13.0b1,<0.14.0b1)", "py-geth (>=5.1.0)"] + +[[package]] +name = "websockets" +version = "13.1" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websockets-13.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee"}, + {file = "websockets-13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7"}, + {file = "websockets-13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6"}, + {file = "websockets-13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b"}, + {file = "websockets-13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa"}, + {file = "websockets-13.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700"}, + {file = "websockets-13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c"}, + {file = "websockets-13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0"}, + {file = "websockets-13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f"}, + {file = "websockets-13.1-cp310-cp310-win32.whl", hash = "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe"}, + {file = "websockets-13.1-cp310-cp310-win_amd64.whl", hash = "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a"}, + {file = "websockets-13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19"}, + {file = "websockets-13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5"}, + {file = "websockets-13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd"}, + {file = "websockets-13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02"}, + {file = "websockets-13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7"}, + {file = "websockets-13.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096"}, + {file = "websockets-13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084"}, + {file = "websockets-13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3"}, + {file = "websockets-13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9"}, + {file = "websockets-13.1-cp311-cp311-win32.whl", hash = "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f"}, + {file = "websockets-13.1-cp311-cp311-win_amd64.whl", hash = "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557"}, + {file = "websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc"}, + {file = "websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49"}, + {file = "websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd"}, + {file = "websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0"}, + {file = "websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6"}, + {file = "websockets-13.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9"}, + {file = "websockets-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68"}, + {file = "websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14"}, + {file = "websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf"}, + {file = "websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c"}, + {file = "websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3"}, + {file = "websockets-13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6"}, + {file = "websockets-13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708"}, + {file = "websockets-13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418"}, + {file = "websockets-13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a"}, + {file = "websockets-13.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f"}, + {file = "websockets-13.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5"}, + {file = "websockets-13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135"}, + {file = "websockets-13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2"}, + {file = "websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6"}, + {file = "websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d"}, + {file = "websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2"}, + {file = "websockets-13.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d"}, + {file = "websockets-13.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23"}, + {file = "websockets-13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c"}, + {file = "websockets-13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea"}, + {file = "websockets-13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7"}, + {file = "websockets-13.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54"}, + {file = "websockets-13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db"}, + {file = "websockets-13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295"}, + {file = "websockets-13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96"}, + {file = "websockets-13.1-cp38-cp38-win32.whl", hash = "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf"}, + {file = "websockets-13.1-cp38-cp38-win_amd64.whl", hash = "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6"}, + {file = "websockets-13.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d"}, + {file = "websockets-13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7"}, + {file = "websockets-13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a"}, + {file = "websockets-13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa"}, + {file = "websockets-13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa"}, + {file = "websockets-13.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79"}, + {file = "websockets-13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17"}, + {file = "websockets-13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6"}, + {file = "websockets-13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5"}, + {file = "websockets-13.1-cp39-cp39-win32.whl", hash = "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c"}, + {file = "websockets-13.1-cp39-cp39-win_amd64.whl", hash = "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d"}, + {file = "websockets-13.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238"}, + {file = "websockets-13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5"}, + {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9"}, + {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6"}, + {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a"}, + {file = "websockets-13.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23"}, + {file = "websockets-13.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b"}, + {file = "websockets-13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51"}, + {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7"}, + {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d"}, + {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027"}, + {file = "websockets-13.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978"}, + {file = "websockets-13.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e"}, + {file = "websockets-13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09"}, + {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842"}, + {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb"}, + {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20"}, + {file = "websockets-13.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678"}, + {file = "websockets-13.1-py3-none-any.whl", hash = "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f"}, + {file = "websockets-13.1.tar.gz", hash = "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878"}, +] + +[[package]] +name = "yarl" +version = "1.20.0" +description = "Yet another URL library" +optional = false +python-versions = ">=3.9" +files = [ + {file = "yarl-1.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f1f6670b9ae3daedb325fa55fbe31c22c8228f6e0b513772c2e1c623caa6ab22"}, + {file = "yarl-1.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:85a231fa250dfa3308f3c7896cc007a47bc76e9e8e8595c20b7426cac4884c62"}, + {file = "yarl-1.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a06701b647c9939d7019acdfa7ebbfbb78ba6aa05985bb195ad716ea759a569"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7595498d085becc8fb9203aa314b136ab0516c7abd97e7d74f7bb4eb95042abe"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af5607159085dcdb055d5678fc2d34949bd75ae6ea6b4381e784bbab1c3aa195"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95b50910e496567434cb77a577493c26bce0f31c8a305135f3bda6a2483b8e10"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b594113a301ad537766b4e16a5a6750fcbb1497dcc1bc8a4daae889e6402a634"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:083ce0393ea173cd37834eb84df15b6853b555d20c52703e21fbababa8c129d2"}, + {file = "yarl-1.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f1a350a652bbbe12f666109fbddfdf049b3ff43696d18c9ab1531fbba1c977a"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fb0caeac4a164aadce342f1597297ec0ce261ec4532bbc5a9ca8da5622f53867"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:d88cc43e923f324203f6ec14434fa33b85c06d18d59c167a0637164863b8e995"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e52d6ed9ea8fd3abf4031325dc714aed5afcbfa19ee4a89898d663c9976eb487"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ce360ae48a5e9961d0c730cf891d40698a82804e85f6e74658fb175207a77cb2"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:06d06c9d5b5bc3eb56542ceeba6658d31f54cf401e8468512447834856fb0e61"}, + {file = "yarl-1.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c27d98f4e5c4060582f44e58309c1e55134880558f1add7a87c1bc36ecfade19"}, + {file = "yarl-1.20.0-cp310-cp310-win32.whl", hash = "sha256:f4d3fa9b9f013f7050326e165c3279e22850d02ae544ace285674cb6174b5d6d"}, + {file = "yarl-1.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:bc906b636239631d42eb8a07df8359905da02704a868983265603887ed68c076"}, + {file = "yarl-1.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fdb5204d17cb32b2de2d1e21c7461cabfacf17f3645e4b9039f210c5d3378bf3"}, + {file = "yarl-1.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:eaddd7804d8e77d67c28d154ae5fab203163bd0998769569861258e525039d2a"}, + {file = "yarl-1.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:634b7ba6b4a85cf67e9df7c13a7fb2e44fa37b5d34501038d174a63eaac25ee2"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d409e321e4addf7d97ee84162538c7258e53792eb7c6defd0c33647d754172e"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ea52f7328a36960ba3231c6677380fa67811b414798a6e071c7085c57b6d20a9"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8703517b924463994c344dcdf99a2d5ce9eca2b6882bb640aa555fb5efc706a"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:077989b09ffd2f48fb2d8f6a86c5fef02f63ffe6b1dd4824c76de7bb01e4f2e2"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0acfaf1da020253f3533526e8b7dd212838fdc4109959a2c53cafc6db611bff2"}, + {file = "yarl-1.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4230ac0b97ec5eeb91d96b324d66060a43fd0d2a9b603e3327ed65f084e41f8"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a6a1e6ae21cdd84011c24c78d7a126425148b24d437b5702328e4ba640a8902"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:86de313371ec04dd2531f30bc41a5a1a96f25a02823558ee0f2af0beaa7ca791"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dd59c9dd58ae16eaa0f48c3d0cbe6be8ab4dc7247c3ff7db678edecbaf59327f"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a0bc5e05f457b7c1994cc29e83b58f540b76234ba6b9648a4971ddc7f6aa52da"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c9471ca18e6aeb0e03276b5e9b27b14a54c052d370a9c0c04a68cefbd1455eb4"}, + {file = "yarl-1.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:40ed574b4df723583a26c04b298b283ff171bcc387bc34c2683235e2487a65a5"}, + {file = "yarl-1.20.0-cp311-cp311-win32.whl", hash = "sha256:db243357c6c2bf3cd7e17080034ade668d54ce304d820c2a58514a4e51d0cfd6"}, + {file = "yarl-1.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:8c12cd754d9dbd14204c328915e23b0c361b88f3cffd124129955e60a4fbfcfb"}, + {file = "yarl-1.20.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e06b9f6cdd772f9b665e5ba8161968e11e403774114420737f7884b5bd7bdf6f"}, + {file = "yarl-1.20.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b9ae2fbe54d859b3ade40290f60fe40e7f969d83d482e84d2c31b9bff03e359e"}, + {file = "yarl-1.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d12b8945250d80c67688602c891237994d203d42427cb14e36d1a732eda480e"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:087e9731884621b162a3e06dc0d2d626e1542a617f65ba7cc7aeab279d55ad33"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:69df35468b66c1a6e6556248e6443ef0ec5f11a7a4428cf1f6281f1879220f58"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b2992fe29002fd0d4cbaea9428b09af9b8686a9024c840b8a2b8f4ea4abc16f"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c903e0b42aab48abfbac668b5a9d7b6938e721a6341751331bcd7553de2dcae"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf099e2432131093cc611623e0b0bcc399b8cddd9a91eded8bfb50402ec35018"}, + {file = "yarl-1.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a7f62f5dc70a6c763bec9ebf922be52aa22863d9496a9a30124d65b489ea672"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:54ac15a8b60382b2bcefd9a289ee26dc0920cf59b05368c9b2b72450751c6eb8"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:25b3bc0763a7aca16a0f1b5e8ef0f23829df11fb539a1b70476dcab28bd83da7"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b2586e36dc070fc8fad6270f93242124df68b379c3a251af534030a4a33ef594"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:866349da9d8c5290cfefb7fcc47721e94de3f315433613e01b435473be63daa6"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:33bb660b390a0554d41f8ebec5cd4475502d84104b27e9b42f5321c5192bfcd1"}, + {file = "yarl-1.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:737e9f171e5a07031cbee5e9180f6ce21a6c599b9d4b2c24d35df20a52fabf4b"}, + {file = "yarl-1.20.0-cp312-cp312-win32.whl", hash = "sha256:839de4c574169b6598d47ad61534e6981979ca2c820ccb77bf70f4311dd2cc64"}, + {file = "yarl-1.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:3d7dbbe44b443b0c4aa0971cb07dcb2c2060e4a9bf8d1301140a33a93c98e18c"}, + {file = "yarl-1.20.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2137810a20b933b1b1b7e5cf06a64c3ed3b4747b0e5d79c9447c00db0e2f752f"}, + {file = "yarl-1.20.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:447c5eadd750db8389804030d15f43d30435ed47af1313303ed82a62388176d3"}, + {file = "yarl-1.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:42fbe577272c203528d402eec8bf4b2d14fd49ecfec92272334270b850e9cd7d"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18e321617de4ab170226cd15006a565d0fa0d908f11f724a2c9142d6b2812ab0"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4345f58719825bba29895011e8e3b545e6e00257abb984f9f27fe923afca2501"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d9b980d7234614bc4674468ab173ed77d678349c860c3af83b1fffb6a837ddc"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af4baa8a445977831cbaa91a9a84cc09debb10bc8391f128da2f7bd070fc351d"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123393db7420e71d6ce40d24885a9e65eb1edefc7a5228db2d62bcab3386a5c0"}, + {file = "yarl-1.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab47acc9332f3de1b39e9b702d9c916af7f02656b2a86a474d9db4e53ef8fd7a"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4a34c52ed158f89876cba9c600b2c964dfc1ca52ba7b3ab6deb722d1d8be6df2"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:04d8cfb12714158abf2618f792c77bc5c3d8c5f37353e79509608be4f18705c9"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7dc63ad0d541c38b6ae2255aaa794434293964677d5c1ec5d0116b0e308031f5"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d02b591a64e4e6ca18c5e3d925f11b559c763b950184a64cf47d74d7e41877"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:95fc9876f917cac7f757df80a5dda9de59d423568460fe75d128c813b9af558e"}, + {file = "yarl-1.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bb769ae5760cd1c6a712135ee7915f9d43f11d9ef769cb3f75a23e398a92d384"}, + {file = "yarl-1.20.0-cp313-cp313-win32.whl", hash = "sha256:70e0c580a0292c7414a1cead1e076c9786f685c1fc4757573d2967689b370e62"}, + {file = "yarl-1.20.0-cp313-cp313-win_amd64.whl", hash = "sha256:4c43030e4b0af775a85be1fa0433119b1565673266a70bf87ef68a9d5ba3174c"}, + {file = "yarl-1.20.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b6c4c3d0d6a0ae9b281e492b1465c72de433b782e6b5001c8e7249e085b69051"}, + {file = "yarl-1.20.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8681700f4e4df891eafa4f69a439a6e7d480d64e52bf460918f58e443bd3da7d"}, + {file = "yarl-1.20.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:84aeb556cb06c00652dbf87c17838eb6d92cfd317799a8092cee0e570ee11229"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f166eafa78810ddb383e930d62e623d288fb04ec566d1b4790099ae0f31485f1"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5d3d6d14754aefc7a458261027a562f024d4f6b8a798adb472277f675857b1eb"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a8f64df8ed5d04c51260dbae3cc82e5649834eebea9eadfd829837b8093eb00"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d9949eaf05b4d30e93e4034a7790634bbb41b8be2d07edd26754f2e38e491de"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c366b254082d21cc4f08f522ac201d0d83a8b8447ab562732931d31d80eb2a5"}, + {file = "yarl-1.20.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91bc450c80a2e9685b10e34e41aef3d44ddf99b3a498717938926d05ca493f6a"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c2aa4387de4bc3a5fe158080757748d16567119bef215bec643716b4fbf53f9"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:d2cbca6760a541189cf87ee54ff891e1d9ea6406079c66341008f7ef6ab61145"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:798a5074e656f06b9fad1a162be5a32da45237ce19d07884d0b67a0aa9d5fdda"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f106e75c454288472dbe615accef8248c686958c2e7dd3b8d8ee2669770d020f"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:3b60a86551669c23dc5445010534d2c5d8a4e012163218fc9114e857c0586fdd"}, + {file = "yarl-1.20.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e429857e341d5e8e15806118e0294f8073ba9c4580637e59ab7b238afca836f"}, + {file = "yarl-1.20.0-cp313-cp313t-win32.whl", hash = "sha256:65a4053580fe88a63e8e4056b427224cd01edfb5f951498bfefca4052f0ce0ac"}, + {file = "yarl-1.20.0-cp313-cp313t-win_amd64.whl", hash = "sha256:53b2da3a6ca0a541c1ae799c349788d480e5144cac47dba0266c7cb6c76151fe"}, + {file = "yarl-1.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:119bca25e63a7725b0c9d20ac67ca6d98fa40e5a894bd5d4686010ff73397914"}, + {file = "yarl-1.20.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:35d20fb919546995f1d8c9e41f485febd266f60e55383090010f272aca93edcc"}, + {file = "yarl-1.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:484e7a08f72683c0f160270566b4395ea5412b4359772b98659921411d32ad26"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d8a3d54a090e0fff5837cd3cc305dd8a07d3435a088ddb1f65e33b322f66a94"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f0cf05ae2d3d87a8c9022f3885ac6dea2b751aefd66a4f200e408a61ae9b7f0d"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a884b8974729e3899d9287df46f015ce53f7282d8d3340fa0ed57536b440621c"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8d8aa8dd89ffb9a831fedbcb27d00ffd9f4842107d52dc9d57e64cb34073d5c"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4e88d6c3c8672f45a30867817e4537df1bbc6f882a91581faf1f6d9f0f1b5a"}, + {file = "yarl-1.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdb77efde644d6f1ad27be8a5d67c10b7f769804fff7a966ccb1da5a4de4b656"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4ba5e59f14bfe8d261a654278a0f6364feef64a794bd456a8c9e823071e5061c"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:d0bf955b96ea44ad914bc792c26a0edcd71b4668b93cbcd60f5b0aeaaed06c64"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:27359776bc359ee6eaefe40cb19060238f31228799e43ebd3884e9c589e63b20"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:04d9c7a1dc0a26efb33e1acb56c8849bd57a693b85f44774356c92d610369efa"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:faa709b66ae0e24c8e5134033187a972d849d87ed0a12a0366bedcc6b5dc14a5"}, + {file = "yarl-1.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:44869ee8538208fe5d9342ed62c11cc6a7a1af1b3d0bb79bb795101b6e77f6e0"}, + {file = "yarl-1.20.0-cp39-cp39-win32.whl", hash = "sha256:b7fa0cb9fd27ffb1211cde944b41f5c67ab1c13a13ebafe470b1e206b8459da8"}, + {file = "yarl-1.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:d4fad6e5189c847820288286732075f213eabf81be4d08d6cc309912e62be5b7"}, + {file = "yarl-1.20.0-py3-none-any.whl", hash = "sha256:5d0fe6af927a47a230f31e6004621fd0959eaa915fc62acfafa67ff7229a3124"}, + {file = "yarl-1.20.0.tar.gz", hash = "sha256:686d51e51ee5dfe62dec86e4866ee0e9ed66df700d55c828a615640adc885307"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" +propcache = ">=0.2.1" + +[metadata] +lock-version = "2.0" +python-versions = "^3.12" +content-hash = "7bb818916fad69593448f930b004777e44e5491af530a0902fa96efb71bd711c" diff --git a/tests/integration_tests/pyproject.toml b/tests/integration_tests/pyproject.toml new file mode 100644 index 000000000..600056215 --- /dev/null +++ b/tests/integration_tests/pyproject.toml @@ -0,0 +1,40 @@ +[tool.poetry] +name = "integration-tests" +version = "0.1.0" +description = "" +authors = ["Your Name "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.12" +pytest = "^8.3.4" +pystarport = { git = "https://github.com/MANTRA-Chain/pystarport.git", branch = "ref_cmd" } +pytest-github-actions-annotate-failures = "^0.3.0" +flake8-black = "^0.3.6" +flake8-isort = "^6.1.2" +pyunormalize = "^16.0.0" +cprotobuf = { git = "https://github.com/yihuang/cprotobuf.git", branch = "master" } +web3 = "^7.3.0" +eth-bloom = "^3.0" +flaky = "^3.8.1" +pytest-asyncio = "0.25.3" +eth-contract = { git = "https://github.com/yihuang/eth-contract.git", branch = "main" } +py-ecc = "^8.0.0" + +[tool.poetry.dev-dependencies] +attrs = "24.2.0" +referencing = "v0.35.1" +rpds-py = "v0.22.3" +aiohappyeyeballs = "2.4.4" +types-requests = "2.32.0.20250328" +typing-inspection = "0.4.0" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.black] +line-length = 88 + +[tool.isort] +profile = "black" diff --git a/tests/integration_tests/shell.nix b/tests/integration_tests/shell.nix new file mode 100644 index 000000000..b299bbf48 --- /dev/null +++ b/tests/integration_tests/shell.nix @@ -0,0 +1,16 @@ +{ + system ? builtins.currentSystem, + pkgs ? import ../nix { inherit system; }, +}: +pkgs.mkShell { + buildInputs = [ + pkgs.git + pkgs.test-env + pkgs.poetry + pkgs.solc + # pkgs.evmd + ]; + shellHook = '' + export TMPDIR=/tmp + ''; +} diff --git a/tests/integration_tests/test_account.py b/tests/integration_tests/test_account.py new file mode 100644 index 000000000..ed40b2569 --- /dev/null +++ b/tests/integration_tests/test_account.py @@ -0,0 +1,14 @@ +import pytest +import web3 + +from .utils import derive_new_account + + +def test_future_blk(evm): + w3 = evm.w3 + acc = derive_new_account(2).address + current = w3.eth.block_number + future = current + 1000 + with pytest.raises(web3.exceptions.Web3RPCError) as exc: + w3.eth.get_transaction_count(acc, hex(future)) + assert "cannot query with height in the future" in str(exc) diff --git a/tests/integration_tests/utils.py b/tests/integration_tests/utils.py new file mode 100644 index 000000000..16f4f7c38 --- /dev/null +++ b/tests/integration_tests/utils.py @@ -0,0 +1,1046 @@ +import asyncio +import base64 +import binascii +import configparser +import hashlib +import json +import os +import re +import secrets +import socket +import subprocess +import sys +import time +from collections import defaultdict +from concurrent.futures import ThreadPoolExecutor, as_completed +from enum import Enum +from itertools import takewhile +from pathlib import Path +from urllib.parse import urlparse + +import bech32 +import eth_utils +import requests +import rlp +from dateutil.parser import isoparse +from dotenv import load_dotenv +from eth_account import Account +from eth_contract.create2 import create2_address +from eth_contract.deploy_utils import ( + ensure_create2_deployed, + ensure_deployed_by_create2, +) +from eth_contract.erc20 import ERC20 +from eth_contract.utils import ZERO_ADDRESS, balance_of, get_initcode +from eth_contract.utils import send_transaction as send_transaction_async +from eth_contract.weth import WETH, WETH9_ARTIFACT +from eth_utils import to_checksum_address +from hexbytes import HexBytes +from pystarport import cluster +from web3 import AsyncWeb3 +from web3._utils.transactions import fill_nonce, fill_transaction_defaults + +load_dotenv(Path(__file__).parent.parent / "scripts/.env") +Account.enable_unaudited_hdwallet_features() +MNEMONICS = { + "validator": os.getenv("VALIDATOR1_MNEMONIC"), + "validator2": os.getenv("VALIDATOR2_MNEMONIC"), + "validator3": os.getenv("VALIDATOR3_MNEMONIC"), + "community": os.getenv("COMMUNITY_MNEMONIC"), + "signer1": os.getenv("SIGNER1_MNEMONIC"), + "signer2": os.getenv("SIGNER2_MNEMONIC"), + "reserve": os.getenv("RESERVE_MNEMONIC"), +} +ACCOUNTS = { + name: Account.from_mnemonic(mnemonic) for name, mnemonic in MNEMONICS.items() +} +KEYS = {name: account.key for name, account in ACCOUNTS.items()} +ADDRS = {name: account.address for name, account in ACCOUNTS.items()} + +DEFAULT_DENOM = os.getenv("EVM_DENOM", "uom") +DEFAULT_EXTENDED_DENOM = os.getenv("EVM_EXTENDED_DENOM", "aom") +CHAIN_ID = os.getenv("CHAIN_ID", "evm-canary-net-1") +EVM_CHAIN_ID = int(os.getenv("EVM_CHAIN_ID", 7888)) +# the default initial base fee used by integration tests +DEFAULT_GAS_AMT = float(os.getenv("DEFAULT_GAS_AMT", 0.01)) +DEFAULT_GAS_PRICE = f"{DEFAULT_GAS_AMT}{DEFAULT_DENOM}" +DEFAULT_GAS = 200000 +DEFAULT_FEE = int(DEFAULT_GAS_AMT * DEFAULT_GAS) +WEI_PER_ETH = 10**18 # 10^18 wei == 1 ether +WEI_PER_DENOM = int(os.getenv("WEI_PER_DENOM", 10**12)) # 10^12 wei == 1 uom +ADDRESS_PREFIX = os.getenv("ADDRESS_PREFIX", "evm") +CMD = os.getenv("CMD", "evmd") + + +WETH_SALT = 999 +WETH_ADDRESS = create2_address(get_initcode(WETH9_ARTIFACT), WETH_SALT) + + +class BondStatus(Enum): + UNSPECIFIED = "BOND_STATUS_UNSPECIFIED" + UNBONDED = "BOND_STATUS_UNBONDED" + UNBONDING = "BOND_STATUS_UNBONDING" + BONDED = "BOND_STATUS_BONDED" + + def to_int(self): + mapping = { + BondStatus.UNSPECIFIED: 0, + BondStatus.UNBONDED: 1, + BondStatus.UNBONDING: 2, + BondStatus.BONDED: 3, + } + return mapping[self] + + +class Contract: + def __init__(self, name, private_key=KEYS["community"], chain_id=EVM_CHAIN_ID): + self.chain_id = chain_id + self.account = Account.from_key(private_key) + self.owner = self.account.address + self.private_key = private_key + res = build_contract(name) + self.bytecode = res["bytecode"] + self.code = res["code"] + self.abi = res["abi"] + self.contract = None + self.w3 = None + + def deploy(self, w3, exp_gas_used=None): + "Deploy contract on `w3` and return the receipt." + if self.contract is None: + self.w3 = w3 + contract = self.w3.eth.contract(abi=self.abi, bytecode=self.bytecode) + transaction = contract.constructor().build_transaction( + {"chainId": self.chain_id, "from": self.owner} + ) + receipt = send_transaction(self.w3, transaction, self.private_key) + if exp_gas_used is not None: + assert ( + exp_gas_used == receipt.gasUsed + ), f"exp {exp_gas_used}, got {receipt.gasUsed}" + self.contract = self.w3.eth.contract( + address=receipt.contractAddress, abi=self.abi + ) + return receipt + else: + return receipt + + +class Greeter(Contract): + "Greeter contract." + + def transfer(self, string): + "Call contract on `w3` and return the receipt." + transaction = self.contract.functions.setGreeting(string).build_transaction( + { + "chainId": self.chain_id, + "from": self.owner, + } + ) + receipt = send_transaction(self.w3, transaction, self.private_key) + assert string == self.contract.functions.greet().call() + return receipt + + +class RevertTestContract(Contract): + "RevertTestContract contract." + + def transfer(self, value): + "Call contract on `w3` and return the receipt." + transaction = self.contract.functions.transfer(value).build_transaction( + { + "chainId": self.chain_id, + "from": self.owner, + "gas": 100000, # skip estimateGas error + } + ) + receipt = send_transaction(self.w3, transaction, self.private_key) + return receipt + + +def wait_for_fn(name, fn, *, timeout=120, interval=1): + for i in range(int(timeout / interval)): + result = fn() + if result: + return result + time.sleep(interval) + else: + raise TimeoutError(f"wait for {name} timeout") + + +async def wait_for_fn_async(name, fn, *, timeout=120, interval=1): + for i in range(int(timeout / interval)): + result = await fn() + if result: + return result + await asyncio.sleep(interval) + else: + raise TimeoutError(f"wait for {name} timeout") + + +def wait_for_block_time(cli, t): + print("wait for block time", t) + while True: + now = isoparse(get_sync_info(cli.status())["latest_block_time"]) + print("block time now:", now) + if now >= t: + break + time.sleep(0.5) + + +def w3_wait_for_block(w3, height, timeout=120): + for _ in range(timeout * 2): + try: + current_height = w3.eth.block_number + except Exception as e: + print(f"get json-rpc block number failed: {e}", file=sys.stderr) + else: + if current_height >= height: + break + print("current block height", current_height) + time.sleep(0.5) + else: + raise TimeoutError(f"wait for block {height} timeout") + + +async def w3_wait_for_block_async(w3, height, timeout=120): + for _ in range(timeout * 2): + try: + current_height = await w3.eth.block_number + except Exception as e: + print(f"get json-rpc block number failed: {e}", file=sys.stderr) + else: + if current_height >= height: + break + print("current block height", current_height) + await asyncio.sleep(0.1) + else: + raise TimeoutError(f"wait for block {height} timeout") + + +def get_sync_info(s): + return s.get("SyncInfo") or s.get("sync_info") + + +def wait_for_new_blocks(cli, n, sleep=0.5, timeout=120): + cur_height = begin_height = int(get_sync_info(cli.status())["latest_block_height"]) + start_time = time.time() + while cur_height - begin_height < n: + time.sleep(sleep) + cur_height = int(get_sync_info(cli.status())["latest_block_height"]) + if time.time() - start_time > timeout: + raise TimeoutError(f"wait for block {begin_height + n} timeout") + return cur_height + + +def wait_for_block(cli, height, timeout=120): + for i in range(timeout * 2): + try: + status = cli.status() + except AssertionError as e: + print(f"get sync status failed: {e}", file=sys.stderr) + else: + current_height = int(get_sync_info(status)["latest_block_height"]) + print("current block height", current_height) + if current_height >= height: + break + time.sleep(0.5) + else: + raise TimeoutError(f"wait for block {height} timeout") + + +def wait_for_port(port, host="127.0.0.1", timeout=40.0): + print("wait for port", port, "to be available") + start_time = time.perf_counter() + while True: + try: + with socket.create_connection((host, port), timeout=timeout): + break + except OSError as ex: + time.sleep(0.1) + if time.perf_counter() - start_time >= timeout: + raise TimeoutError( + "Waited too long for the port {} on host {} to start accepting " + "connections.".format(port, host) + ) from ex + + +def wait_for_url(url, timeout=40.0): + print("wait for url", url, "to be available") + start_time = time.perf_counter() + while True: + try: + parsed = urlparse(url) + host = parsed.hostname + port = parsed.port + with socket.create_connection((host, int(port or 80)), timeout=timeout): + break + except OSError as ex: + time.sleep(0.1) + if time.perf_counter() - start_time >= timeout: + raise TimeoutError( + "Waited too long for the port {} on host {} to start accepting " + "connections.".format(port, host) + ) from ex + + +def w3_wait_for_new_blocks(w3, n, sleep=0.5): + begin_height = w3.eth.block_number + while True: + time.sleep(sleep) + cur_height = w3.eth.block_number + if cur_height - begin_height >= n: + break + + +async def w3_wait_for_new_blocks_async(w3: AsyncWeb3, n: int, sleep=0.1): + begin_height = await w3.eth.block_number + target = begin_height + n + + while True: + cur_height = await w3.eth.block_number + if cur_height >= target: + break + await asyncio.sleep(sleep) + + +def supervisorctl(inipath, *args): + return subprocess.check_output( + (sys.executable, "-msupervisor.supervisorctl", "-c", inipath, *args), + ).decode() + + +def find_log_event_attrs(events, ev_type, cond=None): + for ev in events: + if ev["type"] == ev_type: + attrs = {attr["key"]: attr["value"] for attr in ev["attributes"]} + if cond is None or cond(attrs): + return attrs + return None + + +def find_duplicate(attributes): + res = set() + key = attributes[0]["key"] + for attribute in attributes: + if attribute["key"] == key: + value0 = attribute["value"] + elif attribute["key"] == "amount": + amount = attribute["value"] + value_pair = f"{value0}:{amount}" + if value_pair in res: + return value_pair + res.add(value_pair) + return None + + +def sign_transaction(w3, tx, key=KEYS["community"]): + "fill default fields and sign" + acct = Account.from_key(key) + tx["from"] = acct.address + tx = fill_transaction_defaults(w3, tx) + tx = fill_nonce(w3, tx) + return acct.sign_transaction(tx) + + +def send_raw_transactions(w3, raw_transactions): + with ThreadPoolExecutor(len(raw_transactions)) as exec: + tasks = [ + exec.submit(w3.eth.send_raw_transaction, raw) for raw in raw_transactions + ] + sended_hash_set = {future.result() for future in as_completed(tasks)} + return sended_hash_set + + +def send_transaction(w3, tx, key=KEYS["community"], check=True): + signed = sign_transaction(w3, tx, key) + txhash = w3.eth.send_raw_transaction(signed.raw_transaction) + if check: + return w3.eth.wait_for_transaction_receipt(txhash) + return txhash + + +def send_txs(w3, cli, to, keys, params): + tx = {"to": to, "value": 10000} | params + # use different sender accounts to be able be send concurrently + raw_transactions = [] + for key_from in keys: + signed = sign_transaction(w3, tx, key_from) + raw_transactions.append(signed.raw_transaction) + + # wait block update + block_num_0 = wait_for_new_blocks(cli, 1, sleep=0.1) + print(f"block number start: {block_num_0}") + + # send transactions + sended_hash_set = send_raw_transactions(w3, raw_transactions) + return block_num_0, sended_hash_set + + +# Global cache for built contracts +CONTRACTS = {} + + +def build_contract(name, dir="contracts") -> dict: + if name in CONTRACTS: + return CONTRACTS[name] + cmd = [ + "solc", + "--abi", + "--bin", + "--bin-runtime", + f"contracts/{dir}/{name}.sol", + "-o", + "build", + "--overwrite", + "--optimize", + "--optimize-runs", + "100000", + "--via-ir", + "--metadata-hash", + "none", + "--no-cbor-metadata", + "--base-path", + "./contracts", + # "$(cat contracts/remappings.txt)", + ] + with open("contracts/remappings.txt", "r") as f: + remappings = f.read().strip().split() + + cmd.extend(remappings) + print(*cmd) + subprocess.run(cmd, check=True) + bytecode = Path(f"build/{name}.bin").read_text().strip() + code = Path(f"build/{name}.bin-runtime").read_text().strip() + result = { + "abi": json.loads(Path(f"build/{name}.abi").read_text()), + "bytecode": f"0x{bytecode}", + "code": f"0x{code}", + } + CONTRACTS[name] = result + return result + + +async def build_and_deploy_contract_async( + w3: AsyncWeb3, + name, + args=(), + key=KEYS["community"], + exp_gas_used=None, + dir="contracts", +): + res = build_contract(name, dir=dir) + contract = w3.eth.contract(abi=res["abi"], bytecode=res["bytecode"]) + acct = Account.from_key(key) + tx = await contract.constructor(*args).build_transaction({"from": acct.address}) + txreceipt = await send_transaction_async(w3, Account.from_key(key), **tx) + if exp_gas_used is not None: + assert ( + exp_gas_used == txreceipt.gasUsed + ), f"exp {exp_gas_used}, got {txreceipt.gasUsed}" + address = txreceipt.contractAddress + return w3.eth.contract(address=address, abi=res["abi"]) + + +def create_contract_transaction(w3, name, args=(), key=KEYS["community"]): + """ + create contract transaction + """ + acct = Account.from_key(key) + res = build_contract(name) + contract = w3.eth.contract(abi=res["abi"], bytecode=res["bytecode"]) + tx = contract.constructor(*args).build_transaction({"from": acct.address}) + return tx + + +async def build_deploy_contract_async( + w3: AsyncWeb3, res, args=(), key=KEYS["community"] +): + acct = Account.from_key(key) + contract = w3.eth.contract(abi=res["abi"], bytecode=res["bytecode"]) + return await contract.constructor(*args).build_transaction({"from": acct.address}) + + +def eth_to_bech32(addr, prefix=ADDRESS_PREFIX): + bz = bech32.convertbits(HexBytes(addr), 8, 5) + return bech32.bech32_encode(prefix, bz) + + +def decode_bech32(addr): + _, bz = bech32.bech32_decode(addr) + return HexBytes(bytes(bech32.convertbits(bz, 5, 8))) + + +def bech32_to_eth(addr): + return to_checksum_address(decode_bech32(addr).hex()) + + +def hash_func(address_type_bytes, key): + hasher = hashlib.sha256() + hasher.update(address_type_bytes) + th = hasher.digest() + hasher = hashlib.sha256() + hasher.update(th) + hasher.update(key) + return hasher.digest() + + +def derive(address_type_bytes, key): + return hash_func(address_type_bytes, key) + + +def module_address(name, *derivation_keys): + m_key = name.encode() + if len(derivation_keys) == 0: + address_bytes = hashlib.sha256(m_key).digest()[:20] + else: + m_key = m_key + b"\x00" + first_key = m_key + derivation_keys[0] + addr = hash_func("module".encode(), first_key) + for k in derivation_keys[1:]: + addr = derive(addr, k) + address_bytes = addr[:20] + eth_address = "0x" + address_bytes.hex() + return eth_to_bech32(eth_address) + + +def generate_isolated_address(channel_id, sender): + name = "ibc-callbacks" + return module_address(name, channel_id.encode(), sender.encode()) + + +def get_balance(cli, name): + try: + addr = cli.address(name, skip_create=True) + except Exception as e: + if "key not found" not in str(e): + raise + addr = name + uom = cli.balance(addr) + return uom + + +def assert_balance(cli, w3, name, evm=False): + try: + addr = cli.address(name, skip_create=True) + except Exception as e: + if "key not found" not in str(e): + raise + addr = name + uom = get_balance(cli, name) + wei = w3.eth.get_balance(bech32_to_eth(addr)) + assert uom == wei // WEI_PER_DENOM + print( + f"wei: {wei}, ether: {wei // WEI_PER_ETH}.", + ) + return wei if evm else uom + + +def find_fee(rsp): + res = find_log_event_attrs(rsp["events"], "tx", lambda attrs: "fee" in attrs) + return int("".join(takewhile(lambda s: s.isdigit() or s == ".", res["fee"]))) + + +def assert_transfer(cli, addr_a, addr_b, amt=1): + balance_a = cli.balance(addr_a) + balance_b = cli.balance(addr_b) + rsp = cli.transfer(addr_a, addr_b, f"{amt}{DEFAULT_DENOM}") + assert rsp["code"] == 0, rsp["raw_log"] + fee = find_fee(rsp) + assert cli.balance(addr_a) == balance_a - amt - fee + assert cli.balance(addr_b) == balance_b + amt + + +def denom_to_erc20_address(denom): + denom_hash = hashlib.sha256(denom.encode()).digest() + return to_checksum_address("0x" + denom_hash[-20:].hex()) + + +def escrow_address(port, channel): + escrow_addr_version = "ics20-1" + pre_image = f"{escrow_addr_version}\x00{port}/{channel}" + return eth_to_bech32(hashlib.sha256(pre_image.encode()).digest()[:20].hex()) + + +def ibc_denom_address(denom): + if not denom.startswith("ibc/"): + raise ValueError(f"coin {denom} does not have 'ibc/' prefix") + if len(denom) < 5 or denom[4:].strip() == "": + raise ValueError(f"coin {denom} is not a valid IBC voucher hash") + hash_part = denom[4:] # remove "ibc/" prefix + hash_bytes = binascii.unhexlify(hash_part) + return to_checksum_address("0x" + hash_bytes[-20:].hex()) + + +def retry_on_seq_mismatch(fn, *args, max_retries=3, **kwargs): + for attempt in range(max_retries): + rsp = fn(*args, **kwargs) + if rsp["code"] == 0: + return rsp + if rsp["code"] == 32 and "account sequence mismatch" in rsp["raw_log"]: + if attempt < max_retries - 1: + continue + return rsp + return rsp + + +def assert_create_tokenfactory_denom(cli, subdenom, is_legacy=False, **kwargs): + # check create tokenfactory denom + rsp = retry_on_seq_mismatch(cli.create_tokenfactory_denom, subdenom, **kwargs) + assert rsp["code"] == 0, rsp["raw_log"] + event = find_log_event_attrs( + rsp["events"], "create_denom", lambda attrs: "creator" in attrs + ) + sender = kwargs.get("_from") + rsp = cli.query_tokenfactory_denoms(sender) + denom = f"factory/{sender}/{subdenom}" + assert denom in rsp.get("denoms"), rsp + expected = {"creator": sender, "new_token_denom": denom} + erc20_address = None + if not is_legacy: + erc20_address = denom_to_erc20_address(denom) + expected["new_token_eth_addr"] = erc20_address + pair = cli.query_erc20_token_pair(denom) + assert pair == { + "erc20_address": erc20_address, + "denom": denom, + "enabled": True, + "contract_owner": "OWNER_MODULE", + } + assert expected.items() <= event.items() + meta = {"denom_units": [{"denom": denom}], "base": denom} + if not is_legacy: + # all missing metadata fields fixed in rc3 + meta["name"] = denom + meta["display"] = denom + meta["symbol"] = denom + assert meta.items() <= cli.query_bank_denom_metadata(denom).items() + _from = None if is_legacy else sender + rsp = cli.query_denom_authority_metadata(denom, _from=_from).get("Admin") + assert rsp == sender, rsp + return denom + + +def assert_mint_tokenfactory_denom(cli, denom, amt, is_legacy=False, **kwargs): + # check mint tokenfactory denom + sender = kwargs.get("_from") + balance = cli.balance(sender, denom) + coin = f"{amt}{denom}" + rsp = retry_on_seq_mismatch(cli.mint_tokenfactory_denom, coin, **kwargs) + assert rsp["code"] == 0, rsp["raw_log"] + if not is_legacy: + event = find_log_event_attrs( + rsp["events"], "tf_mint", lambda attrs: "mint_to_address" in attrs + ) + expected = { + "mint_to_address": sender, + "amount": coin, + } + assert expected.items() <= event.items() + current = cli.balance(sender, denom) + assert current == balance + amt + return current + + +def assert_transfer_tokenfactory_denom(cli, denom, receiver, amt, **kwargs): + # check transfer tokenfactory denom + sender = kwargs.get("_from") + balance = cli.balance(sender, denom) + rsp = cli.transfer(sender, receiver, f"{amt}{denom}") + assert rsp["code"] == 0, rsp["raw_log"] + current = cli.balance(sender, denom) + assert current == balance - amt + return current + + +def assert_burn_tokenfactory_denom(cli, denom, amt, **kwargs): + # check burn tokenfactory denom + sender = kwargs.get("_from") + balance = cli.balance(sender, denom) + coin = f"{amt}{denom}" + rsp = cli.burn_tokenfactory_denom(coin, **kwargs) + assert rsp["code"] == 0, rsp["raw_log"] + event = find_log_event_attrs( + rsp["events"], "tf_burn", lambda attrs: "burn_from_address" in attrs + ) + expected = { + "burn_from_address": sender, + "amount": coin, + } + assert expected.items() <= event.items() + current = cli.balance(sender, denom) + assert current == balance - amt + return current + + +def assert_set_tokenfactory_denom(cli, tmp_path, denom, **kwargs): + sender = kwargs.get("_from") + name = "Dubai" + symbol = "DLD" + meta = { + "description": name, + "denom_units": [{"denom": denom}, {"denom": symbol, "exponent": 6}], + "base": denom, + "display": symbol, + "name": name, + "symbol": symbol, + } + file_meta = Path(tmp_path) / "meta.json" + file_meta.write_text(json.dumps(meta)) + rsp = cli.set_tokenfactory_denom(file_meta, **kwargs) + assert rsp["code"] == 0, rsp["raw_log"] + assert cli.query_bank_denom_metadata(denom) == meta + rsp = cli.query_denom_authority_metadata(denom).get("Admin") + assert rsp == sender, rsp + + +def recover_community(cli, tmp_path): + return cli.create_account( + "community", + mnemonic=os.getenv("COMMUNITY_MNEMONIC"), + home=tmp_path, + )["address"] + + +def transfer_via_cosmos(cli, from_addr, to_addr, amount): + tx = cli.transfer( + from_addr, + to_addr, + f"{amount}{DEFAULT_DENOM}", + generate_only=True, + chain_id=cli.chain_id, + ) + tx_json = cli.sign_tx_json( + tx, from_addr, home=cli.data_dir, node=cli.node_rpc, chain_id=cli.chain_id + ) + rsp = cli.broadcast_tx_json(tx_json, home=cli.data_dir) + assert rsp["code"] == 0, rsp["raw_log"] + attrs = find_log_event_attrs(rsp["events"], "tx", lambda attrs: "fee" in attrs) + return int("".join(takewhile(lambda s: s.isdigit() or s == ".", attrs["fee"]))) + + +class ContractAddress(rlp.Serializable): + fields = [ + ("from", rlp.sedes.Binary()), + ("nonce", rlp.sedes.big_endian_int), + ] + + +def contract_address(addr, nonce): + return eth_utils.to_checksum_address( + eth_utils.to_hex( + eth_utils.keccak( + rlp.encode(ContractAddress(eth_utils.to_bytes(hexstr=addr), nonce)) + )[12:] + ) + ) + + +def build_batch_tx(w3, cli, txs, key=KEYS["community"]): + "return cosmos batch tx and eth tx hashes" + signed_txs = [sign_transaction(w3, tx, key) for tx in txs] + tmp_txs = [ + cli.build_evm_tx(f"0x{s.raw_transaction.hex()}", chain_id=EVM_CHAIN_ID) + for s in signed_txs + ] + + msgs = [tx["body"]["messages"][0] for tx in tmp_txs] + fee = sum(int(tx["auth_info"]["fee"]["amount"][0]["amount"]) for tx in tmp_txs) + gas_limit = sum(int(tx["auth_info"]["fee"]["gas_limit"]) for tx in tmp_txs) + + tx_hashes = [signed.hash for signed in signed_txs] + + # build batch cosmos tx + return { + "body": { + "messages": msgs, + "memo": "", + "timeout_height": "0", + "extension_options": [ + {"@type": "/cosmos.evm.vm.v1.ExtensionOptionsEthereumTx"} + ], + "non_critical_extension_options": [], + }, + "auth_info": { + "signer_infos": [], + "fee": { + "amount": [{"denom": "aom", "amount": str(fee)}], + "gas_limit": str(gas_limit), + "payer": "", + "granter": "", + }, + }, + "signatures": [], + }, tx_hashes + + +def approve_proposal(n, events, event_query_tx=False): + cli = n.cosmos_cli() + + # get proposal_id + ev = find_log_event_attrs( + events, "submit_proposal", lambda attrs: "proposal_id" in attrs + ) + proposal_id = ev["proposal_id"] + for i in range(len(n.config["validators"])): + rsp = n.cosmos_cli(i).gov_vote( + "validator", + proposal_id, + "yes", + event_query_tx, + gas_prices=f"{80 * DEFAULT_GAS_AMT}{DEFAULT_DENOM}", + ) + assert rsp["code"] == 0, rsp["raw_log"] + wait_for_new_blocks(cli, 1) + res = cli.query_tally(proposal_id) + res = res.get("tally") or res + assert ( + int(res["yes_count"]) == cli.staking_pool() + ), "all validators should have voted yes" + print("wait for proposal to be activated") + proposal = cli.query_proposal(proposal_id) + wait_for_block_time(cli, isoparse(proposal["voting_end_time"])) + proposal = cli.query_proposal(proposal_id) + assert proposal["status"] == "PROPOSAL_STATUS_PASSED", proposal + + +def submit_gov_proposal(evm, tmp_path, messages, **kwargs): + proposal = tmp_path / "proposal.json" + proposal_src = { + "title": "title", + "summary": "summary", + "deposit": f"1{DEFAULT_DENOM}", + "messages": messages, + } + proposal.write_text(json.dumps(proposal_src)) + rsp = evm.cosmos_cli().submit_gov_proposal(proposal, from_="community", **kwargs) + assert rsp["code"] == 0, rsp["raw_log"] + approve_proposal(evm, rsp["events"]) + print("check params have been updated now") + return rsp + + +def derive_new_account(n=1, mnemonic="SIGNER1_MNEMONIC"): + # derive a new address + account_path = f"m/44'/60'/0'/0/{n}" + return Account.from_mnemonic(os.getenv(mnemonic), account_path=account_path) + + +def derive_random_account(): + return derive_new_account(secrets.randbelow(10000) + 1) + + +def edit_ini_sections(chain_id, ini_path, callback): + ini = configparser.RawConfigParser() + ini.read(ini_path) + reg = re.compile(rf"^program:{chain_id}-node(\d+)") + for section in ini.sections(): + m = reg.match(section) + if m: + i = m.group(1) + old = ini[section] + ini[section].update(callback(i, old)) + with ini_path.open("w") as fp: + ini.write(fp) + + +def adjust_base_fee(parent_fee, gas_limit, gas_used, params): + "spec: https://eips.ethereum.org/EIPS/eip-1559#specification" + params = {k: float(v) for k, v in params.items()} + change_denominator = params.get("base_fee_change_denominator", 8) + elasticity_multiplier = params.get("elasticity_multiplier", 2) + gas_target = gas_limit // elasticity_multiplier + if gas_used == gas_target: + return parent_fee + delta = parent_fee * abs(gas_target - gas_used) // gas_target // change_denominator + # https://github.com/cosmos/evm/blob/0e511d32206b1ac709a0eb0ddb1aa21d29e833b8/x/feemarket/keeper/eip1559.go#L93 + if gas_target > gas_used: + min_gas_price = float(params.get("min_gas_price", 0)) * WEI_PER_DENOM + return max(parent_fee - delta, min_gas_price) + else: + return parent_fee + max(delta, 1) + + +def assert_duplicate(rpc, height): + res = requests.get(f"{rpc}/block_results?height={height}").json().get("result") + res = next((tx for tx in res.get("txs_results") if tx["code"] == 0), None) + values = set() + for event in res.get("events", []): + if event["type"] != "transfer": + continue + str = json.dumps(event) + assert str not in values, f"dup event find: {str}" + values.add(str) + + +def fund_acc(w3, acc, fund=4_000_000_000_000_000_000): + addr = acc.address + if w3.eth.get_balance(addr, "latest") == 0: + tx = {"to": addr, "value": fund, "gasPrice": w3.eth.gas_price} + send_transaction(w3, tx) + assert w3.eth.get_balance(addr, "latest") == fund + + +def do_multisig(cli, tmp_path, signer1_name, signer2_name, multisig_name): + # prepare multisig and accounts + signer1 = cli.address(signer1_name) + signer2 = cli.address(signer2_name) + cli.make_multisig(multisig_name, signer1_name, signer2_name) + multi_addr = cli.address(multisig_name) + amt = 4_000_000_000_000_000 // WEI_PER_DENOM + rsp = cli.transfer(signer1, multi_addr, f"{amt}{DEFAULT_DENOM}") + assert rsp["code"] == 0, rsp["raw_log"] + acc = cli.account(multi_addr) + res = cli.account_by_num(acc["account"]["value"]["account_number"]) + assert res["account_address"] == multi_addr + + m_txt = tmp_path / "m.txt" + p1_txt = tmp_path / "p1.txt" + p2_txt = tmp_path / "p2.txt" + tx_txt = tmp_path / "tx.txt" + amt = 1 + multi_tx = cli.transfer( + multi_addr, + signer2, + f"{amt}{DEFAULT_DENOM}", + generate_only=True, + ) + json.dump(multi_tx, m_txt.open("w")) + signature1 = cli.sign_multisig_tx(m_txt, multi_addr, signer1_name) + json.dump(signature1, p1_txt.open("w")) + signature2 = cli.sign_multisig_tx(m_txt, multi_addr, signer2_name) + json.dump(signature2, p2_txt.open("w")) + final_multi_tx = cli.combine_multisig_tx( + m_txt, + multisig_name, + p1_txt, + p2_txt, + ) + json.dump(final_multi_tx, tx_txt.open("w")) + rsp = cli.broadcast_tx(tx_txt) + assert rsp["code"] == 0, rsp["raw_log"] + assert cli.account(multi_addr)["account"]["value"]["address"] == multi_addr + + +def decode_base64(raw): + try: + return base64.b64decode(raw.encode()).decode() + except Exception: + return raw + + +def parse_events_rpc(events): + result = defaultdict(dict) + for ev in events: + for attr in ev["attributes"]: + if attr["key"] is None: + continue + key = decode_base64(attr["key"]) + if attr["value"] is not None: + value = decode_base64(attr["value"]) + else: + value = None + result[ev["type"]][key] = value + return result + + +async def assert_create_erc20_denom(w3, signer): + await ensure_create2_deployed(w3, signer) + await ensure_deployed_by_create2( + w3, signer, get_initcode(WETH9_ARTIFACT), salt=WETH_SALT + ) + assert (await ERC20.fns.decimals().call(w3, to=WETH_ADDRESS)) == 18 + total_bf = await ERC20.fns.totalSupply().call(w3, to=WETH_ADDRESS) + balance_bf = await ERC20.fns.balanceOf(signer).call(w3, to=WETH_ADDRESS) + assert total_bf == balance_bf + + weth = WETH(to=WETH_ADDRESS) + erc20_denom = f"erc20:{WETH_ADDRESS}" + deposit_amt = 100 + res = await weth.fns.deposit().transact(w3, signer, value=deposit_amt) + assert res.status == 1 + total = await ERC20.fns.totalSupply().call(w3, to=WETH_ADDRESS) + balance = await ERC20.fns.balanceOf(signer).call(w3, to=WETH_ADDRESS) + assert total == balance + assert (total - total_bf) == (balance - balance_bf) == deposit_amt + return erc20_denom, total + + +async def assert_weth_flow(w3, weth_addr, owner, account): + weth = WETH(to=weth_addr) + before = await balance_of(w3, ZERO_ADDRESS, owner) + receipt = await weth.fns.deposit().transact(w3, account, value=1000) + fee = receipt["effectiveGasPrice"] * receipt["gasUsed"] + await balance_of(w3, weth_addr, owner) == 1000 + receipt = await weth.fns.withdraw(1000).transact(w3, account) + fee += receipt["effectiveGasPrice"] * receipt["gasUsed"] + await balance_of(w3, weth_addr, owner) == 0 + assert await balance_of(w3, ZERO_ADDRESS, owner) == before - fee + assert await weth.fns.decimals().call(w3) == 18 + assert await weth.fns.symbol().call(w3) == "WETH" + assert await weth.fns.name().call(w3) == "Wrapped Ether" + + +def address_to_bytes32(addr) -> HexBytes: + return HexBytes(addr).rjust(32, b"\x00") + + +async def assert_tf_flow(w3, receiver, signer1, signer2, tf_erc20_addr): + # signer1 transfer 5tf_erc20 to receiver + transfer_amt = 5 + signer1_balance_bf = await ERC20.fns.balanceOf(signer1).call(w3, to=tf_erc20_addr) + signer2_balance_bf = await ERC20.fns.balanceOf(signer2).call(w3, to=tf_erc20_addr) + receiver_balance_bf = await ERC20.fns.balanceOf(receiver).call(w3, to=tf_erc20_addr) + await ERC20.fns.transfer(receiver, transfer_amt).transact( + w3, signer1, to=tf_erc20_addr, gasPrice=(await w3.eth.gas_price) + ) + signer1_balance = await ERC20.fns.balanceOf(signer1).call(w3, to=tf_erc20_addr) + assert signer1_balance == signer1_balance_bf - transfer_amt + signer1_balance_bf = signer1_balance + + receiver_balance = await ERC20.fns.balanceOf(receiver).call(w3, to=tf_erc20_addr) + assert receiver_balance == receiver_balance_bf + transfer_amt + receiver_balance_bf = receiver_balance + + # signer1 approve 2tf_erc20 to signer2 + approve_amt = 2 + await ERC20.fns.approve(signer2, approve_amt).transact( + w3, signer1, to=tf_erc20_addr, gasPrice=(await w3.eth.gas_price) + ) + allowance = await ERC20.fns.allowance(signer1, signer2).call(w3, to=tf_erc20_addr) + assert allowance == approve_amt + + # transferFrom signer1 to receiver via signer2 with 2tf_erc20 + await ERC20.fns.transferFrom(signer1, receiver, approve_amt).transact( + w3, signer2, to=tf_erc20_addr, gasPrice=(await w3.eth.gas_price) + ) + signer1_balance = await ERC20.fns.balanceOf(signer1).call(w3, to=tf_erc20_addr) + assert signer1_balance == signer1_balance_bf - approve_amt + signer1_balance_bf = signer1_balance + + signer2_balance = await ERC20.fns.balanceOf(signer2).call(w3, to=tf_erc20_addr) + assert signer2_balance == signer2_balance_bf + receiver_balance = await ERC20.fns.balanceOf(receiver).call(w3, to=tf_erc20_addr) + assert receiver_balance == receiver_balance_bf + approve_amt + receiver_balance_bf = receiver_balance + + +def edit_app_cfg(cli, i): + # Modify the json-rpc addresses to avoid conflict + cluster.edit_app_cfg( + cli.home(i) / "config/app.toml", + cli.base_port(i), + { + "json-rpc": { + "enable": True, + "address": "127.0.0.1:{EVMRPC_PORT}", + "ws-address": "127.0.0.1:{EVMRPC_PORT_WS}", + }, + }, + ) + + +def duration(duration_str): + mult = {"s": 1, "m": 60, "h": 3600, "d": 86400} + parts = re.findall(r"(\d+)([smhd])", duration_str.lower()) + return sum(int(value) * mult[unit] for value, unit in parts) diff --git a/tests/nix/default.nix b/tests/nix/default.nix new file mode 100644 index 000000000..ce6a8bd3b --- /dev/null +++ b/tests/nix/default.nix @@ -0,0 +1,18 @@ +{ + sources ? import ./sources.nix, + system ? builtins.currentSystem, + ... +}: +import sources.nixpkgs { + overlays = [ + (_: pkgs: { + flake-compat = import sources.flake-compat; + dapp = pkgs.dapp; + }) + (import "${sources.poetry2nix}/overlay.nix") + (_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; }) + (_: pkgs: { evmd = pkgs.callPackage ./evm/default.nix { }; }) + ]; + config = { }; + inherit system; +} diff --git a/tests/nix/sources.json b/tests/nix/sources.json new file mode 100644 index 000000000..bae3fc297 --- /dev/null +++ b/tests/nix/sources.json @@ -0,0 +1,63 @@ +{ + "flake-compat": { + "branch": "master", + "description": null, + "homepage": null, + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "sha256": "1qc703yg0babixi6wshn5wm2kgl5y1drcswgszh4xxzbrwkk9sv7", + "type": "tarball", + "url": "https://github.com/edolstra/flake-compat/archive/b4a34015c698c7793d592d66adbab377907a2be8.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "niv": { + "branch": "master", + "description": "Easy dependency management for Nix projects", + "homepage": "https://github.com/nmattia/niv", + "owner": "nmattia", + "repo": "niv", + "rev": "e0ca65c81a2d7a4d82a189f1e23a48d59ad42070", + "sha256": "1pq9nh1d8nn3xvbdny8fafzw87mj7gsmp6pxkdl65w2g18rmcmzx", + "type": "tarball", + "url": "https://github.com/nmattia/niv/archive/e0ca65c81a2d7a4d82a189f1e23a48d59ad42070.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "nixpkgs": { + "branch": "release-24.11", + "description": "Nix Packages collection", + "homepage": "", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "daa477e013dd736c939fcc111dc4dd889bc17c94", + "sha256": "1vbbl1iy5wxmwww8hi1ngcby6mnyzn7l5x9yxf58yd9z0nmx6p74", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/daa477e013dd736c939fcc111dc4dd889bc17c94.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "poetry2nix": { + "branch": "master", + "description": "Convert poetry projects to nix automagically [maintainer=@adisbladis] ", + "homepage": "", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d90f9db68a4bda31c346be16dfd8d3263be4547e", + "sha256": "0yfg51z8giwapc4kxxcrh47xr0zppwxiwaj7iyy6qsfd3a9649yz", + "type": "tarball", + "url": "https://github.com/nix-community/poetry2nix/archive/d90f9db68a4bda31c346be16dfd8d3263be4547e.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "dapptools": { + "branch": "master", + "description": "Dapp, Seth, Hevm, and more", + "homepage": "https://dapp.tools", + "owner": "dapphub", + "repo": "dapptools", + "rev": "a782a9dfcbf87756170c975c30e83339a99194b5", + "sha256": "sha256:0fsp4pvip77qjb3yciz2a3224ir8wvbb1snc851fbgmf34q7dqfi", + "type": "tarball", + "url": "https://github.com/dapphub/dapptools/archive/a782a9dfcbf87756170c975c30e83339a99194b5.tar.gz", + "url_template": "https://github.com///archive/.tar.gz", + "version": "hevm/0.49.0" + } +} \ No newline at end of file diff --git a/tests/nix/sources.nix b/tests/nix/sources.nix new file mode 100644 index 000000000..c420541d7 --- /dev/null +++ b/tests/nix/sources.nix @@ -0,0 +1,232 @@ +# This file has been generated by Niv. + +let + + # + # The fetchers. fetch_ fetches specs of type . + # + + fetch_file = + pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchurl { + inherit (spec) url sha256; + name = name'; + } + else + pkgs.fetchurl { + inherit (spec) url sha256; + name = name'; + }; + + fetch_tarball = + pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchTarball { + name = name'; + inherit (spec) url sha256; + } + else + pkgs.fetchzip { + name = name'; + inherit (spec) url sha256; + }; + + fetch_git = + name: spec: + let + ref = + if spec ? ref then + spec.ref + else if spec ? branch then + "refs/heads/${spec.branch}" + else if spec ? tag then + "refs/tags/${spec.tag}" + else + abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; + in + builtins.fetchGit { + url = spec.repo; + inherit (spec) rev; + inherit ref; + }; + + fetch_local = spec: spec.path; + + fetch_builtin-tarball = + name: + throw '' + [${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=tarball -a builtin=true''; + + fetch_builtin-url = + name: + throw '' + [${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=file -a builtin=true''; + + # + # Various helpers + # + + # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 + sanitizeName = + name: + (concatMapStrings (s: if builtins.isList s then "-" else s) ( + builtins.split "[^[:alnum:]+._?=-]+" ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) + )); + + # The set of packages used when specs are fetched using non-builtins. + mkPkgs = + sources: system: + let + sourcesNixpkgs = import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { + inherit system; + }; + hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; + hasThisAsNixpkgsPath = == ./.; + in + if builtins.hasAttr "nixpkgs" sources then + sourcesNixpkgs + else if hasNixpkgsPath && !hasThisAsNixpkgsPath then + import { } + else + abort '' + Please specify either (through -I or NIX_PATH=nixpkgs=...) or + add a package called "nixpkgs" to your sources.json. + ''; + + # The actual fetching function. + fetch = + pkgs: name: spec: + + if !builtins.hasAttr "type" spec then + abort "ERROR: niv spec ${name} does not have a 'type' attribute" + else if spec.type == "file" then + fetch_file pkgs name spec + else if spec.type == "tarball" then + fetch_tarball pkgs name spec + else if spec.type == "git" then + fetch_git name spec + else if spec.type == "local" then + fetch_local spec + else if spec.type == "builtin-tarball" then + fetch_builtin-tarball name + else if spec.type == "builtin-url" then + fetch_builtin-url name + else + abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; + + # If the environment variable NIV_OVERRIDE_${name} is set, then use + # the path directly as opposed to the fetched source. + replace = + name: drv: + let + saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; + ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; + in + if ersatz == "" then + drv + else + # this turns the string into an actual Nix path (for both absolute and + # relative paths) + if builtins.substring 0 1 ersatz == "/" then + /. + ersatz + else + /. + builtins.getEnv "PWD" + "/${ersatz}"; + + # Ports of functions for older nix versions + + # a Nix version of mapAttrs if the built-in doesn't exist + mapAttrs = + builtins.mapAttrs or ( + f: set: + with builtins; + listToAttrs ( + map (attr: { + name = attr; + value = f attr set.${attr}; + }) (attrNames set) + ) + ); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 + range = + first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 + stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 + stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); + concatMapStrings = f: list: concatStrings (map f list); + concatStrings = builtins.concatStringsSep ""; + + # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 + optionalAttrs = cond: as: if cond then as else { }; + + # fetchTarball version that is compatible between all the versions of Nix + builtins_fetchTarball = + { + url, + name ? null, + sha256, + }@attrs: + let + inherit (builtins) lessThan nixVersion fetchTarball; + in + if lessThan nixVersion "1.12" then + fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchTarball attrs; + + # fetchurl version that is compatible between all the versions of Nix + builtins_fetchurl = + { + url, + name ? null, + sha256, + }@attrs: + let + inherit (builtins) lessThan nixVersion fetchurl; + in + if lessThan nixVersion "1.12" then + fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchurl attrs; + + # Create the final "sources" from the config + mkSources = + config: + mapAttrs ( + name: spec: + if builtins.hasAttr "outPath" spec then + abort "The values in sources.json should not have an 'outPath' attribute" + else + spec // { outPath = replace name (fetch config.pkgs name spec); } + ) config.sources; + + # The "config" used by the fetchers + mkConfig = + { + sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null, + sources ? if isNull sourcesFile then { } else builtins.fromJSON (builtins.readFile sourcesFile), + system ? builtins.currentSystem, + pkgs ? mkPkgs sources system, + }: + rec { + # The sources, i.e. the attribute set of spec name to spec + inherit sources; + + # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers + inherit pkgs; + }; + +in +mkSources (mkConfig { }) // { __functor = _: settings: mkSources (mkConfig settings); } diff --git a/tests/nix/testenv.nix b/tests/nix/testenv.nix new file mode 100644 index 000000000..1604af435 --- /dev/null +++ b/tests/nix/testenv.nix @@ -0,0 +1,39 @@ +{ + poetry2nix, + lib, + python3, +}: +poetry2nix.mkPoetryEnv { + projectDir = ../integration_tests; + python = python3; + overrides = poetry2nix.overrides.withDefaults ( + self: super: + let + buildSystems = { + pystarport = [ "poetry-core" ]; + cprotobuf = [ + "setuptools" + "poetry-core" + ]; + durations = [ "setuptools" ]; + multitail2 = [ "setuptools" ]; + docker = [ + "hatchling" + "hatch-vcs" + ]; + flake8-black = [ "setuptools" ]; + flake8-isort = [ "hatchling" ]; + pytest-github-actions-annotate-failures = [ "setuptools" ]; + pyunormalize = [ "setuptools" ]; + typing-inspection = [ "hatchling" ]; + eth-bloom = [ "setuptools" ]; + }; + in + lib.mapAttrs ( + attr: systems: + super.${attr}.overridePythonAttrs (old: { + nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ map (a: self.${a}) systems; + }) + ) buildSystems + ); +} diff --git a/tests/scripts/env.template b/tests/scripts/env.template new file mode 100644 index 000000000..26905451e --- /dev/null +++ b/tests/scripts/env.template @@ -0,0 +1,19 @@ +export VALIDATOR1_MNEMONIC="visit craft resemble online window solution west chuckle music diesel vital settle comic tribe project blame bulb armed flower region sausage mercy arrive release" +export VALIDATOR2_MNEMONIC="direct travel shrug hand twice agent sail sell jump phone velvet pilot mango charge usual multiply orient garment bleak virtual action mention panda vast" +export VALIDATOR3_MNEMONIC="panda much deny whale fun iron liquid rookie rice ridge artist slush legend salad adapt public all thunder galaxy give ostrich endless prosper good" +export VALIDATOR4_MNEMONIC="echo embody public spot theory explain paddle layer bless finish method bread journey race couch deer image movie element rival clarify dice loan file" +export COMMUNITY_MNEMONIC="notable error gospel wave pair ugly measure elite toddler cost various fly make eye ketchup despair slab throw tribe swarm word fruit into inmate" +export SIGNER1_MNEMONIC="shed crumble dismiss loyal latin million oblige gesture shrug still oxygen custom remove ribbon disorder palace addict again blanket sad flock consider obey popular" +export SIGNER2_MNEMONIC="night renew tonight dinner shaft scheme domain oppose echo summer broccoli agent face guitar surface belt veteran siren poem alcohol menu custom crunch index" +export RECOVER_MNEMONIC="enrich fly eternal zone noodle aunt avoid loan pony cycle lady just nothing duck ketchup wet garment welcome unaware vocal ethics reject use impulse" +export RESERVE_MNEMONIC="tomato absent ritual fitness able doll sibling wife entry walnut claim recall breeze shell drive tape process aspect visual table rare evolve impose increase" +export RPC="http://127.0.0.1:26657" +export EVM_RPC="http://127.0.0.1:26651" +export EVM_RPC_WS="http://127.0.0.1:26652" +export CHAIN_ID="evm-canary-net-1" +export EVM_CHAIN_ID=262144 +export EVM_DENOM="atest" +export DEFAULT_GAS_AMT=10000000000 +export CMD="evmd" +export WEI_PER_DENOM=1 +export ADDRESS_PREFIX="cosmos" \ No newline at end of file diff --git a/tests/scripts/export_envs.sh b/tests/scripts/export_envs.sh new file mode 100755 index 000000000..e91535049 --- /dev/null +++ b/tests/scripts/export_envs.sh @@ -0,0 +1,41 @@ +#!/bin/bash +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +ENV_FILE="$SCRIPT_DIR/.env" + +export_envs() { + local env_file="${1:-$ENV_FILE}" + local envs_output="" + + if [[ ! -f "$env_file" ]]; then + echo "ERROR: Environment file $env_file not found" >&2 + exit 1 + fi + + while IFS= read -r line || [[ -n "$line" ]]; do + [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue + + line="${line#export }" + + [[ "$line" != *"="* ]] && continue + + key="${line%%=*}" + value="${line#*=}" + value="${value#\"}" + value="${value%\"}" + value="${value#\'}" + value="${value%\'}" + + if [[ -n "$envs_output" ]]; then + envs_output="$envs_output,$key=$value" + else + envs_output="$key=$value" + fi + + done < "$env_file" + echo "$envs_output" +} + +ENVS_STRING=$(export_envs "$ENV_FILE") +echo "$ENVS_STRING" diff --git a/tests/scripts/restore_envs.sh b/tests/scripts/restore_envs.sh new file mode 100755 index 000000000..daed854fe --- /dev/null +++ b/tests/scripts/restore_envs.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +echo $SCRIPT_DIR + +cd "$SCRIPT_DIR/../integration_tests" + +restore_env_file() { + local env_file="$SCRIPT_DIR/.env" + local env_template="$SCRIPT_DIR/env.template" + + if [[ -n "$ENVS" ]]; then + echo "Restoring .env from ENVS secret" + IFS=',' read -ra ADDR <<< "$ENVS" + for kv in "${ADDR[@]}"; do + key="${kv%%=*}" + val="${kv#*=}" + echo "export $key=\"$val\"" + done > "$env_file" + echo "Environment file restored from ENVS secret" + elif [[ ! -f "$env_file" ]]; then + if [[ -f "$env_template" ]]; then + echo "No ENVS secret found and no .env file exists, copying from template" + cp "$env_template" "$env_file" + else + echo "ERROR: Neither ENVS secret nor env.template found" >&2 + exit 1 + fi + else + echo "Using existing .env file" + fi +} + +restore_env_file diff --git a/tests/scripts/run-integration-tests.sh b/tests/scripts/run-integration-tests.sh new file mode 100755 index 000000000..ee95d4a97 --- /dev/null +++ b/tests/scripts/run-integration-tests.sh @@ -0,0 +1,49 @@ +#!/bin/bash +set -e + +# explicitly set a short TMPDIR to prevent path too long issue on macosx +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +export TMPDIR=/tmp + +cd "$SCRIPT_DIR/../integration_tests" + +TESTS_TO_RUN="${TESTS_TO_RUN:-all}" +CHAIN_CONFIG="${CHAIN_CONFIG:-}" + +# pytest command with chain-config +build_pytest_cmd() { + local base_cmd="$1" + if [[ -n "$CHAIN_CONFIG" ]]; then + echo "$base_cmd --chain-config $CHAIN_CONFIG" + else + echo "$base_cmd" + fi +} + +load_env_file() { + local env_file="$1" + if [ -f "$env_file" ]; then + echo "Loading environment variables from $(basename "$env_file")" + set -a + source "$env_file" + set +a + else + echo "ERROR: $(basename "$env_file") not found. Please create it from $(basename "$env_file").template." >&2 + exit 1 + fi +} + +load_env_file "$SCRIPT_DIR/.env" + +if [[ "$TESTS_TO_RUN" == "all" ]]; then + echo "run all local tests" + cmd=$(build_pytest_cmd "pytest -s -vvv -m \"not connect\"") +elif [[ "$TESTS_TO_RUN" == "connect" ]]; then + echo "run tests matching $TESTS_TO_RUN" + cmd=$(build_pytest_cmd "pytest -vv -s -m connect") +else + echo "run tests matching $TESTS_TO_RUN" + cmd=$(build_pytest_cmd "pytest -vv -s -m \"$TESTS_TO_RUN\"") +fi + +eval $cmd \ No newline at end of file From 4cdfe91f51ef249098546c28ab35d9cf54a151ff Mon Sep 17 00:00:00 2001 From: mmsqe Date: Tue, 28 Oct 2025 14:34:23 +0800 Subject: [PATCH 02/22] add evmd rm dapp --- tests/integration_tests/shell.nix | 2 +- tests/nix/default.nix | 1 - tests/nix/evm/default.nix | 82 +++++++++++++++++++++++++++++++ tests/nix/sources.json | 13 ----- 4 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 tests/nix/evm/default.nix diff --git a/tests/integration_tests/shell.nix b/tests/integration_tests/shell.nix index b299bbf48..c0a1543b9 100644 --- a/tests/integration_tests/shell.nix +++ b/tests/integration_tests/shell.nix @@ -8,7 +8,7 @@ pkgs.mkShell { pkgs.test-env pkgs.poetry pkgs.solc - # pkgs.evmd + pkgs.evmd ]; shellHook = '' export TMPDIR=/tmp diff --git a/tests/nix/default.nix b/tests/nix/default.nix index ce6a8bd3b..c21d1f211 100644 --- a/tests/nix/default.nix +++ b/tests/nix/default.nix @@ -7,7 +7,6 @@ import sources.nixpkgs { overlays = [ (_: pkgs: { flake-compat = import sources.flake-compat; - dapp = pkgs.dapp; }) (import "${sources.poetry2nix}/overlay.nix") (_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; }) diff --git a/tests/nix/evm/default.nix b/tests/nix/evm/default.nix new file mode 100644 index 000000000..effe86905 --- /dev/null +++ b/tests/nix/evm/default.nix @@ -0,0 +1,82 @@ +{ + lib, + stdenv, + buildGo123Module, + fetchFromGitHub, + rev ? "dirty", + nativeByteOrder ? true, # nativeByteOrder mode will panic on big endian machines + fetchurl, + pkgsStatic, +}: +let + version = "v0.5.0"; + pname = "evmd"; + + # Use static packages for Linux to ensure musl compatibility + buildPackages = if stdenv.isLinux then pkgsStatic else { inherit stdenv buildGo123Module; }; + buildStdenv = buildPackages.stdenv; + buildGo123Module' = if stdenv.isLinux then buildPackages.buildGo123Module else buildGo123Module; + + tags = + [ + "ledger" + "netgo" + "osusergo" + "pebbledb" + ] + ++ lib.optionals nativeByteOrder [ "nativebyteorder" ] + ++ lib.optionals buildStdenv.isLinux [ "muslc" ]; + + ldflags = + [ + "-X github.com/cosmos/cosmos-sdk/version.Name=evmd" + "-X github.com/cosmos/cosmos-sdk/version.AppName=${pname}" + "-X github.com/cosmos/cosmos-sdk/version.Version=${version}" + "-X github.com/cosmos/cosmos-sdk/version.BuildTags=${lib.concatStringsSep "," tags}" + "-X github.com/cosmos/cosmos-sdk/version.Commit=${rev}" + ] + ++ [ + "-w" + "-s" + "-linkmode=external" + ] + ++ lib.optionals buildStdenv.isLinux [ + "-extldflags '-static -lm'" + ]; + +in +buildGo123Module' rec { + inherit + pname + version + tags + ldflags + ; + stdenv = buildStdenv; + src = fetchFromGitHub { + owner = "cosmos"; + repo = "evm"; + rev = "733ea6190eb1be15ed1276ab54f4a8b511ff1c66"; + hash = "sha256-mZQhW6CpIUGPj3WWw5v2Zeov1mMnKx+ZqNX3YcFOcVE="; + }; + + vendorHash = "sha256-IDJHj2e2LBMe0BtwduG7/wLM/C2rRQyIUpbMawJAilk="; + proxyVendor = true; + sourceRoot = "source/evmd"; + subPackages = [ "cmd/evmd" ]; + CGO_ENABLED = "1"; + + preBuild = '' + mkdir -p $TMPDIR/lib + export CGO_LDFLAGS="-L$TMPDIR/lib $CGO_LDFLAGS" + ''; + + doCheck = false; + meta = with lib; { + description = "An EVM compatible framework for blockchain development with the Cosmos SDK"; + homepage = "https://github.com/cosmos/evm"; + license = licenses.asl20; + mainProgram = "evmd" + buildStdenv.hostPlatform.extensions.executable; + platforms = platforms.all; + }; +} \ No newline at end of file diff --git a/tests/nix/sources.json b/tests/nix/sources.json index bae3fc297..38e06b72a 100644 --- a/tests/nix/sources.json +++ b/tests/nix/sources.json @@ -46,18 +46,5 @@ "type": "tarball", "url": "https://github.com/nix-community/poetry2nix/archive/d90f9db68a4bda31c346be16dfd8d3263be4547e.tar.gz", "url_template": "https://github.com///archive/.tar.gz" - }, - "dapptools": { - "branch": "master", - "description": "Dapp, Seth, Hevm, and more", - "homepage": "https://dapp.tools", - "owner": "dapphub", - "repo": "dapptools", - "rev": "a782a9dfcbf87756170c975c30e83339a99194b5", - "sha256": "sha256:0fsp4pvip77qjb3yciz2a3224ir8wvbb1snc851fbgmf34q7dqfi", - "type": "tarball", - "url": "https://github.com/dapphub/dapptools/archive/a782a9dfcbf87756170c975c30e83339a99194b5.tar.gz", - "url_template": "https://github.com///archive/.tar.gz", - "version": "hevm/0.49.0" } } \ No newline at end of file From 9271a381b0b7a18262483d1bc099706b61f12ede Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 6 Nov 2025 09:32:27 +0800 Subject: [PATCH 03/22] go 1.25 --- tests/nix/default.nix | 4 ++++ tests/nix/evm/default.nix | 21 +++++++++++++-------- tests/nix/go_1_25.nix | 14 ++++++++++++++ tests/nix/sources.json | 6 +++--- 4 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 tests/nix/go_1_25.nix diff --git a/tests/nix/default.nix b/tests/nix/default.nix index c21d1f211..ebf262b51 100644 --- a/tests/nix/default.nix +++ b/tests/nix/default.nix @@ -11,6 +11,10 @@ import sources.nixpkgs { (import "${sources.poetry2nix}/overlay.nix") (_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; }) (_: pkgs: { evmd = pkgs.callPackage ./evm/default.nix { }; }) + (_: pkgs: { + go_1_25 = pkgs.callPackage ./go_1_25.nix { }; + evmd = pkgs.callPackage ./evm/default.nix { }; + }) ]; config = { }; inherit system; diff --git a/tests/nix/evm/default.nix b/tests/nix/evm/default.nix index effe86905..b8b3dcc98 100644 --- a/tests/nix/evm/default.nix +++ b/tests/nix/evm/default.nix @@ -1,7 +1,8 @@ { lib, stdenv, - buildGo123Module, + buildGoModule, + go_1_25, fetchFromGitHub, rev ? "dirty", nativeByteOrder ? true, # nativeByteOrder mode will panic on big endian machines @@ -13,9 +14,11 @@ let pname = "evmd"; # Use static packages for Linux to ensure musl compatibility - buildPackages = if stdenv.isLinux then pkgsStatic else { inherit stdenv buildGo123Module; }; + buildPackages = if stdenv.isLinux then pkgsStatic else { inherit stdenv; buildGoModule = buildGoModule.override { go = go_1_25; }; }; buildStdenv = buildPackages.stdenv; - buildGo123Module' = if stdenv.isLinux then buildPackages.buildGo123Module else buildGo123Module; + buildGoModule' = if stdenv.isLinux + then (buildPackages.buildGoModule.override { go = go_1_25; }) + else (buildGoModule.override { go = go_1_25; }); tags = [ @@ -25,6 +28,7 @@ let "pebbledb" ] ++ lib.optionals nativeByteOrder [ "nativebyteorder" ] + ++ lib.optionals buildStdenv.isDarwin [ "static_wasm" ] ++ lib.optionals buildStdenv.isLinux [ "muslc" ]; ldflags = @@ -45,7 +49,7 @@ let ]; in -buildGo123Module' rec { + buildGoModule' rec { inherit pname version @@ -56,19 +60,20 @@ buildGo123Module' rec { src = fetchFromGitHub { owner = "cosmos"; repo = "evm"; - rev = "733ea6190eb1be15ed1276ab54f4a8b511ff1c66"; - hash = "sha256-mZQhW6CpIUGPj3WWw5v2Zeov1mMnKx+ZqNX3YcFOcVE="; + rev = "79bcc14fefa4b5c82386a3fb0724c3f9a7688ba5"; + hash = "sha256-QoQR7VBkAUMTj9M4qbAK76avjgiyH8htUeFFggVDExA="; }; - vendorHash = "sha256-IDJHj2e2LBMe0BtwduG7/wLM/C2rRQyIUpbMawJAilk="; + vendorHash = "sha256-DO9SS1c5p9hSMR2M+bCxci/kdjpN7a9TZhMZhq2Efag="; proxyVendor = true; sourceRoot = "source/evmd"; subPackages = [ "cmd/evmd" ]; - CGO_ENABLED = "1"; preBuild = '' mkdir -p $TMPDIR/lib + export CGO_ENABLED=1 export CGO_LDFLAGS="-L$TMPDIR/lib $CGO_LDFLAGS" + export GOTOOLCHAIN=local ''; doCheck = false; diff --git a/tests/nix/go_1_25.nix b/tests/nix/go_1_25.nix new file mode 100644 index 000000000..3b7832da7 --- /dev/null +++ b/tests/nix/go_1_25.nix @@ -0,0 +1,14 @@ +{ pkgs }: + +let + nixpkgs-unstable = builtins.fetchTarball { + url = "https://github.com/NixOS/nixpkgs/archive/7241bcbb4f099a66aafca120d37c65e8dda32717.tar.gz"; + sha256 = "1awaf4s01snazyvy7s788m47dzc7k4vd8hj1ikxfvrrgpa1w03k2"; + }; + + unstable = import nixpkgs-unstable { + system = pkgs.system; + config = {}; + }; +in + unstable.go_1_25 or pkgs.go_1_23 diff --git a/tests/nix/sources.json b/tests/nix/sources.json index 38e06b72a..8327ef635 100644 --- a/tests/nix/sources.json +++ b/tests/nix/sources.json @@ -29,10 +29,10 @@ "homepage": "", "owner": "NixOS", "repo": "nixpkgs", - "rev": "daa477e013dd736c939fcc111dc4dd889bc17c94", - "sha256": "1vbbl1iy5wxmwww8hi1ngcby6mnyzn7l5x9yxf58yd9z0nmx6p74", + "rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674", + "sha256": "1s2gr5rcyqvpr58vxdcb095mdhblij9bfzaximrva2243aal3dgx", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/daa477e013dd736c939fcc111dc4dd889bc17c94.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/50ab793786d9de88ee30ec4e4c24fb4236fc2674.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "poetry2nix": { From 567b55a8facbe48dd07272ad7e95ecd543d6bb4e Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 6 Nov 2025 09:32:31 +0800 Subject: [PATCH 04/22] build src --- tests/nix/evm/default.nix | 22 ++++++++++++---------- tests/nix/go_1_25.nix | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/nix/evm/default.nix b/tests/nix/evm/default.nix index b8b3dcc98..0d647911d 100644 --- a/tests/nix/evm/default.nix +++ b/tests/nix/evm/default.nix @@ -57,23 +57,25 @@ in ldflags ; stdenv = buildStdenv; - src = fetchFromGitHub { - owner = "cosmos"; - repo = "evm"; - rev = "79bcc14fefa4b5c82386a3fb0724c3f9a7688ba5"; - hash = "sha256-QoQR7VBkAUMTj9M4qbAK76avjgiyH8htUeFFggVDExA="; - }; - vendorHash = "sha256-DO9SS1c5p9hSMR2M+bCxci/kdjpN7a9TZhMZhq2Efag="; + src = lib.sourceByRegex ../../.. [ + "^(evmd|ante|api|client|crypto|encoding|ethereum|ibc|indexer|mempool|metrics|precompiles|proto|rpc|server|testutil|utils|version|wallets|x|eips|contracts|go.mod|go.sum|interfaces.go)($|/.*)" + "^tests(/.*[.]go)?$" + ]; + + vendorHash = null; proxyVendor = true; - sourceRoot = "source/evmd"; + + setSourceRoot = '' + export sourceRoot=$(find . -maxdepth 2 -name "evmd" -type d | head -1) + echo "evmd at: $sourceRoot" + ''; subPackages = [ "cmd/evmd" ]; - preBuild = '' mkdir -p $TMPDIR/lib export CGO_ENABLED=1 export CGO_LDFLAGS="-L$TMPDIR/lib $CGO_LDFLAGS" - export GOTOOLCHAIN=local + export GOPROXY=https://proxy.golang.org,direct ''; doCheck = false; diff --git a/tests/nix/go_1_25.nix b/tests/nix/go_1_25.nix index 3b7832da7..06064b2e0 100644 --- a/tests/nix/go_1_25.nix +++ b/tests/nix/go_1_25.nix @@ -11,4 +11,4 @@ let config = {}; }; in - unstable.go_1_25 or pkgs.go_1_23 + unstable.go_1_25 From 8214693be3479fb2a4407fe731f9ed00e0f553d4 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 6 Nov 2025 16:49:08 +0800 Subject: [PATCH 05/22] more test --- .gitmodules | 3 + Makefile | 6 + tests/integration_tests/.flake8 | 4 + .../configs/accounts.jsonnet | 15 + .../integration_tests/configs/chains.jsonnet | 2 +- .../integration_tests/configs/default.jsonnet | 9 +- .../integration_tests/configs/exploit.jsonnet | 12 + .../configs/fee-history.jsonnet | 17 + tests/integration_tests/configs/ibc.jsonnet | 36 + .../configs/ibc_common.jsonnet | 22 + .../configs/min_gas_price.jsonnet | 30 + .../configs/min_gas_price_eq.jsonnet | 15 + .../configs/min_gas_price_lte.jsonnet | 16 + .../configs/rly_chain.jsonnet | 20 + .../configs/rly_common.jsonnet | 24 + .../integration_tests/configs/staking.jsonnet | 15 + tests/integration_tests/contracts/.gitignore | 1 + .../contracts/common/Types.sol | 1 + .../contracts/contracts/BurnGas.sol | 14 + .../contracts/CounterWithCallbacks.sol | 115 +++ .../contracts/contracts/DistributionI.sol | 1 + .../contracts/ERC20MinterBurnerDecimals.sol | 125 ++++ .../contracts/contracts/Greeter.sol | 26 + .../contracts/contracts/ICallbacks.sol | 1 + .../contracts/contracts/MockERC20.json | 1 + .../contracts/contracts/Multicall3Router.json | 1 + .../contracts/contracts/MyToken.sol | 33 + .../contracts/contracts/MyToken2.sol | 10 + .../contracts/contracts/Random.sol | 8 + .../contracts/contracts/StakingI.sol | 1 + .../contracts/TestBlockTxProperties.sol | 8 + .../contracts/contracts/TestERC20A.sol | 18 + .../contracts/TestExploitContract.sol | 10 + .../contracts/contracts/TestMessageCall.sol | 30 + .../contracts/contracts/TestRevert.sol | 31 + .../contracts/contracts/WETH9.sol | 73 ++ .../openzeppelin-contracts-upgradeable | 1 + .../contracts/remappings.txt | 2 + tests/integration_tests/expected_constants.py | 27 + tests/integration_tests/ibc_utils.py | 140 ++++ tests/integration_tests/network.py | 9 +- tests/integration_tests/poetry.lock | 56 +- tests/integration_tests/pyproject.toml | 5 +- tests/integration_tests/test_account.py | 34 +- tests/integration_tests/test_basic.py | 499 +++++++++++++ tests/integration_tests/test_call.py | 181 +++++ tests/integration_tests/test_contract.py | 422 +++++++++++ .../test_debug_traceblock.py | 67 ++ tests/integration_tests/test_distribution.py | 114 +++ .../test_distribution_precompile.py | 140 ++++ tests/integration_tests/test_eip1559.py | 113 +++ tests/integration_tests/test_erc20.py | 42 ++ tests/integration_tests/test_estimate_gas.py | 48 ++ tests/integration_tests/test_exploit.py | 101 +++ tests/integration_tests/test_fee_history.py | 224 ++++++ tests/integration_tests/test_filters.py | 131 ++++ tests/integration_tests/test_gas.py | 63 ++ tests/integration_tests/test_ibc.py | 234 +++++++ tests/integration_tests/test_min_gas_price.py | 123 ++++ tests/integration_tests/test_permission.py | 82 +++ tests/integration_tests/test_precompile.py | 654 ++++++++++++++++++ tests/integration_tests/test_priority.py | 242 +++++++ tests/integration_tests/test_staking.py | 172 +++++ .../test_staking_precompile.py | 289 ++++++++ tests/integration_tests/test_subscribe.py | 170 +++++ tests/integration_tests/test_tracers.py | 154 +++++ tests/integration_tests/utils.py | 480 ++++--------- tests/nix/sources.json | 25 + tests/nix/testenv.nix | 63 +- tests/pytest.ini | 4 + 70 files changed, 5492 insertions(+), 373 deletions(-) create mode 100644 tests/integration_tests/.flake8 create mode 100644 tests/integration_tests/configs/accounts.jsonnet create mode 100644 tests/integration_tests/configs/exploit.jsonnet create mode 100644 tests/integration_tests/configs/fee-history.jsonnet create mode 100644 tests/integration_tests/configs/ibc.jsonnet create mode 100644 tests/integration_tests/configs/ibc_common.jsonnet create mode 100644 tests/integration_tests/configs/min_gas_price.jsonnet create mode 100644 tests/integration_tests/configs/min_gas_price_eq.jsonnet create mode 100644 tests/integration_tests/configs/min_gas_price_lte.jsonnet create mode 100644 tests/integration_tests/configs/rly_chain.jsonnet create mode 100644 tests/integration_tests/configs/rly_common.jsonnet create mode 100644 tests/integration_tests/configs/staking.jsonnet create mode 100644 tests/integration_tests/contracts/.gitignore create mode 120000 tests/integration_tests/contracts/common/Types.sol create mode 100644 tests/integration_tests/contracts/contracts/BurnGas.sol create mode 100644 tests/integration_tests/contracts/contracts/CounterWithCallbacks.sol create mode 120000 tests/integration_tests/contracts/contracts/DistributionI.sol create mode 100644 tests/integration_tests/contracts/contracts/ERC20MinterBurnerDecimals.sol create mode 100644 tests/integration_tests/contracts/contracts/Greeter.sol create mode 120000 tests/integration_tests/contracts/contracts/ICallbacks.sol create mode 100644 tests/integration_tests/contracts/contracts/MockERC20.json create mode 100644 tests/integration_tests/contracts/contracts/Multicall3Router.json create mode 100644 tests/integration_tests/contracts/contracts/MyToken.sol create mode 100644 tests/integration_tests/contracts/contracts/MyToken2.sol create mode 100644 tests/integration_tests/contracts/contracts/Random.sol create mode 120000 tests/integration_tests/contracts/contracts/StakingI.sol create mode 100644 tests/integration_tests/contracts/contracts/TestBlockTxProperties.sol create mode 100644 tests/integration_tests/contracts/contracts/TestERC20A.sol create mode 100644 tests/integration_tests/contracts/contracts/TestExploitContract.sol create mode 100644 tests/integration_tests/contracts/contracts/TestMessageCall.sol create mode 100644 tests/integration_tests/contracts/contracts/TestRevert.sol create mode 100644 tests/integration_tests/contracts/contracts/WETH9.sol create mode 160000 tests/integration_tests/contracts/openzeppelin-contracts-upgradeable create mode 100644 tests/integration_tests/contracts/remappings.txt create mode 100644 tests/integration_tests/expected_constants.py create mode 100644 tests/integration_tests/ibc_utils.py create mode 100644 tests/integration_tests/test_basic.py create mode 100644 tests/integration_tests/test_call.py create mode 100644 tests/integration_tests/test_contract.py create mode 100644 tests/integration_tests/test_debug_traceblock.py create mode 100644 tests/integration_tests/test_distribution.py create mode 100644 tests/integration_tests/test_distribution_precompile.py create mode 100644 tests/integration_tests/test_eip1559.py create mode 100644 tests/integration_tests/test_erc20.py create mode 100644 tests/integration_tests/test_estimate_gas.py create mode 100644 tests/integration_tests/test_exploit.py create mode 100644 tests/integration_tests/test_fee_history.py create mode 100644 tests/integration_tests/test_filters.py create mode 100644 tests/integration_tests/test_gas.py create mode 100644 tests/integration_tests/test_ibc.py create mode 100644 tests/integration_tests/test_min_gas_price.py create mode 100644 tests/integration_tests/test_permission.py create mode 100644 tests/integration_tests/test_precompile.py create mode 100644 tests/integration_tests/test_priority.py create mode 100644 tests/integration_tests/test_staking.py create mode 100644 tests/integration_tests/test_staking_precompile.py create mode 100644 tests/integration_tests/test_subscribe.py create mode 100644 tests/integration_tests/test_tracers.py create mode 100644 tests/pytest.ini diff --git a/.gitmodules b/.gitmodules index 5262fb41c..68a14e116 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,3 +34,6 @@ [submodule "tests/evm-tools-compatibility/foundry/lib/forge-std"] path = tests/evm-tools-compatibility/foundry/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "tests/integration_tests/contracts/openzeppelin-contracts-upgradeable"] + path = tests/integration_tests/contracts/openzeppelin-contracts-upgradeable + url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable.git diff --git a/Makefile b/Makefile index 0c84679bc..e5183b399 100644 --- a/Makefile +++ b/Makefile @@ -239,6 +239,12 @@ lint-fix: lint-fix-contracts: solhint --fix contracts/**/*.sol +lint-py: + flake8 --show-source --count --statistics \ + --format="::error file=%(path)s,line=%(row)d,col=%(col)d::%(path)s:%(row)d:%(col)d: %(code)s %(text)s" \ + --exclude=tests/integration_tests/contracts \ + tests/integration_tests/ + .PHONY: lint lint-fix lint-contracts lint-go lint-python format: format-go format-python format-shell diff --git a/tests/integration_tests/.flake8 b/tests/integration_tests/.flake8 new file mode 100644 index 000000000..e4ccbbbd5 --- /dev/null +++ b/tests/integration_tests/.flake8 @@ -0,0 +1,4 @@ +[flake8] +max-line-length = 88 +extend-ignore = E203 +exclude = .git,__pycache__,./integration_tests/contracts diff --git a/tests/integration_tests/configs/accounts.jsonnet b/tests/integration_tests/configs/accounts.jsonnet new file mode 100644 index 000000000..1c216a0a6 --- /dev/null +++ b/tests/integration_tests/configs/accounts.jsonnet @@ -0,0 +1,15 @@ +local config = import 'default.jsonnet'; +local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; + +config { + 'evm-canary-net-1'+: { + accounts: super.accounts[:std.length(super.accounts) - 1] + [ + { + 'coin-type': 60, + name: 'user' + i, + coins: '100000000000000000' + chain.evm_denom, + } + for i in std.range(0, 5) + ], + }, +} diff --git a/tests/integration_tests/configs/chains.jsonnet b/tests/integration_tests/configs/chains.jsonnet index 6461d4b4c..b23ecd99f 100644 --- a/tests/integration_tests/configs/chains.jsonnet +++ b/tests/integration_tests/configs/chains.jsonnet @@ -27,7 +27,7 @@ feemarket: { params: { base_fee: '1000000000', - min_gas_price: '0', + min_gas_price: '1000000000', }, }, }, diff --git a/tests/integration_tests/configs/default.jsonnet b/tests/integration_tests/configs/default.jsonnet index 47ca6325e..87051a77e 100644 --- a/tests/integration_tests/configs/default.jsonnet +++ b/tests/integration_tests/configs/default.jsonnet @@ -1,4 +1,5 @@ local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; +local gas_price = 1000000000; { dotenv: '../../scripts/.env', @@ -39,13 +40,13 @@ local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; 'coin-type': 60, coins: '100000000000000000000' + chain.evm_denom, staked: '10000000000000000000' + chain.evm_denom, - gas_prices: '0.01' + chain.evm_denom, + gas_prices: gas_price + chain.evm_denom, mnemonic: '${VALIDATOR1_MNEMONIC}', }, { 'coin-type': 60, coins: '100000000000000000000' + chain.evm_denom, staked: '10000000000000000000' + chain.evm_denom, - gas_prices: '0.01' + chain.evm_denom, + gas_prices: gas_price + chain.evm_denom, mnemonic: '${VALIDATOR2_MNEMONIC}', config: { db_backend: 'pebbledb', @@ -57,7 +58,7 @@ local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; 'coin-type': 60, coins: '100000000000000000000' + chain.evm_denom, staked: '10000000000000000000' + chain.evm_denom, - gas_prices: '0.01' + chain.evm_denom, + gas_prices: gas_price + chain.evm_denom, mnemonic: '${VALIDATOR3_MNEMONIC}', config: { db_backend: 'goleveldb', @@ -106,6 +107,8 @@ local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; evm_denom: chain.evm_denom, active_static_precompiles: [ '0x0000000000000000000000000000000000000800', + '0x0000000000000000000000000000000000000801', + '0x0000000000000000000000000000000000000805', '0x0000000000000000000000000000000000000807', ], }, diff --git a/tests/integration_tests/configs/exploit.jsonnet b/tests/integration_tests/configs/exploit.jsonnet new file mode 100644 index 000000000..f48c97b22 --- /dev/null +++ b/tests/integration_tests/configs/exploit.jsonnet @@ -0,0 +1,12 @@ +local config = import 'default.jsonnet'; + +config { + 'evm-canary-net-1'+: { + 'app-config'+: { + 'json-rpc'+: { + 'batch-request-limit': 2, + 'batch-response-max-size': 7188483, // memory_byte_size - 1 + }, + }, + }, +} diff --git a/tests/integration_tests/configs/fee-history.jsonnet b/tests/integration_tests/configs/fee-history.jsonnet new file mode 100644 index 000000000..fb164bdd9 --- /dev/null +++ b/tests/integration_tests/configs/fee-history.jsonnet @@ -0,0 +1,17 @@ +local config = import 'default.jsonnet'; + +config { + 'evm-canary-net-1'+: { + genesis+: { + app_state+: { + feemarket+: { + params+: { + elasticity_multiplier: 3, + base_fee_change_denominator: 100000000, + // min_gas_price: '0.000000000000000000', # TODO: remove after basefee fix + }, + }, + }, + }, + }, +} diff --git a/tests/integration_tests/configs/ibc.jsonnet b/tests/integration_tests/configs/ibc.jsonnet new file mode 100644 index 000000000..7c039b499 --- /dev/null +++ b/tests/integration_tests/configs/ibc.jsonnet @@ -0,0 +1,36 @@ +local config = import 'default.jsonnet'; +local rly_chain = import 'rly_chain.jsonnet'; +local rly_common = import 'rly_common.jsonnet'; +local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; +local basic = config['evm-canary-net-1']; +local ibc_common = import 'ibc_common.jsonnet'; + +config { + 'evm-canary-net-1'+: ibc_common { + key_name: 'signer2', + 'account-prefix': chain['account-prefix'], + }, + 'evm-canary-net-2'+: basic + ibc_common { + key_name: 'signer1', + 'account-prefix': chain['account-prefix'], + validators: [validator { + base_port: 26800 + i * 10, + } for i in std.range(0, std.length(super.validators) - 1) for validator in [super.validators[i]]], + }, + relayer: rly_common { + chains: [ + rly_chain { + id: 'evm-canary-net-1', + gas_price+: { + denom: chain.evm_denom, + }, + }, + rly_chain { + id: 'evm-canary-net-2', + gas_price+: { + denom: chain.evm_denom, + }, + }, + ], + }, +} diff --git a/tests/integration_tests/configs/ibc_common.jsonnet b/tests/integration_tests/configs/ibc_common.jsonnet new file mode 100644 index 000000000..803d99d72 --- /dev/null +++ b/tests/integration_tests/configs/ibc_common.jsonnet @@ -0,0 +1,22 @@ +{ + 'coin-type': 60, + 'app-config'+: { + 'index-events': super['index-events'] + ['message.action'], + }, + genesis+: { + app_state+: { + feemarket+: { + params+: { + no_base_fee: true, + base_fee: '0', + min_gas_price: '0', + }, + }, + staking+: { + params+: { + unbonding_time: '1814400s', + }, + }, + }, + }, +} diff --git a/tests/integration_tests/configs/min_gas_price.jsonnet b/tests/integration_tests/configs/min_gas_price.jsonnet new file mode 100644 index 000000000..ad731449f --- /dev/null +++ b/tests/integration_tests/configs/min_gas_price.jsonnet @@ -0,0 +1,30 @@ +local config = import 'default.jsonnet'; +local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; +local gas_price = 10000000000000; + +config { + 'evm-canary-net-1'+: { + validators: [validator { + gas_prices: gas_price + chain.evm_denom, + } for validator in super.validators], + genesis+: { + consensus+: { + params+: { + block+: { + max_gas+: '81500000', + }, + }, + }, + app_state+: { + feemarket+: { + params+: { + base_fee_change_denominator: '3', + elasticity_multiplier: '4', + base_fee: gas_price, + min_gas_price: gas_price, + }, + }, + }, + }, + }, +} diff --git a/tests/integration_tests/configs/min_gas_price_eq.jsonnet b/tests/integration_tests/configs/min_gas_price_eq.jsonnet new file mode 100644 index 000000000..b0b41a907 --- /dev/null +++ b/tests/integration_tests/configs/min_gas_price_eq.jsonnet @@ -0,0 +1,15 @@ +local config = import 'min_gas_price_lte.jsonnet'; + +config { + 'evm-canary-net-1'+: { + genesis+: { + consensus+: { + params+: { + block+: { + max_gas: '84000000', + }, + }, + }, + }, + }, +} diff --git a/tests/integration_tests/configs/min_gas_price_lte.jsonnet b/tests/integration_tests/configs/min_gas_price_lte.jsonnet new file mode 100644 index 000000000..60cfbf89c --- /dev/null +++ b/tests/integration_tests/configs/min_gas_price_lte.jsonnet @@ -0,0 +1,16 @@ +local config = import 'min_gas_price.jsonnet'; + +config { + 'evm-canary-net-1'+: { + genesis+: { + app_state+: { + feemarket+: { + params+: { + base_fee_change_denominator: '300', + elasticity_multiplier: '4000', + }, + }, + }, + }, + }, +} diff --git a/tests/integration_tests/configs/rly_chain.jsonnet b/tests/integration_tests/configs/rly_chain.jsonnet new file mode 100644 index 000000000..98e536722 --- /dev/null +++ b/tests/integration_tests/configs/rly_chain.jsonnet @@ -0,0 +1,20 @@ +{ + max_gas: 2500000, + gas_multiplier: 1.1, + address_type: { + derivation: 'ethermint', + proto_type: { + pk_type: '/cosmos.evm.crypto.v1.ethsecp256k1.PubKey', + }, + }, + gas_price: { + price: 0.1, + }, + event_source: { + batch_delay: '5000ms', + }, + extension_options: [{ + type: 'cosmos_evm_dynamic_fee_v1', + value: '10000000000000000', + }], +} diff --git a/tests/integration_tests/configs/rly_common.jsonnet b/tests/integration_tests/configs/rly_common.jsonnet new file mode 100644 index 000000000..e148229b6 --- /dev/null +++ b/tests/integration_tests/configs/rly_common.jsonnet @@ -0,0 +1,24 @@ +{ + mode: { + clients: { + enabled: true, + refresh: true, + misbehaviour: true, + }, + connections: { + enabled: true, + }, + channels: { + enabled: true, + }, + packets: { + enabled: true, + tx_confirmation: true, + }, + }, + rest: { + enabled: true, + host: '127.0.0.1', + port: 3000, + }, +} diff --git a/tests/integration_tests/configs/staking.jsonnet b/tests/integration_tests/configs/staking.jsonnet new file mode 100644 index 000000000..1403fc735 --- /dev/null +++ b/tests/integration_tests/configs/staking.jsonnet @@ -0,0 +1,15 @@ +local config = import 'default.jsonnet'; +local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; + +config { + 'evm-canary-net-1'+: { + validators: super.validators + [{ + 'coin-type': 60, + coins: '100000000000000000000' + chain.evm_denom, + staked: '10000000000000000000' + chain.evm_denom, + gas_prices: '0.01' + chain.evm_denom, + min_self_delegation: 1000000000000000000, + mnemonic: '${VALIDATOR4_MNEMONIC}', + }], + }, +} diff --git a/tests/integration_tests/contracts/.gitignore b/tests/integration_tests/contracts/.gitignore new file mode 100644 index 000000000..14d86ad62 --- /dev/null +++ b/tests/integration_tests/contracts/.gitignore @@ -0,0 +1 @@ +/cache diff --git a/tests/integration_tests/contracts/common/Types.sol b/tests/integration_tests/contracts/common/Types.sol new file mode 120000 index 000000000..a18c9f2db --- /dev/null +++ b/tests/integration_tests/contracts/common/Types.sol @@ -0,0 +1 @@ +../../../../precompiles/common/Types.sol \ No newline at end of file diff --git a/tests/integration_tests/contracts/contracts/BurnGas.sol b/tests/integration_tests/contracts/contracts/BurnGas.sol new file mode 100644 index 000000000..b7aae2420 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/BurnGas.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +contract BurnGas { + int[] expensive; + + function burnGas(uint256 count) public { + for (uint i = 0; i < count; i++) { + unchecked { + expensive.push(10); + } + } + } +} diff --git a/tests/integration_tests/contracts/contracts/CounterWithCallbacks.sol b/tests/integration_tests/contracts/contracts/CounterWithCallbacks.sol new file mode 100644 index 000000000..20cd3171d --- /dev/null +++ b/tests/integration_tests/contracts/contracts/CounterWithCallbacks.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +import "./ICallbacks.sol"; +import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract CounterWithCallbacks is ICallbacks { + // State variables + int public counter; + + // Mapping: user address => token address => balance + mapping(address => mapping(address => uint256)) public userTokenBalances; + + // Events + event CounterIncremented(int newValue, address indexed user); + event TokensDeposited( + address indexed user, + address indexed token, + uint256 amount, + uint256 newBalance + ); + event PacketAcknowledged( + string indexed channelId, + string indexed portId, + uint64 sequence, + bytes data, + bytes acknowledgement + ); + event PacketTimedOut( + string indexed channelId, + string indexed portId, + uint64 sequence, + bytes data + ); + + /** + * @dev Increment the counter and deposit ERC20 tokens + * @param token The address of the ERC20 token + * @param amount The amount of tokens to deposit + */ + function add(address token, uint256 amount) + external + { + // Transfer tokens from user to this contract + IERC20(token).transferFrom(msg.sender, address(this), amount); + + // Increment counter + counter += 1; + + // Add to user's token balance + userTokenBalances[msg.sender][token] += amount; + + // Emit events + emit CounterIncremented(counter, msg.sender); + emit TokensDeposited(msg.sender, token, amount, userTokenBalances[msg.sender][token]); + } + + /** + * @dev Get the current counter value + * @return The current counter value + */ + function getCounter() external view returns (int) { + return counter; + } + + /** + * @dev Get a user's balance for a specific token + * @param user The address of the user + * @param token The address of the token + * @return The user's token balance + */ + function getTokenBalance(address user, address token) external view returns (uint256) { + return userTokenBalances[user][token]; + } + + /** + * @dev Implementation of ICallbacks interface + * Called when a packet acknowledgement is received + */ + function onPacketAcknowledgement( + string memory channelId, + string memory portId, + uint64 sequence, + bytes memory data, + bytes memory acknowledgement + ) external override { + // Emit event when packet is acknowledged + emit PacketAcknowledged(channelId, portId, sequence, data, acknowledgement); + + counter += 1; // Increment counter on acknowledgement + } + + /** + * @dev Implementation of ICallbacks interface + * Called when a packet times out + */ + function onPacketTimeout( + string memory channelId, + string memory portId, + uint64 sequence, + bytes memory data + ) external override { + // Emit event when packet times out + emit PacketTimedOut(channelId, portId, sequence, data); + counter -= 1; // Decrement counter on timeout + } + + /** + * @dev Reset the counter + */ + function resetCounter() external { + counter = 0; + } +} \ No newline at end of file diff --git a/tests/integration_tests/contracts/contracts/DistributionI.sol b/tests/integration_tests/contracts/contracts/DistributionI.sol new file mode 120000 index 000000000..e1fd8c544 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/DistributionI.sol @@ -0,0 +1 @@ +../../../../precompiles/distribution/DistributionI.sol \ No newline at end of file diff --git a/tests/integration_tests/contracts/contracts/ERC20MinterBurnerDecimals.sol b/tests/integration_tests/contracts/contracts/ERC20MinterBurnerDecimals.sol new file mode 100644 index 000000000..fef9f7bdc --- /dev/null +++ b/tests/integration_tests/contracts/contracts/ERC20MinterBurnerDecimals.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.3.2 (token/ERC20/presets/ERC20PresetMinterPauser.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol"; +import "@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; + +/** + * @dev {ERC20} token, including: + * + * - ability for holders to burn (destroy) their tokens + * - a minter role that allows for token minting (creation) + * - a pauser role that allows to stop all token transfers + * + * This contract uses {AccessControl} to lock permissioned functions using the + * different roles - head to its documentation for details. + * + * The account that deploys the contract will be granted the minter and pauser + * roles, as well as the default admin role, which will let it grant both minter + * and pauser roles to other accounts. + */ +contract ERC20MinterBurnerDecimals is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable { + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); + bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); + uint8 private _decimals; + + /** + * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the + * account that deploys the contract and customizes tokens decimals + * + * See {ERC20-constructor}. + */ + constructor(string memory name, string memory symbol, uint8 decimals_) + ERC20(name, symbol) { + _grantRole(DEFAULT_ADMIN_ROLE, _msgSender()); + + _grantRole(MINTER_ROLE, _msgSender()); + _grantRole(PAUSER_ROLE, _msgSender()); + _grantRole(BURNER_ROLE, _msgSender()); + _setupDecimals(decimals_); + } + + /** + * @dev Sets `_decimals` as `decimals_ once at Deployment' + */ + function _setupDecimals(uint8 decimals_) private { + _decimals = decimals_; + } + + /** + * @dev Overrides the `decimals()` method with custom `_decimals` + */ + function decimals() public view virtual override returns (uint8) { + return _decimals; + } + + /** + * @dev Creates `amount` new tokens for `to`. + * + * See {ERC20-_mint}. + * + * Requirements: + * + * - the caller must have the `MINTER_ROLE`. + */ + function mint(address to, uint256 amount) public virtual { + require(hasRole(MINTER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have minter role to mint"); + _mint(to, amount); + } + + /** + * @dev Destroys `amount` new tokens for `to`. + * + * See {ERC20-_burn}. + * + * Requirements: + * + * - the caller must have the `BURNER_ROLE`. + */ + function burnCoins(address from, uint256 amount) public virtual { + require(hasRole(BURNER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have burner role to burn"); + _burn(from, amount); + } + + /** + * @dev Pauses all token transfers. + * + * See {ERC20Pausable} and {Pausable-_pause}. + * + * Requirements: + * + * - the caller must have the `PAUSER_ROLE`. + */ + function pause() public virtual { + require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have pauser role to pause"); + _pause(); + } + + /** + * @dev Unpauses all token transfers. + * + * See {ERC20Pausable} and {Pausable-_unpause}. + * + * Requirements: + * + * - the caller must have the `PAUSER_ROLE`. + */ + function unpause() public virtual { + require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20MinterBurnerDecimals: must have pauser role to unpause"); + _unpause(); + } + + function _update( + address from, + address to, + uint256 amount + ) internal virtual override(ERC20, ERC20Pausable) { + super._update(from, to, amount); + } +} \ No newline at end of file diff --git a/tests/integration_tests/contracts/contracts/Greeter.sol b/tests/integration_tests/contracts/contracts/Greeter.sol new file mode 100644 index 000000000..2d6856b17 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/Greeter.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +contract Greeter { + uint public n; + string public greeting; + + event ChangeGreeting(address from, string value); + + constructor() { + greeting = "Hello"; + } + + function setGreeting(string memory _greeting) public { + greeting = _greeting; + emit ChangeGreeting(msg.sender, _greeting); + } + + function greet() public view returns (string memory) { + return greeting; + } + + function intValue() public view returns (uint) { + return n; + } +} diff --git a/tests/integration_tests/contracts/contracts/ICallbacks.sol b/tests/integration_tests/contracts/contracts/ICallbacks.sol new file mode 120000 index 000000000..5a0e9aaf5 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/ICallbacks.sol @@ -0,0 +1 @@ +../../../../precompiles/callbacks/ICallbacks.sol \ No newline at end of file diff --git a/tests/integration_tests/contracts/contracts/MockERC20.json b/tests/integration_tests/contracts/contracts/MockERC20.json new file mode 100644 index 000000000..f9a09d91c --- /dev/null +++ b/tests/integration_tests/contracts/contracts/MockERC20.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"_name","type":"string","internalType":"string"},{"name":"_symbol","type":"string","internalType":"string"},{"name":"_decimals","type":"uint8","internalType":"uint8"}],"stateMutability":"nonpayable"},{"type":"function","name":"DOMAIN_SEPARATOR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"allowance","inputs":[{"name":"","type":"address","internalType":"address"},{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"approve","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"balanceOf","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"burn","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"mint","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"nonces","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"permit","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"spender","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"},{"name":"v","type":"uint8","internalType":"uint8"},{"name":"r","type":"bytes32","internalType":"bytes32"},{"name":"s","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"transfer","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferFrom","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"event","name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"spender","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false}],"bytecode":{"object":"0x60e06040523480156200001157600080fd5b5060405162001240380380620012408339810160408190526200003491620001e3565b8282826000620000458482620002f7565b506001620000548382620002f7565b5060ff81166080524660a0526200006a6200007a565b60c0525062000441945050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051620000ae9190620003c3565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200013e57600080fd5b81516001600160401b03808211156200015b576200015b62000116565b604051601f8301601f19908116603f0116810190828211818310171562000186576200018662000116565b81604052838152602092508683858801011115620001a357600080fd5b600091505b83821015620001c75785820183015181830184015290820190620001a8565b83821115620001d95760008385830101525b9695505050505050565b600080600060608486031215620001f957600080fd5b83516001600160401b03808211156200021157600080fd5b6200021f878388016200012c565b945060208601519150808211156200023657600080fd5b5062000245868287016200012c565b925050604084015160ff811681146200025d57600080fd5b809150509250925092565b600181811c908216806200027d57607f821691505b6020821081036200029e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002f257600081815260208120601f850160051c81016020861015620002cd5750805b601f850160051c820191505b81811015620002ee57828155600101620002d9565b5050505b505050565b81516001600160401b0381111562000313576200031362000116565b6200032b8162000324845462000268565b84620002a4565b602080601f8311600181146200036357600084156200034a5750858301515b600019600386901b1c1916600185901b178555620002ee565b600085815260208120601f198616915b82811015620003945788860151825594840194600190910190840162000373565b5085821015620003b35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000808354620003d38162000268565b60018281168015620003ee5760018114620004045762000435565b60ff198416875282151583028701945062000435565b8760005260208060002060005b858110156200042c5781548a82015290840190820162000411565b50505082870194505b50929695505050505050565b60805160a05160c051610dcf6200047160003960006104e0015260006104ab0152600061015f0152610dcf6000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806370a082311161008c5780639dc29fac116100665780639dc29fac146101f8578063a9059cbb1461020b578063d505accf1461021e578063dd62ed3e1461023157600080fd5b806370a08231146101b05780637ecebe00146101d057806395d89b41146101f057600080fd5b806323b872dd116100c857806323b872dd14610147578063313ce5671461015a5780633644e5151461019357806340c10f191461019b57600080fd5b806306fdde03146100ef578063095ea7b31461010d57806318160ddd14610130575b600080fd5b6100f761025c565b6040516101049190610a71565b60405180910390f35b61012061011b366004610b0d565b6102ea565b6040519015158152602001610104565b61013960025481565b604051908152602001610104565b610120610155366004610b37565b610363565b6101817f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610104565b6101396104a7565b6101ae6101a9366004610b0d565b610502565b005b6101396101be366004610b73565b60036020526000908152604090205481565b6101396101de366004610b73565b60056020526000908152604090205481565b6100f7610510565b6101ae610206366004610b0d565b61051d565b610120610219366004610b0d565b610527565b6101ae61022c366004610b95565b6105ac565b61013961023f366004610c08565b600460209081526000928352604080842090915290825290205481565b6000805461026990610c3b565b80601f016020809104026020016040519081016040528092919081815260200182805461029590610c3b565b80156102e25780601f106102b7576101008083540402835291602001916102e2565b820191906000526020600020905b8154815290600101906020018083116102c557829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103529086815260200190565b60405180910390a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146103f7576103c58382610cbd565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff85166000908152600360205260408120805485929061042c908490610cbd565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906104949087815260200190565b60405180910390a3506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146104dd576104d86108d0565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b61050c828261096a565b5050565b6001805461026990610c3b565b61050c82826109e3565b33600090815260036020526040812080548391908390610548908490610cbd565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906103529086815260200190565b4284101561061b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f4558504952454400000000000000000060448201526064015b60405180910390fd5b600060016106276104a7565b73ffffffffffffffffffffffffffffffffffffffff8a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610779573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116158015906107f457508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b61085a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e45520000000000000000000000000000000000006044820152606401610612565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516109029190610cd4565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b806002600082825461097c9190610daa565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054839290610a18908490610cbd565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016109d7565b600060208083528351808285015260005b81811015610a9e57858101830151858201604001528201610a82565b81811115610ab0576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b0857600080fd5b919050565b60008060408385031215610b2057600080fd5b610b2983610ae4565b946020939093013593505050565b600080600060608486031215610b4c57600080fd5b610b5584610ae4565b9250610b6360208501610ae4565b9150604084013590509250925092565b600060208284031215610b8557600080fd5b610b8e82610ae4565b9392505050565b600080600080600080600060e0888a031215610bb057600080fd5b610bb988610ae4565b9650610bc760208901610ae4565b95506040880135945060608801359350608088013560ff81168114610beb57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215610c1b57600080fd5b610c2483610ae4565b9150610c3260208401610ae4565b90509250929050565b600181811c90821680610c4f57607f821691505b602082108103610c88577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610ccf57610ccf610c8e565b500390565b600080835481600182811c915080831680610cf057607f831692505b60208084108203610d28577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015610d3c5760018114610d6f57610d9c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952841515850289019650610d9c565b60008a81526020902060005b86811015610d945781548b820152908501908301610d7b565b505084890196505b509498975050505050505050565b60008219821115610dbd57610dbd610c8e565b50019056fea164736f6c634300080f000a","sourceMap":"118:368:32:-:0;;;152:138;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;261:5;268:7;277:9;2094:4:45;:12;261:5:32;2094:4:45;:12;:::i;:::-;-1:-1:-1;2116:6:45;:16;2125:7;2116:6;:16;:::i;:::-;-1:-1:-1;2142:20:45;;;;;2192:13;2173:32;;2242:24;:22;:24::i;:::-;2215:51;;-1:-1:-1;118:368:32;;-1:-1:-1;;;;;118:368:32;5510:446:45;5575:7;5672:95;5805:4;5789:22;;;;;;:::i;:::-;;;;;;;;;;5640:295;;;5450:25:60;;;;5491:18;;5484:34;;;;5833:14:45;5534:18:60;;;5527:34;5869:13:45;5577:18:60;;;5570:34;5912:4:45;5620:19:60;;;5613:61;5422:19;;5640:295:45;;;;;;;;;;;;5613:336;;;;;;5594:355;;5510:446;:::o;14:127:60:-;75:10;70:3;66:20;63:1;56:31;106:4;103:1;96:15;130:4;127:1;120:15;146:885;200:5;253:3;246:4;238:6;234:17;230:27;220:55;;271:1;268;261:12;220:55;294:13;;-1:-1:-1;;;;;356:10:60;;;353:36;;;369:18;;:::i;:::-;444:2;438:9;412:2;498:13;;-1:-1:-1;;494:22:60;;;518:2;490:31;486:40;474:53;;;542:18;;;562:22;;;539:46;536:72;;;588:18;;:::i;:::-;628:10;624:2;617:22;663:2;655:6;648:18;685:4;675:14;;730:3;725:2;720;712:6;708:15;704:24;701:33;698:53;;;747:1;744;737:12;698:53;769:1;760:10;;779:133;793:2;790:1;787:9;779:133;;;881:14;;;877:23;;871:30;850:14;;;846:23;;839:63;804:10;;;;779:133;;;930:2;927:1;924:9;921:80;;;989:1;984:2;979;971:6;967:15;963:24;956:35;921:80;1019:6;146:885;-1:-1:-1;;;;;;146:885:60:o;1036:712::-;1142:6;1150;1158;1211:2;1199:9;1190:7;1186:23;1182:32;1179:52;;;1227:1;1224;1217:12;1179:52;1254:16;;-1:-1:-1;;;;;1319:14:60;;;1316:34;;;1346:1;1343;1336:12;1316:34;1369:61;1422:7;1413:6;1402:9;1398:22;1369:61;:::i;:::-;1359:71;;1476:2;1465:9;1461:18;1455:25;1439:41;;1505:2;1495:8;1492:16;1489:36;;;1521:1;1518;1511:12;1489:36;;1544:63;1599:7;1588:8;1577:9;1573:24;1544:63;:::i;:::-;1534:73;;;1650:2;1639:9;1635:18;1629:25;1694:4;1687:5;1683:16;1676:5;1673:27;1663:55;;1714:1;1711;1704:12;1663:55;1737:5;1727:15;;;1036:712;;;;;:::o;1753:380::-;1832:1;1828:12;;;;1875;;;1896:61;;1950:4;1942:6;1938:17;1928:27;;1896:61;2003:2;1995:6;1992:14;1972:18;1969:38;1966:161;;2049:10;2044:3;2040:20;2037:1;2030:31;2084:4;2081:1;2074:15;2112:4;2109:1;2102:15;1966:161;;1753:380;;;:::o;2264:545::-;2366:2;2361:3;2358:11;2355:448;;;2402:1;2427:5;2423:2;2416:17;2472:4;2468:2;2458:19;2542:2;2530:10;2526:19;2523:1;2519:27;2513:4;2509:38;2578:4;2566:10;2563:20;2560:47;;;-1:-1:-1;2601:4:60;2560:47;2656:2;2651:3;2647:12;2644:1;2640:20;2634:4;2630:31;2620:41;;2711:82;2729:2;2722:5;2719:13;2711:82;;;2774:17;;;2755:1;2744:13;2711:82;;;2715:3;;;2355:448;2264:545;;;:::o;2985:1352::-;3105:10;;-1:-1:-1;;;;;3127:30:60;;3124:56;;;3160:18;;:::i;:::-;3189:97;3279:6;3239:38;3271:4;3265:11;3239:38;:::i;:::-;3233:4;3189:97;:::i;:::-;3341:4;;3405:2;3394:14;;3422:1;3417:663;;;;4124:1;4141:6;4138:89;;;-1:-1:-1;4193:19:60;;;4187:26;4138:89;-1:-1:-1;;2942:1:60;2938:11;;;2934:24;2930:29;2920:40;2966:1;2962:11;;;2917:57;4240:81;;3387:944;;3417:663;2211:1;2204:14;;;2248:4;2235:18;;-1:-1:-1;;3453:20:60;;;3571:236;3585:7;3582:1;3579:14;3571:236;;;3674:19;;;3668:26;3653:42;;3766:27;;;;3734:1;3722:14;;;;3601:19;;3571:236;;;3575:3;3835:6;3826:7;3823:19;3820:201;;;3896:19;;;3890:26;-1:-1:-1;;3979:1:60;3975:14;;;3991:3;3971:24;3967:37;3963:42;3948:58;3933:74;;3820:201;-1:-1:-1;;;;;4067:1:60;4051:14;;;4047:22;4034:36;;-1:-1:-1;2985:1352:60:o;4342:844::-;4472:3;4501:1;4534:6;4528:13;4564:36;4590:9;4564:36;:::i;:::-;4619:1;4636:18;;;4663:133;;;;4810:1;4805:356;;;;4629:532;;4663:133;-1:-1:-1;;4696:24:60;;4684:37;;4769:14;;4762:22;4750:35;;4741:45;;;-1:-1:-1;4663:133:60;;4805:356;4836:6;4833:1;4826:17;4866:4;4911:2;4908:1;4898:16;4936:1;4950:165;4964:6;4961:1;4958:13;4950:165;;;5042:14;;5029:11;;;5022:35;5085:16;;;;4979:10;;4950:165;;;4954:3;;;5144:6;5139:3;5135:16;5128:23;;4629:532;-1:-1:-1;5177:3:60;;4342:844;-1:-1:-1;;;;;;4342:844:60:o;5191:489::-;118:368:32;;;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c806370a082311161008c5780639dc29fac116100665780639dc29fac146101f8578063a9059cbb1461020b578063d505accf1461021e578063dd62ed3e1461023157600080fd5b806370a08231146101b05780637ecebe00146101d057806395d89b41146101f057600080fd5b806323b872dd116100c857806323b872dd14610147578063313ce5671461015a5780633644e5151461019357806340c10f191461019b57600080fd5b806306fdde03146100ef578063095ea7b31461010d57806318160ddd14610130575b600080fd5b6100f761025c565b6040516101049190610a71565b60405180910390f35b61012061011b366004610b0d565b6102ea565b6040519015158152602001610104565b61013960025481565b604051908152602001610104565b610120610155366004610b37565b610363565b6101817f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610104565b6101396104a7565b6101ae6101a9366004610b0d565b610502565b005b6101396101be366004610b73565b60036020526000908152604090205481565b6101396101de366004610b73565b60056020526000908152604090205481565b6100f7610510565b6101ae610206366004610b0d565b61051d565b610120610219366004610b0d565b610527565b6101ae61022c366004610b95565b6105ac565b61013961023f366004610c08565b600460209081526000928352604080842090915290825290205481565b6000805461026990610c3b565b80601f016020809104026020016040519081016040528092919081815260200182805461029590610c3b565b80156102e25780601f106102b7576101008083540402835291602001916102e2565b820191906000526020600020905b8154815290600101906020018083116102c557829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103529086815260200190565b60405180910390a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146103f7576103c58382610cbd565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff85166000908152600360205260408120805485929061042c908490610cbd565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906104949087815260200190565b60405180910390a3506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146104dd576104d86108d0565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b61050c828261096a565b5050565b6001805461026990610c3b565b61050c82826109e3565b33600090815260036020526040812080548391908390610548908490610cbd565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906103529086815260200190565b4284101561061b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f4558504952454400000000000000000060448201526064015b60405180910390fd5b600060016106276104a7565b73ffffffffffffffffffffffffffffffffffffffff8a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610779573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116158015906107f457508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b61085a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e45520000000000000000000000000000000000006044820152606401610612565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516109029190610cd4565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b806002600082825461097c9190610daa565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054839290610a18908490610cbd565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016109d7565b600060208083528351808285015260005b81811015610a9e57858101830151858201604001528201610a82565b81811115610ab0576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b0857600080fd5b919050565b60008060408385031215610b2057600080fd5b610b2983610ae4565b946020939093013593505050565b600080600060608486031215610b4c57600080fd5b610b5584610ae4565b9250610b6360208501610ae4565b9150604084013590509250925092565b600060208284031215610b8557600080fd5b610b8e82610ae4565b9392505050565b600080600080600080600060e0888a031215610bb057600080fd5b610bb988610ae4565b9650610bc760208901610ae4565b95506040880135945060608801359350608088013560ff81168114610beb57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215610c1b57600080fd5b610c2483610ae4565b9150610c3260208401610ae4565b90509250929050565b600181811c90821680610c4f57607f821691505b602082108103610c88577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610ccf57610ccf610c8e565b500390565b600080835481600182811c915080831680610cf057607f831692505b60208084108203610d28577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015610d3c5760018114610d6f57610d9c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952841515850289019650610d9c565b60008a81526020902060005b86811015610d945781548b820152908501908301610d7b565b505084890196505b509498975050505050505050565b60008219821115610dbd57610dbd610c8e565b50019056fea164736f6c634300080f000a","sourceMap":"118:368:32:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1031:18:45;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2461:211;;;;;;:::i;:::-;;:::i;:::-;;;1300:14:60;;1293:22;1275:41;;1263:2;1248:18;2461:211:45;1135:187:60;1304:26:45;;;;;;;;;1473:25:60;;;1461:2;1446:18;1304:26:45;1327:177:60;3057:592:45;;;;;;:::i;:::-;;:::i;1083:31::-;;;;;;;;2014:4:60;2002:17;;;1984:36;;1972:2;1957:18;1083:31:45;1842:184:60;5327:177:45;;;:::i;296:89:32:-;;;;;;:::i;:::-;;:::i;:::-;;1337:44:45;;;;;;:::i;:::-;;;;;;;;;;;;;;1751:41;;;;;;:::i;:::-;;;;;;;;;;;;;;1056:20;;;:::i;391:93:32:-;;;;;;:::i;:::-;;:::i;2678:373:45:-;;;;;;:::i;:::-;;:::i;3838:1483::-;;;;;;:::i;:::-;;:::i;1388:64::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1031:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;2461:211::-;2561:10;2535:4;2551:21;;;:9;:21;;;;;;;;;:30;;;;;;;;;;:39;;;2606:37;2535:4;;2551:30;;2606:37;;;;2584:6;1473:25:60;;1461:2;1446:18;;1327:177;2606:37:45;;;;;;;;-1:-1:-1;2661:4:45;2461:211;;;;:::o;3057:592::-;3209:15;;;3175:4;3209:15;;;:9;:15;;;;;;;;3225:10;3209:27;;;;;;;;3298:17;3287:28;;3283:80;;3347:16;3357:6;3347:7;:16;:::i;:::-;3317:15;;;;;;;:9;:15;;;;;;;;3333:10;3317:27;;;;;;;:46;3283:80;3374:15;;;;;;;:9;:15;;;;;:25;;3393:6;;3374:15;:25;;3393:6;;3374:25;:::i;:::-;;;;-1:-1:-1;;3545:13:45;;;;;;;;:9;:13;;;;;;;:23;;;;;;3594:26;3545:13;;3594:26;;;;;;;3562:6;1473:25:60;;1461:2;1446:18;;1327:177;3594:26:45;;;;;;;;-1:-1:-1;3638:4:45;;3057:592;-1:-1:-1;;;;3057:592:45:o;5327:177::-;5384:7;5427:16;5410:13;:33;:87;;5473:24;:22;:24::i;:::-;5403:94;;5327:177;:::o;5410:87::-;-1:-1:-1;5446:24:45;;5327:177::o;296:89:32:-;362:16;368:2;372:5;362;:16::i;:::-;296:89;;:::o;1056:20:45:-;;;;;;;:::i;391:93:32:-;459:18;465:4;471:5;459;:18::i;2678:373:45:-;2774:10;2748:4;2764:21;;;:9;:21;;;;;:31;;2789:6;;2764:21;2748:4;;2764:31;;2789:6;;2764:31;:::i;:::-;;;;-1:-1:-1;;2941:13:45;;;;;;;:9;:13;;;;;;;:23;;;;;;2990:32;2999:10;;2990:32;;;;2958:6;1473:25:60;;1461:2;1446:18;;1327:177;3838:1483:45;4057:15;4045:8;:27;;4037:63;;;;;;;4330:2:60;4037:63:45;;;4312:21:60;4369:2;4349:18;;;4342:30;4408:25;4388:18;;;4381:53;4451:18;;4037:63:45;;;;;;;;;4265:24;4292:805;4428:18;:16;:18::i;:::-;4873:13;;;;;;;;:6;:13;;;;;;;;;:15;;;;;;;;4511:449;;4555:165;4511:449;;;4767:25:60;4869:18;;;4862:43;;;;4941:15;;;4921:18;;;4914:43;4973:18;;;4966:34;;;5016:19;;;5009:35;;;;5060:19;;;;5053:35;;;4511:449:45;;;;;;;;;;4739:19:60;;;4511:449:45;;;4472:514;;;;;;;;5369:66:60;4350:658:45;;;5357:79:60;5452:11;;;5445:27;;;;5488:12;;;5481:28;;;;5525:12;;4350:658:45;;;;;;;;;;;;;4319:707;;4350:658;4319:707;;;;4292:805;;;;;;;;;5775:25:60;5848:4;5836:17;;5816:18;;;5809:45;5870:18;;;5863:34;;;5913:18;;;5906:34;;;5747:19;;4292:805:45;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4292:805:45;;;;;;-1:-1:-1;;5120:30:45;;;;;;;:59;;;5174:5;5154:25;;:16;:25;;;5120:59;5112:86;;;;;;;6153:2:60;5112:86:45;;;6135:21:60;6192:2;6172:18;;;6165:30;6231:16;6211:18;;;6204:44;6265:18;;5112:86:45;5951:338:60;5112:86:45;5213:27;;;;;;;;:9;:27;;;;;;;;:36;;;;;;;;;;;;;:44;;;5283:31;1473:25:60;;;5213:36:45;;5283:31;;;;;1446:18:60;5283:31:45;;;;;;;3838:1483;;;;;;;:::o;5510:446::-;5575:7;5672:95;5805:4;5789:22;;;;;;:::i;:::-;;;;;;;;;;5640:295;;;7935:25:60;;;;7976:18;;7969:34;;;;5833:14:45;8019:18:60;;;8012:34;5869:13:45;8062:18:60;;;8055:34;5912:4:45;8105:19:60;;;8098:84;7907:19;;5640:295:45;;;;;;;;;;;;5613:336;;;;;;5594:355;;5510:446;:::o;6150:325::-;6235:6;6220:11;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;;6387:13:45;;;;;;;:9;:13;;;;;;;;:23;;;;;;6436:32;1473:25:60;;;6436:32:45;;1446:18:60;6436:32:45;;;;;;;;6150:325;;:::o;6481:328::-;6553:15;;;;;;;:9;:15;;;;;:25;;6572:6;;6553:15;:25;;6572:6;;6553:25;:::i;:::-;;;;-1:-1:-1;;6721:11:45;:21;;;;;;;6768:34;;1473:25:60;;;-1:-1:-1;;6768:34:45;;;;;;1461:2:60;1446:18;6768:34:45;1327:177:60;14:656;126:4;155:2;184;173:9;166:21;216:6;210:13;259:6;254:2;243:9;239:18;232:34;284:1;294:140;308:6;305:1;302:13;294:140;;;403:14;;;399:23;;393:30;369:17;;;388:2;365:26;358:66;323:10;;294:140;;;452:6;449:1;446:13;443:91;;;522:1;517:2;508:6;497:9;493:22;489:31;482:42;443:91;-1:-1:-1;586:2:60;574:15;591:66;570:88;555:104;;;;661:2;551:113;;14:656;-1:-1:-1;;;14:656:60:o;675:196::-;743:20;;803:42;792:54;;782:65;;772:93;;861:1;858;851:12;772:93;675:196;;;:::o;876:254::-;944:6;952;1005:2;993:9;984:7;980:23;976:32;973:52;;;1021:1;1018;1011:12;973:52;1044:29;1063:9;1044:29;:::i;:::-;1034:39;1120:2;1105:18;;;;1092:32;;-1:-1:-1;;;876:254:60:o;1509:328::-;1586:6;1594;1602;1655:2;1643:9;1634:7;1630:23;1626:32;1623:52;;;1671:1;1668;1661:12;1623:52;1694:29;1713:9;1694:29;:::i;:::-;1684:39;;1742:38;1776:2;1765:9;1761:18;1742:38;:::i;:::-;1732:48;;1827:2;1816:9;1812:18;1799:32;1789:42;;1509:328;;;;;:::o;2213:186::-;2272:6;2325:2;2313:9;2304:7;2300:23;2296:32;2293:52;;;2341:1;2338;2331:12;2293:52;2364:29;2383:9;2364:29;:::i;:::-;2354:39;2213:186;-1:-1:-1;;;2213:186:60:o;2404:693::-;2515:6;2523;2531;2539;2547;2555;2563;2616:3;2604:9;2595:7;2591:23;2587:33;2584:53;;;2633:1;2630;2623:12;2584:53;2656:29;2675:9;2656:29;:::i;:::-;2646:39;;2704:38;2738:2;2727:9;2723:18;2704:38;:::i;:::-;2694:48;;2789:2;2778:9;2774:18;2761:32;2751:42;;2840:2;2829:9;2825:18;2812:32;2802:42;;2894:3;2883:9;2879:19;2866:33;2939:4;2932:5;2928:16;2921:5;2918:27;2908:55;;2959:1;2956;2949:12;2908:55;2404:693;;;;-1:-1:-1;2404:693:60;;;;2982:5;3034:3;3019:19;;3006:33;;-1:-1:-1;3086:3:60;3071:19;;;3058:33;;2404:693;-1:-1:-1;;2404:693:60:o;3102:260::-;3170:6;3178;3231:2;3219:9;3210:7;3206:23;3202:32;3199:52;;;3247:1;3244;3237:12;3199:52;3270:29;3289:9;3270:29;:::i;:::-;3260:39;;3318:38;3352:2;3341:9;3337:18;3318:38;:::i;:::-;3308:48;;3102:260;;;;;:::o;3367:437::-;3446:1;3442:12;;;;3489;;;3510:61;;3564:4;3556:6;3552:17;3542:27;;3510:61;3617:2;3609:6;3606:14;3586:18;3583:38;3580:218;;3654:77;3651:1;3644:88;3755:4;3752:1;3745:15;3783:4;3780:1;3773:15;3580:218;;3367:437;;;:::o;3809:184::-;3861:77;3858:1;3851:88;3958:4;3955:1;3948:15;3982:4;3979:1;3972:15;3998:125;4038:4;4066:1;4063;4060:8;4057:34;;;4071:18;;:::i;:::-;-1:-1:-1;4108:9:60;;3998:125::o;6423:1248::-;6553:3;6582:1;6615:6;6609:13;6645:3;6667:1;6695:9;6691:2;6687:18;6677:28;;6755:2;6744:9;6740:18;6777;6767:61;;6821:4;6813:6;6809:17;6799:27;;6767:61;6847:2;6895;6887:6;6884:14;6864:18;6861:38;6858:222;;6934:77;6929:3;6922:90;7035:4;7032:1;7025:15;7065:4;7060:3;7053:17;6858:222;7096:18;7123:191;;;;7328:1;7323:323;;;;7089:557;;7123:191;7171:66;7160:9;7156:82;7151:3;7144:95;7294:6;7287:14;7280:22;7272:6;7268:35;7263:3;7259:45;7252:52;;7123:191;;7323:323;6370:1;6363:14;;;6407:4;6394:18;;7421:1;7435:165;7449:6;7446:1;7443:13;7435:165;;;7527:14;;7514:11;;;7507:35;7570:16;;;;7464:10;;7435:165;;;7439:3;;7629:6;7624:3;7620:16;7613:23;;7089:557;-1:-1:-1;7662:3:60;;6423:1248;-1:-1:-1;;;;;;;;6423:1248:60:o;8193:128::-;8233:3;8264:1;8260:6;8257:1;8254:13;8251:39;;;8270:18;;:::i;:::-;-1:-1:-1;8306:9:60;;8193:128::o","linkReferences":{},"immutableReferences":{"36574":[{"start":351,"length":32}],"36588":[{"start":1195,"length":32}],"36590":[{"start":1248,"length":32}]}},"methodIdentifiers":{"DOMAIN_SEPARATOR()":"3644e515","allowance(address,address)":"dd62ed3e","approve(address,uint256)":"095ea7b3","balanceOf(address)":"70a08231","burn(address,uint256)":"9dc29fac","decimals()":"313ce567","mint(address,uint256)":"40c10f19","name()":"06fdde03","nonces(address)":"7ecebe00","permit(address,address,uint256,uint256,uint8,bytes32,bytes32)":"d505accf","symbol()":"95d89b41","totalSupply()":"18160ddd","transfer(address,uint256)":"a9059cbb","transferFrom(address,address,uint256)":"23b872dd"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/test/utils/mocks/MockERC20.sol\":\"MockERC20\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[\":ds-test/=lib/ds-test/src/\"]},\"sources\":{\"src/test/utils/mocks/MockERC20.sol\":{\"keccak256\":\"0x525129ccb4103c9ecb8f235618d2ff4a8ffde4b8654f7c17766ad175d10ef466\",\"license\":\"AGPL-3.0-only\",\"urls\":[\"bzz-raw://45692a21807ba815c0cf0bfc7d633a14a6cb9ba863ab53f18fc639375a72125e\",\"dweb:/ipfs/QmSrqxyodjDtSU1Dc6G3ScnNc9CFjMnAeHpK8a8guM3nJu\"]},\"src/tokens/ERC20.sol\":{\"keccak256\":\"0xcdfd8db76b2a3415620e4d18cc5545f3d50de792dbf2c3dd5adb40cbe6f94b10\",\"license\":\"AGPL-3.0-only\",\"urls\":[\"bzz-raw://57b3ab70cde374af1cf2c9888636e8de6cf660f087b1c9abd805e9271e19fa35\",\"dweb:/ipfs/QmNrLDBAHYFjpjSd12jerm1AdBkDqEYUUaXgnT854BUZ97\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address","indexed":true},{"internalType":"address","name":"spender","type":"address","indexed":true},{"internalType":"uint256","name":"amount","type":"uint256","indexed":false}],"type":"event","name":"Approval","anonymous":false},{"inputs":[{"internalType":"address","name":"from","type":"address","indexed":true},{"internalType":"address","name":"to","type":"address","indexed":true},{"internalType":"uint256","name":"amount","type":"uint256","indexed":false}],"type":"event","name":"Transfer","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function","name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function","name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"burn"},{"inputs":[],"stateMutability":"view","type":"function","name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"mint"},{"inputs":[],"stateMutability":"view","type":"function","name":"name","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function","name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"stateMutability":"nonpayable","type":"function","name":"permit"},{"inputs":[],"stateMutability":"view","type":"function","name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["ds-test/=lib/ds-test/src/"],"optimizer":{"enabled":true,"runs":1000000},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/test/utils/mocks/MockERC20.sol":"MockERC20"},"evmVersion":"london","libraries":{}},"sources":{"src/test/utils/mocks/MockERC20.sol":{"keccak256":"0x525129ccb4103c9ecb8f235618d2ff4a8ffde4b8654f7c17766ad175d10ef466","urls":["bzz-raw://45692a21807ba815c0cf0bfc7d633a14a6cb9ba863ab53f18fc639375a72125e","dweb:/ipfs/QmSrqxyodjDtSU1Dc6G3ScnNc9CFjMnAeHpK8a8guM3nJu"],"license":"AGPL-3.0-only"},"src/tokens/ERC20.sol":{"keccak256":"0xcdfd8db76b2a3415620e4d18cc5545f3d50de792dbf2c3dd5adb40cbe6f94b10","urls":["bzz-raw://57b3ab70cde374af1cf2c9888636e8de6cf660f087b1c9abd805e9271e19fa35","dweb:/ipfs/QmNrLDBAHYFjpjSd12jerm1AdBkDqEYUUaXgnT854BUZ97"],"license":"AGPL-3.0-only"}},"version":1},"id":32} \ No newline at end of file diff --git a/tests/integration_tests/contracts/contracts/Multicall3Router.json b/tests/integration_tests/contracts/contracts/Multicall3Router.json new file mode 100644 index 000000000..1d0bef2e7 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/Multicall3Router.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"_multicall3","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"fallback","stateMutability":"payable"},{"type":"receive","stateMutability":"payable"},{"type":"function","name":"cleanupERC20","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"refundTo","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"multicall3","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"sellToPool","inputs":[{"name":"sellToken","type":"address","internalType":"address"},{"name":"bps","type":"uint256","internalType":"uint256"},{"name":"pool","type":"address","internalType":"address"},{"name":"offset","type":"uint256","internalType":"uint256"},{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"error","name":"CallFailed","inputs":[{"name":"returnData","type":"bytes","internalType":"bytes"}]},{"type":"error","name":"InvalidOffset","inputs":[]},{"type":"error","name":"InvalidTarget","inputs":[]}],"bytecode":{"object":"0x60a0604052348015600e575f80fd5b50604051610af5380380610af5833981016040819052602b91603b565b6001600160a01b03166080526066565b5f60208284031215604a575f80fd5b81516001600160a01b0381168114605f575f80fd5b9392505050565b608051610a716100845f395f81816046015261014e0152610a715ff3fe608060405260043610610037575f3560e01c80633dad0c9c1461011c57806394b41e521461013d578063ed856306146101995761003e565b3661003e57005b5f3660605f807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16858560405161008b929190610774565b5f60405180830381855af49150503d805f81146100c3576040519150601f19603f3d011682016040523d82523d5f602084013e6100c8565b606091505b50915091508161010f57806040517fa5fa8d2b00000000000000000000000000000000000000000000000000000000815260040161010691906107a5565b60405180910390fd5b8051945060200192505050f35b348015610127575f80fd5b5061013b61013636600461081d565b6101b8565b005b348015610148575f80fd5b506101707f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156101a4575f80fd5b5061013b6101b336600461087b565b6102eb565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610222573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102469190610977565b905080156102e6576040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb906044016020604051808303815f875af11580156102c0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102e4919061098e565b505b505050565b5f60608173ffffffffffffffffffffffffffffffffffffffff88166103ff5761271061031788476109e1565b61032191906109fe565b905083515f036103d5578415610363576040517f01da157200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff87169082905f81818185875af1925050503d805f81146103b6576040519150601f19603f3d011682016040523d82523d5f602084013e6103bb565b606091505b5090935091506103cd83151583610602565b5050506105fb565b83516103e2602087610a36565b95508511156103f5576103f56032610614565b8085850152610525565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9061271090899073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa15801561046f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104939190610977565b61049d91906109e1565b6104a791906109fe565b85519091506104b7602088610a36565b96508611156104ca576104ca6032610614565b80868601528673ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16146105235761052373ffffffffffffffffffffffffffffffffffffffff8a168883610625565b505b8573ffffffffffffffffffffffffffffffffffffffff16818560405161054b9190610a49565b5f6040518083038185875af1925050503d805f8114610585576040519150601f19603f3d011682016040523d82523d5f602084013e61058a565b606091505b50909350915061059c83151583610602565b81511580156105c0575073ffffffffffffffffffffffffffffffffffffffff86163b155b156105f7576040517f82d5d76a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505b5050505050565b816106105761061081610702565b5050565b634e487b715f52806020526024601cfd5b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919085169063dd62ed3e90604401602060405180830381865afa158015610698573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106bc9190610977565b9050818110156102e45780156106d7576106d784845f61070a565b6102e484847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61070a565b805160208201fd5b81601452806034526f095ea7b30000000000000000000000005f5260205f604460105f875af161074d576040516bffffffffffffffffffffffff163d5f823e3d81fd5b3d153d601f1060015f5114161761076b57633e3f8f735f526004601cfd5b5f603452505050565b818382375f9101908152919050565b5f5b8381101561079d578181015183820152602001610785565b50505f910152565b602081525f82518060208401526107c3816040850160208701610783565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610818575f80fd5b919050565b5f806040838503121561082e575f80fd5b610837836107f5565b9150610845602084016107f5565b90509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f805f805f60a0868803121561088f575f80fd5b610898866107f5565b9450602086013593506108ad604087016107f5565b925060608601359150608086013567ffffffffffffffff808211156108d0575f80fd5b818801915088601f8301126108e3575f80fd5b8135818111156108f5576108f561084e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561093b5761093b61084e565b816040528281528b6020848701011115610953575f80fd5b826020860160208301375f6020848301015280955050505050509295509295909350565b5f60208284031215610987575f80fd5b5051919050565b5f6020828403121561099e575f80fd5b815180151581146109ad575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820281158282048414176109f8576109f86109b4565b92915050565b5f82610a31577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b808201808211156109f8576109f86109b4565b5f8251610a5a818460208701610783565b919091019291505056fea164736f6c6343000819000a","sourceMap":"3255:2670:1:-:0;;;3622:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;3665:24:1;;;3255:2670;;14:290:2;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:2;;214:42;;204:70;;270:1;267;260:12;204:70;293:5;14:290;-1:-1:-1;;;14:290:2:o;:::-;3255:2670:1;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405260043610610037575f3560e01c80633dad0c9c1461011c57806394b41e521461013d578063ed856306146101995761003e565b3661003e57005b5f3660605f807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16858560405161008b929190610774565b5f60405180830381855af49150503d805f81146100c3576040519150601f19603f3d011682016040523d82523d5f602084013e6100c8565b606091505b50915091508161010f57806040517fa5fa8d2b00000000000000000000000000000000000000000000000000000000815260040161010691906107a5565b60405180910390fd5b8051945060200192505050f35b348015610127575f80fd5b5061013b61013636600461081d565b6101b8565b005b348015610148575f80fd5b506101707f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156101a4575f80fd5b5061013b6101b336600461087b565b6102eb565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610222573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102469190610977565b905080156102e6576040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb906044016020604051808303815f875af11580156102c0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102e4919061098e565b505b505050565b5f60608173ffffffffffffffffffffffffffffffffffffffff88166103ff5761271061031788476109e1565b61032191906109fe565b905083515f036103d5578415610363576040517f01da157200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff87169082905f81818185875af1925050503d805f81146103b6576040519150601f19603f3d011682016040523d82523d5f602084013e6103bb565b606091505b5090935091506103cd83151583610602565b5050506105fb565b83516103e2602087610a36565b95508511156103f5576103f56032610614565b8085850152610525565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9061271090899073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa15801561046f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104939190610977565b61049d91906109e1565b6104a791906109fe565b85519091506104b7602088610a36565b96508611156104ca576104ca6032610614565b80868601528673ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16146105235761052373ffffffffffffffffffffffffffffffffffffffff8a168883610625565b505b8573ffffffffffffffffffffffffffffffffffffffff16818560405161054b9190610a49565b5f6040518083038185875af1925050503d805f8114610585576040519150601f19603f3d011682016040523d82523d5f602084013e61058a565b606091505b50909350915061059c83151583610602565b81511580156105c0575073ffffffffffffffffffffffffffffffffffffffff86163b155b156105f7576040517f82d5d76a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505b5050505050565b816106105761061081610702565b5050565b634e487b715f52806020526024601cfd5b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919085169063dd62ed3e90604401602060405180830381865afa158015610698573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106bc9190610977565b9050818110156102e45780156106d7576106d784845f61070a565b6102e484847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61070a565b805160208201fd5b81601452806034526f095ea7b30000000000000000000000005f5260205f604460105f875af161074d576040516bffffffffffffffffffffffff163d5f823e3d81fd5b3d153d601f1060015f5114161761076b57633e3f8f735f526004601cfd5b5f603452505050565b818382375f9101908152919050565b5f5b8381101561079d578181015183820152602001610785565b50505f910152565b602081525f82518060208401526107c3816040850160208701610783565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610818575f80fd5b919050565b5f806040838503121561082e575f80fd5b610837836107f5565b9150610845602084016107f5565b90509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f805f805f60a0868803121561088f575f80fd5b610898866107f5565b9450602086013593506108ad604087016107f5565b925060608601359150608086013567ffffffffffffffff808211156108d0575f80fd5b818801915088601f8301126108e3575f80fd5b8135818111156108f5576108f561084e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561093b5761093b61084e565b816040528281528b6020848701011115610953575f80fd5b826020860160208301375f6020848301015280955050505050509295509295909350565b5f60208284031215610987575f80fd5b5051919050565b5f6020828403121561099e575f80fd5b815180151581146109ad575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820281158282048414176109f8576109f86109b4565b92915050565b5f82610a31577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b808201808211156109f8576109f86109b4565b5f8251610a5a818460208701610783565b919091019291505056fea164736f6c6343000819000a","sourceMap":"3255:2670:1:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3860:12;3885;3899:19;3922:10;:23;;3946:5;;3922:30;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3884:68;;;;3967:7;3962:64;;4008:6;3997:18;;;;;;;;;;;:::i;:::-;;;;;;;;3962:64;3255:2670;;;-1:-1:-1;3255:2670:1;;;-1:-1:-1;;;3255:2670:1;5587:336;;;;;;;;;;-1:-1:-1;5587:336:1;;;;;:::i;:::-;;:::i;:::-;;3495:35;;;;;;;;;;;;;;;;;;1645:42:2;1633:55;;;1615:74;;1603:2;1588:18;3495:35:1;;;;;;;4061:1520;;;;;;;;;;-1:-1:-1;4061:1520:1;;;;;:::i;:::-;;:::i;5587:336::-;5731:38;;;;;5763:4;5731:38;;;1615:74:2;5713:15:1;;5731:23;;;;;;1588:18:2;;5731:38:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5713:56;-1:-1:-1;5838:11:1;;5834:83;;5865:41;;;;;:22;3541:55:2;;;5865:41:1;;;3523:74:2;3613:18;;;3606:34;;;5865:22:1;;;;;3496:18:2;;5865:41:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;5834:83;5651:272;5587:336;;:::o;4061:1520::-;4181:12;4203:23;4181:12;4264:23;;;4260:1077;;3387:6;4312:27;4336:3;4312:21;:27;:::i;:::-;4311:37;;;;:::i;:::-;4303:45;;4366:4;:11;4381:1;4366:16;4362:510;;4406:11;;4402:39;;4426:15;;;;;;;;;;;;;;4402:39;4483:36;;:18;;;;4509:5;;4483:36;;;;4509:5;4483:18;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4459:60:1;;-1:-1:-1;4459:60:1;-1:-1:-1;4537:31:1;:19;;;4459:60;4537:19;:31::i;:::-;4586:7;;;;;4362:510;4652:11;;4636:12;4646:2;4636:12;;:::i;:::-;;;;4635:28;4631:113;;;4687:38;881:4;4687:11;:38::i;:::-;4834:5;4825:6;4819:4;4815:17;4808:32;4260:1077;;;4920:42;;;;;4956:4;4920:42;;;1615:74:2;4902:14:1;;3387:6;;4965:3;;4920:27;;;;;;1588:18:2;;4920:42:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:48;;;;:::i;:::-;4919:58;;;;:::i;:::-;5012:11;;4902:75;;-1:-1:-1;4996:12:1;5006:2;4996:12;;:::i;:::-;;;;4995:28;4991:105;;;5043:38;881:4;5043:11;:38::i;:::-;5178:6;5169;5163:4;5159:17;5152:33;5238:4;5216:26;;5224:9;5216:26;;;5212:115;;5262:50;:36;;;5299:4;5305:6;5262:36;:50::i;:::-;4888:449;4260:1077;5379:4;5371:18;;5397:5;5404:4;5371:38;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5347:62:1;;-1:-1:-1;5347:62:1;-1:-1:-1;5419:31:1;:19;;;5347:62;5419:19;:31::i;:::-;5503:17;;:22;:47;;;;-1:-1:-1;5529:16:1;;;;:21;5503:47;5499:75;;;5559:15;;;;;;;;;;;;;;5499:75;4171:1410;;;4061:1520;;;;;;:::o;1182:140::-;1267:7;1262:54;;1290:15;1298:6;1290:7;:15::i;:::-;1182:140;;:::o;135:227::-;240:10;234:4;227:24;310:4;304;297:18;341:4;335;328:18;2891:360;3005:39;;;;;3029:4;3005:39;;;5441:34:2;3005:15:1;5511::2;;;5491:18;;;5484:43;2985:17:1;;3005:15;;;;;;5353:18:2;;3005:39:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2985:59;;3070:6;3058:9;:18;3054:191;;;3096:14;;3092:83;;3130:30;3142:5;3149:7;3158:1;3130:11;:30::i;:::-;3188:46;3200:5;3207:7;3216:17;3188:11;:46::i;1019:157::-;1152:6;1146:13;1139:4;1131:6;1127:17;1120:40;1357:1528;1491:2;1485:4;1478:16;1548:6;1542:4;1535:20;1841:34;1835:4;1828:48;2194:4;2188;2182;2176;2170;2163:5;2156;2151:48;2141:253;;2268:4;2262:11;2234:26;2230:44;2317:16;2311:4;2306:3;2291:43;2363:16;2358:3;2351:29;2141:253;2623:16;2616:24;2596:16;2590:4;2587:26;2580:4;2573;2567:11;2564:21;2560:54;2557:84;2547:221;;2674:10;2668:4;2661:24;2749:4;2743;2736:18;2547:221;2795:4;2789;2782:18;1357:1528;;;:::o;14:271:2:-;197:6;189;184:3;171:33;153:3;223:16;;248:13;;;223:16;14:271;-1:-1:-1;14:271:2:o;290:250::-;375:1;385:113;399:6;396:1;393:13;385:113;;;475:11;;;469:18;456:11;;;449:39;421:2;414:10;385:113;;;-1:-1:-1;;532:1:2;514:16;;507:27;290:250::o;545:453::-;692:2;681:9;674:21;655:4;724:6;718:13;767:6;762:2;751:9;747:18;740:34;783:79;855:6;850:2;839:9;835:18;830:2;822:6;818:15;783:79;:::i;:::-;914:2;902:15;919:66;898:88;883:104;;;;989:2;879:113;;545:453;-1:-1:-1;;545:453:2:o;1003:196::-;1071:20;;1131:42;1120:54;;1110:65;;1100:93;;1189:1;1186;1179:12;1100:93;1003:196;;;:::o;1204:260::-;1272:6;1280;1333:2;1321:9;1312:7;1308:23;1304:32;1301:52;;;1349:1;1346;1339:12;1301:52;1372:29;1391:9;1372:29;:::i;:::-;1362:39;;1420:38;1454:2;1443:9;1439:18;1420:38;:::i;:::-;1410:48;;1204:260;;;;;:::o;1700:184::-;1752:77;1749:1;1742:88;1849:4;1846:1;1839:15;1873:4;1870:1;1863:15;1889:1266;1993:6;2001;2009;2017;2025;2078:3;2066:9;2057:7;2053:23;2049:33;2046:53;;;2095:1;2092;2085:12;2046:53;2118:29;2137:9;2118:29;:::i;:::-;2108:39;;2194:2;2183:9;2179:18;2166:32;2156:42;;2217:38;2251:2;2240:9;2236:18;2217:38;:::i;:::-;2207:48;;2302:2;2291:9;2287:18;2274:32;2264:42;;2357:3;2346:9;2342:19;2329:33;2381:18;2422:2;2414:6;2411:14;2408:34;;;2438:1;2435;2428:12;2408:34;2476:6;2465:9;2461:22;2451:32;;2521:7;2514:4;2510:2;2506:13;2502:27;2492:55;;2543:1;2540;2533:12;2492:55;2579:2;2566:16;2601:2;2597;2594:10;2591:36;;;2607:18;;:::i;:::-;2741:2;2735:9;2803:4;2795:13;;2646:66;2791:22;;;2815:2;2787:31;2783:40;2771:53;;;2839:18;;;2859:22;;;2836:46;2833:72;;;2885:18;;:::i;:::-;2925:10;2921:2;2914:22;2960:2;2952:6;2945:18;3000:7;2995:2;2990;2986;2982:11;2978:20;2975:33;2972:53;;;3021:1;3018;3011:12;2972:53;3077:2;3072;3068;3064:11;3059:2;3051:6;3047:15;3034:46;3122:1;3117:2;3112;3104:6;3100:15;3096:24;3089:35;3143:6;3133:16;;;;;;;1889:1266;;;;;;;;:::o;3160:184::-;3230:6;3283:2;3271:9;3262:7;3258:23;3254:32;3251:52;;;3299:1;3296;3289:12;3251:52;-1:-1:-1;3322:16:2;;3160:184;-1:-1:-1;3160:184:2:o;3651:277::-;3718:6;3771:2;3759:9;3750:7;3746:23;3742:32;3739:52;;;3787:1;3784;3777:12;3739:52;3819:9;3813:16;3872:5;3865:13;3858:21;3851:5;3848:32;3838:60;;3894:1;3891;3884:12;3838:60;3917:5;3651:277;-1:-1:-1;;;3651:277:2:o;3933:184::-;3985:77;3982:1;3975:88;4082:4;4079:1;4072:15;4106:4;4103:1;4096:15;4122:168;4195:9;;;4226;;4243:15;;;4237:22;;4223:37;4213:71;;4264:18;;:::i;:::-;4122:168;;;;:::o;4295:274::-;4335:1;4361;4351:189;;4396:77;4393:1;4386:88;4497:4;4494:1;4487:15;4525:4;4522:1;4515:15;4351:189;-1:-1:-1;4554:9:2;;4295:274::o;4784:125::-;4849:9;;;4870:10;;;4867:36;;;4883:18;;:::i;4914:287::-;5043:3;5081:6;5075:13;5097:66;5156:6;5151:3;5144:4;5136:6;5132:17;5097:66;:::i;:::-;5179:16;;;;;4914:287;-1:-1:-1;;4914:287:2:o","linkReferences":{},"immutableReferences":{"223":[{"start":70,"length":32},{"start":334,"length":32}]}},"methodIdentifiers":{"cleanupERC20(address,address)":"3dad0c9c","multicall3()":"94b41e52","sellToPool(address,uint256,address,uint256,bytes)":"ed856306"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_multicall3\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"CallFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOffset\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTarget\",\"type\":\"error\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"refundTo\",\"type\":\"address\"}],\"name\":\"cleanupERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"multicall3\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sellToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"bps\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"sellToPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Multicall3Router.sol\":\"Multicall3Router\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[\":@arbitrum/=node_modules/@arbitrum/\",\":@axelar-network/=node_modules/@axelar-network/\",\":@chainlink/=node_modules/@chainlink/\",\":@eth-optimism/=node_modules/@eth-optimism/\",\":@hyperlane-xyz/=node_modules/@hyperlane-xyz/core/contracts/\",\":@layerzerolabs/=node_modules/@layerzerolabs/\",\":@offchainlabs/=node_modules/@offchainlabs/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@permit2/=lib/permit2/src/\",\":@scroll-tech/=node_modules/@scroll-tech/\",\":@uniswap/=node_modules/@uniswap/\",\":@zksync/=node_modules/@zksync/\",\":fx-portal/=node_modules/fx-portal/\",\":hardhat-deploy/=node_modules/hardhat-deploy/\",\":solady/=node_modules/solady/\",\":solidity-bytes-utils/=node_modules/solidity-bytes-utils/\"]},\"sources\":{\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bd39944e8fc06be6dbe2dd1d8449b5336e23c6a7ba3e8e9ae5ae0f37f35283f5\",\"dweb:/ipfs/QmPV3FGYjVwvKSgAXKUN3r9T9GwniZz83CxBpM7vyj2G53\"]},\"src/Multicall3Router.sol\":{\"keccak256\":\"0xa0a4965ec74d45bd3dd23197a45d356a5d110bbeaa077c619a6037dfe857552f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ab2a32ebb0c4ab65fd15422490ad98e3bbe78d5eb998edba6322eec632e321ee\",\"dweb:/ipfs/QmaMjkTbBuyvj185oVH29ELLN1ExESXC1Srsr36yD5FZw3\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.25+commit.b61c2a91"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"_multicall3","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes","name":"returnData","type":"bytes"}],"type":"error","name":"CallFailed"},{"inputs":[],"type":"error","name":"InvalidOffset"},{"inputs":[],"type":"error","name":"InvalidTarget"},{"inputs":[],"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"refundTo","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"cleanupERC20"},{"inputs":[],"stateMutability":"view","type":"function","name":"multicall3","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"bps","type":"uint256"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"sellToPool"},{"inputs":[],"stateMutability":"payable","type":"receive"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@arbitrum/=node_modules/@arbitrum/","@axelar-network/=node_modules/@axelar-network/","@chainlink/=node_modules/@chainlink/","@eth-optimism/=node_modules/@eth-optimism/","@hyperlane-xyz/=node_modules/@hyperlane-xyz/core/contracts/","@layerzerolabs/=node_modules/@layerzerolabs/","@offchainlabs/=node_modules/@offchainlabs/","@openzeppelin/=node_modules/@openzeppelin/","@permit2/=lib/permit2/src/","@scroll-tech/=node_modules/@scroll-tech/","@uniswap/=node_modules/@uniswap/","@zksync/=node_modules/@zksync/","fx-portal/=node_modules/fx-portal/","hardhat-deploy/=node_modules/hardhat-deploy/","solady/=node_modules/solady/","solidity-bytes-utils/=node_modules/solidity-bytes-utils/"],"optimizer":{"enabled":true,"runs":10000},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/Multicall3Router.sol":"Multicall3Router"},"evmVersion":"shanghai","libraries":{}},"sources":{"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol":{"keccak256":"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305","urls":["bzz-raw://bd39944e8fc06be6dbe2dd1d8449b5336e23c6a7ba3e8e9ae5ae0f37f35283f5","dweb:/ipfs/QmPV3FGYjVwvKSgAXKUN3r9T9GwniZz83CxBpM7vyj2G53"],"license":"MIT"},"src/Multicall3Router.sol":{"keccak256":"0xa0a4965ec74d45bd3dd23197a45d356a5d110bbeaa077c619a6037dfe857552f","urls":["bzz-raw://ab2a32ebb0c4ab65fd15422490ad98e3bbe78d5eb998edba6322eec632e321ee","dweb:/ipfs/QmaMjkTbBuyvj185oVH29ELLN1ExESXC1Srsr36yD5FZw3"],"license":"MIT"}},"version":1},"id":1} \ No newline at end of file diff --git a/tests/integration_tests/contracts/contracts/MyToken.sol b/tests/integration_tests/contracts/contracts/MyToken.sol new file mode 100644 index 000000000..e2544e973 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/MyToken.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +import "@openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol"; +import "@openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import "@openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20PermitUpgradeable.sol"; +import "@openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; +import "@openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; + +contract MyToken is Initializable, ERC20Upgradeable, OwnableUpgradeable, ERC20PermitUpgradeable, UUPSUpgradeable { + constructor() { + _disableInitializers(); + } + + function initialize(address initialOwner) initializer public { + __ERC20_init("MyToken", "MTK"); + __Ownable_init(initialOwner); + __ERC20Permit_init("MyToken"); + __UUPSUpgradeable_init(); + + _mint(msg.sender, 1000000 * 10 ** decimals()); + } + + function mint(address to, uint256 amount) public onlyOwner { + _mint(to, amount); + } + + function _authorizeUpgrade(address newImplementation) + internal + onlyOwner + override + {} +} \ No newline at end of file diff --git a/tests/integration_tests/contracts/contracts/MyToken2.sol b/tests/integration_tests/contracts/contracts/MyToken2.sol new file mode 100644 index 000000000..ddb6fc390 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/MyToken2.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +import "./MyToken.sol"; + +contract MyToken2 is MyToken { + function newFeature() public pure returns (string memory) { + return "Upgraded!"; + } +} \ No newline at end of file diff --git a/tests/integration_tests/contracts/contracts/Random.sol b/tests/integration_tests/contracts/contracts/Random.sol new file mode 100644 index 000000000..e38374437 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/Random.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +contract Random { + function randomTokenId() public view returns (uint256) { + return uint256(keccak256(abi.encodePacked(block.prevrandao))); + } +} diff --git a/tests/integration_tests/contracts/contracts/StakingI.sol b/tests/integration_tests/contracts/contracts/StakingI.sol new file mode 120000 index 000000000..73006e7b8 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/StakingI.sol @@ -0,0 +1 @@ +../../../../precompiles/staking/StakingI.sol \ No newline at end of file diff --git a/tests/integration_tests/contracts/contracts/TestBlockTxProperties.sol b/tests/integration_tests/contracts/contracts/TestBlockTxProperties.sol new file mode 100644 index 000000000..7e1c294f3 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/TestBlockTxProperties.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +contract TestBlockTxProperties { + function getBlockHash(uint256 blockNumber) public view returns (bytes32) { + return blockhash(blockNumber); + } +} diff --git a/tests/integration_tests/contracts/contracts/TestERC20A.sol b/tests/integration_tests/contracts/contracts/TestERC20A.sol new file mode 100644 index 000000000..2218c43f2 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/TestERC20A.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract TestERC20A is ERC20 { + constructor() ERC20("Bitcoin MAX", "MAX") { + _mint(msg.sender, 100000000000000000000000000); + } + + function test_log0() public { + bytes32 data = "hello world"; + assembly { + let p := mload(0x20) + mstore(p, data) + log0(p, 0x20) + } + } +} diff --git a/tests/integration_tests/contracts/contracts/TestExploitContract.sol b/tests/integration_tests/contracts/contracts/TestExploitContract.sol new file mode 100644 index 000000000..94a39b8f5 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/TestExploitContract.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +contract TestExploitContract { + function dos() public pure { + assembly { + return(0, 0x36d800) + } + } +} diff --git a/tests/integration_tests/contracts/contracts/TestMessageCall.sol b/tests/integration_tests/contracts/contracts/TestMessageCall.sol new file mode 100644 index 000000000..b4b5e041e --- /dev/null +++ b/tests/integration_tests/contracts/contracts/TestMessageCall.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +contract Inner { + event TestEvent(uint256); + function test() public returns (uint256) { + emit TestEvent(42); + return 42; + } +} + +// An contract that do lots of message calls +contract TestMessageCall { + Inner _inner; + constructor() { + _inner = new Inner(); + } + + function test(uint iterations) public returns (uint256) { + uint256 n = 0; + for (uint i = 0; i < iterations; i++) { + n += _inner.test(); + } + return n; + } + + function inner() public view returns (address) { + return address(_inner); + } +} diff --git a/tests/integration_tests/contracts/contracts/TestRevert.sol b/tests/integration_tests/contracts/contracts/TestRevert.sol new file mode 100644 index 000000000..f175fa7db --- /dev/null +++ b/tests/integration_tests/contracts/contracts/TestRevert.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +contract TestRevert { + uint256 state; + constructor() { + state = 0; + } + + function transfer(uint256 value) public payable { + uint256 minimal = 5 * 10 ** 18; + state = value; + if (state < minimal) { + revert("Not enough tokens to transfer"); + } + } + + function query() public view returns (uint256) { + return state; + } + + // 0x9ffb86a5 + function revertWithMsg() public pure { + revert("Function has been reverted"); + } + + // 0x3246485d + function revertWithoutMsg() public pure { + revert(); + } +} diff --git a/tests/integration_tests/contracts/contracts/WETH9.sol b/tests/integration_tests/contracts/contracts/WETH9.sol new file mode 100644 index 000000000..0fbe49cc1 --- /dev/null +++ b/tests/integration_tests/contracts/contracts/WETH9.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +contract WETH9 { + string public name; + string public symbol; + uint8 public decimals; + + event Approval(address indexed src, address indexed guy, uint wad); + event Transfer(address indexed src, address indexed dst, uint wad); + event Deposit(address indexed dst, uint wad); + event Withdrawal(address indexed src, uint wad); + + mapping (address => uint) public balanceOf; + mapping (address => mapping (address => uint)) public allowance; + + constructor(string memory name_, string memory symbol_, uint8 decimals_) { + name=name_; + symbol=symbol_; + decimals=decimals_; + } + + receive() external payable { + deposit(); + } + fallback() external payable { + deposit(); + } + function deposit() public payable { + balanceOf[msg.sender] += msg.value; + emit Deposit(msg.sender, msg.value); + } + function withdraw(uint wad) public { + require(balanceOf[msg.sender] >= wad); + balanceOf[msg.sender] -= wad; + (bool s,) = msg.sender.call{value: wad}(""); + require(s, "WOM: ETH transfer failed"); + emit Withdrawal(msg.sender, wad); + } + + function totalSupply() public view returns (uint) { + return address(this).balance; + } + + function approve(address guy, uint wad) public returns (bool) { + allowance[msg.sender][guy] = wad; + emit Approval(msg.sender, guy, wad); + return true; + } + + function transfer(address dst, uint wad) public returns (bool) { + return transferFrom(msg.sender, dst, wad); + } + + function transferFrom(address src, address dst, uint wad) + public + returns (bool) + { + require(balanceOf[src] >= wad); + + if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) { + require(allowance[src][msg.sender] >= wad); + allowance[src][msg.sender] -= wad; + } + + balanceOf[src] -= wad; + balanceOf[dst] += wad; + + emit Transfer(src, dst, wad); + + return true; + } +} diff --git a/tests/integration_tests/contracts/openzeppelin-contracts-upgradeable b/tests/integration_tests/contracts/openzeppelin-contracts-upgradeable new file mode 160000 index 000000000..625fb3c2b --- /dev/null +++ b/tests/integration_tests/contracts/openzeppelin-contracts-upgradeable @@ -0,0 +1 @@ +Subproject commit 625fb3c2b2696f1747ba2e72d1e1113066e6c177 diff --git a/tests/integration_tests/contracts/remappings.txt b/tests/integration_tests/contracts/remappings.txt new file mode 100644 index 000000000..a3fb38a52 --- /dev/null +++ b/tests/integration_tests/contracts/remappings.txt @@ -0,0 +1,2 @@ +@openzeppelin/contracts/=openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/ +@openzeppelin-contracts-upgradeable/contracts/=openzeppelin-contracts-upgradeable/contracts/ \ No newline at end of file diff --git a/tests/integration_tests/expected_constants.py b/tests/integration_tests/expected_constants.py new file mode 100644 index 000000000..1c81ffdfe --- /dev/null +++ b/tests/integration_tests/expected_constants.py @@ -0,0 +1,27 @@ +EXPECTED_CALLTRACERS = { + "from": "0x378c50d9264c63f3f92b806d4ee56e9d86ffb3ec", + "gas": "0x5208", + "gasUsed": "0x5208", + "input": "0x", + "to": "0xd09f7c8c4529cb5d387aa17e33d707c529a6f694", + "type": "CALL", + "value": "0x64", +} + +EXPECTED_STRUCT_TRACER = { + "failed": False, + "gas": 21000, + "returnValue": "0x", + "structLogs": [], +} + +EXPECTED_CONTRACT_CREATE_TRACER = { + "from": "0x55fa49928e9cfd44c23a8e9b1afab27a76015041", + "gas": "0xc6ac6", + "gasUsed": "0xc4d38", + "input": "0x6080346200037d576040906001600160401b03908083018281118282101762000288578352600b81526020906a084d2e8c6ded2dc409a82b60ab1b82820152835192848401848110828211176200028857855260038085526209a82b60eb1b84860152825182811162000288578154906001948583811c9316801562000372575b878410146200035e578190601f938481116200030b575b508790848311600114620002a8575f926200029c575b50505f1982851b1c191690851b1782555b8551928311620002885760049586548581811c911680156200027d575b878210146200026a5782811162000222575b5085918411600114620001bb579383949184925f95620001af575b50501b925f19911b1c19161782555b331562000199576002546a52b7d2dcc80cd2e4000000928382018092116200018657505f917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9160025533835282815284832084815401905584519384523393a351610bc49081620003828239f35b601190634e487b7160e01b5f525260245ffd5b505f602492519163ec442f0560e01b8352820152fd5b015193505f8062000108565b9190601f19841692875f5284875f20945f5b89898383106200020a5750505010620001f0575b50505050811b01825562000117565b01519060f8845f19921b161c191690555f808080620001e1565b868601518955909701969485019488935001620001cd565b875f52865f208380870160051c82019289881062000260575b0160051c019086905b82811062000254575050620000ed565b5f815501869062000244565b925081926200023b565b602288634e487b7160e01b5f525260245ffd5b90607f1690620000db565b634e487b7160e01b5f52604160045260245ffd5b015190505f80620000ad565b90879350601f19831691865f52895f20925f5b8b828210620002f45750508411620002dc575b505050811b018255620000be565b01515f1983871b60f8161c191690555f8080620002ce565b8385015186558b97909501949384019301620002bb565b909150845f52875f208480850160051c8201928a861062000354575b918991869594930160051c01915b8281106200034557505062000097565b5f815585945089910162000335565b9250819262000327565b634e487b7160e01b5f52602260045260245ffd5b92607f169262000080565b5f80fdfe60806040526004361015610011575f80fd5b5f803560e01c90816306fdde03146100b757508063095ea7b3146100b257806318160ddd146100ad57806323b872dd146100a8578063313ce567146100a357806370a082311461009e5780637e497d801461009957806395d89b4114610094578063a9059cbb1461008f5763dd62ed3e1461008a575f80fd5b61088f565b610840565b610715565b6106bd565b61065b565b610622565b6104fb565b6104c0565b61037a565b3461026657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102665760035460018082169180821c9184841561025c575b602092838510861461022f576101128560805260a090565b959081156101d3575060011461015f575b61014e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808701610920565b6040518061015b81610269565b0390f35b60035f529394507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8385106101c257505050910190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014e838080610123565b805486860152938201938101610188565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016865250505050151560051b0190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014e838080610123565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526022600452fd5b92607f16926100fa565b80fd5b906020918281526080519283818301525f5b8481106102b95750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6040809697860101520116010190565b60a081015183820160400152810161027b565b6020808252825181830181905293925f5b85811061031c575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6040809697860101520116010190565b8181018301518482016040015282016102dd565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361035357565b5f80fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361035357565b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610353576103b1610330565b60243533156104905773ffffffffffffffffffffffffffffffffffffffff82169182156104605761042882916104053373ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b9073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b60246040517f94280d620000000000000000000000000000000000000000000000000000000081525f6004820152fd5b60246040517fe602df050000000000000000000000000000000000000000000000000000000081525f6004820152fd5b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610353576020600254604051908152f35b346103535760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357610532610330565b61053a610357565b6044359073ffffffffffffffffffffffffffffffffffffffff83165f5260016020526105873360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84036105c7575b6105bb93506109d0565b60405160018152602090f35b8284106105e3576105de836105bb95033383610b71565b6105b1565b6040517ffb8f41b20000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606490fd5b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357602060405160128152f35b346103535760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535773ffffffffffffffffffffffffffffffffffffffff6106a7610330565b165f525f602052602060405f2054604051908152f35b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357602080517f68656c6c6f20776f726c640000000000000000000000000000000000000000008152a0005b34610353575f807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102665760405190806004549060019180831c92808216928315610836575b602092838610851461022f5785885260208801949081156107f7575060011461079f575b61015b876107938189038261098f565b604051918291826102cc565b60045f5294509192917f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8386106107e657505050910190506107938261015b5f80610783565b8054858701529482019481016107ca565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685525050505090151560051b0190506107938261015b5f80610783565b93607f169361075f565b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535761088461087a610330565b60243590336109d0565b602060405160018152f35b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535760206109176108cb610330565b73ffffffffffffffffffffffffffffffffffffffff6108e8610357565b91165f526001835260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54604051908152f35b601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101166080016080811067ffffffffffffffff82111761096257604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761096257604052565b9173ffffffffffffffffffffffffffffffffffffffff91828416928315610b41578116938415610b1157610a218173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b54838110610abc57610ab7928492610a7d7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef96610aa194039173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b5573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b8054820190556040519081529081906020820190565b0390a3565b6040517fe450d38c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff929092166004830152602482015260448101839052606490fd5b60246040517fec442f050000000000000000000000000000000000000000000000000000000081525f6004820152fd5b60246040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081525f6004820152fd5b9073ffffffffffffffffffffffffffffffffffffffff808316156104905781161561046057610405610bc19273ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b5556", # noqa: E501 + "output": "0x60806040526004361015610011575f80fd5b5f803560e01c90816306fdde03146100b757508063095ea7b3146100b257806318160ddd146100ad57806323b872dd146100a8578063313ce567146100a357806370a082311461009e5780637e497d801461009957806395d89b4114610094578063a9059cbb1461008f5763dd62ed3e1461008a575f80fd5b61088f565b610840565b610715565b6106bd565b61065b565b610622565b6104fb565b6104c0565b61037a565b3461026657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102665760035460018082169180821c9184841561025c575b602092838510861461022f576101128560805260a090565b959081156101d3575060011461015f575b61014e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808701610920565b6040518061015b81610269565b0390f35b60035f529394507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8385106101c257505050910190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014e838080610123565b805486860152938201938101610188565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016865250505050151560051b0190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014e838080610123565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526022600452fd5b92607f16926100fa565b80fd5b906020918281526080519283818301525f5b8481106102b95750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6040809697860101520116010190565b60a081015183820160400152810161027b565b6020808252825181830181905293925f5b85811061031c575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6040809697860101520116010190565b8181018301518482016040015282016102dd565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361035357565b5f80fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361035357565b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610353576103b1610330565b60243533156104905773ffffffffffffffffffffffffffffffffffffffff82169182156104605761042882916104053373ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b9073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b60246040517f94280d620000000000000000000000000000000000000000000000000000000081525f6004820152fd5b60246040517fe602df050000000000000000000000000000000000000000000000000000000081525f6004820152fd5b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610353576020600254604051908152f35b346103535760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357610532610330565b61053a610357565b6044359073ffffffffffffffffffffffffffffffffffffffff83165f5260016020526105873360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84036105c7575b6105bb93506109d0565b60405160018152602090f35b8284106105e3576105de836105bb95033383610b71565b6105b1565b6040517ffb8f41b20000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606490fd5b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357602060405160128152f35b346103535760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535773ffffffffffffffffffffffffffffffffffffffff6106a7610330565b165f525f602052602060405f2054604051908152f35b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357602080517f68656c6c6f20776f726c640000000000000000000000000000000000000000008152a0005b34610353575f807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102665760405190806004549060019180831c92808216928315610836575b602092838610851461022f5785885260208801949081156107f7575060011461079f575b61015b876107938189038261098f565b604051918291826102cc565b60045f5294509192917f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8386106107e657505050910190506107938261015b5f80610783565b8054858701529482019481016107ca565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685525050505090151560051b0190506107938261015b5f80610783565b93607f169361075f565b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535761088461087a610330565b60243590336109d0565b602060405160018152f35b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535760206109176108cb610330565b73ffffffffffffffffffffffffffffffffffffffff6108e8610357565b91165f526001835260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54604051908152f35b601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101166080016080811067ffffffffffffffff82111761096257604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761096257604052565b9173ffffffffffffffffffffffffffffffffffffffff91828416928315610b41578116938415610b1157610a218173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b54838110610abc57610ab7928492610a7d7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef96610aa194039173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b5573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b8054820190556040519081529081906020820190565b0390a3565b6040517fe450d38c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff929092166004830152602482015260448101839052606490fd5b60246040517fec442f050000000000000000000000000000000000000000000000000000000081525f6004820152fd5b60246040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081525f6004820152fd5b9073ffffffffffffffffffffffffffffffffffffffff808316156104905781161561046057610405610bc19273ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b5556", # noqa: E501 + "to": "0x38b2601eb7317af793dcc5563d3612580a2b40e6", + "type": "CREATE", + "value": "0x0", +} diff --git a/tests/integration_tests/ibc_utils.py b/tests/integration_tests/ibc_utils.py new file mode 100644 index 000000000..8bc812ff7 --- /dev/null +++ b/tests/integration_tests/ibc_utils.py @@ -0,0 +1,140 @@ +import json +import os +import subprocess +import tempfile +from contextlib import contextmanager +from pathlib import Path +from typing import NamedTuple + +from pystarport import cluster, ports +from pystarport.utils import wait_for_new_blocks, wait_for_port + +from .network import Evm, Hermes, setup_custom_evm +from .utils import ( + ADDRESS_PREFIX, + CHAIN_ID, + CMD, + DEFAULT_DENOM, + escrow_address, +) + + +class IBCNetwork(NamedTuple): + ibc1: Evm + ibc2: Evm + hermes: Hermes | None + + +def add_key(hermes, chain, mnemonic_env, key_name): + with tempfile.NamedTemporaryFile("w", delete=False) as f: + f.write(os.getenv(mnemonic_env)) + path = f.name + try: + subprocess.check_call( + [ + "hermes", + "--config", + hermes.configpath, + "keys", + "add", + "--hd-path", + "m/44'/60'/0'/0/0", + "--chain", + chain, + "--mnemonic-file", + path, + "--key-name", + key_name, + "--overwrite", + ] + ) + finally: + os.unlink(path) + + +def call_hermes_cmd(hermes, incentivized, version, b_chain="evm-canary-net-2"): + subprocess.check_call( + [ + "hermes", + "--config", + hermes.configpath, + "create", + "channel", + "--a-port", + "transfer", + "--b-port", + "transfer", + "--a-chain", + CHAIN_ID, + "--b-chain", + b_chain, + "--new-client-connection", + "--yes", + ] + + ( + [ + "--channel-version", + json.dumps(version), + ] + if incentivized + else [] + ) + ) + add_key(hermes, CHAIN_ID, "SIGNER1_MNEMONIC", "signer1") + add_key(hermes, b_chain, "SIGNER2_MNEMONIC", "signer2") + + +def prepare_network(tmp_path, name, chain, b_chain="evm-canary-net-2", cmd=CMD): + name = f"configs/{name}.jsonnet" + with contextmanager(setup_custom_evm)( + tmp_path, + 27000, + Path(__file__).parent / name, + relayer=cluster.Relayer.HERMES.value, + chain=chain, + ) as ibc1: + cli = ibc1.cosmos_cli() + ibc2 = Evm(ibc1.base_dir.parent / b_chain, chain_binary=cmd) + # wait for grpc ready + wait_for_port(ports.grpc_port(ibc2.base_port(0))) + wait_for_port(ports.grpc_port(ibc1.base_port(0))) + wait_for_new_blocks(ibc2.cosmos_cli(), 1) + wait_for_new_blocks(cli, 1) + version = {"fee_version": "ics29-1", "app_version": "ics20-1"} + path = ibc1.base_dir.parent / "relayer" + hermes = Hermes(path.with_suffix(".toml")) + call_hermes_cmd(hermes, False, version, b_chain=b_chain) + ibc1.supervisorctl("start", "relayer-demo") + yield IBCNetwork(ibc1, ibc2, hermes) + wait_for_port(hermes.port) + + +def hermes_transfer( + ibc, + src_chain, + src_key_name, + src_amount, + dst_chain, + dst_addr, + denom=DEFAULT_DENOM, + memo=None, + prefix=ADDRESS_PREFIX, +): + port = "transfer" + channel = "channel-0" + # wait for hermes + output = subprocess.getoutput( + f"curl -s -X GET 'http://127.0.0.1:{ibc.hermes.port}/state' | jq" + ) + assert json.loads(output)["status"] == "success" + cmd = ( + f"hermes --config {ibc.hermes.configpath} tx ft-transfer " + f"--dst-chain {dst_chain} --src-chain {src_chain} --src-port {port} " + f"--src-channel {channel} --amount {src_amount} " + f"--timeout-height-offset 1000 --number-msgs 1 " + f"--denom {denom} --receiver {dst_addr} --key-name {src_key_name}" + ) + if memo: + cmd += f" --memo '{memo}'" + subprocess.run(cmd, check=True, shell=True) + return f"{port}/{channel}/{denom}", escrow_address(port, channel, prefix=prefix) diff --git a/tests/integration_tests/network.py b/tests/integration_tests/network.py index 5b6d9b2d1..590ade276 100644 --- a/tests/integration_tests/network.py +++ b/tests/integration_tests/network.py @@ -5,6 +5,7 @@ from pathlib import Path import _jsonnet +import tomlkit import web3 from pystarport import cluster, ports from pystarport.expansion import expand @@ -18,7 +19,6 @@ TooManyRedirects, ) from web3 import AsyncHTTPProvider, AsyncWeb3, HTTPProvider, WebSocketProvider -from web3.middleware import ExtraDataToPOAMiddleware from web3.providers.rpc.utils import ExceptionRetryConfiguration from .cosmoscli import CosmosCLI @@ -109,6 +109,13 @@ def supervisorctl(self, *args): return supervisorctl(self.base_dir / "../tasks.ini", *args) +class Hermes: + def __init__(self, config: Path): + self.configpath = config + self.config = tomlkit.loads(config.read_text()) + self.port = 3000 + + def setup_evm(path, base_port, chain): cfg = Path(__file__).parent / ("configs/enable-indexer.jsonnet") yield from setup_custom_evm(path, base_port, cfg, chain=chain) diff --git a/tests/integration_tests/poetry.lock b/tests/integration_tests/poetry.lock index 253400c53..7d450fdd0 100644 --- a/tests/integration_tests/poetry.lock +++ b/tests/integration_tests/poetry.lock @@ -920,9 +920,9 @@ web3 = ">=7.12.0" [package.source] type = "git" -url = "https://github.com/yihuang/eth-contract.git" -reference = "main" -resolved_reference = "818d39d43a150cd2c36ea1a5c89db3461f80a8fa" +url = "https://github.com/mmsqe/eth-contract.git" +reference = "event" +resolved_reference = "ad4b03b2d4c8d206585af7bb2a576a4a56d7efe4" [[package]] name = "eth-hash" @@ -1430,6 +1430,32 @@ files = [ [package.dependencies] referencing = ">=0.31.0" +[[package]] +name = "maturin" +version = "1.5.1" +description = "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "maturin-1.5.1-py3-none-linux_armv6l.whl", hash = "sha256:589e9b7024007e130b136ba6f1c2c8393a87e42cf968d12852913ab1e3c69ed3"}, + {file = "maturin-1.5.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a1abda07093b3c8ef897626166c02ed64e3e446c48460b28efb51833abf89cbb"}, + {file = "maturin-1.5.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:48a1fbbdc2514525f27d6d339ab97b098ede28759f8593d110c89cc07bbe40ed"}, + {file = "maturin-1.5.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:96d96b1fa3a165db9ca539f764d31da8ebc92e31ca3a1dd6ccd50008d222bd96"}, + {file = "maturin-1.5.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:786bf36a98c4e27cbebb1dc8e432c1bcbbb59e7a9719592cbb89e46a0ccd5bcc"}, + {file = "maturin-1.5.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:d821b37da759884ad09cfee4cd9deac10f4132744cc66e4d9190a1972233bc83"}, + {file = "maturin-1.5.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:62133bf690555bbc8cc6b1c18a0c57b0ab2b4d68d3fcd320eb16df941563fe06"}, + {file = "maturin-1.5.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:6bff165252b1fcc887679ddf7b71b5cc024327ba96ea893133be38c0ed38f163"}, + {file = "maturin-1.5.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c42a95466ffc3de0a3940cd20c57cf0c44fe5ea679375d73422afbb00236c64"}, + {file = "maturin-1.5.1-py3-none-win32.whl", hash = "sha256:d09538b4aa0da4b59fd47cb429003b45bfd5d801714adf1db2511bf8bdea532f"}, + {file = "maturin-1.5.1-py3-none-win_amd64.whl", hash = "sha256:a3db9054222ac79275e082b21cfd234b8e036714a4ff227a0a28f6a3ffa3744d"}, + {file = "maturin-1.5.1-py3-none-win_arm64.whl", hash = "sha256:acf528e51413f6ae489473d64116d8c83f140386349004949d29137c16a82193"}, + {file = "maturin-1.5.1.tar.gz", hash = "sha256:3dd834ece80edb866af18cbd4635e0ecac40139c726428d5f1849ae154b26dca"}, +] + +[package.extras] +patchelf = ["patchelf"] +zig = ["ziglang (>=0.10.0,<0.11.0)"] + [[package]] name = "mccabe" version = "0.7.0" @@ -1976,6 +2002,24 @@ files = [ {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, ] +[[package]] +name = "pyrevm" +version = "0.3.6" +description = "Python bindings to rust evm (revm)" +optional = false +python-versions = ">=3.8" +files = [] +develop = false + +[package.dependencies] +maturin = "1.5.1" + +[package.source] +type = "git" +url = "https://github.com/yihuang/pyrevm.git" +reference = "master" +resolved_reference = "ef0903ad7ca3d01e675105b63302d07cd03ea4b1" + [[package]] name = "pystarport" version = "0.2.5" @@ -2004,8 +2048,8 @@ tomlkit = "^0" [package.source] type = "git" url = "https://github.com/MANTRA-Chain/pystarport.git" -reference = "ref_cmd" -resolved_reference = "e3fecb361b4a6c5a8ab41fc89b8df10705b8df2c" +reference = "main" +resolved_reference = "c18bf5a6ab424cf7542cfbba3b6438f0ae5d42d0" [[package]] name = "pytest" @@ -2864,4 +2908,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "7bb818916fad69593448f930b004777e44e5491af530a0902fa96efb71bd711c" +content-hash = "385f919771b10a139e5ab0ee6df7534bfe6776980da30b0847336ef293a8269b" diff --git a/tests/integration_tests/pyproject.toml b/tests/integration_tests/pyproject.toml index 600056215..ef071f26c 100644 --- a/tests/integration_tests/pyproject.toml +++ b/tests/integration_tests/pyproject.toml @@ -8,7 +8,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" pytest = "^8.3.4" -pystarport = { git = "https://github.com/MANTRA-Chain/pystarport.git", branch = "ref_cmd" } +pystarport = { git = "https://github.com/MANTRA-Chain/pystarport.git", branch = "main" } pytest-github-actions-annotate-failures = "^0.3.0" flake8-black = "^0.3.6" flake8-isort = "^6.1.2" @@ -18,8 +18,9 @@ web3 = "^7.3.0" eth-bloom = "^3.0" flaky = "^3.8.1" pytest-asyncio = "0.25.3" -eth-contract = { git = "https://github.com/yihuang/eth-contract.git", branch = "main" } +eth-contract = { git = "https://github.com/mmsqe/eth-contract.git", branch = "event" } py-ecc = "^8.0.0" +pyrevm = { git = "https://github.com/yihuang/pyrevm.git", branch = "master" } [tool.poetry.dev-dependencies] attrs = "24.2.0" diff --git a/tests/integration_tests/test_account.py b/tests/integration_tests/test_account.py index ed40b2569..03f5756cc 100644 --- a/tests/integration_tests/test_account.py +++ b/tests/integration_tests/test_account.py @@ -1,7 +1,39 @@ import pytest import web3 +from pystarport.utils import w3_wait_for_new_blocks -from .utils import derive_new_account +from .utils import ( + ADDRS, + KEYS, + assert_duplicate, + derive_new_account, + send_transaction, +) + + +def test_transaction_count(evm): + w3 = evm.w3 + blk = hex(w3.eth.block_number) + name = "community" + sender = ADDRS[name] + receiver = derive_new_account().address + n0 = w3.eth.get_transaction_count(receiver, blk) + # ensure transaction send in new block + w3_wait_for_new_blocks(w3, 1, sleep=0.1) + receipt = send_transaction( + w3, + { + "from": sender, + "to": receiver, + "value": 1000, + }, + KEYS[name], + ) + assert receipt.status == 1 + [n1, n2] = [w3.eth.get_transaction_count(receiver, b) for b in [blk, "latest"]] + assert n0 == n1 + assert n0 == n2 + assert_duplicate(evm.cosmos_cli().node_rpc_http, receipt.blockNumber) def test_future_blk(evm): diff --git a/tests/integration_tests/test_basic.py b/tests/integration_tests/test_basic.py new file mode 100644 index 000000000..297064773 --- /dev/null +++ b/tests/integration_tests/test_basic.py @@ -0,0 +1,499 @@ +import asyncio +import time + +import pytest +import web3 +from eth_account import Account +from eth_bloom import BloomFilter +from eth_contract.erc20 import ERC20 +from eth_contract.utils import broadcast_transaction +from eth_contract.utils import send_transaction as send_transaction_async +from eth_utils import big_endian_to_int +from hexbytes import HexBytes +from pystarport.utils import w3_wait_for_new_blocks_async + +from .utils import ( + ACCOUNTS, + ADDRS, + DEFAULT_DENOM, + KEYS, + WEI_PER_DENOM, + AsyncGreeter, + AsyncTestRevert, + Contract, + RevertTestContract, + address_to_bytes32, + assert_transfer, + bech32_to_eth, + build_batch_tx, + build_contract, + contract_address, + create_periodic_vesting_acct, + do_multisig, + recover_community, + send_transaction, + transfer_via_cosmos, +) + + +def test_simple(evm, check_reserve=True): + """ + check number of validators + """ + cli = evm.cosmos_cli() + assert len(cli.validators()) > 0 + if check_reserve: + # check vesting account + cli = evm.cosmos_cli() + denom = cli.get_params("evm")["evm_denom"] + addr = cli.address("reserve") + account = cli.account(addr)["account"] + assert account["type"] == "/cosmos.vesting.v1beta1.DelayedVestingAccount" + assert account["value"]["base_vesting_account"]["original_vesting"] == [ + {"denom": denom, "amount": "100000000000000000000"} + ] + + +def test_vesting(evm, tmp_path): + cli = evm.cosmos_cli() + start_time = int(time.time()) + end_time = start_time + 3000 + name = f"vesting{start_time}" + addr = cli.create_account(name)["address"] + coin = f"1{DEFAULT_DENOM}" + community = cli.address("community") + rsp = cli.create_periodic_vesting_acct(addr, coin, end_time, from_=community) + assert rsp["code"] == 0, rsp["raw_log"] + create_periodic_vesting_acct(cli, tmp_path, coin, from_=community) + + +def test_transfer(evm): + """ + check simple transfer tx success + """ + cli = evm.cosmos_cli() + addr_a = cli.address("community") + addr_b = cli.address("reserve") + assert_transfer(cli, addr_a, addr_b) + + +async def test_send_transaction(evm, check_gas=True): + tx = {"to": ADDRS["signer1"], "value": 1000} + receipt = await send_transaction_async(evm.async_w3, ACCOUNTS["community"], **tx) + if check_gas: + assert receipt.gasUsed == 21000 + + +def test_events(evm, exp_gas_used=806200): + w3 = evm.w3 + sender = ADDRS["community"] + receiver = ADDRS["signer1"] + contract = Contract("TestERC20A") + contract.deploy(w3, exp_gas_used=exp_gas_used) + erc20 = contract.contract + amt = 10 + tx = erc20.functions.transfer(receiver, amt).build_transaction({"from": sender}) + txreceipt = send_transaction(w3, tx) + assert len(txreceipt.logs) == 1 + expect_log = { + "address": erc20.address, + "topics": [ + ERC20.events.Transfer.topic, + address_to_bytes32(sender), + address_to_bytes32(receiver), + ], + "data": HexBytes(amt.to_bytes(32, "big")), + "transactionIndex": 0, + "logIndex": 0, + "removed": False, + } + assert expect_log.items() <= txreceipt.logs[0].items() + + # check block bloom + bloom = BloomFilter( + big_endian_to_int(w3.eth.get_block(txreceipt.blockNumber).logsBloom) + ) + assert HexBytes(erc20.address) in bloom + for topic in expect_log["topics"]: + assert topic in bloom + + block_logs = w3.eth.get_block_receipts(txreceipt.blockNumber)[0].logs[0] + call = w3.provider.make_request + tx_logs = call("eth_getTransactionLogs", [txreceipt.transactionHash])["result"][0] + for k in expect_log: + assert expect_log[k] == block_logs[k] + if k == "address": + assert expect_log[k] == w3.to_checksum_address(tx_logs[k]) + elif k == "data": + assert expect_log[k].hex() == block_logs[k].hex() == tx_logs[k][2:] + elif k == "topics": + assert expect_log[k] == [HexBytes(t) for t in tx_logs[k]] + elif k in ("transactionIndex", "logIndex"): + assert expect_log[k] == int(tx_logs[k], 16) + else: + assert expect_log[k] == tx_logs[k] + + +@pytest.mark.asyncio +async def test_minimal_gas_price(evm): + w3 = evm.async_w3 + tx = { + "to": "0x0000000000000000000000000000000000000000", + "value": 10000, + "gasPrice": 1, + } + with pytest.raises(web3.exceptions.Web3RPCError, match="insufficient fee"): + await send_transaction_async(w3, ACCOUNTS["community"], **tx) + tx["gasPrice"] = await w3.eth.gas_price + receipt = await send_transaction_async(w3, ACCOUNTS["signer1"], **tx) + assert receipt.status == 1 + + +@pytest.mark.asyncio +@pytest.mark.skip(reason="https://github.com/cosmos/evm/pull/806") +async def test_transaction(evm): + w3 = evm.async_w3 + gas_price = await w3.eth.gas_price + gas = 21000 + acct = ACCOUNTS["community"] + sender = acct.address + receiver = ADDRS["signer1"] + + data = {"to": ADDRS["community"], "value": 10000, "gasPrice": gas_price, "gas": gas} + res = await send_transaction_async(w3, acct, **data) + assert res["transactionIndex"] == 0 + + with pytest.raises(web3.exceptions.Web3RPCError, match="tx already in mempool"): + data["nonce"] = await w3.eth.get_transaction_count(sender) - 1 + await send_transaction_async(w3, acct, **data) + + data["nonce"] = await w3.eth.get_transaction_count(sender) + 1 + txhash = await broadcast_transaction(w3, acct, **data) + + data["nonce"] = await w3.eth.get_transaction_count(sender) + receipt = await send_transaction_async(w3, acct, **data) + assert receipt["status"] == 1 + + receipt = await w3.eth.wait_for_transaction_receipt(txhash) + assert receipt["status"] == 1 + + with pytest.raises(web3.exceptions.Web3RPCError, match="intrinsic gas too low"): + await send_transaction_async( + w3, + acct, + to=receiver, + value=10000, + gasPrice=gas_price, + gas=1, + ) + + with pytest.raises(web3.exceptions.Web3RPCError, match="insufficient fee"): + await send_transaction_async( + w3, + acct, + to=receiver, + value=10000, + gas=gas, + gasPrice=1, + ) + + contracts = { + "test_revert_1": AsyncTestRevert(KEYS["validator"]), + "test_revert_2": AsyncTestRevert(KEYS["community"]), + "greeter_1": AsyncGreeter(KEYS["signer1"]), + "greeter_2": AsyncGreeter(KEYS["signer2"]), + } + await w3_wait_for_new_blocks_async(w3, 1) + + deployment_tasks = [contract.deploy(w3) for contract in contracts.values()] + await asyncio.gather(*deployment_tasks) + await w3_wait_for_new_blocks_async(w3, 1) + + call_tasks = [] + call_tasks.append(contracts["test_revert_1"].transfer(5 * (10**18) - 1)) + call_tasks.append(contracts["test_revert_2"].transfer(5 * (10**18))) + call_tasks.append(contracts["greeter_1"].set_greeting("hello")) + call_tasks.append(contracts["greeter_2"].set_greeting("world")) + results = await asyncio.gather(*call_tasks, return_exceptions=True) + + # revert transaction for 1st, normal transaction for others + statuses = [0, 1, 1, 1] + valid_receipts = [] + + for i, result in enumerate(results): + if isinstance(result, Exception): + if i != 0: + raise result + else: + assert result["status"] == statuses[i] + if result["status"] == 1: + valid_receipts.append(result) + + await assert_receipt_transaction_and_block(w3, valid_receipts) + + +async def assert_receipt_transaction_and_block(w3, receipts): + assert len(receipts) >= 1, "should have at least 1 valid receipt" + block_number = await w3.eth.get_block_number() + for receipt in receipts: + assert receipt["blockNumber"] == block_number + tx_indexes = [receipt["transactionIndex"] for receipt in receipts] + assert len(tx_indexes) == len(set(tx_indexes)), "duplicate index found" + block = await w3.eth.get_block(block_number) + + for receipt in receipts: + tx_index = receipt["transactionIndex"] + tx = await w3.eth.get_transaction_by_block(block_number, tx_index) + assert tx["blockNumber"] == block_number + assert tx["transactionIndex"] == receipt["transactionIndex"] + assert tx["hash"] == receipt["transactionHash"] + assert tx["hash"] in block["transactions"] + assert tx["blockNumber"] == block["number"] + + +def test_exception(evm): + w3 = evm.w3 + key = KEYS["community"] + revert = RevertTestContract("TestRevert", private_key=key) + revert.deploy(w3) + contract = revert.contract + with pytest.raises(web3.exceptions.ContractLogicError): + send_transaction( + w3, + contract.functions.transfer(5 * (10**18) - 1).build_transaction(), + key=key, + ) + assert 0 == contract.caller.query() + + receipt = send_transaction( + w3, contract.functions.transfer(5 * (10**18)).build_transaction(), key=key + ) + assert receipt.status == 1, "should be successfully" + assert 5 * (10**18) == contract.caller.query() + + +def test_message_call(evm, diff=5): + "stress test the evm by doing message calls as much as possible" + w3 = evm.w3 + key = KEYS["community"] + msg = Contract("TestMessageCall", private_key=key) + msg.deploy(w3) + iterations = 13000 + addr = ADDRS["community"] + tx = msg.contract.functions.test(iterations).build_transaction( + { + "from": addr, + "nonce": w3.eth.get_transaction_count(addr), + } + ) + + begin = time.time() + tx["gas"] = w3.eth.estimate_gas(tx) + elapsed = time.time() - begin + print("elapsed:", elapsed) + assert elapsed < diff # should finish in reasonable time + + receipt = send_transaction(w3, tx, key=key) + assert 22768266 == receipt.cumulativeGasUsed + assert receipt.status == 1, "shouldn't fail" + assert len(receipt.logs) == iterations + + +def test_log0(evm): + """ + test compliance of empty topics behavior + """ + w3 = evm.w3 + key = KEYS["community"] + empty = Contract("TestERC20A", private_key=key) + empty.deploy(w3) + contract = empty.contract + tx = contract.functions.test_log0().build_transaction({"from": ADDRS["community"]}) + receipt = send_transaction(w3, tx, key=key) + assert len(receipt.logs) == 1 + log = receipt.logs[0] + assert log.topics == [] + data = "0x68656c6c6f20776f726c64000000000000000000000000000000000000000000" + assert log.data == HexBytes(data) + + +async def test_contract(evm, tmp_path): + "test Greeter contract" + cli = evm.cosmos_cli() + recover_community(cli, tmp_path) + w3 = evm.async_w3 + greeter = AsyncGreeter() + await greeter.deploy(w3) + assert "Hello" == await greeter.greet() + # change + receipt = await greeter.set_greeting("world") + assert "world" == await greeter.greet() + assert receipt.status == 1 + + +def test_batch_tx(evm): + "send multiple eth txs in single cosmos tx should be disabled" + w3 = evm.w3 + cli = evm.cosmos_cli() + sender = ADDRS["community"] + recipient = ADDRS["signer1"] + nonce = w3.eth.get_transaction_count(sender) + res = build_contract("TestERC20A") + contract = w3.eth.contract(abi=res["abi"], bytecode=res["bytecode"]) + deploy_tx = contract.constructor().build_transaction( + {"from": sender, "nonce": nonce} + ) + contract = w3.eth.contract(address=contract_address(sender, nonce), abi=res["abi"]) + transfer_tx1 = contract.functions.transfer(recipient, 1000).build_transaction( + {"from": sender, "nonce": nonce + 1, "gas": 200000} + ) + transfer_tx2 = contract.functions.transfer(recipient, 1000).build_transaction( + {"from": sender, "nonce": nonce + 2, "gas": 200000} + ) + + cosmos_tx, tx_hashes = build_batch_tx( + w3, cli, [deploy_tx, transfer_tx1, transfer_tx2], key=KEYS["community"] + ) + rsp = cli.broadcast_tx_json(cosmos_tx) + assert rsp["code"] == 18 + assert f"got {len(tx_hashes)}" in rsp["raw_log"] + + +def test_refund_unused_gas_when_contract_tx_reverted(evm): + """ + Call a smart contract method that reverts with very high gas limit + + Call tx receipt should be status 0 (fail) + Fee is gasUsed * effectiveGasPrice + """ + w3 = evm.w3 + key = KEYS["community"] + sender = ADDRS["community"] + revert = RevertTestContract("TestRevert", private_key=key) + revert.deploy(w3) + contract = revert.contract + more_than_enough_gas = 1000000 + + balance_bef = w3.eth.get_balance(sender) + receipt = send_transaction( + w3, + contract.functions.transfer(5 * (10**18) - 1).build_transaction( + {"gas": more_than_enough_gas} + ), + key=key, + ) + balance_aft = w3.eth.get_balance(sender) + + assert receipt["status"] == 0, "should be a failed tx" + assert receipt["gasUsed"] != more_than_enough_gas + assert ( + balance_bef - balance_aft == receipt["gasUsed"] * receipt["effectiveGasPrice"] + ) + + +@pytest.mark.skip(reason="skipping batch tx test") +def test_failed_transfer_tx(evm): + """ + It's possible to include a failed transfer transaction in batch tx + """ + w3 = evm.w3 + cli = evm.cosmos_cli() + sender = ADDRS["community"] + recipient = ADDRS["signer1"] + nonce = w3.eth.get_transaction_count(sender) + half_balance = w3.eth.get_balance(sender) // 3 + 1 + + # build batch tx, the third tx will fail, but will be included in block + # because of the batch tx. + transfer1 = {"from": sender, "nonce": nonce, "to": recipient, "value": half_balance} + transfer2 = { + "from": sender, + "nonce": nonce + 1, + "to": recipient, + "value": half_balance, + } + transfer3 = { + "from": sender, + "nonce": nonce + 2, + "to": recipient, + "value": half_balance, + } + cosmos_tx, tx_hashes = build_batch_tx( + w3, cli, [transfer1, transfer2, transfer3], KEYS["community"] + ) + rsp = cli.broadcast_tx_json(cosmos_tx) + assert rsp["code"] == 0, rsp["raw_log"] + + receipts = [w3.eth.wait_for_transaction_receipt(h) for h in tx_hashes] + assert receipts[0].status == receipts[1].status == 1 + assert receipts[2].status == 0 + + # check traceTransaction + rsps = [ + w3.provider.make_request("debug_traceTransaction", [h.hex()]) for h in tx_hashes + ] + for rsp, receipt in zip(rsps, receipts): + if receipt.status == 1: + result = rsp["result"] + assert not result["failed"] + assert receipt.gasUsed == result["gas"] + else: + assert rsp["result"] == { + "failed": True, + "gas": 0, + # "gas": 21000, TODO: mmsqe + "returnValue": "0x", + "structLogs": [], + } + + +def test_multisig(evm, tmp_path): + cli = evm.cosmos_cli() + do_multisig(cli, tmp_path, "signer1", "signer2", "multitest1") + + +def test_multisig_cosmos(evm, tmp_path): + cli = evm.cosmos_cli() + recover1 = "recover1" + recover2 = "recover2" + amt = 6_000_000_000_000_000_000 // WEI_PER_DENOM + addr_recover1 = cli.create_account( + recover1, + coin_type=118, + key_type="secp256k1", + )["address"] + addr_recover2 = cli.create_account( + recover2, + coin_type=118, + key_type="secp256k1", + )["address"] + sender = cli.address("community") + transfer_via_cosmos(cli, sender, addr_recover1, amt) + transfer_via_cosmos(cli, sender, addr_recover2, amt) + do_multisig(cli, tmp_path, recover1, recover2, "multitest2") + + +def test_textual(evm): + cli = evm.cosmos_cli() + rsp = cli.transfer( + cli.address("community"), + cli.address("signer2"), + f"1{DEFAULT_DENOM}", + sign_mode="textual", + ) + assert rsp["code"] == 0, rsp["raw_log"] + + +def test_key_src(evm, tmp_path): + cli = evm.cosmos_cli() + acct, mnemonic = Account.create_with_mnemonic(num_words=24) + src = tmp_path / "mnemonic.txt" + src.write_text(mnemonic) + addr = cli.create_account("user", source=src)["address"] + assert bech32_to_eth(addr) == acct.address + + +def test_comet_validator_set(evm): + cli = evm.cosmos_cli() + res = cli.comet_validator_set(cli.block_height()) + assert len(res["validators"]) == len(cli.validators()) diff --git a/tests/integration_tests/test_call.py b/tests/integration_tests/test_call.py new file mode 100644 index 000000000..cf28d4351 --- /dev/null +++ b/tests/integration_tests/test_call.py @@ -0,0 +1,181 @@ +import io +import json +from contextlib import redirect_stdout +from typing import Iterable, Unpack + +import pyrevm +import pytest +from cprotobuf import Field, ProtoEntity +from eth_contract.erc20 import ERC20 +from eth_contract.slots import parse_balance_slot +from eth_contract.utils import ZERO_ADDRESS +from hexbytes import HexBytes +from web3 import Web3 +from web3._utils.contracts import encode_transaction_data +from web3.types import TxParams + +from .utils import ( + ADDRS, + WETH_ADDRESS, + Greeter, + assert_create_erc20_denom, + build_and_deploy_contract_async, +) + + +def test_temporary_contract_code(evm): + state = 100 + w3: Web3 = evm.w3 + greeter = Greeter("Greeter") + data = encode_transaction_data(w3, "intValue", greeter.abi, args=[], kwargs={}) + # call an arbitrary address + address = w3.to_checksum_address("0x0000000000000000000000000000ffffffffffff") + hex_state = f"0x{HexBytes(w3.codec.encode(('uint256',), (state,))).hex()}" + overrides = { + address: { + "code": greeter.code, + "state": { + ("0x" + "0" * 64): hex_state, + }, + }, + } + result = w3.eth.call( + { + "to": address, + "data": data, + }, + "latest", + overrides, + ) + assert (state,) == w3.codec.decode(("uint256",), result) + + +def test_override_state(evm): + w3: Web3 = evm.w3 + greeter = Greeter("Greeter") + greeter.deploy(w3) + contract = greeter.contract + assert "Hello" == contract.functions.greet().call() + assert 0 == contract.functions.intValue().call() + + int_value = 100 + hex_state = f"0x{HexBytes(w3.codec.encode(('uint256',), (int_value,))).hex()}" + state = { + ("0x" + "0" * 64): hex_state, + } + data = encode_transaction_data(w3, "intValue", greeter.abi, args=[], kwargs={}) + result = w3.eth.call( + { + "to": contract.address, + "data": data, + }, + "latest", + { + contract.address: { + "code": greeter.code, + "stateDiff": state, + }, + }, + ) + assert (int_value,) == w3.codec.decode(("uint256",), result) + + # stateDiff don't affect the other state slots + data = encode_transaction_data(w3, "greet", greeter.abi, args=[], kwargs={}) + result = w3.eth.call( + { + "to": contract.address, + "data": data, + }, + "latest", + { + contract.address: { + "to": contract.address, + "stateDiff": state, + }, + }, + ) + assert ("Hello",) == w3.codec.decode(("string",), result) + + # state will overrides the whole state + data = encode_transaction_data(w3, "greet", greeter.abi, args=[], kwargs={}) + result = w3.eth.call( + { + "to": contract.address, + "data": data, + }, + "latest", + { + contract.address: { + "to": contract.address, + "state": state, + }, + }, + ) + assert ("",) == w3.codec.decode(("string",), result) + + +def trace_call(vm: pyrevm.EVM, **tx: Unpack[TxParams]) -> Iterable[dict]: + """ + Capture and parse traces from a pyrevm message call. + """ + with redirect_stdout(io.StringIO()) as out: + vm.message_call( + caller=tx.get("from", ZERO_ADDRESS), + to=tx.get("to", ""), + calldata=tx.get("data"), + value=tx.get("value", 0), + ) + + out.seek(0) + for line in out.readlines(): + yield json.loads(line) + + +@pytest.mark.asyncio +async def test_override_erc20_state(evm): + w3 = evm.async_w3 + community = ADDRS["community"] + _, total = await assert_create_erc20_denom(w3, community) + int_value = total - 1 + + fn = ERC20.fns.balanceOf(community) + vm = pyrevm.EVM(fork_url=evm.w3_http_endpoint(), tracing=True, with_memory=True) + traces = trace_call(vm, to=WETH_ADDRESS, data=fn.data) + fn_slot = parse_balance_slot(HexBytes(WETH_ADDRESS), HexBytes(community), traces) + state_key = f"0x{fn_slot.value(HexBytes(community)).slot.hex()}" + hex_state = "0x" + HexBytes(w3.codec.encode(("uint256",), (int_value,))).hex() + + state = {state_key: hex_state} + + for state_type in ["stateDiff", "state"]: + res = await w3.eth.call( + {"to": WETH_ADDRESS, "data": fn.data}, + "latest", + {WETH_ADDRESS: {state_type: state}}, + ) + assert fn.decode(res) == int_value + + +class StateEntry(ProtoEntity): + key = Field("bytes", 1) + value = Field("bytes", 2) + delete = Field("bool", 3) + + +class StoreStateDiff(ProtoEntity): + name = Field("string", 1) + entries = Field(StateEntry, 2, repeated=True) + + +def create_bank_balance_key(addr_bytes, denom): + balances_prefix = bytes([2]) + addr_len = bytes([len(addr_bytes)]) + # prefix + addr_len + addr + denom + return balances_prefix + addr_len + addr_bytes + denom.encode("utf-8") + + +@pytest.mark.asyncio +async def test_opcode(evm): + contract = await build_and_deploy_contract_async(evm.async_w3, "Random") + res = await contract.caller.randomTokenId() + assert res > 0, res diff --git a/tests/integration_tests/test_contract.py b/tests/integration_tests/test_contract.py new file mode 100644 index 000000000..31653ee5e --- /dev/null +++ b/tests/integration_tests/test_contract.py @@ -0,0 +1,422 @@ +import asyncio +import json +from pathlib import Path + +import pytest +from eth_abi import encode +from eth_contract.contract import Contract, ContractFunction +from eth_contract.create2 import create2_address +from eth_contract.deploy_utils import ( + ensure_create2_deployed, + ensure_createx_deployed, + ensure_deployed_by_create2, + ensure_deployed_by_create3, + ensure_history_storage_deployed, + ensure_multicall3_deployed, +) +from eth_contract.entrypoint import ( + ENTRYPOINT07_ADDRESS, + ENTRYPOINT07_ARTIFACT, + ENTRYPOINT07_SALT, + ENTRYPOINT08_ADDRESS, + ENTRYPOINT08_ARTIFACT, + ENTRYPOINT08_SALT, +) +from eth_contract.erc20 import ERC20 +from eth_contract.history_storage import HISTORY_STORAGE_ADDRESS +from eth_contract.multicall3 import ( + MULTICALL3, + MULTICALL3_ADDRESS, + Call3Value, + multicall, +) +from eth_contract.utils import ZERO_ADDRESS, balance_of, get_initcode, send_transaction +from eth_contract.weth import WETH, WETH9_ARTIFACT +from eth_hash.auto import keccak +from eth_utils import to_bytes +from pystarport.utils import w3_wait_for_new_blocks_async +from web3 import AsyncWeb3 +from web3._utils.contracts import encode_transaction_data +from web3.types import TxParams + +from .utils import ( + ACCOUNTS, + ADDRS, + KEYS, + WETH_ADDRESS, + WETH_SALT, + MockERC20_ARTIFACT, + address_to_bytes32, + assert_weth_flow, + build_and_deploy_contract_async, + build_contract, + create_contract_transaction, +) + +pytestmark = pytest.mark.asyncio + + +MULTICALL3ROUTER_ARTIFACT = json.loads( + Path(__file__) + .parent.joinpath("contracts/contracts/Multicall3Router.json") + .read_text() +) +MULTICALL3ROUTER = create2_address( + get_initcode(MULTICALL3ROUTER_ARTIFACT, MULTICALL3_ADDRESS) +) + + +async def assert_contract_deployed(w3): + account = ACCOUNTS["community"] + await ensure_create2_deployed(w3, account) + await ensure_multicall3_deployed(w3, account) + await ensure_deployed_by_create2( + w3, + account, + get_initcode(WETH9_ARTIFACT), + salt=WETH_SALT, + ) + assert MULTICALL3ROUTER == await ensure_deployed_by_create2( + w3, + account, + get_initcode(MULTICALL3ROUTER_ARTIFACT, MULTICALL3_ADDRESS), + ) + assert await w3.eth.get_code(WETH_ADDRESS) + assert await w3.eth.get_code(MULTICALL3ROUTER) + assert await w3.eth.get_code(MULTICALL3_ADDRESS) + + +async def test_flow(evm): + w3 = evm.async_w3 + await assert_contract_deployed(w3) + account = ACCOUNTS["community"] + await ensure_createx_deployed(w3, account) + await ensure_history_storage_deployed(w3, account) + assert await w3.eth.get_code(HISTORY_STORAGE_ADDRESS) + salt = 100 + initcode = to_bytes(hexstr=build_contract("TestBlockTxProperties")["bytecode"][2:]) + contract = await ensure_deployed_by_create2(w3, account, initcode, salt=salt) + assert contract == "0xe1B18c74a33b1E67B5f505C931Ac264668EA94F5" + height = await w3.eth.block_number + await w3_wait_for_new_blocks_async(w3, 1) + + blockhash = ContractFunction.from_abi( + "function getBlockHash(uint256) external returns (bytes32)" + ) + res = (await blockhash(height).call(w3, to=contract)).hex() + blk = await w3.eth.get_block(height) + assert res == blk.hash.hex(), res + + owner = account.address + # test_create2_deploy + initcode = get_initcode(MockERC20_ARTIFACT, "TEST", "TEST", 18) + token = await ensure_deployed_by_create2(w3, account, initcode, salt=salt) + assert token == "0x854d811d90C6E81B84b29C1d7ed957843cF87bba" + balance = await ERC20.fns.balanceOf(owner).call(w3, to=token) + amt = 1000 + await ERC20.fns.mint(owner, amt).transact(w3, account, to=token) + assert await ERC20.fns.balanceOf(owner).call(w3, to=token) == balance + amt + + # test_create3_deploy + salt = 200 + token = await ensure_deployed_by_create3(w3, account, initcode, salt=salt) + assert token == "0x60f7B32B5799838a480572Aee2A8F0355f607b38" + balance = await ERC20.fns.balanceOf(owner).call(w3, to=token) + await ERC20.fns.mint(owner, 1000).transact(w3, account, to=token) + assert await ERC20.fns.balanceOf(owner).call(w3, to=token) == balance + amt + + # test_weth + weth = WETH(to=WETH_ADDRESS) + await assert_weth_flow(w3, WETH_ADDRESS, owner, account) + + # test_batch_call + users = [ACCOUNTS[key] for key in ["community", "signer1", "signer2"]] + amount = 1000 + amount_all = amount * len(users) + + balances = [(WETH_ADDRESS, ERC20.fns.balanceOf(user.address)) for user in users] + balances_bf = await multicall(w3, balances) + await MULTICALL3.fns.aggregate3Value( + [Call3Value(WETH_ADDRESS, False, amount_all, weth.fns.deposit().data)] + + [ + Call3Value( + WETH_ADDRESS, False, 0, ERC20.fns.transfer(user.address, amount).data + ) + for user in users + ] + ).transact(w3, users[0], value=amount_all) + balances_af = await multicall(w3, balances) + assert all(af - bf == amount for af, bf in zip(balances_af, balances_bf)) + + for user in users: + await ERC20.fns.approve(MULTICALL3_ADDRESS, amount).transact( + w3, user, to=WETH_ADDRESS + ) + + await MULTICALL3.fns.aggregate3Value( + [ + Call3Value( + WETH_ADDRESS, + data=ERC20.fns.transferFrom( + user.address, MULTICALL3_ADDRESS, amount + ).data, + ) + for user in users + ] + + [ + Call3Value( + WETH_ADDRESS, + data=weth.fns.transferFrom( + MULTICALL3_ADDRESS, users[0].address, amount_all + ).data, + ), + ] + ).transact(w3, users[0]) + await weth.fns.withdraw(amount_all).transact(w3, users[0], to=WETH_ADDRESS) + balances_bf = await multicall(w3, balances) + await balance_of(w3, WETH_ADDRESS, MULTICALL3_ADDRESS) == 0 + + # test_multicall3_router + amount_all = amount * len(users) + router = Contract(MULTICALL3ROUTER_ARTIFACT["abi"]) + multicall3 = MULTICALL3ROUTER + + balances = [(WETH_ADDRESS, ERC20.fns.balanceOf(user.address)) for user in users] + balances_bf = await multicall(w3, balances) + assert (await multicall(w3, balances)) == balances_bf + before = await balance_of(w3, ZERO_ADDRESS, users[0].address) + + # convert amount_all into WETH and distribute to users + receipt = await MULTICALL3.fns.aggregate3Value( + [Call3Value(WETH_ADDRESS, False, amount_all, WETH.fns.deposit().data)] + + [ + Call3Value( + WETH_ADDRESS, False, 0, ERC20.fns.transfer(user.address, amount).data + ) + for user in users + ] + ).transact(w3, users[0], to=multicall3, value=amount_all) + before -= receipt["effectiveGasPrice"] * receipt["gasUsed"] + # check users's weth balances + balances_af = await multicall(w3, balances) + assert all(af - bf == amount for af, bf in zip(balances_af, balances_bf)) + balances_bf = balances_af + + # approve multicall3 to transfer WETH on behalf of users + for i, user in enumerate(users): + receipt = await ERC20.fns.approve(multicall3, amount).transact( + w3, user, to=WETH_ADDRESS + ) + if i == 0: + before -= receipt["effectiveGasPrice"] * receipt["gasUsed"] + + # transfer WETH from all users to multicall3, withdraw it, + # and send back to users[0] + receipt = await MULTICALL3.fns.aggregate3Value( + [ + Call3Value( + WETH_ADDRESS, + data=ERC20.fns.transferFrom(user.address, multicall3, amount).data, + ) + for user in users + ] + + [ + Call3Value(WETH_ADDRESS, data=WETH.fns.withdraw(amount_all).data), + Call3Value( + multicall3, + data=router.fns.sellToPool( + ZERO_ADDRESS, 10000, users[0].address, 0, b"" + ).data, + ), + ] + ).transact(w3, users[0], to=multicall3) + before -= receipt["effectiveGasPrice"] * receipt["gasUsed"] + balances_af = await multicall(w3, balances) + assert all(af + amount == bf for af, bf in zip(balances_af, balances_bf)) + assert await balance_of(w3, WETH_ADDRESS, multicall3) == 0 + assert await balance_of(w3, ZERO_ADDRESS, multicall3) == 0 + + # user get all funds back other than gas fees + assert await balance_of(w3, ZERO_ADDRESS, users[0].address) == before + + +async def test_7702(evm): + w3: AsyncWeb3 = evm.async_w3 + await assert_contract_deployed(w3) + + acct = ACCOUNTS["signer2"] + sponsor = ACCOUNTS["community"] + multicall3 = MULTICALL3ROUTER + + nonce = await w3.eth.get_transaction_count(acct.address) + chain_id = await w3.eth.chain_id + auth = acct.sign_authorization( + {"chainId": chain_id, "address": multicall3, "nonce": nonce} + ) + amount = 1000 + calls = [ + Call3Value(WETH_ADDRESS, False, amount, WETH.fns.deposit().data), + Call3Value(WETH_ADDRESS, False, 0, WETH.fns.withdraw(amount).data), + ] + tx: TxParams = { + "chainId": chain_id, + "to": acct.address, + "value": amount, + "authorizationList": [auth], + "data": MULTICALL3.fns.aggregate3Value(calls).data, + } + + before = await w3.eth.get_balance(acct.address) + receipt = await send_transaction(w3, sponsor, **tx) + after = await w3.eth.get_balance(acct.address) + assert before + amount == after + + assert await w3.eth.get_transaction_count(acct.address) == nonce + 1 + + logs = receipt["logs"] + assert logs[0]["topics"] == [ + WETH.events.Deposit.topic, + address_to_bytes32(acct.address), + ] + assert logs[1]["topics"] == [ + WETH.events.Withdrawal.topic, + address_to_bytes32(acct.address), + ] + + assert await w3.eth.get_code(acct.address) + block = await w3.eth.get_block(receipt["blockNumber"], True) + assert block["transactions"][0] == await w3.eth.get_transaction( + receipt["transactionHash"] + ) + assert block["hash"] == block["transactions"][0]["blockHash"] + receipts = await w3.eth.get_block_receipts(receipt["blockNumber"]) + assert receipts[0] == receipt + + +async def test_4337(evm): + w3: AsyncWeb3 = evm.async_w3 + await assert_contract_deployed(w3) + account = ACCOUNTS["community"] + assert ENTRYPOINT08_ADDRESS == await ensure_deployed_by_create2( + w3, account, get_initcode(ENTRYPOINT08_ARTIFACT), ENTRYPOINT08_SALT + ) + assert ENTRYPOINT07_ADDRESS == await ensure_deployed_by_create2( + w3, account, get_initcode(ENTRYPOINT07_ARTIFACT), ENTRYPOINT07_SALT + ) + + +async def test_deploy_multi(evm): + w3 = evm.async_w3 + name = "community" + key = KEYS[name] + owner = ADDRS[name] + num = 10 + res = build_contract("ERC20MinterBurnerDecimals") + args_list = [(w3, res, (f"MyToken{i}", f"MTK{i}", 18), key) for i in range(num)] + tx_results = await asyncio.gather( + *(create_contract_transaction(*args) for args in args_list) + ) + nonce = await w3.eth.get_transaction_count(owner) + txs = [{**tx, "nonce": nonce + i} for i, tx in enumerate(tx_results)] + receipts = await asyncio.gather( + *(send_transaction(w3, tx["from"], **tx) for tx in txs), return_exceptions=True + ) + for r in receipts: + if isinstance(r, Exception): + pytest.fail(f"send_transaction failed: {r}") + assert len(receipts) == num + total = 100 + token = receipts[0]["contractAddress"] + receipt = await ERC20.fns.mint(owner, total).transact(w3, owner, to=token) + assert receipt.status == 1 + assert await ERC20.fns.balanceOf(owner).call(w3, to=token) == total + + +async def test_upgrade(evm): + w3 = evm.async_w3 + owner = ADDRS["community"] + token = await build_and_deploy_contract_async(w3, "MyToken") + proxy = await build_and_deploy_contract_async( + w3, + "ERC1967Proxy", + args=( + token.address, + encode_transaction_data( + w3, "initialize", token.abi, args=[owner], kwargs={} + ), + ), + dir="openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967", # noqa: E501 + ) + token2 = await build_and_deploy_contract_async(w3, "MyToken2") + proxy = w3.eth.contract(address=proxy.address, abi=token.abi) + hash = await proxy.functions.upgradeToAndCall(token2.address, b"").transact( + {"from": owner} + ) + assert (await w3.eth.wait_for_transaction_receipt(hash)).status == 1 + proxy = w3.eth.contract(address=proxy.address, abi=token2.abi) + assert (await proxy.functions.newFeature().call()) == "Upgraded!" + + +async def test_storage_layout(evm): + w3 = evm.async_w3 + acct = ACCOUNTS["validator"] + + short = "Wrap Ether" + long = "Wrapped Ether Token for testing storage layout" * 32 + + artifact = build_contract("WETH9") + + # deploy + receipt = await send_transaction( + w3, acct, data=get_initcode(artifact, short, long, 18) + ) + contract = receipt["contractAddress"] + + # deposit + await send_transaction(w3, acct, to=contract, value=1000) + + # allowance + spender = ACCOUNTS["community"].address + await ERC20.fns.approve(spender, 500).transact(w3, acct, to=contract) + + # name + slot = await w3.eth.get_storage_at(contract, 0) + # short string + assert slot[-1] % 2 == 0 + length = slot[-1] // 2 + name = slot[:length] + assert short == name.decode() + + # symbol + slot = await w3.eth.get_storage_at(contract, 1) + # long string + assert slot[-1] % 2 == 1 + length = int.from_bytes(slot) >> 1 + assert len(long) == length + + data_slots = (length + 31) // 32 + data_begin = int.from_bytes(keccak((1).to_bytes(32, "big")), "big") + chunks = [] + for i in range(data_slots): + s = await w3.eth.get_storage_at(contract, data_begin + i) + if i == data_slots - 1: + chunks.append(s[: length - i * 32]) + else: + chunks.append(s) + + assert long == b"".join(chunks).decode() + + # decimals + decimals = await w3.eth.get_storage_at(contract, 2) + assert 18 == int.from_bytes(decimals) + + # balances + slot = keccak(encode(["address", "uint256"], [acct.address, 3])) + balance = await w3.eth.get_storage_at(contract, slot) + assert int.from_bytes(balance, "big") == 1000 + + # allowances + tmp = keccak(encode(["address", "uint256"], [acct.address, 4])) + slot = keccak(encode(["address", "bytes32"], [spender, tmp])) + allowance = await w3.eth.get_storage_at(contract, slot) + assert int.from_bytes(allowance, "big") == 500 diff --git a/tests/integration_tests/test_debug_traceblock.py b/tests/integration_tests/test_debug_traceblock.py new file mode 100644 index 000000000..dc08bd913 --- /dev/null +++ b/tests/integration_tests/test_debug_traceblock.py @@ -0,0 +1,67 @@ +import pytest +import requests +import web3 +from pystarport import ports +from pystarport.utils import w3_wait_for_block, wait_for_new_blocks + +from .utils import ( + derive_new_account, + send_transaction, + sign_transaction, +) + + +def test_traceblock(evm): + w3 = evm.w3 + cli = evm.cosmos_cli() + acc = derive_new_account(3) + sender = acc.address + # fund new sender + fund = 3000000000000000000 + tx = {"to": sender, "value": fund, "gasPrice": w3.eth.gas_price} + send_transaction(w3, tx) + assert w3.eth.get_balance(sender, "latest") == fund + nonce = w3.eth.get_transaction_count(sender) + blk = wait_for_new_blocks(cli, 1, sleep=0.1) + txhashes = [] + total = 3 + for n in range(total): + tx = { + "to": "0x2956c404227Cc544Ea6c3f4a36702D0FD73d20A2", + "value": fund // total, + "gas": 21000, + "maxFeePerGas": 6556868066901, + "maxPriorityFeePerGas": 1500000000, + "nonce": nonce + n, + } + signed = sign_transaction(w3, tx, acc.key) + if n == total - 1: + with pytest.raises( + web3.exceptions.Web3RPCError, match="insufficient funds" + ): + w3.eth.send_raw_transaction(signed.raw_transaction) + else: + txhash = w3.eth.send_raw_transaction(signed.raw_transaction) + txhashes.append(txhash) + for txhash in txhashes[0 : total - 1]: + res = w3.eth.wait_for_transaction_receipt(txhash) + assert res.status == 1 + + def trace_blk(blk): + url = f"http://127.0.0.1:{ports.evmrpc_port(evm.base_port(0))}" + params = { + "method": "debug_traceBlockByNumber", + "params": [hex(blk + 1)], + "id": 1, + "jsonrpc": "2.0", + } + rsp = requests.post(url, json=params) + assert rsp.status_code == 200 + return rsp.json()["result"] + + total = len(trace_blk(blk)) + expected = 2 + if total < expected: + total += len(trace_blk(blk + 1)) + assert total == expected + w3_wait_for_block(w3, w3.eth.block_number + 3, timeout=30) diff --git a/tests/integration_tests/test_distribution.py b/tests/integration_tests/test_distribution.py new file mode 100644 index 000000000..025699768 --- /dev/null +++ b/tests/integration_tests/test_distribution.py @@ -0,0 +1,114 @@ +from datetime import timedelta + +import pytest +from dateutil.parser import isoparse +from pystarport.utils import ( + wait_for_block, + wait_for_block_time, + wait_for_new_blocks, +) + +from .utils import ( + DEFAULT_DENOM, + eth_to_bech32, + find_fee, + find_log_event_attrs, +) + +pytestmark = pytest.mark.slow + + +def test_distribution(evm): + cli = evm.cosmos_cli() + tax = cli.get_params("distribution")["community_tax"] + if float(tax) < 0.01: + pytest.skip(f"community_tax is {tax} too low for test") + signer1, signer2 = cli.address("signer1"), cli.address("signer2") + # wait for initial rewards + wait_for_block(cli, 2) + + balance_bf = cli.balance(signer1) + community_bf = cli.distribution_community_pool() + amt = 2 + rsp = cli.transfer(signer1, signer2, f"{amt}{DEFAULT_DENOM}") + assert rsp["code"] == 0, rsp["raw_log"] + fee = find_fee(rsp) + wait_for_new_blocks(cli, 2) + assert cli.balance(signer1) == balance_bf - fee - amt + assert cli.distribution_community_pool() > community_bf + + +def test_commission(evm): + cli = evm.cosmos_cli() + name = "validator" + val = cli.address(name, "val") + initial_commission = cli.distribution_commission(val) + + # wait for rewards to accumulate + wait_for_new_blocks(cli, 3) + + current_commission = cli.distribution_commission(val) + assert current_commission >= initial_commission, "commission should increase" + balance_bf = cli.balance(name) + + rsp = cli.withdraw_validator_commission(val, from_=name) + assert rsp["code"] == 0, rsp["raw_log"] + + balance_af = cli.balance(name) + fee = find_fee(rsp) + assert ( + balance_af >= balance_bf - fee + ), "balance should increase after commission withdrawal" + + +def test_delegation_rewards_flow(evm): + cli = evm.cosmos_cli() + val = cli.validators()[0]["operator_address"] + validator = eth_to_bech32(cli.debug_addr(val, bech="hex")) + rewards_bf = cli.distribution_rewards(validator) + signer1 = cli.address("signer1") + signer2 = cli.address("signer2") + + rsp = cli.set_withdraw_addr(signer2, from_=signer1) + assert rsp["code"] == 0, rsp["raw_log"] + + delegate_amt = 4e6 + gas0 = 250_000 + coin = f"{delegate_amt}{DEFAULT_DENOM}" + rsp = cli.delegate_amount(val, coin, _from=signer1, gas=gas0) + assert rsp["code"] == 0, rsp["raw_log"] + + rewards_af = cli.distribution_rewards(validator) + assert rewards_af >= rewards_bf, "rewards should increase" + + balance_bf = cli.balance(signer2) + rsp = cli.withdraw_rewards(val, from_=signer1) + assert rsp["code"] == 0, rsp["raw_log"] + + balance_af = cli.balance(signer2) + assert balance_af >= balance_bf, "balance should increase" + + rsp = cli.unbond_amount(val, coin, _from=signer1, gas=gas0) + assert rsp["code"] == 0, rsp["raw_log"] + data = find_log_event_attrs( + rsp["events"], "unbond", lambda attrs: "completion_time" in attrs + ) + wait_for_block_time(cli, isoparse(data["completion_time"]) + timedelta(seconds=1)) + + +def test_community_pool_funding(evm): + cli = evm.cosmos_cli() + signer1 = cli.address("signer1") + initial_pool = cli.distribution_community_pool() + + fund_amount = 1000 + balance_bf = cli.balance(signer1) + rsp = cli.fund_community_pool(f"{fund_amount}{DEFAULT_DENOM}", from_=signer1) + assert rsp["code"] == 0, rsp["raw_log"] + + balance_af = cli.balance(signer1) + fee = find_fee(rsp) + assert balance_af == balance_bf - fund_amount - fee, "balance should decrease" + + final_pool = cli.distribution_community_pool() + assert final_pool >= initial_pool + fund_amount, "community pool should increase" diff --git a/tests/integration_tests/test_distribution_precompile.py b/tests/integration_tests/test_distribution_precompile.py new file mode 100644 index 000000000..b1b66f3e0 --- /dev/null +++ b/tests/integration_tests/test_distribution_precompile.py @@ -0,0 +1,140 @@ +import pytest +import requests +from eth_contract.contract import Contract +from pystarport.utils import parse_amount, wait_for_block, wait_for_new_blocks + +from .utils import ( + ACCOUNTS, + DEFAULT_DENOM, + WEI_PER_DENOM, + bech32_to_eth, + build_contract, + find_fee, + find_log_event_attrs, +) + +pytestmark = pytest.mark.asyncio + +PRECOMPILE = Contract(build_contract("DistributionI")["abi"]) + +DISTRIBUTION = "0x0000000000000000000000000000000000000801" + +gas = 400_000 + + +async def community_pool(w3): + res = await PRECOMPILE.fns.communityPool().call(w3, to=DISTRIBUTION) + return res[0][1] if res else 0 + + +async def rewards(w3, val, val_addr): + res = await PRECOMPILE.fns.delegationRewards(val, val_addr).call( + w3, to=DISTRIBUTION + ) + return res[0][1] if res else 0 + + +async def test_distribution(evm): + cli = evm.cosmos_cli() + tax = cli.get_params("distribution")["community_tax"] + if float(tax) < 0.01: + pytest.skip(f"community_tax is {tax} too low for test") + w3 = evm.async_w3 + signer1, signer2 = cli.address("signer1"), cli.address("signer2") + + wait_for_block(cli, 2) + + balance_bf = cli.balance(signer1) + community_bf = await community_pool(w3) + + amt = 2 + rsp = cli.transfer(signer1, signer2, f"{amt}{DEFAULT_DENOM}") + assert rsp["code"] == 0, rsp["raw_log"] + + fee = find_fee(rsp) + wait_for_new_blocks(cli, 2) + + assert cli.balance(signer1) == balance_bf - fee - amt + assert await community_pool(w3) > community_bf + + +async def test_delegation_rewards_flow(evm): + cli = evm.cosmos_cli() + w3 = evm.async_w3 + acct = ACCOUNTS["signer1"] + val = cli.validators()[0]["operator_address"] + validator = cli.debug_addr(val, bech="hex") + rewards_bf = await rewards(w3, validator, val) + signer1 = cli.address("signer1") + signer2 = cli.address("signer2") + signer2_eth = bech32_to_eth(signer2) + + res = await PRECOMPILE.fns.setWithdrawAddress(acct.address, signer2).transact( + w3, acct, to=DISTRIBUTION, gas=gas + ) + assert res.status == 1 + + delegate_amt = 4e6 + gas0 = 250_000 + coin = f"{delegate_amt}{DEFAULT_DENOM}" + rsp = cli.delegate_amount(val, coin, _from=signer1, gas=gas0) + assert rsp["code"] == 0, rsp["raw_log"] + + rewards_af = await rewards(w3, validator, val) + assert rewards_af >= rewards_bf, "rewards should increase" + + balance_bf = await w3.eth.get_balance(signer2_eth) + res = await PRECOMPILE.fns.withdrawDelegatorRewards(acct.address, val).transact( + w3, acct, to=DISTRIBUTION, gas=gas + ) + assert res.status == 1 + + balance_af = await w3.eth.get_balance(signer2_eth) + assert balance_af >= balance_bf, "balance should increase" + + rsp = cli.unbond_amount(val, coin, _from=signer1, gas=gas0) + assert rsp["code"] == 0, rsp["raw_log"] + + +async def test_community_pool_funding(evm): + w3 = evm.async_w3 + acct = ACCOUNTS["signer1"] + initial_pool = await community_pool(w3) + fund_amount = 1000 + balance_bf = await w3.eth.get_balance(acct.address) + + coin = [[DEFAULT_DENOM, fund_amount]] + res = await PRECOMPILE.fns.fundCommunityPool(acct.address, coin).transact( + w3, acct, to=DISTRIBUTION, gas=gas + ) + assert res.status == 1 + + balance_af = await w3.eth.get_balance(acct.address) + fee = res["gasUsed"] * res["effectiveGasPrice"] + assert ( + balance_af == balance_bf - fund_amount * WEI_PER_DENOM - fee + ), "balance should decrease" + + final_pool = await community_pool(w3) + assert final_pool >= initial_pool + fund_amount, "community pool should increase" + + +async def test_validator_rewards_pool_funding(evm): + cli = evm.cosmos_cli() + w3 = evm.async_w3 + acct = ACCOUNTS["signer1"] + val = cli.validators()[0]["operator_address"] + fund_amount = 1000 + coin = [[DEFAULT_DENOM, fund_amount]] + res = await PRECOMPILE.fns.depositValidatorRewardsPool( + acct.address, val, coin + ).transact(w3, acct, to=DISTRIBUTION, gas=gas, check=False) + # TODO: align disabled + assert res.status == 1 + blk = res["blockNumber"] + rsp = requests.get(f"{cli.node_rpc_http}/block_results?height={blk}").json() + rsp = next((tx for tx in rsp["result"]["txs_results"] if tx["code"] == 0), None) + data = find_log_event_attrs( + rsp["events"], "rewards", lambda attrs: "amount" in attrs + ) + assert parse_amount(data["amount"]) == fund_amount diff --git a/tests/integration_tests/test_eip1559.py b/tests/integration_tests/test_eip1559.py new file mode 100644 index 000000000..0ad126128 --- /dev/null +++ b/tests/integration_tests/test_eip1559.py @@ -0,0 +1,113 @@ +import pytest +from eth_contract.utils import send_transaction +from pystarport.utils import w3_wait_for_block_async + +from .utils import ( + ACCOUNTS, + ADDRS, + adjust_base_fee, +) + +pytestmark = pytest.mark.asyncio + + +async def test_dynamic_fee_tx(evm, update_params=True): + """ + test basic eip-1559 tx works: + - tx fee calculation is compliant to go-ethereum + - base fee adjustment is compliant to go-ethereum + """ + w3 = evm.async_w3 + amount = 1000 + before = await w3.eth.get_balance(ADDRS["community"]) + tip_price = 10000000000 + max_price = 1000000000000 + tip_price + begin = await w3.eth.block_number + await w3_wait_for_block_async(w3, begin + 1) + tx = { + "to": "0x0000000000000000000000000000000000000000", + "value": amount, + "gas": 21000, + "maxFeePerGas": max_price, + "maxPriorityFeePerGas": tip_price, + } + txreceipt = await send_transaction(w3, ACCOUNTS["community"], **tx) + blk = await w3.eth.get_block(txreceipt.blockNumber) + assert txreceipt.effectiveGasPrice == blk.baseFeePerGas + tip_price + + fee_expected = txreceipt.gasUsed * txreceipt.effectiveGasPrice + after = await w3.eth.get_balance(ADDRS["community"]) + fee_deducted = before - after - amount + assert fee_deducted == fee_expected + + assert blk.gasUsed == txreceipt.gasUsed # we are the only tx in the block + + if not update_params: + return + + # check the next block's base fee is adjusted accordingly + await w3_wait_for_block_async(w3, txreceipt.blockNumber + 1) + next_base_price = (await w3.eth.get_block(txreceipt.blockNumber + 1)).baseFeePerGas + params = evm.cosmos_cli().get_params("feemarket") + assert ( + abs( + next_base_price + - adjust_base_fee(blk.baseFeePerGas, blk.gasLimit, blk.gasUsed, params) + ) + <= 1 + ) + + +async def test_base_fee_adjustment(evm, update_params=True): + """ + verify base fee adjustment of three continuous empty blocks + """ + w3 = evm.async_w3 + begin = await w3.eth.block_number + await w3_wait_for_block_async(w3, begin + 3) + + if not update_params: + return + + blk = await w3.eth.get_block(begin) + parent_fee = blk.baseFeePerGas + params = evm.cosmos_cli().get_params("feemarket") + + for i in range(3): + fee = (await w3.eth.get_block(begin + 1 + i)).baseFeePerGas + assert abs(fee - adjust_base_fee(parent_fee, blk.gasLimit, 0, params)) <= 1 + parent_fee = fee + + +async def test_recommended_fee_per_gas(evm): + """The recommended base fee per gas returned by eth_gasPrice is + base fee of the block just produced + eth_maxPriorityFeePerGas (the buffer).\n + Verify the calculation of recommended base fee per gas (eth_gasPrice) + """ + w3 = evm.async_w3 + recommended_base_fee_per_gas = await w3.eth.gas_price + latest_block = await w3.eth.get_block("latest") + base_fee = latest_block["baseFeePerGas"] + buffer_fee = await w3.eth.max_priority_fee + + assert recommended_base_fee_per_gas == base_fee + buffer_fee, ( + f"eth_gasPrice is not the {latest_block['number']} block's " + "base fee plus eth_maxPriorityFeePerGas" + ) + + +async def test_gas_price_meets_next_base_fee(evm): + """The recommended base fee per gas returned by eth_gasPrice should + be bigger than or equal to the base fee per gas of the next block, \n + otherwise the tx does not meet the requirement to be included in the next block.\n + """ + w3 = evm.async_w3 + base_block = await w3.eth.block_number + recommended_base_fee = await w3.eth.gas_price + + await w3_wait_for_block_async(w3, base_block + 1) + next_block = await w3.eth.get_block(base_block + 1) + assert recommended_base_fee >= next_block["baseFeePerGas"], ( + f"recommended base fee: {recommended_base_fee} is smaller than " + f"next block {next_block['number']} base fee: {next_block['baseFeePerGas']}" + ) diff --git a/tests/integration_tests/test_erc20.py b/tests/integration_tests/test_erc20.py new file mode 100644 index 000000000..c86bd4fe0 --- /dev/null +++ b/tests/integration_tests/test_erc20.py @@ -0,0 +1,42 @@ +import pytest +from eth_contract.erc20 import ERC20 +from eth_contract.weth import WETH +from eth_utils import to_checksum_address + +from .utils import ACCOUNTS + +WOM = to_checksum_address("0x4200000000000000000000000000000000000006") + + +@pytest.mark.asyncio +async def test_static_erc20(evm): + w3 = evm.async_w3 + acct = ACCOUNTS["community"] + addr = acct.address + balance = await ERC20.fns.balanceOf(addr).call(w3, to=WOM) + assert balance > 0 + + # deposit should be nop + before = await w3.eth.get_balance(addr) + print("intial balance", before) + receipt = await WETH.fns.deposit().transact(w3, acct, value=10**18, to=WOM) + fee = receipt["effectiveGasPrice"] * receipt["gasUsed"] + after = await w3.eth.get_balance(addr) + assert after == before - fee + + # withdraw should be nop + before = await w3.eth.get_balance(addr) + receipt = await WETH.fns.withdraw(100).transact(w3, acct, to=WOM) + fee = receipt["effectiveGasPrice"] * receipt["gasUsed"] + after = await w3.eth.get_balance(addr) + assert after == before - fee + + cli = evm.cosmos_cli() + denom = cli.get_params("evm")["evm_denom"] + meta = cli.query_bank_denom_metadata(denom) + assert ( + await ERC20.fns.decimals().call(w3, to=WOM) + == meta["denom_units"][1]["exponent"] + ) + assert await ERC20.fns.symbol().call(w3, to=WOM) == meta["symbol"] + assert await ERC20.fns.name().call(w3, to=WOM) == meta["name"] diff --git a/tests/integration_tests/test_estimate_gas.py b/tests/integration_tests/test_estimate_gas.py new file mode 100644 index 000000000..a708eeca1 --- /dev/null +++ b/tests/integration_tests/test_estimate_gas.py @@ -0,0 +1,48 @@ +from .utils import ( + AsyncTestMessageCall, + AsyncTestRevert, + create_contract_transaction, +) + +METHOD = "eth_estimateGas" + + +async def test_revert(evm): + w3 = evm.async_w3 + revert = AsyncTestRevert() + await revert.deploy(w3) + data = "0x9ffb86a5" + params = {"to": revert.address, "data": data} + rsp = await w3.provider.make_request(METHOD, [params]) + error = rsp["error"] + assert error["code"] == 3 + assert error["message"] == "execution reverted: Function has been reverted" + assert ( + error["data"] + == "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a46756e6374696f6e20686173206265656e207265766572746564000000000000" # noqa: E501 + ) + + +async def test_out_of_gas_error(evm): + iterations = 1 + gas = 21204 + w3 = evm.async_w3 + msg = AsyncTestMessageCall() + await msg.deploy(w3) + tx_data = msg.get_test_data(iterations) + tx_params = {"to": msg.address, "data": tx_data, "gas": hex(gas)} + rsp = await w3.provider.make_request(METHOD, [tx_params]) + error = rsp["error"] + assert error["code"] == -32000 + assert f"gas required exceeds allowance ({gas})" in error["message"] + + +async def test_storage_out_of_gas_error(evm): + gas = 210000 + w3 = evm.async_w3 + tx = await create_contract_transaction(w3, "TestMessageCall") + tx_params = {"data": tx["data"], "gas": hex(gas)} + rsp = await w3.provider.make_request(METHOD, [tx_params]) + error = rsp["error"] + assert error["code"] == -32000 + assert "contract creation code storage out of gas" in error["message"] diff --git a/tests/integration_tests/test_exploit.py b/tests/integration_tests/test_exploit.py new file mode 100644 index 000000000..7a98b2874 --- /dev/null +++ b/tests/integration_tests/test_exploit.py @@ -0,0 +1,101 @@ +from concurrent.futures import ThreadPoolExecutor, as_completed +from pathlib import Path + +import pytest +import requests +from pystarport import ports + +from .network import setup_custom_evm +from .utils import build_and_deploy_contract_async + +pytestmark = pytest.mark.asyncio + + +@pytest.fixture(scope="module") +def custom_evm(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("exploit") + yield from setup_custom_evm( + path, + 26910, + Path(__file__).parent / "configs/exploit.jsonnet", + chain=chain, + ) + + +def call(port, params): + url = f"http://127.0.0.1:{port}" + rsp = requests.post(url, json=params) + assert rsp.status_code == 200 + return rsp.json() + + +async def run_test(provider, concurrent, batch, expect_cb): + contract = await build_and_deploy_contract_async( + provider.async_w3, "TestExploitContract" + ) + param = { + "jsonrpc": "2.0", + "method": "eth_call", + "params": [ + { + "data": "0x5e67164c", + "to": contract.address, + }, + "latest", + ], + "id": 1, + } + params = [] + for _ in range(batch): + params.append(param) + with ThreadPoolExecutor(concurrent) as executor: + p = ports.evmrpc_port(provider.base_port(0)) + tasks = [executor.submit(call, p, params) for _ in range(0, concurrent)] + results = [future.result() for future in as_completed(tasks)] + assert len(results) == concurrent + for result in results: + expect_cb(result) + + +async def test_large_batch(custom_evm): + concurrent = 1 + batch = 3 + + def expect_cb(result): + found = False + for item in result: + if "error" in item and "batch too large" in str( + item["error"].get("message", "") + ): + found = True + assert found, "no limit found" + + await run_test(custom_evm, concurrent, batch, expect_cb) + + +async def test_large_response(custom_evm): + concurrent = 1 + batch = 2 + + def expect_cb(result): + found = False + for item in result: + if "error" in item and "response too large" in str( + item["error"].get("message", "") + ): + found = True + assert found, "no limit found" + + await run_test(custom_evm, concurrent, batch, expect_cb) + + +async def test_call(evm): + concurrent = 2 + batch = 1 + + def expect_cb(result): + for item in result: + assert "error" not in item + + await run_test(evm, concurrent, batch, expect_cb) diff --git a/tests/integration_tests/test_fee_history.py b/tests/integration_tests/test_fee_history.py new file mode 100644 index 000000000..31f108bfa --- /dev/null +++ b/tests/integration_tests/test_fee_history.py @@ -0,0 +1,224 @@ +from concurrent.futures import ThreadPoolExecutor, as_completed +from pathlib import Path + +import pytest +from pystarport.utils import w3_wait_for_block, w3_wait_for_new_blocks +from web3 import Web3 + +from .network import setup_custom_evm +from .utils import ( + ADDRS, + WEI_PER_DENOM, + adjust_base_fee, + module_address, + send_transaction, + submit_gov_proposal, +) + +NEW_BASE_FEE = 10000000000 + +pytestmark = pytest.mark.slow + + +@pytest.fixture(scope="module") +def custom_evm(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("fee-history") + yield from setup_custom_evm( + path, + 26500, + Path(__file__).parent / "configs/fee-history.jsonnet", + chain=chain, + ) + + +def test_basic(custom_evm): + w3: Web3 = custom_evm.w3 + # need at least 5 blocks + w3_wait_for_block(w3, 5) + call = w3.provider.make_request + tx = {"to": ADDRS["community"], "value": 10, "gasPrice": w3.eth.gas_price} + send_transaction(w3, tx) + size = 4 + # size of base fee + next fee + max = size + 1 + # only 1 base fee + next fee + min = 2 + method = "eth_feeHistory" + field = "baseFeePerGas" + percentiles = [100] + height = w3.eth.block_number + latest = dict( + blocks=["latest", hex(height)], + expect=max, + ) + earliest = dict( + blocks=["earliest", "0x0"], + expect=min, + ) + for tc in [latest, earliest]: + res = [] + with ThreadPoolExecutor(len(tc["blocks"])) as exec: + tasks = [ + exec.submit(call, method, [size, b, percentiles]) for b in tc["blocks"] + ] + res = [future.result()["result"][field] for future in as_completed(tasks)] + assert len(res) == len(tc["blocks"]) + assert res[0] == res[1] + assert len(res[0]) == tc["expect"] + + for x in range(max): + i = x + 1 + fee_history = call(method, [size, hex(i), percentiles]) + # start to reduce diff on i <= size - min + diff = size - min - i + reduce = size - diff + target = reduce if diff >= 0 else max + res = fee_history["result"] + assert len(res[field]) == target + oldest = i + min - max + assert res["oldestBlock"] == hex(oldest if oldest > 0 else 0) + + +def test_change(custom_evm): + w3: Web3 = custom_evm.w3 + call = w3.provider.make_request + tx = {"to": ADDRS["community"], "value": 10, "gasPrice": w3.eth.gas_price} + send_transaction(w3, tx) + size = 4 + method = "eth_feeHistory" + field = "baseFeePerGas" + percentiles = [100] + for b in ["latest", hex(w3.eth.block_number)]: + history0 = call(method, [size, b, percentiles])["result"][field] + w3_wait_for_new_blocks(w3, 2, 0.1) + history1 = call(method, [size, b, percentiles])["result"][field] + if b == "latest": + assert history1 != history0 + else: + assert history1 == history0 + + +def test_next(custom_evm): + w3: Web3 = custom_evm.w3 + tx = {"to": ADDRS["community"], "value": 10, "gasPrice": w3.eth.gas_price} + send_transaction(w3, tx) + assert_histories( + w3, custom_evm.cosmos_cli(), w3.eth.block_number, percentiles=[100] + ) + + +def test_beyond_head(custom_evm): + end = hex(0x7FFFFFFFFFFFFFFF) + res = custom_evm.w3.provider.make_request("eth_feeHistory", [4, end, []]) + msg = f"request beyond head block: requested {int(end, 16)}" + assert msg in res["error"]["message"] + + +def test_percentiles(custom_evm): + w3: Web3 = custom_evm.w3 + call = w3.provider.make_request + method = "eth_feeHistory" + percentiles = [[-1], [101], [2, 1]] + size = 4 + msg = "invalid reward percentile" + with ThreadPoolExecutor(len(percentiles)) as exec: + tasks = [exec.submit(call, method, [size, "latest", p]) for p in percentiles] + result = [future.result() for future in as_completed(tasks)] + assert all(msg in res["error"]["message"] for res in result) + + +def update_feemarket_param(node, tmp_path, new_multiplier=2, new_denominator=200000000): + cli = node.cosmos_cli() + p = cli.get_params("feemarket") + new_base_fee = f"{NEW_BASE_FEE / WEI_PER_DENOM}" + p["base_fee"] = new_base_fee + p["elasticity_multiplier"] = new_multiplier + p["base_fee_change_denominator"] = new_denominator + submit_gov_proposal( + node, + tmp_path, + messages=[ + { + "@type": "/cosmos.evm.feemarket.v1.MsgUpdateParams", + "authority": module_address("gov"), + "params": p, + } + ], + ) + p = cli.get_params("feemarket") + assert float(p["base_fee"]) - float(new_base_fee) == 0 + assert p["elasticity_multiplier"] == new_multiplier + assert p["base_fee_change_denominator"] == new_denominator + + +def test_concurrent(custom_evm, tmp_path): + w3: Web3 = custom_evm.w3 + tx = {"to": ADDRS["community"], "value": 10, "gasPrice": w3.eth.gas_price} + # send multi txs, overlap happens with query with 2nd tx's block number + send_transaction(w3, tx) + receipt1 = send_transaction(w3, tx) + b1 = receipt1.blockNumber + send_transaction(w3, tx) + call = w3.provider.make_request + field = "baseFeePerGas" + update_feemarket_param(custom_evm, tmp_path) + percentiles = [] + method = "eth_feeHistory" + # big enough concurrent requests to trigger overwrite bug + total = 10 + size = 2 + params = [size, hex(b1), percentiles] + res = [] + with ThreadPoolExecutor(total) as exec: + t = [exec.submit(call, method, params) for i in range(total)] + res = [future.result()["result"][field] for future in as_completed(t)] + assert all(sublist == res[0] for sublist in res), res + + +def assert_histories(w3, cli, blk, percentiles=[]): + call = w3.provider.make_request + method = "eth_feeHistory" + field = "baseFeePerGas" + expected = [] + blocks = [] + histories = [] + for i in range(3): + b = blk + i + blocks.append(b) + history = tuple(call(method, [1, hex(b), percentiles])["result"][field]) + histories.append(history) + w3_wait_for_new_blocks(w3, 1, 0.1) + blocks.append(b + 1) + + for b in blocks: + next_base_price = w3.eth.get_block(b).baseFeePerGas + prev = b - 1 + blk = w3.eth.get_block(prev) + base_fee = blk.baseFeePerGas + params = cli.get_params("feemarket") + res = adjust_base_fee( + base_fee, + blk.gasLimit, + blk.gasUsed, + params, + ) + if abs(next_base_price - res) == 1: + next_base_price = res + elif next_base_price != NEW_BASE_FEE: + assert next_base_price == res + expected.append(hex(int(next_base_price))) + assert all( + abs(int(a, 16) - int(exp_a, 16)) <= 1 and abs(int(b, 16) - int(exp_b, 16)) <= 1 + for (a, b), (exp_a, exp_b) in zip(histories, zip(expected, expected[1:])) + ) + + +def test_param_change(custom_evm, tmp_path): + w3 = custom_evm.w3 + cli = custom_evm.cosmos_cli() + update_feemarket_param(custom_evm, tmp_path) + assert_histories(w3, cli, w3.eth.block_number) + tx = {"to": ADDRS["community"], "value": 10, "gasPrice": w3.eth.gas_price} + receipt = send_transaction(w3, tx) + assert_histories(w3, cli, receipt.blockNumber) diff --git a/tests/integration_tests/test_filters.py b/tests/integration_tests/test_filters.py new file mode 100644 index 000000000..4e719aad4 --- /dev/null +++ b/tests/integration_tests/test_filters.py @@ -0,0 +1,131 @@ +import pytest +import web3 +from eth_contract.utils import send_transaction +from pystarport.utils import w3_wait_for_new_blocks_async +from web3 import AsyncWeb3 + +from .utils import ( + ACCOUNTS, + ADDRS, + KEYS, + AsyncGreeter, +) + +pytestmark = pytest.mark.asyncio + + +async def test_get_logs_by_topic(evm): + w3: AsyncWeb3 = evm.async_w3 + greeter = AsyncGreeter(key=KEYS["community"]) + addr = await greeter.deploy(w3) + contract = greeter.contract + topic = contract.events.ChangeGreeting.topic + res = await greeter.set_greeting("Hello") + current = await w3.eth.block_number + # invalid block ranges + test_cases = [ + {"fromBlock": hex(2000), "toBlock": "latest", "address": [addr]}, + {"fromBlock": hex(2), "toBlock": hex(1), "address": [addr]}, + { + "fromBlock": "earliest", + "toBlock": hex(current + 200), + "address": [addr], + }, + { + "fromBlock": hex(current + 20), + "toBlock": hex(current + 200), + "address": [addr], + }, + ] + invalid_block_msg = "invalid block range params" + for params in test_cases: + with pytest.raises(web3.exceptions.Web3RPCError, match=invalid_block_msg): + await w3.eth.get_logs(params) + + # log exists + logs = await w3.eth.get_logs({"topics": [topic]}) + assert len(logs) == 1 + log = logs[0] + assert all( + log[key] == res[key] + for key in ["transactionHash", "transactionIndex", "blockNumber", "blockHash"] + ) + assert log["address"] == addr + assert log["blockTimestamp"] == res["logs"][0]["blockTimestamp"] + assert log["blockTimestamp"] != "0x0" + + # Wait and confirm log doesn't appear in new blocks + await w3_wait_for_new_blocks_async(w3, 2) + assert len(await w3.eth.get_logs({"topics": [topic]})) == 0 + + previous = current + current = await w3.eth.block_number + # valid block ranges + valid_cases = [ + {"fromBlock": "earliest", "toBlock": "latest", "address": [addr]}, + { + "fromBlock": "earliest", + "toBlock": hex(current), + "address": [addr], + }, + { + "fromBlock": hex(previous), + "toBlock": "latest", + "address": [addr], + }, + { + "fromBlock": hex(previous), + "toBlock": hex(current), + "address": [addr], + }, + ] + for params in valid_cases: + logs = await w3.eth.get_logs(params) + assert len(logs) > 0 + + +async def test_pending_transaction_filter(evm): + w3: AsyncWeb3 = evm.async_w3 + flt = await w3.eth.filter("pending") + assert await flt.get_new_entries() == [] + tx = {"to": ADDRS["signer1"], "value": 1000} + receipt = await send_transaction(w3, ACCOUNTS["community"], **tx) + assert receipt.status == 1 + assert receipt["transactionHash"] in await flt.get_new_entries() + + +async def test_block_filter(evm): + w3: AsyncWeb3 = evm.async_w3 + flt = await w3.eth.filter("latest") + # new blocks + await w3_wait_for_new_blocks_async(w3, 1) + tx = {"to": ADDRS["signer1"], "value": 1000} + receipt = await send_transaction(w3, ACCOUNTS["community"], **tx) + assert receipt.status == 1 + blocks = await flt.get_new_entries() + assert len(blocks) >= 1 + + +async def test_event_log_filter(evm): + w3: AsyncWeb3 = evm.async_w3 + greeter = AsyncGreeter(key=KEYS["community"]) + await greeter.deploy(w3) + contract = greeter.contract + assert "Hello" == await greeter.greet() + current_height = hex(await w3.eth.get_block_number()) + event_filter = await contract.events.ChangeGreeting.create_filter( + w3, from_block=current_height + ) + res = await greeter.set_greeting("world") + log = contract.events.ChangeGreeting().process_receipt(res)[0] + assert log["event"] == "ChangeGreeting" + new_entries = await event_filter.get_new_entries() + assert len(new_entries) == 1 + assert new_entries[0] == log + assert "world" == await greeter.greet() + # without new txs since last call`` + assert await event_filter.get_new_entries() == [] + assert await event_filter.get_all_entries() == new_entries + # Uninstall + assert await w3.eth.uninstall_filter(event_filter.filter_id) + assert not await w3.eth.uninstall_filter(event_filter.filter_id) diff --git a/tests/integration_tests/test_gas.py b/tests/integration_tests/test_gas.py new file mode 100644 index 000000000..057e89124 --- /dev/null +++ b/tests/integration_tests/test_gas.py @@ -0,0 +1,63 @@ +import pytest +import web3 +from eth_contract.utils import send_transaction +from pystarport.utils import w3_wait_for_new_blocks_async + +from .utils import ADDRS, build_and_deploy_contract_async + +pytestmark = pytest.mark.asyncio + + +BURN_GAS_CONTRACT = None + + +async def get_burn_gas_contract(w3): + global BURN_GAS_CONTRACT + if BURN_GAS_CONTRACT is None: + BURN_GAS_CONTRACT = await build_and_deploy_contract_async(w3, "BurnGas") + return BURN_GAS_CONTRACT + + +async def test_gas_call(evm): + w3 = evm.async_w3 + input = 10 + contract = await get_burn_gas_contract(w3) + txhash = await contract.functions.burnGas(input).transact( + {"from": ADDRS["community"], "gasPrice": await w3.eth.gas_price} + ) + receipt = await w3.eth.wait_for_transaction_receipt(txhash) + assert receipt.gasUsed == 267649 + + +async def test_block_gas_limit(evm): + w3 = evm.async_w3 + # get the block gas limit from the latest block + await w3_wait_for_new_blocks_async(w3, 5) + block = await w3.eth.get_block("latest") + exceeded_gas_limit = block.gasLimit + 100 + + # send a transaction exceeding the block gas limit + gas_price = await w3.eth.gas_price + value = 10 + tx = { + "to": ADDRS["signer1"], + "value": value, + "gas": exceeded_gas_limit, + "gasPrice": gas_price, + } + # expect an error due to the block gas limit + msg = "exceeds block gas limit" + sender = ADDRS["community"] + with pytest.raises(web3.exceptions.Web3RPCError, match=msg): + await send_transaction(w3, sender, False, **tx) + + # expect an error on contract call due to block gas limit + with pytest.raises(web3.exceptions.Web3RPCError, match=msg): + contract = await get_burn_gas_contract(w3) + await contract.functions.burnGas(exceeded_gas_limit).transact( + { + "from": sender, + "gas": exceeded_gas_limit, + "gasPrice": gas_price, + } + ) diff --git a/tests/integration_tests/test_ibc.py b/tests/integration_tests/test_ibc.py new file mode 100644 index 000000000..9a88790cd --- /dev/null +++ b/tests/integration_tests/test_ibc.py @@ -0,0 +1,234 @@ +import hashlib +import json +import math + +import pytest +from eth_contract.erc20 import ERC20 +from pystarport.utils import wait_for_fn, wait_for_fn_async + +from .ibc_utils import hermes_transfer, prepare_network +from .utils import ( + ADDRS, + DEFAULT_DENOM, + KEYS, + WETH_ADDRESS, + assert_balance, + assert_create_erc20_denom, + build_and_deploy_contract_async, + eth_to_bech32, + find_duplicate, + generate_isolated_address, + ibc_denom_address, + parse_events_rpc, +) + +pytestmark = pytest.mark.asyncio + + +@pytest.fixture(scope="module") +def ibc(request, tmp_path_factory): + "prepare-network" + name = "ibc" + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp(name) + yield from prepare_network(path, name, chain) + + +def assert_dynamic_fee(cli): + # assert that the relayer transactions do enables the dynamic fee extension option. + criteria = "message.action='/ibc.core.channel.v1.MsgChannelOpenInit'" + tx = cli.tx_search(criteria)["txs"][0] + events = parse_events_rpc(tx["events"]) + fee = int(events["tx"]["fee"].removesuffix(DEFAULT_DENOM)) + gas = int(tx["gas_wanted"]) + # the effective fee is decided by the max_priority_fee (base fee is zero) + # rather than the normal gas price + cosmos_evm_dynamic_fee = 10000000000000000 / 10**18 + assert fee == math.ceil(gas * cosmos_evm_dynamic_fee) + + +def assert_dup_events(cli): + # check duplicate OnRecvPacket events + criteria = "message.action='/ibc.core.channel.v1.MsgRecvPacket'" + events = cli.tx_search(criteria)["txs"][0]["events"] + for event in events: + dup = find_duplicate(event["attributes"]) + assert not dup, f"duplicate {dup} in {event['type']}" + + +def wait_for_balance_change(cli, addr, denom, init_balance): + def check_balance(): + current_balance = cli.balance(addr, denom) + return current_balance if current_balance != init_balance else None + + return wait_for_fn("balance change", check_balance) + + +def assert_receiver_events(cli, cli2, target): + criteria = "message.action='/ibc.applications.transfer.v1.MsgTransfer'" + events = cli.tx_search(criteria)["txs"][0]["events"] + events = parse_events_rpc(events) + receiver = events.get("ibc_transfer").get("receiver") + assert receiver == target + + criteria = "message.action='/ibc.core.channel.v1.MsgRecvPacket'" + events = cli2.tx_search(criteria)["txs"][0]["events"] + events = parse_events_rpc(events) + receiver = events.get("fungible_token_packet").get("receiver") + assert receiver == target + + +async def test_ibc_transfer(ibc): + w3 = ibc.ibc1.async_w3 + cli = ibc.ibc1.cosmos_cli() + cli2 = ibc.ibc2.cosmos_cli() + signer1 = ADDRS["signer1"] + community = ADDRS["community"] + addr_signer1 = eth_to_bech32(signer1) + addr_community = eth_to_bech32(community) + + # evm-canary-net-2 signer2 -> evm-canary-net-1 signer1 100 baseunit + transfer_amt = 100 + src_chain = "evm-canary-net-2" + dst_chain = "evm-canary-net-1" + path, escrow_addr = hermes_transfer( + ibc, + src_chain, + "signer2", + transfer_amt, + dst_chain, + addr_signer1, + ) + denom_hash = hashlib.sha256(path.encode()).hexdigest().upper() + dst_denom = f"ibc/{denom_hash}" + signer1_balance_bf = cli.balance(addr_signer1, dst_denom) + signer1_balance = wait_for_balance_change( + cli, addr_signer1, dst_denom, signer1_balance_bf + ) + assert signer1_balance == signer1_balance_bf + transfer_amt + assert cli.ibc_denom_hash(path) == denom_hash + assert_balance(cli2, ibc.ibc2.w3, escrow_addr) == transfer_amt + assert_dynamic_fee(cli) + assert_dup_events(cli) + + # evm-canary-net-1 signer1 -> evm-canary-net-2 community eth addr with 5 baseunit + amount = 5 + rsp = cli.ibc_transfer( + community, + f"{amount}{DEFAULT_DENOM}", + "channel-0", + from_=addr_signer1, + ) + assert rsp["code"] == 0, rsp["raw_log"] + community_balance_bf = cli2.balance(addr_community, dst_denom) + community_balance = wait_for_balance_change( + cli2, addr_community, dst_denom, community_balance_bf + ) + assert community_balance == community_balance_bf + amount + assert_receiver_events(cli, cli2, community) + + ibc_erc20_addr = ibc_denom_address(dst_denom) + assert (await ERC20.fns.decimals().call(w3, to=ibc_erc20_addr)) == 0 + total = await ERC20.fns.totalSupply().call(w3, to=ibc_erc20_addr) + assert total == transfer_amt + + +async def prepare_dest_callback(w3, sender, amt): + # deploy cb contract + contract = await build_and_deploy_contract_async( + w3, "CounterWithCallbacks", KEYS["signer1"] + ) + calldata = await contract.functions.add(WETH_ADDRESS, amt).build_transaction( + {"from": sender, "gas": 210000} + ) + calldata = calldata["data"][2:] + dest_cb = { + "dest_callback": { + "address": contract.address, + "gas_limit": "1000000", + "calldata": calldata, + } + } + return contract.address, json.dumps(dest_cb) + + +async def test_ibc_cb(ibc): + w3 = ibc.ibc1.async_w3 + cli = ibc.ibc1.cosmos_cli() + cli2 = ibc.ibc2.cosmos_cli() + signer1 = ADDRS["signer1"] + signer2 = ADDRS["signer2"] + addr_signer2 = eth_to_bech32(signer2) + erc20_denom, total = await assert_create_erc20_denom(w3, signer1) + + # check native erc20 transfer + res = cli.register_erc20(WETH_ADDRESS, _from="community", gas=400_000) + assert res["code"] == 0 + erc20_denom = f"erc20:{WETH_ADDRESS}" + res = cli.query_erc20_token_pair(erc20_denom) + assert res["erc20_address"] == WETH_ADDRESS, res + + # evm-canary-net-1 signer1 -> evm-canary-net-2 signer2 50erc20_denom + transfer_amt = total // 2 + src_chain = "evm-canary-net-1" + dst_chain = "evm-canary-net-2" + channel = "channel-0" + isolated = generate_isolated_address(channel, addr_signer2) + + path, escrow_addr = hermes_transfer( + ibc, + src_chain, + "signer1", + transfer_amt, + dst_chain, + addr_signer2, + denom=erc20_denom, + ) + + denom_hash = hashlib.sha256(path.encode()).hexdigest().upper() + dst_denom = f"ibc/{denom_hash}" + signer2_balance_bf = cli2.balance(addr_signer2, dst_denom) + signer2_balance = wait_for_balance_change( + cli2, addr_signer2, dst_denom, signer2_balance_bf + ) + assert signer2_balance == signer2_balance_bf + transfer_amt + assert cli2.ibc_denom_hash(path) == denom_hash + signer2_balance_bf = signer2_balance + + assert cli.balance(escrow_addr, erc20_denom) == transfer_amt + signer1_balance_eth = await ERC20.fns.balanceOf(signer1).call(w3, to=WETH_ADDRESS) + assert signer1_balance_eth == total - transfer_amt + + # deploy cb contract + transfer_amt = total // 2 + cb_contract, dest_cb = await prepare_dest_callback(w3, signer1, transfer_amt) + cb_balance_bf = await ERC20.fns.balanceOf(cb_contract).call(w3, to=WETH_ADDRESS) + + # evm-canary-net-2 signer2 -> evm-canary-net-1 signer1 50erc20_denom + src_chain = "evm-canary-net-2" + dst_chain = "evm-canary-net-1" + hermes_transfer( + ibc, + src_chain, + "signer2", + transfer_amt, + dst_chain, + isolated, + denom=dst_denom, + memo=dest_cb, + ) + assert cli2.balance(addr_signer2, dst_denom) == signer2_balance_bf - transfer_amt + + async def wait_for_balance_change_async(w3, addr, token_addr, init_balance): + async def check_balance(): + current_balance = await ERC20.fns.balanceOf(addr).call(w3, to=token_addr) + return current_balance if current_balance != init_balance else None + + return await wait_for_fn_async("balance change", check_balance) + + cb_balance = await wait_for_balance_change_async( + w3, cb_contract, WETH_ADDRESS, cb_balance_bf + ) + assert cb_balance == cb_balance_bf + transfer_amt + assert cli.balance(escrow_addr, erc20_denom) == 0 + assert cli2.balance(addr_signer2, dst_denom) == 0 diff --git a/tests/integration_tests/test_min_gas_price.py b/tests/integration_tests/test_min_gas_price.py new file mode 100644 index 000000000..6cb83b16b --- /dev/null +++ b/tests/integration_tests/test_min_gas_price.py @@ -0,0 +1,123 @@ +from pathlib import Path + +import pytest +from pystarport.utils import w3_wait_for_block, wait_for_new_blocks + +from .network import setup_custom_evm +from .utils import ( + ADDRS, + KEYS, + WEI_PER_DENOM, + adjust_base_fee, + send_transaction, +) + + +@pytest.fixture(scope="module") +def custom_evm_eq(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("min-gas-price-eq") + yield from setup_custom_evm( + path, + 26500, + Path(__file__).parent / "configs/min_gas_price_eq.jsonnet", + chain=chain, + ) + + +@pytest.fixture(scope="module") +def custom_evm(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("min-gas-price") + yield from setup_custom_evm( + path, + 26530, + Path(__file__).parent / "configs/min_gas_price.jsonnet", + chain=chain, + ) + + +@pytest.fixture(scope="module") +def custom_evm_lte(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("min-gas-price-lte") + yield from setup_custom_evm( + path, + 26560, + Path(__file__).parent / "configs/min_gas_price_lte.jsonnet", + chain=chain, + ) + + +@pytest.fixture( + scope="module", + params=["custom_evm_eq", "custom_evm", "custom_evm_lte"], +) +def custom_cluster(request, custom_evm_eq, custom_evm_lte, custom_evm): + if request.param == "custom_evm_eq": + return custom_evm_eq + elif request.param == "custom_evm_lte": + return custom_evm_lte + return custom_evm + + +def test_dynamic_fee_tx(custom_cluster): + cli = custom_cluster.cosmos_cli() + wait_for_new_blocks(cli, 1) + w3 = custom_cluster.w3 + amount = 10000 + before = w3.eth.get_balance(ADDRS["community"]) + tip_price = 1000000 + max_price = 100000000000000 + tip_price + tx = { + "to": "0x0000000000000000000000000000000000000000", + "value": amount, + "gas": 21000, + "maxFeePerGas": max_price, + "maxPriorityFeePerGas": tip_price, + } + txreceipt = send_transaction(w3, tx, KEYS["community"]) + assert txreceipt.status == 1 + blk = w3.eth.get_block(txreceipt.blockNumber) + assert txreceipt.effectiveGasPrice == blk.baseFeePerGas + tip_price + + fee_expected = txreceipt.gasUsed * txreceipt.effectiveGasPrice + after = w3.eth.get_balance(ADDRS["community"]) + fee_deducted = before - after - amount + assert fee_deducted == fee_expected + + assert blk.gasUsed == txreceipt.gasUsed # we are the only tx in the block + + # check the next block's base fee is adjusted accordingly + w3_wait_for_block(w3, txreceipt.blockNumber + 1) + fee = w3.eth.get_block(txreceipt.blockNumber + 1).baseFeePerGas + params = cli.get_params("feemarket") + assert fee == adjust_base_fee( + blk.baseFeePerGas, blk.gasLimit, blk.gasUsed, params + ), fee + + +def test_base_fee_adjustment(custom_cluster): + """ + verify base fee adjustment of three continuous empty blocks + """ + cli = custom_cluster.cosmos_cli() + wait_for_new_blocks(cli, 1) + w3 = custom_cluster.w3 + begin = w3.eth.block_number + w3_wait_for_block(w3, begin + 3) + + blk = w3.eth.get_block(begin) + parent_fee = blk.baseFeePerGas + params = cli.get_params("feemarket") + + for i in range(3): + fee = w3.eth.get_block(begin + 1 + i).baseFeePerGas + assert fee == adjust_base_fee(parent_fee, blk.gasLimit, 0, params) + parent_fee = fee + + call = w3.provider.make_request + res = call("eth_feeHistory", [2, "latest", []])["result"]["baseFeePerGas"] + # nextBaseFee should align max with minGasPrice in eth_feeHistory + min_gas_price = max(float(params.get("min_gas_price", 0)) * WEI_PER_DENOM, 1) + assert all(fee == hex(int(min_gas_price)) for fee in res), res diff --git a/tests/integration_tests/test_permission.py b/tests/integration_tests/test_permission.py new file mode 100644 index 000000000..37e38386b --- /dev/null +++ b/tests/integration_tests/test_permission.py @@ -0,0 +1,82 @@ +import asyncio +from collections import defaultdict +from itertools import groupby +from pathlib import Path + +import pytest + +from .network import setup_custom_evm +from .utils import ( + DEFAULT_DENOM, + assert_transfer, + module_address, +) + +pytestmark = pytest.mark.asyncio + + +@pytest.fixture(scope="module") +def custom_evm(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("permission") + yield from setup_custom_evm( + path, + 26700, + Path(__file__).parent / "configs/accounts.jsonnet", + chain=chain, + ) + + +async def transfer(cli, user, addr_b): + nonce_locks = defaultdict(asyncio.Lock) + async with nonce_locks[user]: + rsp = await asyncio.to_thread( + cli.transfer, user, addr_b, f"1{DEFAULT_DENOM}", event_query_tx=False + ) + rsp = await asyncio.to_thread(cli.event_query_tx_for, rsp["txhash"]) + assert rsp["code"] == 4, rsp["raw_log"] + assert f"{addr_b} is not allowed to receive funds" in rsp["raw_log"] + return rsp + + +async def execute_user_transfers(cli, user_modules): + results = [] + for user_name, module in user_modules: + addr_b = module_address(module) + result = await transfer(cli, user_name, addr_b) + results.append(result) + return results + + +async def test_transfers_not_allowed(custom_evm): + cli = custom_evm.cosmos_cli() + modules = [ + "bonded_tokens_pool", + "distribution", + "erc20", + "evm", + "fee_collector", + "feemarket", + "gov", + "mint", + "not_bonded_tokens_pool", + "precisebank", + "transfer", + ] + users = cli.list_accounts() + users = [user["name"] for user in users if user["name"] != "reserve"] + pairs = [] + for i, module in enumerate(modules): + user = users[i % len(users)] + pairs.append((user, module)) + + user_groups = {} + for user, group in groupby(sorted(pairs), key=lambda x: x[0]): + user_groups[user] = list(group) + + user_tasks = [ + execute_user_transfers(cli, modules) for _, modules in user_groups.items() + ] + + await asyncio.gather(*user_tasks) + assert_transfer(cli, cli.address("community"), cli.address("signer1")) diff --git a/tests/integration_tests/test_precompile.py b/tests/integration_tests/test_precompile.py new file mode 100644 index 000000000..0328c0812 --- /dev/null +++ b/tests/integration_tests/test_precompile.py @@ -0,0 +1,654 @@ +import hashlib +from typing import Optional + +import pytest +from eth_account import Account +from eth_account.messages import encode_defunct +from eth_utils import to_hex +from hexbytes import HexBytes +from py_ecc.bls12_381 import G1, G2, add, multiply +from py_ecc.fields import FQ + +pytestmark = pytest.mark.asyncio + + +# Berlin precompile addresses +PRECOMPILE_ECRECOVER = "0x0000000000000000000000000000000000000001" +PRECOMPILE_SHA256 = "0x0000000000000000000000000000000000000002" +PRECOMPILE_RIPEMD160 = "0x0000000000000000000000000000000000000003" +PRECOMPILE_DATACOPY = "0x0000000000000000000000000000000000000004" +PRECOMPILE_BIGMODEXP = "0x0000000000000000000000000000000000000005" +PRECOMPILE_BN256ADD = "0x0000000000000000000000000000000000000006" +PRECOMPILE_BN256SCALARMUL = "0x0000000000000000000000000000000000000007" +PRECOMPILE_BN256PAIRING = "0x0000000000000000000000000000000000000008" +PRECOMPILE_BLAKE2F = "0x0000000000000000000000000000000000000009" +# Cancun precompile addresses +PRECOMPILE_KZG_POINT_EVALUATION = "0x000000000000000000000000000000000000000A" +# Prague precompile addresses +PRECOMPILE_BLS12381_G1_ADD = "0x000000000000000000000000000000000000000b" +PRECOMPILE_BLS12381_G1_MULTIEXP = "0x000000000000000000000000000000000000000C" +PRECOMPILE_BLS12381_G2_ADD = "0x000000000000000000000000000000000000000d" +PRECOMPILE_BLS12381_G2_MULTIEXP = "0x000000000000000000000000000000000000000E" +PRECOMPILE_BLS12381_PAIRING = "0x000000000000000000000000000000000000000F" +PRECOMPILE_BLS12381_MAP_G1 = "0x0000000000000000000000000000000000000010" +PRECOMPILE_BLS12381_MAP_G2 = "0x0000000000000000000000000000000000000011" + + +async def test_ecrecover(evm): + w3 = evm.async_w3 + account = Account.create() + message = b"hello world" + signable_message = encode_defunct(message) + signed_message = account.sign_message(signable_message) + message_hash = signed_message.message_hash + v = signed_message.v + r = signed_message.r + s = signed_message.s + # Prepare input: hash(32) + v(32) + r(32) + s(32) + input_data = ( + message_hash + + v.to_bytes(32, "big") + + r.to_bytes(32, "big") + + s.to_bytes(32, "big") + ) + result = await w3.eth.call( + { + "to": PRECOMPILE_ECRECOVER, + "data": to_hex(input_data), + } + ) + # The result should be the address (last 20 bytes, padded to 32) + recovered_address = "0x" + result[-20:].hex() + expected_address = account.address.lower() + + print(f"ecrecover result: {result.hex()}") + print(f"recovered address: {recovered_address}") + print(f"expected address: {expected_address}") + + assert recovered_address == expected_address + assert len(result) == 32 + + +async def test_sha256(evm): + w3 = evm.async_w3 + test_data = b"hello world" + result = await w3.eth.call( + { + "to": PRECOMPILE_SHA256, + "data": to_hex(test_data), + } + ) + expected = hashlib.sha256(test_data).digest() + assert result == expected + print(f"SHA-256 test passed: {result.hex()}") + + +async def test_ripemd160(evm): + w3 = evm.async_w3 + test_data = b"hello world" + result = await w3.eth.call( + { + "to": PRECOMPILE_RIPEMD160, + "data": to_hex(test_data), + } + ) + # RIPEMD-160 returns 20 bytes, left-padded to 32 bytes + assert len(result) == 32 + print(f"RIPEMD-160 test passed: {result.hex()}") + + +async def test_identity(evm): + w3 = evm.async_w3 + test_data = b"hello world test data" + result = await w3.eth.call( + { + "to": PRECOMPILE_DATACOPY, + "data": to_hex(test_data), + } + ) + assert result == test_data + print(f"Identity test passed: {result.hex()}") + + +async def test_bigmodexp(evm): + w3 = evm.async_w3 + # Test 2^2 mod 3 = 1 + base_len = (1).to_bytes(32, "big") # base length = 1 + exp_len = (1).to_bytes(32, "big") # exponent length = 1 + mod_len = (1).to_bytes(32, "big") # modulus length = 1 + base = (2).to_bytes(1, "big") # base = 2 + exp = (2).to_bytes(1, "big") # exponent = 2 + mod = (3).to_bytes(1, "big") # modulus = 3 + input_data = base_len + exp_len + mod_len + base + exp + mod + result = await w3.eth.call( + { + "to": PRECOMPILE_BIGMODEXP, + "data": to_hex(input_data), + } + ) + # 2^2 mod 3 = 4 mod 3 = 1 + expected = (1).to_bytes(1, "big") + assert result == expected + print(f"BigModExp test passed: {result.hex()}") + + +async def test_bn256add(evm): + w3 = evm.async_w3 + # Test adding two valid points on the curve + # Using generator point (1, 2) + point at infinity + p1_x = (1).to_bytes(32, "big") + p1_y = (2).to_bytes(32, "big") + p2_x = (0).to_bytes(32, "big") # Point at infinity + p2_y = (0).to_bytes(32, "big") + input_data = p1_x + p1_y + p2_x + p2_y + result = await w3.eth.call( + { + "to": PRECOMPILE_BN256ADD, + "data": to_hex(input_data), + } + ) + assert len(result) == 64 # Should return 64 bytes (two 32-byte coordinates) + print(f"bn256Add test passed: {result.hex()}") + + +async def test_bn256scalarmul(evm): + w3 = evm.async_w3 + # Multiply generator point by scalar 1 + p_x = (1).to_bytes(32, "big") + p_y = (2).to_bytes(32, "big") + scalar = (1).to_bytes(32, "big") + input_data = p_x + p_y + scalar + result = await w3.eth.call( + { + "to": PRECOMPILE_BN256SCALARMUL, + "data": to_hex(input_data), + } + ) + assert len(result) == 64 + print(f"bn256ScalarMul test passed: {result.hex()}") + + +async def test_bn256pairing(evm): + w3 = evm.async_w3 + # Empty input should return true (1) + result = await w3.eth.call({"to": PRECOMPILE_BN256PAIRING, "data": "0x"}) + # Empty pairing should return 1 (true) + expected = (1).to_bytes(32, "big") + assert result == expected + print(f"bn256Pairing test passed: {result.hex()}") + + +async def test_blake2f(evm): + w3 = evm.async_w3 + # Minimal test with 1 round + rounds = (1).to_bytes(4, "big") + h = b"\x00" * 64 # 64 bytes of state + m = b"\x00" * 128 # 128 bytes of message + t = b"\x00" * 16 # 16 bytes of offset counters + final_flag = b"\x01" # 1 byte final flag + input_data = rounds + h + m + t + final_flag + result = await w3.eth.call( + { + "to": PRECOMPILE_BLAKE2F, + "data": to_hex(input_data), + } + ) + assert len(result) == 64 # Should return 64 bytes + print(f"BLAKE2F test passed: {result.hex()}") + + +async def test_all_berlin_precompiles_exist(evm): + w3 = evm.async_w3 + berlin_precompiles = [ + PRECOMPILE_ECRECOVER, + PRECOMPILE_SHA256, + PRECOMPILE_RIPEMD160, + PRECOMPILE_DATACOPY, + PRECOMPILE_BIGMODEXP, + PRECOMPILE_BN256ADD, + PRECOMPILE_BN256SCALARMUL, + PRECOMPILE_BN256PAIRING, + PRECOMPILE_BLAKE2F, + ] + for address in berlin_precompiles: + # Check if precompile exists by getting code (should be empty) + code = await w3.eth.get_code(address) + print(f"{address}: code length {len(code)}") + # Precompiles should have empty code but still be callable + assert len(code) == 0, f"{address} should have empty code" + + +async def test_precompile_gas_costs_berlin(evm): + w3 = evm.async_w3 + # Test simple inputs to verify gas costs + test_cases = [ + (PRECOMPILE_ECRECOVER, "0x" + "00" * 128, 3000), # ECRecover base cost + (PRECOMPILE_SHA256, "0x" + "00" * 32, 60), # SHA256 base cost + (PRECOMPILE_RIPEMD160, "0x" + "00" * 32, 600), # RIPEMD160 base cost + (PRECOMPILE_DATACOPY, "0x" + "00" * 32, 15), # Identity base cost + (PRECOMPILE_BN256ADD, "0x" + "00" * 128, 150), # BN256Add cost + (PRECOMPILE_BN256SCALARMUL, "0x" + "00" * 96, 6000), # BN256ScalarMul cost + ] + for address, data, expected_min_gas in test_cases: + gas_estimate = await w3.eth.estimate_gas( + { + "to": address, + "data": data, + } + ) + print( + f"{address}: estimated gas {gas_estimate}, expected min {expected_min_gas}" + ) + assert gas_estimate >= expected_min_gas, f"Gas estimate too low for {address}" + + +class Spec: + # BLS12-381 field modulus + BLS_MODULUS = 0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001 + INF_POINT = b"\xc0" + b"\x00" * 47 + + @staticmethod + def pad_fq(x: FQ) -> bytes: + # py_ecc FQ elements are integers mod prime, 48 bytes big-endian native size + # Ethereum expects 64 bytes left-padded with zeros + as_bytes = x.n.to_bytes(48, "big") + return as_bytes.rjust(64, b"\x00") + + @classmethod + def point_to_bytes(cls, point) -> bytes: + if point is None: + # Represent point at infinity as zeros (128 bytes) + return b"\x00" * 128 + x, y = point + return cls.pad_fq(x) + cls.pad_fq(y) + + @classmethod + def g2_point_to_bytes(cls, point) -> bytes: + """Convert G2 point to 256 bytes.""" + if point is None: + # Represent point at infinity as zeros (256 bytes) + return b"\x00" * 256 + x, y = point + # G2 points have Fp2 coordinates: x = (x.c0, x.c1), y = (y.c0, y.c1) + # Each component is an FQ element that needs 64-byte padding + x_c0_bytes = cls.pad_fq(x.coeffs[0]) # 64 bytes + x_c1_bytes = cls.pad_fq(x.coeffs[1]) # 64 bytes + y_c0_bytes = cls.pad_fq(y.coeffs[0]) # 64 bytes + y_c1_bytes = cls.pad_fq(y.coeffs[1]) # 64 bytes + return x_c0_bytes + x_c1_bytes + y_c0_bytes + y_c1_bytes + + +# Identity element (point at infinity) +G1_IDENTITY = b"\x00" * 128 +G2_IDENTITY = b"\x00" * 256 +G1_GENERATOR = Spec.point_to_bytes(G1) +G2_GENERATOR = Spec.g2_point_to_bytes(G2) + +# Double the generator point: 2*G1 +G1_GENERATOR_DOUBLE_POINT = add(G1, G1) +G1_GENERATOR_DOUBLE = Spec.point_to_bytes(G1_GENERATOR_DOUBLE_POINT) + +# Example arbitrary test point (multiply G1 by 7) +TEST_POINT_1_POINT = multiply(G1, 7) +TEST_POINT_1 = Spec.point_to_bytes(TEST_POINT_1_POINT) + + +def kzg_to_versioned_hash(kzg_commitment: bytes) -> bytes: + """Convert KZG commitment to versioned hash.""" + hash_result = hashlib.sha256(kzg_commitment).digest() + # Add version byte (0x01 for KZG) + return bytes([0x01]) + hash_result[1:] + + +async def format_precompile_input( + versioned_hash: Optional[bytes], + z: int, + y: int, + kzg_commitment: bytes, + kzg_proof: bytes, +) -> bytes: + """Format the input for the point evaluation precompile (192 bytes total).""" + z_bytes = z.to_bytes(32, "big") + y_bytes = y.to_bytes(32, "big") + if versioned_hash is None: + versioned_hash = kzg_to_versioned_hash(kzg_commitment) + return versioned_hash + z_bytes + y_bytes + kzg_commitment + kzg_proof + + +async def test_kzg_point_evaluation(evm): + w3 = evm.async_w3 + # Use a valid input (infinity point) + input = await format_precompile_input( + versioned_hash=None, + z=Spec.BLS_MODULUS - 1, + y=0, + kzg_commitment=Spec.INF_POINT, + kzg_proof=Spec.INF_POINT, + ) + res = await w3.eth.call( + { + "to": PRECOMPILE_KZG_POINT_EVALUATION, + "data": to_hex(input), + "gas": 150000, + } + ) + prefix_bytes = b"\x00" * 30 + b"\x10\x00" + modulus_bytes = Spec.BLS_MODULUS.to_bytes(32, "big") + assert res == prefix_bytes + modulus_bytes + + +@pytest.mark.parametrize( + "point_a,point_b,expected", + [ + # Identity element tests + (G1_IDENTITY, G1_IDENTITY, G1_IDENTITY), + (G1_GENERATOR, G1_IDENTITY, G1_GENERATOR), + (G1_IDENTITY, G1_GENERATOR, G1_GENERATOR), + # Valid point addition tests + (G1_GENERATOR, G1_GENERATOR, G1_GENERATOR_DOUBLE), + (TEST_POINT_1, G1_IDENTITY, TEST_POINT_1), + ], + ids=[ + "identity_plus_identity", + "generator_plus_identity", + "identity_plus_generator", + "generator_plus_generator", + "test_point_plus_identity", + ], +) +async def test_bls12381_g1_add(evm, point_a, point_b: bytes, expected): + # Verify input points are correct length + if len(point_a) != 128 or len(point_b) != 128: + raise ValueError("Each G1 point must be exactly 128 bytes") + input_data = point_a + point_b + w3 = evm.async_w3 + res = await w3.eth.call( + { + "to": PRECOMPILE_BLS12381_G1_ADD, + "data": "0x" + input_data.hex(), + "gas": 30000, + } + ) + assert len(res) == 128 + assert expected == res + + +async def test_bls12381_g1_multiexp(evm): + w3 = evm.async_w3 + # Test case 1: Single point multiplication - G * 2 = 2G + # Input format: point (128 bytes) + scalar (32 bytes) = 160 bytes per pair + point1 = G1_GENERATOR + scalar1 = (2).to_bytes(32, "big") # Multiply by 2 + input_data = point1 + scalar1 + # Verify input points are correct length + assert len(point1) == 128, f"Point should be 128 bytes, got {len(point1)}" + assert len(scalar1) == 32, f"Scalar should be 32 bytes, got {len(scalar1)}" + assert ( + len(input_data) == 160 + ), f"Single multiexp input should be 160 bytes, got {len(input_data)}" + res = await w3.eth.call( + { + "to": PRECOMPILE_BLS12381_G1_MULTIEXP, + "data": "0x" + input_data.hex(), + "gas": 50000, + } + ) + assert len(res) == 128, f"Result should be 128 bytes, got {len(res)}" + assert res == G1_GENERATOR_DOUBLE, "G * 2 should equal 2G" + + +async def test_bls12381_g2_add(evm): + w3 = evm.async_w3 + # G2 points are 256 bytes each (128 bytes for X + 128 bytes for Y) + # Each coordinate (X, Y) is 128 bytes because G2 is over Fp2 (two Fp elements) + # Verify the generator point is exactly 256 bytes + assert ( + len(G2_GENERATOR) == 256 + ), f"G2 generator should be 256 bytes, got {len(G2_GENERATOR)}" + + async def call(input): + return await w3.eth.call( + { + "to": PRECOMPILE_BLS12381_G2_ADD, + "data": f"0x{input.hex()}", + "gas": 50000, + } + ) + + # Test case 1: Identity + Identity = Identity + input = G2_IDENTITY + G2_IDENTITY + assert len(input) == 512, f"G2 Add input should be 512 bytes, got {len(input)}" + res = await call(input) + assert len(res) == 256, f"G2 result should be 256 bytes, got {len(res)}" + assert res == G2_IDENTITY, "Identity + Identity should equal Identity" + + # Test case 2: Generator + Identity = Generator + input = G2_GENERATOR + G2_IDENTITY + assert len(input) == 512, f"G2 Add input should be 512 bytes, got {len(input)}" + res = await call(input) + assert len(res) == 256, f"G2 result should be 256 bytes, got {len(res)}" + assert res == G2_GENERATOR, "Generator + Identity should equal Generator" + + # Test case 3: Identity + Generator = Generator + input = G2_IDENTITY + G2_GENERATOR + assert len(input) == 512, f"G2 Add input should be 512 bytes, got {len(input)}" + res = await call(input) + assert len(res) == 256, f"G2 result should be 256 bytes, got {len(res)}" + assert res == G2_GENERATOR, "Identity + Generator should equal Generator" + + # Test case 4: Generator + Generator = 2*Generator (point doubling) + input = G2_GENERATOR + G2_GENERATOR + assert len(input) == 512, f"G2 Add input should be 512 bytes, got {len(input)}" + res = await call(input) + assert len(res) == 256, f"G2 result should be 256 bytes, got {len(res)}" + assert res != G2_GENERATOR, "Generator + Generator should not equal Generator" + assert res != G2_IDENTITY, "Generator + Generator should not equal Identity" + + +@pytest.mark.parametrize( + "points,scalars,expected", + [ + # Single point multiplication + ([G2_GENERATOR], [1], G2_GENERATOR), # G2 * 1 = G2 + ([G2_IDENTITY], [5], G2_IDENTITY), # Identity * 5 = Identity + ([G2_GENERATOR], [0], G2_IDENTITY), # G2 * 0 = Identity + # Multiple points with zero scalars + ([G2_GENERATOR, G2_GENERATOR], [0, 0], G2_IDENTITY), # G2*0 + G2*0 = Identity + # Identity point multiplication (should always result in identity) + ( + [G2_IDENTITY, G2_IDENTITY], + [100, 200], + G2_IDENTITY, + ), # Identity*100 + Identity*200 = Identity + ], + ids=[ + "g2_times_1", + "identity_times_5", + "g2_times_0", + "zero_scalars", + "identity_multiplication", + ], +) +async def test_bls12381_g2_multiexp(evm, points, scalars, expected): + w3 = evm.async_w3 + assert len(points) == len(scalars), "Number of points must equal number of scalars" + # Build input data: point1 + scalar1 + point2 + scalar2 + ... + input_data = b"" + for point, scalar in zip(points, scalars): + assert len(point) == 256, f"Each G2 point must be 256 bytes, got {len(point)}" + scalar_bytes = scalar.to_bytes(32, "big") + input_data += point + scalar_bytes + + expected_input_length = len(points) * 288 # 288 bytes per (point + scalar) pair + assert ( + len(input_data) == expected_input_length + ), f"Input should be {expected_input_length} bytes, got {len(input_data)}" + res = await w3.eth.call( + { + "to": PRECOMPILE_BLS12381_G2_MULTIEXP, + "data": "0x" + input_data.hex(), + "gas": 100000, + } + ) + assert len(res) == 256, f"G2 result should be 256 bytes, got {len(res)}" + assert res == expected, f"Expected {expected.hex()}, got {res.hex()}" + + +@pytest.mark.parametrize( + "pairs", + [ + # Single pair with identities (should be true) + ([(G1_IDENTITY, G2_GENERATOR)]), + ([(G1_GENERATOR, G2_IDENTITY)]), + ([(G1_IDENTITY, G2_IDENTITY)]), + # Multiple pairs that should result in true + ([(G1_IDENTITY, G2_GENERATOR), (G1_GENERATOR, G2_IDENTITY)]), + ([(G1_IDENTITY, G2_IDENTITY), (G1_IDENTITY, G2_IDENTITY)]), + ], + ids=[ + "g1_identity_g2_gen", + "g1_gen_g2_identity", + "double_identity", + "mixed_identities", + "all_identities", + ], +) +async def test_bls12381_pairing(evm, pairs): + w3 = evm.async_w3 + # Build input data: g1_point1 + g2_point1 + g1_point2 + g2_point2 + ... + input_data = b"" + for g1_point, g2_point in pairs: + assert len(g1_point) == 128, f"G1 point must be 128 bytes, got {len(g1_point)}" + assert len(g2_point) == 256, f"G2 point must be 256 bytes, got {len(g2_point)}" + input_data += g1_point + g2_point + + expected_input_length = len(pairs) * 384 # 384 bytes per (G1 + G2) pair + assert ( + len(input_data) == expected_input_length + ), f"Input should be {expected_input_length} bytes, got {len(input_data)}" + res = await w3.eth.call( + { + "to": PRECOMPILE_BLS12381_PAIRING, + "data": "0x" + input_data.hex(), + "gas": 200000 + len(pairs) * 100000, # More gas for more pairs + } + ) + assert len(res) == 32, f"Pairing result should be 32 bytes, got {len(res)}" + expected_bytes = b"\x00" * 31 + b"\x01" + assert res == expected_bytes, f"Expected true (1), got {res.hex()}" + + +@pytest.mark.parametrize( + "field", + [ + 0, + 1, + 2, + 42, + 2**64 - 1, + Spec.BLS_MODULUS // 2, + Spec.BLS_MODULUS - 1, + ], + ids=[ + "zero", + "one", + "two", + "forty_two", + "large_number", + "half_modulus", + "max_field_element", + ], +) +async def test_bls12381_map_g1(evm, field): + w3 = evm.async_w3 + input = field.to_bytes(64, "big") + assert len(input) == 64, f"input should be 64 bytes, got {len(input)}" + res = await w3.eth.call( + { + "to": PRECOMPILE_BLS12381_MAP_G1, + "data": f"0x{input.hex()}", + "gas": 50000, + } + ) + assert len(res) == 128, f"G1 map result should be 128 bytes, got {len(res)}" + + +@pytest.mark.parametrize( + "field_pair", + [ + (0, 0), + (1, 0), + (0, 1), + (1, 1), + (42, 123), + (2**64 - 1, 2**32 - 1), + (Spec.BLS_MODULUS // 2, Spec.BLS_MODULUS // 3), + (Spec.BLS_MODULUS - 1, Spec.BLS_MODULUS - 2), + ], + ids=[ + "zero_zero", + "one_zero", + "zero_one", + "one_one", + "forty_two_oneTwoThree", + "large_numbers", + "half_third_modulus", + "max_field_elements", + ], +) +async def test_bls12381_map_g2(evm, field_pair): + w3 = evm.async_w3 + field1, field2 = field_pair + # G2 map takes two field elements (128 bytes total: 64 bytes each) + # This represents an Fp2 element: field1 + field2 * i + data1 = field1.to_bytes(64, "big") + data2 = field2.to_bytes(64, "big") + input = data1 + data2 + assert len(input) == 128, f"G2 map input should be 128 bytes, got {len(input)}" + res = await w3.eth.call( + { + "to": PRECOMPILE_BLS12381_MAP_G2, + "data": "0x" + input.hex(), + "gas": 75000, + } + ) + assert len(res) == 256, f"G2 map result should be 256 bytes, got {len(res)}" + + +async def test_move_precompile_to(evm): + w3 = evm.async_w3 + moved = w3.to_checksum_address("0x00000000000000000000000000000000deadbeef") + input = 1 + code = "0x60003560010160005260206000f3" # bytecode: adds one to input + res = await w3.eth.call( + { + "to": PRECOMPILE_ECRECOVER, + "data": input.to_bytes(32, byteorder="big"), + }, + "latest", + { + PRECOMPILE_ECRECOVER: { + "code": code, + "movePrecompileToAddress": moved, + }, + }, + ) + output = 2 + assert res == output.to_bytes(32, byteorder="big") + + input = "0x82f3df49d3645876de6313df2bbe9fbce593f21341a7b03acdb9423bc171fcc9000000000000000000000000000000000000000000000000000000000000001cba13918f50da910f2d55a7ea64cf716ba31dad91856f45908dde900530377d8a112d60f36900d18eb8f9d3b4f85a697b545085614509e3520e4b762e35d0d6bd" # noqa: E501 + res = await w3.eth.call( + { + "to": moved, + "data": HexBytes(input), + }, + "latest", + { + PRECOMPILE_ECRECOVER: { + "code": code, + "movePrecompileToAddress": moved, + }, + }, + ) + output = "0x000000000000000000000000c6e93f4c1920eaeaa1e699f76a7a8c18e3056074" + assert res == HexBytes(output) diff --git a/tests/integration_tests/test_priority.py b/tests/integration_tests/test_priority.py new file mode 100644 index 000000000..38a1c1851 --- /dev/null +++ b/tests/integration_tests/test_priority.py @@ -0,0 +1,242 @@ +import sys +from pathlib import Path + +import pytest +import web3 +from pystarport.utils import wait_for_new_blocks + +from .network import setup_custom_evm +from .utils import ( + ADDRS, + DEFAULT_DENOM, + KEYS, + WEI_PER_DENOM, + eth_to_bech32, + send_transaction, + sign_transaction, +) + +PRIORITY_REDUCTION = 1000000 + + +def effective_gas_price(tx, base_fee): + if "maxFeePerGas" in tx: + # dynamic fee tx + return min(base_fee + tx["maxPriorityFeePerGas"], tx["maxFeePerGas"]) + else: + # legacy tx + return tx["gasPrice"] + + +def tx_priority(tx, base_fee): + if "maxFeePerGas" in tx: + # dynamic fee tx + return ( + min(tx["maxPriorityFeePerGas"], tx["maxFeePerGas"] - base_fee) + // PRIORITY_REDUCTION + ) + else: + # legacy tx + return (tx["gasPrice"] - base_fee) // PRIORITY_REDUCTION + + +@pytest.mark.skip(reason="https://github.com/cosmos/evm/pull/806") +def test_priority(evm): + """ + test priorities of different tx types + + use a relatively large priority number to counter + the effect of base fee change during the testing. + """ + w3 = evm.w3 + amount = 10000 + base_fee = w3.eth.get_block("latest").baseFeePerGas + + # [ ( sender, tx ), ... ] + # use different senders to avoid nonce conflicts + test_cases = [ + ( + "validator", + { + "to": "0x0000000000000000000000000000000000000000", + "value": amount, + "gas": 21000, + "maxFeePerGas": base_fee + PRIORITY_REDUCTION * 600000, + "maxPriorityFeePerGas": PRIORITY_REDUCTION, + }, + ), + ( + "community", + { + "to": "0x0000000000000000000000000000000000000000", + "value": amount, + "gas": 21000, + "gasPrice": base_fee + PRIORITY_REDUCTION * 200000, + }, + ), + ( + "signer2", + { + "to": "0x0000000000000000000000000000000000000000", + "value": amount, + "gasPrice": base_fee + PRIORITY_REDUCTION * 400000, + "accessList": [ + { + "address": "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae", + "storageKeys": ( + "0x00000000000000000000000000000000000000000000000000000000" + "00000003", + "0x00000000000000000000000000000000000000000000000000000000" + "00000007", + ), + } + ], + }, + ), + ( + "signer1", + { + "to": "0x0000000000000000000000000000000000000000", + "value": amount, + "gas": 21000, + "maxFeePerGas": base_fee + PRIORITY_REDUCTION * 600000, + "maxPriorityFeePerGas": PRIORITY_REDUCTION * 600000, + }, + ), + ] + + # test cases are ordered by priority + expect_priorities = [tx_priority(tx, base_fee) for _, tx in test_cases] + assert expect_priorities == [1, 200000, 400000, 600000] + + signed = [sign_transaction(w3, tx, key=KEYS[sender]) for sender, tx in test_cases] + # send the txs from low priority to high, + # but the later sent txs should be included earlier. + txhashes = [w3.eth.send_raw_transaction(tx.raw_transaction) for tx in signed] + + receipts = [w3.eth.wait_for_transaction_receipt(txhash) for txhash in txhashes] + print(receipts) + assert all(receipt.status == 1 for receipt in receipts), "expect all txs success" + + # the later txs should be included earlier because of higher priority + # FIXME there's some non-deterministics due to mempool logic + tx_indexes = [(r.blockNumber, r.transactionIndex) for r in receipts] + print(tx_indexes) + # the first sent tx are included later, because of lower priority + # ensure desc within continuous block + assert all( + (b1 < b2 or (b1 == b2 and i1 > i2)) + for (b1, i1), (b2, i2) in zip(tx_indexes, tx_indexes[1:]) + ) + + +def conver_gas_prices(base_fee, value): + return base_fee + (value * PRIORITY_REDUCTION) / WEI_PER_DENOM + + +@pytest.fixture(scope="module") +def custom_evm(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("default") + yield from setup_custom_evm( + path, + 27100, + Path(__file__).parent / "configs/default.jsonnet", + chain=chain, + ) + + +def test_native_tx_priority(custom_evm): + cli = custom_evm.cosmos_cli() + base_fee = float(cli.query_base_fee()) + amt = f"1000{DEFAULT_DENOM}" + test_cases = [ + { + "from": eth_to_bech32(ADDRS["community"]), + "to": eth_to_bech32(ADDRS["validator"]), + "amount": amt, + "gas_prices": f"{conver_gas_prices(base_fee, 600000)}{DEFAULT_DENOM}", + "max_priority_price": 0, + }, + { + "from": eth_to_bech32(ADDRS["signer1"]), + "to": eth_to_bech32(ADDRS["signer2"]), + "amount": amt, + "gas_prices": f"{conver_gas_prices(base_fee, 600000)}{DEFAULT_DENOM}", + "max_priority_price": PRIORITY_REDUCTION * 200000 / WEI_PER_DENOM, + }, + { + "from": eth_to_bech32(ADDRS["signer2"]), + "to": eth_to_bech32(ADDRS["signer1"]), + "amount": amt, + "gas_prices": f"{conver_gas_prices(base_fee, 400000)}{DEFAULT_DENOM}", + "max_priority_price": PRIORITY_REDUCTION * 400000 / WEI_PER_DENOM, + }, + { + "from": eth_to_bech32(ADDRS["validator"]), + "to": eth_to_bech32(ADDRS["community"]), + "amount": amt, + "gas_prices": f"{conver_gas_prices(base_fee, 600000)}{DEFAULT_DENOM}", + "max_priority_price": None, # no extension, maximum tipFeeCap + }, + ] + txs = [] + expect_priorities = [] + for tc in test_cases: + tx = cli.transfer( + tc["from"], + tc["to"], + tc["amount"], + gas_prices=tc["gas_prices"], + generate_only=True, + ) + txs.append( + cli.sign_tx_json( + tx, tc["from"], max_priority_price=tc.get("max_priority_price") + ) + ) + gas_price = float(tc["gas_prices"].removesuffix(DEFAULT_DENOM)) + res = min( + get_max_priority_price(tc.get("max_priority_price")), gas_price - base_fee + ) + expect_priorities.append((res * WEI_PER_DENOM) // PRIORITY_REDUCTION) + assert expect_priorities == [0, 200000, 400000, 600000] + + txhashes = [] + for tx in txs: + rsp = cli.broadcast_tx_json(tx) + assert rsp["code"] == 0, rsp["raw_log"] + txhashes.append(rsp["txhash"]) + + print("wait for two new blocks, so the sent txs are all included") + wait_for_new_blocks(cli, 2) + + tx_results = [cli.tx_search_rpc(f"tx.hash='{txhash}'")[0] for txhash in txhashes] + tx_indexes = [(int(r["height"]), r["index"]) for r in tx_results] + print(tx_indexes) + # the first sent tx are included later, because of lower priority + # ensure desc within continuous block + assert all( + (b1 < b2 or (b1 == b2 and i1 > i2)) + for (b1, i1), (b2, i2) in zip(tx_indexes, tx_indexes[1:]) + ) + + +def get_max_priority_price(max_priority_price): + "default to max int64 if None" + return max_priority_price if max_priority_price is not None else sys.maxsize + + +def test_validate(evm): + w3 = evm.w3 + gas = int(1.2 * w3.eth.gas_price) + tx = { + "to": "0x0000000000000000000000000000000000000000", + "value": 1, + "gas": 21000, + "maxFeePerGas": gas, + "maxPriorityFeePerGas": gas + 1, + } + with pytest.raises(web3.exceptions.Web3RPCError) as exc: + send_transaction(w3, tx) + assert "max priority fee per gas higher than max fee per gas" in str(exc) diff --git a/tests/integration_tests/test_staking.py b/tests/integration_tests/test_staking.py new file mode 100644 index 000000000..c9a64b24e --- /dev/null +++ b/tests/integration_tests/test_staking.py @@ -0,0 +1,172 @@ +import time +from datetime import timedelta +from pathlib import Path + +import pytest +from dateutil.parser import isoparse +from pystarport import cluster +from pystarport.utils import ( + BondStatus, + wait_for_block, + wait_for_block_time, + wait_for_new_blocks, +) + +from .network import setup_custom_evm +from .utils import ( + CMD, + DEFAULT_DENOM, + DEFAULT_GAS_PRICE, + WEI_PER_DENOM, + duration, + edit_app_cfg, + find_fee, + find_log_event_attrs, +) + +pytestmark = pytest.mark.slow + + +@pytest.fixture(scope="module") +def custom_evm(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("staking") + yield from setup_custom_evm( + path, + 26800, + Path(__file__).parent / "configs/staking.jsonnet", + chain=chain, + ) + + +def test_staking_unbond(evm): + cli = evm.cosmos_cli() + unbond_duration = duration(cli.get_params("staking")["unbonding_time"]) + if unbond_duration > 60: + pytest.skip(f"unbond_duration is {unbond_duration} too long for test") + name = "signer1" + signer1 = cli.address(name) + validators = cli.validators() + val_ops = [v["operator_address"] for v in validators[:2]] + balance_bf = cli.balance(signer1) + bonded_bf = cli.staking_pool() + amounts = [3, 4] + fee = 0 + gas = 250_000 + + for i, amt in enumerate(amounts): + rsp = cli.delegate_amount( + val_ops[i], f"{amt}{DEFAULT_DENOM}", _from=name, gas=gas + ) + assert rsp["code"] == 0, rsp["raw_log"] + fee += find_fee(rsp) + + assert cli.staking_pool() == bonded_bf + sum(amounts) + assert cli.balance(signer1) == balance_bf - sum(amounts) - fee + + unbonded = cli.staking_pool(bonded=False) + unbonded_amt = 2 + rsp = cli.unbond_amount( + val_ops[1], f"{unbonded_amt}{DEFAULT_DENOM}", _from=name, gas=gas + ) + assert rsp["code"] == 0, rsp["raw_log"] + fee += find_fee(rsp) + assert cli.staking_pool(bonded=False) == unbonded + unbonded_amt + data = find_log_event_attrs( + rsp["events"], "unbond", lambda attrs: "completion_time" in attrs + ) + wait_for_block_time(cli, isoparse(data["completion_time"]) + timedelta(seconds=1)) + assert cli.balance(signer1) == balance_bf - (sum(amounts) - unbonded_amt) - fee + + +def test_staking_redelegate(evm): + cli = evm.cosmos_cli() + name = "signer1" + signer1 = cli.address(name) + validators = cli.validators() + val_ops = [v["operator_address"] for v in validators[:2]] + amounts = [3, 4] + fee = 0 + gas = 400_000 + + for i, amt in enumerate(amounts): + rsp = cli.delegate_amount( + val_ops[i], f"{amt}{DEFAULT_DENOM}", _from=name, gas=gas + ) + assert rsp["code"] == 0, rsp["raw_log"] + fee += find_fee(rsp) + + balance_bf = cli.delegation(signer1, val_ops[0])["balance"]["amount"] + redelegate_amt = 2 + rsp = cli.redelegate( + val_ops[0], + val_ops[1], + f"{redelegate_amt}{DEFAULT_DENOM}", + _from=name, + gas=gas, + ) + assert rsp["code"] == 0, rsp["raw_log"] + balance = cli.delegation(signer1, val_ops[0])["balance"]["amount"] + assert int(balance_bf) == int(balance) + redelegate_amt + + +def test_join_validator(evm): + data = Path(evm.base_dir).parent + chain_id = evm.config["chain_id"] + clustercli = cluster.ClusterCLI(data, cmd=CMD, chain_id=chain_id) + moniker = "new joined" + node_index = clustercli.create_node(moniker=moniker) + cli = clustercli.cosmos_cli(node_index) + cli0 = evm.cosmos_cli() + staked = 10_000_000_000_000_000_000 + fund = f"{staked + 1_000_000_000_000_000_000 // WEI_PER_DENOM}{DEFAULT_DENOM}" + val_addr = cli.address("validator", bech="val") + addr = cli.address("validator") + res = cli0.transfer(cli0.address("community"), addr, fund) + assert res["code"] == 0, res + edit_app_cfg(clustercli, node_index) + clustercli.supervisor.startProcess(f"{chain_id}-node{node_index}") + wait_for_block(cli, cli0.block_height() + 1) + time.sleep(1) + wait_for_block(cli, cli.block_height()) + + count = len(cli.validators()) + gas = 420_000 + opts = {"gas_prices": DEFAULT_GAS_PRICE, "gas": gas} + rsp = cli.create_validator(f"{staked}{DEFAULT_DENOM}", {"moniker": moniker}, **opts) + assert rsp["code"] == 0, rsp["raw_log"] + time.sleep(2) + assert len(cli.validators()) == count + 1 + + val = cli.validator(val_addr) + assert not val.get("jailed") + assert val["status"] == BondStatus.BONDED.value + assert val["tokens"] == str(staked) + assert val["description"]["moniker"] == moniker + assert val["commission"]["commission_rates"] == { + "rate": "0.100000000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.010000000000000000", + } + rsp = cli.edit_validator(commission_rate="0.2", **opts) + assert rsp["code"] == 12, rsp["raw_log"] + assert "commission cannot be changed more than once in 24h" in rsp["raw_log"] + rsp = cli.edit_validator(new_moniker="awesome node", **opts) + assert rsp["code"] == 0, rsp["raw_log"] + assert cli.validator(val_addr)["description"]["moniker"] == "awesome node" + + +def test_min_self_delegation(custom_evm): + cli = custom_evm.cosmos_cli(i=3) + val = cli.address("validator", bech="val") + addr = cli.address("validator") + gas = 320_000 + amt = 9_000_000_000_000_000_000 + assert ( + cli.unbond_amount(val, f"{amt}{DEFAULT_DENOM}", _from=addr, gas=gas)["code"] + == 0 + ) + assert cli.validator(val).get("status") == BondStatus.BONDED.value + assert cli.unbond_amount(val, f"1{DEFAULT_DENOM}", _from=addr, gas=gas)["code"] == 0 + wait_for_new_blocks(cli, 2) + assert cli.validator(val).get("status") == BondStatus.UNBONDING.value diff --git a/tests/integration_tests/test_staking_precompile.py b/tests/integration_tests/test_staking_precompile.py new file mode 100644 index 000000000..f2d56c38c --- /dev/null +++ b/tests/integration_tests/test_staking_precompile.py @@ -0,0 +1,289 @@ +import json +import os +import time +from datetime import timedelta +from pathlib import Path + +import pytest +import requests +import web3 +from dateutil.parser import isoparse +from eth_account import Account +from eth_contract.contract import Contract +from pystarport import cluster +from pystarport.utils import ( + BondStatus, + wait_for_block, + wait_for_block_time, + wait_for_new_blocks, +) + +from .network import setup_custom_evm +from .utils import ( + ACCOUNTS, + CMD, + DEFAULT_DENOM, + WEI_PER_DENOM, + WEI_PER_ETH, + address_to_bytes32, + bech32_to_eth, + build_contract, + duration, + edit_app_cfg, + find_log_event_attrs, +) + +PRECOMPILE = Contract(build_contract("StakingI")["abi"]) +DELEGATE = PRECOMPILE.fns.delegate +UNDELEGATE = PRECOMPILE.fns.undelegate +VALIDATOR = PRECOMPILE.fns.validator +STAKING = "0x0000000000000000000000000000000000000800" +gas = 400_000 + + +pytestmark = pytest.mark.asyncio + + +@pytest.fixture(scope="module") +def custom_evm(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("staking") + yield from setup_custom_evm( + path, + 27200, + Path(__file__).parent / "configs/staking.jsonnet", + chain=chain, + ) + + +async def get_validators(w3): + params = [b"", 0, 10, False, False] + res, _ = await PRECOMPILE.fns.validators(BondStatus.BONDED.value, params).call( + w3, to=STAKING + ) + return res + + +async def test_staking_delegate(evm): + cli = evm.cosmos_cli() + w3 = evm.async_w3 + name = "signer1" + amt = 2 + acct = ACCOUNTS[name] + bonded = cli.staking_pool() + balance_bf = await w3.eth.get_balance(acct.address) + res = await get_validators(w3) + addr = res[0][0] + validator = cli.debug_addr(addr, bech="val") + gas = 200_000 + res = await DELEGATE(acct.address, validator, amt).transact( + w3, acct, to=STAKING, gas=gas + ) + assert res.status == 1 + assert res.logs[0].topics == [ + PRECOMPILE.events.Delegate.topic, + address_to_bytes32(acct.address), + address_to_bytes32(addr), + ] + fee = res["gasUsed"] * res["effectiveGasPrice"] + assert cli.staking_pool() == bonded + amt + balance = await w3.eth.get_balance(acct.address) + assert balance_bf == balance + amt * WEI_PER_DENOM + fee + + +async def test_staking_unbond(evm): + cli = evm.cosmos_cli() + unbond_duration = duration(cli.get_params("staking")["unbonding_time"]) + if unbond_duration > 60: + pytest.skip(f"unbond_duration is {unbond_duration} too long for test") + w3 = evm.async_w3 + name = "signer1" + acct = ACCOUNTS[name] + res = await get_validators(w3) + val_ops = [cli.debug_addr(validator[0], bech="val") for validator in res[:2]] + balance_bf = await w3.eth.get_balance(acct.address) + bonded_bf = cli.staking_pool() + amounts = [3, 4] + fee = 0 + + for i, amt in enumerate(amounts): + res = await DELEGATE(acct.address, val_ops[i], amt).transact( + w3, acct, to=STAKING, gas=gas + ) + assert res.status == 1 + fee += res["gasUsed"] * res["effectiveGasPrice"] + + assert cli.staking_pool() == bonded_bf + sum(amounts) + balance = await w3.eth.get_balance(acct.address) + assert balance == balance_bf - sum(amounts) * WEI_PER_DENOM - fee + + unbonded_bf = cli.staking_pool(bonded=False) + unbonded_amt = 2 + res = await UNDELEGATE(acct.address, val_ops[0], unbonded_amt).transact( + w3, acct, to=STAKING, gas=gas + ) + assert res.status == 1 + addr = cli.debug_addr(val_ops[0], bech="hex") + assert res.logs[0].topics == [ + PRECOMPILE.events.Unbond.topic, + address_to_bytes32(acct.address), + address_to_bytes32(addr), + ] + fee += res["gasUsed"] * res["effectiveGasPrice"] + assert cli.staking_pool(bonded=False) == unbonded_bf + unbonded_amt + blk = res["blockNumber"] + rsp = requests.get(f"{cli.node_rpc_http}/block_results?height={blk}").json() + rsp = next((tx for tx in rsp["result"]["txs_results"] if tx["code"] == 0), None) + data = find_log_event_attrs( + rsp["events"], "unbond", lambda attrs: "completion_time" in attrs + ) + wait_for_block_time(cli, isoparse(data["completion_time"]) + timedelta(seconds=1)) + balance = await w3.eth.get_balance(acct.address) + assert balance == balance_bf - (sum(amounts) - unbonded_amt) * WEI_PER_DENOM - fee + + +async def test_staking_redelegate(evm): + cli = evm.cosmos_cli() + w3 = evm.async_w3 + name = "signer1" + acct = ACCOUNTS[name] + res = await get_validators(w3) + val_ops = [cli.debug_addr(validator[0], bech="val") for validator in res[:2]] + amounts = [3, 4] + fee = 0 + + for i, amt in enumerate(amounts): + res = await DELEGATE(acct.address, val_ops[i], amt).transact( + w3, acct, to=STAKING, gas=gas + ) + assert res.status == 1 + fee += res["gasUsed"] * res["effectiveGasPrice"] + + DELEGATION = PRECOMPILE.fns.delegation + _, balance_bf = await DELEGATION(acct.address, val_ops[0]).call(w3, to=STAKING) + redelegate_amt = 2 + res = await PRECOMPILE.fns.redelegate( + acct.address, val_ops[0], val_ops[1], redelegate_amt + ).transact(w3, acct, to=STAKING, gas=gas) + assert res.status == 1 + assert res.logs[0].topics == [ + PRECOMPILE.events.Redelegate.topic, + address_to_bytes32(acct.address), + address_to_bytes32(cli.debug_addr(val_ops[0], bech="hex")), + address_to_bytes32(cli.debug_addr(val_ops[1], bech="hex")), + ] + fee += res["gasUsed"] * res["effectiveGasPrice"] + _, balance = await DELEGATION(acct.address, val_ops[0]).call(w3, to=STAKING) + assert balance_bf[1] == balance[1] + redelegate_amt + + +async def test_join_validator(evm): + w3 = evm.async_w3 + mnemonic = os.getenv("VALIDATOR4_MNEMONIC") + acct = Account.from_mnemonic(mnemonic) + data = Path(evm.base_dir).parent + chain_id = evm.config["chain_id"] + clustercli = cluster.ClusterCLI(data, cmd=CMD, chain_id=chain_id) + moniker = "new joined" + node_index = clustercli.create_node(moniker=moniker, mnemonic=mnemonic) + cli = clustercli.cosmos_cli(node_index) + cli0 = evm.cosmos_cli() + staked = 10_000_000_000_000_000_000 + fund = f"{staked + 1_000_000_000_000_000_000 // WEI_PER_DENOM}{DEFAULT_DENOM}" + val_addr = cli.address("validator", bech="val") + addr = cli0.debug_addr(val_addr, bech="hex") + + res = cli0.transfer(cli0.address("community"), cli.address("validator"), fund) + assert res["code"] == 0, res + edit_app_cfg(clustercli, node_index) + clustercli.supervisor.startProcess(f"{chain_id}-node{node_index}") + wait_for_block(cli, cli0.block_height() + 1) + time.sleep(1) + wait_for_block(cli, cli.block_height()) + + count = len(cli.validators()) + pubkey = ( + cli.raw( + "comet", + "show-validator", + home=cli.data_dir, + ) + .strip() + .decode() + ) + pubkey = json.loads(pubkey)["key"] + desc = [moniker, "identity", "website", "securityContact", "details"] + commission = [ + int(0.1 * WEI_PER_ETH), + int(0.2 * WEI_PER_ETH), + int(0.01 * WEI_PER_ETH), + ] + min_self_delegation = 1 + res = await PRECOMPILE.fns.createValidator( + desc, commission, min_self_delegation, acct.address, pubkey, staked + ).transact(w3, acct, to=STAKING, gas=gas) + assert res.status == 1 + assert res.logs[0].topics == [ + PRECOMPILE.events.CreateValidator.topic, + address_to_bytes32(addr), + ] + time.sleep(2) + assert len(cli.validators()) == count + 1 + + val = cli.validator(val_addr) + assert not val.get("jailed") + assert val["status"] == BondStatus.BONDED.value + assert val["tokens"] == str(staked) + assert val["description"]["moniker"] == moniker + assert val["commission"]["commission_rates"] == { + "rate": "0.100000000000000000", + "max_rate": "0.200000000000000000", + "max_change_rate": "0.010000000000000000", + } + + EDIT_VALIDATOR = PRECOMPILE.fns.editValidator + msg = "commission cannot be changed more than once in 24h" + with pytest.raises(web3.exceptions.ContractLogicError, match=msg): + await EDIT_VALIDATOR( + desc, acct.address, commission[0] * 2, min_self_delegation + ).transact(w3, acct, to=STAKING) + + desc[0] = "awesome node" + res = await EDIT_VALIDATOR(desc, acct.address, -1, -1).transact( + w3, acct, to=STAKING, gas=gas + ) + assert res.status == 1 + assert res.logs[0].topics == [ + PRECOMPILE.events.EditValidator.topic, + address_to_bytes32(addr), + ] + assert cli.validator(val_addr)["description"]["moniker"] == "awesome node" + + +async def test_min_self_delegation(custom_evm): + mnemonic = os.getenv("VALIDATOR4_MNEMONIC") + acct = Account.from_mnemonic(mnemonic) + cli = custom_evm.cosmos_cli(i=3) + w3 = custom_evm.async_w3 + addr = bech32_to_eth(cli.address("validator")) + val = cli.address("validator", bech="val") + amt = 9_000_000_000_000_000_000 + res = await UNDELEGATE(acct.address, val, amt).transact( + w3, acct, to=STAKING, gas=gas + ) + assert res.status == 1 + res = await VALIDATOR(addr).call(w3, to=STAKING) + assert res[3] == BondStatus.BONDED.to_int() + amt = 1 + res = await UNDELEGATE(acct.address, val, amt).transact( + w3, acct, to=STAKING, gas=gas + ) + assert res.status == 1 + assert res.logs[0].topics == [ + PRECOMPILE.events.Unbond.topic, + address_to_bytes32(acct.address), + address_to_bytes32(addr), + ] + wait_for_new_blocks(cli, 2) + res = await VALIDATOR(addr).call(w3, to=STAKING) + assert res[3] == BondStatus.UNBONDING.to_int() diff --git a/tests/integration_tests/test_subscribe.py b/tests/integration_tests/test_subscribe.py new file mode 100644 index 000000000..26e483882 --- /dev/null +++ b/tests/integration_tests/test_subscribe.py @@ -0,0 +1,170 @@ +import asyncio +import json +import time +from collections import defaultdict + +import websockets +from eth_utils import abi +from hexbytes import HexBytes +from pystarport import ports +from pystarport.utils import wait_for_new_blocks, wait_for_port +from web3 import Web3 + +from .network import Evm +from .utils import ( + ADDRS, + KEYS, + Contract, + send_raw_transactions, + send_transaction, + sign_transaction, +) + + +class Client: + def __init__(self, ws): + self._ws = ws + self._gen_id = 0 + self._subs = defaultdict(asyncio.Queue) + self._rsps = defaultdict(asyncio.Queue) + + def gen_id(self): + self._gen_id += 1 + return self._gen_id + + async def receive_loop(self): + while True: + msg = json.loads(await self._ws.recv()) + if "id" in msg: + # responses + await self._rsps[msg["id"]].put(msg) + else: + # subscriptions + assert msg["method"] == "eth_subscription" + sub_id = msg["params"]["subscription"] + await self._subs[sub_id].put(msg["params"]["result"]) + + async def recv_response(self, rpcid): + rsp = await self._rsps[rpcid].get() + del self._rsps[rpcid] + return rsp + + async def recv_subscription(self, sub_id): + return await self._subs[sub_id].get() + + async def subscribe(self, *args): + rpcid = self.gen_id() + await self._ws.send( + json.dumps({"id": rpcid, "method": "eth_subscribe", "params": args}) + ) + rsp = await self.recv_response(rpcid) + assert "error" not in rsp + return rsp["result"] + + def sub_qsize(self, sub_id): + return self._subs[sub_id].qsize() + + async def unsubscribe(self, sub_id): + rpcid = self.gen_id() + await self._ws.send( + json.dumps({"id": rpcid, "method": "eth_unsubscribe", "params": [sub_id]}) + ) + rsp = await self.recv_response(rpcid) + assert "error" not in rsp + return rsp["result"] + + +# TestEvent topic from TestMessageCall contract calculated from event signature +TEST_EVENT_TOPIC = Web3.keccak(text="TestEvent(uint256)") + + +def test_subscribe_basic(evm: Evm): + """ + test basic subscribe and unsubscribe + """ + wait_for_port(ports.evmrpc_ws_port(evm.base_port(0))) + cli = evm.cosmos_cli() + loop = asyncio.get_event_loop() + + async def assert_unsubscribe(c: Client, sub_id): + assert await c.unsubscribe(sub_id) + # check no more messages + await loop.run_in_executor(None, wait_for_new_blocks, cli, 2) + assert c.sub_qsize(sub_id) == 0 + # unsubscribe again return False + assert not await c.unsubscribe(sub_id) + + async def subscriber_test(c: Client): + sub_id = await c.subscribe("newHeads") + # wait for three new blocks + msgs = [await c.recv_subscription(sub_id) for i in range(3)] + # check blocks are consecutive + assert int(msgs[1]["number"], 0) == int(msgs[0]["number"], 0) + 1 + assert int(msgs[2]["number"], 0) == int(msgs[1]["number"], 0) + 1 + await assert_unsubscribe(c, sub_id) + + async def transfer_test(c: Client, w3, contract, address): + sub_id = await c.subscribe("logs", {"address": address}) + to = ADDRS["signer1"] + _from = ADDRS["community"] + total = 5 + topic = abi.event_signature_to_log_topic("Transfer(address,address,uint256)") + for i in range(total): + amt = 10 + i + tx = contract.functions.transfer(to, amt).build_transaction({"from": _from}) + txreceipt = send_transaction(w3, tx) + assert len(txreceipt.logs) == 1 + expect_log = { + "address": address, + "topics": [ + HexBytes(topic), + HexBytes(b"\x00" * 12 + HexBytes(_from)), + HexBytes(b"\x00" * 12 + HexBytes(to)), + ], + "data": HexBytes(b"\x00" * 31 + HexBytes(amt)), + } + assert expect_log.items() <= txreceipt.logs[0].items() + msgs = [await c.recv_subscription(sub_id) for i in range(total)] + assert len(msgs) == total + await assert_unsubscribe(c, sub_id) + + async def logs_test(c: Client, w3, contract, address): + sub_id = await c.subscribe("logs", {"address": address}) + iterations = 10000 + tx = contract.functions.test(iterations).build_transaction() + raw_transactions = [] + for name, key in KEYS.items(): + if name != "reserve": + signed = sign_transaction(w3, tx, key) + raw_transactions.append(signed.raw_transaction) + send_raw_transactions(w3, raw_transactions) + total = len(raw_transactions) * iterations + msgs = [await c.recv_subscription(sub_id) for i in range(total)] + assert len(msgs) == total + assert all(msg["topics"] == [f"0x{TEST_EVENT_TOPIC.hex()}"] for msg in msgs) + await assert_unsubscribe(c, sub_id) + + async def async_test(): + async with websockets.connect(evm.w3_ws_endpoint()) as ws: + c = Client(ws) + t = asyncio.create_task(c.receive_loop()) + # run three subscribers concurrently + await asyncio.gather(*[subscriber_test(c) for i in range(3)]) + w3 = evm.w3 + erc20 = Contract("TestERC20A") + erc20.deploy(w3) + await transfer_test(c, evm.w3, erc20.contract, erc20.contract.address) + msg = Contract("TestMessageCall") + msg.deploy(w3) + inner = msg.contract.caller.inner() + begin = time.time() + await logs_test(c, evm.w3, msg.contract, inner) + print("msg call time", time.time() - begin) + t.cancel() + try: + await t + except asyncio.CancelledError: + pass + + timeout = 100 + loop.run_until_complete(asyncio.wait_for(async_test(), timeout)) diff --git a/tests/integration_tests/test_tracers.py b/tests/integration_tests/test_tracers.py new file mode 100644 index 000000000..198ad0e72 --- /dev/null +++ b/tests/integration_tests/test_tracers.py @@ -0,0 +1,154 @@ +import itertools +import json +from concurrent.futures import ThreadPoolExecutor, as_completed + +from pystarport.utils import w3_wait_for_new_blocks + +from .expected_constants import ( + EXPECTED_CALLTRACERS, + EXPECTED_CONTRACT_CREATE_TRACER, + EXPECTED_STRUCT_TRACER, +) +from .utils import ( + ADDRS, + Contract, + build_contract, + create_contract_transaction, + derive_new_account, + derive_random_account, + fund_acc, + send_transaction, +) + + +def test_out_of_gas_error(evm): + method = "debug_traceTransaction" + tracer = {"tracer": "callTracer"} + iterations = 1 + acc = derive_random_account() + + def process(w3): + # fund new sender to deploy contract with same address + fund_acc(w3, acc) + msg = Contract("TestMessageCall", acc.key) + msg.deploy(evm.w3) + contract = msg.contract + tx = contract.functions.test(iterations).build_transaction({"gas": 21510}) + tx_hash = send_transaction(w3, tx)["transactionHash"].hex() + tx_hash = f"0x{tx_hash}" + res = [] + call = w3.provider.make_request + resp = call(method, [tx_hash, tracer]) + assert "out of gas" in resp["result"]["error"], resp + res = [json.dumps(resp["result"], sort_keys=True)] + return res + + providers = [evm.w3] + with ThreadPoolExecutor(len(providers)) as exec: + tasks = [exec.submit(process, w3) for w3 in providers] + res = [future.result() for future in as_completed(tasks)] + assert len(res) == len(providers) + assert res[0] == res[-1], res + + +def test_storage_out_of_gas_error(evm): + method = "debug_traceTransaction" + tracer = {"tracer": "callTracer"} + acc = derive_new_account(8) + + def process(w3): + # fund new sender to deploy contract with same address + fund_acc(w3, acc) + tx = create_contract_transaction(w3, "TestMessageCall", key=acc.key) + tx["gas"] = 210000 + tx_hash = send_transaction(w3, tx, key=acc.key)["transactionHash"].hex() + tx_hash = f"0x{tx_hash}" + res = [] + call = w3.provider.make_request + resp = call(method, [tx_hash, tracer]) + msg = "contract creation code storage out of gas" + assert msg in resp["result"]["error"], resp + res = [json.dumps(resp["result"], sort_keys=True)] + return res + + providers = [evm.w3] + with ThreadPoolExecutor(len(providers)) as exec: + tasks = [exec.submit(process, w3) for w3 in providers] + res = [future.result() for future in as_completed(tasks)] + assert len(res) == len(providers) + assert res[0] == res[-1], res + + +def test_trace_transactions_tracers(evm): + method = "debug_traceTransaction" + tracer = {"tracer": "callTracer"} + price = hex(88500000000) + acc = derive_new_account(7) + + def process(w3): + fund_acc(w3, acc) + call = w3.provider.make_request + tx = {"to": ADDRS["signer1"], "value": 100, "gasPrice": price} + tx_hash = send_transaction(w3, tx)["transactionHash"].hex() + tx_hash = f"0x{tx_hash}" + tx_res = call(method, [tx_hash]) + assert tx_res["result"] == EXPECTED_STRUCT_TRACER, "" + tx_res = call(method, [tx_hash, tracer]) + assert tx_res["result"] == EXPECTED_CALLTRACERS, "" + tx_res = call( + method, + [tx_hash, tracer | {"tracerConfig": {"onlyTopCall": True}}], + ) + assert tx_res["result"] == EXPECTED_CALLTRACERS, "" + res = build_contract("TestERC20A") + contract = w3.eth.contract(abi=res["abi"], bytecode=res["bytecode"]) + tx = contract.constructor().build_transaction({"from": acc.address}) + tx_hash = send_transaction(w3, tx, key=acc.key)["transactionHash"].hex() + tx_hash = f"0x{tx_hash}" + w3_wait_for_new_blocks(w3, 1) + tx_res = call(method, [tx_hash, tracer]) + assert tx_res["result"] == EXPECTED_CONTRACT_CREATE_TRACER, "" + + providers = [evm.w3] + with ThreadPoolExecutor(len(providers)) as exec: + tasks = [exec.submit(process, w3) for w3 in providers] + res = [future.result() for future in as_completed(tasks)] + assert len(res) == len(providers) + + +def test_trace_tx(evm): + method = "debug_traceTransaction" + tracer = {"tracer": "callTracer"} + tracers = [ + [], + [tracer], + [tracer | {"tracerConfig": {"onlyTopCall": True}}], + [tracer | {"tracerConfig": {"withLog": True}}], + [tracer | {"tracerConfig": {"diffMode": True}}], + ] + iterations = 1 + acc = derive_random_account() + + def process(w3): + # fund new sender to deploy contract with same address + fund_acc(w3, acc) + msg = Contract("TestMessageCall", acc.key) + msg.deploy(evm.w3) + contract = msg.contract + tx = contract.functions.test(iterations).build_transaction() + tx_hash = send_transaction(w3, tx)["transactionHash"].hex() + tx_hash = f"0x{tx_hash}" + res = [] + call = w3.provider.make_request + with ThreadPoolExecutor(len(tracers)) as exec: + params = [([tx_hash] + cfg) for cfg in tracers] + exec_map = exec.map(call, itertools.repeat(method), params) + res = [json.dumps(resp["result"], sort_keys=True) for resp in exec_map] + return res + + providers = [evm.w3] + with ThreadPoolExecutor(len(providers)) as exec: + tasks = [exec.submit(process, w3) for w3 in providers] + res = [future.result() for future in as_completed(tasks)] + assert len(res) == len(providers) + assert res[0] == res[-1], res diff --git a/tests/integration_tests/utils.py b/tests/integration_tests/utils.py index 16f4f7c38..3ce957c27 100644 --- a/tests/integration_tests/utils.py +++ b/tests/integration_tests/utils.py @@ -1,4 +1,3 @@ -import asyncio import base64 import binascii import configparser @@ -7,16 +6,13 @@ import os import re import secrets -import socket import subprocess import sys import time from collections import defaultdict from concurrent.futures import ThreadPoolExecutor, as_completed -from enum import Enum from itertools import takewhile from pathlib import Path -from urllib.parse import urlparse import bech32 import eth_utils @@ -25,6 +21,7 @@ from dateutil.parser import isoparse from dotenv import load_dotenv from eth_account import Account +from eth_contract.contract import Contract as ContractAsync from eth_contract.create2 import create2_address from eth_contract.deploy_utils import ( ensure_create2_deployed, @@ -37,6 +34,10 @@ from eth_utils import to_checksum_address from hexbytes import HexBytes from pystarport import cluster +from pystarport.utils import ( + wait_for_block_time, + wait_for_new_blocks, +) from web3 import AsyncWeb3 from web3._utils.transactions import fill_nonce, fill_transaction_defaults @@ -57,39 +58,99 @@ KEYS = {name: account.key for name, account in ACCOUNTS.items()} ADDRS = {name: account.address for name, account in ACCOUNTS.items()} -DEFAULT_DENOM = os.getenv("EVM_DENOM", "uom") -DEFAULT_EXTENDED_DENOM = os.getenv("EVM_EXTENDED_DENOM", "aom") +DEFAULT_DENOM = os.getenv("EVM_DENOM", "atest") +DEFAULT_EXTENDED_DENOM = os.getenv("EVM_EXTENDED_DENOM", "atest") CHAIN_ID = os.getenv("CHAIN_ID", "evm-canary-net-1") EVM_CHAIN_ID = int(os.getenv("EVM_CHAIN_ID", 7888)) # the default initial base fee used by integration tests -DEFAULT_GAS_AMT = float(os.getenv("DEFAULT_GAS_AMT", 0.01)) +DEFAULT_GAS_AMT = float(os.getenv("DEFAULT_GAS_AMT", 10000000000)) DEFAULT_GAS_PRICE = f"{DEFAULT_GAS_AMT}{DEFAULT_DENOM}" DEFAULT_GAS = 200000 DEFAULT_FEE = int(DEFAULT_GAS_AMT * DEFAULT_GAS) WEI_PER_ETH = 10**18 # 10^18 wei == 1 ether -WEI_PER_DENOM = int(os.getenv("WEI_PER_DENOM", 10**12)) # 10^12 wei == 1 uom -ADDRESS_PREFIX = os.getenv("ADDRESS_PREFIX", "evm") +WEI_PER_DENOM = int(os.getenv("WEI_PER_DENOM", 1)) # 1 wei == 1 atest +ADDRESS_PREFIX = os.getenv("ADDRESS_PREFIX", "cosmos") CMD = os.getenv("CMD", "evmd") WETH_SALT = 999 WETH_ADDRESS = create2_address(get_initcode(WETH9_ARTIFACT), WETH_SALT) +MockERC20_ARTIFACT = json.loads( + Path(__file__).parent.joinpath("contracts/contracts/MockERC20.json").read_text() +) + + +class AsyncContract: + def __init__(self, name, key=KEYS["community"]): + self.acct = Account.from_key(key) + self.name = name + self.contract = None + self.address = None + self.w3 = None + + async def deploy(self, w3: AsyncWeb3, args=()): + if self.contract: + return self.address + self.w3 = w3 + res = build_contract(self.name) + tx = await create_contract_transaction(w3, res, args, key=self.acct.key) + receipt = await send_transaction_async(w3, self.acct, **tx) + self.contract = ContractAsync(res["abi"]) + self.address = receipt.contractAddress + return self.address + + def _check_deployed(self): + if not self.contract: + raise ValueError("Contract not deployed yet") + + +class AsyncGreeter(AsyncContract): + def __init__(self, key=KEYS["community"]): + super().__init__("Greeter", key) + + async def greet(self): + self._check_deployed() + return await self.contract.fns.greet().call(self.w3, to=self.address) + + async def int_value(self): + self._check_deployed() + return await self.contract.fns.intValue().call(self.w3, to=self.address) + + async def set_greeting(self, message: str): + self._check_deployed() + return await self.contract.fns.setGreeting(message).transact( + self.w3, self.acct, to=self.address + ) + -class BondStatus(Enum): - UNSPECIFIED = "BOND_STATUS_UNSPECIFIED" - UNBONDED = "BOND_STATUS_UNBONDED" - UNBONDING = "BOND_STATUS_UNBONDING" - BONDED = "BOND_STATUS_BONDED" +class AsyncTestRevert(AsyncContract): + def __init__(self, key=KEYS["community"]): + super().__init__("TestRevert", key) - def to_int(self): - mapping = { - BondStatus.UNSPECIFIED: 0, - BondStatus.UNBONDED: 1, - BondStatus.UNBONDING: 2, - BondStatus.BONDED: 3, - } - return mapping[self] + async def transfer(self, value): + self._check_deployed() + return await self.contract.fns.transfer(value).transact( + self.w3, + self.acct, + to=self.address, + gas=100000, # skip estimateGas error + ) + + +class AsyncTestMessageCall(AsyncContract): + def __init__(self, key=KEYS["community"]): + super().__init__("TestMessageCall", key) + + async def test(self, iterations): + self._check_deployed() + return await self.contract.fns.test(iterations).transact( + self.w3, self.acct, to=self.address + ) + + def get_test_data(self, iterations): + self._check_deployed() + return self.contract.fns.test(iterations).data class Contract: @@ -158,152 +219,6 @@ def transfer(self, value): return receipt -def wait_for_fn(name, fn, *, timeout=120, interval=1): - for i in range(int(timeout / interval)): - result = fn() - if result: - return result - time.sleep(interval) - else: - raise TimeoutError(f"wait for {name} timeout") - - -async def wait_for_fn_async(name, fn, *, timeout=120, interval=1): - for i in range(int(timeout / interval)): - result = await fn() - if result: - return result - await asyncio.sleep(interval) - else: - raise TimeoutError(f"wait for {name} timeout") - - -def wait_for_block_time(cli, t): - print("wait for block time", t) - while True: - now = isoparse(get_sync_info(cli.status())["latest_block_time"]) - print("block time now:", now) - if now >= t: - break - time.sleep(0.5) - - -def w3_wait_for_block(w3, height, timeout=120): - for _ in range(timeout * 2): - try: - current_height = w3.eth.block_number - except Exception as e: - print(f"get json-rpc block number failed: {e}", file=sys.stderr) - else: - if current_height >= height: - break - print("current block height", current_height) - time.sleep(0.5) - else: - raise TimeoutError(f"wait for block {height} timeout") - - -async def w3_wait_for_block_async(w3, height, timeout=120): - for _ in range(timeout * 2): - try: - current_height = await w3.eth.block_number - except Exception as e: - print(f"get json-rpc block number failed: {e}", file=sys.stderr) - else: - if current_height >= height: - break - print("current block height", current_height) - await asyncio.sleep(0.1) - else: - raise TimeoutError(f"wait for block {height} timeout") - - -def get_sync_info(s): - return s.get("SyncInfo") or s.get("sync_info") - - -def wait_for_new_blocks(cli, n, sleep=0.5, timeout=120): - cur_height = begin_height = int(get_sync_info(cli.status())["latest_block_height"]) - start_time = time.time() - while cur_height - begin_height < n: - time.sleep(sleep) - cur_height = int(get_sync_info(cli.status())["latest_block_height"]) - if time.time() - start_time > timeout: - raise TimeoutError(f"wait for block {begin_height + n} timeout") - return cur_height - - -def wait_for_block(cli, height, timeout=120): - for i in range(timeout * 2): - try: - status = cli.status() - except AssertionError as e: - print(f"get sync status failed: {e}", file=sys.stderr) - else: - current_height = int(get_sync_info(status)["latest_block_height"]) - print("current block height", current_height) - if current_height >= height: - break - time.sleep(0.5) - else: - raise TimeoutError(f"wait for block {height} timeout") - - -def wait_for_port(port, host="127.0.0.1", timeout=40.0): - print("wait for port", port, "to be available") - start_time = time.perf_counter() - while True: - try: - with socket.create_connection((host, port), timeout=timeout): - break - except OSError as ex: - time.sleep(0.1) - if time.perf_counter() - start_time >= timeout: - raise TimeoutError( - "Waited too long for the port {} on host {} to start accepting " - "connections.".format(port, host) - ) from ex - - -def wait_for_url(url, timeout=40.0): - print("wait for url", url, "to be available") - start_time = time.perf_counter() - while True: - try: - parsed = urlparse(url) - host = parsed.hostname - port = parsed.port - with socket.create_connection((host, int(port or 80)), timeout=timeout): - break - except OSError as ex: - time.sleep(0.1) - if time.perf_counter() - start_time >= timeout: - raise TimeoutError( - "Waited too long for the port {} on host {} to start accepting " - "connections.".format(port, host) - ) from ex - - -def w3_wait_for_new_blocks(w3, n, sleep=0.5): - begin_height = w3.eth.block_number - while True: - time.sleep(sleep) - cur_height = w3.eth.block_number - if cur_height - begin_height >= n: - break - - -async def w3_wait_for_new_blocks_async(w3: AsyncWeb3, n: int, sleep=0.1): - begin_height = await w3.eth.block_number - target = begin_height + n - - while True: - cur_height = await w3.eth.block_number - if cur_height >= target: - break - await asyncio.sleep(sleep) - - def supervisorctl(inipath, *args): return subprocess.check_output( (sys.executable, "-msupervisor.supervisorctl", "-c", inipath, *args), @@ -402,6 +317,8 @@ def build_contract(name, dir="contracts") -> dict: "--no-cbor-metadata", "--base-path", "./contracts", + "--allow-paths", + "../../precompiles", # "$(cat contracts/remappings.txt)", ] with open("contracts/remappings.txt", "r") as f: @@ -426,39 +343,24 @@ async def build_and_deploy_contract_async( name, args=(), key=KEYS["community"], - exp_gas_used=None, dir="contracts", ): res = build_contract(name, dir=dir) - contract = w3.eth.contract(abi=res["abi"], bytecode=res["bytecode"]) - acct = Account.from_key(key) - tx = await contract.constructor(*args).build_transaction({"from": acct.address}) + tx = await create_contract_transaction(w3, res, args, key, dir=dir) txreceipt = await send_transaction_async(w3, Account.from_key(key), **tx) - if exp_gas_used is not None: - assert ( - exp_gas_used == txreceipt.gasUsed - ), f"exp {exp_gas_used}, got {txreceipt.gasUsed}" - address = txreceipt.contractAddress - return w3.eth.contract(address=address, abi=res["abi"]) - - -def create_contract_transaction(w3, name, args=(), key=KEYS["community"]): - """ - create contract transaction - """ - acct = Account.from_key(key) - res = build_contract(name) - contract = w3.eth.contract(abi=res["abi"], bytecode=res["bytecode"]) - tx = contract.constructor(*args).build_transaction({"from": acct.address}) - return tx + return w3.eth.contract(address=txreceipt.contractAddress, abi=res["abi"]) -async def build_deploy_contract_async( - w3: AsyncWeb3, res, args=(), key=KEYS["community"] +def create_contract_transaction( + w3, name_or_res, args=(), key=KEYS["community"], dir="contracts" ): acct = Account.from_key(key) + if isinstance(name_or_res, str): + res = build_contract(name_or_res, dir=dir) + else: + res = name_or_res contract = w3.eth.contract(abi=res["abi"], bytecode=res["bytecode"]) - return await contract.constructor(*args).build_transaction({"from": acct.address}) + return contract.constructor(*args).build_transaction({"from": acct.address}) def eth_to_bech32(addr, prefix=ADDRESS_PREFIX): @@ -516,8 +418,8 @@ def get_balance(cli, name): if "key not found" not in str(e): raise addr = name - uom = cli.balance(addr) - return uom + atest = cli.balance(addr) + return atest def assert_balance(cli, w3, name, evm=False): @@ -527,13 +429,13 @@ def assert_balance(cli, w3, name, evm=False): if "key not found" not in str(e): raise addr = name - uom = get_balance(cli, name) + atest = get_balance(cli, name) wei = w3.eth.get_balance(bech32_to_eth(addr)) - assert uom == wei // WEI_PER_DENOM + assert atest == wei // WEI_PER_DENOM print( f"wei: {wei}, ether: {wei // WEI_PER_ETH}.", ) - return wei if evm else uom + return wei if evm else atest def find_fee(rsp): @@ -556,10 +458,12 @@ def denom_to_erc20_address(denom): return to_checksum_address("0x" + denom_hash[-20:].hex()) -def escrow_address(port, channel): +def escrow_address(port, channel, prefix=ADDRESS_PREFIX): escrow_addr_version = "ics20-1" pre_image = f"{escrow_addr_version}\x00{port}/{channel}" - return eth_to_bech32(hashlib.sha256(pre_image.encode()).digest()[:20].hex()) + return eth_to_bech32( + hashlib.sha256(pre_image.encode()).digest()[:20].hex(), prefix=prefix + ) def ibc_denom_address(denom): @@ -584,116 +488,6 @@ def retry_on_seq_mismatch(fn, *args, max_retries=3, **kwargs): return rsp -def assert_create_tokenfactory_denom(cli, subdenom, is_legacy=False, **kwargs): - # check create tokenfactory denom - rsp = retry_on_seq_mismatch(cli.create_tokenfactory_denom, subdenom, **kwargs) - assert rsp["code"] == 0, rsp["raw_log"] - event = find_log_event_attrs( - rsp["events"], "create_denom", lambda attrs: "creator" in attrs - ) - sender = kwargs.get("_from") - rsp = cli.query_tokenfactory_denoms(sender) - denom = f"factory/{sender}/{subdenom}" - assert denom in rsp.get("denoms"), rsp - expected = {"creator": sender, "new_token_denom": denom} - erc20_address = None - if not is_legacy: - erc20_address = denom_to_erc20_address(denom) - expected["new_token_eth_addr"] = erc20_address - pair = cli.query_erc20_token_pair(denom) - assert pair == { - "erc20_address": erc20_address, - "denom": denom, - "enabled": True, - "contract_owner": "OWNER_MODULE", - } - assert expected.items() <= event.items() - meta = {"denom_units": [{"denom": denom}], "base": denom} - if not is_legacy: - # all missing metadata fields fixed in rc3 - meta["name"] = denom - meta["display"] = denom - meta["symbol"] = denom - assert meta.items() <= cli.query_bank_denom_metadata(denom).items() - _from = None if is_legacy else sender - rsp = cli.query_denom_authority_metadata(denom, _from=_from).get("Admin") - assert rsp == sender, rsp - return denom - - -def assert_mint_tokenfactory_denom(cli, denom, amt, is_legacy=False, **kwargs): - # check mint tokenfactory denom - sender = kwargs.get("_from") - balance = cli.balance(sender, denom) - coin = f"{amt}{denom}" - rsp = retry_on_seq_mismatch(cli.mint_tokenfactory_denom, coin, **kwargs) - assert rsp["code"] == 0, rsp["raw_log"] - if not is_legacy: - event = find_log_event_attrs( - rsp["events"], "tf_mint", lambda attrs: "mint_to_address" in attrs - ) - expected = { - "mint_to_address": sender, - "amount": coin, - } - assert expected.items() <= event.items() - current = cli.balance(sender, denom) - assert current == balance + amt - return current - - -def assert_transfer_tokenfactory_denom(cli, denom, receiver, amt, **kwargs): - # check transfer tokenfactory denom - sender = kwargs.get("_from") - balance = cli.balance(sender, denom) - rsp = cli.transfer(sender, receiver, f"{amt}{denom}") - assert rsp["code"] == 0, rsp["raw_log"] - current = cli.balance(sender, denom) - assert current == balance - amt - return current - - -def assert_burn_tokenfactory_denom(cli, denom, amt, **kwargs): - # check burn tokenfactory denom - sender = kwargs.get("_from") - balance = cli.balance(sender, denom) - coin = f"{amt}{denom}" - rsp = cli.burn_tokenfactory_denom(coin, **kwargs) - assert rsp["code"] == 0, rsp["raw_log"] - event = find_log_event_attrs( - rsp["events"], "tf_burn", lambda attrs: "burn_from_address" in attrs - ) - expected = { - "burn_from_address": sender, - "amount": coin, - } - assert expected.items() <= event.items() - current = cli.balance(sender, denom) - assert current == balance - amt - return current - - -def assert_set_tokenfactory_denom(cli, tmp_path, denom, **kwargs): - sender = kwargs.get("_from") - name = "Dubai" - symbol = "DLD" - meta = { - "description": name, - "denom_units": [{"denom": denom}, {"denom": symbol, "exponent": 6}], - "base": denom, - "display": symbol, - "name": name, - "symbol": symbol, - } - file_meta = Path(tmp_path) / "meta.json" - file_meta.write_text(json.dumps(meta)) - rsp = cli.set_tokenfactory_denom(file_meta, **kwargs) - assert rsp["code"] == 0, rsp["raw_log"] - assert cli.query_bank_denom_metadata(denom) == meta - rsp = cli.query_denom_authority_metadata(denom).get("Admin") - assert rsp == sender, rsp - - def recover_community(cli, tmp_path): return cli.create_account( "community", @@ -764,7 +558,7 @@ def build_batch_tx(w3, cli, txs, key=KEYS["community"]): "auth_info": { "signer_infos": [], "fee": { - "amount": [{"denom": "aom", "amount": str(fee)}], + "amount": [{"denom": "atest", "amount": str(fee)}], "gas_limit": str(gas_limit), "payer": "", "granter": "", @@ -774,9 +568,8 @@ def build_batch_tx(w3, cli, txs, key=KEYS["community"]): }, tx_hashes -def approve_proposal(n, events, event_query_tx=False): +def approve_proposal(n, events, event_query_tx=True, **kwargs): cli = n.cosmos_cli() - # get proposal_id ev = find_log_event_attrs( events, "submit_proposal", lambda attrs: "proposal_id" in attrs @@ -787,8 +580,8 @@ def approve_proposal(n, events, event_query_tx=False): "validator", proposal_id, "yes", - event_query_tx, - gas_prices=f"{80 * DEFAULT_GAS_AMT}{DEFAULT_DENOM}", + event_query_tx=event_query_tx, + **kwargs, ) assert rsp["code"] == 0, rsp["raw_log"] wait_for_new_blocks(cli, 1) @@ -804,7 +597,7 @@ def approve_proposal(n, events, event_query_tx=False): assert proposal["status"] == "PROPOSAL_STATUS_PASSED", proposal -def submit_gov_proposal(evm, tmp_path, messages, **kwargs): +def submit_gov_proposal(evm, tmp_path, messages, event_query_tx=True, **kwargs): proposal = tmp_path / "proposal.json" proposal_src = { "title": "title", @@ -815,11 +608,26 @@ def submit_gov_proposal(evm, tmp_path, messages, **kwargs): proposal.write_text(json.dumps(proposal_src)) rsp = evm.cosmos_cli().submit_gov_proposal(proposal, from_="community", **kwargs) assert rsp["code"] == 0, rsp["raw_log"] - approve_proposal(evm, rsp["events"]) + approve_proposal(evm, rsp["events"], event_query_tx=event_query_tx) print("check params have been updated now") return rsp +def create_periodic_vesting_acct(cli, tmp_path, coin, **kwargs): + start_time = int(time.time()) + periods = tmp_path / "periods.json" + src = { + "start_time": start_time, + "periods": [{"coins": coin, "length_seconds": 2592000}], + } + periods.write_text(json.dumps(src)) + name = f"periodic_vesting{start_time}" + addr = cli.create_account(name)["address"] + rsp = cli.create_periodic_vesting_account(addr, periods, **kwargs) + assert rsp["code"] == 0, rsp["raw_log"] + return addr + + def derive_new_account(n=1, mnemonic="SIGNER1_MNEMONIC"): # derive a new address account_path = f"m/44'/60'/0'/0/{n}" @@ -985,46 +793,6 @@ def address_to_bytes32(addr) -> HexBytes: return HexBytes(addr).rjust(32, b"\x00") -async def assert_tf_flow(w3, receiver, signer1, signer2, tf_erc20_addr): - # signer1 transfer 5tf_erc20 to receiver - transfer_amt = 5 - signer1_balance_bf = await ERC20.fns.balanceOf(signer1).call(w3, to=tf_erc20_addr) - signer2_balance_bf = await ERC20.fns.balanceOf(signer2).call(w3, to=tf_erc20_addr) - receiver_balance_bf = await ERC20.fns.balanceOf(receiver).call(w3, to=tf_erc20_addr) - await ERC20.fns.transfer(receiver, transfer_amt).transact( - w3, signer1, to=tf_erc20_addr, gasPrice=(await w3.eth.gas_price) - ) - signer1_balance = await ERC20.fns.balanceOf(signer1).call(w3, to=tf_erc20_addr) - assert signer1_balance == signer1_balance_bf - transfer_amt - signer1_balance_bf = signer1_balance - - receiver_balance = await ERC20.fns.balanceOf(receiver).call(w3, to=tf_erc20_addr) - assert receiver_balance == receiver_balance_bf + transfer_amt - receiver_balance_bf = receiver_balance - - # signer1 approve 2tf_erc20 to signer2 - approve_amt = 2 - await ERC20.fns.approve(signer2, approve_amt).transact( - w3, signer1, to=tf_erc20_addr, gasPrice=(await w3.eth.gas_price) - ) - allowance = await ERC20.fns.allowance(signer1, signer2).call(w3, to=tf_erc20_addr) - assert allowance == approve_amt - - # transferFrom signer1 to receiver via signer2 with 2tf_erc20 - await ERC20.fns.transferFrom(signer1, receiver, approve_amt).transact( - w3, signer2, to=tf_erc20_addr, gasPrice=(await w3.eth.gas_price) - ) - signer1_balance = await ERC20.fns.balanceOf(signer1).call(w3, to=tf_erc20_addr) - assert signer1_balance == signer1_balance_bf - approve_amt - signer1_balance_bf = signer1_balance - - signer2_balance = await ERC20.fns.balanceOf(signer2).call(w3, to=tf_erc20_addr) - assert signer2_balance == signer2_balance_bf - receiver_balance = await ERC20.fns.balanceOf(receiver).call(w3, to=tf_erc20_addr) - assert receiver_balance == receiver_balance_bf + approve_amt - receiver_balance_bf = receiver_balance - - def edit_app_cfg(cli, i): # Modify the json-rpc addresses to avoid conflict cluster.edit_app_cfg( diff --git a/tests/nix/sources.json b/tests/nix/sources.json index 8327ef635..0956af501 100644 --- a/tests/nix/sources.json +++ b/tests/nix/sources.json @@ -46,5 +46,30 @@ "type": "tarball", "url": "https://github.com/nix-community/poetry2nix/archive/d90f9db68a4bda31c346be16dfd8d3263be4547e.tar.gz", "url_template": "https://github.com///archive/.tar.gz" + }, + "hermes": { + "branch": "v1.13.2", + "description": "Rust implementation of an Inter-Blockchain Communication (IBC) relayer", + "homepage": "", + "owner": "allthatjazzleo", + "repo": "hermes", + "rev": "96035808651ae542e6a5db465eeb364c75351f93", + "sha256": "1kxzwb8wi87xcjw1p22wadqwifr1n0v3gl21lghivig8yhg8ya0c", + "type": "tarball", + "url": "https://github.com/allthatjazzleo/hermes/archive/96035808651ae542e6a5db465eeb364c75351f93.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "dapptools": { + "branch": "master", + "description": "Dapp, Seth, Hevm, and more", + "homepage": "https://dapp.tools", + "owner": "dapphub", + "repo": "dapptools", + "rev": "a782a9dfcbf87756170c975c30e83339a99194b5", + "sha256": "sha256:0fsp4pvip77qjb3yciz2a3224ir8wvbb1snc851fbgmf34q7dqfi", + "type": "tarball", + "url": "https://github.com/dapphub/dapptools/archive/a782a9dfcbf87756170c975c30e83339a99194b5.tar.gz", + "url_template": "https://github.com///archive/.tar.gz", + "version": "hevm/0.49.0" } } \ No newline at end of file diff --git a/tests/nix/testenv.nix b/tests/nix/testenv.nix index 1604af435..659d95c9b 100644 --- a/tests/nix/testenv.nix +++ b/tests/nix/testenv.nix @@ -2,10 +2,17 @@ poetry2nix, lib, python3, + rustc, + cargo, + maturin, + cacert, + openssl, + pkg-config, }: poetry2nix.mkPoetryEnv { projectDir = ../integration_tests; python = python3; + extraPackages = ps: [ ps.setuptools-rust ]; overrides = poetry2nix.overrides.withDefaults ( self: super: let @@ -27,13 +34,63 @@ poetry2nix.mkPoetryEnv { pyunormalize = [ "setuptools" ]; typing-inspection = [ "hatchling" ]; eth-bloom = [ "setuptools" ]; + cryptography = [ "setuptools" "setuptools-rust" ]; + pycryptodome = [ "setuptools" "setuptools-rust" ]; + bcrypt = [ "setuptools" "setuptools-rust" ]; + lxml = [ "setuptools" "setuptools-rust" ]; + pyrevm = [ "setuptools" "setuptools-rust" ]; + }; + packageOverrides = { + maturin = super.maturin.override { preferWheel = true; }; + pyrevm = super.pyrevm.overridePythonAttrs (old: { + nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ + maturin + rustc + cargo + pkg-config + self.setuptools-rust + ]; + buildInputs = (old.buildInputs or [ ]) ++ [ + openssl + ]; + preBuild = '' + export SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt" + export CARGO_NET_GIT_FETCH_WITH_CLI=true + export CARGO_HTTP_CAINFO="${cacert}/etc/ssl/certs/ca-bundle.crt" + export REQUESTS_CA_BUNDLE="${cacert}/etc/ssl/certs/ca-bundle.crt" + export CURL_CA_BUNDLE="${cacert}/etc/ssl/certs/ca-bundle.crt" + + # Set up writable home directory for cargo + export HOME=$(mktemp -d) + mkdir -p $HOME/.cargo + + # Create cargo config to use git cli and set proper registry + cat > $HOME/.cargo/config.toml << EOF + [net] + git-fetch-with-cli = true + + [http] + cainfo = "${cacert}/etc/ssl/certs/ca-bundle.crt" + + [registry] + default = "crates-io" + + [registries.crates-io] + index = "https://github.com/rust-lang/crates.io-index" + EOF + ''; + }); }; in - lib.mapAttrs ( + (lib.mapAttrs ( attr: systems: super.${attr}.overridePythonAttrs (old: { - nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ map (a: self.${a}) systems; + nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ map (a: self.${a}) systems + ++ lib.optionals (builtins.elem "setuptools-rust" systems) [ + rustc + cargo + ]; }) - ) buildSystems + ) buildSystems) // packageOverrides ); } diff --git a/tests/pytest.ini b/tests/pytest.ini new file mode 100644 index 000000000..0524c7d76 --- /dev/null +++ b/tests/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +addopts = --ignore=contracts +python_files = integration_tests/*.py +asyncio_mode = auto \ No newline at end of file From 13a908b0fbb4ccc1e0a2e385a38120f0763a2a53 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 6 Nov 2025 16:49:19 +0800 Subject: [PATCH 06/22] ledger_zemu --- tests/integration_tests/configs/hw.jsonnet | 12 ++++ tests/integration_tests/test_ledger.py | 69 ++++++++++++++++++++++ tests/nix/evm/default.nix | 2 +- 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 tests/integration_tests/configs/hw.jsonnet create mode 100644 tests/integration_tests/test_ledger.py diff --git a/tests/integration_tests/configs/hw.jsonnet b/tests/integration_tests/configs/hw.jsonnet new file mode 100644 index 000000000..184c16ec7 --- /dev/null +++ b/tests/integration_tests/configs/hw.jsonnet @@ -0,0 +1,12 @@ +local config = import 'default.jsonnet'; +local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; + +config { + 'evm-canary-net-1'+: { + hw_account: { + name: 'hw', + coins: '8000000000000000000' + chain.evm_denom, + 'coin-type': 118, + }, + }, +} diff --git a/tests/integration_tests/test_ledger.py b/tests/integration_tests/test_ledger.py new file mode 100644 index 000000000..26fa631fe --- /dev/null +++ b/tests/integration_tests/test_ledger.py @@ -0,0 +1,69 @@ +from pathlib import Path + +import pytest +from pystarport.ledger import Ledger + +from .network import setup_custom_evm +from .utils import DEFAULT_DENOM, WEI_PER_DENOM, find_fee + +pytestmark = pytest.mark.slow + + +@pytest.fixture(scope="module") +def custom_evm(request, tmp_path_factory): + chain = request.config.getoption("chain_config") + path = tmp_path_factory.mktemp("hw") + ledger = Ledger() + try: + ledger.start() + assert ledger.is_running(), "failed to start Ledger simulator" + + yield from setup_custom_evm( + path, + 27300, + Path(__file__).parent / "configs/hw.jsonnet", + chain=chain, + ) + finally: + try: + ledger.stop() + except Exception as e: + print(f"error during ledger cleanup: {e}") + + +def test_ledger(custom_evm): + cli = custom_evm.cosmos_cli() + name = "hw" + hw = cli.address(name) + community = cli.address("community") + amt1 = 8_000_000_000_000_000_000 // WEI_PER_DENOM + assert cli.balance(hw) == amt1 + community_balance = cli.balance(community) + amt2 = 4_000_000_000_000_000_000 // WEI_PER_DENOM + rsp = cli.transfer( + hw, community, f"{amt2}{DEFAULT_DENOM}", ledger=True, sign_mode="amino-json" + ) + print("mm-rsp", rsp) + assert rsp["code"] == 0, rsp["raw_log"] + assert cli.balance(hw) == amt2 - find_fee(rsp) + assert cli.balance(community) == community_balance + amt2 + + cli.delete_account(name) + + def check_account(name): + res = cli.create_account(name, ledger=True, coin_type=118, key_type="secp256k1") + assert "address" in res + assert "pubkey" in res + assert res["type"] == "ledger" + cli.delete_account(name) + + names = [ + "abc 1", + r"\&a\)bcd*^", + "钱對중ガジÑá", + "this_is_a_very_long_long_long_long_long_long_long_long_long_long_long_long_name", # noqa: E501 + "1 abc &abcd*^ 钱對중ガジÑá long_long_long_long_long_long_long_long_long_long_long_long_name", # noqa: E501 + ] + + for name in names: + check_account(name) diff --git a/tests/nix/evm/default.nix b/tests/nix/evm/default.nix index 0d647911d..9eed8ca95 100644 --- a/tests/nix/evm/default.nix +++ b/tests/nix/evm/default.nix @@ -23,12 +23,12 @@ let tags = [ "ledger" + "ledger_zemu" "netgo" "osusergo" "pebbledb" ] ++ lib.optionals nativeByteOrder [ "nativebyteorder" ] - ++ lib.optionals buildStdenv.isDarwin [ "static_wasm" ] ++ lib.optionals buildStdenv.isLinux [ "muslc" ]; ldflags = From 1f298c46f3ca17fac83d174db156cbe9e7b9bbca Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 6 Nov 2025 18:11:38 +0800 Subject: [PATCH 07/22] try ci --- .github/workflows/tests-e2e-nix.yml | 54 +++++++++++++++++++ Makefile | 4 ++ .../configs/fee-history.jsonnet | 2 +- .../configs/min_gas_price.jsonnet | 4 +- .../integration_tests/configs/staking.jsonnet | 3 +- tests/integration_tests/test_ledger.py | 1 - 6 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/tests-e2e-nix.yml diff --git a/.github/workflows/tests-e2e-nix.yml b/.github/workflows/tests-e2e-nix.yml new file mode 100644 index 000000000..23a07af64 --- /dev/null +++ b/.github/workflows/tests-e2e-nix.yml @@ -0,0 +1,54 @@ +name: E2E Nix Tests +on: + push: + branches: + - main + - release/** + pull_request: + branches: + - main + - release/** + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + integration_tests: + runs-on: ubuntu-latest-x64-xlarge + timeout-minutes: 240 + strategy: + matrix: + tests: [all] + env: + TESTS_TO_RUN: ${{ matrix.tests }} + steps: + - name: Create more disk space + run: sudo rm -rf /usr/share/dotnet && sudo rm -rf /opt/ghc && sudo rm -rf "/usr/local/share/boost" && sudo rm -rf "$AGENT_TOOLSDIRECTORY" + - uses: actions/checkout@v3 + with: + submodules: recursive + fetch-depth: 1 + - id: changed-files + uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5 + with: + files: | + docs + *.md + **/*.md + - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 + with: + nix_path: nixpkgs=channel:nixos-24.11 + if: steps.changed-files.outputs.only_changed == 'false' + - name: Run integration tests + if: steps.changed-files.outputs.only_changed == 'false' + run: make test-e2e-nix + - name: 'Tar debug files' + if: failure() + run: tar cfz debug_files.tar.gz -C "${TMPDIR-/tmp}/pytest-of-runner" . + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: debug-files + path: debug_files.tar.gz + if-no-files-found: ignore diff --git a/Makefile b/Makefile index e5183b399..de4246d5f 100644 --- a/Makefile +++ b/Makefile @@ -205,6 +205,10 @@ test-solidity: @echo "Beginning solidity tests..." ./scripts/run-solidity-tests.sh +test-e2e-nix: + @bash ./tests/scripts/restore_envs.sh + @nix-shell ./tests/integration_tests/shell.nix --run "CHAIN_CONFIG=$(CHAIN_CONFIG) ./tests/scripts/run-integration-tests.sh" + .PHONY: run-tests test test-all $(TEST_TARGETS) benchmark: diff --git a/tests/integration_tests/configs/fee-history.jsonnet b/tests/integration_tests/configs/fee-history.jsonnet index fb164bdd9..3c5e7cbd6 100644 --- a/tests/integration_tests/configs/fee-history.jsonnet +++ b/tests/integration_tests/configs/fee-history.jsonnet @@ -8,7 +8,7 @@ config { params+: { elasticity_multiplier: 3, base_fee_change_denominator: 100000000, - // min_gas_price: '0.000000000000000000', # TODO: remove after basefee fix + min_gas_price: '0.000000000000000000', # TODO: remove after basefee fix }, }, }, diff --git a/tests/integration_tests/configs/min_gas_price.jsonnet b/tests/integration_tests/configs/min_gas_price.jsonnet index ad731449f..3a3c0ea0c 100644 --- a/tests/integration_tests/configs/min_gas_price.jsonnet +++ b/tests/integration_tests/configs/min_gas_price.jsonnet @@ -20,8 +20,8 @@ config { params+: { base_fee_change_denominator: '3', elasticity_multiplier: '4', - base_fee: gas_price, - min_gas_price: gas_price, + base_fee: gas_price + '', + min_gas_price: gas_price + '', }, }, }, diff --git a/tests/integration_tests/configs/staking.jsonnet b/tests/integration_tests/configs/staking.jsonnet index 1403fc735..53a0791e7 100644 --- a/tests/integration_tests/configs/staking.jsonnet +++ b/tests/integration_tests/configs/staking.jsonnet @@ -1,5 +1,6 @@ local config = import 'default.jsonnet'; local chain = (import 'chains.jsonnet')[std.extVar('CHAIN_CONFIG')]; +local gas_price = 1000000000; config { 'evm-canary-net-1'+: { @@ -7,7 +8,7 @@ config { 'coin-type': 60, coins: '100000000000000000000' + chain.evm_denom, staked: '10000000000000000000' + chain.evm_denom, - gas_prices: '0.01' + chain.evm_denom, + gas_prices: gas_price + chain.evm_denom, min_self_delegation: 1000000000000000000, mnemonic: '${VALIDATOR4_MNEMONIC}', }], diff --git a/tests/integration_tests/test_ledger.py b/tests/integration_tests/test_ledger.py index 26fa631fe..4c913be52 100644 --- a/tests/integration_tests/test_ledger.py +++ b/tests/integration_tests/test_ledger.py @@ -43,7 +43,6 @@ def test_ledger(custom_evm): rsp = cli.transfer( hw, community, f"{amt2}{DEFAULT_DENOM}", ledger=True, sign_mode="amino-json" ) - print("mm-rsp", rsp) assert rsp["code"] == 0, rsp["raw_log"] assert cli.balance(hw) == amt2 - find_fee(rsp) assert cli.balance(community) == community_balance + amt2 From dc4fd25b063fd2099fdabad7d896bca7ad61765d Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 6 Nov 2025 18:19:45 +0800 Subject: [PATCH 08/22] align --- .github/workflows/tests-e2e-nix.yml | 2 +- tests/integration_tests/test_staking.py | 2 +- tests/integration_tests/test_staking_precompile.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests-e2e-nix.yml b/.github/workflows/tests-e2e-nix.yml index 23a07af64..bfbe2925e 100644 --- a/.github/workflows/tests-e2e-nix.yml +++ b/.github/workflows/tests-e2e-nix.yml @@ -15,7 +15,7 @@ concurrency: jobs: integration_tests: - runs-on: ubuntu-latest-x64-xlarge + runs-on: ubuntu-latest timeout-minutes: 240 strategy: matrix: diff --git a/tests/integration_tests/test_staking.py b/tests/integration_tests/test_staking.py index c9a64b24e..9662e2e6d 100644 --- a/tests/integration_tests/test_staking.py +++ b/tests/integration_tests/test_staking.py @@ -75,7 +75,7 @@ def test_staking_unbond(evm): data = find_log_event_attrs( rsp["events"], "unbond", lambda attrs: "completion_time" in attrs ) - wait_for_block_time(cli, isoparse(data["completion_time"]) + timedelta(seconds=1)) + wait_for_block_time(cli, isoparse(data["completion_time"]) + timedelta(seconds=5)) assert cli.balance(signer1) == balance_bf - (sum(amounts) - unbonded_amt) - fee diff --git a/tests/integration_tests/test_staking_precompile.py b/tests/integration_tests/test_staking_precompile.py index f2d56c38c..3678e7600 100644 --- a/tests/integration_tests/test_staking_precompile.py +++ b/tests/integration_tests/test_staking_precompile.py @@ -137,7 +137,7 @@ async def test_staking_unbond(evm): data = find_log_event_attrs( rsp["events"], "unbond", lambda attrs: "completion_time" in attrs ) - wait_for_block_time(cli, isoparse(data["completion_time"]) + timedelta(seconds=1)) + wait_for_block_time(cli, isoparse(data["completion_time"]) + timedelta(seconds=5)) balance = await w3.eth.get_balance(acct.address) assert balance == balance_bf - (sum(amounts) - unbonded_amt) * WEI_PER_DENOM - fee From 9fee4ed4c42bbc4c0227e9dcd700cb396039171f Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 6 Nov 2025 19:03:07 +0800 Subject: [PATCH 09/22] access-tokens --- .github/workflows/tests-e2e-nix.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/tests-e2e-nix.yml b/.github/workflows/tests-e2e-nix.yml index bfbe2925e..29b548c23 100644 --- a/.github/workflows/tests-e2e-nix.yml +++ b/.github/workflows/tests-e2e-nix.yml @@ -39,6 +39,9 @@ jobs: - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 with: nix_path: nixpkgs=channel:nixos-24.11 + extra_nix_config: | + access-tokens = github.com=${{ secrets.NIX_GH_TOKEN || github.token }} + sandbox = false if: steps.changed-files.outputs.only_changed == 'false' - name: Run integration tests if: steps.changed-files.outputs.only_changed == 'false' From f5f7325007447239d44f79c071b056e22c83f931 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 6 Nov 2025 21:31:34 +0800 Subject: [PATCH 10/22] add hermes --- tests/integration_tests/shell.nix | 1 + tests/nix/default.nix | 1 + tests/nix/hermes.nix | 49 +++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 tests/nix/hermes.nix diff --git a/tests/integration_tests/shell.nix b/tests/integration_tests/shell.nix index c0a1543b9..2b5e80773 100644 --- a/tests/integration_tests/shell.nix +++ b/tests/integration_tests/shell.nix @@ -8,6 +8,7 @@ pkgs.mkShell { pkgs.test-env pkgs.poetry pkgs.solc + pkgs.hermes pkgs.evmd ]; shellHook = '' diff --git a/tests/nix/default.nix b/tests/nix/default.nix index ebf262b51..f83906ad4 100644 --- a/tests/nix/default.nix +++ b/tests/nix/default.nix @@ -9,6 +9,7 @@ import sources.nixpkgs { flake-compat = import sources.flake-compat; }) (import "${sources.poetry2nix}/overlay.nix") + (_: pkgs: { hermes = pkgs.callPackage ./hermes.nix { src = sources.hermes; };}) (_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; }) (_: pkgs: { evmd = pkgs.callPackage ./evm/default.nix { }; }) (_: pkgs: { diff --git a/tests/nix/hermes.nix b/tests/nix/hermes.nix new file mode 100644 index 000000000..6bedd745e --- /dev/null +++ b/tests/nix/hermes.nix @@ -0,0 +1,49 @@ +{ + src, + lib, + stdenv, + darwin, + rustPackages_1_83, + symlinkJoin, + openssl, + pkg-config, + protobuf, + clang, + llvmPackages, +}: + +rustPackages_1_83.rustPlatform.buildRustPackage rec { + name = "hermes"; + inherit src; + cargoBuildFlags = [ "-p" "ibc-relayer-cli" ]; + nativeBuildInputs = [ + pkg-config + protobuf + clang + ]; + buildInputs = [ + openssl + llvmPackages.libclang.lib + ] ++ lib.optionals stdenv.isDarwin [ + darwin.apple_sdk.frameworks.Security + darwin.libiconv + darwin.apple_sdk.frameworks.SystemConfiguration + ]; + cargoLock = { + lockFile = "${src}/Cargo.lock"; + }; + doCheck = false; + env = { + RUSTFLAGS = "--cfg ossl111 --cfg ossl110 --cfg ossl101"; + OPENSSL_NO_VENDOR = "1"; + PROTOC = "${protobuf}/bin/protoc"; + LIBCLANG_PATH = "${llvmPackages.libclang.lib}/lib"; + OPENSSL_DIR = symlinkJoin { + name = "openssl"; + paths = with openssl; [ + out + dev + ]; + }; + }; +} \ No newline at end of file From e53c5d0f1e93e1b6cd94d8ebd81bb1dd5fe005d3 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 6 Nov 2025 21:39:13 +0800 Subject: [PATCH 11/22] wait lfs fix for hermes --- tests/integration_tests/shell.nix | 1 - tests/integration_tests/test_ibc.py | 3 ++ tests/nix/default.nix | 1 - tests/nix/hermes.nix | 49 ----------------------------- 4 files changed, 3 insertions(+), 51 deletions(-) delete mode 100644 tests/nix/hermes.nix diff --git a/tests/integration_tests/shell.nix b/tests/integration_tests/shell.nix index 2b5e80773..c0a1543b9 100644 --- a/tests/integration_tests/shell.nix +++ b/tests/integration_tests/shell.nix @@ -8,7 +8,6 @@ pkgs.mkShell { pkgs.test-env pkgs.poetry pkgs.solc - pkgs.hermes pkgs.evmd ]; shellHook = '' diff --git a/tests/integration_tests/test_ibc.py b/tests/integration_tests/test_ibc.py index 9a88790cd..924e36387 100644 --- a/tests/integration_tests/test_ibc.py +++ b/tests/integration_tests/test_ibc.py @@ -23,6 +23,9 @@ ) pytestmark = pytest.mark.asyncio +pytest.skip( + "https://github.com/penumbra-zone/penumbra/issues/5270", allow_module_level=True +) @pytest.fixture(scope="module") diff --git a/tests/nix/default.nix b/tests/nix/default.nix index f83906ad4..ebf262b51 100644 --- a/tests/nix/default.nix +++ b/tests/nix/default.nix @@ -9,7 +9,6 @@ import sources.nixpkgs { flake-compat = import sources.flake-compat; }) (import "${sources.poetry2nix}/overlay.nix") - (_: pkgs: { hermes = pkgs.callPackage ./hermes.nix { src = sources.hermes; };}) (_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; }) (_: pkgs: { evmd = pkgs.callPackage ./evm/default.nix { }; }) (_: pkgs: { diff --git a/tests/nix/hermes.nix b/tests/nix/hermes.nix deleted file mode 100644 index 6bedd745e..000000000 --- a/tests/nix/hermes.nix +++ /dev/null @@ -1,49 +0,0 @@ -{ - src, - lib, - stdenv, - darwin, - rustPackages_1_83, - symlinkJoin, - openssl, - pkg-config, - protobuf, - clang, - llvmPackages, -}: - -rustPackages_1_83.rustPlatform.buildRustPackage rec { - name = "hermes"; - inherit src; - cargoBuildFlags = [ "-p" "ibc-relayer-cli" ]; - nativeBuildInputs = [ - pkg-config - protobuf - clang - ]; - buildInputs = [ - openssl - llvmPackages.libclang.lib - ] ++ lib.optionals stdenv.isDarwin [ - darwin.apple_sdk.frameworks.Security - darwin.libiconv - darwin.apple_sdk.frameworks.SystemConfiguration - ]; - cargoLock = { - lockFile = "${src}/Cargo.lock"; - }; - doCheck = false; - env = { - RUSTFLAGS = "--cfg ossl111 --cfg ossl110 --cfg ossl101"; - OPENSSL_NO_VENDOR = "1"; - PROTOC = "${protobuf}/bin/protoc"; - LIBCLANG_PATH = "${llvmPackages.libclang.lib}/lib"; - OPENSSL_DIR = symlinkJoin { - name = "openssl"; - paths = with openssl; [ - out - dev - ]; - }; - }; -} \ No newline at end of file From 839f11ec0cee78dc20552c0bcdcc64e7836057b6 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 7 Nov 2025 10:21:25 +0800 Subject: [PATCH 12/22] optional penumbra --- tests/integration_tests/shell.nix | 1 + tests/integration_tests/test_ibc.py | 3 -- tests/nix/default.nix | 1 + tests/nix/hermes.nix | 49 +++++++++++++++++++++++++++++ tests/nix/sources.json | 10 +++--- 5 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 tests/nix/hermes.nix diff --git a/tests/integration_tests/shell.nix b/tests/integration_tests/shell.nix index c0a1543b9..2b5e80773 100644 --- a/tests/integration_tests/shell.nix +++ b/tests/integration_tests/shell.nix @@ -8,6 +8,7 @@ pkgs.mkShell { pkgs.test-env pkgs.poetry pkgs.solc + pkgs.hermes pkgs.evmd ]; shellHook = '' diff --git a/tests/integration_tests/test_ibc.py b/tests/integration_tests/test_ibc.py index 924e36387..9a88790cd 100644 --- a/tests/integration_tests/test_ibc.py +++ b/tests/integration_tests/test_ibc.py @@ -23,9 +23,6 @@ ) pytestmark = pytest.mark.asyncio -pytest.skip( - "https://github.com/penumbra-zone/penumbra/issues/5270", allow_module_level=True -) @pytest.fixture(scope="module") diff --git a/tests/nix/default.nix b/tests/nix/default.nix index ebf262b51..f83906ad4 100644 --- a/tests/nix/default.nix +++ b/tests/nix/default.nix @@ -9,6 +9,7 @@ import sources.nixpkgs { flake-compat = import sources.flake-compat; }) (import "${sources.poetry2nix}/overlay.nix") + (_: pkgs: { hermes = pkgs.callPackage ./hermes.nix { src = sources.hermes; };}) (_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; }) (_: pkgs: { evmd = pkgs.callPackage ./evm/default.nix { }; }) (_: pkgs: { diff --git a/tests/nix/hermes.nix b/tests/nix/hermes.nix new file mode 100644 index 000000000..6bedd745e --- /dev/null +++ b/tests/nix/hermes.nix @@ -0,0 +1,49 @@ +{ + src, + lib, + stdenv, + darwin, + rustPackages_1_83, + symlinkJoin, + openssl, + pkg-config, + protobuf, + clang, + llvmPackages, +}: + +rustPackages_1_83.rustPlatform.buildRustPackage rec { + name = "hermes"; + inherit src; + cargoBuildFlags = [ "-p" "ibc-relayer-cli" ]; + nativeBuildInputs = [ + pkg-config + protobuf + clang + ]; + buildInputs = [ + openssl + llvmPackages.libclang.lib + ] ++ lib.optionals stdenv.isDarwin [ + darwin.apple_sdk.frameworks.Security + darwin.libiconv + darwin.apple_sdk.frameworks.SystemConfiguration + ]; + cargoLock = { + lockFile = "${src}/Cargo.lock"; + }; + doCheck = false; + env = { + RUSTFLAGS = "--cfg ossl111 --cfg ossl110 --cfg ossl101"; + OPENSSL_NO_VENDOR = "1"; + PROTOC = "${protobuf}/bin/protoc"; + LIBCLANG_PATH = "${llvmPackages.libclang.lib}/lib"; + OPENSSL_DIR = symlinkJoin { + name = "openssl"; + paths = with openssl; [ + out + dev + ]; + }; + }; +} \ No newline at end of file diff --git a/tests/nix/sources.json b/tests/nix/sources.json index 0956af501..64c472ccc 100644 --- a/tests/nix/sources.json +++ b/tests/nix/sources.json @@ -51,12 +51,12 @@ "branch": "v1.13.2", "description": "Rust implementation of an Inter-Blockchain Communication (IBC) relayer", "homepage": "", - "owner": "allthatjazzleo", - "repo": "hermes", - "rev": "96035808651ae542e6a5db465eeb364c75351f93", - "sha256": "1kxzwb8wi87xcjw1p22wadqwifr1n0v3gl21lghivig8yhg8ya0c", + "owner": "mmsqe", + "repo": "ibc-rs", + "rev": "ae80ab348952840696e6c9a0c7096d2de11ea579", + "sha256": "1q9a1lx8bqfnycmacwy39wga9n3bzb6h29kqqj5l6jbk0y0vf4yj", "type": "tarball", - "url": "https://github.com/allthatjazzleo/hermes/archive/96035808651ae542e6a5db465eeb364c75351f93.tar.gz", + "url": "https://github.com/mmsqe/ibc-rs/archive/ae80ab348952840696e6c9a0c7096d2de11ea579.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "dapptools": { From b4df5333e75c51e15ff0389c6edf39273bcc83ad Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 7 Nov 2025 10:22:47 +0800 Subject: [PATCH 13/22] resolve --- tests/integration_tests/test_basic.py | 1 - tests/integration_tests/test_priority.py | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/integration_tests/test_basic.py b/tests/integration_tests/test_basic.py index 297064773..a33e97028 100644 --- a/tests/integration_tests/test_basic.py +++ b/tests/integration_tests/test_basic.py @@ -150,7 +150,6 @@ async def test_minimal_gas_price(evm): @pytest.mark.asyncio -@pytest.mark.skip(reason="https://github.com/cosmos/evm/pull/806") async def test_transaction(evm): w3 = evm.async_w3 gas_price = await w3.eth.gas_price diff --git a/tests/integration_tests/test_priority.py b/tests/integration_tests/test_priority.py index 38a1c1851..21f849d0a 100644 --- a/tests/integration_tests/test_priority.py +++ b/tests/integration_tests/test_priority.py @@ -40,7 +40,6 @@ def tx_priority(tx, base_fee): return (tx["gasPrice"] - base_fee) // PRIORITY_REDUCTION -@pytest.mark.skip(reason="https://github.com/cosmos/evm/pull/806") def test_priority(evm): """ test priorities of different tx types From 1f3ece64b7a6ed1ba81758b7bdaffacb3f615071 Mon Sep 17 00:00:00 2001 From: yihuang Date: Fri, 14 Nov 2025 11:41:32 +0800 Subject: [PATCH 14/22] nixify evmd --- default.nix | 43 ++++++++++++++++ flake.lock | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 53 +++++++++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 default.nix create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/default.nix b/default.nix new file mode 100644 index 000000000..fec1ecc33 --- /dev/null +++ b/default.nix @@ -0,0 +1,43 @@ +{ + lib, + stdenv, + buildGo125Module, + rev ? "dirty", +}: +buildGo125Module rec { + version = "v0.5.0"; + pname = "evmd"; + tags = [ + "ledger" + "ledger_zemu" + "netgo" # pure go dns resolver + "osusergo" # pure go user/group lookup + "pebbledb" + ]; + ldflags = [ + "-X github.com/cosmos/cosmos-sdk/version.Name=evmd" + "-X github.com/cosmos/cosmos-sdk/version.AppName=${pname}" + "-X github.com/cosmos/cosmos-sdk/version.Version=${version}" + "-X github.com/cosmos/cosmos-sdk/version.BuildTags=${lib.concatStringsSep "," tags}" + "-X github.com/cosmos/cosmos-sdk/version.Commit=${rev}" + ]; + + src = lib.cleanSource ./.; + vendorHash = "sha256-+L4nKIKHV1bos9Trr50/kG69hR8iNL6MXLi9mun5iXQ="; + proxyVendor = true; + env = { + CGO_ENABLED = "1"; + }; + + sourceRoot = "source/evmd"; + subPackages = [ "cmd/evmd" ]; + + doCheck = false; + meta = with lib; { + description = "An EVM compatible framework for blockchain development with the Cosmos SDK"; + homepage = "https://github.com/cosmos/evm"; + license = licenses.asl20; + mainProgram = "evmd" + stdenv.hostPlatform.extensions.executable; + platforms = platforms.all; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..c657ab3e0 --- /dev/null +++ b/flake.lock @@ -0,0 +1,145 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1729742964, + "narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "e04df33f62cdcf93d73e9a04142464753a16db67", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1762943920, + "narHash": "sha256-ITeH8GBpQTw9457ICZBddQEBjlXMmilML067q0e6vqY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "91c9a64ce2a84e648d0cf9671274bb9c2fb9ba60", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems_2", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1743690424, + "narHash": "sha256-cX98bUuKuihOaRp8dNV1Mq7u6/CQZWTPth2IJPATBXc=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "ce2369db77f45688172384bbeb962bc6c2ea6f94", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "poetry2nix": "poetry2nix" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1730120726, + "narHash": "sha256-LqHYIxMrl/1p3/kvm2ir925tZ8DkI0KA10djk8wecSk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "9ef337e492a5555d8e17a51c911ff1f02635be15", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..05849854b --- /dev/null +++ b/flake.nix @@ -0,0 +1,53 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + poetry2nix = { + url = "github:nix-community/poetry2nix"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.flake-utils.follows = "flake-utils"; + }; + }; + + outputs = + { + self, + nixpkgs, + flake-utils, + poetry2nix, + }: + let + rev = self.shortRev or "dirty"; + in + (flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { + inherit system; + overlays = self.overlays.default; + config = { }; + }; + in + { + legacyPackages = pkgs; + packages.default = pkgs.evmd; + devShells = { + default = pkgs.mkShell { + buildInputs = [ + pkgs.evmd.go + pkgs.nixfmt-rfc-style + pkgs.solc + ]; + }; + }; + } + )) + // { + overlays.default = [ + poetry2nix.overlays.default + (final: super: { + evmd = final.callPackage ./. { inherit rev; }; + }) + ]; + }; +} From 65dd19fdf067784b9e7b8fbc4104f17d7e7aecb7 Mon Sep 17 00:00:00 2001 From: yihuang Date: Fri, 14 Nov 2025 12:03:27 +0800 Subject: [PATCH 15/22] transform to uv --- flake.nix | 2 + tests/integration_tests/pyproject.toml | 59 ++++++++++++++------------ 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/flake.nix b/flake.nix index 05849854b..1f4bb1466 100644 --- a/flake.nix +++ b/flake.nix @@ -37,6 +37,8 @@ pkgs.evmd.go pkgs.nixfmt-rfc-style pkgs.solc + pkgs.python312 + pkgs.uv ]; }; }; diff --git a/tests/integration_tests/pyproject.toml b/tests/integration_tests/pyproject.toml index ef071f26c..34dcea825 100644 --- a/tests/integration_tests/pyproject.toml +++ b/tests/integration_tests/pyproject.toml @@ -1,38 +1,41 @@ -[tool.poetry] +[project] name = "integration-tests" version = "0.1.0" description = "" -authors = ["Your Name "] readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "pytest >= 8.3.4", + "pystarport >= 0.2.5", + "pytest-github-actions-annotate-failures >= 0.3.0", + "flake8-black >= 0.3.6", + "flake8-isort >= 6.1.2", + "pyunormalize >= 16.0.0", + "cprotobuf >= 0.1.11", + "web3 >= 7.3.0", + "eth-bloom >= 3.0", + "flaky >= 3.8.1", + "pytest-asyncio >= 1.3.0", + "eth-contract >= 0.3.0", + "py-ecc >= 8.0.0", + "pyrevm >= 0.3.3", +] -[tool.poetry.dependencies] -python = "^3.12" -pytest = "^8.3.4" +[dependency-groups] +dev=[ + "attrs >= 24.2.0", + "referencing >= v0.35.1", + "rpds-py >= v0.22.3", + "aiohappyeyeballs >= 2.4.4", + "types-requests >= 2.32.0.20250328", + "typing-inspection >= 0.4.0", +] + +[tool.uv.sources] pystarport = { git = "https://github.com/MANTRA-Chain/pystarport.git", branch = "main" } -pytest-github-actions-annotate-failures = "^0.3.0" -flake8-black = "^0.3.6" -flake8-isort = "^6.1.2" -pyunormalize = "^16.0.0" -cprotobuf = { git = "https://github.com/yihuang/cprotobuf.git", branch = "master" } -web3 = "^7.3.0" -eth-bloom = "^3.0" -flaky = "^3.8.1" -pytest-asyncio = "0.25.3" -eth-contract = { git = "https://github.com/mmsqe/eth-contract.git", branch = "event" } -py-ecc = "^8.0.0" +eth-contract = { git = "https://github.com/mmsqe/eth-contract.git", branch = "main" } pyrevm = { git = "https://github.com/yihuang/pyrevm.git", branch = "master" } - -[tool.poetry.dev-dependencies] -attrs = "24.2.0" -referencing = "v0.35.1" -rpds-py = "v0.22.3" -aiohappyeyeballs = "2.4.4" -types-requests = "2.32.0.20250328" -typing-inspection = "0.4.0" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" +cprotobuf = { git = "https://github.com/yihuang/cprotobuf.git", branch = "master" } [tool.black] line-length = 88 From 09183639fef8f72a2f9f59b5e8cea49010fe5574 Mon Sep 17 00:00:00 2001 From: yihuang Date: Fri, 14 Nov 2025 12:07:03 +0800 Subject: [PATCH 16/22] fix uv project --- .envrc.example | 4 + .gitignore | 5 +- flake.lock | 8 +- flake.nix | 2 +- tests/integration_tests/pyproject.toml | 2 +- tests/integration_tests/uv.lock | 2050 ++++++++++++++++++++++++ 6 files changed, 2063 insertions(+), 8 deletions(-) create mode 100644 .envrc.example create mode 100644 tests/integration_tests/uv.lock diff --git a/.envrc.example b/.envrc.example new file mode 100644 index 000000000..650f1143b --- /dev/null +++ b/.envrc.example @@ -0,0 +1,4 @@ +use flake +export VIRTUAL_ENV=."venv" +layout python +TMPDIR=/tmp diff --git a/.gitignore b/.gitignore index 65ed582ad..e9146bbe5 100644 --- a/.gitignore +++ b/.gitignore @@ -40,5 +40,6 @@ tests/systemtests/testnet # Environments *.env -.envrc -.venv +/.envrc +/.venv +/.direnv diff --git a/flake.lock b/flake.lock index c657ab3e0..cabd81eed 100644 --- a/flake.lock +++ b/flake.lock @@ -41,16 +41,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1762943920, - "narHash": "sha256-ITeH8GBpQTw9457ICZBddQEBjlXMmilML067q0e6vqY=", + "lastModified": 1763075743, + "narHash": "sha256-jUClngoxx+v6tk9Kav5bmy6nhD7eyEkPD5RMTaVtW5M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "91c9a64ce2a84e648d0cf9671274bb9c2fb9ba60", + "rev": "9b61355474ef06923d16c05db4e998535b237fc5", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "release-25.05", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index 1f4bb1466..73b50be63 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,6 @@ { inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + nixpkgs.url = "github:NixOS/nixpkgs/release-25.05"; flake-utils.url = "github:numtide/flake-utils"; poetry2nix = { url = "github:nix-community/poetry2nix"; diff --git a/tests/integration_tests/pyproject.toml b/tests/integration_tests/pyproject.toml index 34dcea825..a0421d27a 100644 --- a/tests/integration_tests/pyproject.toml +++ b/tests/integration_tests/pyproject.toml @@ -33,7 +33,7 @@ dev=[ [tool.uv.sources] pystarport = { git = "https://github.com/MANTRA-Chain/pystarport.git", branch = "main" } -eth-contract = { git = "https://github.com/mmsqe/eth-contract.git", branch = "main" } +eth-contract = { git = "https://github.com/mmsqe/eth-contract.git", branch = "event" } pyrevm = { git = "https://github.com/yihuang/pyrevm.git", branch = "master" } cprotobuf = { git = "https://github.com/yihuang/cprotobuf.git", branch = "master" } diff --git a/tests/integration_tests/uv.lock b/tests/integration_tests/uv.lock new file mode 100644 index 000000000..736f9abec --- /dev/null +++ b/tests/integration_tests/uv.lock @@ -0,0 +1,2050 @@ +version = 1 +revision = 2 +requires-python = ">=3.12" + +[[package]] +name = "aiohappyeyeballs" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.13.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/ce/3b83ebba6b3207a7135e5fcaba49706f8a4b6008153b4e30540c982fae26/aiohttp-3.13.2.tar.gz", hash = "sha256:40176a52c186aefef6eb3cad2cdd30cd06e3afbe88fe8ab2af9c0b90f228daca", size = 7837994, upload-time = "2025-10-28T20:59:39.937Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/29/9b/01f00e9856d0a73260e86dd8ed0c2234a466c5c1712ce1c281548df39777/aiohttp-3.13.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b1e56bab2e12b2b9ed300218c351ee2a3d8c8fdab5b1ec6193e11a817767e47b", size = 737623, upload-time = "2025-10-28T20:56:30.797Z" }, + { url = "https://files.pythonhosted.org/packages/5a/1b/4be39c445e2b2bd0aab4ba736deb649fabf14f6757f405f0c9685019b9e9/aiohttp-3.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:364e25edaabd3d37b1db1f0cbcee8c73c9a3727bfa262b83e5e4cf3489a2a9dc", size = 492664, upload-time = "2025-10-28T20:56:32.708Z" }, + { url = "https://files.pythonhosted.org/packages/28/66/d35dcfea8050e131cdd731dff36434390479b4045a8d0b9d7111b0a968f1/aiohttp-3.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c5c94825f744694c4b8db20b71dba9a257cd2ba8e010a803042123f3a25d50d7", size = 491808, upload-time = "2025-10-28T20:56:34.57Z" }, + { url = "https://files.pythonhosted.org/packages/00/29/8e4609b93e10a853b65f8291e64985de66d4f5848c5637cddc70e98f01f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba2715d842ffa787be87cbfce150d5e88c87a98e0b62e0f5aa489169a393dbbb", size = 1738863, upload-time = "2025-10-28T20:56:36.377Z" }, + { url = "https://files.pythonhosted.org/packages/9d/fa/4ebdf4adcc0def75ced1a0d2d227577cd7b1b85beb7edad85fcc87693c75/aiohttp-3.13.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:585542825c4bc662221fb257889e011a5aa00f1ae4d75d1d246a5225289183e3", size = 1700586, upload-time = "2025-10-28T20:56:38.034Z" }, + { url = "https://files.pythonhosted.org/packages/da/04/73f5f02ff348a3558763ff6abe99c223381b0bace05cd4530a0258e52597/aiohttp-3.13.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39d02cb6025fe1aabca329c5632f48c9532a3dabccd859e7e2f110668972331f", size = 1768625, upload-time = "2025-10-28T20:56:39.75Z" }, + { url = "https://files.pythonhosted.org/packages/f8/49/a825b79ffec124317265ca7d2344a86bcffeb960743487cb11988ffb3494/aiohttp-3.13.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e67446b19e014d37342f7195f592a2a948141d15a312fe0e700c2fd2f03124f6", size = 1867281, upload-time = "2025-10-28T20:56:41.471Z" }, + { url = "https://files.pythonhosted.org/packages/b9/48/adf56e05f81eac31edcfae45c90928f4ad50ef2e3ea72cb8376162a368f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4356474ad6333e41ccefd39eae869ba15a6c5299c9c01dfdcfdd5c107be4363e", size = 1752431, upload-time = "2025-10-28T20:56:43.162Z" }, + { url = "https://files.pythonhosted.org/packages/30/ab/593855356eead019a74e862f21523db09c27f12fd24af72dbc3555b9bfd9/aiohttp-3.13.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeacf451c99b4525f700f078becff32c32ec327b10dcf31306a8a52d78166de7", size = 1562846, upload-time = "2025-10-28T20:56:44.85Z" }, + { url = "https://files.pythonhosted.org/packages/39/0f/9f3d32271aa8dc35036e9668e31870a9d3b9542dd6b3e2c8a30931cb27ae/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8a9b889aeabd7a4e9af0b7f4ab5ad94d42e7ff679aaec6d0db21e3b639ad58d", size = 1699606, upload-time = "2025-10-28T20:56:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/2c/3c/52d2658c5699b6ef7692a3f7128b2d2d4d9775f2a68093f74bca06cf01e1/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fa89cb11bc71a63b69568d5b8a25c3ca25b6d54c15f907ca1c130d72f320b76b", size = 1720663, upload-time = "2025-10-28T20:56:48.528Z" }, + { url = "https://files.pythonhosted.org/packages/9b/d4/8f8f3ff1fb7fb9e3f04fcad4e89d8a1cd8fc7d05de67e3de5b15b33008ff/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8aa7c807df234f693fed0ecd507192fc97692e61fee5702cdc11155d2e5cadc8", size = 1737939, upload-time = "2025-10-28T20:56:50.77Z" }, + { url = "https://files.pythonhosted.org/packages/03/d3/ddd348f8a27a634daae39a1b8e291ff19c77867af438af844bf8b7e3231b/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9eb3e33fdbe43f88c3c75fa608c25e7c47bbd80f48d012763cb67c47f39a7e16", size = 1555132, upload-time = "2025-10-28T20:56:52.568Z" }, + { url = "https://files.pythonhosted.org/packages/39/b8/46790692dc46218406f94374903ba47552f2f9f90dad554eed61bfb7b64c/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9434bc0d80076138ea986833156c5a48c9c7a8abb0c96039ddbb4afc93184169", size = 1764802, upload-time = "2025-10-28T20:56:54.292Z" }, + { url = "https://files.pythonhosted.org/packages/ba/e4/19ce547b58ab2a385e5f0b8aa3db38674785085abcf79b6e0edd1632b12f/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ff15c147b2ad66da1f2cbb0622313f2242d8e6e8f9b79b5206c84523a4473248", size = 1719512, upload-time = "2025-10-28T20:56:56.428Z" }, + { url = "https://files.pythonhosted.org/packages/70/30/6355a737fed29dcb6dfdd48682d5790cb5eab050f7b4e01f49b121d3acad/aiohttp-3.13.2-cp312-cp312-win32.whl", hash = "sha256:27e569eb9d9e95dbd55c0fc3ec3a9335defbf1d8bc1d20171a49f3c4c607b93e", size = 426690, upload-time = "2025-10-28T20:56:58.736Z" }, + { url = "https://files.pythonhosted.org/packages/0a/0d/b10ac09069973d112de6ef980c1f6bb31cb7dcd0bc363acbdad58f927873/aiohttp-3.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:8709a0f05d59a71f33fd05c17fc11fcb8c30140506e13c2f5e8ee1b8964e1b45", size = 453465, upload-time = "2025-10-28T20:57:00.795Z" }, + { url = "https://files.pythonhosted.org/packages/bf/78/7e90ca79e5aa39f9694dcfd74f4720782d3c6828113bb1f3197f7e7c4a56/aiohttp-3.13.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7519bdc7dfc1940d201651b52bf5e03f5503bda45ad6eacf64dda98be5b2b6be", size = 732139, upload-time = "2025-10-28T20:57:02.455Z" }, + { url = "https://files.pythonhosted.org/packages/db/ed/1f59215ab6853fbaa5c8495fa6cbc39edfc93553426152b75d82a5f32b76/aiohttp-3.13.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:088912a78b4d4f547a1f19c099d5a506df17eacec3c6f4375e2831ec1d995742", size = 490082, upload-time = "2025-10-28T20:57:04.784Z" }, + { url = "https://files.pythonhosted.org/packages/68/7b/fe0fe0f5e05e13629d893c760465173a15ad0039c0a5b0d0040995c8075e/aiohttp-3.13.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5276807b9de9092af38ed23ce120539ab0ac955547b38563a9ba4f5b07b95293", size = 489035, upload-time = "2025-10-28T20:57:06.894Z" }, + { url = "https://files.pythonhosted.org/packages/d2/04/db5279e38471b7ac801d7d36a57d1230feeee130bbe2a74f72731b23c2b1/aiohttp-3.13.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1237c1375eaef0db4dcd7c2559f42e8af7b87ea7d295b118c60c36a6e61cb811", size = 1720387, upload-time = "2025-10-28T20:57:08.685Z" }, + { url = "https://files.pythonhosted.org/packages/31/07/8ea4326bd7dae2bd59828f69d7fdc6e04523caa55e4a70f4a8725a7e4ed2/aiohttp-3.13.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:96581619c57419c3d7d78703d5b78c1e5e5fc0172d60f555bdebaced82ded19a", size = 1688314, upload-time = "2025-10-28T20:57:10.693Z" }, + { url = "https://files.pythonhosted.org/packages/48/ab/3d98007b5b87ffd519d065225438cc3b668b2f245572a8cb53da5dd2b1bc/aiohttp-3.13.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2713a95b47374169409d18103366de1050fe0ea73db358fc7a7acb2880422d4", size = 1756317, upload-time = "2025-10-28T20:57:12.563Z" }, + { url = "https://files.pythonhosted.org/packages/97/3d/801ca172b3d857fafb7b50c7c03f91b72b867a13abca982ed6b3081774ef/aiohttp-3.13.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:228a1cd556b3caca590e9511a89444925da87d35219a49ab5da0c36d2d943a6a", size = 1858539, upload-time = "2025-10-28T20:57:14.623Z" }, + { url = "https://files.pythonhosted.org/packages/f7/0d/4764669bdf47bd472899b3d3db91fffbe925c8e3038ec591a2fd2ad6a14d/aiohttp-3.13.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac6cde5fba8d7d8c6ac963dbb0256a9854e9fafff52fbcc58fdf819357892c3e", size = 1739597, upload-time = "2025-10-28T20:57:16.399Z" }, + { url = "https://files.pythonhosted.org/packages/c4/52/7bd3c6693da58ba16e657eb904a5b6decfc48ecd06e9ac098591653b1566/aiohttp-3.13.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2bef8237544f4e42878c61cef4e2839fee6346dc60f5739f876a9c50be7fcdb", size = 1555006, upload-time = "2025-10-28T20:57:18.288Z" }, + { url = "https://files.pythonhosted.org/packages/48/30/9586667acec5993b6f41d2ebcf96e97a1255a85f62f3c653110a5de4d346/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:16f15a4eac3bc2d76c45f7ebdd48a65d41b242eb6c31c2245463b40b34584ded", size = 1683220, upload-time = "2025-10-28T20:57:20.241Z" }, + { url = "https://files.pythonhosted.org/packages/71/01/3afe4c96854cfd7b30d78333852e8e851dceaec1c40fd00fec90c6402dd2/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:bb7fb776645af5cc58ab804c58d7eba545a97e047254a52ce89c157b5af6cd0b", size = 1712570, upload-time = "2025-10-28T20:57:22.253Z" }, + { url = "https://files.pythonhosted.org/packages/11/2c/22799d8e720f4697a9e66fd9c02479e40a49de3de2f0bbe7f9f78a987808/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e1b4951125ec10c70802f2cb09736c895861cd39fd9dcb35107b4dc8ae6220b8", size = 1733407, upload-time = "2025-10-28T20:57:24.37Z" }, + { url = "https://files.pythonhosted.org/packages/34/cb/90f15dd029f07cebbd91f8238a8b363978b530cd128488085b5703683594/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:550bf765101ae721ee1d37d8095f47b1f220650f85fe1af37a90ce75bab89d04", size = 1550093, upload-time = "2025-10-28T20:57:26.257Z" }, + { url = "https://files.pythonhosted.org/packages/69/46/12dce9be9d3303ecbf4d30ad45a7683dc63d90733c2d9fe512be6716cd40/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fe91b87fc295973096251e2d25a811388e7d8adf3bd2b97ef6ae78bc4ac6c476", size = 1758084, upload-time = "2025-10-28T20:57:28.349Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c8/0932b558da0c302ffd639fc6362a313b98fdf235dc417bc2493da8394df7/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0c8e31cfcc4592cb200160344b2fb6ae0f9e4effe06c644b5a125d4ae5ebe23", size = 1716987, upload-time = "2025-10-28T20:57:30.233Z" }, + { url = "https://files.pythonhosted.org/packages/5d/8b/f5bd1a75003daed099baec373aed678f2e9b34f2ad40d85baa1368556396/aiohttp-3.13.2-cp313-cp313-win32.whl", hash = "sha256:0740f31a60848d6edb296a0df827473eede90c689b8f9f2a4cdde74889eb2254", size = 425859, upload-time = "2025-10-28T20:57:32.105Z" }, + { url = "https://files.pythonhosted.org/packages/5d/28/a8a9fc6957b2cee8902414e41816b5ab5536ecf43c3b1843c10e82c559b2/aiohttp-3.13.2-cp313-cp313-win_amd64.whl", hash = "sha256:a88d13e7ca367394908f8a276b89d04a3652044612b9a408a0bb22a5ed976a1a", size = 452192, upload-time = "2025-10-28T20:57:34.166Z" }, + { url = "https://files.pythonhosted.org/packages/9b/36/e2abae1bd815f01c957cbf7be817b3043304e1c87bad526292a0410fdcf9/aiohttp-3.13.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2475391c29230e063ef53a66669b7b691c9bfc3f1426a0f7bcdf1216bdbac38b", size = 735234, upload-time = "2025-10-28T20:57:36.415Z" }, + { url = "https://files.pythonhosted.org/packages/ca/e3/1ee62dde9b335e4ed41db6bba02613295a0d5b41f74a783c142745a12763/aiohttp-3.13.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f33c8748abef4d8717bb20e8fb1b3e07c6adacb7fd6beaae971a764cf5f30d61", size = 490733, upload-time = "2025-10-28T20:57:38.205Z" }, + { url = "https://files.pythonhosted.org/packages/1a/aa/7a451b1d6a04e8d15a362af3e9b897de71d86feac3babf8894545d08d537/aiohttp-3.13.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ae32f24bbfb7dbb485a24b30b1149e2f200be94777232aeadba3eecece4d0aa4", size = 491303, upload-time = "2025-10-28T20:57:40.122Z" }, + { url = "https://files.pythonhosted.org/packages/57/1e/209958dbb9b01174870f6a7538cd1f3f28274fdbc88a750c238e2c456295/aiohttp-3.13.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d7f02042c1f009ffb70067326ef183a047425bb2ff3bc434ead4dd4a4a66a2b", size = 1717965, upload-time = "2025-10-28T20:57:42.28Z" }, + { url = "https://files.pythonhosted.org/packages/08/aa/6a01848d6432f241416bc4866cae8dc03f05a5a884d2311280f6a09c73d6/aiohttp-3.13.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93655083005d71cd6c072cdab54c886e6570ad2c4592139c3fb967bfc19e4694", size = 1667221, upload-time = "2025-10-28T20:57:44.869Z" }, + { url = "https://files.pythonhosted.org/packages/87/4f/36c1992432d31bbc789fa0b93c768d2e9047ec8c7177e5cd84ea85155f36/aiohttp-3.13.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0db1e24b852f5f664cd728db140cf11ea0e82450471232a394b3d1a540b0f906", size = 1757178, upload-time = "2025-10-28T20:57:47.216Z" }, + { url = "https://files.pythonhosted.org/packages/ac/b4/8e940dfb03b7e0f68a82b88fd182b9be0a65cb3f35612fe38c038c3112cf/aiohttp-3.13.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b009194665bcd128e23eaddef362e745601afa4641930848af4c8559e88f18f9", size = 1838001, upload-time = "2025-10-28T20:57:49.337Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ef/39f3448795499c440ab66084a9db7d20ca7662e94305f175a80f5b7e0072/aiohttp-3.13.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c038a8fdc8103cd51dbd986ecdce141473ffd9775a7a8057a6ed9c3653478011", size = 1716325, upload-time = "2025-10-28T20:57:51.327Z" }, + { url = "https://files.pythonhosted.org/packages/d7/51/b311500ffc860b181c05d91c59a1313bdd05c82960fdd4035a15740d431e/aiohttp-3.13.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66bac29b95a00db411cd758fea0e4b9bdba6d549dfe333f9a945430f5f2cc5a6", size = 1547978, upload-time = "2025-10-28T20:57:53.554Z" }, + { url = "https://files.pythonhosted.org/packages/31/64/b9d733296ef79815226dab8c586ff9e3df41c6aff2e16c06697b2d2e6775/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4ebf9cfc9ba24a74cf0718f04aac2a3bbe745902cc7c5ebc55c0f3b5777ef213", size = 1682042, upload-time = "2025-10-28T20:57:55.617Z" }, + { url = "https://files.pythonhosted.org/packages/3f/30/43d3e0f9d6473a6db7d472104c4eff4417b1e9df01774cb930338806d36b/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a4b88ebe35ce54205c7074f7302bd08a4cb83256a3e0870c72d6f68a3aaf8e49", size = 1680085, upload-time = "2025-10-28T20:57:57.59Z" }, + { url = "https://files.pythonhosted.org/packages/16/51/c709f352c911b1864cfd1087577760ced64b3e5bee2aa88b8c0c8e2e4972/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:98c4fb90bb82b70a4ed79ca35f656f4281885be076f3f970ce315402b53099ae", size = 1728238, upload-time = "2025-10-28T20:57:59.525Z" }, + { url = "https://files.pythonhosted.org/packages/19/e2/19bd4c547092b773caeb48ff5ae4b1ae86756a0ee76c16727fcfd281404b/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:ec7534e63ae0f3759df3a1ed4fa6bc8f75082a924b590619c0dd2f76d7043caa", size = 1544395, upload-time = "2025-10-28T20:58:01.914Z" }, + { url = "https://files.pythonhosted.org/packages/cf/87/860f2803b27dfc5ed7be532832a3498e4919da61299b4a1f8eb89b8ff44d/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5b927cf9b935a13e33644cbed6c8c4b2d0f25b713d838743f8fe7191b33829c4", size = 1742965, upload-time = "2025-10-28T20:58:03.972Z" }, + { url = "https://files.pythonhosted.org/packages/67/7f/db2fc7618925e8c7a601094d5cbe539f732df4fb570740be88ed9e40e99a/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:88d6c017966a78c5265d996c19cdb79235be5e6412268d7e2ce7dee339471b7a", size = 1697585, upload-time = "2025-10-28T20:58:06.189Z" }, + { url = "https://files.pythonhosted.org/packages/0c/07/9127916cb09bb38284db5036036042b7b2c514c8ebaeee79da550c43a6d6/aiohttp-3.13.2-cp314-cp314-win32.whl", hash = "sha256:f7c183e786e299b5d6c49fb43a769f8eb8e04a2726a2bd5887b98b5cc2d67940", size = 431621, upload-time = "2025-10-28T20:58:08.636Z" }, + { url = "https://files.pythonhosted.org/packages/fb/41/554a8a380df6d3a2bba8a7726429a23f4ac62aaf38de43bb6d6cde7b4d4d/aiohttp-3.13.2-cp314-cp314-win_amd64.whl", hash = "sha256:fe242cd381e0fb65758faf5ad96c2e460df6ee5b2de1072fe97e4127927e00b4", size = 457627, upload-time = "2025-10-28T20:58:11Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8e/3824ef98c039d3951cb65b9205a96dd2b20f22241ee17d89c5701557c826/aiohttp-3.13.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:f10d9c0b0188fe85398c61147bbd2a657d616c876863bfeff43376e0e3134673", size = 767360, upload-time = "2025-10-28T20:58:13.358Z" }, + { url = "https://files.pythonhosted.org/packages/a4/0f/6a03e3fc7595421274fa34122c973bde2d89344f8a881b728fa8c774e4f1/aiohttp-3.13.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:e7c952aefdf2460f4ae55c5e9c3e80aa72f706a6317e06020f80e96253b1accd", size = 504616, upload-time = "2025-10-28T20:58:15.339Z" }, + { url = "https://files.pythonhosted.org/packages/c6/aa/ed341b670f1bc8a6f2c6a718353d13b9546e2cef3544f573c6a1ff0da711/aiohttp-3.13.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c20423ce14771d98353d2e25e83591fa75dfa90a3c1848f3d7c68243b4fbded3", size = 509131, upload-time = "2025-10-28T20:58:17.693Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f0/c68dac234189dae5c4bbccc0f96ce0cc16b76632cfc3a08fff180045cfa4/aiohttp-3.13.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e96eb1a34396e9430c19d8338d2ec33015e4a87ef2b4449db94c22412e25ccdf", size = 1864168, upload-time = "2025-10-28T20:58:20.113Z" }, + { url = "https://files.pythonhosted.org/packages/8f/65/75a9a76db8364b5d0e52a0c20eabc5d52297385d9af9c35335b924fafdee/aiohttp-3.13.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:23fb0783bc1a33640036465019d3bba069942616a6a2353c6907d7fe1ccdaf4e", size = 1719200, upload-time = "2025-10-28T20:58:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/f5/55/8df2ed78d7f41d232f6bd3ff866b6f617026551aa1d07e2f03458f964575/aiohttp-3.13.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e1a9bea6244a1d05a4e57c295d69e159a5c50d8ef16aa390948ee873478d9a5", size = 1843497, upload-time = "2025-10-28T20:58:24.672Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e0/94d7215e405c5a02ccb6a35c7a3a6cfff242f457a00196496935f700cde5/aiohttp-3.13.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0a3d54e822688b56e9f6b5816fb3de3a3a64660efac64e4c2dc435230ad23bad", size = 1935703, upload-time = "2025-10-28T20:58:26.758Z" }, + { url = "https://files.pythonhosted.org/packages/0b/78/1eeb63c3f9b2d1015a4c02788fb543141aad0a03ae3f7a7b669b2483f8d4/aiohttp-3.13.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7a653d872afe9f33497215745da7a943d1dc15b728a9c8da1c3ac423af35178e", size = 1792738, upload-time = "2025-10-28T20:58:29.787Z" }, + { url = "https://files.pythonhosted.org/packages/41/75/aaf1eea4c188e51538c04cc568040e3082db263a57086ea74a7d38c39e42/aiohttp-3.13.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:56d36e80d2003fa3fc0207fac644216d8532e9504a785ef9a8fd013f84a42c61", size = 1624061, upload-time = "2025-10-28T20:58:32.529Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c2/3b6034de81fbcc43de8aeb209073a2286dfb50b86e927b4efd81cf848197/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:78cd586d8331fb8e241c2dd6b2f4061778cc69e150514b39a9e28dd050475661", size = 1789201, upload-time = "2025-10-28T20:58:34.618Z" }, + { url = "https://files.pythonhosted.org/packages/c9/38/c15dcf6d4d890217dae79d7213988f4e5fe6183d43893a9cf2fe9e84ca8d/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:20b10bbfbff766294fe99987f7bb3b74fdd2f1a2905f2562132641ad434dcf98", size = 1776868, upload-time = "2025-10-28T20:58:38.835Z" }, + { url = "https://files.pythonhosted.org/packages/04/75/f74fd178ac81adf4f283a74847807ade5150e48feda6aef024403716c30c/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9ec49dff7e2b3c85cdeaa412e9d438f0ecd71676fde61ec57027dd392f00c693", size = 1790660, upload-time = "2025-10-28T20:58:41.507Z" }, + { url = "https://files.pythonhosted.org/packages/e7/80/7368bd0d06b16b3aba358c16b919e9c46cf11587dc572091031b0e9e3ef0/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:94f05348c4406450f9d73d38efb41d669ad6cd90c7ee194810d0eefbfa875a7a", size = 1617548, upload-time = "2025-10-28T20:58:43.674Z" }, + { url = "https://files.pythonhosted.org/packages/7d/4b/a6212790c50483cb3212e507378fbe26b5086d73941e1ec4b56a30439688/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:fa4dcb605c6f82a80c7f95713c2b11c3b8e9893b3ebd2bc9bde93165ed6107be", size = 1817240, upload-time = "2025-10-28T20:58:45.787Z" }, + { url = "https://files.pythonhosted.org/packages/ff/f7/ba5f0ba4ea8d8f3c32850912944532b933acbf0f3a75546b89269b9b7dde/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf00e5db968c3f67eccd2778574cf64d8b27d95b237770aa32400bd7a1ca4f6c", size = 1762334, upload-time = "2025-10-28T20:58:47.936Z" }, + { url = "https://files.pythonhosted.org/packages/7e/83/1a5a1856574588b1cad63609ea9ad75b32a8353ac995d830bf5da9357364/aiohttp-3.13.2-cp314-cp314t-win32.whl", hash = "sha256:d23b5fe492b0805a50d3371e8a728a9134d8de5447dce4c885f5587294750734", size = 464685, upload-time = "2025-10-28T20:58:50.642Z" }, + { url = "https://files.pythonhosted.org/packages/9f/4d/d22668674122c08f4d56972297c51a624e64b3ed1efaa40187607a7cb66e/aiohttp-3.13.2-cp314-cp314t-win_amd64.whl", hash = "sha256:ff0a7b0a82a7ab905cbda74006318d1b12e37c797eb1b0d4eb3e316cf47f658f", size = 498093, upload-time = "2025-10-28T20:58:52.782Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "attrs" +version = "25.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, +] + +[[package]] +name = "bech32" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ab/fe/b67ac9b123e25a3c1b8fc3f3c92648804516ab44215adb165284e024c43f/bech32-1.2.0.tar.gz", hash = "sha256:7d6db8214603bd7871fcfa6c0826ef68b85b0abd90fa21c285a9c5e21d2bd899", size = 3695, upload-time = "2020-02-17T15:31:09.763Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/41/7022a226e5a6ac7091a95ba36bad057012ab7330b9894ad4e14e31d0b858/bech32-1.2.0-py3-none-any.whl", hash = "sha256:990dc8e5a5e4feabbdf55207b5315fdd9b73db40be294a19b3752cde9e79d981", size = 4587, upload-time = "2020-02-17T15:31:08.299Z" }, +] + +[[package]] +name = "bitarray" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/95/06/92fdc84448d324ab8434b78e65caf4fb4c6c90b4f8ad9bdd4c8021bfaf1e/bitarray-3.8.0.tar.gz", hash = "sha256:3eae38daffd77c9621ae80c16932eea3fb3a4af141fb7cc724d4ad93eff9210d", size = 151991, upload-time = "2025-11-02T21:41:15.117Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/a0/0c41d893eda756315491adfdbf9bc928aee3d377a7f97a8834d453aa5de1/bitarray-3.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2fcbe9b3a5996b417e030aa33a562e7e20dfc86271e53d7e841fc5df16268b8", size = 148575, upload-time = "2025-11-02T21:39:25.718Z" }, + { url = "https://files.pythonhosted.org/packages/0e/30/12ab2f4a4429bd844b419c37877caba93d676d18be71354fbbeb21d9f4cc/bitarray-3.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cd761d158f67e288fd0ebe00c3b158095ce80a4bc7c32b60c7121224003ba70d", size = 145454, upload-time = "2025-11-02T21:39:26.695Z" }, + { url = "https://files.pythonhosted.org/packages/26/58/314b3e3f219533464e120f0c51ac5123e7b1c1b91f725a4073fb70c5a858/bitarray-3.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c394a3f055b49f92626f83c1a0b6d6cd2c628f1ccd72481c3e3c6aa4695f3b20", size = 332949, upload-time = "2025-11-02T21:39:27.801Z" }, + { url = "https://files.pythonhosted.org/packages/ea/ce/ca8c706bd8341c7a22dd92d2a528af71f7e5f4726085d93f81fd768cb03b/bitarray-3.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:969fd67de8c42affdb47b38b80f1eaa79ac0ef17d65407cdd931db1675315af1", size = 360599, upload-time = "2025-11-02T21:39:28.964Z" }, + { url = "https://files.pythonhosted.org/packages/ef/dc/aa181df85f933052d962804906b282acb433cb9318b08ec2aceb4ee34faf/bitarray-3.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:99d25aff3745c54e61ab340b98400c52ebec04290a62078155e0d7eb30380220", size = 371972, upload-time = "2025-11-02T21:39:30.228Z" }, + { url = "https://files.pythonhosted.org/packages/ff/d9/b805bfa158c7bcf4df0ac19b1be581b47e1ddb792c11023aed80a7058e78/bitarray-3.8.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e645b4c365d6f1f9e0799380ad6395268f3c3b898244a650aaeb8d9d27b74c35", size = 340303, upload-time = "2025-11-02T21:39:31.342Z" }, + { url = "https://files.pythonhosted.org/packages/1f/42/5308cc97ea929e30727292617a3a88293470166851e13c9e3f16f395da55/bitarray-3.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2fa23fdb3beab313950bbb49674e8a161e61449332d3997089fe3944953f1b77", size = 330494, upload-time = "2025-11-02T21:39:32.769Z" }, + { url = "https://files.pythonhosted.org/packages/4c/89/64f1596cb80433323efdbc8dcd0d6e57c40dfbe6ea3341623f34ec397edd/bitarray-3.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:165052a0e61c880f7093808a0c524ce1b3555bfa114c0dfb5c809cd07918a60d", size = 358123, upload-time = "2025-11-02T21:39:34.331Z" }, + { url = "https://files.pythonhosted.org/packages/27/fd/f3d49c5443b57087f888b5e118c8dd78bb7c8e8cfeeed250f8e92128a05f/bitarray-3.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:337c8cd46a4c6568d367ed676cbf2d7de16f890bb31dbb54c44c1d6bb6d4a1de", size = 356046, upload-time = "2025-11-02T21:39:35.449Z" }, + { url = "https://files.pythonhosted.org/packages/aa/db/1fd0b402bd2b47142e958b6930dbb9445235d03fa703c9a24caa6e576ae2/bitarray-3.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:21ca6a47bf20db9e7ad74ca04b3d479e4d76109b68333eb23535553d2705339e", size = 336872, upload-time = "2025-11-02T21:39:36.891Z" }, + { url = "https://files.pythonhosted.org/packages/58/73/680b47718f1313b4538af479c4732eaca0aeda34d93fc5b869f87932d57d/bitarray-3.8.0-cp312-cp312-win32.whl", hash = "sha256:178c5a4c7fdfb5cd79e372ae7f675390e670f3732e5bc68d327e01a5b3ff8d55", size = 143025, upload-time = "2025-11-02T21:39:38.303Z" }, + { url = "https://files.pythonhosted.org/packages/f8/11/7792587c19c79a8283e8838f44709fa4338a8f7d2a3091dfd81c07ae89c7/bitarray-3.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:75a3b6e9c695a6570ea488db75b84bb592ff70a944957efa1c655867c575018b", size = 149969, upload-time = "2025-11-02T21:39:39.715Z" }, + { url = "https://files.pythonhosted.org/packages/9a/00/9df64b5d8a84e8e9ec392f6f9ce93f50626a5b301cb6c6b3fe3406454d66/bitarray-3.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:5591daf81313096909d973fb2612fccd87528fdfdd39f6478bdce54543178954", size = 146907, upload-time = "2025-11-02T21:39:40.815Z" }, + { url = "https://files.pythonhosted.org/packages/3e/35/480364d4baf1e34c79076750914664373f561c58abb5c31c35b3fae613ff/bitarray-3.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:18214bac86341f1cc413772e66447d6cca10981e2880b70ecaf4e826c04f95e9", size = 148582, upload-time = "2025-11-02T21:39:42.268Z" }, + { url = "https://files.pythonhosted.org/packages/5e/a8/718b95524c803937f4edbaaf6480f39c80f6ed189d61357b345e8361ffb6/bitarray-3.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:01c5f0dc080b0ebb432f7a68ee1e88a76bd34f6d89c9568fcec65fb16ed71f0e", size = 145433, upload-time = "2025-11-02T21:39:43.552Z" }, + { url = "https://files.pythonhosted.org/packages/03/66/4a10f30dc9e2e01e3b4ecd44a511219f98e63c86b0e0f704c90fac24059b/bitarray-3.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86685fa04067f7175f9718489ae755f6acde03593a1a9ca89305554af40e14fd", size = 332986, upload-time = "2025-11-02T21:39:44.656Z" }, + { url = "https://files.pythonhosted.org/packages/53/25/4c08774d847f80a1166e4c704b4e0f1c417c0afe6306eae0bc5e70d35faa/bitarray-3.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56896ceeffe25946c4010320629e2d858ca763cd8ded273c81672a5edbcb1e0a", size = 360634, upload-time = "2025-11-02T21:39:45.798Z" }, + { url = "https://files.pythonhosted.org/packages/a5/8f/bf8ad26169ebd0b2746d5c7564db734453ca467f8aab87e9d43b0a794383/bitarray-3.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9858dcbc23ba7eaadcd319786b982278a1a2b2020720b19db43e309579ff76fb", size = 371992, upload-time = "2025-11-02T21:39:46.968Z" }, + { url = "https://files.pythonhosted.org/packages/a9/16/ce166754e7c9d10650e02914552fa637cf3b2591f7ed16632bbf6b783312/bitarray-3.8.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa7dec53c25f1949513457ef8b0ea1fb40e76c672cc4d2daa8ad3c8d6b73491a", size = 340315, upload-time = "2025-11-02T21:39:48.182Z" }, + { url = "https://files.pythonhosted.org/packages/de/2a/fbba3a106ddd260e84b9a624f730257c32ba51a8a029565248dfedfdf6f2/bitarray-3.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:15a2eff91f54d2b1f573cca8ca6fb58763ce8fea80e7899ab028f3987ef71cd5", size = 330473, upload-time = "2025-11-02T21:39:49.705Z" }, + { url = "https://files.pythonhosted.org/packages/68/97/56cf3c70196e7307ad32318a9d6ed969dbdc6a4534bbe429112fa7dfe42e/bitarray-3.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b1572ee0eb1967e71787af636bb7d1eb9c6735d5337762c450650e7f51844594", size = 358129, upload-time = "2025-11-02T21:39:51.189Z" }, + { url = "https://files.pythonhosted.org/packages/fd/be/afd391a5c0896d3339613321b2f94af853f29afc8bd3fbc327431244c642/bitarray-3.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5bfac7f236ba1a4d402644bdce47fb9db02a7cf3214a1f637d3a88390f9e5428", size = 356005, upload-time = "2025-11-02T21:39:52.355Z" }, + { url = "https://files.pythonhosted.org/packages/ae/08/a8e1a371babba29bad3378bb3a2cdca2b012170711e7fe1f22031a6b7b95/bitarray-3.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f0a55cf02d2cdd739b40ce10c09bbdd520e141217696add7a48b56e67bdfdfe6", size = 336862, upload-time = "2025-11-02T21:39:54.345Z" }, + { url = "https://files.pythonhosted.org/packages/ee/8a/6dc1d0fdc06991c8dc3b1fcfe1ae49fbaced42064cd1b5f24278e73fe05f/bitarray-3.8.0-cp313-cp313-win32.whl", hash = "sha256:a2ba92f59e30ce915e9e79af37649432e3a212ddddf416d4d686b1b4825bcdb2", size = 143018, upload-time = "2025-11-02T21:39:56.361Z" }, + { url = "https://files.pythonhosted.org/packages/2e/72/76e13f5cd23b8b9071747909663ce3b02da24a5e7e22c35146338625db35/bitarray-3.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c8f2a5d8006db5a555e06f9437e76bf52537d3dfd130cb8ae2b30866aca32c9", size = 149977, upload-time = "2025-11-02T21:39:57.718Z" }, + { url = "https://files.pythonhosted.org/packages/01/37/60f336c32336cc3ec03b0c61076f16ea2f05d5371c8a56e802161d218b77/bitarray-3.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:50ddbe3a7b4b6ab96812f5a4d570f401a2cdb95642fd04c062f98939610bbeee", size = 146930, upload-time = "2025-11-02T21:39:59.308Z" }, + { url = "https://files.pythonhosted.org/packages/1b/b0/411327a6c7f6b2bead64bb06fe60b92e0344957ec1ab0645d5ccc25fdafe/bitarray-3.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8cbd4bfc933b33b85c43ef4c1f4d5e3e9d91975ea6368acf5fbac02bac06ea89", size = 148563, upload-time = "2025-11-02T21:40:01.006Z" }, + { url = "https://files.pythonhosted.org/packages/2a/bc/ff80d97c627d774f879da0ea93223adb1267feab7e07d5c17580ffe6d632/bitarray-3.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9d35d8f8a1c9ed4e2b08187b513f8a3c71958600129db3aa26d85ea3abfd1310", size = 145422, upload-time = "2025-11-02T21:40:02.535Z" }, + { url = "https://files.pythonhosted.org/packages/66/e7/b4cb6c5689aacd0a32f3aa8a507155eaa33528c63de2f182b60843fbf700/bitarray-3.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99f55e14e7c56f4fafe1343480c32b110ef03836c21ff7c48bae7add6818f77c", size = 332852, upload-time = "2025-11-02T21:40:03.645Z" }, + { url = "https://files.pythonhosted.org/packages/e7/91/fbd1b047e3e2f4b65590f289c8151df1d203d75b005f5aae4e072fe77d76/bitarray-3.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dfbe2aa45b273f49e715c5345d94874cb65a28482bf231af408891c260601b8d", size = 360801, upload-time = "2025-11-02T21:40:04.827Z" }, + { url = "https://files.pythonhosted.org/packages/ef/4a/63064c593627bac8754fdafcb5343999c93ab2aeb27bcd9d270a010abea5/bitarray-3.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:64af877116edf051375b45f0bda648143176a017b13803ec7b3a3111dc05f4c5", size = 371408, upload-time = "2025-11-02T21:40:05.985Z" }, + { url = "https://files.pythonhosted.org/packages/46/97/ddc07723767bdafd170f2ff6e173c940fa874192783ee464aa3c1dedf07d/bitarray-3.8.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cdfbb27f2c46bb5bbdcee147530cbc5ca8ab858d7693924e88e30ada21b2c5e2", size = 340033, upload-time = "2025-11-02T21:40:07.189Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1e/e1ea9f1146fd4af032817069ff118918d73e5de519854ce3860e2ed560ff/bitarray-3.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4d73d4948dcc5591d880db8933004e01f1dd2296df9de815354d53469beb26fe", size = 330774, upload-time = "2025-11-02T21:40:08.496Z" }, + { url = "https://files.pythonhosted.org/packages/cf/9f/8242296c124a48d1eab471fd0838aeb7ea9c6fd720302d99ab7855d3e6d3/bitarray-3.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:28a85b056c0eb7f5d864c0ceef07034117e8ebfca756f50648c71950a568ba11", size = 358337, upload-time = "2025-11-02T21:40:10.035Z" }, + { url = "https://files.pythonhosted.org/packages/b5/6b/9095d75264c67d479f298c80802422464ce18c3cdd893252eeccf4997611/bitarray-3.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:79ec4498a545733ecace48d780d22407411b07403a2e08b9a4d7596c0b97ebd7", size = 355639, upload-time = "2025-11-02T21:40:11.485Z" }, + { url = "https://files.pythonhosted.org/packages/a0/af/c93c0ae5ef824136e90ac7ddf6cceccb1232f34240b2f55a922f874da9b4/bitarray-3.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:33af25c4ff7723363cb8404dfc2eefeab4110b654f6c98d26aba8a08c745d860", size = 336999, upload-time = "2025-11-02T21:40:12.709Z" }, + { url = "https://files.pythonhosted.org/packages/81/0f/72c951f5997b2876355d5e671f78dd2362493254876675cf22dbd24389ae/bitarray-3.8.0-cp314-cp314-win32.whl", hash = "sha256:2c3bb96b6026643ce24677650889b09073f60b9860a71765f843c99f9ab38b25", size = 142169, upload-time = "2025-11-02T21:40:14.031Z" }, + { url = "https://files.pythonhosted.org/packages/8a/55/ef1b4de8107bf13823da8756c20e1fbc9452228b4e837f46f6d9ddba3eb3/bitarray-3.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:847c7f61964225fc489fe1d49eda7e0e0d253e98862c012cecf845f9ad45cdf4", size = 148737, upload-time = "2025-11-02T21:40:15.436Z" }, + { url = "https://files.pythonhosted.org/packages/5f/26/bc0784136775024ac56cc67c0d6f9aa77a7770de7f82c3a7c9be11c217cd/bitarray-3.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:a2cb35a6efaa0e3623d8272471371a12c7e07b51a33e5efce9b58f655d864b4e", size = 146083, upload-time = "2025-11-02T21:40:17.135Z" }, + { url = "https://files.pythonhosted.org/packages/6e/64/57984e64264bf43d93a1809e645972771566a2d0345f4896b041ce20b000/bitarray-3.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:15e8d0597cc6e8496de6f4dea2a6880c57e1251502a7072f5631108a1aa28521", size = 149455, upload-time = "2025-11-02T21:40:18.558Z" }, + { url = "https://files.pythonhosted.org/packages/81/c0/0d5f2eaef1867f462f764bdb07d1e116c33a1bf052ea21889aefe4282f5b/bitarray-3.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8ffe660e963ae711cb9e2b8d8461c9b1ad6167823837fc17d59d5e539fb898fa", size = 146491, upload-time = "2025-11-02T21:40:19.665Z" }, + { url = "https://files.pythonhosted.org/packages/65/c6/bc1261f7a8862c0c59220a484464739e52235fd1e2afcb24d7f7d3fb5702/bitarray-3.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4779f356083c62e29b4198d290b7b17a39a69702d150678b7efff0fdddf494a8", size = 339721, upload-time = "2025-11-02T21:40:21.277Z" }, + { url = "https://files.pythonhosted.org/packages/81/d8/289ca55dd2939ea17b1108dc53bffc0fdc5160ba44f77502dfaae35d08c6/bitarray-3.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:025d133bf4ca8cf75f904eeb8ea946228d7c043231866143f31946a6f4dd0bf3", size = 367823, upload-time = "2025-11-02T21:40:22.463Z" }, + { url = "https://files.pythonhosted.org/packages/91/a2/61e7461ca9ac0fcb70f327a2e84b006996d2a840898e69037a39c87c6d06/bitarray-3.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:451f9958850ea98440d542278368c8d1e1ea821e2494b204570ba34a340759df", size = 377341, upload-time = "2025-11-02T21:40:23.789Z" }, + { url = "https://files.pythonhosted.org/packages/6c/87/4a0c9c8bdb13916d443e04d8f8542eef9190f31425da3c17c3478c40173f/bitarray-3.8.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6d79f659965290af60d6acc8e2716341865fe74609a7ede2a33c2f86ad893b8f", size = 344985, upload-time = "2025-11-02T21:40:25.261Z" }, + { url = "https://files.pythonhosted.org/packages/17/4c/ff9259b916efe53695b631772e5213699c738efc2471b5ffe273f4000994/bitarray-3.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fbf05678c2ae0064fb1b8de7e9e8f0fc30621b73c8477786dd0fb3868044a8c8", size = 336796, upload-time = "2025-11-02T21:40:26.942Z" }, + { url = "https://files.pythonhosted.org/packages/0f/4b/51b2468bbddbade5e2f3b8d5db08282c5b309e8687b0f02f75a8b5ff559c/bitarray-3.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:c396358023b876cff547ce87f4e8ff8a2280598873a137e8cc69e115262260b8", size = 365085, upload-time = "2025-11-02T21:40:28.224Z" }, + { url = "https://files.pythonhosted.org/packages/bf/79/53473bfc2e052c6dbb628cdc1b156be621c77aaeb715918358b01574be55/bitarray-3.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:ed3493a369fe849cce98542d7405c88030b355e4d2e113887cb7ecc86c205773", size = 361012, upload-time = "2025-11-02T21:40:29.635Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b1/242bf2e44bfc69e73fa2b954b425d761a8e632f78ea31008f1c3cfad0854/bitarray-3.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c764fb167411d5afaef88138542a4bfa28bd5e5ded5e8e42df87cef965efd6e9", size = 340644, upload-time = "2025-11-02T21:40:31.089Z" }, + { url = "https://files.pythonhosted.org/packages/cf/01/12e5ecf30a5de28a32485f226cad4b8a546845f65f755ce0365057ab1e92/bitarray-3.8.0-cp314-cp314t-win32.whl", hash = "sha256:e12769d3adcc419e65860de946df8d2ed274932177ac1cdb05186e498aaa9149", size = 143630, upload-time = "2025-11-02T21:40:32.351Z" }, + { url = "https://files.pythonhosted.org/packages/b6/92/6b6ade587b08024a8a890b07724775d29da9cf7497be5c3cbe226185e463/bitarray-3.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0ca70ccf789446a6dfde40b482ec21d28067172cd1f8efd50d5548159fccad9e", size = 150250, upload-time = "2025-11-02T21:40:33.596Z" }, + { url = "https://files.pythonhosted.org/packages/ed/40/be3858ffed004e47e48a2cefecdbf9b950d41098b780f9dc3aa609a88351/bitarray-3.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2a3d1b05ffdd3e95687942ae7b13c63689f85d3f15c39b33329e3cb9ce6c015f", size = 147015, upload-time = "2025-11-02T21:40:35.064Z" }, +] + +[[package]] +name = "black" +version = "25.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "pytokens" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8c/ad/33adf4708633d047950ff2dfdea2e215d84ac50ef95aff14a614e4b6e9b2/black-25.11.0.tar.gz", hash = "sha256:9a323ac32f5dc75ce7470501b887250be5005a01602e931a15e45593f70f6e08", size = 655669, upload-time = "2025-11-10T01:53:50.558Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/12/5c35e600b515f35ffd737da7febdb2ab66bb8c24d88560d5e3ef3d28c3fd/black-25.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:80e7486ad3535636657aa180ad32a7d67d7c273a80e12f1b4bfa0823d54e8fac", size = 1772831, upload-time = "2025-11-10T02:03:47Z" }, + { url = "https://files.pythonhosted.org/packages/1a/75/b3896bec5a2bb9ed2f989a970ea40e7062f8936f95425879bbe162746fe5/black-25.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6cced12b747c4c76bc09b4db057c319d8545307266f41aaee665540bc0e04e96", size = 1608520, upload-time = "2025-11-10T01:58:46.895Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b5/2bfc18330eddbcfb5aab8d2d720663cd410f51b2ed01375f5be3751595b0/black-25.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cb2d54a39e0ef021d6c5eef442e10fd71fcb491be6413d083a320ee768329dd", size = 1682719, upload-time = "2025-11-10T01:56:55.24Z" }, + { url = "https://files.pythonhosted.org/packages/96/fb/f7dc2793a22cdf74a72114b5ed77fe3349a2e09ef34565857a2f917abdf2/black-25.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae263af2f496940438e5be1a0c1020e13b09154f3af4df0835ea7f9fe7bfa409", size = 1362684, upload-time = "2025-11-10T01:57:07.639Z" }, + { url = "https://files.pythonhosted.org/packages/ad/47/3378d6a2ddefe18553d1115e36aea98f4a90de53b6a3017ed861ba1bd3bc/black-25.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0a1d40348b6621cc20d3d7530a5b8d67e9714906dfd7346338249ad9c6cedf2b", size = 1772446, upload-time = "2025-11-10T02:02:16.181Z" }, + { url = "https://files.pythonhosted.org/packages/ba/4b/0f00bfb3d1f7e05e25bfc7c363f54dc523bb6ba502f98f4ad3acf01ab2e4/black-25.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:51c65d7d60bb25429ea2bf0731c32b2a2442eb4bd3b2afcb47830f0b13e58bfd", size = 1607983, upload-time = "2025-11-10T02:02:52.502Z" }, + { url = "https://files.pythonhosted.org/packages/99/fe/49b0768f8c9ae57eb74cc10a1f87b4c70453551d8ad498959721cc345cb7/black-25.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:936c4dd07669269f40b497440159a221ee435e3fddcf668e0c05244a9be71993", size = 1682481, upload-time = "2025-11-10T01:57:12.35Z" }, + { url = "https://files.pythonhosted.org/packages/55/17/7e10ff1267bfa950cc16f0a411d457cdff79678fbb77a6c73b73a5317904/black-25.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:f42c0ea7f59994490f4dccd64e6b2dd49ac57c7c84f38b8faab50f8759db245c", size = 1363869, upload-time = "2025-11-10T01:58:24.608Z" }, + { url = "https://files.pythonhosted.org/packages/67/c0/cc865ce594d09e4cd4dfca5e11994ebb51604328489f3ca3ae7bb38a7db5/black-25.11.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:35690a383f22dd3e468c85dc4b915217f87667ad9cce781d7b42678ce63c4170", size = 1771358, upload-time = "2025-11-10T02:03:33.331Z" }, + { url = "https://files.pythonhosted.org/packages/37/77/4297114d9e2fd2fc8ab0ab87192643cd49409eb059e2940391e7d2340e57/black-25.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dae49ef7369c6caa1a1833fd5efb7c3024bb7e4499bf64833f65ad27791b1545", size = 1612902, upload-time = "2025-11-10T01:59:33.382Z" }, + { url = "https://files.pythonhosted.org/packages/de/63/d45ef97ada84111e330b2b2d45e1dd163e90bd116f00ac55927fb6bf8adb/black-25.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bd4a22a0b37401c8e492e994bce79e614f91b14d9ea911f44f36e262195fdda", size = 1680571, upload-time = "2025-11-10T01:57:04.239Z" }, + { url = "https://files.pythonhosted.org/packages/ff/4b/5604710d61cdff613584028b4cb4607e56e148801ed9b38ee7970799dab6/black-25.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:aa211411e94fdf86519996b7f5f05e71ba34835d8f0c0f03c00a26271da02664", size = 1382599, upload-time = "2025-11-10T01:57:57.427Z" }, + { url = "https://files.pythonhosted.org/packages/00/5d/aed32636ed30a6e7f9efd6ad14e2a0b0d687ae7c8c7ec4e4a557174b895c/black-25.11.0-py3-none-any.whl", hash = "sha256:e3f562da087791e96cefcd9dda058380a442ab322a02e222add53736451f604b", size = 204918, upload-time = "2025-11-10T01:53:48.917Z" }, +] + +[[package]] +name = "certifi" +version = "2025.11.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/8c/58f469717fa48465e4a50c014a0400602d3c437d7c0c468e17ada824da3a/certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316", size = 160538, upload-time = "2025-11-12T02:54:51.517Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, + { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, + { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, + { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, + { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, + { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, + { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, + { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, + { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, + { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, + { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, + { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, + { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, + { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, + { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, + { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +] + +[[package]] +name = "ckzg" +version = "2.1.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/e8/b262fff67d6bcaecd19c71d19ebea9184a1204e00368664e1544a2511bd8/ckzg-2.1.5.tar.gz", hash = "sha256:e48e092f9b89ebb6aaa195de2e2bb72ad2d4b35c87d3a15e4545f13c51fbbe30", size = 1123745, upload-time = "2025-09-30T19:09:13.391Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dd/9f/3ef8acd201e4d098af6bc368991ac1469a5390399abd1e78307fffb65218/ckzg-2.1.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:edead535bd9afef27b8650bba09659debd4f52638aee5ec1ab7d2c9d7e86953c", size = 116333, upload-time = "2025-09-30T19:07:53.223Z" }, + { url = "https://files.pythonhosted.org/packages/25/c2/202947c143336185180216a4939296d824cbffca4e1438d0fe696daf1904/ckzg-2.1.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc78622855de3d47767cdeecfdf58fd58911f43a0fa783524e414b7e75149020", size = 99822, upload-time = "2025-09-30T19:07:54.06Z" }, + { url = "https://files.pythonhosted.org/packages/0e/45/d720181bc2445340b9108a55c9e91a23a10e4eeb6c091588e550b0a28a54/ckzg-2.1.5-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:e5639064b0dd147b73f2ce2c2506844b0c625b232396ac852dc52eced04bd529", size = 180441, upload-time = "2025-11-06T21:05:34.937Z" }, + { url = "https://files.pythonhosted.org/packages/ad/91/467ff00f3ec3d97d14b9e31789904107a907dca7526eb003e218be8038d1/ckzg-2.1.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0864813902b96cde171e65334ce8d13c5ff5b6855f2e71a2272ae268fa07e8", size = 166199, upload-time = "2025-11-06T21:05:36.497Z" }, + { url = "https://files.pythonhosted.org/packages/c4/8b/1148f4edbd252386e59d8c73670caa3138991292656cf84bb584ebb0e113/ckzg-2.1.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e6f13f673a24c01e681eb66aed8f8e4ce191f009dd2149f3e1b9ad0dd59b4cd", size = 175829, upload-time = "2025-11-06T21:05:37.971Z" }, + { url = "https://files.pythonhosted.org/packages/ac/20/ace67811fbabcfece937f8286cdd96f5668757b8944a74630b6454131545/ckzg-2.1.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:094add5f197a3d278924ec1480d258f3b8b0e9f8851ae409eec83a21a738bffe", size = 176595, upload-time = "2025-09-30T19:07:54.792Z" }, + { url = "https://files.pythonhosted.org/packages/f1/65/127fa59aae21688887249ec1caa92dabaced331de5cb4e0224216270c3d0/ckzg-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b4b05f798784400e8c4dedaf1a1d57bbbc54de790855855add876fff3c9f629", size = 162014, upload-time = "2025-09-30T19:07:55.776Z" }, + { url = "https://files.pythonhosted.org/packages/35/de/dcaa260f6f5aca83eb9017ea0c691d3d37458e08e24dcad5efcd348d807e/ckzg-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64aef50a1cf599041b9af018bc885a3fad6a20bbaf443fc45f0457cb47914610", size = 171396, upload-time = "2025-09-30T19:07:56.583Z" }, + { url = "https://files.pythonhosted.org/packages/c4/72/f87db164d687759ae0666a2188c5f5d11a62cac9093464efbedc1f69f4e1/ckzg-2.1.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0171484eedc42b9417a79e33aff3f35d48915b01c54f42c829b891947ac06551", size = 173548, upload-time = "2025-09-30T19:07:58.555Z" }, + { url = "https://files.pythonhosted.org/packages/03/ad/b5a88a445f27dbd39eece56edffbe986bf356003bded75f79ef59e2b37c9/ckzg-2.1.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2342b98acd7b6e6e33fbbc48ccec9093e1652461daf4353115adcd708498efcd", size = 188988, upload-time = "2025-09-30T19:07:59.496Z" }, + { url = "https://files.pythonhosted.org/packages/6e/57/42fbf29d39bd3f11a673a4e61af41b5485aa0ecf99473a0d4afc2528d24b/ckzg-2.1.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cbce75c1e17fa60b5c33bae5069b8533cf5a4d028ef7d1f755b14a16f72307cf", size = 183513, upload-time = "2025-09-30T19:08:00.341Z" }, + { url = "https://files.pythonhosted.org/packages/27/c0/ef4c9e9256088e5a425cedb80f26e2a0c853128571b027d8174caf97b2f6/ckzg-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:827be2aeffc8a10bfb39b8dad45def82164dfcde735818c4053f5064474ae1b4", size = 100992, upload-time = "2025-09-30T19:08:01.633Z" }, + { url = "https://files.pythonhosted.org/packages/ba/4b/089392b6f0015bb368b453f26330c643bf0087f77835df2328a1da2af401/ckzg-2.1.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d955f4e18bb9a9b3a6f55114052edd41650c29edd5f81e417c8f01abace8207", size = 116340, upload-time = "2025-09-30T19:08:02.478Z" }, + { url = "https://files.pythonhosted.org/packages/bb/45/4d8b70f69f0bc67e9262ec68200707d2d92a27e712cda2c163ebd4b4dcfa/ckzg-2.1.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0c0961a685761196264aa49b1cf06e8a2b2add4d57987853d7dd7a7240dc5de7", size = 99822, upload-time = "2025-09-30T19:08:03.65Z" }, + { url = "https://files.pythonhosted.org/packages/49/f0/1e03c6a491899264117a5a80670a26a569f9eeb67c723157891141d1646f/ckzg-2.1.5-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:026ef3bba0637032c21f6bdb8e92aefeae7c67003bf631a4ee80c515a36a9dbd", size = 180443, upload-time = "2025-11-06T21:05:39.2Z" }, + { url = "https://files.pythonhosted.org/packages/60/f2/b85b5e5fee12d4ea13060066e9b50260f747a0a5db23634dc199e742894f/ckzg-2.1.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf031139a86e4ff00a717f9539331ef148ae9013b58848f2a7ac14596d812915", size = 166248, upload-time = "2025-11-06T21:05:40.384Z" }, + { url = "https://files.pythonhosted.org/packages/1c/41/07c5c7471d70d9cc49f2ce5013bb174529f2184611478d176c88c2fa048f/ckzg-2.1.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f51339d58541ae450c78a509b32822eec643595d8b96949fb1963fba802dc78b", size = 175870, upload-time = "2025-11-06T21:05:41.495Z" }, + { url = "https://files.pythonhosted.org/packages/c4/95/4193e4af65dc4839fa9fe07efad689fe726303b3ba62ee2f46c403458bec/ckzg-2.1.5-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:badb1c7dc6b932bed2c3f7695e1ce3e4bcc9601706136957408ac2bde5dd0892", size = 176586, upload-time = "2025-09-30T19:08:04.818Z" }, + { url = "https://files.pythonhosted.org/packages/7d/9e/850f48cb41685f5016028dbde8f7846ce9c56bfdc2e9e0f3df1a975263fe/ckzg-2.1.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58d92816b9babaee87bd9f23be10c07d5d07c709be184aa7ea08ddb2bcf2541c", size = 161970, upload-time = "2025-09-30T19:08:05.734Z" }, + { url = "https://files.pythonhosted.org/packages/ca/df/a9993dc124e95eb30059c108efd83a1504709cf069d3bee0745d450262a0/ckzg-2.1.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cf39f9abe8b3f1a71188fb601a8589672ee40eb0671fc36d8cdf4e78f00f43f", size = 171364, upload-time = "2025-09-30T19:08:06.979Z" }, + { url = "https://files.pythonhosted.org/packages/f9/03/78e8a723c1b832766e5698f7b39cc8dc27da95b62bc5c738a59564cb5f2c/ckzg-2.1.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:999df675674d8d31528fd9b9afd548e86decc86447f5555b451237e7953fd63f", size = 173571, upload-time = "2025-09-30T19:08:08.173Z" }, + { url = "https://files.pythonhosted.org/packages/e3/64/27f96201c6d78fbdb9a0812cf45dded974c4d03d876dac11d9c764ef858f/ckzg-2.1.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c39a1c7b32ac345cc44046076fd069ad6b7e6f7bef230ef9be414c712c4453b8", size = 189014, upload-time = "2025-09-30T19:08:09.045Z" }, + { url = "https://files.pythonhosted.org/packages/d2/6e/82177c4530265694f7ec151821c79351a07706dda4d8b23e8b37d0c122f0/ckzg-2.1.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4564765b0cc65929eca057241b9c030afac1dbae015f129cb60ca6abd6ff620", size = 183530, upload-time = "2025-09-30T19:08:09.867Z" }, + { url = "https://files.pythonhosted.org/packages/4d/41/1edfbd007b0398321defeedf6ad2d9f86a73f6a99d5ca4b4944bf6f2d757/ckzg-2.1.5-cp313-cp313-win_amd64.whl", hash = "sha256:55013b36514b8176197655b929bc53f020aa51a144331720dead2efc3793ed85", size = 100992, upload-time = "2025-09-30T19:08:10.719Z" }, + { url = "https://files.pythonhosted.org/packages/8f/07/6ac017fc1593ea8059de1271825eab1f55d0a2f2127e811d5597cc0f328e/ckzg-2.1.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a0cab7deaed093898a92d3644d4ca8621b63cb49296833e2d8b3edac456656d5", size = 116524, upload-time = "2025-11-06T21:05:42.614Z" }, + { url = "https://files.pythonhosted.org/packages/cc/57/c08133d854dad59d1052ad11796a1c6326c87363049feb8848ee291e68ba/ckzg-2.1.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:caedc9eba3d28584be9b6051585f20745f6abfec0d0657cce3dd45edb7f28586", size = 99833, upload-time = "2025-11-06T21:05:43.647Z" }, + { url = "https://files.pythonhosted.org/packages/df/80/b07dc3a7581e202dd871a53d8ff65eb70beace3cd81f17e587c3bac64c42/ckzg-2.1.5-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:2f67e545d41ba960189b1011d078953311259674620c485e619c933494b88fd9", size = 180474, upload-time = "2025-11-06T21:05:44.734Z" }, + { url = "https://files.pythonhosted.org/packages/e2/38/eaa3d40cf5c886966cb32b987f45d6fe07fded3ec2a731b71ca320574849/ckzg-2.1.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6f65ff296033c259d0829093d2c55bb45651e001e0269b8b88d072fdc86ecc6", size = 166274, upload-time = "2025-11-06T21:05:45.882Z" }, + { url = "https://files.pythonhosted.org/packages/7f/74/a878da70ea299f75c0f279b01bfc46101893a1cc827ead5d5df661ff209a/ckzg-2.1.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d66d34ff33be94c8a1f0da86483cd5bfdc15842998f3654ed91b8fdbffa2a81", size = 175904, upload-time = "2025-11-06T21:05:47.039Z" }, + { url = "https://files.pythonhosted.org/packages/bb/6f/72029116643f22b70adeb622ead6137af5d504f74f064d08397e972648dc/ckzg-2.1.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:25cf954bae3e2b2db6fa5e811d9800f89199d3eb4fa906c96a1c03434d4893c9", size = 173641, upload-time = "2025-11-06T21:05:48.147Z" }, + { url = "https://files.pythonhosted.org/packages/3c/67/a618cb1a7b48a810d7dbeeec282ec4337d872111fbdaded2630c224e6566/ckzg-2.1.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:34d7128735e0bcfcac876bff47d0f85e674f1e24f99014e326ec266abed7a82c", size = 189020, upload-time = "2025-11-06T21:05:49.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/3b/417f0c9a8b40a2876c70384f19fe63289214a6f1480bc86e3a3beaf21b6b/ckzg-2.1.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1dec3efae8679f7b8e26263b8bb0d3061ef4c9c6fe395e55b71f8f0df90ca8a0", size = 183519, upload-time = "2025-11-06T21:05:50.542Z" }, + { url = "https://files.pythonhosted.org/packages/81/77/5b1c3d31adf65040e52e77f13e38e89707a2ac46e0ca0ecf881a68833944/ckzg-2.1.5-cp314-cp314-win_amd64.whl", hash = "sha256:ce37c0ee0effe55d4ceed1735a2d85a3556a86238f3c89b7b7d1ca4ce4e92358", size = 104038, upload-time = "2025-11-06T21:05:51.677Z" }, + { url = "https://files.pythonhosted.org/packages/d9/fc/5ebcd1d75513e270440f4517a7423c496c0d025bf730da12c7c8693932c9/ckzg-2.1.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:db804d27f4b08e3aea440cdc6558af4ceb8256b18ea2b83681d80cc654a4085b", size = 116740, upload-time = "2025-11-06T21:05:52.767Z" }, + { url = "https://files.pythonhosted.org/packages/ad/2e/b661f589b8cdc586304c7a88cc58d48ca34a28200659e1222ffec8a58994/ckzg-2.1.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d472e3beeb95a110275b4d27e51d1c2b26ab99ddb91ac1c5587d710080c39c5e", size = 100101, upload-time = "2025-11-06T21:05:54.007Z" }, + { url = "https://files.pythonhosted.org/packages/34/3f/88544854ca9623433aba919d85db5f2a3c190922eb7e96bf151b35273c79/ckzg-2.1.5-cp314-cp314t-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:4b44a018124a79138fab8fde25221083574c181c324519be51eab09b1e43ae27", size = 183321, upload-time = "2025-11-06T21:05:55.085Z" }, + { url = "https://files.pythonhosted.org/packages/0a/11/b9dd3ea012bd215d2aff8e49953e8fe57e62c962eb1e2717663fab5bdc6a/ckzg-2.1.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a91d7b444300cf8ecae4f55983726630530cdde15cab92023026230a30d094e", size = 169404, upload-time = "2025-11-06T21:05:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/cf/cf/d695acc82fc7386b65833b2bcfe5b312070f9eb58ae7c5bdfcad7f8e460d/ckzg-2.1.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8674c64efbf2a12edf6d776061847bbe182997737e7690a69af932ce61a9c2a", size = 178676, upload-time = "2025-11-06T21:05:57.528Z" }, + { url = "https://files.pythonhosted.org/packages/82/35/9319f1d8a8aa2ae9a7779bf6d49a46e6e2af481178eaabbca1ea9d8f9072/ckzg-2.1.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:4290aa17c6402c98f16017fd6ee0bff8aeb5c97be5c3cee7c72aea1b7d176f3a", size = 176309, upload-time = "2025-11-06T21:05:59.047Z" }, + { url = "https://files.pythonhosted.org/packages/b9/24/e28206e43160f411d3ae53f2e557c1905af2928854f7ce4a1be1af893915/ckzg-2.1.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a0f82b8958ea97df12e29094f0a672cbe7532399724ea61b2399545991ed6017", size = 191777, upload-time = "2025-11-06T21:06:00.456Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ae/51b4e2575d1b4ab76433c6ef56d4dfc1bad38c2f7ffb33353e271c4e4d05/ckzg-2.1.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:22300bf0d717a083c388de5cfafec08443c9938b3abde2e89f9d5d1fffde1c51", size = 186138, upload-time = "2025-11-06T21:06:01.684Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6e/8ea848be3043b6bf9a7761492719a8c2d2c17a3da7b9551be7ec88a52c01/ckzg-2.1.5-cp314-cp314t-win_amd64.whl", hash = "sha256:aa8228206c3e3729fc117ca38e27588c079b0928a5ab628ee4d9fccaa2b8467d", size = 104191, upload-time = "2025-11-06T21:06:03.188Z" }, +] + +[[package]] +name = "click" +version = "8.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", size = 276943, upload-time = "2025-09-18T17:32:23.696Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295, upload-time = "2025-09-18T17:32:22.42Z" }, +] + +[[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, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "cprotobuf" +version = "0.1.11" +source = { git = "https://github.com/yihuang/cprotobuf.git?branch=master#62d5870c6d89b12290d539fe5362e965db21ad61" } +dependencies = [ + { name = "cython" }, +] + +[[package]] +name = "cython" +version = "3.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/36/cce2972e13e83ffe58bc73bfd9d37340b5e5113e8243841a57511c7ae1c2/cython-3.2.1.tar.gz", hash = "sha256:2be1e4d0cbdf7f4cd4d9b8284a034e1989b59fd060f6bd4d24bf3729394d2ed8", size = 3270455, upload-time = "2025-11-12T19:02:59.847Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/0e/19d5041b87f98ed19c94c388607cd27c1f7458078c3bad5de2dead55b2e1/cython-3.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ea5097d97afd2ab14e98637b7033eba5146de29a5dedf89f5e946076396ab891", size = 2966736, upload-time = "2025-11-12T19:03:25.064Z" }, + { url = "https://files.pythonhosted.org/packages/84/b8/bcc36d9d2464348106984956608a52a42a01ab44ea64031207dffdebc078/cython-3.2.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4bf12de0475bb6a21e2336a4a04dc4a2b4dd0507a2a3c703e045f3484266605", size = 3221633, upload-time = "2025-11-12T19:03:26.754Z" }, + { url = "https://files.pythonhosted.org/packages/79/20/7d4807fe4ebcef9f20f2e5f93312d0f5d02f9f76524fd4e37706d04e83f7/cython-3.2.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18c64a0f69a1b8164de70ec7efc72250c589fec21519170de21582300f6aaed9", size = 3389542, upload-time = "2025-11-12T19:03:28.656Z" }, + { url = "https://files.pythonhosted.org/packages/2a/92/b06ba6721299293bc41e89732070132c453bdbaaeabb8f8cc76851b75345/cython-3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:5ba14907d5826d8010e82306ce279a0d3650f5b50a4813c80836a17b2213c520", size = 2755307, upload-time = "2025-11-12T19:03:30.684Z" }, + { url = "https://files.pythonhosted.org/packages/40/28/c6e36c214baeb27ae45b518552e74457536c7c964b1a55b5900b047fa467/cython-3.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b4e850fc7a2f72d19679dd083fe4d20bf66860fceabb4f3207112f240249d708", size = 2957307, upload-time = "2025-11-12T19:03:32.471Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c8/b0b9ba64f81f2875c42aab5c0979d6454cd1ac6b3c1e2373ad552701565d/cython-3.2.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d20ca4afe993f7dccad3aeddbf4c3536cb0fd3ad6dc7a225935a666a5655af2", size = 3210919, upload-time = "2025-11-12T19:03:34.274Z" }, + { url = "https://files.pythonhosted.org/packages/f9/33/5d9ca6abba0e77e1851b843dd1b3c4095fbc6373166935e83c4414f80e88/cython-3.2.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5a54a757d01ca6a260b02ce5baf17d9db1c2253566ab5844ee4966ff2a69c19", size = 3373350, upload-time = "2025-11-12T19:03:35.927Z" }, + { url = "https://files.pythonhosted.org/packages/e4/29/4408c3486ff380a2d6ae0d4b71da5195efcef3c4360017113ee7d1cb7335/cython-3.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:1b81e56584727a328e00d91c164f8f0f2c59b02bf6857c3f000cd830fa571453", size = 2753425, upload-time = "2025-11-12T19:03:38.157Z" }, + { url = "https://files.pythonhosted.org/packages/f0/32/c1aa03ccadda89487ff31b90d8651c3706ce2744bf4f2c2ae213147e89bd/cython-3.2.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7af6ad01c0fe1965d1d3badaeb6df53c1f37383ebae1ccb405b73f628f87713", size = 2967833, upload-time = "2025-11-12T19:03:40.233Z" }, + { url = "https://files.pythonhosted.org/packages/ff/dc/3488d3ade0635408a2ebb05561a3009e2f54616bfefd1f107088dfeb2c4c/cython-3.2.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3ea7cd085b62acb67c0fbde5cd17a7d9e47992c965e81ec977cf9ea7c59cd65", size = 3256237, upload-time = "2025-11-12T19:03:42.005Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ba/f3d35d3803c9a424fa8812893847114deb9e2440c1bc67a31ab9ec4b9355/cython-3.2.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:986aea38fdf231e78d73745f83271c5654852c822dc5141a1d3fba64429a6aa6", size = 3383100, upload-time = "2025-11-12T19:03:43.675Z" }, + { url = "https://files.pythonhosted.org/packages/86/dc/d72dbb2f8e7ca95d2d18fd86f32b2e385996576230e7ecddd7d250786825/cython-3.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:4960e26cd34c1385f21646339f2e0361fcdd2ed3c01cdb50fe734add577ec56a", size = 2790322, upload-time = "2025-11-12T19:03:45.373Z" }, + { url = "https://files.pythonhosted.org/packages/5a/7e/1194f4ba98b981bbdca945a292e4f49e87ea09d69516b24445409e7cf611/cython-3.2.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:4e9167316bf6ecfea33dcca62f074605648fb93cc053ef46b5deb3e5d12fc0d3", size = 2872858, upload-time = "2025-11-12T19:03:55.074Z" }, + { url = "https://files.pythonhosted.org/packages/6b/1a/393ca8ffec7ad3f02b8e4bffaba3dba4fb62c4a1c4c0b6dbf3b80e709fe3/cython-3.2.1-cp39-abi3-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3095df6cd470064742f428c937bed7200c5123b9e19ee04aa09ec61281e565a3", size = 3209664, upload-time = "2025-11-12T19:03:56.771Z" }, + { url = "https://files.pythonhosted.org/packages/37/57/f209f64c609d3d8fac60a572e56da2f621dc1789e399c58db61d5645a31f/cython-3.2.1-cp39-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:db3f53b2d9afb206075a2605f1150aa019f0733c7795a38eccc6119c2e9c3f7b", size = 2854607, upload-time = "2025-11-12T19:03:59.413Z" }, + { url = "https://files.pythonhosted.org/packages/fc/af/1e5c73fe52423f40776130b0be914fd9f9f8dc26c4f6ea4c2ed04772d558/cython-3.2.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0fc5e7687ac8f8e2b2fb95648f43e9e074ebaa72fd5cb3d8e20e5f1e8b8e02d9", size = 2991567, upload-time = "2025-11-12T19:04:02.209Z" }, + { url = "https://files.pythonhosted.org/packages/39/2c/3ea175b6b1fdfb429f9e9c395240d894155b3c0615caced05fef43264cba/cython-3.2.1-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:bbb3bc152bc0de82b031c8d355418fa4890a92424209d59366c2c0bc9e6cf53c", size = 2889178, upload-time = "2025-11-12T19:04:05.272Z" }, + { url = "https://files.pythonhosted.org/packages/f1/88/b2ab22a3a3feac78c62354a823c5c0c33659909e9918f53aa05904532b4b/cython-3.2.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:a2022bc48ad0c2c0e0485bf0b54902913a3d81086b7d435f4437620c667799f6", size = 3223755, upload-time = "2025-11-12T19:04:07.262Z" }, + { url = "https://files.pythonhosted.org/packages/0b/56/9ba58629a03cbffb5965a3c65ccd91fa683d95d588c21a875da72fdc249b/cython-3.2.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:99fdd4ffc2dcb513f4be9ce71c6fedd895b96b1f814655b6bbab196df497b090", size = 3113456, upload-time = "2025-11-12T19:04:09.175Z" }, + { url = "https://files.pythonhosted.org/packages/56/5b/148c1a7ea5aebe460a70cad716a77e5fd0205be2de9fc5250491eb13ad8c/cython-3.2.1-cp39-abi3-win32.whl", hash = "sha256:06071f85bd5ce040464d43b2f9f287742a79f905e81b709fe904567230f1ed51", size = 2434223, upload-time = "2025-11-12T19:04:11.294Z" }, + { url = "https://files.pythonhosted.org/packages/7a/54/bb9b0c9db2a92a5e93747ca3027cfc645741411f8f1c6af2fb2a7b82df5d/cython-3.2.1-cp39-abi3-win_arm64.whl", hash = "sha256:e87c131d59480aee1ebac622b64f287c0e1d665ad1a1b7d498ac48accdb36c6b", size = 2439268, upload-time = "2025-11-12T19:04:12.931Z" }, + { url = "https://files.pythonhosted.org/packages/aa/30/373775b8d933d781d055c1dd0f110f275a101f320dab724c8c63a7c1b945/cython-3.2.1-py3-none-any.whl", hash = "sha256:cd72c46e7bffe8250c52d400e72c8d5d3086437b6aeec5b0eca99ccd337f5834", size = 1254219, upload-time = "2025-11-12T19:02:56.14Z" }, +] + +[[package]] +name = "cytoolz" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "toolz" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/d4/16916f3dc20a3f5455b63c35dcb260b3716f59ce27a93586804e70e431d5/cytoolz-1.1.0.tar.gz", hash = "sha256:13a7bf254c3c0d28b12e2290b82aed0f0977a4c2a2bf84854fcdc7796a29f3b0", size = 642510, upload-time = "2025-10-19T00:44:56.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/ec/01426224f7acf60183d3921b25e1a8e71713d3d39cb464d64ac7aace6ea6/cytoolz-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:99f8e134c9be11649342853ec8c90837af4089fc8ff1e8f9a024a57d1fa08514", size = 1327800, upload-time = "2025-10-19T00:40:48.674Z" }, + { url = "https://files.pythonhosted.org/packages/b4/07/e07e8fedd332ac9626ad58bea31416dda19bfd14310731fa38b16a97e15f/cytoolz-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0a6f44cf9319c30feb9a50aa513d777ef51efec16f31c404409e7deb8063df64", size = 997118, upload-time = "2025-10-19T00:40:50.919Z" }, + { url = "https://files.pythonhosted.org/packages/ab/72/c0f766d63ed2f9ea8dc8e1628d385d99b41fb834ce17ac3669e3f91e115d/cytoolz-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:945580dc158c557172fca899a35a99a16fbcebf6db0c77cb6621084bc82189f9", size = 991169, upload-time = "2025-10-19T00:40:52.887Z" }, + { url = "https://files.pythonhosted.org/packages/df/4b/1f757353d1bf33e56a7391ecc9bc49c1e529803b93a9d2f67fe5f92906fe/cytoolz-1.1.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:257905ec050d04f2f856854620d1e25556fd735064cebd81b460f54939b9f9d5", size = 2700680, upload-time = "2025-10-19T00:40:54.597Z" }, + { url = "https://files.pythonhosted.org/packages/25/73/9b25bb7ed8d419b9d6ff2ae0b3d06694de79a3f98f5169a1293ff7ad3a3f/cytoolz-1.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82779049f352fb3ab5e8c993ab45edbb6e02efb1f17f0b50f4972c706cc51d76", size = 2824951, upload-time = "2025-10-19T00:40:56.137Z" }, + { url = "https://files.pythonhosted.org/packages/0c/93/9c787f7c909e75670fff467f2504725d06d8c3f51d6dfe22c55a08c8ccd4/cytoolz-1.1.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7d3e405e435320e08c5a1633afaf285a392e2d9cef35c925d91e2a31dfd7a688", size = 2679635, upload-time = "2025-10-19T00:40:57.799Z" }, + { url = "https://files.pythonhosted.org/packages/50/aa/9ee92c302cccf7a41a7311b325b51ebeff25d36c1f82bdc1bbe3f58dc947/cytoolz-1.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:923df8f5591e0d20543060c29909c149ab1963a7267037b39eee03a83dbc50a8", size = 2938352, upload-time = "2025-10-19T00:40:59.49Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a3/3b58c5c1692c3bacd65640d0d5c7267a7ebb76204f7507aec29de7063d2f/cytoolz-1.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:25db9e4862f22ea0ae2e56c8bec9fc9fd756b655ae13e8c7b5625d7ed1c582d4", size = 3022121, upload-time = "2025-10-19T00:41:01.209Z" }, + { url = "https://files.pythonhosted.org/packages/e1/93/c647bc3334355088c57351a536c2d4a83dd45f7de591fab383975e45bff9/cytoolz-1.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7a98deb11ccd8e5d9f9441ef2ff3352aab52226a2b7d04756caaa53cd612363", size = 2857656, upload-time = "2025-10-19T00:41:03.456Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c2/43fea146bf4141deea959e19dcddf268c5ed759dec5c2ed4a6941d711933/cytoolz-1.1.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dce4ee9fc99104bc77efdea80f32ca5a650cd653bcc8a1d984a931153d3d9b58", size = 2551284, upload-time = "2025-10-19T00:41:05.347Z" }, + { url = "https://files.pythonhosted.org/packages/6f/df/cdc7a81ce5cfcde7ef523143d545635fc37e80ccacce140ae58483a21da3/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80d6da158f7d20c15819701bbda1c041f0944ede2f564f5c739b1bc80a9ffb8b", size = 2721673, upload-time = "2025-10-19T00:41:07.528Z" }, + { url = "https://files.pythonhosted.org/packages/45/be/f8524bb9ad8812ad375e61238dcaa3177628234d1b908ad0b74e3657cafd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3b5c5a192abda123ad45ef716ec9082b4cf7d95e9ada8291c5c2cc5558be858b", size = 2722884, upload-time = "2025-10-19T00:41:09.698Z" }, + { url = "https://files.pythonhosted.org/packages/23/e6/6bb8e4f9c267ad42d1ff77b6d2e4984665505afae50a216290e1d7311431/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5b399ce7d967b1cb6280250818b786be652aa8ddffd3c0bb5c48c6220d945ab5", size = 2685486, upload-time = "2025-10-19T00:41:11.349Z" }, + { url = "https://files.pythonhosted.org/packages/d7/dd/88619f9c8d2b682562c0c886bbb7c35720cb83fda2ac9a41bdd14073d9bd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e7e29a1a03f00b4322196cfe8e2c38da9a6c8d573566052c586df83aacc5663c", size = 2839661, upload-time = "2025-10-19T00:41:13.053Z" }, + { url = "https://files.pythonhosted.org/packages/b8/8d/4478ebf471ee78dd496d254dc0f4ad729cd8e6ba8257de4f0a98a2838ef2/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5291b117d71652a817ec164e7011f18e6a51f8a352cc9a70ed5b976c51102fda", size = 2547095, upload-time = "2025-10-19T00:41:16.054Z" }, + { url = "https://files.pythonhosted.org/packages/e6/68/f1dea33367b0b3f64e199c230a14a6b6f243c189020effafd31e970ca527/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8caef62f846a9011676c51bda9189ae394cdd6bb17f2946ecaedc23243268320", size = 2870901, upload-time = "2025-10-19T00:41:17.727Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9a/33591c09dfe799b8fb692cf2ad383e2c41ab6593cc960b00d1fc8a145655/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:de425c5a8e3be7bb3a195e19191d28d9eb3c2038046064a92edc4505033ec9cb", size = 2765422, upload-time = "2025-10-19T00:41:20.075Z" }, + { url = "https://files.pythonhosted.org/packages/60/2b/a8aa233c9416df87f004e57ae4280bd5e1f389b4943d179f01020c6ec629/cytoolz-1.1.0-cp312-cp312-win32.whl", hash = "sha256:296440a870e8d1f2e1d1edf98f60f1532b9d3ab8dfbd4b25ec08cd76311e79e5", size = 901933, upload-time = "2025-10-19T00:41:21.646Z" }, + { url = "https://files.pythonhosted.org/packages/ad/33/4c9bdf8390dc01d2617c7f11930697157164a52259b6818ddfa2f94f89f4/cytoolz-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:07156987f224c6dac59aa18fb8bf91e1412f5463961862716a3381bf429c8699", size = 947989, upload-time = "2025-10-19T00:41:23.288Z" }, + { url = "https://files.pythonhosted.org/packages/35/ac/6e2708835875f5acb52318462ed296bf94ed0cb8c7cb70e62fbd03f709e3/cytoolz-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:23e616b38f5b3160c7bb45b0f84a8f3deb4bd26b29fb2dfc716f241c738e27b8", size = 903913, upload-time = "2025-10-19T00:41:24.992Z" }, + { url = "https://files.pythonhosted.org/packages/71/4a/b3ddb3ee44fe0045e95dd973746f93f033b6f92cce1fc3cbbe24b329943c/cytoolz-1.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:76c9b58555300be6dde87a41faf1f97966d79b9a678b7a526fcff75d28ef4945", size = 976728, upload-time = "2025-10-19T00:41:26.5Z" }, + { url = "https://files.pythonhosted.org/packages/42/21/a3681434aa425875dd828bb515924b0f12c37a55c7d2bc5c0c5de3aeb0b4/cytoolz-1.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d1d638b10d3144795655e9395566ce35807df09219fd7cacd9e6acbdef67946a", size = 986057, upload-time = "2025-10-19T00:41:28.911Z" }, + { url = "https://files.pythonhosted.org/packages/d9/cb/efc1b29e211e0670a6953222afaac84dcbba5cb940b130c0e49858978040/cytoolz-1.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:26801c1a165e84786a99e03c9c9973356caaca002d66727b761fb1042878ef06", size = 992632, upload-time = "2025-10-19T00:41:30.612Z" }, + { url = "https://files.pythonhosted.org/packages/be/b0/e50621d21e939338c97faab651f58ea7fa32101226a91de79ecfb89d71e1/cytoolz-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2a9a464542912d3272f6dccc5142df057c71c6a5cbd30439389a732df401afb7", size = 1317534, upload-time = "2025-10-19T00:41:32.625Z" }, + { url = "https://files.pythonhosted.org/packages/0d/6b/25aa9739b0235a5bc4c1ea293186bc6822a4c6607acfe1422423287e7400/cytoolz-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ed6104fa942aa5784bf54f339563de637557e3443b105760bc4de8f16a7fc79b", size = 992336, upload-time = "2025-10-19T00:41:34.073Z" }, + { url = "https://files.pythonhosted.org/packages/e1/53/5f4deb0ff958805309d135d899c764364c1e8a632ce4994bd7c45fb98df2/cytoolz-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56161f0ab60dc4159ec343509abaf809dc88e85c7e420e354442c62e3e7cbb77", size = 986118, upload-time = "2025-10-19T00:41:35.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/e3/f6255b76c8cc0debbe1c0779130777dc0434da6d9b28a90d9f76f8cb67cd/cytoolz-1.1.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:832bd36cc9123535f1945acf6921f8a2a15acc19cfe4065b1c9b985a28671886", size = 2679563, upload-time = "2025-10-19T00:41:37.926Z" }, + { url = "https://files.pythonhosted.org/packages/59/8a/acc6e39a84e930522b965586ad3a36694f9bf247b23188ee0eb47b1c9ed1/cytoolz-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1842636b6e034f229bf084c2bcdcfd36c8437e752eefd2c74ce9e2f10415cb6e", size = 2813020, upload-time = "2025-10-19T00:41:39.935Z" }, + { url = "https://files.pythonhosted.org/packages/db/f5/0083608286ad1716eda7c41f868e85ac549f6fd6b7646993109fa0bdfd98/cytoolz-1.1.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:823df012ab90d2f2a0f92fea453528539bf71ac1879e518524cd0c86aa6df7b9", size = 2669312, upload-time = "2025-10-19T00:41:41.55Z" }, + { url = "https://files.pythonhosted.org/packages/47/a8/d16080b575520fe5da00cede1ece4e0a4180ec23f88dcdc6a2f5a90a7f7f/cytoolz-1.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f1fcf9e7e7b3487883ff3f815abc35b89dcc45c4cf81c72b7ee457aa72d197b", size = 2922147, upload-time = "2025-10-19T00:41:43.252Z" }, + { url = "https://files.pythonhosted.org/packages/7e/bc/716c9c1243701e58cad511eb3937fd550e645293c5ed1907639c5d66f194/cytoolz-1.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4cdb3fa1772116827f263f25b0cdd44c663b6701346a56411960534a06c082de", size = 2981602, upload-time = "2025-10-19T00:41:45.354Z" }, + { url = "https://files.pythonhosted.org/packages/14/bc/571b232996846b27f4ac0c957dc8bf60261e9b4d0d01c8d955e82329544e/cytoolz-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1b5c95041741b81430454db65183e133976f45ac3c03454cfa8147952568529", size = 2830103, upload-time = "2025-10-19T00:41:47.959Z" }, + { url = "https://files.pythonhosted.org/packages/5b/55/c594afb46ecd78e4b7e1fb92c947ed041807875661ceda73baaf61baba4f/cytoolz-1.1.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b2079fd9f1a65f4c61e6278c8a6d4f85edf30c606df8d5b32f1add88cbbe2286", size = 2533802, upload-time = "2025-10-19T00:41:49.683Z" }, + { url = "https://files.pythonhosted.org/packages/93/83/1edcf95832555a78fc43b975f3ebe8ceadcc9664dd47fd33747a14df5069/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a92a320d72bef1c7e2d4c6d875125cf57fc38be45feb3fac1bfa64ea401f54a4", size = 2706071, upload-time = "2025-10-19T00:41:51.386Z" }, + { url = "https://files.pythonhosted.org/packages/e2/df/035a408df87f25cfe3611557818b250126cd2281b2104cd88395de205583/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06d1c79aa51e6a92a90b0e456ebce2288f03dd6a76c7f582bfaa3eda7692e8a5", size = 2707575, upload-time = "2025-10-19T00:41:53.305Z" }, + { url = "https://files.pythonhosted.org/packages/7a/a4/ef78e13e16e93bf695a9331321d75fbc834a088d941f1c19e6b63314e257/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e1d7be25f6971e986a52b6d3a0da28e1941850985417c35528f6823aef2cfec5", size = 2660486, upload-time = "2025-10-19T00:41:55.542Z" }, + { url = "https://files.pythonhosted.org/packages/30/7a/2c3d60682b26058d435416c4e90d4a94db854de5be944dfd069ed1be648a/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:964b248edc31efc50a65e9eaa0c845718503823439d2fa5f8d2c7e974c2b5409", size = 2819605, upload-time = "2025-10-19T00:41:58.257Z" }, + { url = "https://files.pythonhosted.org/packages/45/92/19b722a1d83cc443fbc0c16e0dc376f8a451437890d3d9ee370358cf0709/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c9ff2b3c57c79b65cb5be14a18c6fd4a06d5036fb3f33e973a9f70e9ac13ca28", size = 2533559, upload-time = "2025-10-19T00:42:00.324Z" }, + { url = "https://files.pythonhosted.org/packages/1d/15/fa3b7891da51115204416f14192081d3dea0eaee091f123fdc1347de8dd1/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:22290b73086af600042d99f5ce52a43d4ad9872c382610413176e19fc1d4fd2d", size = 2839171, upload-time = "2025-10-19T00:42:01.881Z" }, + { url = "https://files.pythonhosted.org/packages/46/40/d3519d5cd86eebebf1e8b7174ec32dfb6ecec67b48b0cfb92bf226659b5a/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a2ade74fccd080ea793382968913ee38d7a35c921df435bbf0a6aeecf0d17574", size = 2743379, upload-time = "2025-10-19T00:42:03.809Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/a9e7511f0a13fdbefa5bf73cf8e4763878140de9453fd3e50d6ac57b6be7/cytoolz-1.1.0-cp313-cp313-win32.whl", hash = "sha256:db5dbcfda1c00e937426cbf9bdc63c24ebbc358c3263bfcbc1ab4a88dc52aa8e", size = 900844, upload-time = "2025-10-19T00:42:05.967Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a4/fb7eb403c6a4c81e5a30363f34a71adcc8bf5292dc8ea32e2440aa5668f2/cytoolz-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9e2d3fe3b45c3eb7233746f7aca37789be3dceec3e07dcc406d3e045ea0f7bdc", size = 946461, upload-time = "2025-10-19T00:42:07.983Z" }, + { url = "https://files.pythonhosted.org/packages/93/bb/1c8c33d353548d240bc6e8677ee8c3560ce5fa2f084e928facf7c35a6dcf/cytoolz-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:32c559f95ff44a9ebcbd934acaa1e6dc8f3e6ffce4762a79a88528064873d6d5", size = 902673, upload-time = "2025-10-19T00:42:09.982Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/4a53acc60f59030fcaf48c7766e3c4c81bd997379425aa45b129396557b5/cytoolz-1.1.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9e2cd93b28f667c5870a070ab2b8bb4397470a85c4b204f2454b0ad001cd1ca3", size = 1372336, upload-time = "2025-10-19T00:42:12.104Z" }, + { url = "https://files.pythonhosted.org/packages/ac/90/f28fd8ad8319d8f5c8da69a2c29b8cf52a6d2c0161602d92b366d58926ab/cytoolz-1.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f494124e141a9361f31d79875fe7ea459a3be2b9dadd90480427c0c52a0943d4", size = 1011930, upload-time = "2025-10-19T00:42:14.231Z" }, + { url = "https://files.pythonhosted.org/packages/c9/95/4561c4e0ad1c944f7673d6d916405d68080f10552cfc5d69a1cf2475a9a1/cytoolz-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:53a3262bf221f19437ed544bf8c0e1980c81ac8e2a53d87a9bc075dba943d36f", size = 1020610, upload-time = "2025-10-19T00:42:15.877Z" }, + { url = "https://files.pythonhosted.org/packages/c3/14/b2e1ffa4995ec36e1372e243411ff36325e4e6d7ffa34eb4098f5357d176/cytoolz-1.1.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:47663e57d3f3f124921f38055e86a1022d0844c444ede2e8f090d3bbf80deb65", size = 2917327, upload-time = "2025-10-19T00:42:17.706Z" }, + { url = "https://files.pythonhosted.org/packages/4a/29/7cab6c609b4514ac84cca2f7dca6c509977a8fc16d27c3a50e97f105fa6a/cytoolz-1.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5a8755c4104ee4e3d5ba434c543b5f85fdee6a1f1df33d93f518294da793a60", size = 3108951, upload-time = "2025-10-19T00:42:19.363Z" }, + { url = "https://files.pythonhosted.org/packages/9a/71/1d1103b819458679277206ad07d78ca6b31c4bb88d6463fd193e19bfb270/cytoolz-1.1.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4d96ff3d381423af1b105295f97de86d1db51732c9566eb37378bab6670c5010", size = 2807149, upload-time = "2025-10-19T00:42:20.964Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d4/3d83a05a21e7d2ed2b9e6daf489999c29934b005de9190272b8a2e3735d0/cytoolz-1.1.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0ec96b3d537cdf47d4e76ded199f7440715f4c71029b45445cff92c1248808c2", size = 3111608, upload-time = "2025-10-19T00:42:22.684Z" }, + { url = "https://files.pythonhosted.org/packages/51/88/96f68354c3d4af68de41f0db4fe41a23b96a50a4a416636cea325490cfeb/cytoolz-1.1.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:208e2f2ef90a32b0acbff3303d90d89b13570a228d491d2e622a7883a3c68148", size = 3179373, upload-time = "2025-10-19T00:42:24.395Z" }, + { url = "https://files.pythonhosted.org/packages/ce/50/ed87a5cd8e6f27ffbb64c39e9730e18ec66c37631db2888ae711909f10c9/cytoolz-1.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d416a81bb0bd517558668e49d30a7475b5445f9bbafaab7dcf066f1e9adba36", size = 3003120, upload-time = "2025-10-19T00:42:26.18Z" }, + { url = "https://files.pythonhosted.org/packages/d3/a7/acde155b050d6eaa8e9c7845c98fc5fb28501568e78e83ebbf44f8855274/cytoolz-1.1.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f32e94c91ffe49af04835ee713ebd8e005c85ebe83e7e1fdcc00f27164c2d636", size = 2703225, upload-time = "2025-10-19T00:42:27.93Z" }, + { url = "https://files.pythonhosted.org/packages/1b/b6/9d518597c5bdea626b61101e8d2ff94124787a42259dafd9f5fc396f346a/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15d0c6405efc040499c46df44056a5c382f551a7624a41cf3e4c84a96b988a15", size = 2956033, upload-time = "2025-10-19T00:42:29.993Z" }, + { url = "https://files.pythonhosted.org/packages/89/7a/93e5f860926165538c85e1c5e1670ad3424f158df810f8ccd269da652138/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:bf069c5381d757debae891401b88b3a346ba3a28ca45ba9251103b282463fad8", size = 2862950, upload-time = "2025-10-19T00:42:31.803Z" }, + { url = "https://files.pythonhosted.org/packages/76/e6/99d6af00487bedc27597b54c9fcbfd5c833a69c6b7a9b9f0fff777bfc7aa/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d5cf15892e63411ec1bd67deff0e84317d974e6ab2cdfefdd4a7cea2989df66", size = 2861757, upload-time = "2025-10-19T00:42:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/71/ca/adfa1fb7949478135a37755cb8e88c20cd6b75c22a05f1128f05f3ab2c60/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3e3872c21170f8341656f8692f8939e8800dcee6549ad2474d4c817bdefd62cd", size = 2979049, upload-time = "2025-10-19T00:42:35.377Z" }, + { url = "https://files.pythonhosted.org/packages/70/4c/7bf47a03a4497d500bc73d4204e2d907771a017fa4457741b2a1d7c09319/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b9ddeff8e8fd65eb1fcefa61018100b2b627e759ea6ad275d2e2a93ffac147bf", size = 2699492, upload-time = "2025-10-19T00:42:37.133Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e7/3d034b0e4817314f07aa465d5864e9b8df9d25cb260a53dd84583e491558/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:02feeeda93e1fa3b33414eb57c2b0aefd1db8f558dd33fdfcce664a0f86056e4", size = 2995646, upload-time = "2025-10-19T00:42:38.912Z" }, + { url = "https://files.pythonhosted.org/packages/c1/62/be357181c71648d9fe1d1ce91cd42c63457dcf3c158e144416fd51dced83/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d08154ad45349162b6c37f12d5d1b2e6eef338e657b85e1621e4e6a4a69d64cb", size = 2919481, upload-time = "2025-10-19T00:42:40.85Z" }, + { url = "https://files.pythonhosted.org/packages/62/d5/bf5434fde726c4f80cb99912b2d8e0afa1587557e2a2d7e0315eb942f2de/cytoolz-1.1.0-cp313-cp313t-win32.whl", hash = "sha256:10ae4718a056948d73ca3e1bb9ab1f95f897ec1e362f829b9d37cc29ab566c60", size = 951595, upload-time = "2025-10-19T00:42:42.877Z" }, + { url = "https://files.pythonhosted.org/packages/64/29/39c161e9204a9715321ddea698cbd0abc317e78522c7c642363c20589e71/cytoolz-1.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:1bb77bc6197e5cb19784b6a42bb0f8427e81737a630d9d7dda62ed31733f9e6c", size = 1004445, upload-time = "2025-10-19T00:42:44.855Z" }, + { url = "https://files.pythonhosted.org/packages/e2/5a/7cbff5e9a689f558cb0bdf277f9562b2ac51acf7cd15e055b8c3efb0e1ef/cytoolz-1.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:563dda652c6ff52d215704fbe6b491879b78d7bbbb3a9524ec8e763483cb459f", size = 926207, upload-time = "2025-10-19T00:42:46.456Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e8/297a85ba700f437c01eba962428e6ab4572f6c3e68e8ff442ce5c9d3a496/cytoolz-1.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d542cee7c7882d2a914a33dec4d3600416fb336734df979473249d4c53d207a1", size = 980613, upload-time = "2025-10-19T00:42:47.988Z" }, + { url = "https://files.pythonhosted.org/packages/e8/d7/2b02c9d18e9cc263a0e22690f78080809f1eafe72f26b29ccc115d3bf5c8/cytoolz-1.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31922849b701b0f24bb62e56eb2488dcd3aa6ae3057694bd6b3b7c4c2bc27c2f", size = 990476, upload-time = "2025-10-19T00:42:49.653Z" }, + { url = "https://files.pythonhosted.org/packages/89/26/b6b159d2929310fca0eff8a4989cd4b1ecbdf7c46fdff46c7a20fcae55c8/cytoolz-1.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e68308d32afd31943314735c1335e4ab5696110e96b405f6bdb8f2a8dc771a16", size = 992712, upload-time = "2025-10-19T00:42:51.306Z" }, + { url = "https://files.pythonhosted.org/packages/42/a0/f7c572aa151ed466b0fce4a327c3cc916d3ef3c82e341be59ea4b9bee9e4/cytoolz-1.1.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fc4bb48b3b866e1867f7c6411a4229e5b44be3989060663713e10efc24c9bd5f", size = 1322596, upload-time = "2025-10-19T00:42:52.978Z" }, + { url = "https://files.pythonhosted.org/packages/72/7c/a55d035e20b77b6725e85c8f1a418b3a4c23967288b8b0c2d1a40f158cbe/cytoolz-1.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:456f77207d1445025d7ef262b8370a05492dcb1490cb428b0f3bf1bd744a89b0", size = 992825, upload-time = "2025-10-19T00:42:55.026Z" }, + { url = "https://files.pythonhosted.org/packages/03/af/39d2d3db322136e12e9336a1f13bab51eab88b386bfb11f91d3faff8ba34/cytoolz-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:174ebc71ebb20a9baeffce6ee07ee2cd913754325c93f99d767380d8317930f7", size = 990525, upload-time = "2025-10-19T00:42:56.666Z" }, + { url = "https://files.pythonhosted.org/packages/a6/bd/65d7a869d307f9b10ad45c2c1cbb40b81a8d0ed1138fa17fd904f5c83298/cytoolz-1.1.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8b3604fef602bcd53415055a4f68468339192fd17be39e687ae24f476d23d56e", size = 2672409, upload-time = "2025-10-19T00:42:58.81Z" }, + { url = "https://files.pythonhosted.org/packages/2d/fb/74dfd844bfd67e810bd36e8e3903a143035447245828e7fcd7c81351d775/cytoolz-1.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3604b959a01f64c366e7d10ec7634d5f5cfe10301e27a8f090f6eb3b2a628a18", size = 2808477, upload-time = "2025-10-19T00:43:00.577Z" }, + { url = "https://files.pythonhosted.org/packages/d6/1f/587686c43e31c19241ec317da66438d093523921ea7749bbc65558a30df9/cytoolz-1.1.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6db2127a3c1bc2f59f08010d2ae53a760771a9de2f67423ad8d400e9ba4276e8", size = 2636881, upload-time = "2025-10-19T00:43:02.24Z" }, + { url = "https://files.pythonhosted.org/packages/bc/6d/90468cd34f77cb38a11af52c4dc6199efcc97a486395a21bef72e9b7602e/cytoolz-1.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56584745ac647993a016a21bc76399113b7595e312f8d0a1b140c9fcf9b58a27", size = 2937315, upload-time = "2025-10-19T00:43:03.954Z" }, + { url = "https://files.pythonhosted.org/packages/d9/50/7b92cd78c613b92e3509e6291d3fb7e0d72ebda999a8df806a96c40ca9ab/cytoolz-1.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db2c4c3a7f7bd7e03bb1a236a125c8feb86c75802f4ecda6ecfaf946610b2930", size = 2959988, upload-time = "2025-10-19T00:43:05.758Z" }, + { url = "https://files.pythonhosted.org/packages/44/d5/34b5a28a8d9bb329f984b4c2259407ca3f501d1abeb01bacea07937d85d1/cytoolz-1.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48cb8a692111a285d2b9acd16d185428176bfbffa8a7c274308525fccd01dd42", size = 2795116, upload-time = "2025-10-19T00:43:07.411Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d9/5dd829e33273ec03bdc3c812e6c3281987ae2c5c91645582f6c331544a64/cytoolz-1.1.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d2f344ba5eb17dcf38ee37fdde726f69053f54927db8f8a1bed6ac61e5b1890d", size = 2535390, upload-time = "2025-10-19T00:43:09.104Z" }, + { url = "https://files.pythonhosted.org/packages/87/1f/7f9c58068a8eec2183110df051bc6b69dd621143f84473eeb6dc1b32905a/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:abf76b1c1abd031f098f293b6d90ee08bdaa45f8b5678430e331d991b82684b1", size = 2704834, upload-time = "2025-10-19T00:43:10.942Z" }, + { url = "https://files.pythonhosted.org/packages/d2/90/667def5665333575d01a65fe3ec0ca31b897895f6e3bc1a42d6ea3659369/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ddf9a38a5b686091265ff45b53d142e44a538cd6c2e70610d3bc6be094219032", size = 2658441, upload-time = "2025-10-19T00:43:12.655Z" }, + { url = "https://files.pythonhosted.org/packages/23/79/6615f9a14960bd29ac98b823777b6589357833f65cf1a11b5abc1587c120/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:946786755274f07bb2be0400f28adb31d7d85a7c7001873c0a8e24a503428fb3", size = 2654766, upload-time = "2025-10-19T00:43:14.325Z" }, + { url = "https://files.pythonhosted.org/packages/b0/99/be59c6e0ae02153ef10ae1ff0f380fb19d973c651b50cf829a731f6c9e79/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:d5b8f78b9fed79cf185ad4ddec099abeef45951bdcb416c5835ba05f0a1242c7", size = 2827649, upload-time = "2025-10-19T00:43:16.132Z" }, + { url = "https://files.pythonhosted.org/packages/19/b7/854ddcf9f9618844108677c20d48f4611b5c636956adea0f0e85e027608f/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fccde6efefdbc02e676ccb352a2ccc8a8e929f59a1c6d3d60bb78e923a49ca44", size = 2533456, upload-time = "2025-10-19T00:43:17.764Z" }, + { url = "https://files.pythonhosted.org/packages/45/66/bfe6fbb2bdcf03c8377c8c2f542576e15f3340c905a09d78a6cb3badd39a/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:717b7775313da5f51b0fbf50d865aa9c39cb241bd4cb605df3cf2246d6567397", size = 2826455, upload-time = "2025-10-19T00:43:19.561Z" }, + { url = "https://files.pythonhosted.org/packages/c3/0c/cce4047bd927e95f59e73319c02c9bc86bd3d76392e0eb9e41a1147a479c/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5158744a09d0e0e4a4f82225e3a3c4ebf38f9ae74467aaa905467270e52f2794", size = 2714897, upload-time = "2025-10-19T00:43:21.291Z" }, + { url = "https://files.pythonhosted.org/packages/ac/9a/061323bb289b565802bad14fb7ab59fcd8713105df142bcf4dd9ff64f8ac/cytoolz-1.1.0-cp314-cp314-win32.whl", hash = "sha256:1ed534bdbbf063b2bb28fca7d0f6723a3e5a72b086e7c7fe6d74ae8c3e4d00e2", size = 901490, upload-time = "2025-10-19T00:43:22.895Z" }, + { url = "https://files.pythonhosted.org/packages/a3/20/1f3a733d710d2a25d6f10b463bef55ada52fe6392a5d233c8d770191f48a/cytoolz-1.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:472c1c9a085f5ad973ec0ad7f0b9ba0969faea6f96c9e397f6293d386f3a25ec", size = 946730, upload-time = "2025-10-19T00:43:24.838Z" }, + { url = "https://files.pythonhosted.org/packages/f2/22/2d657db4a5d1c10a152061800f812caba9ef20d7bd2406f51a5fd800c180/cytoolz-1.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:a7ad7ca3386fa86bd301be3fa36e7f0acb024f412f665937955acfc8eb42deff", size = 905722, upload-time = "2025-10-19T00:43:26.439Z" }, + { url = "https://files.pythonhosted.org/packages/19/97/b4a8c76796a9a8b9bc90c7992840fa1589a1af8e0426562dea4ce9b384a7/cytoolz-1.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:64b63ed4b71b1ba813300ad0f06b8aff19a12cf51116e0e4f1ed837cea4debcf", size = 1372606, upload-time = "2025-10-19T00:43:28.491Z" }, + { url = "https://files.pythonhosted.org/packages/08/d4/a1bb1a32b454a2d650db8374ff3bf875ba0fc1c36e6446ec02a83b9140a1/cytoolz-1.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a60ba6f2ed9eb0003a737e1ee1e9fa2258e749da6477946008d4324efa25149f", size = 1012189, upload-time = "2025-10-19T00:43:30.177Z" }, + { url = "https://files.pythonhosted.org/packages/21/4b/2f5cbbd81588918ee7dd70cffb66731608f578a9b72166aafa991071af7d/cytoolz-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1aa58e2434d732241f7f051e6f17657e969a89971025e24578b5cbc6f1346485", size = 1020624, upload-time = "2025-10-19T00:43:31.712Z" }, + { url = "https://files.pythonhosted.org/packages/f5/99/c4954dd86cd593cd776a038b36795a259b8b5c12cbab6363edf5f6d9c909/cytoolz-1.1.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6965af3fc7214645970e312deb9bd35a213a1eaabcfef4f39115e60bf2f76867", size = 2917016, upload-time = "2025-10-19T00:43:33.531Z" }, + { url = "https://files.pythonhosted.org/packages/b2/7c/f1f70a17e272b433232bc8a27df97e46b202d6cc07e3b0d63f7f41ba0f2d/cytoolz-1.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ddd2863f321d67527d3b67a93000a378ad6f967056f68c06467fe011278a6d0e", size = 3107634, upload-time = "2025-10-19T00:43:35.57Z" }, + { url = "https://files.pythonhosted.org/packages/8f/bd/c3226a57474b4aef1f90040510cba30d0decd3515fed48dc229b37c2f898/cytoolz-1.1.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4e6b428e9eb5126053c2ae0efa62512ff4b38ed3951f4d0888ca7005d63e56f5", size = 2806221, upload-time = "2025-10-19T00:43:37.707Z" }, + { url = "https://files.pythonhosted.org/packages/c3/47/2f7bfe4aaa1e07dc9828bea228ed744faf73b26aee0c1bdf3b5520bf1909/cytoolz-1.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d758e5ef311d2671e0ae8c214c52e44617cf1e58bef8f022b547b9802a5a7f30", size = 3107671, upload-time = "2025-10-19T00:43:39.401Z" }, + { url = "https://files.pythonhosted.org/packages/4d/12/6ff3b04fbd1369d0fcd5f8b5910ba6e427e33bf113754c4c35ec3f747924/cytoolz-1.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a95416eca473e6c1179b48d86adcf528b59c63ce78f4cb9934f2e413afa9b56b", size = 3176350, upload-time = "2025-10-19T00:43:41.148Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/6691d986b728e77b5d2872743ebcd962d37a2d0f7e9ad95a81b284fbf905/cytoolz-1.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36c8ede93525cf11e2cc787b7156e5cecd7340193ef800b816a16f1404a8dc6d", size = 3001173, upload-time = "2025-10-19T00:43:42.923Z" }, + { url = "https://files.pythonhosted.org/packages/7a/cb/f59d83a5058e1198db5a1f04e4a124c94d60390e4fa89b6d2e38ee8288a0/cytoolz-1.1.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c949755b6d8a649c5fbc888bc30915926f1b09fe42fea9f289e297c2f6ddd3", size = 2701374, upload-time = "2025-10-19T00:43:44.716Z" }, + { url = "https://files.pythonhosted.org/packages/b7/f0/1ae6d28df503b0bdae094879da2072b8ba13db5919cd3798918761578411/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e1b6d37545816905a76d9ed59fa4e332f929e879f062a39ea0f6f620405cdc27", size = 2953081, upload-time = "2025-10-19T00:43:47.103Z" }, + { url = "https://files.pythonhosted.org/packages/f4/06/d86fe811c6222dc32d3e08f5d88d2be598a6055b4d0590e7c1428d55c386/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:05332112d4087904842b36954cd1d3fc0e463a2f4a7ef9477bd241427c593c3b", size = 2862228, upload-time = "2025-10-19T00:43:49.353Z" }, + { url = "https://files.pythonhosted.org/packages/ae/32/978ef6f42623be44a0a03ae9de875ab54aa26c7e38c5c4cd505460b0927d/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:31538ca2fad2d688cbd962ccc3f1da847329e2258a52940f10a2ac0719e526be", size = 2861971, upload-time = "2025-10-19T00:43:51.028Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f7/74c69497e756b752b359925d1feef68b91df024a4124a823740f675dacd3/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:747562aa70abf219ea16f07d50ac0157db856d447f7f498f592e097cbc77df0b", size = 2975304, upload-time = "2025-10-19T00:43:52.99Z" }, + { url = "https://files.pythonhosted.org/packages/5b/2b/3ce0e6889a6491f3418ad4d84ae407b8456b02169a5a1f87990dbba7433b/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:3dc15c48b20c0f467e15e341e102896c8422dccf8efc6322def5c1b02f074629", size = 2697371, upload-time = "2025-10-19T00:43:55.312Z" }, + { url = "https://files.pythonhosted.org/packages/15/87/c616577f0891d97860643c845f7221e95240aa589586de727e28a5eb6e52/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3c03137ee6103ba92d5d6ad6a510e86fded69cd67050bd8a1843f15283be17ac", size = 2992436, upload-time = "2025-10-19T00:43:57.253Z" }, + { url = "https://files.pythonhosted.org/packages/e7/9f/490c81bffb3428ab1fa114051fbb5ba18aaa2e2fe4da5bf4170ca524e6b3/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:be8e298d88f88bd172b59912240558be3b7a04959375646e7fd4996401452941", size = 2917612, upload-time = "2025-10-19T00:43:59.423Z" }, + { url = "https://files.pythonhosted.org/packages/66/35/0fec2769660ca6472bbf3317ab634675827bb706d193e3240aaf20eab961/cytoolz-1.1.0-cp314-cp314t-win32.whl", hash = "sha256:3d407140f5604a89578285d4aac7b18b8eafa055cf776e781aabb89c48738fad", size = 960842, upload-time = "2025-10-19T00:44:01.143Z" }, + { url = "https://files.pythonhosted.org/packages/46/b4/b7ce3d3cd20337becfec978ecfa6d0ef64884d0cf32d44edfed8700914b9/cytoolz-1.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:56e5afb69eb6e1b3ffc34716ee5f92ffbdb5cb003b3a5ca4d4b0fe700e217162", size = 1020835, upload-time = "2025-10-19T00:44:03.246Z" }, + { url = "https://files.pythonhosted.org/packages/2c/1f/0498009aa563a9c5d04f520aadc6e1c0942434d089d0b2f51ea986470f55/cytoolz-1.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:27b19b4a286b3ff52040efa42dbe403730aebe5fdfd2def704eb285e2125c63e", size = 927963, upload-time = "2025-10-19T00:44:04.85Z" }, +] + +[[package]] +name = "docker" +version = "7.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "requests" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" }, +] + +[[package]] +name = "durations" +version = "0.3.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/18/d2cfee21f8cfa271efd498bbf1a2e49c26221ae15301855835d00a570fbc/durations-0.3.3.tar.gz", hash = "sha256:820ffe09c390469dc621b6a0aa46d3a624b6dadf09b439e175696b6f6b77ef2f", size = 3679, upload-time = "2014-01-10T09:40:18.041Z" } + +[[package]] +name = "eth-abi" +version = "5.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eth-typing" }, + { name = "eth-utils" }, + { name = "parsimonious" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/71/d9e1380bd77fd22f98b534699af564f189b56d539cc2b9dab908d4e4c242/eth_abi-5.2.0.tar.gz", hash = "sha256:178703fa98c07d8eecd5ae569e7e8d159e493ebb6eeb534a8fe973fbc4e40ef0", size = 49797, upload-time = "2025-01-14T16:29:34.629Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/b4/2f3982c4cbcbf5eeb6aec62df1533c0e63c653b3021ff338d44944405676/eth_abi-5.2.0-py3-none-any.whl", hash = "sha256:17abe47560ad753f18054f5b3089fcb588f3e3a092136a416b6c1502cb7e8877", size = 28511, upload-time = "2025-01-14T16:29:31.862Z" }, +] + +[[package]] +name = "eth-account" +version = "0.13.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bitarray" }, + { name = "ckzg" }, + { name = "eth-abi" }, + { name = "eth-keyfile" }, + { name = "eth-keys" }, + { name = "eth-rlp" }, + { name = "eth-utils" }, + { name = "hexbytes" }, + { name = "pydantic" }, + { name = "rlp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/cf/20f76a29be97339c969fd765f1237154286a565a1d61be98e76bb7af946a/eth_account-0.13.7.tar.gz", hash = "sha256:5853ecbcbb22e65411176f121f5f24b8afeeaf13492359d254b16d8b18c77a46", size = 935998, upload-time = "2025-04-21T21:11:21.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/18/088fb250018cbe665bc2111974301b2d59f294a565aff7564c4df6878da2/eth_account-0.13.7-py3-none-any.whl", hash = "sha256:39727de8c94d004ff61d10da7587509c04d2dc7eac71e04830135300bdfc6d24", size = 587452, upload-time = "2025-04-21T21:11:18.346Z" }, +] + +[[package]] +name = "eth-bloom" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eth-hash", extra = ["pycryptodome"] }, +] +sdist = { url = "https://files.pythonhosted.org/packages/89/d6/9c345601de27b536dc8b0f4c1d6cb84fe76a47de9ac02753f58deae59c86/eth_bloom-3.1.0.tar.gz", hash = "sha256:4bc918f6fde44334e92b23cfb345db961e2e3af620535cbc872444f7a143cb88", size = 9807, upload-time = "2025-01-08T19:05:18.945Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/e5/251bda1d3f3cff230fa39e95d41141c1b44e8f55c101c5f593ccf5a31b63/eth_bloom-3.1.0-py3-none-any.whl", hash = "sha256:c96b2dd6cafa407373bca1a9d74b650378ba672d5b17f2771bf7d3c3aaa7651c", size = 5785, upload-time = "2025-01-08T19:05:17.757Z" }, +] + +[[package]] +name = "eth-contract" +version = "0.3.0" +source = { git = "https://github.com/mmsqe/eth-contract.git?branch=event#48b53463ad0ae46754ed6a6711b3a46bef3d1b59" } +dependencies = [ + { name = "web3" }, +] + +[[package]] +name = "eth-hash" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/38/577b7bc9380ef9dff0f1dffefe0c9a1ded2385e7a06c306fd95afb6f9451/eth_hash-0.7.1.tar.gz", hash = "sha256:d2411a403a0b0a62e8247b4117932d900ffb4c8c64b15f92620547ca5ce46be5", size = 12227, upload-time = "2025-01-13T21:29:21.765Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/db/f8775490669d28aca24871c67dd56b3e72105cb3bcae9a4ec65dd70859b3/eth_hash-0.7.1-py3-none-any.whl", hash = "sha256:0fb1add2adf99ef28883fd6228eb447ef519ea72933535ad1a0b28c6f65f868a", size = 8028, upload-time = "2025-01-13T21:29:19.365Z" }, +] + +[package.optional-dependencies] +pycryptodome = [ + { name = "pycryptodome" }, +] + +[[package]] +name = "eth-keyfile" +version = "0.8.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eth-keys" }, + { name = "eth-utils" }, + { name = "pycryptodome" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/35/66/dd823b1537befefbbff602e2ada88f1477c5b40ec3731e3d9bc676c5f716/eth_keyfile-0.8.1.tar.gz", hash = "sha256:9708bc31f386b52cca0969238ff35b1ac72bd7a7186f2a84b86110d3c973bec1", size = 12267, upload-time = "2024-04-23T20:28:53.862Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/fc/48a586175f847dd9e05e5b8994d2fe8336098781ec2e9836a2ad94280281/eth_keyfile-0.8.1-py3-none-any.whl", hash = "sha256:65387378b82fe7e86d7cb9f8d98e6d639142661b2f6f490629da09fddbef6d64", size = 7510, upload-time = "2024-04-23T20:28:51.063Z" }, +] + +[[package]] +name = "eth-keys" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eth-typing" }, + { name = "eth-utils" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/11/1ed831c50bd74f57829aa06e58bd82a809c37e070ee501c953b9ac1f1552/eth_keys-0.7.0.tar.gz", hash = "sha256:79d24fd876201df67741de3e3fefb3f4dbcbb6ace66e47e6fe662851a4547814", size = 30166, upload-time = "2025-04-07T17:40:21.697Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/25/0ae00f2b0095e559d61ad3dc32171bd5a29dfd95ab04b4edd641f7c75f72/eth_keys-0.7.0-py3-none-any.whl", hash = "sha256:b0cdda8ffe8e5ba69c7c5ca33f153828edcace844f67aabd4542d7de38b159cf", size = 20656, upload-time = "2025-04-07T17:40:20.441Z" }, +] + +[[package]] +name = "eth-rlp" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eth-utils" }, + { name = "hexbytes" }, + { name = "rlp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7f/ea/ad39d001fa9fed07fad66edb00af701e29b48be0ed44a3bcf58cb3adf130/eth_rlp-2.2.0.tar.gz", hash = "sha256:5e4b2eb1b8213e303d6a232dfe35ab8c29e2d3051b86e8d359def80cd21db83d", size = 7720, upload-time = "2025-02-04T21:51:08.134Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/3b/57efe2bc2df0980680d57c01a36516cd3171d2319ceb30e675de19fc2cc5/eth_rlp-2.2.0-py3-none-any.whl", hash = "sha256:5692d595a741fbaef1203db6a2fedffbd2506d31455a6ad378c8449ee5985c47", size = 4446, upload-time = "2025-02-04T21:51:05.823Z" }, +] + +[[package]] +name = "eth-typing" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/54/62aa24b9cc708f06316167ee71c362779c8ed21fc8234a5cd94a8f53b623/eth_typing-5.2.1.tar.gz", hash = "sha256:7557300dbf02a93c70fa44af352b5c4a58f94e997a0fd6797fb7d1c29d9538ee", size = 21806, upload-time = "2025-04-14T20:39:28.217Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/72/c370bbe4c53da7bf998d3523f5a0f38867654923a82192df88d0705013d3/eth_typing-5.2.1-py3-none-any.whl", hash = "sha256:b0c2812ff978267563b80e9d701f487dd926f1d376d674f3b535cfe28b665d3d", size = 19163, upload-time = "2025-04-14T20:39:26.571Z" }, +] + +[[package]] +name = "eth-utils" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cytoolz", marker = "implementation_name == 'cpython'" }, + { name = "eth-hash" }, + { name = "eth-typing" }, + { name = "pydantic" }, + { name = "toolz", marker = "implementation_name == 'pypy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e6/e1/ee3a8728227c3558853e63ff35bd4c449abdf5022a19601369400deacd39/eth_utils-5.3.1.tar.gz", hash = "sha256:c94e2d2abd024a9a42023b4ddc1c645814ff3d6a737b33d5cfd890ebf159c2d1", size = 123506, upload-time = "2025-08-27T16:37:17.378Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/4d/257cdc01ada430b8e84b9f2385c2553f33218f5b47da9adf0a616308d4b7/eth_utils-5.3.1-py3-none-any.whl", hash = "sha256:1f5476d8f29588d25b8ae4987e1ffdfae6d4c09026e476c4aad13b32dda3ead0", size = 102529, upload-time = "2025-08-27T16:37:15.449Z" }, +] + +[[package]] +name = "fire" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "termcolor" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/00/f8d10588d2019d6d6452653def1ee807353b21983db48550318424b5ff18/fire-0.7.1.tar.gz", hash = "sha256:3b208f05c736de98fb343310d090dcc4d8c78b2a89ea4f32b837c586270a9cbf", size = 88720, upload-time = "2025-08-16T20:20:24.175Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/4c/93d0f85318da65923e4b91c1c2ff03d8a458cbefebe3bc612a6693c7906d/fire-0.7.1-py3-none-any.whl", hash = "sha256:e43fd8a5033a9001e7e2973bab96070694b9f12f2e0ecf96d4683971b5ab1882", size = 115945, upload-time = "2025-08-16T20:20:22.87Z" }, +] + +[[package]] +name = "flake8" +version = "7.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mccabe" }, + { name = "pycodestyle" }, + { name = "pyflakes" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/af/fbfe3c4b5a657d79e5c47a2827a362f9e1b763336a52f926126aa6dc7123/flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872", size = 48326, upload-time = "2025-06-20T19:31:35.838Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e", size = 57922, upload-time = "2025-06-20T19:31:34.425Z" }, +] + +[[package]] +name = "flake8-black" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "black" }, + { name = "flake8" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/c5/99d47b42d31cb820b81f9aa86c63eb6221a1a23e7b3d15e6d528a17457d7/flake8_black-0.4.0.tar.gz", hash = "sha256:bf226868f695dee48d55ff6d7747e900709bfd6f605b7a378c70e711e3fc26cb", size = 13706, upload-time = "2025-09-21T18:56:37.822Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/b0/692cb58998c21c0f2348bd128171173455515b164be89bec195eeb8c5d8a/flake8_black-0.4.0-py3-none-any.whl", hash = "sha256:288762d0c9ea065782d87eeecbcc20c69079d17fe1d0f0445f0eb0b0ffb80c39", size = 10145, upload-time = "2025-09-21T18:56:36.597Z" }, +] + +[[package]] +name = "flake8-isort" +version = "7.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "flake8" }, + { name = "isort" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/a4/4b170983fd2e9b5ecc40c88738db6dfb77e069c71be9a81f9893cdb8a0cc/flake8_isort-7.0.0.tar.gz", hash = "sha256:a677199d1197f826eb69084e7ac272f208f4583363285f43111c34272abe7e5d", size = 17796, upload-time = "2025-10-25T13:31:08.768Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/7d/907ef4135f6ede5187930d9ddd1f36564e07c6cdcd15ae8fb9849c9517e0/flake8_isort-7.0.0-py3-none-any.whl", hash = "sha256:c301a0e55fc77582348e636194b84b1a0baf0dfdaa6eddf3b0eeea75f8be7f36", size = 18383, upload-time = "2025-10-25T13:31:06.914Z" }, +] + +[[package]] +name = "flaky" +version = "3.8.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/c5/ef69119a01427204ff2db5fc8f98001087bcce719bbb94749dcd7b191365/flaky-3.8.1.tar.gz", hash = "sha256:47204a81ec905f3d5acfbd61daeabcada8f9d4031616d9bcb0618461729699f5", size = 25248, upload-time = "2024-03-12T22:17:59.265Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/b8/b830fc43663246c3f3dd1ae7dca4847b96ed992537e85311e27fa41ac40e/flaky-3.8.1-py2.py3-none-any.whl", hash = "sha256:194ccf4f0d3a22b2de7130f4b62e45e977ac1b5ccad74d4d48f3005dcc38815e", size = 19139, upload-time = "2024-03-12T22:17:51.59Z" }, +] + +[[package]] +name = "frozenlist" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, + { url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, + { url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, + { url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, + { url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, + { url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, + { url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, + { url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, + { url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, + { url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, + { url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, + { url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, + { url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, + { url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, + { url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, + { url = "https://files.pythonhosted.org/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, + { url = "https://files.pythonhosted.org/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, + { url = "https://files.pythonhosted.org/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, + { url = "https://files.pythonhosted.org/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, + { url = "https://files.pythonhosted.org/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, + { url = "https://files.pythonhosted.org/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, + { url = "https://files.pythonhosted.org/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, + { url = "https://files.pythonhosted.org/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, + { url = "https://files.pythonhosted.org/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, + { url = "https://files.pythonhosted.org/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, + { url = "https://files.pythonhosted.org/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, + { url = "https://files.pythonhosted.org/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, + { url = "https://files.pythonhosted.org/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, + { url = "https://files.pythonhosted.org/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, + { url = "https://files.pythonhosted.org/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, + { url = "https://files.pythonhosted.org/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, + { url = "https://files.pythonhosted.org/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c8/85da824b7e7b9b6e7f7705b2ecaf9591ba6f79c1177f324c2735e41d36a2/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", size = 86127, upload-time = "2025-10-06T05:37:08.438Z" }, + { url = "https://files.pythonhosted.org/packages/8e/e8/a1185e236ec66c20afd72399522f142c3724c785789255202d27ae992818/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", size = 49698, upload-time = "2025-10-06T05:37:09.48Z" }, + { url = "https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", size = 49749, upload-time = "2025-10-06T05:37:10.569Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", size = 231298, upload-time = "2025-10-06T05:37:11.993Z" }, + { url = "https://files.pythonhosted.org/packages/3a/3b/d9b1e0b0eed36e70477ffb8360c49c85c8ca8ef9700a4e6711f39a6e8b45/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", size = 232015, upload-time = "2025-10-06T05:37:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/dc/94/be719d2766c1138148564a3960fc2c06eb688da592bdc25adcf856101be7/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", size = 225038, upload-time = "2025-10-06T05:37:14.577Z" }, + { url = "https://files.pythonhosted.org/packages/e4/09/6712b6c5465f083f52f50cf74167b92d4ea2f50e46a9eea0523d658454ae/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", size = 240130, upload-time = "2025-10-06T05:37:15.781Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d4/cd065cdcf21550b54f3ce6a22e143ac9e4836ca42a0de1022da8498eac89/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", size = 242845, upload-time = "2025-10-06T05:37:17.037Z" }, + { url = "https://files.pythonhosted.org/packages/62/c3/f57a5c8c70cd1ead3d5d5f776f89d33110b1addae0ab010ad774d9a44fb9/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", size = 229131, upload-time = "2025-10-06T05:37:18.221Z" }, + { url = "https://files.pythonhosted.org/packages/6c/52/232476fe9cb64f0742f3fde2b7d26c1dac18b6d62071c74d4ded55e0ef94/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", size = 240542, upload-time = "2025-10-06T05:37:19.771Z" }, + { url = "https://files.pythonhosted.org/packages/5f/85/07bf3f5d0fb5414aee5f47d33c6f5c77bfe49aac680bfece33d4fdf6a246/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", size = 237308, upload-time = "2025-10-06T05:37:20.969Z" }, + { url = "https://files.pythonhosted.org/packages/11/99/ae3a33d5befd41ac0ca2cc7fd3aa707c9c324de2e89db0e0f45db9a64c26/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", size = 238210, upload-time = "2025-10-06T05:37:22.252Z" }, + { url = "https://files.pythonhosted.org/packages/b2/60/b1d2da22f4970e7a155f0adde9b1435712ece01b3cd45ba63702aea33938/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", size = 231972, upload-time = "2025-10-06T05:37:23.5Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ab/945b2f32de889993b9c9133216c068b7fcf257d8595a0ac420ac8677cab0/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", size = 40536, upload-time = "2025-10-06T05:37:25.581Z" }, + { url = "https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", size = 44330, upload-time = "2025-10-06T05:37:26.928Z" }, + { url = "https://files.pythonhosted.org/packages/82/13/e6950121764f2676f43534c555249f57030150260aee9dcf7d64efda11dd/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", size = 40627, upload-time = "2025-10-06T05:37:28.075Z" }, + { url = "https://files.pythonhosted.org/packages/c0/c7/43200656ecc4e02d3f8bc248df68256cd9572b3f0017f0a0c4e93440ae23/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", size = 89238, upload-time = "2025-10-06T05:37:29.373Z" }, + { url = "https://files.pythonhosted.org/packages/d1/29/55c5f0689b9c0fb765055629f472c0de484dcaf0acee2f7707266ae3583c/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", size = 50738, upload-time = "2025-10-06T05:37:30.792Z" }, + { url = "https://files.pythonhosted.org/packages/ba/7d/b7282a445956506fa11da8c2db7d276adcbf2b17d8bb8407a47685263f90/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", size = 51739, upload-time = "2025-10-06T05:37:32.127Z" }, + { url = "https://files.pythonhosted.org/packages/62/1c/3d8622e60d0b767a5510d1d3cf21065b9db874696a51ea6d7a43180a259c/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", size = 284186, upload-time = "2025-10-06T05:37:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/2d/14/aa36d5f85a89679a85a1d44cd7a6657e0b1c75f61e7cad987b203d2daca8/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", size = 292196, upload-time = "2025-10-06T05:37:36.107Z" }, + { url = "https://files.pythonhosted.org/packages/05/23/6bde59eb55abd407d34f77d39a5126fb7b4f109a3f611d3929f14b700c66/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", size = 273830, upload-time = "2025-10-06T05:37:37.663Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3f/22cff331bfad7a8afa616289000ba793347fcd7bc275f3b28ecea2a27909/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", size = 294289, upload-time = "2025-10-06T05:37:39.261Z" }, + { url = "https://files.pythonhosted.org/packages/a4/89/5b057c799de4838b6c69aa82b79705f2027615e01be996d2486a69ca99c4/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", size = 300318, upload-time = "2025-10-06T05:37:43.213Z" }, + { url = "https://files.pythonhosted.org/packages/30/de/2c22ab3eb2a8af6d69dc799e48455813bab3690c760de58e1bf43b36da3e/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", size = 282814, upload-time = "2025-10-06T05:37:45.337Z" }, + { url = "https://files.pythonhosted.org/packages/59/f7/970141a6a8dbd7f556d94977858cfb36fa9b66e0892c6dd780d2219d8cd8/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", size = 291762, upload-time = "2025-10-06T05:37:46.657Z" }, + { url = "https://files.pythonhosted.org/packages/c1/15/ca1adae83a719f82df9116d66f5bb28bb95557b3951903d39135620ef157/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", size = 289470, upload-time = "2025-10-06T05:37:47.946Z" }, + { url = "https://files.pythonhosted.org/packages/ac/83/dca6dc53bf657d371fbc88ddeb21b79891e747189c5de990b9dfff2ccba1/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", size = 289042, upload-time = "2025-10-06T05:37:49.499Z" }, + { url = "https://files.pythonhosted.org/packages/96/52/abddd34ca99be142f354398700536c5bd315880ed0a213812bc491cff5e4/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", size = 283148, upload-time = "2025-10-06T05:37:50.745Z" }, + { url = "https://files.pythonhosted.org/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", size = 44676, upload-time = "2025-10-06T05:37:52.222Z" }, + { url = "https://files.pythonhosted.org/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", size = 49451, upload-time = "2025-10-06T05:37:53.425Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", size = 42507, upload-time = "2025-10-06T05:37:54.513Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, +] + +[[package]] +name = "grpcio" +version = "1.76.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b6/e0/318c1ce3ae5a17894d5791e87aea147587c9e702f24122cc7a5c8bbaeeb1/grpcio-1.76.0.tar.gz", hash = "sha256:7be78388d6da1a25c0d5ec506523db58b18be22d9c37d8d3a32c08be4987bd73", size = 12785182, upload-time = "2025-10-21T16:23:12.106Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/05/8e29121994b8d959ffa0afd28996d452f291b48cfc0875619de0bde2c50c/grpcio-1.76.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:81fd9652b37b36f16138611c7e884eb82e0cec137c40d3ef7c3f9b3ed00f6ed8", size = 5799718, upload-time = "2025-10-21T16:21:17.939Z" }, + { url = "https://files.pythonhosted.org/packages/d9/75/11d0e66b3cdf998c996489581bdad8900db79ebd83513e45c19548f1cba4/grpcio-1.76.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:04bbe1bfe3a68bbfd4e52402ab7d4eb59d72d02647ae2042204326cf4bbad280", size = 11825627, upload-time = "2025-10-21T16:21:20.466Z" }, + { url = "https://files.pythonhosted.org/packages/28/50/2f0aa0498bc188048f5d9504dcc5c2c24f2eb1a9337cd0fa09a61a2e75f0/grpcio-1.76.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d388087771c837cdb6515539f43b9d4bf0b0f23593a24054ac16f7a960be16f4", size = 6359167, upload-time = "2025-10-21T16:21:23.122Z" }, + { url = "https://files.pythonhosted.org/packages/66/e5/bbf0bb97d29ede1d59d6588af40018cfc345b17ce979b7b45424628dc8bb/grpcio-1.76.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:9f8f757bebaaea112c00dba718fc0d3260052ce714e25804a03f93f5d1c6cc11", size = 7044267, upload-time = "2025-10-21T16:21:25.995Z" }, + { url = "https://files.pythonhosted.org/packages/f5/86/f6ec2164f743d9609691115ae8ece098c76b894ebe4f7c94a655c6b03e98/grpcio-1.76.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:980a846182ce88c4f2f7e2c22c56aefd515daeb36149d1c897f83cf57999e0b6", size = 6573963, upload-time = "2025-10-21T16:21:28.631Z" }, + { url = "https://files.pythonhosted.org/packages/60/bc/8d9d0d8505feccfdf38a766d262c71e73639c165b311c9457208b56d92ae/grpcio-1.76.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f92f88e6c033db65a5ae3d97905c8fea9c725b63e28d5a75cb73b49bda5024d8", size = 7164484, upload-time = "2025-10-21T16:21:30.837Z" }, + { url = "https://files.pythonhosted.org/packages/67/e6/5d6c2fc10b95edf6df9b8f19cf10a34263b7fd48493936fffd5085521292/grpcio-1.76.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4baf3cbe2f0be3289eb68ac8ae771156971848bb8aaff60bad42005539431980", size = 8127777, upload-time = "2025-10-21T16:21:33.577Z" }, + { url = "https://files.pythonhosted.org/packages/3f/c8/dce8ff21c86abe025efe304d9e31fdb0deaaa3b502b6a78141080f206da0/grpcio-1.76.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:615ba64c208aaceb5ec83bfdce7728b80bfeb8be97562944836a7a0a9647d882", size = 7594014, upload-time = "2025-10-21T16:21:41.882Z" }, + { url = "https://files.pythonhosted.org/packages/e0/42/ad28191ebf983a5d0ecef90bab66baa5a6b18f2bfdef9d0a63b1973d9f75/grpcio-1.76.0-cp312-cp312-win32.whl", hash = "sha256:45d59a649a82df5718fd9527ce775fd66d1af35e6d31abdcdc906a49c6822958", size = 3984750, upload-time = "2025-10-21T16:21:44.006Z" }, + { url = "https://files.pythonhosted.org/packages/9e/00/7bd478cbb851c04a48baccaa49b75abaa8e4122f7d86da797500cccdd771/grpcio-1.76.0-cp312-cp312-win_amd64.whl", hash = "sha256:c088e7a90b6017307f423efbb9d1ba97a22aa2170876223f9709e9d1de0b5347", size = 4704003, upload-time = "2025-10-21T16:21:46.244Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ed/71467ab770effc9e8cef5f2e7388beb2be26ed642d567697bb103a790c72/grpcio-1.76.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:26ef06c73eb53267c2b319f43e6634c7556ea37672029241a056629af27c10e2", size = 5807716, upload-time = "2025-10-21T16:21:48.475Z" }, + { url = "https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:45e0111e73f43f735d70786557dc38141185072d7ff8dc1829d6a77ac1471468", size = 11821522, upload-time = "2025-10-21T16:21:51.142Z" }, + { url = "https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:83d57312a58dcfe2a3a0f9d1389b299438909a02db60e2f2ea2ae2d8034909d3", size = 6362558, upload-time = "2025-10-21T16:21:54.213Z" }, + { url = "https://files.pythonhosted.org/packages/bd/64/9784eab483358e08847498ee56faf8ff6ea8e0a4592568d9f68edc97e9e9/grpcio-1.76.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3e2a27c89eb9ac3d81ec8835e12414d73536c6e620355d65102503064a4ed6eb", size = 7049990, upload-time = "2025-10-21T16:21:56.476Z" }, + { url = "https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61f69297cba3950a524f61c7c8ee12e55c486cb5f7db47ff9dcee33da6f0d3ae", size = 6575387, upload-time = "2025-10-21T16:21:59.051Z" }, + { url = "https://files.pythonhosted.org/packages/15/0f/f12c32b03f731f4a6242f771f63039df182c8b8e2cf8075b245b409259d4/grpcio-1.76.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6a15c17af8839b6801d554263c546c69c4d7718ad4321e3166175b37eaacca77", size = 7166668, upload-time = "2025-10-21T16:22:02.049Z" }, + { url = "https://files.pythonhosted.org/packages/ff/2d/3ec9ce0c2b1d92dd59d1c3264aaec9f0f7c817d6e8ac683b97198a36ed5a/grpcio-1.76.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:25a18e9810fbc7e7f03ec2516addc116a957f8cbb8cbc95ccc80faa072743d03", size = 8124928, upload-time = "2025-10-21T16:22:04.984Z" }, + { url = "https://files.pythonhosted.org/packages/1a/74/fd3317be5672f4856bcdd1a9e7b5e17554692d3db9a3b273879dc02d657d/grpcio-1.76.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:931091142fd8cc14edccc0845a79248bc155425eee9a98b2db2ea4f00a235a42", size = 7589983, upload-time = "2025-10-21T16:22:07.881Z" }, + { url = "https://files.pythonhosted.org/packages/45/bb/ca038cf420f405971f19821c8c15bcbc875505f6ffadafe9ffd77871dc4c/grpcio-1.76.0-cp313-cp313-win32.whl", hash = "sha256:5e8571632780e08526f118f74170ad8d50fb0a48c23a746bef2a6ebade3abd6f", size = 3984727, upload-time = "2025-10-21T16:22:10.032Z" }, + { url = "https://files.pythonhosted.org/packages/41/80/84087dc56437ced7cdd4b13d7875e7439a52a261e3ab4e06488ba6173b0a/grpcio-1.76.0-cp313-cp313-win_amd64.whl", hash = "sha256:f9f7bd5faab55f47231ad8dba7787866b69f5e93bc306e3915606779bbfb4ba8", size = 4702799, upload-time = "2025-10-21T16:22:12.709Z" }, + { url = "https://files.pythonhosted.org/packages/b4/46/39adac80de49d678e6e073b70204091e76631e03e94928b9ea4ecf0f6e0e/grpcio-1.76.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:ff8a59ea85a1f2191a0ffcc61298c571bc566332f82e5f5be1b83c9d8e668a62", size = 5808417, upload-time = "2025-10-21T16:22:15.02Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f5/a4531f7fb8b4e2a60b94e39d5d924469b7a6988176b3422487be61fe2998/grpcio-1.76.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:06c3d6b076e7b593905d04fdba6a0525711b3466f43b3400266f04ff735de0cd", size = 11828219, upload-time = "2025-10-21T16:22:17.954Z" }, + { url = "https://files.pythonhosted.org/packages/4b/1c/de55d868ed7a8bd6acc6b1d6ddc4aa36d07a9f31d33c912c804adb1b971b/grpcio-1.76.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd5ef5932f6475c436c4a55e4336ebbe47bd3272be04964a03d316bbf4afbcbc", size = 6367826, upload-time = "2025-10-21T16:22:20.721Z" }, + { url = "https://files.pythonhosted.org/packages/59/64/99e44c02b5adb0ad13ab3adc89cb33cb54bfa90c74770f2607eea629b86f/grpcio-1.76.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b331680e46239e090f5b3cead313cc772f6caa7d0fc8de349337563125361a4a", size = 7049550, upload-time = "2025-10-21T16:22:23.637Z" }, + { url = "https://files.pythonhosted.org/packages/43/28/40a5be3f9a86949b83e7d6a2ad6011d993cbe9b6bd27bea881f61c7788b6/grpcio-1.76.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2229ae655ec4e8999599469559e97630185fdd53ae1e8997d147b7c9b2b72cba", size = 6575564, upload-time = "2025-10-21T16:22:26.016Z" }, + { url = "https://files.pythonhosted.org/packages/4b/a9/1be18e6055b64467440208a8559afac243c66a8b904213af6f392dc2212f/grpcio-1.76.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:490fa6d203992c47c7b9e4a9d39003a0c2bcc1c9aa3c058730884bbbb0ee9f09", size = 7176236, upload-time = "2025-10-21T16:22:28.362Z" }, + { url = "https://files.pythonhosted.org/packages/0f/55/dba05d3fcc151ce6e81327541d2cc8394f442f6b350fead67401661bf041/grpcio-1.76.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:479496325ce554792dba6548fae3df31a72cef7bad71ca2e12b0e58f9b336bfc", size = 8125795, upload-time = "2025-10-21T16:22:31.075Z" }, + { url = "https://files.pythonhosted.org/packages/4a/45/122df922d05655f63930cf42c9e3f72ba20aadb26c100ee105cad4ce4257/grpcio-1.76.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1c9b93f79f48b03ada57ea24725d83a30284a012ec27eab2cf7e50a550cbbbcc", size = 7592214, upload-time = "2025-10-21T16:22:33.831Z" }, + { url = "https://files.pythonhosted.org/packages/4a/6e/0b899b7f6b66e5af39e377055fb4a6675c9ee28431df5708139df2e93233/grpcio-1.76.0-cp314-cp314-win32.whl", hash = "sha256:747fa73efa9b8b1488a95d0ba1039c8e2dca0f741612d80415b1e1c560febf4e", size = 4062961, upload-time = "2025-10-21T16:22:36.468Z" }, + { url = "https://files.pythonhosted.org/packages/19/41/0b430b01a2eb38ee887f88c1f07644a1df8e289353b78e82b37ef988fb64/grpcio-1.76.0-cp314-cp314-win_amd64.whl", hash = "sha256:922fa70ba549fce362d2e2871ab542082d66e2aaf0c19480ea453905b01f384e", size = 4834462, upload-time = "2025-10-21T16:22:39.772Z" }, +] + +[[package]] +name = "hexbytes" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7f/87/adf4635b4b8c050283d74e6db9a81496063229c9263e6acc1903ab79fbec/hexbytes-1.3.1.tar.gz", hash = "sha256:a657eebebdfe27254336f98d8af6e2236f3f83aed164b87466b6cf6c5f5a4765", size = 8633, upload-time = "2025-05-14T16:45:17.5Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/e0/3b31492b1c89da3c5a846680517871455b30c54738486fc57ac79a5761bd/hexbytes-1.3.1-py3-none-any.whl", hash = "sha256:da01ff24a1a9a2b1881c4b85f0e9f9b0f51b526b379ffa23832ae7899d29c2c7", size = 5074, upload-time = "2025-05-14T16:45:16.179Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "integration-tests" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "cprotobuf" }, + { name = "eth-bloom" }, + { name = "eth-contract" }, + { name = "flake8-black" }, + { name = "flake8-isort" }, + { name = "flaky" }, + { name = "py-ecc" }, + { name = "pyrevm" }, + { name = "pystarport" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-github-actions-annotate-failures" }, + { name = "pyunormalize" }, + { name = "web3" }, +] + +[package.dev-dependencies] +dev = [ + { name = "aiohappyeyeballs" }, + { name = "attrs" }, + { name = "referencing" }, + { name = "rpds-py" }, + { name = "types-requests" }, + { name = "typing-inspection" }, +] + +[package.metadata] +requires-dist = [ + { name = "cprotobuf", git = "https://github.com/yihuang/cprotobuf.git?branch=master" }, + { name = "eth-bloom", specifier = ">=3.0" }, + { name = "eth-contract", git = "https://github.com/mmsqe/eth-contract.git?branch=event" }, + { name = "flake8-black", specifier = ">=0.3.6" }, + { name = "flake8-isort", specifier = ">=6.1.2" }, + { name = "flaky", specifier = ">=3.8.1" }, + { name = "py-ecc", specifier = ">=8.0.0" }, + { name = "pyrevm", git = "https://github.com/yihuang/pyrevm.git?branch=master" }, + { name = "pystarport", git = "https://github.com/MANTRA-Chain/pystarport.git?branch=main" }, + { name = "pytest", specifier = ">=8.3.4" }, + { name = "pytest-asyncio", specifier = ">=1.3.0" }, + { name = "pytest-github-actions-annotate-failures", specifier = ">=0.3.0" }, + { name = "pyunormalize", specifier = ">=16.0.0" }, + { name = "web3", specifier = ">=7.3.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "aiohappyeyeballs", specifier = ">=2.4.4" }, + { name = "attrs", specifier = ">=24.2.0" }, + { name = "referencing", specifier = ">=0.35.1" }, + { name = "rpds-py", specifier = ">=0.22.3" }, + { name = "types-requests", specifier = ">=2.32.0.20250328" }, + { name = "typing-inspection", specifier = ">=0.4.0" }, +] + +[[package]] +name = "isort" +version = "7.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/63/53/4f3c058e3bace40282876f9b553343376ee687f3c35a525dc79dbd450f88/isort-7.0.0.tar.gz", hash = "sha256:5513527951aadb3ac4292a41a16cbc50dd1642432f5e8c20057d414bdafb4187", size = 805049, upload-time = "2025-10-11T13:30:59.107Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/ed/e3705d6d02b4f7aea715a353c8ce193efd0b5db13e204df895d38734c244/isort-7.0.0-py3-none-any.whl", hash = "sha256:1bcabac8bc3c36c7fb7b98a76c8abb18e0f841a3ba81decac7691008592499c1", size = 94672, upload-time = "2025-10-11T13:30:57.665Z" }, +] + +[[package]] +name = "jsonmerge" +version = "1.9.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonschema" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/37/9f/959b3191324d831494b81ec06cfaeb11017858fc59cd9de9c6bd757ef29e/jsonmerge-1.9.2.tar.gz", hash = "sha256:c43757e0180b0e19b7ae4c130ad42a07cc580c31912f61f4823e8eaf2fa394a3", size = 34717, upload-time = "2023-07-19T08:10:07.51Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/c2/1032d0dbc2152c45f3d1e582a72e68f41898de9665202392d9400dfa329d/jsonmerge-1.9.2-py3-none-any.whl", hash = "sha256:cab93ee7763fb51a4a09bbdab2eacf499ffb208ab94247ae86acea3e0e823b05", size = 19367, upload-time = "2023-07-19T08:10:06.144Z" }, +] + +[[package]] +name = "jsonnet" +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/bd/e4a77ccb757a3060f30eefbd090b9593fe6ad15e5ef8ff0c3fc4aa5237cf/jsonnet-0.21.0.tar.gz", hash = "sha256:7fe2865e6e1dc2b9791d880fea3eba7e72334b256d85f027da3ae1f56a55b1da", size = 461207, upload-time = "2025-05-07T13:20:51.321Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/42/2bf7da089e6b5ca75f7a7c3bb2e9c39e1783d4359ab17c5083b0698dfbfa/jsonnet-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba35051103bed81ddcb446db52c31bba00391c52069107498eb44952feac8a30", size = 473523, upload-time = "2025-05-07T13:20:22.449Z" }, + { url = "https://files.pythonhosted.org/packages/8d/e0/f3ef97fa0535b435fbde76df9da63b78602692cca0d4b8ddf2d8439830fc/jsonnet-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71afa464a74dcbec30b39d8f28cad091ce27497a8620c0ef7859814e173ce454", size = 438912, upload-time = "2025-05-07T13:20:24.425Z" }, + { url = "https://files.pythonhosted.org/packages/97/ee/3613b2f2216d4a53c13bb081f7b77d6a7977a4169039efa7eb77bf9d71da/jsonnet-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fccebb019917004cf860490a80d17189bad01c9d425b7a1cb138a14745488cf0", size = 6529912, upload-time = "2025-05-07T13:20:26.671Z" }, + { url = "https://files.pythonhosted.org/packages/3b/90/dee03ee550737b913f64428ac392e8970d807b02c938b766bf7e40fa3cfc/jsonnet-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba913bb650b2b5dac29e65fd6963dff7cad960580523c0ccdd66e23e22e3b772", size = 6782491, upload-time = "2025-05-07T13:20:28.576Z" }, + { url = "https://files.pythonhosted.org/packages/aa/a5/c3a2592383ec68e02d9d31740764f144dfb8df28d4f2d003c40d05f73478/jsonnet-0.21.0-cp312-cp312-win_amd64.whl", hash = "sha256:7a39b5a3195bb6ec16050d14f8aa9378cf862ff2dd54ca0973cbbfbc9cec6e89", size = 318260, upload-time = "2025-05-07T13:20:30.159Z" }, + { url = "https://files.pythonhosted.org/packages/87/9a/b7825f91d889fbe47125911a34f56f0cb94f01afdffb0bc6390f1573bb1c/jsonnet-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:95d0e0e59ed29f7e424066c05c4585fd255e288fd6050686e1d5bb54bd719896", size = 473524, upload-time = "2025-05-07T13:20:31.601Z" }, + { url = "https://files.pythonhosted.org/packages/d0/66/fe05afdcf269a8be7a99aa33741ad31cf083a505acb46010a90781b00106/jsonnet-0.21.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb926cae6ea157e2e0851e6ec8f6a2949e926f67754a87980bbcb2698a211dc5", size = 438913, upload-time = "2025-05-07T13:20:33.281Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2c/c4760c07b3506312f37c237c9a0840f3db44e476da5af2c0b883bb5b1070/jsonnet-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb642fe864e41a432957f71bfa57ae4eaab904886f06dec183c9e40d6ce4e24b", size = 6529866, upload-time = "2025-05-07T13:20:35.359Z" }, + { url = "https://files.pythonhosted.org/packages/1c/56/33a2eb1d263952603f9b16f3789ecac0c7a3b9bb5a6410d69173a6ed3bd9/jsonnet-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:22a87070c1c50ecf6c0c8df252a4984a89275ceb18fe059dfa99eeaf548be71f", size = 6782518, upload-time = "2025-05-07T13:20:37.777Z" }, + { url = "https://files.pythonhosted.org/packages/bb/d9/2c68a80f9cbda8e4b4721032b7def236109bd8991d1670b60beb5cfb505c/jsonnet-0.21.0-cp313-cp313-win_amd64.whl", hash = "sha256:6e23e55e0a0811b899398aaa03a5b46eea01ffcafc697a705fe7b07eb8cd0ce7", size = 318264, upload-time = "2025-05-07T13:20:39.842Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.25.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[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, upload-time = "2022-01-24T01:14:51.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, +] + +[[package]] +name = "multidict" +version = "6.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/9e/9f61ac18d9c8b475889f32ccfa91c9f59363480613fc807b6e3023d6f60b/multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", size = 76877, upload-time = "2025-10-06T14:49:20.884Z" }, + { url = "https://files.pythonhosted.org/packages/38/6f/614f09a04e6184f8824268fce4bc925e9849edfa654ddd59f0b64508c595/multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", size = 45467, upload-time = "2025-10-06T14:49:22.054Z" }, + { url = "https://files.pythonhosted.org/packages/b3/93/c4f67a436dd026f2e780c433277fff72be79152894d9fc36f44569cab1a6/multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", size = 43834, upload-time = "2025-10-06T14:49:23.566Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f5/013798161ca665e4a422afbc5e2d9e4070142a9ff8905e482139cd09e4d0/multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", size = 250545, upload-time = "2025-10-06T14:49:24.882Z" }, + { url = "https://files.pythonhosted.org/packages/71/2f/91dbac13e0ba94669ea5119ba267c9a832f0cb65419aca75549fcf09a3dc/multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", size = 258305, upload-time = "2025-10-06T14:49:26.778Z" }, + { url = "https://files.pythonhosted.org/packages/ef/b0/754038b26f6e04488b48ac621f779c341338d78503fb45403755af2df477/multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", size = 242363, upload-time = "2025-10-06T14:49:28.562Z" }, + { url = "https://files.pythonhosted.org/packages/87/15/9da40b9336a7c9fa606c4cf2ed80a649dffeb42b905d4f63a1d7eb17d746/multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", size = 268375, upload-time = "2025-10-06T14:49:29.96Z" }, + { url = "https://files.pythonhosted.org/packages/82/72/c53fcade0cc94dfaad583105fd92b3a783af2091eddcb41a6d5a52474000/multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", size = 269346, upload-time = "2025-10-06T14:49:31.404Z" }, + { url = "https://files.pythonhosted.org/packages/0d/e2/9baffdae21a76f77ef8447f1a05a96ec4bc0a24dae08767abc0a2fe680b8/multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", size = 256107, upload-time = "2025-10-06T14:49:32.974Z" }, + { url = "https://files.pythonhosted.org/packages/3c/06/3f06f611087dc60d65ef775f1fb5aca7c6d61c6db4990e7cda0cef9b1651/multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", size = 253592, upload-time = "2025-10-06T14:49:34.52Z" }, + { url = "https://files.pythonhosted.org/packages/20/24/54e804ec7945b6023b340c412ce9c3f81e91b3bf5fa5ce65558740141bee/multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", size = 251024, upload-time = "2025-10-06T14:49:35.956Z" }, + { url = "https://files.pythonhosted.org/packages/14/48/011cba467ea0b17ceb938315d219391d3e421dfd35928e5dbdc3f4ae76ef/multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", size = 251484, upload-time = "2025-10-06T14:49:37.631Z" }, + { url = "https://files.pythonhosted.org/packages/0d/2f/919258b43bb35b99fa127435cfb2d91798eb3a943396631ef43e3720dcf4/multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", size = 263579, upload-time = "2025-10-06T14:49:39.502Z" }, + { url = "https://files.pythonhosted.org/packages/31/22/a0e884d86b5242b5a74cf08e876bdf299e413016b66e55511f7a804a366e/multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", size = 259654, upload-time = "2025-10-06T14:49:41.32Z" }, + { url = "https://files.pythonhosted.org/packages/b2/e5/17e10e1b5c5f5a40f2fcbb45953c9b215f8a4098003915e46a93f5fcaa8f/multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", size = 251511, upload-time = "2025-10-06T14:49:46.021Z" }, + { url = "https://files.pythonhosted.org/packages/e3/9a/201bb1e17e7af53139597069c375e7b0dcbd47594604f65c2d5359508566/multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", size = 41895, upload-time = "2025-10-06T14:49:48.718Z" }, + { url = "https://files.pythonhosted.org/packages/46/e2/348cd32faad84eaf1d20cce80e2bb0ef8d312c55bca1f7fa9865e7770aaf/multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", size = 46073, upload-time = "2025-10-06T14:49:50.28Z" }, + { url = "https://files.pythonhosted.org/packages/25/ec/aad2613c1910dce907480e0c3aa306905830f25df2e54ccc9dea450cb5aa/multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", size = 43226, upload-time = "2025-10-06T14:49:52.304Z" }, + { url = "https://files.pythonhosted.org/packages/d2/86/33272a544eeb36d66e4d9a920602d1a2f57d4ebea4ef3cdfe5a912574c95/multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", size = 76135, upload-time = "2025-10-06T14:49:54.26Z" }, + { url = "https://files.pythonhosted.org/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", size = 45117, upload-time = "2025-10-06T14:49:55.82Z" }, + { url = "https://files.pythonhosted.org/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", size = 43472, upload-time = "2025-10-06T14:49:57.048Z" }, + { url = "https://files.pythonhosted.org/packages/75/3f/e2639e80325af0b6c6febdf8e57cc07043ff15f57fa1ef808f4ccb5ac4cd/multidict-6.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8", size = 249342, upload-time = "2025-10-06T14:49:58.368Z" }, + { url = "https://files.pythonhosted.org/packages/5d/cc/84e0585f805cbeaa9cbdaa95f9a3d6aed745b9d25700623ac89a6ecff400/multidict-6.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60", size = 257082, upload-time = "2025-10-06T14:49:59.89Z" }, + { url = "https://files.pythonhosted.org/packages/b0/9c/ac851c107c92289acbbf5cfb485694084690c1b17e555f44952c26ddc5bd/multidict-6.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4", size = 240704, upload-time = "2025-10-06T14:50:01.485Z" }, + { url = "https://files.pythonhosted.org/packages/50/cc/5f93e99427248c09da95b62d64b25748a5f5c98c7c2ab09825a1d6af0e15/multidict-6.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f", size = 266355, upload-time = "2025-10-06T14:50:02.955Z" }, + { url = "https://files.pythonhosted.org/packages/ec/0c/2ec1d883ceb79c6f7f6d7ad90c919c898f5d1c6ea96d322751420211e072/multidict-6.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf", size = 267259, upload-time = "2025-10-06T14:50:04.446Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2d/f0b184fa88d6630aa267680bdb8623fb69cb0d024b8c6f0d23f9a0f406d3/multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32", size = 254903, upload-time = "2025-10-06T14:50:05.98Z" }, + { url = "https://files.pythonhosted.org/packages/06/c9/11ea263ad0df7dfabcad404feb3c0dd40b131bc7f232d5537f2fb1356951/multidict-6.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036", size = 252365, upload-time = "2025-10-06T14:50:07.511Z" }, + { url = "https://files.pythonhosted.org/packages/41/88/d714b86ee2c17d6e09850c70c9d310abac3d808ab49dfa16b43aba9d53fd/multidict-6.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec", size = 250062, upload-time = "2025-10-06T14:50:09.074Z" }, + { url = "https://files.pythonhosted.org/packages/15/fe/ad407bb9e818c2b31383f6131ca19ea7e35ce93cf1310fce69f12e89de75/multidict-6.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e", size = 249683, upload-time = "2025-10-06T14:50:10.714Z" }, + { url = "https://files.pythonhosted.org/packages/8c/a4/a89abdb0229e533fb925e7c6e5c40201c2873efebc9abaf14046a4536ee6/multidict-6.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64", size = 261254, upload-time = "2025-10-06T14:50:12.28Z" }, + { url = "https://files.pythonhosted.org/packages/8d/aa/0e2b27bd88b40a4fb8dc53dd74eecac70edaa4c1dd0707eb2164da3675b3/multidict-6.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd", size = 257967, upload-time = "2025-10-06T14:50:14.16Z" }, + { url = "https://files.pythonhosted.org/packages/d0/8e/0c67b7120d5d5f6d874ed85a085f9dc770a7f9d8813e80f44a9fec820bb7/multidict-6.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288", size = 250085, upload-time = "2025-10-06T14:50:15.639Z" }, + { url = "https://files.pythonhosted.org/packages/ba/55/b73e1d624ea4b8fd4dd07a3bb70f6e4c7c6c5d9d640a41c6ffe5cdbd2a55/multidict-6.7.0-cp313-cp313-win32.whl", hash = "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17", size = 41713, upload-time = "2025-10-06T14:50:17.066Z" }, + { url = "https://files.pythonhosted.org/packages/32/31/75c59e7d3b4205075b4c183fa4ca398a2daf2303ddf616b04ae6ef55cffe/multidict-6.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390", size = 45915, upload-time = "2025-10-06T14:50:18.264Z" }, + { url = "https://files.pythonhosted.org/packages/31/2a/8987831e811f1184c22bc2e45844934385363ee61c0a2dcfa8f71b87e608/multidict-6.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e", size = 43077, upload-time = "2025-10-06T14:50:19.853Z" }, + { url = "https://files.pythonhosted.org/packages/e8/68/7b3a5170a382a340147337b300b9eb25a9ddb573bcdfff19c0fa3f31ffba/multidict-6.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00", size = 83114, upload-time = "2025-10-06T14:50:21.223Z" }, + { url = "https://files.pythonhosted.org/packages/55/5c/3fa2d07c84df4e302060f555bbf539310980362236ad49f50eeb0a1c1eb9/multidict-6.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb", size = 48442, upload-time = "2025-10-06T14:50:22.871Z" }, + { url = "https://files.pythonhosted.org/packages/fc/56/67212d33239797f9bd91962bb899d72bb0f4c35a8652dcdb8ed049bef878/multidict-6.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b", size = 46885, upload-time = "2025-10-06T14:50:24.258Z" }, + { url = "https://files.pythonhosted.org/packages/46/d1/908f896224290350721597a61a69cd19b89ad8ee0ae1f38b3f5cd12ea2ac/multidict-6.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c", size = 242588, upload-time = "2025-10-06T14:50:25.716Z" }, + { url = "https://files.pythonhosted.org/packages/ab/67/8604288bbd68680eee0ab568fdcb56171d8b23a01bcd5cb0c8fedf6e5d99/multidict-6.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1", size = 249966, upload-time = "2025-10-06T14:50:28.192Z" }, + { url = "https://files.pythonhosted.org/packages/20/33/9228d76339f1ba51e3efef7da3ebd91964d3006217aae13211653193c3ff/multidict-6.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b", size = 228618, upload-time = "2025-10-06T14:50:29.82Z" }, + { url = "https://files.pythonhosted.org/packages/f8/2d/25d9b566d10cab1c42b3b9e5b11ef79c9111eaf4463b8c257a3bd89e0ead/multidict-6.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5", size = 257539, upload-time = "2025-10-06T14:50:31.731Z" }, + { url = "https://files.pythonhosted.org/packages/b6/b1/8d1a965e6637fc33de3c0d8f414485c2b7e4af00f42cab3d84e7b955c222/multidict-6.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad", size = 256345, upload-time = "2025-10-06T14:50:33.26Z" }, + { url = "https://files.pythonhosted.org/packages/ba/0c/06b5a8adbdeedada6f4fb8d8f193d44a347223b11939b42953eeb6530b6b/multidict-6.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c", size = 247934, upload-time = "2025-10-06T14:50:34.808Z" }, + { url = "https://files.pythonhosted.org/packages/8f/31/b2491b5fe167ca044c6eb4b8f2c9f3b8a00b24c432c365358eadac5d7625/multidict-6.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5", size = 245243, upload-time = "2025-10-06T14:50:36.436Z" }, + { url = "https://files.pythonhosted.org/packages/61/1a/982913957cb90406c8c94f53001abd9eafc271cb3e70ff6371590bec478e/multidict-6.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10", size = 235878, upload-time = "2025-10-06T14:50:37.953Z" }, + { url = "https://files.pythonhosted.org/packages/be/c0/21435d804c1a1cf7a2608593f4d19bca5bcbd7a81a70b253fdd1c12af9c0/multidict-6.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754", size = 243452, upload-time = "2025-10-06T14:50:39.574Z" }, + { url = "https://files.pythonhosted.org/packages/54/0a/4349d540d4a883863191be6eb9a928846d4ec0ea007d3dcd36323bb058ac/multidict-6.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c", size = 252312, upload-time = "2025-10-06T14:50:41.612Z" }, + { url = "https://files.pythonhosted.org/packages/26/64/d5416038dbda1488daf16b676e4dbfd9674dde10a0cc8f4fc2b502d8125d/multidict-6.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762", size = 246935, upload-time = "2025-10-06T14:50:43.972Z" }, + { url = "https://files.pythonhosted.org/packages/9f/8c/8290c50d14e49f35e0bd4abc25e1bc7711149ca9588ab7d04f886cdf03d9/multidict-6.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6", size = 243385, upload-time = "2025-10-06T14:50:45.648Z" }, + { url = "https://files.pythonhosted.org/packages/ef/a0/f83ae75e42d694b3fbad3e047670e511c138be747bc713cf1b10d5096416/multidict-6.7.0-cp313-cp313t-win32.whl", hash = "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d", size = 47777, upload-time = "2025-10-06T14:50:47.154Z" }, + { url = "https://files.pythonhosted.org/packages/dc/80/9b174a92814a3830b7357307a792300f42c9e94664b01dee8e457551fa66/multidict-6.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6", size = 53104, upload-time = "2025-10-06T14:50:48.851Z" }, + { url = "https://files.pythonhosted.org/packages/cc/28/04baeaf0428d95bb7a7bea0e691ba2f31394338ba424fb0679a9ed0f4c09/multidict-6.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792", size = 45503, upload-time = "2025-10-06T14:50:50.16Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b1/3da6934455dd4b261d4c72f897e3a5728eba81db59959f3a639245891baa/multidict-6.7.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842", size = 75128, upload-time = "2025-10-06T14:50:51.92Z" }, + { url = "https://files.pythonhosted.org/packages/14/2c/f069cab5b51d175a1a2cb4ccdf7a2c2dabd58aa5bd933fa036a8d15e2404/multidict-6.7.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b", size = 44410, upload-time = "2025-10-06T14:50:53.275Z" }, + { url = "https://files.pythonhosted.org/packages/42/e2/64bb41266427af6642b6b128e8774ed84c11b80a90702c13ac0a86bb10cc/multidict-6.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38", size = 43205, upload-time = "2025-10-06T14:50:54.911Z" }, + { url = "https://files.pythonhosted.org/packages/02/68/6b086fef8a3f1a8541b9236c594f0c9245617c29841f2e0395d979485cde/multidict-6.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128", size = 245084, upload-time = "2025-10-06T14:50:56.369Z" }, + { url = "https://files.pythonhosted.org/packages/15/ee/f524093232007cd7a75c1d132df70f235cfd590a7c9eaccd7ff422ef4ae8/multidict-6.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34", size = 252667, upload-time = "2025-10-06T14:50:57.991Z" }, + { url = "https://files.pythonhosted.org/packages/02/a5/eeb3f43ab45878f1895118c3ef157a480db58ede3f248e29b5354139c2c9/multidict-6.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99", size = 233590, upload-time = "2025-10-06T14:50:59.589Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/76d02f8270b97269d7e3dbd45644b1785bda457b474315f8cf999525a193/multidict-6.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202", size = 264112, upload-time = "2025-10-06T14:51:01.183Z" }, + { url = "https://files.pythonhosted.org/packages/76/0b/c28a70ecb58963847c2a8efe334904cd254812b10e535aefb3bcce513918/multidict-6.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1", size = 261194, upload-time = "2025-10-06T14:51:02.794Z" }, + { url = "https://files.pythonhosted.org/packages/b4/63/2ab26e4209773223159b83aa32721b4021ffb08102f8ac7d689c943fded1/multidict-6.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3", size = 248510, upload-time = "2025-10-06T14:51:04.724Z" }, + { url = "https://files.pythonhosted.org/packages/93/cd/06c1fa8282af1d1c46fd55c10a7930af652afdce43999501d4d68664170c/multidict-6.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d", size = 248395, upload-time = "2025-10-06T14:51:06.306Z" }, + { url = "https://files.pythonhosted.org/packages/99/ac/82cb419dd6b04ccf9e7e61befc00c77614fc8134362488b553402ecd55ce/multidict-6.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6", size = 239520, upload-time = "2025-10-06T14:51:08.091Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f3/a0f9bf09493421bd8716a362e0cd1d244f5a6550f5beffdd6b47e885b331/multidict-6.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7", size = 245479, upload-time = "2025-10-06T14:51:10.365Z" }, + { url = "https://files.pythonhosted.org/packages/8d/01/476d38fc73a212843f43c852b0eee266b6971f0e28329c2184a8df90c376/multidict-6.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb", size = 258903, upload-time = "2025-10-06T14:51:12.466Z" }, + { url = "https://files.pythonhosted.org/packages/49/6d/23faeb0868adba613b817d0e69c5f15531b24d462af8012c4f6de4fa8dc3/multidict-6.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f", size = 252333, upload-time = "2025-10-06T14:51:14.48Z" }, + { url = "https://files.pythonhosted.org/packages/1e/cc/48d02ac22b30fa247f7dad82866e4b1015431092f4ba6ebc7e77596e0b18/multidict-6.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f", size = 243411, upload-time = "2025-10-06T14:51:16.072Z" }, + { url = "https://files.pythonhosted.org/packages/4a/03/29a8bf5a18abf1fe34535c88adbdfa88c9fb869b5a3b120692c64abe8284/multidict-6.7.0-cp314-cp314-win32.whl", hash = "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885", size = 40940, upload-time = "2025-10-06T14:51:17.544Z" }, + { url = "https://files.pythonhosted.org/packages/82/16/7ed27b680791b939de138f906d5cf2b4657b0d45ca6f5dd6236fdddafb1a/multidict-6.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c", size = 45087, upload-time = "2025-10-06T14:51:18.875Z" }, + { url = "https://files.pythonhosted.org/packages/cd/3c/e3e62eb35a1950292fe39315d3c89941e30a9d07d5d2df42965ab041da43/multidict-6.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000", size = 42368, upload-time = "2025-10-06T14:51:20.225Z" }, + { url = "https://files.pythonhosted.org/packages/8b/40/cd499bd0dbc5f1136726db3153042a735fffd0d77268e2ee20d5f33c010f/multidict-6.7.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63", size = 82326, upload-time = "2025-10-06T14:51:21.588Z" }, + { url = "https://files.pythonhosted.org/packages/13/8a/18e031eca251c8df76daf0288e6790561806e439f5ce99a170b4af30676b/multidict-6.7.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718", size = 48065, upload-time = "2025-10-06T14:51:22.93Z" }, + { url = "https://files.pythonhosted.org/packages/40/71/5e6701277470a87d234e433fb0a3a7deaf3bcd92566e421e7ae9776319de/multidict-6.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2", size = 46475, upload-time = "2025-10-06T14:51:24.352Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6a/bab00cbab6d9cfb57afe1663318f72ec28289ea03fd4e8236bb78429893a/multidict-6.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e", size = 239324, upload-time = "2025-10-06T14:51:25.822Z" }, + { url = "https://files.pythonhosted.org/packages/2a/5f/8de95f629fc22a7769ade8b41028e3e5a822c1f8904f618d175945a81ad3/multidict-6.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064", size = 246877, upload-time = "2025-10-06T14:51:27.604Z" }, + { url = "https://files.pythonhosted.org/packages/23/b4/38881a960458f25b89e9f4a4fdcb02ac101cfa710190db6e5528841e67de/multidict-6.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e", size = 225824, upload-time = "2025-10-06T14:51:29.664Z" }, + { url = "https://files.pythonhosted.org/packages/1e/39/6566210c83f8a261575f18e7144736059f0c460b362e96e9cf797a24b8e7/multidict-6.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd", size = 253558, upload-time = "2025-10-06T14:51:31.684Z" }, + { url = "https://files.pythonhosted.org/packages/00/a3/67f18315100f64c269f46e6c0319fa87ba68f0f64f2b8e7fd7c72b913a0b/multidict-6.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a", size = 252339, upload-time = "2025-10-06T14:51:33.699Z" }, + { url = "https://files.pythonhosted.org/packages/c8/2a/1cb77266afee2458d82f50da41beba02159b1d6b1f7973afc9a1cad1499b/multidict-6.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96", size = 244895, upload-time = "2025-10-06T14:51:36.189Z" }, + { url = "https://files.pythonhosted.org/packages/dd/72/09fa7dd487f119b2eb9524946ddd36e2067c08510576d43ff68469563b3b/multidict-6.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e", size = 241862, upload-time = "2025-10-06T14:51:41.291Z" }, + { url = "https://files.pythonhosted.org/packages/65/92/bc1f8bd0853d8669300f732c801974dfc3702c3eeadae2f60cef54dc69d7/multidict-6.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599", size = 232376, upload-time = "2025-10-06T14:51:43.55Z" }, + { url = "https://files.pythonhosted.org/packages/09/86/ac39399e5cb9d0c2ac8ef6e10a768e4d3bc933ac808d49c41f9dc23337eb/multidict-6.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394", size = 240272, upload-time = "2025-10-06T14:51:45.265Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b6/fed5ac6b8563ec72df6cb1ea8dac6d17f0a4a1f65045f66b6d3bf1497c02/multidict-6.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38", size = 248774, upload-time = "2025-10-06T14:51:46.836Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8d/b954d8c0dc132b68f760aefd45870978deec6818897389dace00fcde32ff/multidict-6.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9", size = 242731, upload-time = "2025-10-06T14:51:48.541Z" }, + { url = "https://files.pythonhosted.org/packages/16/9d/a2dac7009125d3540c2f54e194829ea18ac53716c61b655d8ed300120b0f/multidict-6.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0", size = 240193, upload-time = "2025-10-06T14:51:50.355Z" }, + { url = "https://files.pythonhosted.org/packages/39/ca/c05f144128ea232ae2178b008d5011d4e2cea86e4ee8c85c2631b1b94802/multidict-6.7.0-cp314-cp314t-win32.whl", hash = "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13", size = 48023, upload-time = "2025-10-06T14:51:51.883Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8f/0a60e501584145588be1af5cc829265701ba3c35a64aec8e07cbb71d39bb/multidict-6.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd", size = 53507, upload-time = "2025-10-06T14:51:53.672Z" }, + { url = "https://files.pythonhosted.org/packages/7f/ae/3148b988a9c6239903e786eac19c889fab607c31d6efa7fb2147e5680f23/multidict-6.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827", size = 44804, upload-time = "2025-10-06T14:51:55.415Z" }, + { url = "https://files.pythonhosted.org/packages/b7/da/7d22601b625e241d4f23ef1ebff8acfc60da633c9e7e7922e24d10f592b3/multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3", size = 12317, upload-time = "2025-10-06T14:52:29.272Z" }, +] + +[[package]] +name = "multitail2" +version = "1.5.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/69/03/2ef6c7016e477714bd6258943b90610e2dc264bcf3076393e40ae3565b51/multitail2-1.5.2.tar.gz", hash = "sha256:7086598c1cd1901ec79ce3c1eda9420299e3778f6c18464958c1f74ffd1950c9", size = 3516, upload-time = "2019-08-05T22:51:09.878Z" } + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "parsimonious" +version = "0.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "regex" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7b/91/abdc50c4ef06fdf8d047f60ee777ca9b2a7885e1a9cea81343fbecda52d7/parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c", size = 52172, upload-time = "2022-09-03T17:01:17.004Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/0f/c8b64d9b54ea631fcad4e9e3c8dbe8c11bb32a623be94f22974c88e71eaf/parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f", size = 48427, upload-time = "2022-09-03T17:01:13.814Z" }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/61/33/9611380c2bdb1225fdef633e2a9610622310fed35ab11dac9620972ee088/platformdirs-4.5.0.tar.gz", hash = "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312", size = 21632, upload-time = "2025-10-08T17:44:48.791Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/cb/ac7874b3e5d58441674fb70742e6c374b28b0c7cb988d37d991cde47166c/platformdirs-4.5.0-py3-none-any.whl", hash = "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3", size = 18651, upload-time = "2025-10-08T17:44:47.223Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "propcache" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, + { url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, + { url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, + { url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, + { url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, + { url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, + { url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, + { url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, + { url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, + { url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, + { url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, + { url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" }, + { url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" }, + { url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" }, + { url = "https://files.pythonhosted.org/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" }, + { url = "https://files.pythonhosted.org/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" }, + { url = "https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" }, + { url = "https://files.pythonhosted.org/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" }, + { url = "https://files.pythonhosted.org/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" }, + { url = "https://files.pythonhosted.org/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" }, + { url = "https://files.pythonhosted.org/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" }, + { url = "https://files.pythonhosted.org/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" }, + { url = "https://files.pythonhosted.org/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" }, + { url = "https://files.pythonhosted.org/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" }, + { url = "https://files.pythonhosted.org/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" }, + { url = "https://files.pythonhosted.org/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" }, + { url = "https://files.pythonhosted.org/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" }, + { url = "https://files.pythonhosted.org/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" }, + { url = "https://files.pythonhosted.org/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" }, + { url = "https://files.pythonhosted.org/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" }, + { url = "https://files.pythonhosted.org/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" }, + { url = "https://files.pythonhosted.org/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" }, + { url = "https://files.pythonhosted.org/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" }, + { url = "https://files.pythonhosted.org/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" }, + { url = "https://files.pythonhosted.org/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" }, + { url = "https://files.pythonhosted.org/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" }, + { url = "https://files.pythonhosted.org/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" }, + { url = "https://files.pythonhosted.org/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" }, + { url = "https://files.pythonhosted.org/packages/8e/5c/bca52d654a896f831b8256683457ceddd490ec18d9ec50e97dfd8fc726a8/propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", size = 78152, upload-time = "2025-10-08T19:47:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/65/9b/03b04e7d82a5f54fb16113d839f5ea1ede58a61e90edf515f6577c66fa8f/propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", size = 44869, upload-time = "2025-10-08T19:47:52.594Z" }, + { url = "https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", size = 46596, upload-time = "2025-10-08T19:47:54.073Z" }, + { url = "https://files.pythonhosted.org/packages/86/bd/47816020d337f4a746edc42fe8d53669965138f39ee117414c7d7a340cfe/propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", size = 206981, upload-time = "2025-10-08T19:47:55.715Z" }, + { url = "https://files.pythonhosted.org/packages/df/f6/c5fa1357cc9748510ee55f37173eb31bfde6d94e98ccd9e6f033f2fc06e1/propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", size = 211490, upload-time = "2025-10-08T19:47:57.499Z" }, + { url = "https://files.pythonhosted.org/packages/80/1e/e5889652a7c4a3846683401a48f0f2e5083ce0ec1a8a5221d8058fbd1adf/propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", size = 215371, upload-time = "2025-10-08T19:47:59.317Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", size = 201424, upload-time = "2025-10-08T19:48:00.67Z" }, + { url = "https://files.pythonhosted.org/packages/27/73/033d63069b57b0812c8bd19f311faebeceb6ba31b8f32b73432d12a0b826/propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", size = 197566, upload-time = "2025-10-08T19:48:02.604Z" }, + { url = "https://files.pythonhosted.org/packages/dc/89/ce24f3dc182630b4e07aa6d15f0ff4b14ed4b9955fae95a0b54c58d66c05/propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", size = 193130, upload-time = "2025-10-08T19:48:04.499Z" }, + { url = "https://files.pythonhosted.org/packages/a9/24/ef0d5fd1a811fb5c609278d0209c9f10c35f20581fcc16f818da959fc5b4/propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", size = 202625, upload-time = "2025-10-08T19:48:06.213Z" }, + { url = "https://files.pythonhosted.org/packages/f5/02/98ec20ff5546f68d673df2f7a69e8c0d076b5abd05ca882dc7ee3a83653d/propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", size = 204209, upload-time = "2025-10-08T19:48:08.432Z" }, + { url = "https://files.pythonhosted.org/packages/a0/87/492694f76759b15f0467a2a93ab68d32859672b646aa8a04ce4864e7932d/propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", size = 197797, upload-time = "2025-10-08T19:48:09.968Z" }, + { url = "https://files.pythonhosted.org/packages/ee/36/66367de3575db1d2d3f3d177432bd14ee577a39d3f5d1b3d5df8afe3b6e2/propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", size = 38140, upload-time = "2025-10-08T19:48:11.232Z" }, + { url = "https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", size = 41257, upload-time = "2025-10-08T19:48:12.707Z" }, + { url = "https://files.pythonhosted.org/packages/34/5e/63bd5896c3fec12edcbd6f12508d4890d23c265df28c74b175e1ef9f4f3b/propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", size = 38097, upload-time = "2025-10-08T19:48:13.923Z" }, + { url = "https://files.pythonhosted.org/packages/99/85/9ff785d787ccf9bbb3f3106f79884a130951436f58392000231b4c737c80/propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", size = 81455, upload-time = "2025-10-08T19:48:15.16Z" }, + { url = "https://files.pythonhosted.org/packages/90/85/2431c10c8e7ddb1445c1f7c4b54d886e8ad20e3c6307e7218f05922cad67/propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", size = 46372, upload-time = "2025-10-08T19:48:16.424Z" }, + { url = "https://files.pythonhosted.org/packages/01/20/b0972d902472da9bcb683fa595099911f4d2e86e5683bcc45de60dd05dc3/propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", size = 48411, upload-time = "2025-10-08T19:48:17.577Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e3/7dc89f4f21e8f99bad3d5ddb3a3389afcf9da4ac69e3deb2dcdc96e74169/propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", size = 275712, upload-time = "2025-10-08T19:48:18.901Z" }, + { url = "https://files.pythonhosted.org/packages/20/67/89800c8352489b21a8047c773067644e3897f02ecbbd610f4d46b7f08612/propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", size = 273557, upload-time = "2025-10-08T19:48:20.762Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a1/b52b055c766a54ce6d9c16d9aca0cad8059acd9637cdf8aa0222f4a026ef/propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", size = 280015, upload-time = "2025-10-08T19:48:22.592Z" }, + { url = "https://files.pythonhosted.org/packages/48/c8/33cee30bd890672c63743049f3c9e4be087e6780906bfc3ec58528be59c1/propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", size = 262880, upload-time = "2025-10-08T19:48:23.947Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b1/8f08a143b204b418285c88b83d00edbd61afbc2c6415ffafc8905da7038b/propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", size = 260938, upload-time = "2025-10-08T19:48:25.656Z" }, + { url = "https://files.pythonhosted.org/packages/cf/12/96e4664c82ca2f31e1c8dff86afb867348979eb78d3cb8546a680287a1e9/propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", size = 247641, upload-time = "2025-10-08T19:48:27.207Z" }, + { url = "https://files.pythonhosted.org/packages/18/ed/e7a9cfca28133386ba52278136d42209d3125db08d0a6395f0cba0c0285c/propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", size = 262510, upload-time = "2025-10-08T19:48:28.65Z" }, + { url = "https://files.pythonhosted.org/packages/f5/76/16d8bf65e8845dd62b4e2b57444ab81f07f40caa5652b8969b87ddcf2ef6/propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", size = 263161, upload-time = "2025-10-08T19:48:30.133Z" }, + { url = "https://files.pythonhosted.org/packages/e7/70/c99e9edb5d91d5ad8a49fa3c1e8285ba64f1476782fed10ab251ff413ba1/propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", size = 257393, upload-time = "2025-10-08T19:48:31.567Z" }, + { url = "https://files.pythonhosted.org/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", size = 42546, upload-time = "2025-10-08T19:48:32.872Z" }, + { url = "https://files.pythonhosted.org/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", size = 46259, upload-time = "2025-10-08T19:48:34.226Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", size = 40428, upload-time = "2025-10-08T19:48:35.441Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, +] + +[[package]] +name = "py-ecc" +version = "8.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eth-typing" }, + { name = "eth-utils" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/96/e73075d5c885274efada2fbc5db6377022036c2f5b4b470dbcf4106e07d5/py_ecc-8.0.0.tar.gz", hash = "sha256:56aca19e5dc37294f60c1cc76666c03c2276e7666412b9a559fa0145d099933d", size = 51193, upload-time = "2025-04-14T16:14:03.29Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/58/383335eac96d2f1aba78741c6ce128c54e7eba2ea1dc47408257d751d35c/py_ecc-8.0.0-py3-none-any.whl", hash = "sha256:c0b2dfc4bde67a55122a392591a10e851a986d5128f680628c80b405f7663e13", size = 47814, upload-time = "2025-04-14T16:14:01.827Z" }, +] + +[[package]] +name = "pycodestyle" +version = "2.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/e0/abfd2a0d2efe47670df87f3e3a0e2edda42f055053c85361f19c0e2c1ca8/pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783", size = 39472, upload-time = "2025-06-20T18:49:48.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d", size = 31594, upload-time = "2025-06-20T18:49:47.491Z" }, +] + +[[package]] +name = "pycryptodome" +version = "3.23.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276, upload-time = "2025-05-17T17:21:45.242Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152, upload-time = "2025-05-17T17:20:20.833Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348, upload-time = "2025-05-17T17:20:23.171Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033, upload-time = "2025-05-17T17:20:25.424Z" }, + { url = "https://files.pythonhosted.org/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142, upload-time = "2025-05-17T17:20:27.808Z" }, + { url = "https://files.pythonhosted.org/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384, upload-time = "2025-05-17T17:20:30.765Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237, upload-time = "2025-05-17T17:20:33.736Z" }, + { url = "https://files.pythonhosted.org/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898, upload-time = "2025-05-17T17:20:36.086Z" }, + { url = "https://files.pythonhosted.org/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197, upload-time = "2025-05-17T17:20:38.414Z" }, + { url = "https://files.pythonhosted.org/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600, upload-time = "2025-05-17T17:20:40.688Z" }, + { url = "https://files.pythonhosted.org/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740, upload-time = "2025-05-17T17:20:42.413Z" }, + { url = "https://files.pythonhosted.org/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685, upload-time = "2025-05-17T17:20:44.388Z" }, + { url = "https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627, upload-time = "2025-05-17T17:20:47.139Z" }, + { url = "https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362, upload-time = "2025-05-17T17:20:50.392Z" }, + { url = "https://files.pythonhosted.org/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625, upload-time = "2025-05-17T17:20:52.866Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954, upload-time = "2025-05-17T17:20:55.027Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534, upload-time = "2025-05-17T17:20:57.279Z" }, + { url = "https://files.pythonhosted.org/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853, upload-time = "2025-05-17T17:20:59.322Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465, upload-time = "2025-05-17T17:21:03.83Z" }, + { url = "https://files.pythonhosted.org/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414, upload-time = "2025-05-17T17:21:06.72Z" }, + { url = "https://files.pythonhosted.org/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484, upload-time = "2025-05-17T17:21:08.535Z" }, + { url = "https://files.pythonhosted.org/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636, upload-time = "2025-05-17T17:21:10.393Z" }, + { url = "https://files.pythonhosted.org/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675, upload-time = "2025-05-17T17:21:13.146Z" }, +] + +[[package]] +name = "pydantic" +version = "2.12.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/ad/a17bc283d7d81837c061c49e3eaa27a45991759a1b7eae1031921c6bd924/pydantic-2.12.4.tar.gz", hash = "sha256:0f8cb9555000a4b5b617f66bfd2566264c4984b27589d3b845685983e8ea85ac", size = 821038, upload-time = "2025-11-05T10:50:08.59Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl", hash = "sha256:92d3d202a745d46f9be6df459ac5a064fdaa3c1c4cd8adcfa332ccf3c05f871e", size = 463400, upload-time = "2025-11-05T10:50:06.732Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.41.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, + { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, + { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, + { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, + { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, + { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, + { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, + { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, + { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, + { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, + { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, + { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, + { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, + { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, + { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, + { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, + { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, + { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, + { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, + { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, + { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, + { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, + { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, + { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, + { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, + { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, + { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, + { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, + { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, + { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, + { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, + { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, + { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, + { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, + { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, + { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, + { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, + { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, + { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, +] + +[[package]] +name = "pyflakes" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/45/dc/fd034dc20b4b264b3d015808458391acbf9df40b1e54750ef175d39180b1/pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58", size = 64669, upload-time = "2025-06-20T18:45:27.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f", size = 63551, upload-time = "2025-06-20T18:45:26.937Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pyrevm" +version = "0.3.6" +source = { git = "https://github.com/yihuang/pyrevm.git?branch=master#ef0903ad7ca3d01e675105b63302d07cd03ea4b1" } + +[[package]] +name = "pystarport" +version = "0.2.5" +source = { git = "https://github.com/MANTRA-Chain/pystarport.git?branch=main#daf72216bcd3169340d5ee2cb00bbd4f7b64a51d" } +dependencies = [ + { name = "bech32" }, + { name = "docker" }, + { name = "durations" }, + { name = "fire" }, + { name = "grpcio" }, + { name = "jsonmerge" }, + { name = "jsonnet" }, + { name = "multitail2" }, + { name = "python-dateutil" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "pyyaml-include" }, + { name = "supervisor" }, + { name = "tomlkit" }, +] + +[[package]] +name = "pytest" +version = "9.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/56/f013048ac4bc4c1d9be45afd4ab209ea62822fb1598f40687e6bf45dcea4/pytest-9.0.1.tar.gz", hash = "sha256:3e9c069ea73583e255c3b21cf46b8d3c56f6e3a1a8f6da94ccb0fcf57b9d73c8", size = 1564125, upload-time = "2025-11-12T13:05:09.333Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/8b/6300fb80f858cda1c51ffa17075df5d846757081d11ab4aa35cef9e6258b/pytest-9.0.1-py3-none-any.whl", hash = "sha256:67be0030d194df2dfa7b556f2e56fb3c3315bd5c8822c6951162b92b32ce7dad", size = 373668, upload-time = "2025-11-12T13:05:07.379Z" }, +] + +[[package]] +name = "pytest-asyncio" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" }, +] + +[[package]] +name = "pytest-github-actions-annotate-failures" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/39/d4/c54ee6a871eee4a7468e3a8c0dead28e634c0bc2110c694309dcb7563a66/pytest_github_actions_annotate_failures-0.3.0.tar.gz", hash = "sha256:d4c3177c98046c3900a7f8ddebb22ea54b9f6822201b5d3ab8fcdea51e010db7", size = 11248, upload-time = "2025-01-17T22:39:32.722Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/73/7b0b15cb8605ee967b34aa1d949737ab664f94e6b0f1534e8339d9e64ab2/pytest_github_actions_annotate_failures-0.3.0-py3-none-any.whl", hash = "sha256:41ea558ba10c332c0bfc053daeee0c85187507b2034e990f21e4f7e5fef044cf", size = 6030, upload-time = "2025-01-17T22:39:31.701Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, +] + +[[package]] +name = "pytokens" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/8d/a762be14dae1c3bf280202ba3172020b2b0b4c537f94427435f19c413b72/pytokens-0.3.0.tar.gz", hash = "sha256:2f932b14ed08de5fcf0b391ace2642f858f1394c0857202959000b68ed7a458a", size = 17644, upload-time = "2025-11-05T13:36:35.34Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/25/d9db8be44e205a124f6c98bc0324b2bb149b7431c53877fc6d1038dddaf5/pytokens-0.3.0-py3-none-any.whl", hash = "sha256:95b2b5eaf832e469d141a378872480ede3f251a5a5041b8ec6e581d3ac71bbf3", size = 12195, upload-time = "2025-11-05T13:36:33.183Z" }, +] + +[[package]] +name = "pyunormalize" +version = "17.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/25/ab/b912c484cfb96ba4834efe050bbf10c9e157bd8189eb859aefba8712b136/pyunormalize-17.0.0.tar.gz", hash = "sha256:0949a3e56817e287febcaf1b0cc4b5adf0bb107628d379335938040947eec792", size = 53121, upload-time = "2025-09-28T20:53:06.141Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/80/61512483dc509e3ae8a42fb143479d1e406ce1d91f8f08d538a3dde39c6d/pyunormalize-17.0.0-py3-none-any.whl", hash = "sha256:f0d93b076f938db2b26d319d04f2b58505d1cd7a80b5b72badbe7d1aa4d2a31c", size = 51358, upload-time = "2025-09-28T20:53:04.876Z" }, +] + +[[package]] +name = "pywin32" +version = "311" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, + { url = "https://files.pythonhosted.org/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, + { url = "https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, + { url = "https://files.pythonhosted.org/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, + { url = "https://files.pythonhosted.org/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" }, + { url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "pyyaml-include" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7f/be/2d07ad85e3d593d69640876a8686eae2c533db8cb7bf298d25c421b4d2d5/pyyaml-include-1.4.1.tar.gz", hash = "sha256:1a96e33a99a3e56235f5221273832464025f02ff3d8539309a3bf00dec624471", size = 20592, upload-time = "2024-03-25T14:56:43.748Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/ca/6a2cc3a73170d10b5af1f1613baa2ed1f8f46f62dd0bfab2bffd2c2fe260/pyyaml_include-1.4.1-py3-none-any.whl", hash = "sha256:323c7f3a19c82fbc4d73abbaab7ef4f793e146a13383866831631b26ccc7fb00", size = 19079, upload-time = "2024-03-25T14:56:41.274Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "regex" +version = "2025.11.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/a9/546676f25e573a4cf00fe8e119b78a37b6a8fe2dc95cda877b30889c9c45/regex-2025.11.3.tar.gz", hash = "sha256:1fedc720f9bb2494ce31a58a1631f9c82df6a09b49c19517ea5cc280b4541e01", size = 414669, upload-time = "2025-11-03T21:34:22.089Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/74/18f04cb53e58e3fb107439699bd8375cf5a835eec81084e0bddbd122e4c2/regex-2025.11.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bc8ab71e2e31b16e40868a40a69007bc305e1109bd4658eb6cad007e0bf67c41", size = 489312, upload-time = "2025-11-03T21:31:34.343Z" }, + { url = "https://files.pythonhosted.org/packages/78/3f/37fcdd0d2b1e78909108a876580485ea37c91e1acf66d3bb8e736348f441/regex-2025.11.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:22b29dda7e1f7062a52359fca6e58e548e28c6686f205e780b02ad8ef710de36", size = 291256, upload-time = "2025-11-03T21:31:35.675Z" }, + { url = "https://files.pythonhosted.org/packages/bf/26/0a575f58eb23b7ebd67a45fccbc02ac030b737b896b7e7a909ffe43ffd6a/regex-2025.11.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3a91e4a29938bc1a082cc28fdea44be420bf2bebe2665343029723892eb073e1", size = 288921, upload-time = "2025-11-03T21:31:37.07Z" }, + { url = "https://files.pythonhosted.org/packages/ea/98/6a8dff667d1af907150432cf5abc05a17ccd32c72a3615410d5365ac167a/regex-2025.11.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08b884f4226602ad40c5d55f52bf91a9df30f513864e0054bad40c0e9cf1afb7", size = 798568, upload-time = "2025-11-03T21:31:38.784Z" }, + { url = "https://files.pythonhosted.org/packages/64/15/92c1db4fa4e12733dd5a526c2dd2b6edcbfe13257e135fc0f6c57f34c173/regex-2025.11.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3e0b11b2b2433d1c39c7c7a30e3f3d0aeeea44c2a8d0bae28f6b95f639927a69", size = 864165, upload-time = "2025-11-03T21:31:40.559Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e7/3ad7da8cdee1ce66c7cd37ab5ab05c463a86ffeb52b1a25fe7bd9293b36c/regex-2025.11.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:87eb52a81ef58c7ba4d45c3ca74e12aa4b4e77816f72ca25258a85b3ea96cb48", size = 912182, upload-time = "2025-11-03T21:31:42.002Z" }, + { url = "https://files.pythonhosted.org/packages/84/bd/9ce9f629fcb714ffc2c3faf62b6766ecb7a585e1e885eb699bcf130a5209/regex-2025.11.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a12ab1f5c29b4e93db518f5e3872116b7e9b1646c9f9f426f777b50d44a09e8c", size = 803501, upload-time = "2025-11-03T21:31:43.815Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0f/8dc2e4349d8e877283e6edd6c12bdcebc20f03744e86f197ab6e4492bf08/regex-2025.11.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7521684c8c7c4f6e88e35ec89680ee1aa8358d3f09d27dfbdf62c446f5d4c695", size = 787842, upload-time = "2025-11-03T21:31:45.353Z" }, + { url = "https://files.pythonhosted.org/packages/f9/73/cff02702960bc185164d5619c0c62a2f598a6abff6695d391b096237d4ab/regex-2025.11.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7fe6e5440584e94cc4b3f5f4d98a25e29ca12dccf8873679a635638349831b98", size = 858519, upload-time = "2025-11-03T21:31:46.814Z" }, + { url = "https://files.pythonhosted.org/packages/61/83/0e8d1ae71e15bc1dc36231c90b46ee35f9d52fab2e226b0e039e7ea9c10a/regex-2025.11.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8e026094aa12b43f4fd74576714e987803a315c76edb6b098b9809db5de58f74", size = 850611, upload-time = "2025-11-03T21:31:48.289Z" }, + { url = "https://files.pythonhosted.org/packages/c8/f5/70a5cdd781dcfaa12556f2955bf170cd603cb1c96a1827479f8faea2df97/regex-2025.11.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:435bbad13e57eb5606a68443af62bed3556de2f46deb9f7d4237bc2f1c9fb3a0", size = 789759, upload-time = "2025-11-03T21:31:49.759Z" }, + { url = "https://files.pythonhosted.org/packages/59/9b/7c29be7903c318488983e7d97abcf8ebd3830e4c956c4c540005fcfb0462/regex-2025.11.3-cp312-cp312-win32.whl", hash = "sha256:3839967cf4dc4b985e1570fd8d91078f0c519f30491c60f9ac42a8db039be204", size = 266194, upload-time = "2025-11-03T21:31:51.53Z" }, + { url = "https://files.pythonhosted.org/packages/1a/67/3b92df89f179d7c367be654ab5626ae311cb28f7d5c237b6bb976cd5fbbb/regex-2025.11.3-cp312-cp312-win_amd64.whl", hash = "sha256:e721d1b46e25c481dc5ded6f4b3f66c897c58d2e8cfdf77bbced84339108b0b9", size = 277069, upload-time = "2025-11-03T21:31:53.151Z" }, + { url = "https://files.pythonhosted.org/packages/d7/55/85ba4c066fe5094d35b249c3ce8df0ba623cfd35afb22d6764f23a52a1c5/regex-2025.11.3-cp312-cp312-win_arm64.whl", hash = "sha256:64350685ff08b1d3a6fff33f45a9ca183dc1d58bbfe4981604e70ec9801bbc26", size = 270330, upload-time = "2025-11-03T21:31:54.514Z" }, + { url = "https://files.pythonhosted.org/packages/e1/a7/dda24ebd49da46a197436ad96378f17df30ceb40e52e859fc42cac45b850/regex-2025.11.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c1e448051717a334891f2b9a620fe36776ebf3dd8ec46a0b877c8ae69575feb4", size = 489081, upload-time = "2025-11-03T21:31:55.9Z" }, + { url = "https://files.pythonhosted.org/packages/19/22/af2dc751aacf88089836aa088a1a11c4f21a04707eb1b0478e8e8fb32847/regex-2025.11.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9b5aca4d5dfd7fbfbfbdaf44850fcc7709a01146a797536a8f84952e940cca76", size = 291123, upload-time = "2025-11-03T21:31:57.758Z" }, + { url = "https://files.pythonhosted.org/packages/a3/88/1a3ea5672f4b0a84802ee9891b86743438e7c04eb0b8f8c4e16a42375327/regex-2025.11.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:04d2765516395cf7dda331a244a3282c0f5ae96075f728629287dfa6f76ba70a", size = 288814, upload-time = "2025-11-03T21:32:01.12Z" }, + { url = "https://files.pythonhosted.org/packages/fb/8c/f5987895bf42b8ddeea1b315c9fedcfe07cadee28b9c98cf50d00adcb14d/regex-2025.11.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d9903ca42bfeec4cebedba8022a7c97ad2aab22e09573ce9976ba01b65e4361", size = 798592, upload-time = "2025-11-03T21:32:03.006Z" }, + { url = "https://files.pythonhosted.org/packages/99/2a/6591ebeede78203fa77ee46a1c36649e02df9eaa77a033d1ccdf2fcd5d4e/regex-2025.11.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:639431bdc89d6429f6721625e8129413980ccd62e9d3f496be618a41d205f160", size = 864122, upload-time = "2025-11-03T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/94/d6/be32a87cf28cf8ed064ff281cfbd49aefd90242a83e4b08b5a86b38e8eb4/regex-2025.11.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f117efad42068f9715677c8523ed2be1518116d1c49b1dd17987716695181efe", size = 912272, upload-time = "2025-11-03T21:32:06.148Z" }, + { url = "https://files.pythonhosted.org/packages/62/11/9bcef2d1445665b180ac7f230406ad80671f0fc2a6ffb93493b5dd8cd64c/regex-2025.11.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4aecb6f461316adf9f1f0f6a4a1a3d79e045f9b71ec76055a791affa3b285850", size = 803497, upload-time = "2025-11-03T21:32:08.162Z" }, + { url = "https://files.pythonhosted.org/packages/e5/a7/da0dc273d57f560399aa16d8a68ae7f9b57679476fc7ace46501d455fe84/regex-2025.11.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3b3a5f320136873cc5561098dfab677eea139521cb9a9e8db98b7e64aef44cbc", size = 787892, upload-time = "2025-11-03T21:32:09.769Z" }, + { url = "https://files.pythonhosted.org/packages/da/4b/732a0c5a9736a0b8d6d720d4945a2f1e6f38f87f48f3173559f53e8d5d82/regex-2025.11.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:75fa6f0056e7efb1f42a1c34e58be24072cb9e61a601340cc1196ae92326a4f9", size = 858462, upload-time = "2025-11-03T21:32:11.769Z" }, + { url = "https://files.pythonhosted.org/packages/0c/f5/a2a03df27dc4c2d0c769220f5110ba8c4084b0bfa9ab0f9b4fcfa3d2b0fc/regex-2025.11.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:dbe6095001465294f13f1adcd3311e50dd84e5a71525f20a10bd16689c61ce0b", size = 850528, upload-time = "2025-11-03T21:32:13.906Z" }, + { url = "https://files.pythonhosted.org/packages/d6/09/e1cd5bee3841c7f6eb37d95ca91cdee7100b8f88b81e41c2ef426910891a/regex-2025.11.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:454d9b4ae7881afbc25015b8627c16d88a597479b9dea82b8c6e7e2e07240dc7", size = 789866, upload-time = "2025-11-03T21:32:15.748Z" }, + { url = "https://files.pythonhosted.org/packages/eb/51/702f5ea74e2a9c13d855a6a85b7f80c30f9e72a95493260193c07f3f8d74/regex-2025.11.3-cp313-cp313-win32.whl", hash = "sha256:28ba4d69171fc6e9896337d4fc63a43660002b7da53fc15ac992abcf3410917c", size = 266189, upload-time = "2025-11-03T21:32:17.493Z" }, + { url = "https://files.pythonhosted.org/packages/8b/00/6e29bb314e271a743170e53649db0fdb8e8ff0b64b4f425f5602f4eb9014/regex-2025.11.3-cp313-cp313-win_amd64.whl", hash = "sha256:bac4200befe50c670c405dc33af26dad5a3b6b255dd6c000d92fe4629f9ed6a5", size = 277054, upload-time = "2025-11-03T21:32:19.042Z" }, + { url = "https://files.pythonhosted.org/packages/25/f1/b156ff9f2ec9ac441710764dda95e4edaf5f36aca48246d1eea3f1fd96ec/regex-2025.11.3-cp313-cp313-win_arm64.whl", hash = "sha256:2292cd5a90dab247f9abe892ac584cb24f0f54680c73fcb4a7493c66c2bf2467", size = 270325, upload-time = "2025-11-03T21:32:21.338Z" }, + { url = "https://files.pythonhosted.org/packages/20/28/fd0c63357caefe5680b8ea052131acbd7f456893b69cc2a90cc3e0dc90d4/regex-2025.11.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:1eb1ebf6822b756c723e09f5186473d93236c06c579d2cc0671a722d2ab14281", size = 491984, upload-time = "2025-11-03T21:32:23.466Z" }, + { url = "https://files.pythonhosted.org/packages/df/ec/7014c15626ab46b902b3bcc4b28a7bae46d8f281fc7ea9c95e22fcaaa917/regex-2025.11.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1e00ec2970aab10dc5db34af535f21fcf32b4a31d99e34963419636e2f85ae39", size = 292673, upload-time = "2025-11-03T21:32:25.034Z" }, + { url = "https://files.pythonhosted.org/packages/23/ab/3b952ff7239f20d05f1f99e9e20188513905f218c81d52fb5e78d2bf7634/regex-2025.11.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a4cb042b615245d5ff9b3794f56be4138b5adc35a4166014d31d1814744148c7", size = 291029, upload-time = "2025-11-03T21:32:26.528Z" }, + { url = "https://files.pythonhosted.org/packages/21/7e/3dc2749fc684f455f162dcafb8a187b559e2614f3826877d3844a131f37b/regex-2025.11.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44f264d4bf02f3176467d90b294d59bf1db9fe53c141ff772f27a8b456b2a9ed", size = 807437, upload-time = "2025-11-03T21:32:28.363Z" }, + { url = "https://files.pythonhosted.org/packages/1b/0b/d529a85ab349c6a25d1ca783235b6e3eedf187247eab536797021f7126c6/regex-2025.11.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7be0277469bf3bd7a34a9c57c1b6a724532a0d235cd0dc4e7f4316f982c28b19", size = 873368, upload-time = "2025-11-03T21:32:30.4Z" }, + { url = "https://files.pythonhosted.org/packages/7d/18/2d868155f8c9e3e9d8f9e10c64e9a9f496bb8f7e037a88a8bed26b435af6/regex-2025.11.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0d31e08426ff4b5b650f68839f5af51a92a5b51abd8554a60c2fbc7c71f25d0b", size = 914921, upload-time = "2025-11-03T21:32:32.123Z" }, + { url = "https://files.pythonhosted.org/packages/2d/71/9d72ff0f354fa783fe2ba913c8734c3b433b86406117a8db4ea2bf1c7a2f/regex-2025.11.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e43586ce5bd28f9f285a6e729466841368c4a0353f6fd08d4ce4630843d3648a", size = 812708, upload-time = "2025-11-03T21:32:34.305Z" }, + { url = "https://files.pythonhosted.org/packages/e7/19/ce4bf7f5575c97f82b6e804ffb5c4e940c62609ab2a0d9538d47a7fdf7d4/regex-2025.11.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0f9397d561a4c16829d4e6ff75202c1c08b68a3bdbfe29dbfcdb31c9830907c6", size = 795472, upload-time = "2025-11-03T21:32:36.364Z" }, + { url = "https://files.pythonhosted.org/packages/03/86/fd1063a176ffb7b2315f9a1b08d17b18118b28d9df163132615b835a26ee/regex-2025.11.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:dd16e78eb18ffdb25ee33a0682d17912e8cc8a770e885aeee95020046128f1ce", size = 868341, upload-time = "2025-11-03T21:32:38.042Z" }, + { url = "https://files.pythonhosted.org/packages/12/43/103fb2e9811205e7386366501bc866a164a0430c79dd59eac886a2822950/regex-2025.11.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:ffcca5b9efe948ba0661e9df0fa50d2bc4b097c70b9810212d6b62f05d83b2dd", size = 854666, upload-time = "2025-11-03T21:32:40.079Z" }, + { url = "https://files.pythonhosted.org/packages/7d/22/e392e53f3869b75804762c7c848bd2dd2abf2b70fb0e526f58724638bd35/regex-2025.11.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c56b4d162ca2b43318ac671c65bd4d563e841a694ac70e1a976ac38fcf4ca1d2", size = 799473, upload-time = "2025-11-03T21:32:42.148Z" }, + { url = "https://files.pythonhosted.org/packages/4f/f9/8bd6b656592f925b6845fcbb4d57603a3ac2fb2373344ffa1ed70aa6820a/regex-2025.11.3-cp313-cp313t-win32.whl", hash = "sha256:9ddc42e68114e161e51e272f667d640f97e84a2b9ef14b7477c53aac20c2d59a", size = 268792, upload-time = "2025-11-03T21:32:44.13Z" }, + { url = "https://files.pythonhosted.org/packages/e5/87/0e7d603467775ff65cd2aeabf1b5b50cc1c3708556a8b849a2fa4dd1542b/regex-2025.11.3-cp313-cp313t-win_amd64.whl", hash = "sha256:7a7c7fdf755032ffdd72c77e3d8096bdcb0eb92e89e17571a196f03d88b11b3c", size = 280214, upload-time = "2025-11-03T21:32:45.853Z" }, + { url = "https://files.pythonhosted.org/packages/8d/d0/2afc6f8e94e2b64bfb738a7c2b6387ac1699f09f032d363ed9447fd2bb57/regex-2025.11.3-cp313-cp313t-win_arm64.whl", hash = "sha256:df9eb838c44f570283712e7cff14c16329a9f0fb19ca492d21d4b7528ee6821e", size = 271469, upload-time = "2025-11-03T21:32:48.026Z" }, + { url = "https://files.pythonhosted.org/packages/31/e9/f6e13de7e0983837f7b6d238ad9458800a874bf37c264f7923e63409944c/regex-2025.11.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9697a52e57576c83139d7c6f213d64485d3df5bf84807c35fa409e6c970801c6", size = 489089, upload-time = "2025-11-03T21:32:50.027Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5c/261f4a262f1fa65141c1b74b255988bd2fa020cc599e53b080667d591cfc/regex-2025.11.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e18bc3f73bd41243c9b38a6d9f2366cd0e0137a9aebe2d8ff76c5b67d4c0a3f4", size = 291059, upload-time = "2025-11-03T21:32:51.682Z" }, + { url = "https://files.pythonhosted.org/packages/8e/57/f14eeb7f072b0e9a5a090d1712741fd8f214ec193dba773cf5410108bb7d/regex-2025.11.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:61a08bcb0ec14ff4e0ed2044aad948d0659604f824cbd50b55e30b0ec6f09c73", size = 288900, upload-time = "2025-11-03T21:32:53.569Z" }, + { url = "https://files.pythonhosted.org/packages/3c/6b/1d650c45e99a9b327586739d926a1cd4e94666b1bd4af90428b36af66dc7/regex-2025.11.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9c30003b9347c24bcc210958c5d167b9e4f9be786cb380a7d32f14f9b84674f", size = 799010, upload-time = "2025-11-03T21:32:55.222Z" }, + { url = "https://files.pythonhosted.org/packages/99/ee/d66dcbc6b628ce4e3f7f0cbbb84603aa2fc0ffc878babc857726b8aab2e9/regex-2025.11.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4e1e592789704459900728d88d41a46fe3969b82ab62945560a31732ffc19a6d", size = 864893, upload-time = "2025-11-03T21:32:57.239Z" }, + { url = "https://files.pythonhosted.org/packages/bf/2d/f238229f1caba7ac87a6c4153d79947fb0261415827ae0f77c304260c7d3/regex-2025.11.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6538241f45eb5a25aa575dbba1069ad786f68a4f2773a29a2bd3dd1f9de787be", size = 911522, upload-time = "2025-11-03T21:32:59.274Z" }, + { url = "https://files.pythonhosted.org/packages/bd/3d/22a4eaba214a917c80e04f6025d26143690f0419511e0116508e24b11c9b/regex-2025.11.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce22519c989bb72a7e6b36a199384c53db7722fe669ba891da75907fe3587db", size = 803272, upload-time = "2025-11-03T21:33:01.393Z" }, + { url = "https://files.pythonhosted.org/packages/84/b1/03188f634a409353a84b5ef49754b97dbcc0c0f6fd6c8ede505a8960a0a4/regex-2025.11.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:66d559b21d3640203ab9075797a55165d79017520685fb407b9234d72ab63c62", size = 787958, upload-time = "2025-11-03T21:33:03.379Z" }, + { url = "https://files.pythonhosted.org/packages/99/6a/27d072f7fbf6fadd59c64d210305e1ff865cc3b78b526fd147db768c553b/regex-2025.11.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:669dcfb2e38f9e8c69507bace46f4889e3abbfd9b0c29719202883c0a603598f", size = 859289, upload-time = "2025-11-03T21:33:05.374Z" }, + { url = "https://files.pythonhosted.org/packages/9a/70/1b3878f648e0b6abe023172dacb02157e685564853cc363d9961bcccde4e/regex-2025.11.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:32f74f35ff0f25a5021373ac61442edcb150731fbaa28286bbc8bb1582c89d02", size = 850026, upload-time = "2025-11-03T21:33:07.131Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d5/68e25559b526b8baab8e66839304ede68ff6727237a47727d240006bd0ff/regex-2025.11.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e6c7a21dffba883234baefe91bc3388e629779582038f75d2a5be918e250f0ed", size = 789499, upload-time = "2025-11-03T21:33:09.141Z" }, + { url = "https://files.pythonhosted.org/packages/fc/df/43971264857140a350910d4e33df725e8c94dd9dee8d2e4729fa0d63d49e/regex-2025.11.3-cp314-cp314-win32.whl", hash = "sha256:795ea137b1d809eb6836b43748b12634291c0ed55ad50a7d72d21edf1cd565c4", size = 271604, upload-time = "2025-11-03T21:33:10.9Z" }, + { url = "https://files.pythonhosted.org/packages/01/6f/9711b57dc6894a55faf80a4c1b5aa4f8649805cb9c7aef46f7d27e2b9206/regex-2025.11.3-cp314-cp314-win_amd64.whl", hash = "sha256:9f95fbaa0ee1610ec0fc6b26668e9917a582ba80c52cc6d9ada15e30aa9ab9ad", size = 280320, upload-time = "2025-11-03T21:33:12.572Z" }, + { url = "https://files.pythonhosted.org/packages/f1/7e/f6eaa207d4377481f5e1775cdeb5a443b5a59b392d0065f3417d31d80f87/regex-2025.11.3-cp314-cp314-win_arm64.whl", hash = "sha256:dfec44d532be4c07088c3de2876130ff0fbeeacaa89a137decbbb5f665855a0f", size = 273372, upload-time = "2025-11-03T21:33:14.219Z" }, + { url = "https://files.pythonhosted.org/packages/c3/06/49b198550ee0f5e4184271cee87ba4dfd9692c91ec55289e6282f0f86ccf/regex-2025.11.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ba0d8a5d7f04f73ee7d01d974d47c5834f8a1b0224390e4fe7c12a3a92a78ecc", size = 491985, upload-time = "2025-11-03T21:33:16.555Z" }, + { url = "https://files.pythonhosted.org/packages/ce/bf/abdafade008f0b1c9da10d934034cb670432d6cf6cbe38bbb53a1cfd6cf8/regex-2025.11.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:442d86cf1cfe4faabf97db7d901ef58347efd004934da045c745e7b5bd57ac49", size = 292669, upload-time = "2025-11-03T21:33:18.32Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ef/0c357bb8edbd2ad8e273fcb9e1761bc37b8acbc6e1be050bebd6475f19c1/regex-2025.11.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:fd0a5e563c756de210bb964789b5abe4f114dacae9104a47e1a649b910361536", size = 291030, upload-time = "2025-11-03T21:33:20.048Z" }, + { url = "https://files.pythonhosted.org/packages/79/06/edbb67257596649b8fb088d6aeacbcb248ac195714b18a65e018bf4c0b50/regex-2025.11.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf3490bcbb985a1ae97b2ce9ad1c0f06a852d5b19dde9b07bdf25bf224248c95", size = 807674, upload-time = "2025-11-03T21:33:21.797Z" }, + { url = "https://files.pythonhosted.org/packages/f4/d9/ad4deccfce0ea336296bd087f1a191543bb99ee1c53093dcd4c64d951d00/regex-2025.11.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3809988f0a8b8c9dcc0f92478d6501fac7200b9ec56aecf0ec21f4a2ec4b6009", size = 873451, upload-time = "2025-11-03T21:33:23.741Z" }, + { url = "https://files.pythonhosted.org/packages/13/75/a55a4724c56ef13e3e04acaab29df26582f6978c000ac9cd6810ad1f341f/regex-2025.11.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f4ff94e58e84aedb9c9fce66d4ef9f27a190285b451420f297c9a09f2b9abee9", size = 914980, upload-time = "2025-11-03T21:33:25.999Z" }, + { url = "https://files.pythonhosted.org/packages/67/1e/a1657ee15bd9116f70d4a530c736983eed997b361e20ecd8f5ca3759d5c5/regex-2025.11.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eb542fd347ce61e1321b0a6b945d5701528dca0cd9759c2e3bb8bd57e47964d", size = 812852, upload-time = "2025-11-03T21:33:27.852Z" }, + { url = "https://files.pythonhosted.org/packages/b8/6f/f7516dde5506a588a561d296b2d0044839de06035bb486b326065b4c101e/regex-2025.11.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d6c2d5919075a1f2e413c00b056ea0c2f065b3f5fe83c3d07d325ab92dce51d6", size = 795566, upload-time = "2025-11-03T21:33:32.364Z" }, + { url = "https://files.pythonhosted.org/packages/d9/dd/3d10b9e170cc16fb34cb2cef91513cf3df65f440b3366030631b2984a264/regex-2025.11.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:3f8bf11a4827cc7ce5a53d4ef6cddd5ad25595d3c1435ef08f76825851343154", size = 868463, upload-time = "2025-11-03T21:33:34.459Z" }, + { url = "https://files.pythonhosted.org/packages/f5/8e/935e6beff1695aa9085ff83195daccd72acc82c81793df480f34569330de/regex-2025.11.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:22c12d837298651e5550ac1d964e4ff57c3f56965fc1812c90c9fb2028eaf267", size = 854694, upload-time = "2025-11-03T21:33:36.793Z" }, + { url = "https://files.pythonhosted.org/packages/92/12/10650181a040978b2f5720a6a74d44f841371a3d984c2083fc1752e4acf6/regex-2025.11.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:62ba394a3dda9ad41c7c780f60f6e4a70988741415ae96f6d1bf6c239cf01379", size = 799691, upload-time = "2025-11-03T21:33:39.079Z" }, + { url = "https://files.pythonhosted.org/packages/67/90/8f37138181c9a7690e7e4cb388debbd389342db3c7381d636d2875940752/regex-2025.11.3-cp314-cp314t-win32.whl", hash = "sha256:4bf146dca15cdd53224a1bf46d628bd7590e4a07fbb69e720d561aea43a32b38", size = 274583, upload-time = "2025-11-03T21:33:41.302Z" }, + { url = "https://files.pythonhosted.org/packages/8f/cd/867f5ec442d56beb56f5f854f40abcfc75e11d10b11fdb1869dd39c63aaf/regex-2025.11.3-cp314-cp314t-win_amd64.whl", hash = "sha256:adad1a1bcf1c9e76346e091d22d23ac54ef28e1365117d99521631078dfec9de", size = 284286, upload-time = "2025-11-03T21:33:43.324Z" }, + { url = "https://files.pythonhosted.org/packages/20/31/32c0c4610cbc070362bf1d2e4ea86d1ea29014d400a6d6c2486fcfd57766/regex-2025.11.3-cp314-cp314t-win_arm64.whl", hash = "sha256:c54f768482cef41e219720013cd05933b6f971d9562544d691c68699bf2b6801", size = 274741, upload-time = "2025-11-03T21:33:45.557Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "rlp" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eth-utils" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1b/2d/439b0728a92964a04d9c88ea1ca9ebb128893fbbd5834faa31f987f2fd4c/rlp-4.1.0.tar.gz", hash = "sha256:be07564270a96f3e225e2c107db263de96b5bc1f27722d2855bd3459a08e95a9", size = 33429, upload-time = "2025-02-04T22:05:59.089Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/fb/e4c0ced9893b84ac95b7181d69a9786ce5879aeb3bbbcbba80a164f85d6a/rlp-4.1.0-py3-none-any.whl", hash = "sha256:8eca394c579bad34ee0b937aecb96a57052ff3716e19c7a578883e767bc5da6f", size = 19973, upload-time = "2025-02-04T22:05:57.05Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.28.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/48/dc/95f074d43452b3ef5d06276696ece4b3b5d696e7c9ad7173c54b1390cd70/rpds_py-0.28.0.tar.gz", hash = "sha256:abd4df20485a0983e2ca334a216249b6186d6e3c1627e106651943dbdb791aea", size = 27419, upload-time = "2025-10-22T22:24:29.327Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/5c/6c3936495003875fe7b14f90ea812841a08fca50ab26bd840e924097d9c8/rpds_py-0.28.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6b4f28583a4f247ff60cd7bdda83db8c3f5b05a7a82ff20dd4b078571747708f", size = 366439, upload-time = "2025-10-22T22:22:04.525Z" }, + { url = "https://files.pythonhosted.org/packages/56/f9/a0f1ca194c50aa29895b442771f036a25b6c41a35e4f35b1a0ea713bedae/rpds_py-0.28.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d678e91b610c29c4b3d52a2c148b641df2b4676ffe47c59f6388d58b99cdc424", size = 348170, upload-time = "2025-10-22T22:22:06.397Z" }, + { url = "https://files.pythonhosted.org/packages/18/ea/42d243d3a586beb72c77fa5def0487daf827210069a95f36328e869599ea/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e819e0e37a44a78e1383bf1970076e2ccc4dc8c2bbaa2f9bd1dc987e9afff628", size = 378838, upload-time = "2025-10-22T22:22:07.932Z" }, + { url = "https://files.pythonhosted.org/packages/e7/78/3de32e18a94791af8f33601402d9d4f39613136398658412a4e0b3047327/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5ee514e0f0523db5d3fb171f397c54875dbbd69760a414dccf9d4d7ad628b5bd", size = 393299, upload-time = "2025-10-22T22:22:09.435Z" }, + { url = "https://files.pythonhosted.org/packages/13/7e/4bdb435afb18acea2eb8a25ad56b956f28de7c59f8a1d32827effa0d4514/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f3fa06d27fdcee47f07a39e02862da0100cb4982508f5ead53ec533cd5fe55e", size = 518000, upload-time = "2025-10-22T22:22:11.326Z" }, + { url = "https://files.pythonhosted.org/packages/31/d0/5f52a656875cdc60498ab035a7a0ac8f399890cc1ee73ebd567bac4e39ae/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46959ef2e64f9e4a41fc89aa20dbca2b85531f9a72c21099a3360f35d10b0d5a", size = 408746, upload-time = "2025-10-22T22:22:13.143Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/49ce51767b879cde77e7ad9fae164ea15dce3616fe591d9ea1df51152706/rpds_py-0.28.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8455933b4bcd6e83fde3fefc987a023389c4b13f9a58c8d23e4b3f6d13f78c84", size = 386379, upload-time = "2025-10-22T22:22:14.602Z" }, + { url = "https://files.pythonhosted.org/packages/6a/99/e4e1e1ee93a98f72fc450e36c0e4d99c35370220e815288e3ecd2ec36a2a/rpds_py-0.28.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:ad50614a02c8c2962feebe6012b52f9802deec4263946cddea37aaf28dd25a66", size = 401280, upload-time = "2025-10-22T22:22:16.063Z" }, + { url = "https://files.pythonhosted.org/packages/61/35/e0c6a57488392a8b319d2200d03dad2b29c0db9996f5662c3b02d0b86c02/rpds_py-0.28.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e5deca01b271492553fdb6c7fd974659dce736a15bae5dad7ab8b93555bceb28", size = 412365, upload-time = "2025-10-22T22:22:17.504Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6a/841337980ea253ec797eb084665436007a1aad0faac1ba097fb906c5f69c/rpds_py-0.28.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:735f8495a13159ce6a0d533f01e8674cec0c57038c920495f87dcb20b3ddb48a", size = 559573, upload-time = "2025-10-22T22:22:19.108Z" }, + { url = "https://files.pythonhosted.org/packages/e7/5e/64826ec58afd4c489731f8b00729c5f6afdb86f1df1df60bfede55d650bb/rpds_py-0.28.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:961ca621ff10d198bbe6ba4957decca61aa2a0c56695384c1d6b79bf61436df5", size = 583973, upload-time = "2025-10-22T22:22:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ee/44d024b4843f8386a4eeaa4c171b3d31d55f7177c415545fd1a24c249b5d/rpds_py-0.28.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2374e16cc9131022e7d9a8f8d65d261d9ba55048c78f3b6e017971a4f5e6353c", size = 553800, upload-time = "2025-10-22T22:22:22.25Z" }, + { url = "https://files.pythonhosted.org/packages/7d/89/33e675dccff11a06d4d85dbb4d1865f878d5020cbb69b2c1e7b2d3f82562/rpds_py-0.28.0-cp312-cp312-win32.whl", hash = "sha256:d15431e334fba488b081d47f30f091e5d03c18527c325386091f31718952fe08", size = 216954, upload-time = "2025-10-22T22:22:24.105Z" }, + { url = "https://files.pythonhosted.org/packages/af/36/45f6ebb3210887e8ee6dbf1bc710ae8400bb417ce165aaf3024b8360d999/rpds_py-0.28.0-cp312-cp312-win_amd64.whl", hash = "sha256:a410542d61fc54710f750d3764380b53bf09e8c4edbf2f9141a82aa774a04f7c", size = 227844, upload-time = "2025-10-22T22:22:25.551Z" }, + { url = "https://files.pythonhosted.org/packages/57/91/f3fb250d7e73de71080f9a221d19bd6a1c1eb0d12a1ea26513f6c1052ad6/rpds_py-0.28.0-cp312-cp312-win_arm64.whl", hash = "sha256:1f0cfd1c69e2d14f8c892b893997fa9a60d890a0c8a603e88dca4955f26d1edd", size = 217624, upload-time = "2025-10-22T22:22:26.914Z" }, + { url = "https://files.pythonhosted.org/packages/d3/03/ce566d92611dfac0085c2f4b048cd53ed7c274a5c05974b882a908d540a2/rpds_py-0.28.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e9e184408a0297086f880556b6168fa927d677716f83d3472ea333b42171ee3b", size = 366235, upload-time = "2025-10-22T22:22:28.397Z" }, + { url = "https://files.pythonhosted.org/packages/00/34/1c61da1b25592b86fd285bd7bd8422f4c9d748a7373b46126f9ae792a004/rpds_py-0.28.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:edd267266a9b0448f33dc465a97cfc5d467594b600fe28e7fa2f36450e03053a", size = 348241, upload-time = "2025-10-22T22:22:30.171Z" }, + { url = "https://files.pythonhosted.org/packages/fc/00/ed1e28616848c61c493a067779633ebf4b569eccaacf9ccbdc0e7cba2b9d/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85beb8b3f45e4e32f6802fb6cd6b17f615ef6c6a52f265371fb916fae02814aa", size = 378079, upload-time = "2025-10-22T22:22:31.644Z" }, + { url = "https://files.pythonhosted.org/packages/11/b2/ccb30333a16a470091b6e50289adb4d3ec656fd9951ba8c5e3aaa0746a67/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d2412be8d00a1b895f8ad827cc2116455196e20ed994bb704bf138fe91a42724", size = 393151, upload-time = "2025-10-22T22:22:33.453Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d0/73e2217c3ee486d555cb84920597480627d8c0240ff3062005c6cc47773e/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cf128350d384b777da0e68796afdcebc2e9f63f0e9f242217754e647f6d32491", size = 517520, upload-time = "2025-10-22T22:22:34.949Z" }, + { url = "https://files.pythonhosted.org/packages/c4/91/23efe81c700427d0841a4ae7ea23e305654381831e6029499fe80be8a071/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2036d09b363aa36695d1cc1a97b36865597f4478470b0697b5ee9403f4fe399", size = 408699, upload-time = "2025-10-22T22:22:36.584Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ee/a324d3198da151820a326c1f988caaa4f37fc27955148a76fff7a2d787a9/rpds_py-0.28.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8e1e9be4fa6305a16be628959188e4fd5cd6f1b0e724d63c6d8b2a8adf74ea6", size = 385720, upload-time = "2025-10-22T22:22:38.014Z" }, + { url = "https://files.pythonhosted.org/packages/19/ad/e68120dc05af8b7cab4a789fccd8cdcf0fe7e6581461038cc5c164cd97d2/rpds_py-0.28.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0a403460c9dd91a7f23fc3188de6d8977f1d9603a351d5db6cf20aaea95b538d", size = 401096, upload-time = "2025-10-22T22:22:39.869Z" }, + { url = "https://files.pythonhosted.org/packages/99/90/c1e070620042459d60df6356b666bb1f62198a89d68881816a7ed121595a/rpds_py-0.28.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d7366b6553cdc805abcc512b849a519167db8f5e5c3472010cd1228b224265cb", size = 411465, upload-time = "2025-10-22T22:22:41.395Z" }, + { url = "https://files.pythonhosted.org/packages/68/61/7c195b30d57f1b8d5970f600efee72a4fad79ec829057972e13a0370fd24/rpds_py-0.28.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5b43c6a3726efd50f18d8120ec0551241c38785b68952d240c45ea553912ac41", size = 558832, upload-time = "2025-10-22T22:22:42.871Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3d/06f3a718864773f69941d4deccdf18e5e47dd298b4628062f004c10f3b34/rpds_py-0.28.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0cb7203c7bc69d7c1585ebb33a2e6074492d2fc21ad28a7b9d40457ac2a51ab7", size = 583230, upload-time = "2025-10-22T22:22:44.877Z" }, + { url = "https://files.pythonhosted.org/packages/66/df/62fc783781a121e77fee9a21ead0a926f1b652280a33f5956a5e7833ed30/rpds_py-0.28.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a52a5169c664dfb495882adc75c304ae1d50df552fbd68e100fdc719dee4ff9", size = 553268, upload-time = "2025-10-22T22:22:46.441Z" }, + { url = "https://files.pythonhosted.org/packages/84/85/d34366e335140a4837902d3dea89b51f087bd6a63c993ebdff59e93ee61d/rpds_py-0.28.0-cp313-cp313-win32.whl", hash = "sha256:2e42456917b6687215b3e606ab46aa6bca040c77af7df9a08a6dcfe8a4d10ca5", size = 217100, upload-time = "2025-10-22T22:22:48.342Z" }, + { url = "https://files.pythonhosted.org/packages/3c/1c/f25a3f3752ad7601476e3eff395fe075e0f7813fbb9862bd67c82440e880/rpds_py-0.28.0-cp313-cp313-win_amd64.whl", hash = "sha256:e0a0311caedc8069d68fc2bf4c9019b58a2d5ce3cd7cb656c845f1615b577e1e", size = 227759, upload-time = "2025-10-22T22:22:50.219Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d6/5f39b42b99615b5bc2f36ab90423ea404830bdfee1c706820943e9a645eb/rpds_py-0.28.0-cp313-cp313-win_arm64.whl", hash = "sha256:04c1b207ab8b581108801528d59ad80aa83bb170b35b0ddffb29c20e411acdc1", size = 217326, upload-time = "2025-10-22T22:22:51.647Z" }, + { url = "https://files.pythonhosted.org/packages/5c/8b/0c69b72d1cee20a63db534be0df271effe715ef6c744fdf1ff23bb2b0b1c/rpds_py-0.28.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f296ea3054e11fc58ad42e850e8b75c62d9a93a9f981ad04b2e5ae7d2186ff9c", size = 355736, upload-time = "2025-10-22T22:22:53.211Z" }, + { url = "https://files.pythonhosted.org/packages/f7/6d/0c2ee773cfb55c31a8514d2cece856dd299170a49babd50dcffb15ddc749/rpds_py-0.28.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5a7306c19b19005ad98468fcefeb7100b19c79fc23a5f24a12e06d91181193fa", size = 342677, upload-time = "2025-10-22T22:22:54.723Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1c/22513ab25a27ea205144414724743e305e8153e6abe81833b5e678650f5a/rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5d9b86aa501fed9862a443c5c3116f6ead8bc9296185f369277c42542bd646b", size = 371847, upload-time = "2025-10-22T22:22:56.295Z" }, + { url = "https://files.pythonhosted.org/packages/60/07/68e6ccdb4b05115ffe61d31afc94adef1833d3a72f76c9632d4d90d67954/rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e5bbc701eff140ba0e872691d573b3d5d30059ea26e5785acba9132d10c8c31d", size = 381800, upload-time = "2025-10-22T22:22:57.808Z" }, + { url = "https://files.pythonhosted.org/packages/73/bf/6d6d15df80781d7f9f368e7c1a00caf764436518c4877fb28b029c4624af/rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a5690671cd672a45aa8616d7374fdf334a1b9c04a0cac3c854b1136e92374fe", size = 518827, upload-time = "2025-10-22T22:22:59.826Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d3/2decbb2976cc452cbf12a2b0aaac5f1b9dc5dd9d1f7e2509a3ee00421249/rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9f1d92ecea4fa12f978a367c32a5375a1982834649cdb96539dcdc12e609ab1a", size = 399471, upload-time = "2025-10-22T22:23:01.968Z" }, + { url = "https://files.pythonhosted.org/packages/b1/2c/f30892f9e54bd02e5faca3f6a26d6933c51055e67d54818af90abed9748e/rpds_py-0.28.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d252db6b1a78d0a3928b6190156042d54c93660ce4d98290d7b16b5296fb7cc", size = 377578, upload-time = "2025-10-22T22:23:03.52Z" }, + { url = "https://files.pythonhosted.org/packages/f0/5d/3bce97e5534157318f29ac06bf2d279dae2674ec12f7cb9c12739cee64d8/rpds_py-0.28.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d61b355c3275acb825f8777d6c4505f42b5007e357af500939d4a35b19177259", size = 390482, upload-time = "2025-10-22T22:23:05.391Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f0/886bd515ed457b5bd93b166175edb80a0b21a210c10e993392127f1e3931/rpds_py-0.28.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:acbe5e8b1026c0c580d0321c8aae4b0a1e1676861d48d6e8c6586625055b606a", size = 402447, upload-time = "2025-10-22T22:23:06.93Z" }, + { url = "https://files.pythonhosted.org/packages/42/b5/71e8777ac55e6af1f4f1c05b47542a1eaa6c33c1cf0d300dca6a1c6e159a/rpds_py-0.28.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8aa23b6f0fc59b85b4c7d89ba2965af274346f738e8d9fc2455763602e62fd5f", size = 552385, upload-time = "2025-10-22T22:23:08.557Z" }, + { url = "https://files.pythonhosted.org/packages/5d/cb/6ca2d70cbda5a8e36605e7788c4aa3bea7c17d71d213465a5a675079b98d/rpds_py-0.28.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7b14b0c680286958817c22d76fcbca4800ddacef6f678f3a7c79a1fe7067fe37", size = 575642, upload-time = "2025-10-22T22:23:10.348Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d4/407ad9960ca7856d7b25c96dcbe019270b5ffdd83a561787bc682c797086/rpds_py-0.28.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bcf1d210dfee61a6c86551d67ee1031899c0fdbae88b2d44a569995d43797712", size = 544507, upload-time = "2025-10-22T22:23:12.434Z" }, + { url = "https://files.pythonhosted.org/packages/51/31/2f46fe0efcac23fbf5797c6b6b7e1c76f7d60773e525cb65fcbc582ee0f2/rpds_py-0.28.0-cp313-cp313t-win32.whl", hash = "sha256:3aa4dc0fdab4a7029ac63959a3ccf4ed605fee048ba67ce89ca3168da34a1342", size = 205376, upload-time = "2025-10-22T22:23:13.979Z" }, + { url = "https://files.pythonhosted.org/packages/92/e4/15947bda33cbedfc134490a41841ab8870a72a867a03d4969d886f6594a2/rpds_py-0.28.0-cp313-cp313t-win_amd64.whl", hash = "sha256:7b7d9d83c942855e4fdcfa75d4f96f6b9e272d42fffcb72cd4bb2577db2e2907", size = 215907, upload-time = "2025-10-22T22:23:15.5Z" }, + { url = "https://files.pythonhosted.org/packages/08/47/ffe8cd7a6a02833b10623bf765fbb57ce977e9a4318ca0e8cf97e9c3d2b3/rpds_py-0.28.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:dcdcb890b3ada98a03f9f2bb108489cdc7580176cb73b4f2d789e9a1dac1d472", size = 353830, upload-time = "2025-10-22T22:23:17.03Z" }, + { url = "https://files.pythonhosted.org/packages/f9/9f/890f36cbd83a58491d0d91ae0db1702639edb33fb48eeb356f80ecc6b000/rpds_py-0.28.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f274f56a926ba2dc02976ca5b11c32855cbd5925534e57cfe1fda64e04d1add2", size = 341819, upload-time = "2025-10-22T22:23:18.57Z" }, + { url = "https://files.pythonhosted.org/packages/09/e3/921eb109f682aa24fb76207698fbbcf9418738f35a40c21652c29053f23d/rpds_py-0.28.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fe0438ac4a29a520ea94c8c7f1754cdd8feb1bc490dfda1bfd990072363d527", size = 373127, upload-time = "2025-10-22T22:23:20.216Z" }, + { url = "https://files.pythonhosted.org/packages/23/13/bce4384d9f8f4989f1a9599c71b7a2d877462e5fd7175e1f69b398f729f4/rpds_py-0.28.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a358a32dd3ae50e933347889b6af9a1bdf207ba5d1a3f34e1a38cd3540e6733", size = 382767, upload-time = "2025-10-22T22:23:21.787Z" }, + { url = "https://files.pythonhosted.org/packages/23/e1/579512b2d89a77c64ccef5a0bc46a6ef7f72ae0cf03d4b26dcd52e57ee0a/rpds_py-0.28.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e80848a71c78aa328fefaba9c244d588a342c8e03bda518447b624ea64d1ff56", size = 517585, upload-time = "2025-10-22T22:23:23.699Z" }, + { url = "https://files.pythonhosted.org/packages/62/3c/ca704b8d324a2591b0b0adcfcaadf9c862375b11f2f667ac03c61b4fd0a6/rpds_py-0.28.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f586db2e209d54fe177e58e0bc4946bea5fb0102f150b1b2f13de03e1f0976f8", size = 399828, upload-time = "2025-10-22T22:23:25.713Z" }, + { url = "https://files.pythonhosted.org/packages/da/37/e84283b9e897e3adc46b4c88bb3f6ec92a43bd4d2f7ef5b13459963b2e9c/rpds_py-0.28.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ae8ee156d6b586e4292491e885d41483136ab994e719a13458055bec14cf370", size = 375509, upload-time = "2025-10-22T22:23:27.32Z" }, + { url = "https://files.pythonhosted.org/packages/1a/c2/a980beab869d86258bf76ec42dec778ba98151f253a952b02fe36d72b29c/rpds_py-0.28.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:a805e9b3973f7e27f7cab63a6b4f61d90f2e5557cff73b6e97cd5b8540276d3d", size = 392014, upload-time = "2025-10-22T22:23:29.332Z" }, + { url = "https://files.pythonhosted.org/packages/da/b5/b1d3c5f9d3fa5aeef74265f9c64de3c34a0d6d5cd3c81c8b17d5c8f10ed4/rpds_py-0.28.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5d3fd16b6dc89c73a4da0b4ac8b12a7ecc75b2864b95c9e5afed8003cb50a728", size = 402410, upload-time = "2025-10-22T22:23:31.14Z" }, + { url = "https://files.pythonhosted.org/packages/74/ae/cab05ff08dfcc052afc73dcb38cbc765ffc86f94e966f3924cd17492293c/rpds_py-0.28.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6796079e5d24fdaba6d49bda28e2c47347e89834678f2bc2c1b4fc1489c0fb01", size = 553593, upload-time = "2025-10-22T22:23:32.834Z" }, + { url = "https://files.pythonhosted.org/packages/70/80/50d5706ea2a9bfc9e9c5f401d91879e7c790c619969369800cde202da214/rpds_py-0.28.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:76500820c2af232435cbe215e3324c75b950a027134e044423f59f5b9a1ba515", size = 576925, upload-time = "2025-10-22T22:23:34.47Z" }, + { url = "https://files.pythonhosted.org/packages/ab/12/85a57d7a5855a3b188d024b099fd09c90db55d32a03626d0ed16352413ff/rpds_py-0.28.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bbdc5640900a7dbf9dd707fe6388972f5bbd883633eb68b76591044cfe346f7e", size = 542444, upload-time = "2025-10-22T22:23:36.093Z" }, + { url = "https://files.pythonhosted.org/packages/6c/65/10643fb50179509150eb94d558e8837c57ca8b9adc04bd07b98e57b48f8c/rpds_py-0.28.0-cp314-cp314-win32.whl", hash = "sha256:adc8aa88486857d2b35d75f0640b949759f79dc105f50aa2c27816b2e0dd749f", size = 207968, upload-time = "2025-10-22T22:23:37.638Z" }, + { url = "https://files.pythonhosted.org/packages/b4/84/0c11fe4d9aaea784ff4652499e365963222481ac647bcd0251c88af646eb/rpds_py-0.28.0-cp314-cp314-win_amd64.whl", hash = "sha256:66e6fa8e075b58946e76a78e69e1a124a21d9a48a5b4766d15ba5b06869d1fa1", size = 218876, upload-time = "2025-10-22T22:23:39.179Z" }, + { url = "https://files.pythonhosted.org/packages/0f/e0/3ab3b86ded7bb18478392dc3e835f7b754cd446f62f3fc96f4fe2aca78f6/rpds_py-0.28.0-cp314-cp314-win_arm64.whl", hash = "sha256:a6fe887c2c5c59413353b7c0caff25d0e566623501ccfff88957fa438a69377d", size = 212506, upload-time = "2025-10-22T22:23:40.755Z" }, + { url = "https://files.pythonhosted.org/packages/51/ec/d5681bb425226c3501eab50fc30e9d275de20c131869322c8a1729c7b61c/rpds_py-0.28.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7a69df082db13c7070f7b8b1f155fa9e687f1d6aefb7b0e3f7231653b79a067b", size = 355433, upload-time = "2025-10-22T22:23:42.259Z" }, + { url = "https://files.pythonhosted.org/packages/be/ec/568c5e689e1cfb1ea8b875cffea3649260955f677fdd7ddc6176902d04cd/rpds_py-0.28.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b1cde22f2c30ebb049a9e74c5374994157b9b70a16147d332f89c99c5960737a", size = 342601, upload-time = "2025-10-22T22:23:44.372Z" }, + { url = "https://files.pythonhosted.org/packages/32/fe/51ada84d1d2a1d9d8f2c902cfddd0133b4a5eb543196ab5161d1c07ed2ad/rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5338742f6ba7a51012ea470bd4dc600a8c713c0c72adaa0977a1b1f4327d6592", size = 372039, upload-time = "2025-10-22T22:23:46.025Z" }, + { url = "https://files.pythonhosted.org/packages/07/c1/60144a2f2620abade1a78e0d91b298ac2d9b91bc08864493fa00451ef06e/rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e1460ebde1bcf6d496d80b191d854adedcc619f84ff17dc1c6d550f58c9efbba", size = 382407, upload-time = "2025-10-22T22:23:48.098Z" }, + { url = "https://files.pythonhosted.org/packages/45/ed/091a7bbdcf4038a60a461df50bc4c82a7ed6d5d5e27649aab61771c17585/rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e3eb248f2feba84c692579257a043a7699e28a77d86c77b032c1d9fbb3f0219c", size = 518172, upload-time = "2025-10-22T22:23:50.16Z" }, + { url = "https://files.pythonhosted.org/packages/54/dd/02cc90c2fd9c2ef8016fd7813bfacd1c3a1325633ec8f244c47b449fc868/rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3bbba5def70b16cd1c1d7255666aad3b290fbf8d0fe7f9f91abafb73611a91", size = 399020, upload-time = "2025-10-22T22:23:51.81Z" }, + { url = "https://files.pythonhosted.org/packages/ab/81/5d98cc0329bbb911ccecd0b9e19fbf7f3a5de8094b4cda5e71013b2dd77e/rpds_py-0.28.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3114f4db69ac5a1f32e7e4d1cbbe7c8f9cf8217f78e6e002cedf2d54c2a548ed", size = 377451, upload-time = "2025-10-22T22:23:53.711Z" }, + { url = "https://files.pythonhosted.org/packages/b4/07/4d5bcd49e3dfed2d38e2dcb49ab6615f2ceb9f89f5a372c46dbdebb4e028/rpds_py-0.28.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:4b0cb8a906b1a0196b863d460c0222fb8ad0f34041568da5620f9799b83ccf0b", size = 390355, upload-time = "2025-10-22T22:23:55.299Z" }, + { url = "https://files.pythonhosted.org/packages/3f/79/9f14ba9010fee74e4f40bf578735cfcbb91d2e642ffd1abe429bb0b96364/rpds_py-0.28.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf681ac76a60b667106141e11a92a3330890257e6f559ca995fbb5265160b56e", size = 403146, upload-time = "2025-10-22T22:23:56.929Z" }, + { url = "https://files.pythonhosted.org/packages/39/4c/f08283a82ac141331a83a40652830edd3a4a92c34e07e2bbe00baaea2f5f/rpds_py-0.28.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1e8ee6413cfc677ce8898d9cde18cc3a60fc2ba756b0dec5b71eb6eb21c49fa1", size = 552656, upload-time = "2025-10-22T22:23:58.62Z" }, + { url = "https://files.pythonhosted.org/packages/61/47/d922fc0666f0dd8e40c33990d055f4cc6ecff6f502c2d01569dbed830f9b/rpds_py-0.28.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b3072b16904d0b5572a15eb9d31c1954e0d3227a585fc1351aa9878729099d6c", size = 576782, upload-time = "2025-10-22T22:24:00.312Z" }, + { url = "https://files.pythonhosted.org/packages/d3/0c/5bafdd8ccf6aa9d3bfc630cfece457ff5b581af24f46a9f3590f790e3df2/rpds_py-0.28.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b670c30fd87a6aec281c3c9896d3bae4b205fd75d79d06dc87c2503717e46092", size = 544671, upload-time = "2025-10-22T22:24:02.297Z" }, + { url = "https://files.pythonhosted.org/packages/2c/37/dcc5d8397caa924988693519069d0beea077a866128719351a4ad95e82fc/rpds_py-0.28.0-cp314-cp314t-win32.whl", hash = "sha256:8014045a15b4d2b3476f0a287fcc93d4f823472d7d1308d47884ecac9e612be3", size = 205749, upload-time = "2025-10-22T22:24:03.848Z" }, + { url = "https://files.pythonhosted.org/packages/d7/69/64d43b21a10d72b45939a28961216baeb721cc2a430f5f7c3bfa21659a53/rpds_py-0.28.0-cp314-cp314t-win_amd64.whl", hash = "sha256:7a4e59c90d9c27c561eb3160323634a9ff50b04e4f7820600a2beb0ac90db578", size = 216233, upload-time = "2025-10-22T22:24:05.471Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "supervisor" +version = "4.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/b5/37e7a3706de436a8a2d75334711dad1afb4ddffab09f25e31d89e467542f/supervisor-4.3.0.tar.gz", hash = "sha256:4a2bf149adf42997e1bb44b70c43b613275ec9852c3edacca86a9166b27e945e", size = 468912, upload-time = "2025-08-23T18:25:02.418Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/65/5e726c372da8a5e35022a94388b12252710aad0c2351699c3d76ae8dba78/supervisor-4.3.0-py2.py3-none-any.whl", hash = "sha256:0bcb763fddafba410f35cbde226aa7f8514b9fb82eb05a0c85f6588d1c13f8db", size = 320736, upload-time = "2025-08-23T18:25:00.767Z" }, +] + +[[package]] +name = "termcolor" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/87/56/ab275c2b56a5e2342568838f0d5e3e66a32354adcc159b495e374cda43f5/termcolor-3.2.0.tar.gz", hash = "sha256:610e6456feec42c4bcd28934a8c87a06c3fa28b01561d46aa09a9881b8622c58", size = 14423, upload-time = "2025-10-25T19:11:42.586Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/d5/141f53d7c1eb2a80e6d3e9a390228c3222c27705cbe7f048d3623053f3ca/termcolor-3.2.0-py3-none-any.whl", hash = "sha256:a10343879eba4da819353c55cb8049b0933890c2ebf9ad5d3ecd2bb32ea96ea6", size = 7698, upload-time = "2025-10-25T19:11:41.536Z" }, +] + +[[package]] +name = "tomlkit" +version = "0.13.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/18/0bbf3884e9eaa38819ebe46a7bd25dcd56b67434402b66a58c4b8e552575/tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", size = 185207, upload-time = "2025-06-05T07:13:44.947Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0", size = 38901, upload-time = "2025-06-05T07:13:43.546Z" }, +] + +[[package]] +name = "toolz" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/d6/114b492226588d6ff54579d95847662fc69196bdeec318eb45393b24c192/toolz-1.1.0.tar.gz", hash = "sha256:27a5c770d068c110d9ed9323f24f1543e83b2f300a687b7891c1a6d56b697b5b", size = 52613, upload-time = "2025-10-17T04:03:21.661Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl", hash = "sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8", size = 58093, upload-time = "2025-10-17T04:03:20.435Z" }, +] + +[[package]] +name = "types-requests" +version = "2.32.4.20250913" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/27/489922f4505975b11de2b5ad07b4fe1dca0bca9be81a703f26c5f3acfce5/types_requests-2.32.4.20250913.tar.gz", hash = "sha256:abd6d4f9ce3a9383f269775a9835a4c24e5cd6b9f647d64f88aa4613c33def5d", size = 23113, upload-time = "2025-09-13T02:40:02.309Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/20/9a227ea57c1285986c4cf78400d0a91615d25b24e257fd9e2969606bdfae/types_requests-2.32.4.20250913-py3-none-any.whl", hash = "sha256:78c9c1fffebbe0fa487a418e0fa5252017e9c60d1a2da394077f1780f655d7e1", size = 20658, upload-time = "2025-09-13T02:40:01.115Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + +[[package]] +name = "web3" +version = "7.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "eth-abi" }, + { name = "eth-account" }, + { name = "eth-hash", extra = ["pycryptodome"] }, + { name = "eth-typing" }, + { name = "eth-utils" }, + { name = "hexbytes" }, + { name = "pydantic" }, + { name = "pyunormalize" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "requests" }, + { name = "types-requests" }, + { name = "typing-extensions" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/85/1515644dc1b0170e43e8c26531a3cec8ebc916185fbe2db0020e450b7114/web3-7.14.0.tar.gz", hash = "sha256:d82c78007c280e478b3920cd56658df17f2f76af584ee3318df6b60d4944b8a2", size = 2194249, upload-time = "2025-10-16T19:25:07.484Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/66/94/68ce430b5e19803d2b34736dd653e8627bde68d93cd8b0bec44384487a59/web3-7.14.0-py3-none-any.whl", hash = "sha256:a78c0a979bf11c47795f564512131c01b7598a276976f7031c55140f733e210a", size = 1370801, upload-time = "2025-10-16T19:25:04.052Z" }, +] + +[[package]] +name = "websockets" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440, upload-time = "2025-03-05T20:02:36.695Z" }, + { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098, upload-time = "2025-03-05T20:02:37.985Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329, upload-time = "2025-03-05T20:02:39.298Z" }, + { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111, upload-time = "2025-03-05T20:02:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054, upload-time = "2025-03-05T20:02:41.926Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496, upload-time = "2025-03-05T20:02:43.304Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829, upload-time = "2025-03-05T20:02:48.812Z" }, + { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217, upload-time = "2025-03-05T20:02:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +] + +[[package]] +name = "yarl" +version = "1.22.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, + { url = "https://files.pythonhosted.org/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, + { url = "https://files.pythonhosted.org/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, + { url = "https://files.pythonhosted.org/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, + { url = "https://files.pythonhosted.org/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, + { url = "https://files.pythonhosted.org/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, + { url = "https://files.pythonhosted.org/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, + { url = "https://files.pythonhosted.org/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, + { url = "https://files.pythonhosted.org/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, + { url = "https://files.pythonhosted.org/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, + { url = "https://files.pythonhosted.org/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, + { url = "https://files.pythonhosted.org/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, + { url = "https://files.pythonhosted.org/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, + { url = "https://files.pythonhosted.org/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, + { url = "https://files.pythonhosted.org/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" }, + { url = "https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" }, + { url = "https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" }, + { url = "https://files.pythonhosted.org/packages/61/3a/caf4e25036db0f2da4ca22a353dfeb3c9d3c95d2761ebe9b14df8fc16eb0/yarl-1.22.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", size = 373243, upload-time = "2025-10-06T14:10:19.44Z" }, + { url = "https://files.pythonhosted.org/packages/6e/9e/51a77ac7516e8e7803b06e01f74e78649c24ee1021eca3d6a739cb6ea49c/yarl-1.22.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", size = 342361, upload-time = "2025-10-06T14:10:21.124Z" }, + { url = "https://files.pythonhosted.org/packages/d4/f8/33b92454789dde8407f156c00303e9a891f1f51a0330b0fad7c909f87692/yarl-1.22.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", size = 387036, upload-time = "2025-10-06T14:10:22.902Z" }, + { url = "https://files.pythonhosted.org/packages/d9/9a/c5db84ea024f76838220280f732970aa4ee154015d7f5c1bfb60a267af6f/yarl-1.22.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", size = 397671, upload-time = "2025-10-06T14:10:24.523Z" }, + { url = "https://files.pythonhosted.org/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", size = 377059, upload-time = "2025-10-06T14:10:26.406Z" }, + { url = "https://files.pythonhosted.org/packages/a1/b9/ab437b261702ced75122ed78a876a6dec0a1b0f5e17a4ac7a9a2482d8abe/yarl-1.22.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", size = 365356, upload-time = "2025-10-06T14:10:28.461Z" }, + { url = "https://files.pythonhosted.org/packages/b2/9d/8e1ae6d1d008a9567877b08f0ce4077a29974c04c062dabdb923ed98e6fe/yarl-1.22.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", size = 361331, upload-time = "2025-10-06T14:10:30.541Z" }, + { url = "https://files.pythonhosted.org/packages/ca/5a/09b7be3905962f145b73beb468cdd53db8aa171cf18c80400a54c5b82846/yarl-1.22.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", size = 382590, upload-time = "2025-10-06T14:10:33.352Z" }, + { url = "https://files.pythonhosted.org/packages/aa/7f/59ec509abf90eda5048b0bc3e2d7b5099dffdb3e6b127019895ab9d5ef44/yarl-1.22.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", size = 385316, upload-time = "2025-10-06T14:10:35.034Z" }, + { url = "https://files.pythonhosted.org/packages/e5/84/891158426bc8036bfdfd862fabd0e0fa25df4176ec793e447f4b85cf1be4/yarl-1.22.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", size = 374431, upload-time = "2025-10-06T14:10:37.76Z" }, + { url = "https://files.pythonhosted.org/packages/bb/49/03da1580665baa8bef5e8ed34c6df2c2aca0a2f28bf397ed238cc1bbc6f2/yarl-1.22.0-cp313-cp313-win32.whl", hash = "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", size = 81555, upload-time = "2025-10-06T14:10:39.649Z" }, + { url = "https://files.pythonhosted.org/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl", hash = "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", size = 86965, upload-time = "2025-10-06T14:10:41.313Z" }, + { url = "https://files.pythonhosted.org/packages/98/4d/264a01eae03b6cf629ad69bae94e3b0e5344741e929073678e84bf7a3e3b/yarl-1.22.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", size = 81205, upload-time = "2025-10-06T14:10:43.167Z" }, + { url = "https://files.pythonhosted.org/packages/88/fc/6908f062a2f77b5f9f6d69cecb1747260831ff206adcbc5b510aff88df91/yarl-1.22.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", size = 146209, upload-time = "2025-10-06T14:10:44.643Z" }, + { url = "https://files.pythonhosted.org/packages/65/47/76594ae8eab26210b4867be6f49129861ad33da1f1ebdf7051e98492bf62/yarl-1.22.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", size = 95966, upload-time = "2025-10-06T14:10:46.554Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ce/05e9828a49271ba6b5b038b15b3934e996980dd78abdfeb52a04cfb9467e/yarl-1.22.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", size = 97312, upload-time = "2025-10-06T14:10:48.007Z" }, + { url = "https://files.pythonhosted.org/packages/d1/c5/7dffad5e4f2265b29c9d7ec869c369e4223166e4f9206fc2243ee9eea727/yarl-1.22.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", size = 361967, upload-time = "2025-10-06T14:10:49.997Z" }, + { url = "https://files.pythonhosted.org/packages/50/b2/375b933c93a54bff7fc041e1a6ad2c0f6f733ffb0c6e642ce56ee3b39970/yarl-1.22.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", size = 323949, upload-time = "2025-10-06T14:10:52.004Z" }, + { url = "https://files.pythonhosted.org/packages/66/50/bfc2a29a1d78644c5a7220ce2f304f38248dc94124a326794e677634b6cf/yarl-1.22.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", size = 361818, upload-time = "2025-10-06T14:10:54.078Z" }, + { url = "https://files.pythonhosted.org/packages/46/96/f3941a46af7d5d0f0498f86d71275696800ddcdd20426298e572b19b91ff/yarl-1.22.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", size = 372626, upload-time = "2025-10-06T14:10:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/c1/42/8b27c83bb875cd89448e42cd627e0fb971fa1675c9ec546393d18826cb50/yarl-1.22.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", size = 341129, upload-time = "2025-10-06T14:10:57.985Z" }, + { url = "https://files.pythonhosted.org/packages/49/36/99ca3122201b382a3cf7cc937b95235b0ac944f7e9f2d5331d50821ed352/yarl-1.22.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", size = 346776, upload-time = "2025-10-06T14:10:59.633Z" }, + { url = "https://files.pythonhosted.org/packages/85/b4/47328bf996acd01a4c16ef9dcd2f59c969f495073616586f78cd5f2efb99/yarl-1.22.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", size = 334879, upload-time = "2025-10-06T14:11:01.454Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ad/b77d7b3f14a4283bffb8e92c6026496f6de49751c2f97d4352242bba3990/yarl-1.22.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", size = 350996, upload-time = "2025-10-06T14:11:03.452Z" }, + { url = "https://files.pythonhosted.org/packages/81/c8/06e1d69295792ba54d556f06686cbd6a7ce39c22307100e3fb4a2c0b0a1d/yarl-1.22.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", size = 356047, upload-time = "2025-10-06T14:11:05.115Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b8/4c0e9e9f597074b208d18cef227d83aac36184bfbc6eab204ea55783dbc5/yarl-1.22.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", size = 342947, upload-time = "2025-10-06T14:11:08.137Z" }, + { url = "https://files.pythonhosted.org/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", size = 86943, upload-time = "2025-10-06T14:11:10.284Z" }, + { url = "https://files.pythonhosted.org/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249", size = 93715, upload-time = "2025-10-06T14:11:11.739Z" }, + { url = "https://files.pythonhosted.org/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", size = 83857, upload-time = "2025-10-06T14:11:13.586Z" }, + { url = "https://files.pythonhosted.org/packages/46/b3/e20ef504049f1a1c54a814b4b9bed96d1ac0e0610c3b4da178f87209db05/yarl-1.22.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4", size = 140520, upload-time = "2025-10-06T14:11:15.465Z" }, + { url = "https://files.pythonhosted.org/packages/e4/04/3532d990fdbab02e5ede063676b5c4260e7f3abea2151099c2aa745acc4c/yarl-1.22.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683", size = 93504, upload-time = "2025-10-06T14:11:17.106Z" }, + { url = "https://files.pythonhosted.org/packages/11/63/ff458113c5c2dac9a9719ac68ee7c947cb621432bcf28c9972b1c0e83938/yarl-1.22.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b", size = 94282, upload-time = "2025-10-06T14:11:19.064Z" }, + { url = "https://files.pythonhosted.org/packages/a7/bc/315a56aca762d44a6aaaf7ad253f04d996cb6b27bad34410f82d76ea8038/yarl-1.22.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e", size = 372080, upload-time = "2025-10-06T14:11:20.996Z" }, + { url = "https://files.pythonhosted.org/packages/3f/3f/08e9b826ec2e099ea6e7c69a61272f4f6da62cb5b1b63590bb80ca2e4a40/yarl-1.22.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590", size = 338696, upload-time = "2025-10-06T14:11:22.847Z" }, + { url = "https://files.pythonhosted.org/packages/e3/9f/90360108e3b32bd76789088e99538febfea24a102380ae73827f62073543/yarl-1.22.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2", size = 387121, upload-time = "2025-10-06T14:11:24.889Z" }, + { url = "https://files.pythonhosted.org/packages/98/92/ab8d4657bd5b46a38094cfaea498f18bb70ce6b63508fd7e909bd1f93066/yarl-1.22.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da", size = 394080, upload-time = "2025-10-06T14:11:27.307Z" }, + { url = "https://files.pythonhosted.org/packages/f5/e7/d8c5a7752fef68205296201f8ec2bf718f5c805a7a7e9880576c67600658/yarl-1.22.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784", size = 372661, upload-time = "2025-10-06T14:11:29.387Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2e/f4d26183c8db0bb82d491b072f3127fb8c381a6206a3a56332714b79b751/yarl-1.22.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b", size = 364645, upload-time = "2025-10-06T14:11:31.423Z" }, + { url = "https://files.pythonhosted.org/packages/80/7c/428e5812e6b87cd00ee8e898328a62c95825bf37c7fa87f0b6bb2ad31304/yarl-1.22.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694", size = 355361, upload-time = "2025-10-06T14:11:33.055Z" }, + { url = "https://files.pythonhosted.org/packages/ec/2a/249405fd26776f8b13c067378ef4d7dd49c9098d1b6457cdd152a99e96a9/yarl-1.22.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d", size = 381451, upload-time = "2025-10-06T14:11:35.136Z" }, + { url = "https://files.pythonhosted.org/packages/67/a8/fb6b1adbe98cf1e2dd9fad71003d3a63a1bc22459c6e15f5714eb9323b93/yarl-1.22.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd", size = 383814, upload-time = "2025-10-06T14:11:37.094Z" }, + { url = "https://files.pythonhosted.org/packages/d9/f9/3aa2c0e480fb73e872ae2814c43bc1e734740bb0d54e8cb2a95925f98131/yarl-1.22.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da", size = 370799, upload-time = "2025-10-06T14:11:38.83Z" }, + { url = "https://files.pythonhosted.org/packages/50/3c/af9dba3b8b5eeb302f36f16f92791f3ea62e3f47763406abf6d5a4a3333b/yarl-1.22.0-cp314-cp314-win32.whl", hash = "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2", size = 82990, upload-time = "2025-10-06T14:11:40.624Z" }, + { url = "https://files.pythonhosted.org/packages/ac/30/ac3a0c5bdc1d6efd1b41fa24d4897a4329b3b1e98de9449679dd327af4f0/yarl-1.22.0-cp314-cp314-win_amd64.whl", hash = "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79", size = 88292, upload-time = "2025-10-06T14:11:42.578Z" }, + { url = "https://files.pythonhosted.org/packages/df/0a/227ab4ff5b998a1b7410abc7b46c9b7a26b0ca9e86c34ba4b8d8bc7c63d5/yarl-1.22.0-cp314-cp314-win_arm64.whl", hash = "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33", size = 82888, upload-time = "2025-10-06T14:11:44.863Z" }, + { url = "https://files.pythonhosted.org/packages/06/5e/a15eb13db90abd87dfbefb9760c0f3f257ac42a5cac7e75dbc23bed97a9f/yarl-1.22.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1", size = 146223, upload-time = "2025-10-06T14:11:46.796Z" }, + { url = "https://files.pythonhosted.org/packages/18/82/9665c61910d4d84f41a5bf6837597c89e665fa88aa4941080704645932a9/yarl-1.22.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca", size = 95981, upload-time = "2025-10-06T14:11:48.845Z" }, + { url = "https://files.pythonhosted.org/packages/5d/9a/2f65743589809af4d0a6d3aa749343c4b5f4c380cc24a8e94a3c6625a808/yarl-1.22.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53", size = 97303, upload-time = "2025-10-06T14:11:50.897Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ab/5b13d3e157505c43c3b43b5a776cbf7b24a02bc4cccc40314771197e3508/yarl-1.22.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c", size = 361820, upload-time = "2025-10-06T14:11:52.549Z" }, + { url = "https://files.pythonhosted.org/packages/fb/76/242a5ef4677615cf95330cfc1b4610e78184400699bdda0acb897ef5e49a/yarl-1.22.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf", size = 323203, upload-time = "2025-10-06T14:11:54.225Z" }, + { url = "https://files.pythonhosted.org/packages/8c/96/475509110d3f0153b43d06164cf4195c64d16999e0c7e2d8a099adcd6907/yarl-1.22.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face", size = 363173, upload-time = "2025-10-06T14:11:56.069Z" }, + { url = "https://files.pythonhosted.org/packages/c9/66/59db471aecfbd559a1fd48aedd954435558cd98c7d0da8b03cc6c140a32c/yarl-1.22.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b", size = 373562, upload-time = "2025-10-06T14:11:58.783Z" }, + { url = "https://files.pythonhosted.org/packages/03/1f/c5d94abc91557384719da10ff166b916107c1b45e4d0423a88457071dd88/yarl-1.22.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486", size = 339828, upload-time = "2025-10-06T14:12:00.686Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/aa6a143d3afba17b6465733681c70cf175af89f76ec8d9286e08437a7454/yarl-1.22.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138", size = 347551, upload-time = "2025-10-06T14:12:02.628Z" }, + { url = "https://files.pythonhosted.org/packages/43/3c/45a2b6d80195959239a7b2a8810506d4eea5487dce61c2a3393e7fc3c52e/yarl-1.22.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a", size = 334512, upload-time = "2025-10-06T14:12:04.871Z" }, + { url = "https://files.pythonhosted.org/packages/86/a0/c2ab48d74599c7c84cb104ebd799c5813de252bea0f360ffc29d270c2caa/yarl-1.22.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529", size = 352400, upload-time = "2025-10-06T14:12:06.624Z" }, + { url = "https://files.pythonhosted.org/packages/32/75/f8919b2eafc929567d3d8411f72bdb1a2109c01caaab4ebfa5f8ffadc15b/yarl-1.22.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093", size = 357140, upload-time = "2025-10-06T14:12:08.362Z" }, + { url = "https://files.pythonhosted.org/packages/cf/72/6a85bba382f22cf78add705d8c3731748397d986e197e53ecc7835e76de7/yarl-1.22.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c", size = 341473, upload-time = "2025-10-06T14:12:10.994Z" }, + { url = "https://files.pythonhosted.org/packages/35/18/55e6011f7c044dc80b98893060773cefcfdbf60dfefb8cb2f58b9bacbd83/yarl-1.22.0-cp314-cp314t-win32.whl", hash = "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", size = 89056, upload-time = "2025-10-06T14:12:13.317Z" }, + { url = "https://files.pythonhosted.org/packages/f9/86/0f0dccb6e59a9e7f122c5afd43568b1d31b8ab7dda5f1b01fb5c7025c9a9/yarl-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", size = 96292, upload-time = "2025-10-06T14:12:15.398Z" }, + { url = "https://files.pythonhosted.org/packages/48/b7/503c98092fb3b344a179579f55814b613c1fbb1c23b3ec14a7b008a66a6e/yarl-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", size = 85171, upload-time = "2025-10-06T14:12:16.935Z" }, + { url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, +] From dd62d27e1fd13dc916e05a94f6dc2c0a2ecbb9c8 Mon Sep 17 00:00:00 2001 From: yihuang Date: Fri, 14 Nov 2025 12:43:49 +0800 Subject: [PATCH 17/22] move venv directory --- .envrc.example | 2 +- .gitignore | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.envrc.example b/.envrc.example index 650f1143b..60fdaac89 100644 --- a/.envrc.example +++ b/.envrc.example @@ -1,4 +1,4 @@ use flake -export VIRTUAL_ENV=."venv" +export VIRTUAL_ENV="tests/integration_tests/.venv" layout python TMPDIR=/tmp diff --git a/.gitignore b/.gitignore index e9146bbe5..8ff616ffd 100644 --- a/.gitignore +++ b/.gitignore @@ -41,5 +41,5 @@ tests/systemtests/testnet # Environments *.env /.envrc -/.venv +.venv /.direnv From a03485ad4002d0a429ea9b66d1c5fc6b356c7d72 Mon Sep 17 00:00:00 2001 From: yihuang Date: Fri, 14 Nov 2025 15:32:05 +0800 Subject: [PATCH 18/22] cprotobuf published new version --- tests/integration_tests/pyproject.toml | 3 +-- tests/integration_tests/uv.lock | 37 +++----------------------- 2 files changed, 5 insertions(+), 35 deletions(-) diff --git a/tests/integration_tests/pyproject.toml b/tests/integration_tests/pyproject.toml index a0421d27a..2a93bfdfa 100644 --- a/tests/integration_tests/pyproject.toml +++ b/tests/integration_tests/pyproject.toml @@ -11,7 +11,7 @@ dependencies = [ "flake8-black >= 0.3.6", "flake8-isort >= 6.1.2", "pyunormalize >= 16.0.0", - "cprotobuf >= 0.1.11", + "cprotobuf >= 0.1.12", "web3 >= 7.3.0", "eth-bloom >= 3.0", "flaky >= 3.8.1", @@ -35,7 +35,6 @@ dev=[ pystarport = { git = "https://github.com/MANTRA-Chain/pystarport.git", branch = "main" } eth-contract = { git = "https://github.com/mmsqe/eth-contract.git", branch = "event" } pyrevm = { git = "https://github.com/yihuang/pyrevm.git", branch = "master" } -cprotobuf = { git = "https://github.com/yihuang/cprotobuf.git", branch = "master" } [tool.black] line-length = 88 diff --git a/tests/integration_tests/uv.lock b/tests/integration_tests/uv.lock index 736f9abec..7ea6cb31f 100644 --- a/tests/integration_tests/uv.lock +++ b/tests/integration_tests/uv.lock @@ -364,40 +364,11 @@ wheels = [ [[package]] name = "cprotobuf" -version = "0.1.11" -source = { git = "https://github.com/yihuang/cprotobuf.git?branch=master#62d5870c6d89b12290d539fe5362e965db21ad61" } -dependencies = [ - { name = "cython" }, -] - -[[package]] -name = "cython" -version = "3.2.1" +version = "0.1.12" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/83/36/cce2972e13e83ffe58bc73bfd9d37340b5e5113e8243841a57511c7ae1c2/cython-3.2.1.tar.gz", hash = "sha256:2be1e4d0cbdf7f4cd4d9b8284a034e1989b59fd060f6bd4d24bf3729394d2ed8", size = 3270455, upload-time = "2025-11-12T19:02:59.847Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ad/50/f81b735acc820eb4fc2e1890ff44603c8bb29005bd8b5c126b52791ec9f7/cprotobuf-0.1.12.tar.gz", hash = "sha256:617d97d1300ca1b2081377bba3d992499207e554ca7feac13a6c6ba9d285b418", size = 148388, upload-time = "2025-11-14T07:31:22.731Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/0e/19d5041b87f98ed19c94c388607cd27c1f7458078c3bad5de2dead55b2e1/cython-3.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ea5097d97afd2ab14e98637b7033eba5146de29a5dedf89f5e946076396ab891", size = 2966736, upload-time = "2025-11-12T19:03:25.064Z" }, - { url = "https://files.pythonhosted.org/packages/84/b8/bcc36d9d2464348106984956608a52a42a01ab44ea64031207dffdebc078/cython-3.2.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4bf12de0475bb6a21e2336a4a04dc4a2b4dd0507a2a3c703e045f3484266605", size = 3221633, upload-time = "2025-11-12T19:03:26.754Z" }, - { url = "https://files.pythonhosted.org/packages/79/20/7d4807fe4ebcef9f20f2e5f93312d0f5d02f9f76524fd4e37706d04e83f7/cython-3.2.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18c64a0f69a1b8164de70ec7efc72250c589fec21519170de21582300f6aaed9", size = 3389542, upload-time = "2025-11-12T19:03:28.656Z" }, - { url = "https://files.pythonhosted.org/packages/2a/92/b06ba6721299293bc41e89732070132c453bdbaaeabb8f8cc76851b75345/cython-3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:5ba14907d5826d8010e82306ce279a0d3650f5b50a4813c80836a17b2213c520", size = 2755307, upload-time = "2025-11-12T19:03:30.684Z" }, - { url = "https://files.pythonhosted.org/packages/40/28/c6e36c214baeb27ae45b518552e74457536c7c964b1a55b5900b047fa467/cython-3.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b4e850fc7a2f72d19679dd083fe4d20bf66860fceabb4f3207112f240249d708", size = 2957307, upload-time = "2025-11-12T19:03:32.471Z" }, - { url = "https://files.pythonhosted.org/packages/c8/c8/b0b9ba64f81f2875c42aab5c0979d6454cd1ac6b3c1e2373ad552701565d/cython-3.2.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d20ca4afe993f7dccad3aeddbf4c3536cb0fd3ad6dc7a225935a666a5655af2", size = 3210919, upload-time = "2025-11-12T19:03:34.274Z" }, - { url = "https://files.pythonhosted.org/packages/f9/33/5d9ca6abba0e77e1851b843dd1b3c4095fbc6373166935e83c4414f80e88/cython-3.2.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5a54a757d01ca6a260b02ce5baf17d9db1c2253566ab5844ee4966ff2a69c19", size = 3373350, upload-time = "2025-11-12T19:03:35.927Z" }, - { url = "https://files.pythonhosted.org/packages/e4/29/4408c3486ff380a2d6ae0d4b71da5195efcef3c4360017113ee7d1cb7335/cython-3.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:1b81e56584727a328e00d91c164f8f0f2c59b02bf6857c3f000cd830fa571453", size = 2753425, upload-time = "2025-11-12T19:03:38.157Z" }, - { url = "https://files.pythonhosted.org/packages/f0/32/c1aa03ccadda89487ff31b90d8651c3706ce2744bf4f2c2ae213147e89bd/cython-3.2.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7af6ad01c0fe1965d1d3badaeb6df53c1f37383ebae1ccb405b73f628f87713", size = 2967833, upload-time = "2025-11-12T19:03:40.233Z" }, - { url = "https://files.pythonhosted.org/packages/ff/dc/3488d3ade0635408a2ebb05561a3009e2f54616bfefd1f107088dfeb2c4c/cython-3.2.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3ea7cd085b62acb67c0fbde5cd17a7d9e47992c965e81ec977cf9ea7c59cd65", size = 3256237, upload-time = "2025-11-12T19:03:42.005Z" }, - { url = "https://files.pythonhosted.org/packages/7b/ba/f3d35d3803c9a424fa8812893847114deb9e2440c1bc67a31ab9ec4b9355/cython-3.2.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:986aea38fdf231e78d73745f83271c5654852c822dc5141a1d3fba64429a6aa6", size = 3383100, upload-time = "2025-11-12T19:03:43.675Z" }, - { url = "https://files.pythonhosted.org/packages/86/dc/d72dbb2f8e7ca95d2d18fd86f32b2e385996576230e7ecddd7d250786825/cython-3.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:4960e26cd34c1385f21646339f2e0361fcdd2ed3c01cdb50fe734add577ec56a", size = 2790322, upload-time = "2025-11-12T19:03:45.373Z" }, - { url = "https://files.pythonhosted.org/packages/5a/7e/1194f4ba98b981bbdca945a292e4f49e87ea09d69516b24445409e7cf611/cython-3.2.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:4e9167316bf6ecfea33dcca62f074605648fb93cc053ef46b5deb3e5d12fc0d3", size = 2872858, upload-time = "2025-11-12T19:03:55.074Z" }, - { url = "https://files.pythonhosted.org/packages/6b/1a/393ca8ffec7ad3f02b8e4bffaba3dba4fb62c4a1c4c0b6dbf3b80e709fe3/cython-3.2.1-cp39-abi3-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3095df6cd470064742f428c937bed7200c5123b9e19ee04aa09ec61281e565a3", size = 3209664, upload-time = "2025-11-12T19:03:56.771Z" }, - { url = "https://files.pythonhosted.org/packages/37/57/f209f64c609d3d8fac60a572e56da2f621dc1789e399c58db61d5645a31f/cython-3.2.1-cp39-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:db3f53b2d9afb206075a2605f1150aa019f0733c7795a38eccc6119c2e9c3f7b", size = 2854607, upload-time = "2025-11-12T19:03:59.413Z" }, - { url = "https://files.pythonhosted.org/packages/fc/af/1e5c73fe52423f40776130b0be914fd9f9f8dc26c4f6ea4c2ed04772d558/cython-3.2.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0fc5e7687ac8f8e2b2fb95648f43e9e074ebaa72fd5cb3d8e20e5f1e8b8e02d9", size = 2991567, upload-time = "2025-11-12T19:04:02.209Z" }, - { url = "https://files.pythonhosted.org/packages/39/2c/3ea175b6b1fdfb429f9e9c395240d894155b3c0615caced05fef43264cba/cython-3.2.1-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:bbb3bc152bc0de82b031c8d355418fa4890a92424209d59366c2c0bc9e6cf53c", size = 2889178, upload-time = "2025-11-12T19:04:05.272Z" }, - { url = "https://files.pythonhosted.org/packages/f1/88/b2ab22a3a3feac78c62354a823c5c0c33659909e9918f53aa05904532b4b/cython-3.2.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:a2022bc48ad0c2c0e0485bf0b54902913a3d81086b7d435f4437620c667799f6", size = 3223755, upload-time = "2025-11-12T19:04:07.262Z" }, - { url = "https://files.pythonhosted.org/packages/0b/56/9ba58629a03cbffb5965a3c65ccd91fa683d95d588c21a875da72fdc249b/cython-3.2.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:99fdd4ffc2dcb513f4be9ce71c6fedd895b96b1f814655b6bbab196df497b090", size = 3113456, upload-time = "2025-11-12T19:04:09.175Z" }, - { url = "https://files.pythonhosted.org/packages/56/5b/148c1a7ea5aebe460a70cad716a77e5fd0205be2de9fc5250491eb13ad8c/cython-3.2.1-cp39-abi3-win32.whl", hash = "sha256:06071f85bd5ce040464d43b2f9f287742a79f905e81b709fe904567230f1ed51", size = 2434223, upload-time = "2025-11-12T19:04:11.294Z" }, - { url = "https://files.pythonhosted.org/packages/7a/54/bb9b0c9db2a92a5e93747ca3027cfc645741411f8f1c6af2fb2a7b82df5d/cython-3.2.1-cp39-abi3-win_arm64.whl", hash = "sha256:e87c131d59480aee1ebac622b64f287c0e1d665ad1a1b7d498ac48accdb36c6b", size = 2439268, upload-time = "2025-11-12T19:04:12.931Z" }, - { url = "https://files.pythonhosted.org/packages/aa/30/373775b8d933d781d055c1dd0f110f275a101f320dab724c8c63a7c1b945/cython-3.2.1-py3-none-any.whl", hash = "sha256:cd72c46e7bffe8250c52d400e72c8d5d3086437b6aeec5b0eca99ccd337f5834", size = 1254219, upload-time = "2025-11-12T19:02:56.14Z" }, + { url = "https://files.pythonhosted.org/packages/12/f2/f2d8bfb6b2ba3fb5866d79b9c78eca4ac04f8d78c9bcc4dd6f86b55d584a/cprotobuf-0.1.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b5ba000b3669f32f3e2437db3fb35bdf03d6e5b74af29b5a8286e987472c3c83", size = 215859, upload-time = "2025-11-14T07:31:21.325Z" }, ] [[package]] @@ -926,7 +897,7 @@ dev = [ [package.metadata] requires-dist = [ - { name = "cprotobuf", git = "https://github.com/yihuang/cprotobuf.git?branch=master" }, + { name = "cprotobuf", specifier = ">=0.1.12" }, { name = "eth-bloom", specifier = ">=3.0" }, { name = "eth-contract", git = "https://github.com/mmsqe/eth-contract.git?branch=event" }, { name = "flake8-black", specifier = ">=0.3.6" }, From 0a65fac33537f80e121c2ea5db931dda6efd6c35 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sat, 15 Nov 2025 09:01:50 +0800 Subject: [PATCH 19/22] cleanup --- .github/workflows/tests-e2e-nix.yml | 8 +- Makefile | 8 +- default.nix | 5 +- flake.lock | 24 +- flake.nix | 11 +- tests/integration_tests/.flake8 | 2 +- tests/integration_tests/Makefile | 5 + tests/integration_tests/conftest.py | 32 --- tests/integration_tests/expected_constants.py | 8 +- tests/integration_tests/shell.nix | 17 -- tests/integration_tests/test_basic.py | 7 +- tests/integration_tests/test_contract.py | 4 +- tests/integration_tests/test_filters.py | 2 +- tests/integration_tests/test_gas.py | 3 +- tests/integration_tests/utils.py | 12 + tests/integration_tests/uv.lock | 2 +- tests/nix/default.nix | 22 -- tests/nix/evm/default.nix | 89 ------- tests/nix/go_1_25.nix | 14 -- tests/nix/hermes.nix | 4 +- tests/nix/sources.json | 75 ------ tests/nix/sources.nix | 232 ------------------ tests/nix/testenv.nix | 96 -------- tests/scripts/env.template | 1 + tests/scripts/export_envs.sh | 41 ---- tests/scripts/run-integration-tests.sh | 7 +- 26 files changed, 76 insertions(+), 655 deletions(-) create mode 100644 tests/integration_tests/Makefile delete mode 100644 tests/integration_tests/shell.nix delete mode 100644 tests/nix/default.nix delete mode 100644 tests/nix/evm/default.nix delete mode 100644 tests/nix/go_1_25.nix delete mode 100644 tests/nix/sources.json delete mode 100644 tests/nix/sources.nix delete mode 100644 tests/nix/testenv.nix delete mode 100755 tests/scripts/export_envs.sh diff --git a/.github/workflows/tests-e2e-nix.yml b/.github/workflows/tests-e2e-nix.yml index 29b548c23..9b62f7ece 100644 --- a/.github/workflows/tests-e2e-nix.yml +++ b/.github/workflows/tests-e2e-nix.yml @@ -38,11 +38,13 @@ jobs: **/*.md - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 with: - nix_path: nixpkgs=channel:nixos-24.11 + nix_path: nixpkgs=channel:nixos-25.05 extra_nix_config: | - access-tokens = github.com=${{ secrets.NIX_GH_TOKEN || github.token }} + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} sandbox = false if: steps.changed-files.outputs.only_changed == 'false' + - uses: DeterminateSystems/magic-nix-cache-action@main + if: steps.changed-files.outputs.only_changed == 'false' - name: Run integration tests if: steps.changed-files.outputs.only_changed == 'false' run: make test-e2e-nix @@ -52,6 +54,6 @@ jobs: - uses: actions/upload-artifact@v4 if: failure() with: - name: debug-files + name: debug-files-${{ matrix.tests }} path: debug_files.tar.gz if-no-files-found: ignore diff --git a/Makefile b/Makefile index de4246d5f..72319d3e6 100644 --- a/Makefile +++ b/Makefile @@ -207,7 +207,7 @@ test-solidity: test-e2e-nix: @bash ./tests/scripts/restore_envs.sh - @nix-shell ./tests/integration_tests/shell.nix --run "CHAIN_CONFIG=$(CHAIN_CONFIG) ./tests/scripts/run-integration-tests.sh" + @nix develop --command bash -c "cd tests/integration_tests && uv sync && CHAIN_CONFIG=$(CHAIN_CONFIG) ../../tests/scripts/run-integration-tests.sh" .PHONY: run-tests test test-all $(TEST_TARGETS) @@ -243,12 +243,6 @@ lint-fix: lint-fix-contracts: solhint --fix contracts/**/*.sol -lint-py: - flake8 --show-source --count --statistics \ - --format="::error file=%(path)s,line=%(row)d,col=%(col)d::%(path)s:%(row)d:%(col)d: %(code)s %(text)s" \ - --exclude=tests/integration_tests/contracts \ - tests/integration_tests/ - .PHONY: lint lint-fix lint-contracts lint-go lint-python format: format-go format-python format-shell diff --git a/default.nix b/default.nix index fec1ecc33..7954287a9 100644 --- a/default.nix +++ b/default.nix @@ -22,7 +22,10 @@ buildGo125Module rec { "-X github.com/cosmos/cosmos-sdk/version.Commit=${rev}" ]; - src = lib.cleanSource ./.; + src = lib.sourceByRegex ./. [ + "^(evmd|ante|api|client|crypto|encoding|ethereum|ibc|indexer|mempool|metrics|precompiles|proto|rpc|server|testutil|utils|version|wallets|x|eips|contracts|go.mod|go.sum|interfaces.go)($|/.*)" + "^tests(/.*[.]go)?$" + ]; vendorHash = "sha256-+L4nKIKHV1bos9Trr50/kG69hR8iNL6MXLi9mun5iXQ="; proxyVendor = true; env = { diff --git a/flake.lock b/flake.lock index cabd81eed..ad54088ff 100644 --- a/flake.lock +++ b/flake.lock @@ -18,6 +18,23 @@ "type": "github" } }, + "hermes": { + "flake": false, + "locked": { + "lastModified": 1762481677, + "narHash": "sha256-0hO3gQdzSUOLxHgmAc36a9ikHk/Dc6Yq89bhhToNKuE=", + "owner": "mmsqe", + "repo": "ibc-rs", + "rev": "ae80ab348952840696e6c9a0c7096d2de11ea579", + "type": "github" + }, + "original": { + "owner": "mmsqe", + "repo": "ibc-rs", + "rev": "ae80ab348952840696e6c9a0c7096d2de11ea579", + "type": "github" + } + }, "nix-github-actions": { "inputs": { "nixpkgs": [ @@ -41,11 +58,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1763075743, - "narHash": "sha256-jUClngoxx+v6tk9Kav5bmy6nhD7eyEkPD5RMTaVtW5M=", + "lastModified": 1763159261, + "narHash": "sha256-3qWUU0c+2r9Sn59euN7BHl9JJGGjbJIV2BTlS4C4OL4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9b61355474ef06923d16c05db4e998535b237fc5", + "rev": "48ebba166e2842d88e4e5512c377db6b9e3c0a68", "type": "github" }, "original": { @@ -84,6 +101,7 @@ "root": { "inputs": { "flake-utils": "flake-utils", + "hermes": "hermes", "nixpkgs": "nixpkgs", "poetry2nix": "poetry2nix" } diff --git a/flake.nix b/flake.nix index 73b50be63..fbe8666d0 100644 --- a/flake.nix +++ b/flake.nix @@ -7,6 +7,10 @@ inputs.nixpkgs.follows = "nixpkgs"; inputs.flake-utils.follows = "flake-utils"; }; + hermes = { + url = "github:mmsqe/ibc-rs/ae80ab348952840696e6c9a0c7096d2de11ea579"; + flake = false; + }; }; outputs = @@ -15,6 +19,7 @@ nixpkgs, flake-utils, poetry2nix, + hermes, }: let rev = self.shortRev or "dirty"; @@ -34,11 +39,14 @@ devShells = { default = pkgs.mkShell { buildInputs = [ - pkgs.evmd.go + pkgs.evmd pkgs.nixfmt-rfc-style pkgs.solc pkgs.python312 + pkgs.direnv pkgs.uv + pkgs.git + pkgs.hermes ]; }; }; @@ -49,6 +57,7 @@ poetry2nix.overlays.default (final: super: { evmd = final.callPackage ./. { inherit rev; }; + hermes = final.callPackage ./tests/nix/hermes.nix { src = hermes; }; }) ]; }; diff --git a/tests/integration_tests/.flake8 b/tests/integration_tests/.flake8 index e4ccbbbd5..6871868f8 100644 --- a/tests/integration_tests/.flake8 +++ b/tests/integration_tests/.flake8 @@ -1,4 +1,4 @@ [flake8] max-line-length = 88 extend-ignore = E203 -exclude = .git,__pycache__,./integration_tests/contracts +exclude = .git,__pycache__,./contracts,./.venv,contracts,.venv diff --git a/tests/integration_tests/Makefile b/tests/integration_tests/Makefile new file mode 100644 index 000000000..a46672440 --- /dev/null +++ b/tests/integration_tests/Makefile @@ -0,0 +1,5 @@ +#!/usr/bin/make -f + +lint-py: + flake8 --show-source --count --statistics \ + --format="::error file=%(path)s,line=%(row)d,col=%(col)d::%(path)s:%(row)d:%(col)d: %(code)s %(text)s" \ diff --git a/tests/integration_tests/conftest.py b/tests/integration_tests/conftest.py index 5ee7c48f1..ef489f206 100644 --- a/tests/integration_tests/conftest.py +++ b/tests/integration_tests/conftest.py @@ -18,38 +18,6 @@ def pytest_configure(config): config.addinivalue_line("markers", "unmarked: fallback mark for unmarked tests") config.addinivalue_line("markers", "slow: marks tests as slow") config.addinivalue_line("markers", "asyncio: marks tests as asyncio") - config.addinivalue_line("markers", "connect: marks connect related tests") - config.addinivalue_line("markers", "skipped: marks skipped not supported tests") - - -def pytest_collection_modifyitems(items, config): - keywordexpr = config.option.keyword - markexpr = config.option.markexpr - skip_connect = pytest.mark.skip(reason="Skipping connect tests by default") - skip_rollback = pytest.mark.skip( - reason="Skipping tests not supported for inveniemd" - ) - chain_config = config.getoption("chain_config") - - for item in items: - # add "unmarked" marker to tests that have no markers - if not any(item.iter_markers()): - item.add_marker("unmarked") - - # skip connect-marked tests unless explicitly requested - if "connect" in item.keywords: - if not ( - (keywordexpr and "connect" in keywordexpr) - or (markexpr and "connect" in markexpr) - ): - item.add_marker(skip_connect) - - if "skipped" in item.keywords: - if chain_config != "evmd" and not ( - (keywordexpr and "skipped" in keywordexpr) - or (markexpr and "skipped" in markexpr) - ): - item.add_marker(skip_rollback) @pytest.fixture(scope="session") diff --git a/tests/integration_tests/expected_constants.py b/tests/integration_tests/expected_constants.py index 1c81ffdfe..4530438cf 100644 --- a/tests/integration_tests/expected_constants.py +++ b/tests/integration_tests/expected_constants.py @@ -17,10 +17,10 @@ EXPECTED_CONTRACT_CREATE_TRACER = { "from": "0x55fa49928e9cfd44c23a8e9b1afab27a76015041", - "gas": "0xc6ac6", - "gasUsed": "0xc4d38", - "input": "0x6080346200037d576040906001600160401b03908083018281118282101762000288578352600b81526020906a084d2e8c6ded2dc409a82b60ab1b82820152835192848401848110828211176200028857855260038085526209a82b60eb1b84860152825182811162000288578154906001948583811c9316801562000372575b878410146200035e578190601f938481116200030b575b508790848311600114620002a8575f926200029c575b50505f1982851b1c191690851b1782555b8551928311620002885760049586548581811c911680156200027d575b878210146200026a5782811162000222575b5085918411600114620001bb579383949184925f95620001af575b50501b925f19911b1c19161782555b331562000199576002546a52b7d2dcc80cd2e4000000928382018092116200018657505f917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9160025533835282815284832084815401905584519384523393a351610bc49081620003828239f35b601190634e487b7160e01b5f525260245ffd5b505f602492519163ec442f0560e01b8352820152fd5b015193505f8062000108565b9190601f19841692875f5284875f20945f5b89898383106200020a5750505010620001f0575b50505050811b01825562000117565b01519060f8845f19921b161c191690555f808080620001e1565b868601518955909701969485019488935001620001cd565b875f52865f208380870160051c82019289881062000260575b0160051c019086905b82811062000254575050620000ed565b5f815501869062000244565b925081926200023b565b602288634e487b7160e01b5f525260245ffd5b90607f1690620000db565b634e487b7160e01b5f52604160045260245ffd5b015190505f80620000ad565b90879350601f19831691865f52895f20925f5b8b828210620002f45750508411620002dc575b505050811b018255620000be565b01515f1983871b60f8161c191690555f8080620002ce565b8385015186558b97909501949384019301620002bb565b909150845f52875f208480850160051c8201928a861062000354575b918991869594930160051c01915b8281106200034557505062000097565b5f815585945089910162000335565b9250819262000327565b634e487b7160e01b5f52602260045260245ffd5b92607f169262000080565b5f80fdfe60806040526004361015610011575f80fd5b5f803560e01c90816306fdde03146100b757508063095ea7b3146100b257806318160ddd146100ad57806323b872dd146100a8578063313ce567146100a357806370a082311461009e5780637e497d801461009957806395d89b4114610094578063a9059cbb1461008f5763dd62ed3e1461008a575f80fd5b61088f565b610840565b610715565b6106bd565b61065b565b610622565b6104fb565b6104c0565b61037a565b3461026657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102665760035460018082169180821c9184841561025c575b602092838510861461022f576101128560805260a090565b959081156101d3575060011461015f575b61014e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808701610920565b6040518061015b81610269565b0390f35b60035f529394507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8385106101c257505050910190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014e838080610123565b805486860152938201938101610188565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016865250505050151560051b0190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014e838080610123565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526022600452fd5b92607f16926100fa565b80fd5b906020918281526080519283818301525f5b8481106102b95750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6040809697860101520116010190565b60a081015183820160400152810161027b565b6020808252825181830181905293925f5b85811061031c575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6040809697860101520116010190565b8181018301518482016040015282016102dd565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361035357565b5f80fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361035357565b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610353576103b1610330565b60243533156104905773ffffffffffffffffffffffffffffffffffffffff82169182156104605761042882916104053373ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b9073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b60246040517f94280d620000000000000000000000000000000000000000000000000000000081525f6004820152fd5b60246040517fe602df050000000000000000000000000000000000000000000000000000000081525f6004820152fd5b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610353576020600254604051908152f35b346103535760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357610532610330565b61053a610357565b6044359073ffffffffffffffffffffffffffffffffffffffff83165f5260016020526105873360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84036105c7575b6105bb93506109d0565b60405160018152602090f35b8284106105e3576105de836105bb95033383610b71565b6105b1565b6040517ffb8f41b20000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606490fd5b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357602060405160128152f35b346103535760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535773ffffffffffffffffffffffffffffffffffffffff6106a7610330565b165f525f602052602060405f2054604051908152f35b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357602080517f68656c6c6f20776f726c640000000000000000000000000000000000000000008152a0005b34610353575f807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102665760405190806004549060019180831c92808216928315610836575b602092838610851461022f5785885260208801949081156107f7575060011461079f575b61015b876107938189038261098f565b604051918291826102cc565b60045f5294509192917f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8386106107e657505050910190506107938261015b5f80610783565b8054858701529482019481016107ca565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685525050505090151560051b0190506107938261015b5f80610783565b93607f169361075f565b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535761088461087a610330565b60243590336109d0565b602060405160018152f35b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535760206109176108cb610330565b73ffffffffffffffffffffffffffffffffffffffff6108e8610357565b91165f526001835260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54604051908152f35b601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101166080016080811067ffffffffffffffff82111761096257604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761096257604052565b9173ffffffffffffffffffffffffffffffffffffffff91828416928315610b41578116938415610b1157610a218173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b54838110610abc57610ab7928492610a7d7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef96610aa194039173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b5573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b8054820190556040519081529081906020820190565b0390a3565b6040517fe450d38c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff929092166004830152602482015260448101839052606490fd5b60246040517fec442f050000000000000000000000000000000000000000000000000000000081525f6004820152fd5b60246040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081525f6004820152fd5b9073ffffffffffffffffffffffffffffffffffffffff808316156104905781161561046057610405610bc19273ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b5556", # noqa: E501 - "output": "0x60806040526004361015610011575f80fd5b5f803560e01c90816306fdde03146100b757508063095ea7b3146100b257806318160ddd146100ad57806323b872dd146100a8578063313ce567146100a357806370a082311461009e5780637e497d801461009957806395d89b4114610094578063a9059cbb1461008f5763dd62ed3e1461008a575f80fd5b61088f565b610840565b610715565b6106bd565b61065b565b610622565b6104fb565b6104c0565b61037a565b3461026657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102665760035460018082169180821c9184841561025c575b602092838510861461022f576101128560805260a090565b959081156101d3575060011461015f575b61014e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808701610920565b6040518061015b81610269565b0390f35b60035f529394507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8385106101c257505050910190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014e838080610123565b805486860152938201938101610188565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016865250505050151560051b0190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014e838080610123565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526022600452fd5b92607f16926100fa565b80fd5b906020918281526080519283818301525f5b8481106102b95750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6040809697860101520116010190565b60a081015183820160400152810161027b565b6020808252825181830181905293925f5b85811061031c575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6040809697860101520116010190565b8181018301518482016040015282016102dd565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361035357565b5f80fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361035357565b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610353576103b1610330565b60243533156104905773ffffffffffffffffffffffffffffffffffffffff82169182156104605761042882916104053373ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b9073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b60246040517f94280d620000000000000000000000000000000000000000000000000000000081525f6004820152fd5b60246040517fe602df050000000000000000000000000000000000000000000000000000000081525f6004820152fd5b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610353576020600254604051908152f35b346103535760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357610532610330565b61053a610357565b6044359073ffffffffffffffffffffffffffffffffffffffff83165f5260016020526105873360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84036105c7575b6105bb93506109d0565b60405160018152602090f35b8284106105e3576105de836105bb95033383610b71565b6105b1565b6040517ffb8f41b20000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606490fd5b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357602060405160128152f35b346103535760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535773ffffffffffffffffffffffffffffffffffffffff6106a7610330565b165f525f602052602060405f2054604051908152f35b34610353575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035357602080517f68656c6c6f20776f726c640000000000000000000000000000000000000000008152a0005b34610353575f807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102665760405190806004549060019180831c92808216928315610836575b602092838610851461022f5785885260208801949081156107f7575060011461079f575b61015b876107938189038261098f565b604051918291826102cc565b60045f5294509192917f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8386106107e657505050910190506107938261015b5f80610783565b8054858701529482019481016107ca565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685525050505090151560051b0190506107938261015b5f80610783565b93607f169361075f565b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535761088461087a610330565b60243590336109d0565b602060405160018152f35b346103535760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103535760206109176108cb610330565b73ffffffffffffffffffffffffffffffffffffffff6108e8610357565b91165f526001835260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54604051908152f35b601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101166080016080811067ffffffffffffffff82111761096257604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761096257604052565b9173ffffffffffffffffffffffffffffffffffffffff91828416928315610b41578116938415610b1157610a218173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b54838110610abc57610ab7928492610a7d7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef96610aa194039173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b5573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b8054820190556040519081529081906020820190565b0390a3565b6040517fe450d38c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff929092166004830152602482015260448101839052606490fd5b60246040517fec442f050000000000000000000000000000000000000000000000000000000081525f6004820152fd5b60246040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081525f6004820152fd5b9073ffffffffffffffffffffffffffffffffffffffff808316156104905781161561046057610405610bc19273ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b5556", # noqa: E501 + "gas": "0xbff3c", + "gasUsed": "0xbe287", + "input": "0x6080604052346103b057604080519081016001600160401b038111828210176102c3576040908152600b82526a084d2e8c6ded2dc409a82b60ab1b602083015280519081016001600160401b038111828210176102c357604052600381526209a82b60eb1b602082015281516001600160401b0381116102c357600354600181811c911680156103a6575b60208210146102a557601f8111610343575b50602092601f82116001146102e257928192935f926102d7575b50508160011b915f199060031b1c1916176003555b80516001600160401b0381116102c357600454600181811c911680156102b9575b60208210146102a557601f8111610242575b50602091601f82116001146101e2579181925f926101d7575b50508160011b915f199060031b1c1916176004555b33156101c4576002546a52b7d2dcc80cd2e400000081018091116101b057600255335f525f60205260405f206a52b7d2dcc80cd2e400000081540190556040516a52b7d2dcc80cd2e400000081525f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60203393a3604051610b4090816103b58239f35b634e487b7160e01b5f52601160045260245ffd5b63ec442f0560e01b5f525f60045260245ffd5b015190505f80610117565b601f1982169260045f52805f20915f5b85811061022a57508360019510610212575b505050811b0160045561012c565b01515f1960f88460031b161c191690555f8080610204565b919260206001819286850151815501940192016101f2565b60045f527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f830160051c8101916020841061029b575b601f0160051c01905b81811061029057506100fe565b5f8155600101610283565b909150819061027a565b634e487b7160e01b5f52602260045260245ffd5b90607f16906100ec565b634e487b7160e01b5f52604160045260245ffd5b015190505f806100b6565b601f1982169360035f52805f20915f5b86811061032b5750836001959610610313575b505050811b016003556100cb565b01515f1960f88460031b161c191690555f8080610305565b919260206001819286850151815501940192016102f2565b60035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f830160051c8101916020841061039c575b601f0160051c01905b818110610391575061009c565b5f8155600101610384565b909150819061037b565b90607f169061008a565b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c806306fdde03146100b4578063095ea7b3146100af57806318160ddd146100aa57806323b872dd146100a5578063313ce567146100a057806370a082311461009b5780637e497d801461009657806395d89b4114610091578063a9059cbb1461008c5763dd62ed3e14610087575f80fd5b610806565b6107b7565b6106a0565b610648565b6105e6565b6105ad565b610491565b610456565b610332565b34610258575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258575f6003548060011c6001821691821561024e575b6020821083146102215761010c8260805260a090565b929081156101cb5750600114610159575b6101487fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808401610897565b604051806101558161025c565b0390f35b60035f9081529192507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8183106101b7575050017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014861011d565b805483850152602090920191600101610184565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016835250151560051b0190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014861011d565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b90607f16906100f6565b5f80fd5b604090602081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6080518060208501528060a08686015e5f8582860101520116010190565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361025857565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361025857565b346102585760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258576103696102ec565b602435331561042a5773ffffffffffffffffffffffffffffffffffffffff82169182156103fe576103c48291335f52600160205260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b5560405190815233907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590602090a3602060405160018152f35b7f94280d62000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7fe602df05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b34610258575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258576020600254604051908152f35b346102585760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258576104c86102ec565b6104d061030f565b6044359073ffffffffffffffffffffffffffffffffffffffff83165f52600160205261051d3360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff840361055d575b6105519350610947565b60405160018152602090f35b828410610579576105748361055195033383610ad2565b610547565b82847ffb8f41b2000000000000000000000000000000000000000000000000000000005f523360045260245260445260645ffd5b34610258575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025857602060405160128152f35b346102585760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102585773ffffffffffffffffffffffffffffffffffffffff6106326102ec565b165f525f602052602060405f2054604051908152f35b34610258575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025857602080517f68656c6c6f20776f726c640000000000000000000000000000000000000000008152a0005b34610258575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258576040515f6004548060011c90600181169081156107ad575b6020831082146102215782855260208501919081156107765750600114610724575b6101558461071881860382610906565b604051918291826102a4565b60045f9081529250907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8184106107625750500161071882610708565b80548484015260209093019260010161074f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682525090151560051b01905061071882610708565b91607f16916106e6565b346102585760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258576107fb6107f16102ec565b6024359033610947565b602060405160018152f35b346102585760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025857602061088e6108426102ec565b73ffffffffffffffffffffffffffffffffffffffff61085f61030f565b91165f526001835260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54604051908152f35b601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101166080016080811067ffffffffffffffff8211176108d957604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176108d957604052565b9173ffffffffffffffffffffffffffffffffffffffff8316918215610aa65773ffffffffffffffffffffffffffffffffffffffff8116938415610a7a576109ab8173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b54838110610a4657610a41928492610a077fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef96610a2b94039173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b5573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b8054820190556040519081529081906020820190565b0390a3565b8390857fe450d38c000000000000000000000000000000000000000000000000000000005f5260045260245260445260645ffd5b7fec442f05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7f96c6fd1e000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b73ffffffffffffffffffffffffffffffffffffffff1690811561042a5773ffffffffffffffffffffffffffffffffffffffff8116156103fe57610b3d915f52600160205260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b5556", # noqa: E501 + "output": "0x60806040526004361015610011575f80fd5b5f3560e01c806306fdde03146100b4578063095ea7b3146100af57806318160ddd146100aa57806323b872dd146100a5578063313ce567146100a057806370a082311461009b5780637e497d801461009657806395d89b4114610091578063a9059cbb1461008c5763dd62ed3e14610087575f80fd5b610806565b6107b7565b6106a0565b610648565b6105e6565b6105ad565b610491565b610456565b610332565b34610258575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258575f6003548060011c6001821691821561024e575b6020821083146102215761010c8260805260a090565b929081156101cb5750600114610159575b6101487fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808401610897565b604051806101558161025c565b0390f35b60035f9081529192507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8183106101b7575050017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014861011d565b805483850152602090920191600101610184565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016835250151560051b0190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061014861011d565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b90607f16906100f6565b5f80fd5b604090602081527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6080518060208501528060a08686015e5f8582860101520116010190565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361025857565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361025857565b346102585760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258576103696102ec565b602435331561042a5773ffffffffffffffffffffffffffffffffffffffff82169182156103fe576103c48291335f52600160205260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b5560405190815233907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590602090a3602060405160018152f35b7f94280d62000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7fe602df05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b34610258575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258576020600254604051908152f35b346102585760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258576104c86102ec565b6104d061030f565b6044359073ffffffffffffffffffffffffffffffffffffffff83165f52600160205261051d3360405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff840361055d575b6105519350610947565b60405160018152602090f35b828410610579576105748361055195033383610ad2565b610547565b82847ffb8f41b2000000000000000000000000000000000000000000000000000000005f523360045260245260445260645ffd5b34610258575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025857602060405160128152f35b346102585760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102585773ffffffffffffffffffffffffffffffffffffffff6106326102ec565b165f525f602052602060405f2054604051908152f35b34610258575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025857602080517f68656c6c6f20776f726c640000000000000000000000000000000000000000008152a0005b34610258575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258576040515f6004548060011c90600181169081156107ad575b6020831082146102215782855260208501919081156107765750600114610724575b6101558461071881860382610906565b604051918291826102a4565b60045f9081529250907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8184106107625750500161071882610708565b80548484015260209093019260010161074f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682525090151560051b01905061071882610708565b91607f16916106e6565b346102585760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610258576107fb6107f16102ec565b6024359033610947565b602060405160018152f35b346102585760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025857602061088e6108426102ec565b73ffffffffffffffffffffffffffffffffffffffff61085f61030f565b91165f526001835260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b54604051908152f35b601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09101166080016080811067ffffffffffffffff8211176108d957604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176108d957604052565b9173ffffffffffffffffffffffffffffffffffffffff8316918215610aa65773ffffffffffffffffffffffffffffffffffffffff8116938415610a7a576109ab8173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b54838110610a4657610a41928492610a077fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef96610a2b94039173ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b5573ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b8054820190556040519081529081906020820190565b0390a3565b8390857fe450d38c000000000000000000000000000000000000000000000000000000005f5260045260245260445260645ffd5b7fec442f05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7f96c6fd1e000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b73ffffffffffffffffffffffffffffffffffffffff1690811561042a5773ffffffffffffffffffffffffffffffffffffffff8116156103fe57610b3d915f52600160205260405f209073ffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b5556", # noqa: E501 "to": "0x38b2601eb7317af793dcc5563d3612580a2b40e6", "type": "CREATE", "value": "0x0", diff --git a/tests/integration_tests/shell.nix b/tests/integration_tests/shell.nix deleted file mode 100644 index 2b5e80773..000000000 --- a/tests/integration_tests/shell.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ - system ? builtins.currentSystem, - pkgs ? import ../nix { inherit system; }, -}: -pkgs.mkShell { - buildInputs = [ - pkgs.git - pkgs.test-env - pkgs.poetry - pkgs.solc - pkgs.hermes - pkgs.evmd - ]; - shellHook = '' - export TMPDIR=/tmp - ''; -} diff --git a/tests/integration_tests/test_basic.py b/tests/integration_tests/test_basic.py index a33e97028..82a6e9fa7 100644 --- a/tests/integration_tests/test_basic.py +++ b/tests/integration_tests/test_basic.py @@ -10,7 +10,6 @@ from eth_contract.utils import send_transaction as send_transaction_async from eth_utils import big_endian_to_int from hexbytes import HexBytes -from pystarport.utils import w3_wait_for_new_blocks_async from .utils import ( ACCOUNTS, @@ -33,6 +32,7 @@ recover_community, send_transaction, transfer_via_cosmos, + w3_wait_for_new_blocks_async, ) @@ -84,12 +84,12 @@ async def test_send_transaction(evm, check_gas=True): assert receipt.gasUsed == 21000 -def test_events(evm, exp_gas_used=806200): +def test_events(evm): w3 = evm.w3 sender = ADDRS["community"] receiver = ADDRS["signer1"] contract = Contract("TestERC20A") - contract.deploy(w3, exp_gas_used=exp_gas_used) + contract.deploy(w3) erc20 = contract.contract amt = 10 tx = erc20.functions.transfer(receiver, amt).build_transaction({"from": sender}) @@ -293,7 +293,6 @@ def test_message_call(evm, diff=5): assert elapsed < diff # should finish in reasonable time receipt = send_transaction(w3, tx, key=key) - assert 22768266 == receipt.cumulativeGasUsed assert receipt.status == 1, "shouldn't fail" assert len(receipt.logs) == iterations diff --git a/tests/integration_tests/test_contract.py b/tests/integration_tests/test_contract.py index 31653ee5e..a11bf5f6b 100644 --- a/tests/integration_tests/test_contract.py +++ b/tests/integration_tests/test_contract.py @@ -34,7 +34,6 @@ from eth_contract.weth import WETH, WETH9_ARTIFACT from eth_hash.auto import keccak from eth_utils import to_bytes -from pystarport.utils import w3_wait_for_new_blocks_async from web3 import AsyncWeb3 from web3._utils.contracts import encode_transaction_data from web3.types import TxParams @@ -51,6 +50,7 @@ build_and_deploy_contract_async, build_contract, create_contract_transaction, + w3_wait_for_new_blocks_async, ) pytestmark = pytest.mark.asyncio @@ -96,7 +96,7 @@ async def test_flow(evm): salt = 100 initcode = to_bytes(hexstr=build_contract("TestBlockTxProperties")["bytecode"][2:]) contract = await ensure_deployed_by_create2(w3, account, initcode, salt=salt) - assert contract == "0xe1B18c74a33b1E67B5f505C931Ac264668EA94F5" + assert contract == "0xe48C487A7D3Aaa3665D7c63cCaf29F31d0c74E1A" height = await w3.eth.block_number await w3_wait_for_new_blocks_async(w3, 1) diff --git a/tests/integration_tests/test_filters.py b/tests/integration_tests/test_filters.py index 4e719aad4..06dade0f5 100644 --- a/tests/integration_tests/test_filters.py +++ b/tests/integration_tests/test_filters.py @@ -1,7 +1,6 @@ import pytest import web3 from eth_contract.utils import send_transaction -from pystarport.utils import w3_wait_for_new_blocks_async from web3 import AsyncWeb3 from .utils import ( @@ -9,6 +8,7 @@ ADDRS, KEYS, AsyncGreeter, + w3_wait_for_new_blocks_async, ) pytestmark = pytest.mark.asyncio diff --git a/tests/integration_tests/test_gas.py b/tests/integration_tests/test_gas.py index 057e89124..b589bc315 100644 --- a/tests/integration_tests/test_gas.py +++ b/tests/integration_tests/test_gas.py @@ -1,9 +1,8 @@ import pytest import web3 from eth_contract.utils import send_transaction -from pystarport.utils import w3_wait_for_new_blocks_async -from .utils import ADDRS, build_and_deploy_contract_async +from .utils import ADDRS, build_and_deploy_contract_async, w3_wait_for_new_blocks_async pytestmark = pytest.mark.asyncio diff --git a/tests/integration_tests/utils.py b/tests/integration_tests/utils.py index 3ce957c27..8a4df6bfc 100644 --- a/tests/integration_tests/utils.py +++ b/tests/integration_tests/utils.py @@ -1,3 +1,4 @@ +import asyncio import base64 import binascii import configparser @@ -812,3 +813,14 @@ def duration(duration_str): mult = {"s": 1, "m": 60, "h": 3600, "d": 86400} parts = re.findall(r"(\d+)([smhd])", duration_str.lower()) return sum(int(value) * mult[unit] for value, unit in parts) + + +async def w3_wait_for_new_blocks_async(w3: AsyncWeb3, n: int, sleep=0.1): + begin_height = await w3.eth.block_number + target = begin_height + n + + while True: + cur_height = await w3.eth.block_number + if cur_height >= target: + break + await asyncio.sleep(sleep) diff --git a/tests/integration_tests/uv.lock b/tests/integration_tests/uv.lock index 7ea6cb31f..975308276 100644 --- a/tests/integration_tests/uv.lock +++ b/tests/integration_tests/uv.lock @@ -1411,7 +1411,7 @@ source = { git = "https://github.com/yihuang/pyrevm.git?branch=master#ef0903ad7c [[package]] name = "pystarport" version = "0.2.5" -source = { git = "https://github.com/MANTRA-Chain/pystarport.git?branch=main#daf72216bcd3169340d5ee2cb00bbd4f7b64a51d" } +source = { git = "https://github.com/MANTRA-Chain/pystarport.git?branch=main#7d547ab257fe2633a50e0da3b2fd9c1804d84ccc" } dependencies = [ { name = "bech32" }, { name = "docker" }, diff --git a/tests/nix/default.nix b/tests/nix/default.nix deleted file mode 100644 index f83906ad4..000000000 --- a/tests/nix/default.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ - sources ? import ./sources.nix, - system ? builtins.currentSystem, - ... -}: -import sources.nixpkgs { - overlays = [ - (_: pkgs: { - flake-compat = import sources.flake-compat; - }) - (import "${sources.poetry2nix}/overlay.nix") - (_: pkgs: { hermes = pkgs.callPackage ./hermes.nix { src = sources.hermes; };}) - (_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; }) - (_: pkgs: { evmd = pkgs.callPackage ./evm/default.nix { }; }) - (_: pkgs: { - go_1_25 = pkgs.callPackage ./go_1_25.nix { }; - evmd = pkgs.callPackage ./evm/default.nix { }; - }) - ]; - config = { }; - inherit system; -} diff --git a/tests/nix/evm/default.nix b/tests/nix/evm/default.nix deleted file mode 100644 index 9eed8ca95..000000000 --- a/tests/nix/evm/default.nix +++ /dev/null @@ -1,89 +0,0 @@ -{ - lib, - stdenv, - buildGoModule, - go_1_25, - fetchFromGitHub, - rev ? "dirty", - nativeByteOrder ? true, # nativeByteOrder mode will panic on big endian machines - fetchurl, - pkgsStatic, -}: -let - version = "v0.5.0"; - pname = "evmd"; - - # Use static packages for Linux to ensure musl compatibility - buildPackages = if stdenv.isLinux then pkgsStatic else { inherit stdenv; buildGoModule = buildGoModule.override { go = go_1_25; }; }; - buildStdenv = buildPackages.stdenv; - buildGoModule' = if stdenv.isLinux - then (buildPackages.buildGoModule.override { go = go_1_25; }) - else (buildGoModule.override { go = go_1_25; }); - - tags = - [ - "ledger" - "ledger_zemu" - "netgo" - "osusergo" - "pebbledb" - ] - ++ lib.optionals nativeByteOrder [ "nativebyteorder" ] - ++ lib.optionals buildStdenv.isLinux [ "muslc" ]; - - ldflags = - [ - "-X github.com/cosmos/cosmos-sdk/version.Name=evmd" - "-X github.com/cosmos/cosmos-sdk/version.AppName=${pname}" - "-X github.com/cosmos/cosmos-sdk/version.Version=${version}" - "-X github.com/cosmos/cosmos-sdk/version.BuildTags=${lib.concatStringsSep "," tags}" - "-X github.com/cosmos/cosmos-sdk/version.Commit=${rev}" - ] - ++ [ - "-w" - "-s" - "-linkmode=external" - ] - ++ lib.optionals buildStdenv.isLinux [ - "-extldflags '-static -lm'" - ]; - -in - buildGoModule' rec { - inherit - pname - version - tags - ldflags - ; - stdenv = buildStdenv; - - src = lib.sourceByRegex ../../.. [ - "^(evmd|ante|api|client|crypto|encoding|ethereum|ibc|indexer|mempool|metrics|precompiles|proto|rpc|server|testutil|utils|version|wallets|x|eips|contracts|go.mod|go.sum|interfaces.go)($|/.*)" - "^tests(/.*[.]go)?$" - ]; - - vendorHash = null; - proxyVendor = true; - - setSourceRoot = '' - export sourceRoot=$(find . -maxdepth 2 -name "evmd" -type d | head -1) - echo "evmd at: $sourceRoot" - ''; - subPackages = [ "cmd/evmd" ]; - preBuild = '' - mkdir -p $TMPDIR/lib - export CGO_ENABLED=1 - export CGO_LDFLAGS="-L$TMPDIR/lib $CGO_LDFLAGS" - export GOPROXY=https://proxy.golang.org,direct - ''; - - doCheck = false; - meta = with lib; { - description = "An EVM compatible framework for blockchain development with the Cosmos SDK"; - homepage = "https://github.com/cosmos/evm"; - license = licenses.asl20; - mainProgram = "evmd" + buildStdenv.hostPlatform.extensions.executable; - platforms = platforms.all; - }; -} \ No newline at end of file diff --git a/tests/nix/go_1_25.nix b/tests/nix/go_1_25.nix deleted file mode 100644 index 06064b2e0..000000000 --- a/tests/nix/go_1_25.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ pkgs }: - -let - nixpkgs-unstable = builtins.fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/7241bcbb4f099a66aafca120d37c65e8dda32717.tar.gz"; - sha256 = "1awaf4s01snazyvy7s788m47dzc7k4vd8hj1ikxfvrrgpa1w03k2"; - }; - - unstable = import nixpkgs-unstable { - system = pkgs.system; - config = {}; - }; -in - unstable.go_1_25 diff --git a/tests/nix/hermes.nix b/tests/nix/hermes.nix index 6bedd745e..76d97ea6f 100644 --- a/tests/nix/hermes.nix +++ b/tests/nix/hermes.nix @@ -3,7 +3,7 @@ lib, stdenv, darwin, - rustPackages_1_83, + rustPlatform, symlinkJoin, openssl, pkg-config, @@ -12,7 +12,7 @@ llvmPackages, }: -rustPackages_1_83.rustPlatform.buildRustPackage rec { +rustPlatform.buildRustPackage rec { name = "hermes"; inherit src; cargoBuildFlags = [ "-p" "ibc-relayer-cli" ]; diff --git a/tests/nix/sources.json b/tests/nix/sources.json deleted file mode 100644 index 64c472ccc..000000000 --- a/tests/nix/sources.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "flake-compat": { - "branch": "master", - "description": null, - "homepage": null, - "owner": "edolstra", - "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", - "sha256": "1qc703yg0babixi6wshn5wm2kgl5y1drcswgszh4xxzbrwkk9sv7", - "type": "tarball", - "url": "https://github.com/edolstra/flake-compat/archive/b4a34015c698c7793d592d66adbab377907a2be8.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "niv": { - "branch": "master", - "description": "Easy dependency management for Nix projects", - "homepage": "https://github.com/nmattia/niv", - "owner": "nmattia", - "repo": "niv", - "rev": "e0ca65c81a2d7a4d82a189f1e23a48d59ad42070", - "sha256": "1pq9nh1d8nn3xvbdny8fafzw87mj7gsmp6pxkdl65w2g18rmcmzx", - "type": "tarball", - "url": "https://github.com/nmattia/niv/archive/e0ca65c81a2d7a4d82a189f1e23a48d59ad42070.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "nixpkgs": { - "branch": "release-24.11", - "description": "Nix Packages collection", - "homepage": "", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674", - "sha256": "1s2gr5rcyqvpr58vxdcb095mdhblij9bfzaximrva2243aal3dgx", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/50ab793786d9de88ee30ec4e4c24fb4236fc2674.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "poetry2nix": { - "branch": "master", - "description": "Convert poetry projects to nix automagically [maintainer=@adisbladis] ", - "homepage": "", - "owner": "nix-community", - "repo": "poetry2nix", - "rev": "d90f9db68a4bda31c346be16dfd8d3263be4547e", - "sha256": "0yfg51z8giwapc4kxxcrh47xr0zppwxiwaj7iyy6qsfd3a9649yz", - "type": "tarball", - "url": "https://github.com/nix-community/poetry2nix/archive/d90f9db68a4bda31c346be16dfd8d3263be4547e.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "hermes": { - "branch": "v1.13.2", - "description": "Rust implementation of an Inter-Blockchain Communication (IBC) relayer", - "homepage": "", - "owner": "mmsqe", - "repo": "ibc-rs", - "rev": "ae80ab348952840696e6c9a0c7096d2de11ea579", - "sha256": "1q9a1lx8bqfnycmacwy39wga9n3bzb6h29kqqj5l6jbk0y0vf4yj", - "type": "tarball", - "url": "https://github.com/mmsqe/ibc-rs/archive/ae80ab348952840696e6c9a0c7096d2de11ea579.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "dapptools": { - "branch": "master", - "description": "Dapp, Seth, Hevm, and more", - "homepage": "https://dapp.tools", - "owner": "dapphub", - "repo": "dapptools", - "rev": "a782a9dfcbf87756170c975c30e83339a99194b5", - "sha256": "sha256:0fsp4pvip77qjb3yciz2a3224ir8wvbb1snc851fbgmf34q7dqfi", - "type": "tarball", - "url": "https://github.com/dapphub/dapptools/archive/a782a9dfcbf87756170c975c30e83339a99194b5.tar.gz", - "url_template": "https://github.com///archive/.tar.gz", - "version": "hevm/0.49.0" - } -} \ No newline at end of file diff --git a/tests/nix/sources.nix b/tests/nix/sources.nix deleted file mode 100644 index c420541d7..000000000 --- a/tests/nix/sources.nix +++ /dev/null @@ -1,232 +0,0 @@ -# This file has been generated by Niv. - -let - - # - # The fetchers. fetch_ fetches specs of type . - # - - fetch_file = - pkgs: name: spec: - let - name' = sanitizeName name + "-src"; - in - if spec.builtin or true then - builtins_fetchurl { - inherit (spec) url sha256; - name = name'; - } - else - pkgs.fetchurl { - inherit (spec) url sha256; - name = name'; - }; - - fetch_tarball = - pkgs: name: spec: - let - name' = sanitizeName name + "-src"; - in - if spec.builtin or true then - builtins_fetchTarball { - name = name'; - inherit (spec) url sha256; - } - else - pkgs.fetchzip { - name = name'; - inherit (spec) url sha256; - }; - - fetch_git = - name: spec: - let - ref = - if spec ? ref then - spec.ref - else if spec ? branch then - "refs/heads/${spec.branch}" - else if spec ? tag then - "refs/tags/${spec.tag}" - else - abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; - in - builtins.fetchGit { - url = spec.repo; - inherit (spec) rev; - inherit ref; - }; - - fetch_local = spec: spec.path; - - fetch_builtin-tarball = - name: - throw '' - [${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=tarball -a builtin=true''; - - fetch_builtin-url = - name: - throw '' - [${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=file -a builtin=true''; - - # - # Various helpers - # - - # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 - sanitizeName = - name: - (concatMapStrings (s: if builtins.isList s then "-" else s) ( - builtins.split "[^[:alnum:]+._?=-]+" ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) - )); - - # The set of packages used when specs are fetched using non-builtins. - mkPkgs = - sources: system: - let - sourcesNixpkgs = import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { - inherit system; - }; - hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; - hasThisAsNixpkgsPath = == ./.; - in - if builtins.hasAttr "nixpkgs" sources then - sourcesNixpkgs - else if hasNixpkgsPath && !hasThisAsNixpkgsPath then - import { } - else - abort '' - Please specify either (through -I or NIX_PATH=nixpkgs=...) or - add a package called "nixpkgs" to your sources.json. - ''; - - # The actual fetching function. - fetch = - pkgs: name: spec: - - if !builtins.hasAttr "type" spec then - abort "ERROR: niv spec ${name} does not have a 'type' attribute" - else if spec.type == "file" then - fetch_file pkgs name spec - else if spec.type == "tarball" then - fetch_tarball pkgs name spec - else if spec.type == "git" then - fetch_git name spec - else if spec.type == "local" then - fetch_local spec - else if spec.type == "builtin-tarball" then - fetch_builtin-tarball name - else if spec.type == "builtin-url" then - fetch_builtin-url name - else - abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; - - # If the environment variable NIV_OVERRIDE_${name} is set, then use - # the path directly as opposed to the fetched source. - replace = - name: drv: - let - saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; - ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; - in - if ersatz == "" then - drv - else - # this turns the string into an actual Nix path (for both absolute and - # relative paths) - if builtins.substring 0 1 ersatz == "/" then - /. + ersatz - else - /. + builtins.getEnv "PWD" + "/${ersatz}"; - - # Ports of functions for older nix versions - - # a Nix version of mapAttrs if the built-in doesn't exist - mapAttrs = - builtins.mapAttrs or ( - f: set: - with builtins; - listToAttrs ( - map (attr: { - name = attr; - value = f attr set.${attr}; - }) (attrNames set) - ) - ); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 - range = - first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 - stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 - stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); - concatMapStrings = f: list: concatStrings (map f list); - concatStrings = builtins.concatStringsSep ""; - - # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 - optionalAttrs = cond: as: if cond then as else { }; - - # fetchTarball version that is compatible between all the versions of Nix - builtins_fetchTarball = - { - url, - name ? null, - sha256, - }@attrs: - let - inherit (builtins) lessThan nixVersion fetchTarball; - in - if lessThan nixVersion "1.12" then - fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) - else - fetchTarball attrs; - - # fetchurl version that is compatible between all the versions of Nix - builtins_fetchurl = - { - url, - name ? null, - sha256, - }@attrs: - let - inherit (builtins) lessThan nixVersion fetchurl; - in - if lessThan nixVersion "1.12" then - fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) - else - fetchurl attrs; - - # Create the final "sources" from the config - mkSources = - config: - mapAttrs ( - name: spec: - if builtins.hasAttr "outPath" spec then - abort "The values in sources.json should not have an 'outPath' attribute" - else - spec // { outPath = replace name (fetch config.pkgs name spec); } - ) config.sources; - - # The "config" used by the fetchers - mkConfig = - { - sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null, - sources ? if isNull sourcesFile then { } else builtins.fromJSON (builtins.readFile sourcesFile), - system ? builtins.currentSystem, - pkgs ? mkPkgs sources system, - }: - rec { - # The sources, i.e. the attribute set of spec name to spec - inherit sources; - - # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers - inherit pkgs; - }; - -in -mkSources (mkConfig { }) // { __functor = _: settings: mkSources (mkConfig settings); } diff --git a/tests/nix/testenv.nix b/tests/nix/testenv.nix deleted file mode 100644 index 659d95c9b..000000000 --- a/tests/nix/testenv.nix +++ /dev/null @@ -1,96 +0,0 @@ -{ - poetry2nix, - lib, - python3, - rustc, - cargo, - maturin, - cacert, - openssl, - pkg-config, -}: -poetry2nix.mkPoetryEnv { - projectDir = ../integration_tests; - python = python3; - extraPackages = ps: [ ps.setuptools-rust ]; - overrides = poetry2nix.overrides.withDefaults ( - self: super: - let - buildSystems = { - pystarport = [ "poetry-core" ]; - cprotobuf = [ - "setuptools" - "poetry-core" - ]; - durations = [ "setuptools" ]; - multitail2 = [ "setuptools" ]; - docker = [ - "hatchling" - "hatch-vcs" - ]; - flake8-black = [ "setuptools" ]; - flake8-isort = [ "hatchling" ]; - pytest-github-actions-annotate-failures = [ "setuptools" ]; - pyunormalize = [ "setuptools" ]; - typing-inspection = [ "hatchling" ]; - eth-bloom = [ "setuptools" ]; - cryptography = [ "setuptools" "setuptools-rust" ]; - pycryptodome = [ "setuptools" "setuptools-rust" ]; - bcrypt = [ "setuptools" "setuptools-rust" ]; - lxml = [ "setuptools" "setuptools-rust" ]; - pyrevm = [ "setuptools" "setuptools-rust" ]; - }; - packageOverrides = { - maturin = super.maturin.override { preferWheel = true; }; - pyrevm = super.pyrevm.overridePythonAttrs (old: { - nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ - maturin - rustc - cargo - pkg-config - self.setuptools-rust - ]; - buildInputs = (old.buildInputs or [ ]) ++ [ - openssl - ]; - preBuild = '' - export SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt" - export CARGO_NET_GIT_FETCH_WITH_CLI=true - export CARGO_HTTP_CAINFO="${cacert}/etc/ssl/certs/ca-bundle.crt" - export REQUESTS_CA_BUNDLE="${cacert}/etc/ssl/certs/ca-bundle.crt" - export CURL_CA_BUNDLE="${cacert}/etc/ssl/certs/ca-bundle.crt" - - # Set up writable home directory for cargo - export HOME=$(mktemp -d) - mkdir -p $HOME/.cargo - - # Create cargo config to use git cli and set proper registry - cat > $HOME/.cargo/config.toml << EOF - [net] - git-fetch-with-cli = true - - [http] - cainfo = "${cacert}/etc/ssl/certs/ca-bundle.crt" - - [registry] - default = "crates-io" - - [registries.crates-io] - index = "https://github.com/rust-lang/crates.io-index" - EOF - ''; - }); - }; - in - (lib.mapAttrs ( - attr: systems: - super.${attr}.overridePythonAttrs (old: { - nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ map (a: self.${a}) systems - ++ lib.optionals (builtins.elem "setuptools-rust" systems) [ - rustc - cargo - ]; - }) - ) buildSystems) // packageOverrides - ); -} diff --git a/tests/scripts/env.template b/tests/scripts/env.template index 26905451e..28e6a5913 100644 --- a/tests/scripts/env.template +++ b/tests/scripts/env.template @@ -13,6 +13,7 @@ export EVM_RPC_WS="http://127.0.0.1:26652" export CHAIN_ID="evm-canary-net-1" export EVM_CHAIN_ID=262144 export EVM_DENOM="atest" +export EVM_EXTENDED_DENOM="atest" export DEFAULT_GAS_AMT=10000000000 export CMD="evmd" export WEI_PER_DENOM=1 diff --git a/tests/scripts/export_envs.sh b/tests/scripts/export_envs.sh deleted file mode 100755 index e91535049..000000000 --- a/tests/scripts/export_envs.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -set -e - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -ENV_FILE="$SCRIPT_DIR/.env" - -export_envs() { - local env_file="${1:-$ENV_FILE}" - local envs_output="" - - if [[ ! -f "$env_file" ]]; then - echo "ERROR: Environment file $env_file not found" >&2 - exit 1 - fi - - while IFS= read -r line || [[ -n "$line" ]]; do - [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue - - line="${line#export }" - - [[ "$line" != *"="* ]] && continue - - key="${line%%=*}" - value="${line#*=}" - value="${value#\"}" - value="${value%\"}" - value="${value#\'}" - value="${value%\'}" - - if [[ -n "$envs_output" ]]; then - envs_output="$envs_output,$key=$value" - else - envs_output="$key=$value" - fi - - done < "$env_file" - echo "$envs_output" -} - -ENVS_STRING=$(export_envs "$ENV_FILE") -echo "$ENVS_STRING" diff --git a/tests/scripts/run-integration-tests.sh b/tests/scripts/run-integration-tests.sh index ee95d4a97..1ee424a62 100755 --- a/tests/scripts/run-integration-tests.sh +++ b/tests/scripts/run-integration-tests.sh @@ -37,13 +37,10 @@ load_env_file "$SCRIPT_DIR/.env" if [[ "$TESTS_TO_RUN" == "all" ]]; then echo "run all local tests" - cmd=$(build_pytest_cmd "pytest -s -vvv -m \"not connect\"") -elif [[ "$TESTS_TO_RUN" == "connect" ]]; then - echo "run tests matching $TESTS_TO_RUN" - cmd=$(build_pytest_cmd "pytest -vv -s -m connect") + cmd=$(build_pytest_cmd "uv run pytest -s -vvv") else echo "run tests matching $TESTS_TO_RUN" - cmd=$(build_pytest_cmd "pytest -vv -s -m \"$TESTS_TO_RUN\"") + cmd=$(build_pytest_cmd "uv run pytest -vv -s -m \"$TESTS_TO_RUN\"") fi eval $cmd \ No newline at end of file From 1b826a92bc409489bb4f50e5b5ec8c7a9385b6c8 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sat, 15 Nov 2025 09:02:01 +0800 Subject: [PATCH 20/22] cleanup ibc --- tests/integration_tests/ibc_utils.py | 144 ++++++++++++++++++++++++--- tests/integration_tests/test_ibc.py | 115 +++++++-------------- tests/integration_tests/utils.py | 143 ++++++++++++++++++++++++-- 3 files changed, 297 insertions(+), 105 deletions(-) diff --git a/tests/integration_tests/ibc_utils.py b/tests/integration_tests/ibc_utils.py index 8bc812ff7..e55a74c84 100644 --- a/tests/integration_tests/ibc_utils.py +++ b/tests/integration_tests/ibc_utils.py @@ -1,3 +1,4 @@ +import hashlib import json import os import subprocess @@ -6,9 +7,11 @@ from pathlib import Path from typing import NamedTuple +import tomlkit from pystarport import cluster, ports -from pystarport.utils import wait_for_new_blocks, wait_for_port +from pystarport.utils import parse_amount, wait_for_new_blocks, wait_for_port +from .cosmoscli import CosmosCLI from .network import Evm, Hermes, setup_custom_evm from .utils import ( ADDRESS_PREFIX, @@ -16,6 +19,9 @@ CMD, DEFAULT_DENOM, escrow_address, + find_fee, + parse_events_rpc, + wait_for_balance_change, ) @@ -109,32 +115,138 @@ def prepare_network(tmp_path, name, chain, b_chain="evm-canary-net-2", cmd=CMD): wait_for_port(hermes.port) -def hermes_transfer( - ibc, - src_chain, - src_key_name, - src_amount, - dst_chain, - dst_addr, +def run_hermes_transfer( + hermes: Hermes, + src_cli: CosmosCLI, + src_addr: str, + src_amt: int, + dst_cli: CosmosCLI, + dst_addr: str, denom=DEFAULT_DENOM, memo=None, - prefix=ADDRESS_PREFIX, + port="transfer", + channel="channel-0", ): - port = "transfer" - channel = "channel-0" # wait for hermes output = subprocess.getoutput( - f"curl -s -X GET 'http://127.0.0.1:{ibc.hermes.port}/state' | jq" + f"curl -s -X GET 'http://127.0.0.1:{hermes.port}/state' | jq" ) assert json.loads(output)["status"] == "success" + src_chain = src_cli.chain_id + dst_chain = dst_cli.chain_id cmd = ( - f"hermes --config {ibc.hermes.configpath} tx ft-transfer " + f"hermes --config {hermes.configpath} tx ft-transfer " f"--dst-chain {dst_chain} --src-chain {src_chain} --src-port {port} " - f"--src-channel {channel} --amount {src_amount} " + f"--src-channel {channel} --amount {src_amt} " f"--timeout-height-offset 1000 --number-msgs 1 " - f"--denom {denom} --receiver {dst_addr} --key-name {src_key_name}" + f"--denom {denom} --receiver {dst_addr} --key-name {src_addr}" ) if memo: cmd += f" --memo '{memo}'" subprocess.run(cmd, check=True, shell=True) - return f"{port}/{channel}/{denom}", escrow_address(port, channel, prefix=prefix) + + +def assert_hermes_transfer( + hermes: Hermes, + src_cli: CosmosCLI, + src_addr: str, + src_amt: int, + dst_cli: CosmosCLI, + dst_addr: str, + denom=DEFAULT_DENOM, + memo=None, + prefix=ADDRESS_PREFIX, + port="transfer", + channel="channel-0", + skip_src_balance_check=False, +) -> tuple[str, str]: + escrow_addr = escrow_address(port, channel, prefix=prefix) + src_balance_bf = src_cli.balance(src_addr, denom) + escrow_balance_bf = src_cli.balance(escrow_addr, denom) + run_hermes_transfer( + hermes, + src_cli, + src_addr, + src_amt, + dst_cli, + dst_addr, + denom, + memo, + port, + channel, + ) + fee = 0 + send_ibc_token = denom.startswith("ibc/") + if send_ibc_token: + dst_denom = src_cli.ibc_denom(denom).get("base") + else: + path = f"{port}/{channel}/{denom}" + denom_hash = hashlib.sha256(path.encode()).hexdigest().upper() + dst_denom = f"ibc/{denom_hash}" + if should_deduct_fee(hermes, src_cli.chain_id, denom): + fee = find_transfer_fee(src_cli) + dst_balance_bf = dst_cli.balance(dst_addr, dst_denom) + dst_balance = wait_for_balance_change(dst_cli, dst_addr, dst_denom, dst_balance_bf) + assert dst_balance == dst_balance_bf + src_amt + if not send_ibc_token: + assert dst_cli.ibc_denom_hash(path) == denom_hash + assert src_cli.balance(escrow_addr, denom) == escrow_balance_bf + src_amt + if not skip_src_balance_check: + assert src_cli.balance(src_addr, denom) == src_balance_bf - src_amt - fee + return dst_denom, dst_balance + + +def should_deduct_fee(hermes: Hermes, chain_id, denom: str) -> bool: + cfg = tomlkit.parse(hermes.configpath.read_text()) + for chain in cfg["chains"]: + if chain["id"] == chain_id: + return chain.get("gas_price", {}).get("denom") == denom + return False + + +def assert_ibc_transfer( + hermes: Hermes, + src_cli, + dst_cli: CosmosCLI, + src_addr, + dst_eth_addr: str, + amt: int, + dst_denom: str, + denom=DEFAULT_DENOM, + channel="channel-0", + **kwargs, +) -> None: + src_balance_bf = src_cli.balance(src_addr, denom=denom) + rsp = src_cli.ibc_transfer( + dst_eth_addr, f"{amt}{denom}", channel, from_=src_addr, **kwargs + ) + assert rsp["code"] == 0, rsp["raw_log"] + fee = find_fee(rsp) if should_deduct_fee(hermes, src_cli.chain_id, denom) else 0 + dst_addr = dst_cli.debug_addr(dst_eth_addr, bech="acc") + dst_balance_bf = dst_cli.balance(dst_addr, dst_denom) + dst_balance = wait_for_balance_change(dst_cli, dst_addr, dst_denom, dst_balance_bf) + assert dst_balance == dst_balance_bf + amt + assert src_cli.balance(src_addr, denom=denom) == src_balance_bf - amt - fee + + +def ibc_denom_hash(path): + return hashlib.sha256(path.encode()).hexdigest().upper() + + +def find_transfer_fee(cli): + criteria = "message.action='/ibc.applications.transfer.v1.MsgTransfer'" + tx = cli.tx_search(criteria, order_by="desc", limit=1)["txs"][0] + events = parse_events_rpc(tx["events"]) + return int(parse_amount(events["tx"]["fee"])) + + +def assert_receiver_events(cli, cli2: CosmosCLI, dst_eth_addr: str): + criteria = "message.action='/ibc.applications.transfer.v1.MsgTransfer'" + events = cli.tx_search(criteria, order_by="desc", limit=1)["txs"][0] + events = parse_events_rpc(events["events"]) + assert events.get("ibc_transfer").get("receiver") == dst_eth_addr + + criteria = "message.action='/ibc.core.channel.v1.MsgRecvPacket'" + events = cli2.tx_search(criteria, order_by="desc", limit=1)["txs"][0] + events = parse_events_rpc(events["events"]) + assert events.get("fungible_token_packet").get("receiver") == dst_eth_addr diff --git a/tests/integration_tests/test_ibc.py b/tests/integration_tests/test_ibc.py index 9a88790cd..b2da88e7a 100644 --- a/tests/integration_tests/test_ibc.py +++ b/tests/integration_tests/test_ibc.py @@ -1,20 +1,25 @@ -import hashlib import json import math import pytest from eth_contract.erc20 import ERC20 -from pystarport.utils import wait_for_fn, wait_for_fn_async - -from .ibc_utils import hermes_transfer, prepare_network +from pystarport.utils import wait_for_fn_async + +from .ibc_utils import ( + assert_hermes_transfer, + assert_ibc_transfer, + assert_receiver_events, + prepare_network, + run_hermes_transfer, +) from .utils import ( ADDRS, DEFAULT_DENOM, KEYS, WETH_ADDRESS, - assert_balance, assert_create_erc20_denom, build_and_deploy_contract_async, + escrow_address, eth_to_bech32, find_duplicate, generate_isolated_address, @@ -56,28 +61,6 @@ def assert_dup_events(cli): assert not dup, f"duplicate {dup} in {event['type']}" -def wait_for_balance_change(cli, addr, denom, init_balance): - def check_balance(): - current_balance = cli.balance(addr, denom) - return current_balance if current_balance != init_balance else None - - return wait_for_fn("balance change", check_balance) - - -def assert_receiver_events(cli, cli2, target): - criteria = "message.action='/ibc.applications.transfer.v1.MsgTransfer'" - events = cli.tx_search(criteria)["txs"][0]["events"] - events = parse_events_rpc(events) - receiver = events.get("ibc_transfer").get("receiver") - assert receiver == target - - criteria = "message.action='/ibc.core.channel.v1.MsgRecvPacket'" - events = cli2.tx_search(criteria)["txs"][0]["events"] - events = parse_events_rpc(events) - receiver = events.get("fungible_token_packet").get("receiver") - assert receiver == target - - async def test_ibc_transfer(ibc): w3 = ibc.ibc1.async_w3 cli = ibc.ibc1.cosmos_cli() @@ -85,48 +68,32 @@ async def test_ibc_transfer(ibc): signer1 = ADDRS["signer1"] community = ADDRS["community"] addr_signer1 = eth_to_bech32(signer1) - addr_community = eth_to_bech32(community) - # evm-canary-net-2 signer2 -> evm-canary-net-1 signer1 100 baseunit + # evm-canary-net-2 signer2 -> evm-canary-net-1 signer1 100atest transfer_amt = 100 - src_chain = "evm-canary-net-2" - dst_chain = "evm-canary-net-1" - path, escrow_addr = hermes_transfer( - ibc, - src_chain, + dst_denom, _ = assert_hermes_transfer( + ibc.hermes, + cli2, "signer2", transfer_amt, - dst_chain, + cli, addr_signer1, ) - denom_hash = hashlib.sha256(path.encode()).hexdigest().upper() - dst_denom = f"ibc/{denom_hash}" - signer1_balance_bf = cli.balance(addr_signer1, dst_denom) - signer1_balance = wait_for_balance_change( - cli, addr_signer1, dst_denom, signer1_balance_bf - ) - assert signer1_balance == signer1_balance_bf + transfer_amt - assert cli.ibc_denom_hash(path) == denom_hash - assert_balance(cli2, ibc.ibc2.w3, escrow_addr) == transfer_amt assert_dynamic_fee(cli) assert_dup_events(cli) - # evm-canary-net-1 signer1 -> evm-canary-net-2 community eth addr with 5 baseunit + # evm-canary-net-1 signer1 -> evm-canary-net-2 community eth addr with 5atest amount = 5 - rsp = cli.ibc_transfer( + assert_ibc_transfer( + ibc.hermes, + cli, + cli2, + addr_signer1, community, - f"{amount}{DEFAULT_DENOM}", - "channel-0", - from_=addr_signer1, + amount, + dst_denom, ) - assert rsp["code"] == 0, rsp["raw_log"] - community_balance_bf = cli2.balance(addr_community, dst_denom) - community_balance = wait_for_balance_change( - cli2, addr_community, dst_denom, community_balance_bf - ) - assert community_balance == community_balance_bf + amount assert_receiver_events(cli, cli2, community) - ibc_erc20_addr = ibc_denom_address(dst_denom) assert (await ERC20.fns.decimals().call(w3, to=ibc_erc20_addr)) == 0 total = await ERC20.fns.totalSupply().call(w3, to=ibc_erc20_addr) @@ -170,32 +137,21 @@ async def test_ibc_cb(ibc): # evm-canary-net-1 signer1 -> evm-canary-net-2 signer2 50erc20_denom transfer_amt = total // 2 - src_chain = "evm-canary-net-1" - dst_chain = "evm-canary-net-2" + port = "transfer" channel = "channel-0" isolated = generate_isolated_address(channel, addr_signer2) - path, escrow_addr = hermes_transfer( - ibc, - src_chain, + dst_denom, signer2_balance = assert_hermes_transfer( + ibc.hermes, + cli, "signer1", transfer_amt, - dst_chain, + cli2, addr_signer2, denom=erc20_denom, + skip_src_balance_check=True, ) - denom_hash = hashlib.sha256(path.encode()).hexdigest().upper() - dst_denom = f"ibc/{denom_hash}" - signer2_balance_bf = cli2.balance(addr_signer2, dst_denom) - signer2_balance = wait_for_balance_change( - cli2, addr_signer2, dst_denom, signer2_balance_bf - ) - assert signer2_balance == signer2_balance_bf + transfer_amt - assert cli2.ibc_denom_hash(path) == denom_hash - signer2_balance_bf = signer2_balance - - assert cli.balance(escrow_addr, erc20_denom) == transfer_amt signer1_balance_eth = await ERC20.fns.balanceOf(signer1).call(w3, to=WETH_ADDRESS) assert signer1_balance_eth == total - transfer_amt @@ -205,19 +161,17 @@ async def test_ibc_cb(ibc): cb_balance_bf = await ERC20.fns.balanceOf(cb_contract).call(w3, to=WETH_ADDRESS) # evm-canary-net-2 signer2 -> evm-canary-net-1 signer1 50erc20_denom - src_chain = "evm-canary-net-2" - dst_chain = "evm-canary-net-1" - hermes_transfer( - ibc, - src_chain, + run_hermes_transfer( + ibc.hermes, + cli2, "signer2", transfer_amt, - dst_chain, + cli, isolated, denom=dst_denom, memo=dest_cb, ) - assert cli2.balance(addr_signer2, dst_denom) == signer2_balance_bf - transfer_amt + assert cli2.balance(addr_signer2, dst_denom) == signer2_balance - transfer_amt async def wait_for_balance_change_async(w3, addr, token_addr, init_balance): async def check_balance(): @@ -230,5 +184,6 @@ async def check_balance(): w3, cb_contract, WETH_ADDRESS, cb_balance_bf ) assert cb_balance == cb_balance_bf + transfer_amt + escrow_addr = escrow_address(port, channel) assert cli.balance(escrow_addr, erc20_denom) == 0 assert cli2.balance(addr_signer2, dst_denom) == 0 diff --git a/tests/integration_tests/utils.py b/tests/integration_tests/utils.py index 8a4df6bfc..e6eae0edf 100644 --- a/tests/integration_tests/utils.py +++ b/tests/integration_tests/utils.py @@ -17,8 +17,10 @@ import bech32 import eth_utils +import jsonmerge import requests import rlp +import web3 from dateutil.parser import isoparse from dotenv import load_dotenv from eth_account import Account @@ -37,6 +39,7 @@ from pystarport import cluster from pystarport.utils import ( wait_for_block_time, + wait_for_fn, wait_for_new_blocks, ) from web3 import AsyncWeb3 @@ -489,6 +492,51 @@ def retry_on_seq_mismatch(fn, *args, max_retries=3, **kwargs): return rsp +async def retry_on_nonce_mismatch(fn, *args, max_retries=3, **kwargs): + for attempt in range(max_retries): + try: + return await fn(*args, **kwargs) + except Exception as e: + error_msg = str(e).lower() + # Handle nonce mismatch errors + should_retry = "nonce" in error_msg and ( + "lower" in error_msg or "invalid" in error_msg + ) + # Handle "already known" errors (transaction already in mempool) + should_retry = should_retry or ("already known" in error_msg) + + if should_retry and attempt < max_retries - 1: + # Wait a bit longer for "already known" errors + wait_time = 2.0 if "already known" in error_msg else 1.0 + await asyncio.sleep(wait_time) + continue + raise e + return None + + +def call_with_retry(fn, expect_error=False, max_retries=3, retry_delay=0.1): + for attempt in range(1, max_retries + 1): + try: + fn() + if expect_error: + print(f"no error but query succeeded on attempt {attempt}") + return False + print(f"query successful on attempt {attempt}") + return True + except web3.exceptions.Web3RPCError as e: + error_str = str(e) + if "Error while dialing" in error_str or "connection refused" in error_str: + if expect_error: + return True + if attempt == max_retries: + print(f"failed after {max_retries} attempts") + return False + time.sleep(retry_delay) + else: + raise + return False + + def recover_community(cli, tmp_path): return cli.create_account( "community", @@ -559,7 +607,7 @@ def build_batch_tx(w3, cli, txs, key=KEYS["community"]): "auth_info": { "signer_infos": [], "fee": { - "amount": [{"denom": "atest", "amount": str(fee)}], + "amount": [{"denom": DEFAULT_EXTENDED_DENOM, "amount": str(fee)}], "gas_limit": str(gas_limit), "payer": "", "granter": "", @@ -577,8 +625,13 @@ def approve_proposal(n, events, event_query_tx=True, **kwargs): ) proposal_id = ev["proposal_id"] for i in range(len(n.config["validators"])): + node = n.config["validators"][i] + # skip fullnodes + if "staked" not in node: + continue + account_name = node.get("name", "validator") rsp = n.cosmos_cli(i).gov_vote( - "validator", + account_name, proposal_id, "yes", event_query_tx=event_query_tx, @@ -794,18 +847,33 @@ def address_to_bytes32(addr) -> HexBytes: return HexBytes(addr).rjust(32, b"\x00") -def edit_app_cfg(cli, i): +def assert_approval_log(receipt, owner, spender, expected): + approval_topic = HexBytes(ERC20.events.Approval.topic.hex()) + approval_logs = [ + log for log in receipt["logs"] if log["topics"][0] == approval_topic + ] + assert len(approval_logs) == 1 + approval_log = approval_logs[0] + assert approval_log["topics"][1] == address_to_bytes32(owner), "owner mismatch" + assert approval_log["topics"][2] == address_to_bytes32(spender), "spender mismatch" + return int.from_bytes(approval_log["data"], "big") == expected + + +def edit_app_cfg(cli, i, app_config={}): # Modify the json-rpc addresses to avoid conflict cluster.edit_app_cfg( cli.home(i) / "config/app.toml", cli.base_port(i), - { - "json-rpc": { - "enable": True, - "address": "127.0.0.1:{EVMRPC_PORT}", - "ws-address": "127.0.0.1:{EVMRPC_PORT_WS}", + jsonmerge.merge( + { + "json-rpc": { + "enable": True, + "address": "127.0.0.1:{EVMRPC_PORT}", + "ws-address": "127.0.0.1:{EVMRPC_PORT_WS}", + }, }, - }, + app_config, + ), ) @@ -815,6 +883,14 @@ def duration(duration_str): return sum(int(value) * mult[unit] for value, unit in parts) +def wait_for_balance_change(cli, addr, denom, init_balance): + def check_balance(): + current_balance = cli.balance(addr, denom) + return current_balance if current_balance != init_balance else None + + return wait_for_fn("balance change", check_balance) + + async def w3_wait_for_new_blocks_async(w3: AsyncWeb3, n: int, sleep=0.1): begin_height = await w3.eth.block_number target = begin_height + n @@ -824,3 +900,52 @@ async def w3_wait_for_new_blocks_async(w3: AsyncWeb3, n: int, sleep=0.1): if cur_height >= target: break await asyncio.sleep(sleep) + + +def update_node_cmd(path, cmd, i, **kwargs): + ini_path = path / cluster.SUPERVISOR_CONFIG_FILE + ini = configparser.RawConfigParser() + ini.read(ini_path) + for section in ini.sections(): + if section == f"program:{CHAIN_ID}-node{i}": + updates = {} + base_cmd = f"{cmd} start --home %(here)s/node{i}" + if kwargs: + extra_flags = " ".join( + f"--{k.replace('_', '-')}" for k in kwargs.keys() + ) + updates["command"] = f"{base_cmd} {extra_flags}" + else: + updates["command"] = base_cmd + updates["autorestart"] = "false" + ini[section].update(updates) + with ini_path.open("w") as fp: + ini.write(fp) + + +def grpc_eth_call( + port: int, + args: dict, + expect_cb, + chain_id=None, + proposer_address=None, +): + max_retry = 3 + sleep = 1 + success = False + for i in range(max_retry): + params = { + "args": base64.b64encode(json.dumps(args).encode()).decode(), + } + if chain_id is not None: + params["chain_id"] = str(chain_id) + if proposer_address is not None: + params["proposer_address"] = str(proposer_address) + rsp = requests.get( + f"http://localhost:{port}/cosmos/evm/vm/v1/eth_call", params + ).json() + success = expect_cb(rsp) + if success: + break + time.sleep(sleep) + assert success, str(rsp) From e7d133670919cc5a1c89b42e943a106279af5b70 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sat, 15 Nov 2025 09:28:54 +0800 Subject: [PATCH 21/22] fix --- flake.nix | 2 ++ tests/integration_tests/test_gas.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index fbe8666d0..da146bbed 100644 --- a/flake.nix +++ b/flake.nix @@ -47,6 +47,8 @@ pkgs.uv pkgs.git pkgs.hermes + (pkgs.lib.optional pkgs.stdenv.isLinux pkgs.stdenv.cc.cc) + pkgs.python312Packages.jsonnet ]; }; }; diff --git a/tests/integration_tests/test_gas.py b/tests/integration_tests/test_gas.py index b589bc315..206d4aa07 100644 --- a/tests/integration_tests/test_gas.py +++ b/tests/integration_tests/test_gas.py @@ -25,7 +25,7 @@ async def test_gas_call(evm): {"from": ADDRS["community"], "gasPrice": await w3.eth.gas_price} ) receipt = await w3.eth.wait_for_transaction_receipt(txhash) - assert receipt.gasUsed == 267649 + assert receipt.gasUsed == 267441 async def test_block_gas_limit(evm): From c52dfd617fe4504efc0b4857791d3b618dab6446 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Mon, 17 Nov 2025 10:34:52 +0800 Subject: [PATCH 22/22] cleanup --- .github/workflows/tests-e2e-nix.yml | 105 +++++++++++------ flake.lock | 86 +------------- flake.nix | 7 -- tests/Makefile | 18 +++ tests/integration_tests/Makefile | 5 - tests/integration_tests/ibc_utils.py | 163 +++++++++++++++++++++++++++ tests/integration_tests/test_ibc.py | 87 +++----------- 7 files changed, 272 insertions(+), 199 deletions(-) create mode 100644 tests/Makefile delete mode 100644 tests/integration_tests/Makefile diff --git a/.github/workflows/tests-e2e-nix.yml b/.github/workflows/tests-e2e-nix.yml index 9b62f7ece..f8a815bbf 100644 --- a/.github/workflows/tests-e2e-nix.yml +++ b/.github/workflows/tests-e2e-nix.yml @@ -1,59 +1,100 @@ name: E2E Nix Tests on: - push: - branches: - - main - - release/** + push: + branches: [ main, release/** ] pull_request: - branches: - - main - - release/** + branches: [ main, release/** ] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: - integration_tests: + build-env: runs-on: ubuntu-latest - timeout-minutes: 240 - strategy: - matrix: - tests: [all] - env: - TESTS_TO_RUN: ${{ matrix.tests }} + outputs: + run_tests: ${{ steps.set-run-tests.outputs.run_tests }} steps: - - name: Create more disk space - run: sudo rm -rf /usr/share/dotnet && sudo rm -rf /opt/ghc && sudo rm -rf "/usr/local/share/boost" && sudo rm -rf "$AGENT_TOOLSDIRECTORY" - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 1 + - name: Skip marker (commit message) + run: | + msg="$(git log -1 --pretty=%B)" + if echo "$msg" | grep -qi '\[skip e2e\]'; then + echo "Skipping E2E by marker." + echo "run_tests=false" >> "$GITHUB_OUTPUT" + exit 0 + fi - id: changed-files - uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5 + uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c with: files: | - docs - *.md + docs/** **/*.md - - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 + - id: set-run-tests + run: | + if [ "${{ steps.changed-files.outputs.only_changed }}" = "true" ]; then + echo "Docs-only change detected. Skipping tests." + echo "run_tests=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "run_tests=true" >> "$GITHUB_OUTPUT" + - name: Free disk space + if: steps.set-run-tests.outputs.run_tests == 'true' + run: sudo rm -rf /usr/share/dotnet /opt/ghc "/usr/local/share/boost" "$AGENT_TOOLSDIRECTORY" || true + - name: Install Nix + if: steps.set-run-tests.outputs.run_tests == 'true' + uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b + with: + nix_path: nixpkgs=channel:nixos-25.05 + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + sandbox = false + - name: Enable Magic Nix Cache + if: steps.set-run-tests.outputs.run_tests == 'true' + uses: DeterminateSystems/magic-nix-cache-action@main + - name: Pre-build dependencies (warm cache) + if: steps.set-run-tests.outputs.run_tests == 'true' + run: | + nix build .#evmd .#hermes || true + integration_tests: + needs: build-env + if: needs.build-env.outputs.run_tests == 'true' + runs-on: ubuntu-latest + timeout-minutes: 240 + strategy: + fail-fast: true + matrix: + group: [all] + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 1 + - name: Install Nix + uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b with: nix_path: nixpkgs=channel:nixos-25.05 extra_nix_config: | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} sandbox = false - if: steps.changed-files.outputs.only_changed == 'false' - - uses: DeterminateSystems/magic-nix-cache-action@main - if: steps.changed-files.outputs.only_changed == 'false' - - name: Run integration tests - if: steps.changed-files.outputs.only_changed == 'false' - run: make test-e2e-nix - - name: 'Tar debug files' + - name: Enable Magic Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@main + - name: Run test group via Makefile + env: + TESTS_TO_RUN: ${{ matrix.group }} + run: make test-e2e-nix TESTS_TO_RUN="${TESTS_TO_RUN}" + - name: Collect debug artifacts if: failure() - run: tar cfz debug_files.tar.gz -C "${TMPDIR-/tmp}/pytest-of-runner" . - - uses: actions/upload-artifact@v4 + run: tar cfz debug_${{ matrix.group }}.tar.gz -C "${TMPDIR-/tmp}/pytest-of-runner" . || true + - name: Upload debug artifacts if: failure() + uses: actions/upload-artifact@v4 with: - name: debug-files-${{ matrix.tests }} - path: debug_files.tar.gz + name: debug-${{ matrix.group }} + path: debug_${{ matrix.group }}.tar.gz if-no-files-found: ignore diff --git a/flake.lock b/flake.lock index ad54088ff..9bafe0ed0 100644 --- a/flake.lock +++ b/flake.lock @@ -35,27 +35,6 @@ "type": "github" } }, - "nix-github-actions": { - "inputs": { - "nixpkgs": [ - "poetry2nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1729742964, - "narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=", - "owner": "nix-community", - "repo": "nix-github-actions", - "rev": "e04df33f62cdcf93d73e9a04142464753a16db67", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nix-github-actions", - "type": "github" - } - }, "nixpkgs": { "locked": { "lastModified": 1763159261, @@ -72,38 +51,11 @@ "type": "github" } }, - "poetry2nix": { - "inputs": { - "flake-utils": [ - "flake-utils" - ], - "nix-github-actions": "nix-github-actions", - "nixpkgs": [ - "nixpkgs" - ], - "systems": "systems_2", - "treefmt-nix": "treefmt-nix" - }, - "locked": { - "lastModified": 1743690424, - "narHash": "sha256-cX98bUuKuihOaRp8dNV1Mq7u6/CQZWTPth2IJPATBXc=", - "owner": "nix-community", - "repo": "poetry2nix", - "rev": "ce2369db77f45688172384bbeb962bc6c2ea6f94", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "poetry2nix", - "type": "github" - } - }, "root": { "inputs": { "flake-utils": "flake-utils", "hermes": "hermes", - "nixpkgs": "nixpkgs", - "poetry2nix": "poetry2nix" + "nixpkgs": "nixpkgs" } }, "systems": { @@ -120,42 +72,6 @@ "repo": "default", "type": "github" } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "treefmt-nix": { - "inputs": { - "nixpkgs": [ - "poetry2nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1730120726, - "narHash": "sha256-LqHYIxMrl/1p3/kvm2ir925tZ8DkI0KA10djk8wecSk=", - "owner": "numtide", - "repo": "treefmt-nix", - "rev": "9ef337e492a5555d8e17a51c911ff1f02635be15", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "treefmt-nix", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index da146bbed..24c3eb812 100644 --- a/flake.nix +++ b/flake.nix @@ -2,11 +2,6 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/release-25.05"; flake-utils.url = "github:numtide/flake-utils"; - poetry2nix = { - url = "github:nix-community/poetry2nix"; - inputs.nixpkgs.follows = "nixpkgs"; - inputs.flake-utils.follows = "flake-utils"; - }; hermes = { url = "github:mmsqe/ibc-rs/ae80ab348952840696e6c9a0c7096d2de11ea579"; flake = false; @@ -18,7 +13,6 @@ self, nixpkgs, flake-utils, - poetry2nix, hermes, }: let @@ -56,7 +50,6 @@ )) // { overlays.default = [ - poetry2nix.overlays.default (final: super: { evmd = final.callPackage ./. { inherit rev; }; hermes = final.callPackage ./tests/nix/hermes.nix { src = hermes; }; diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 000000000..84ec3902c --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,18 @@ +#!/usr/bin/make -f + +TESTS_TO_RUN ?= all + +NIX_DEV_CMD = nix develop --accept-flake-config -c + +test-e2e-nix: + @echo "TESTS_TO_RUN=$(TESTS_TO_RUN)" + @bash scripts/restore_envs.sh + @CHAIN_CONFIG=$(CHAIN_CONFIG) TESTS_TO_RUN=$(TESTS_TO_RUN) bash scripts/run-integration-tests.sh + +dev: + @$(NIX_DEV_CMD) bash + +lint-py: + @cd integration_tests && uv run flake8 --show-source --count --statistics --format="::error file=%(path)s,line=%(row)d,col=%(col)d::%(path)s:%(row)d:%(col)d: %(code)s %(text)s" + +.PHONY: test-e2e-nix dev lint-py diff --git a/tests/integration_tests/Makefile b/tests/integration_tests/Makefile deleted file mode 100644 index a46672440..000000000 --- a/tests/integration_tests/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/make -f - -lint-py: - flake8 --show-source --count --statistics \ - --format="::error file=%(path)s,line=%(row)d,col=%(col)d::%(path)s:%(row)d:%(col)d: %(code)s %(text)s" \ diff --git a/tests/integration_tests/ibc_utils.py b/tests/integration_tests/ibc_utils.py index e55a74c84..b0f81b94b 100644 --- a/tests/integration_tests/ibc_utils.py +++ b/tests/integration_tests/ibc_utils.py @@ -1,5 +1,6 @@ import hashlib import json +import math import os import subprocess import tempfile @@ -8,6 +9,7 @@ from typing import NamedTuple import tomlkit +from eth_contract.erc20 import ERC20 from pystarport import cluster, ports from pystarport.utils import parse_amount, wait_for_new_blocks, wait_for_port @@ -15,11 +17,14 @@ from .network import Evm, Hermes, setup_custom_evm from .utils import ( ADDRESS_PREFIX, + ADDRS, CHAIN_ID, CMD, DEFAULT_DENOM, escrow_address, + find_duplicate, find_fee, + ibc_denom_address, parse_events_rpc, wait_for_balance_change, ) @@ -250,3 +255,161 @@ def assert_receiver_events(cli, cli2: CosmosCLI, dst_eth_addr: str): events = cli2.tx_search(criteria, order_by="desc", limit=1)["txs"][0] events = parse_events_rpc(events["events"]) assert events.get("fungible_token_packet").get("receiver") == dst_eth_addr + + +def assert_dynamic_fee(cli): + # assert that the relayer transactions do enables the dynamic fee extension option. + criteria = "message.action='/ibc.core.channel.v1.MsgChannelOpenInit'" + tx = cli.tx_search(criteria)["txs"][0] + events = parse_events_rpc(tx["events"]) + fee = int(events["tx"]["fee"].removesuffix(DEFAULT_DENOM)) + gas = int(tx["gas_wanted"]) + # the effective fee is decided by the max_priority_fee (base fee is zero) + # rather than the normal gas price + cosmos_evm_dynamic_fee = 10000000000000000 / 10**18 + assert fee == math.ceil(gas * cosmos_evm_dynamic_fee) + + +def assert_dup_events(cli): + # check duplicate OnRecvPacket events + criteria = "message.action='/ibc.core.channel.v1.MsgRecvPacket'" + events = cli.tx_search(criteria)["txs"][0]["events"] + for event in events: + dup = find_duplicate(event["attributes"]) + assert not dup, f"duplicate {dup} in {event['type']}" + + +async def assert_ibc_transfer_flow( + ibc: IBCNetwork, + denom=DEFAULT_DENOM, + chain2_denom="atest", + chain2_prefix="cosmos", + return_ratio=1, +) -> str: + w3 = ibc.ibc1.async_w3 + cli1 = ibc.ibc1.cosmos_cli() + cli2 = ibc.ibc2.cosmos_cli() + chain2_gas_prices = f"10000000000{chain2_denom}" + amt = 100 + amt2 = 2 + amt3 = 3 + amt4 = 4 + port = "transfer" + channel = "channel-0" + eth_community = ADDRS["community"] + for c in [cli1, cli2]: + add_key(ibc.hermes, c.chain_id, "COMMUNITY_MNEMONIC", "community") + + print(f"chain2 signer2 -> chain1 signer1 {amt}{chain2_denom}") + dst_denom, _ = assert_hermes_transfer( + ibc.hermes, + cli2, + "signer2", + amt, + cli1, + cli1.address("signer1"), + denom=chain2_denom, + prefix=chain2_prefix, + ) + assert_dynamic_fee(cli1) + assert_dup_events(cli1) + ibc_erc20_addr = ibc_denom_address(dst_denom) + assert (await ERC20.fns.decimals().call(w3, to=ibc_erc20_addr)) == 0 + assert await ERC20.fns.totalSupply().call(w3, to=ibc_erc20_addr) == amt + + print(f"chain1 signer1 -> chain2 signer2 {amt2}{denom}") + dst_denom2, _ = assert_hermes_transfer( + ibc.hermes, + cli1, + "signer1", + amt2, + cli2, + cli2.address("signer2"), + denom=denom, + ) + + print(f"chain1 community -> chain2 eth_community {amt3}{denom}") + denom_hash = ibc_denom_hash(f"{port}/{channel}/{denom}") + dst_denom3 = f"ibc/{denom_hash}" + assert_ibc_transfer( + ibc.hermes, + cli1, + cli2, + "community", + eth_community, + amt3, + dst_denom3, + denom=denom, + ) + assert_receiver_events(cli1, cli2, eth_community) + + print(f"chain2 community -> chain1 eth_community {amt4}{chain2_denom}") + denom_hash = ibc_denom_hash(f"{port}/{channel}/{chain2_denom}") + dst_denom4 = f"ibc/{denom_hash}" + assert_ibc_transfer( + ibc.hermes, + cli2, + cli1, + "community", + eth_community, + amt4, + dst_denom4, + denom=chain2_denom, + gas_prices=chain2_gas_prices, + ) + assert_receiver_events(cli2, cli1, eth_community) + + amt = int(amt * return_ratio) + print(f"chain1 signer1 -> chain2 signer2 back {amt}{dst_denom}") + assert_hermes_transfer( + ibc.hermes, + cli1, + "signer1", + amt, + cli2, + cli2.address("signer2"), + denom=dst_denom, + ) + + amt2 = int(amt2 * return_ratio) + print(f"chain2 signer2 -> chain1 signer1 back {amt2}{dst_denom2}") + assert_hermes_transfer( + ibc.hermes, + cli2, + "signer2", + amt2, + cli1, + cli1.address("signer1"), + denom=dst_denom2, + prefix=chain2_prefix, + ) + + amt3 = int(amt3 * return_ratio) + print(f"chain2 community -> chain1 eth_community back {amt3}{dst_denom3}") + assert_ibc_transfer( + ibc.hermes, + cli2, + cli1, + "community", + eth_community, + amt3, + denom, + denom=dst_denom3, + gas_prices=chain2_gas_prices, + ) + assert_receiver_events(cli2, cli1, eth_community) + + amt4 = int(amt4 * return_ratio) + print(f"chain1 community -> chain2 eth_community back {amt4}{dst_denom4}") + assert_ibc_transfer( + ibc.hermes, + cli1, + cli2, + "community", + eth_community, + amt4, + chain2_denom, + denom=dst_denom4, + ) + assert_receiver_events(cli1, cli2, eth_community) + return ibc_erc20_addr diff --git a/tests/integration_tests/test_ibc.py b/tests/integration_tests/test_ibc.py index b2da88e7a..0860ad456 100644 --- a/tests/integration_tests/test_ibc.py +++ b/tests/integration_tests/test_ibc.py @@ -1,18 +1,18 @@ import json -import math import pytest from eth_contract.erc20 import ERC20 from pystarport.utils import wait_for_fn_async +from web3 import AsyncWeb3 from .ibc_utils import ( assert_hermes_transfer, - assert_ibc_transfer, - assert_receiver_events, + assert_ibc_transfer_flow, prepare_network, run_hermes_transfer, ) from .utils import ( + ADDRESS_PREFIX, ADDRS, DEFAULT_DENOM, KEYS, @@ -21,10 +21,7 @@ build_and_deploy_contract_async, escrow_address, eth_to_bech32, - find_duplicate, generate_isolated_address, - ibc_denom_address, - parse_events_rpc, ) pytestmark = pytest.mark.asyncio @@ -39,65 +36,23 @@ def ibc(request, tmp_path_factory): yield from prepare_network(path, name, chain) -def assert_dynamic_fee(cli): - # assert that the relayer transactions do enables the dynamic fee extension option. - criteria = "message.action='/ibc.core.channel.v1.MsgChannelOpenInit'" - tx = cli.tx_search(criteria)["txs"][0] - events = parse_events_rpc(tx["events"]) - fee = int(events["tx"]["fee"].removesuffix(DEFAULT_DENOM)) - gas = int(tx["gas_wanted"]) - # the effective fee is decided by the max_priority_fee (base fee is zero) - # rather than the normal gas price - cosmos_evm_dynamic_fee = 10000000000000000 / 10**18 - assert fee == math.ceil(gas * cosmos_evm_dynamic_fee) +async def wait_for_balance_change_async( + w3: AsyncWeb3, addr, token_addr: str, init_balance: int +): + async def check_balance(): + current_balance = await ERC20.fns.balanceOf(addr).call(w3, to=token_addr) + return current_balance if current_balance != init_balance else None - -def assert_dup_events(cli): - # check duplicate OnRecvPacket events - criteria = "message.action='/ibc.core.channel.v1.MsgRecvPacket'" - events = cli.tx_search(criteria)["txs"][0]["events"] - for event in events: - dup = find_duplicate(event["attributes"]) - assert not dup, f"duplicate {dup} in {event['type']}" + return await wait_for_fn_async("balance change", check_balance) async def test_ibc_transfer(ibc): - w3 = ibc.ibc1.async_w3 - cli = ibc.ibc1.cosmos_cli() - cli2 = ibc.ibc2.cosmos_cli() - signer1 = ADDRS["signer1"] - community = ADDRS["community"] - addr_signer1 = eth_to_bech32(signer1) - - # evm-canary-net-2 signer2 -> evm-canary-net-1 signer1 100atest - transfer_amt = 100 - dst_denom, _ = assert_hermes_transfer( - ibc.hermes, - cli2, - "signer2", - transfer_amt, - cli, - addr_signer1, + await assert_ibc_transfer_flow( + ibc, + chain2_denom=DEFAULT_DENOM, + chain2_prefix=ADDRESS_PREFIX, + return_ratio=0.5, ) - assert_dynamic_fee(cli) - assert_dup_events(cli) - - # evm-canary-net-1 signer1 -> evm-canary-net-2 community eth addr with 5atest - amount = 5 - assert_ibc_transfer( - ibc.hermes, - cli, - cli2, - addr_signer1, - community, - amount, - dst_denom, - ) - assert_receiver_events(cli, cli2, community) - ibc_erc20_addr = ibc_denom_address(dst_denom) - assert (await ERC20.fns.decimals().call(w3, to=ibc_erc20_addr)) == 0 - total = await ERC20.fns.totalSupply().call(w3, to=ibc_erc20_addr) - assert total == transfer_amt async def prepare_dest_callback(w3, sender, amt): @@ -135,8 +90,8 @@ async def test_ibc_cb(ibc): res = cli.query_erc20_token_pair(erc20_denom) assert res["erc20_address"] == WETH_ADDRESS, res - # evm-canary-net-1 signer1 -> evm-canary-net-2 signer2 50erc20_denom transfer_amt = total // 2 + print(f"chain1 signer1 -> chain2 signer2 {transfer_amt}{erc20_denom}") port = "transfer" channel = "channel-0" isolated = generate_isolated_address(channel, addr_signer2) @@ -160,7 +115,7 @@ async def test_ibc_cb(ibc): cb_contract, dest_cb = await prepare_dest_callback(w3, signer1, transfer_amt) cb_balance_bf = await ERC20.fns.balanceOf(cb_contract).call(w3, to=WETH_ADDRESS) - # evm-canary-net-2 signer2 -> evm-canary-net-1 signer1 50erc20_denom + print(f"chain2 signer2 -> chain1 signer1 {transfer_amt}{dst_denom}") run_hermes_transfer( ibc.hermes, cli2, @@ -172,14 +127,6 @@ async def test_ibc_cb(ibc): memo=dest_cb, ) assert cli2.balance(addr_signer2, dst_denom) == signer2_balance - transfer_amt - - async def wait_for_balance_change_async(w3, addr, token_addr, init_balance): - async def check_balance(): - current_balance = await ERC20.fns.balanceOf(addr).call(w3, to=token_addr) - return current_balance if current_balance != init_balance else None - - return await wait_for_fn_async("balance change", check_balance) - cb_balance = await wait_for_balance_change_async( w3, cb_contract, WETH_ADDRESS, cb_balance_bf )