From 1318e0d7193acf12baa31fe03b39c285bdd48945 Mon Sep 17 00:00:00 2001 From: Fernando Campos Date: Mon, 17 Feb 2025 19:57:58 -0300 Subject: [PATCH 1/2] Adds Allora Network price inference to the CDP AgentKit. --- .../coinbase_agentkit/__init__.py | 2 + .../action_providers/__init__.py | 3 + .../allora/allora_action_provider.py | 172 ++++++++++++++ .../action_providers/allora/schemas.py | 47 ++++ python/coinbase-agentkit/poetry.lock | 158 ++++++++++++- python/coinbase-agentkit/pyproject.toml | 2 + .../tests/action_providers/allora/__init__.py | 0 .../allora/test_allora_action_provider.py | 212 ++++++++++++++++++ 8 files changed, 590 insertions(+), 6 deletions(-) create mode 100644 python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/allora_action_provider.py create mode 100644 python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/schemas.py create mode 100644 python/coinbase-agentkit/tests/action_providers/allora/__init__.py create mode 100644 python/coinbase-agentkit/tests/action_providers/allora/test_allora_action_provider.py diff --git a/python/coinbase-agentkit/coinbase_agentkit/__init__.py b/python/coinbase-agentkit/coinbase_agentkit/__init__.py index 61e7c455f..2e1fe5daf 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/__init__.py +++ b/python/coinbase-agentkit/coinbase_agentkit/__init__.py @@ -17,6 +17,7 @@ wallet_action_provider, weth_action_provider, wow_action_provider, + allora_action_provider, ) from .agentkit import AgentKit, AgentKitConfig from .wallet_providers import ( @@ -56,5 +57,6 @@ "wallet_action_provider", "weth_action_provider", "wow_action_provider", + "allora_action_provider", "__version__", ] diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py b/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py index a9205db97..40e711803 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py @@ -20,6 +20,7 @@ from .wallet.wallet_action_provider import WalletActionProvider, wallet_action_provider from .weth.weth_action_provider import WethActionProvider, weth_action_provider from .wow.wow_action_provider import WowActionProvider, wow_action_provider +from .allora.allora_action_provider import AlloraActionProvider, allora_action_provider __all__ = [ "Action", @@ -49,4 +50,6 @@ "weth_action_provider", "WowActionProvider", "wow_action_provider", + "AlloraActionProvider", + "allora_action_provider", ] diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/allora_action_provider.py b/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/allora_action_provider.py new file mode 100644 index 000000000..4cbf3d1fc --- /dev/null +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/allora_action_provider.py @@ -0,0 +1,172 @@ +"""Allora Network action provider.""" + +import json +from typing import Any, Optional + +from allora_sdk.v2.api_client import ( + AlloraAPIClient, + ChainSlug, + PriceInferenceToken, + PriceInferenceTimeframe, +) + +from ..action_decorator import create_action +from ..action_provider import ActionProvider +from .schemas import GetAllTopicsInput, GetInferenceByTopicIdInput, GetPriceInferenceInput + + +class AlloraActionProvider(ActionProvider): + """Action provider for interacting with Allora Network.""" + + def __init__( + self, + api_key: Optional[str] = None, + chain_slug: Optional[ChainSlug] = None, + ): + """Initialize the Allora action provider. + + Args: + api_key: API key for Allora Network + chain_slug: Chain slug to use (testnet or mainnet) + + """ + super().__init__("allora", []) + self.client = AlloraAPIClient( + api_key=api_key or "UP-4151d0cc489a44a7aa5cd7ef", + chain_slug=chain_slug or ChainSlug.TESTNET, + ) + + @create_action( + name="get_all_topics", + description=""" +This tool will get all available inference topics from Allora Network. + +A successful response will return a message with a list of available topics from Allora Network in JSON format. Example: + [ + { + "topic_id": 1, + "topic_name": "Bitcoin 8h", + "description": "Bitcoin price prediction for the next 8 hours", + "epoch_length": 100, + "ground_truth_lag": 10, + "loss_method": "method1", + "worker_submission_window": 50, + "worker_count": 5, + "reputer_count": 3, + "total_staked_allo": 1000, + "total_emissions_allo": 500, + "is_active": true, + "updated_at": "2023-01-01T00:00:00Z" + } + ] +The description field is a short description of the topic, and the topic_name is the name of the topic. These fields can be used to understand the topic and its purpose. +The topic_id field is the unique identifier for the topic, and can be used to get the inference data for the topic using the get_inference_by_topic_id action. +The is_active field indicates if the topic is currently active and accepting submissions. +The updated_at field is the timestamp of the last update for the topic. + +A failure response will return an error message with details. + """, + schema=GetAllTopicsInput, + ) + async def get_all_topics(self, args: dict[str, Any]) -> str: + """Get all available topics from Allora Network.""" + try: + topics = await self.client.get_all_topics() + topics_json = json.dumps(topics) + return f"The available topics at Allora Network are:\n {topics_json}" + except Exception as e: + return f"Error getting all topics: {e}" + + @create_action( + name="get_inference_by_topic_id", + description=""" +This tool will get inference for a specific topic from Allora Network. +It requires a topic ID as input, which can be obtained from the get_all_topics action. + +A successful response will return a message with the inference data in JSON format. Example: + { + "network_inference": "0.5", + "network_inference_normalized": "0.5", + "confidence_interval_percentiles": ["0.1", "0.5", "0.9"], + "confidence_interval_percentiles_normalized": ["0.1", "0.5", "0.9"], + "confidence_interval_values": ["0.1", "0.5", "0.9"], + "confidence_interval_values_normalized": ["0.1", "0.5", "0.9"], + "topic_id": "1", + "timestamp": 1718198400, + "extra_data": "extra_data" + } +The network_inference field is the inference for the topic. +The network_inference_normalized field is the normalized inference for the topic. + +A failure response will return an error message with details. + """, + schema=GetInferenceByTopicIdInput, + ) + async def get_inference_by_topic_id(self, args: dict[str, Any]) -> str: + """Get inference data for a specific topic.""" + try: + inference = await self.client.get_inference_by_topic_id(args["topic_id"]) + inference_json = json.dumps(inference.inference_data) + return f"The inference for topic {args['topic_id']} is:\n {inference_json}" + except Exception as e: + return f"Error getting inference for topic {args['topic_id']}: {e}" + + @create_action( + name="get_price_inference", + description=""" +This tool will get price inference for a specific token and timeframe from Allora Network. +It requires an asset symbol (e.g., 'BTC', 'ETH') and a timeframe (e.g., '5m', '8h') as input. + +Supported timeframes: +- Minutes: 5m +- Hours: 8h + +A successful response will return a message with the price inference. Example: + The price inference for BTC (8h) is: + { + "price": "100000", + "timestamp": 1718198400, + "asset": "BTC", + "timeframe": "8h" + } + +A failure response will return an error message with details. + """, + schema=GetPriceInferenceInput, + ) + async def get_price_inference(self, args: dict[str, Any]) -> str: + """Get price inference for a token/timeframe pair.""" + try: + inference = await self.client.get_price_inference( + args["asset"], + args["timeframe"], + ) + response = { + "price": inference.inference_data["network_inference_normalized"], + "timestamp": inference.inference_data["timestamp"], + "asset": args["asset"].value, # Convert enum to string for JSON + "timeframe": args["timeframe"].value, # Convert enum to string for JSON + } + inference_json = json.dumps(response) + return f"The price inference for {args['asset'].value} ({args['timeframe'].value}) is:\n{inference_json}" + except Exception as e: + return f"Error getting price inference for {args['asset'].value} ({args['timeframe'].value}): {e}" + + def supports_network(self) -> bool: + """Check if the provider supports a given network. + + Returns: + bool: Always returns True as Allora service is network-agnostic + + """ + return True # Allora service is network-agnostic + + +def allora_action_provider() -> AlloraActionProvider: + """Create a new Allora action provider. + + Returns: + AlloraActionProvider: A new Allora action provider instance. + + """ + return AlloraActionProvider() diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/schemas.py b/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/schemas.py new file mode 100644 index 000000000..3e9469deb --- /dev/null +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/schemas.py @@ -0,0 +1,47 @@ +"""Schemas for Allora action provider.""" + +from typing import Any + +from pydantic import BaseModel, Field, field_validator +from allora_sdk.v2.api_client import PriceInferenceToken, PriceInferenceTimeframe + + +class GetAllTopicsInput(BaseModel): + """Input schema for getting all topics from Allora Network.""" + + pass + + +class GetInferenceByTopicIdInput(BaseModel): + """Input schema for getting inference data by topic ID.""" + + topic_id: int = Field( + ..., + description="The ID of the topic to get inference data for", + gt=0, # Must be greater than 0 + ) + + @field_validator("topic_id", mode="before") + @classmethod + def validate_topic_id(cls, v: Any) -> int: + """Validate topic_id is a positive integer.""" + if not isinstance(v, int) or isinstance(v, bool): + raise ValueError("topic_id must be an integer") + if v <= 0: + raise ValueError("topic_id must be greater than 0") + return v + + +class GetPriceInferenceInput(BaseModel): + """Input schema for getting price inference for a token/timeframe pair.""" + + asset: str = Field( + ..., + description="The token to get price inference for (e.g., BTC, ETH). Common values include BTC and ETH, but others may be supported.", + min_length=1, + ) + timeframe: str = Field( + ..., + description="The timeframe for the prediction (e.g., '5m', '8h'). Common values include 5m and 8h, but others may be supported.", + min_length=1, + ) diff --git a/python/coinbase-agentkit/poetry.lock b/python/coinbase-agentkit/poetry.lock index 83cd7aaae..b34ae72dc 100644 --- a/python/coinbase-agentkit/poetry.lock +++ b/python/coinbase-agentkit/poetry.lock @@ -139,6 +139,49 @@ files = [ {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"}, ] +[[package]] +name = "allora-sdk" +version = "0.2.0" +description = "Allora Network SDK" +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [] +develop = false + +[package.dependencies] +aiohttp = "*" +annotated-types = "0.7.0" +cachetools = "5.5.0" +certifi = "2024.12.14" +chardet = "5.2.0" +charset-normalizer = "3.4.1" +colorama = "0.4.6" +distlib = "0.3.9" +filelock = "3.16.1" +idna = "3.10" +packaging = "24.2" +platformdirs = "4.3.6" +pluggy = "1.5.0" +pydantic = "2.10.4" +pydantic_core = "2.27.2" +pyproject-api = "1.8.0" +requests = "2.32.3" +tox = "4.23.2" +typing_extensions = "4.12.2" +urllib3 = "2.3.0" +virtualenv = "20.28.1" + +[package.extras] +dev = ["fastapi", "pytest", "pytest-asyncio", "starlette", "tox"] + +[package.source] +type = "git" +url = "https://github.com/allora-network/allora-sdk-py.git" +reference = "master" +resolved_reference = "ac4ecaa5f978fd27bd5ab0db0bdb38ef7235b157" + [[package]] name = "annotated-types" version = "0.7.0" @@ -511,13 +554,13 @@ web3 = ">=7.6.0,<8.0.0" [[package]] name = "certifi" -version = "2025.1.31" +version = "2024.12.14" 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"}, + {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, + {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] [[package]] @@ -599,6 +642,19 @@ files = [ [package.dependencies] pycparser = "*" +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = false +python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + [[package]] name = "charset-normalizer" version = "3.4.1" @@ -1154,6 +1210,19 @@ toolz = ">=0.8.0" [package.extras] cython = ["cython"] +[[package]] +name = "distlib" +version = "0.3.9" +description = "Distribution utilities" +optional = false +python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, + {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, +] + [[package]] name = "docstring-to-markdown" version = "0.15" @@ -1394,6 +1463,24 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "filelock" +version = "3.16.1" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +typing = ["typing-extensions (>=4.12.2)"] + [[package]] name = "frozenlist" version = "1.5.0" @@ -1983,6 +2070,24 @@ files = [ qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] testing = ["docopt", "pytest"] +[[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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +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" @@ -2301,13 +2406,13 @@ files = [ [[package]] name = "pydantic" -version = "2.10.6" +version = "2.10.4" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, - {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, + {file = "pydantic-2.10.4-py3-none-any.whl", hash = "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d"}, + {file = "pydantic-2.10.4.tar.gz", hash = "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06"}, ] [package.dependencies] @@ -2506,6 +2611,27 @@ cffi = ">=1.4.1" docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] +[[package]] +name = "pyproject-api" +version = "1.8.0" +description = "API to interact with the python pyproject.toml based projects" +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "pyproject_api-1.8.0-py3-none-any.whl", hash = "sha256:3d7d347a047afe796fd5d1885b1e391ba29be7169bd2f102fcd378f04273d228"}, + {file = "pyproject_api-1.8.0.tar.gz", hash = "sha256:77b8049f2feb5d33eefcc21b57f1e279636277a8ac8ad6b5871037b243778496"}, +] + +[package.dependencies] +packaging = ">=24.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2024.8.6)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "pytest (>=8.3.3)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "setuptools (>=75.1)"] + [[package]] name = "pytest" version = "8.3.5" @@ -2528,6 +2654,26 @@ tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +[[package]] +name = "pytest-asyncio" +version = "0.23.8" +description = "Pytest support for asyncio" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}, + {file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}, +] + +[package.dependencies] +pytest = ">=7.0.0,<9" + +[package.extras] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] + [[package]] name = "pytest-cov" version = "6.0.0" diff --git a/python/coinbase-agentkit/pyproject.toml b/python/coinbase-agentkit/pyproject.toml index 112ff5613..868be6e27 100644 --- a/python/coinbase-agentkit/pyproject.toml +++ b/python/coinbase-agentkit/pyproject.toml @@ -17,6 +17,7 @@ pydantic = "^2.0" web3 = "^7.6.0" python-dotenv = "^1.0.1" requests = "^2.31.0" +allora-sdk = "^0.2.0" [tool.poetry.scripts] generate-action-provider = "scripts.generate_action_provider.main:main" @@ -26,6 +27,7 @@ ruff = "^0.7.1" mypy = "^1.13.0" pytest = "^8.3.3" pytest-cov = "^6.0.0" +pytest-asyncio = "^0.23.5" sphinx = "^8.0.2" sphinx-autobuild = "^2024.9.19" sphinxcontrib-napoleon = "^0.7" diff --git a/python/coinbase-agentkit/tests/action_providers/allora/__init__.py b/python/coinbase-agentkit/tests/action_providers/allora/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/python/coinbase-agentkit/tests/action_providers/allora/test_allora_action_provider.py b/python/coinbase-agentkit/tests/action_providers/allora/test_allora_action_provider.py new file mode 100644 index 000000000..d392ebaa3 --- /dev/null +++ b/python/coinbase-agentkit/tests/action_providers/allora/test_allora_action_provider.py @@ -0,0 +1,212 @@ +"""Tests for Allora action provider.""" + +import json +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest +from allora_sdk.v2.api_client import ( + AlloraAPIClient, + ChainSlug, + PriceInferenceToken, + PriceInferenceTimeframe, +) + +from coinbase_agentkit.action_providers.allora.allora_action_provider import AlloraActionProvider +from coinbase_agentkit.action_providers.allora.schemas import ( + GetAllTopicsInput, + GetInferenceByTopicIdInput, + GetPriceInferenceInput, +) + + +@pytest.fixture +def mock_client(): + """Create a mock Allora API client.""" + with patch("allora_sdk.v2.api_client.AlloraAPIClient") as mock: + yield mock + + +@pytest.fixture +def provider(mock_client): + """Create an Allora action provider with a mock client.""" + provider = AlloraActionProvider(api_key="test-api-key", chain_slug=ChainSlug.TESTNET) + provider.client = mock_client.return_value + return provider + + +def test_get_all_topics_input_schema(): + """Test get all topics input schema.""" + # Empty input is valid for this schema + parsed_input = GetAllTopicsInput() + assert isinstance(parsed_input, GetAllTopicsInput) + + +def test_get_inference_by_topic_id_input_schema(): + """Test get inference by topic ID input schema.""" + # Test valid inputs + valid_inputs = [ + {"topic_id": 1}, + {"topic_id": 100}, + {"topic_id": 999999}, + ] + for input_data in valid_inputs: + parsed_input = GetInferenceByTopicIdInput(**input_data) + assert parsed_input.topic_id == input_data["topic_id"] + + # Test invalid topic IDs + invalid_topic_ids = [ + 0, # Zero is not allowed + -1, # Negative numbers not allowed + "1", # String not allowed + 1.5, # Float not allowed + ] + for topic_id in invalid_topic_ids: + with pytest.raises(ValueError) as exc_info: + GetInferenceByTopicIdInput(topic_id=topic_id) + error_msg = str(exc_info.value) + if isinstance(topic_id, (int, float)) and topic_id <= 0: + assert "greater than 0" in error_msg + else: + assert "must be an integer" in error_msg + + +def test_get_price_inference_input_schema(): + """Test get price inference input schema.""" + # Test valid inputs + valid_inputs = [ + {"asset": "BTC", "timeframe": "5m"}, + {"asset": "ETH", "timeframe": "8h"}, + # Test that other values are also accepted + {"asset": "SOL", "timeframe": "1h"}, + {"asset": "DOGE", "timeframe": "1d"}, + ] + for input_data in valid_inputs: + parsed_input = GetPriceInferenceInput(**input_data) + assert parsed_input.asset == input_data["asset"] + assert parsed_input.timeframe == input_data["timeframe"] + + # Test that empty strings are not allowed (Pydantic's built-in validation) + with pytest.raises(ValueError): + GetPriceInferenceInput(asset="", timeframe="5m") + with pytest.raises(ValueError): + GetPriceInferenceInput(asset="BTC", timeframe="") + + +@pytest.mark.asyncio +async def test_get_all_topics_success(provider, mock_client): + """Test successful get all topics.""" + mock_topics = [ + { + "topic_id": 1, + "topic_name": "Bitcoin 8h", + "description": "Bitcoin price prediction", + "epoch_length": 100, + "ground_truth_lag": 10, + "loss_method": "method1", + "worker_submission_window": 50, + "worker_count": 5, + "reputer_count": 3, + "total_staked_allo": 1000, + "total_emissions_allo": 500, + "is_active": True, + "updated_at": "2023-01-01T00:00:00Z", + } + ] + + mock_client.return_value.get_all_topics = AsyncMock(return_value=mock_topics) + result = await provider.get_all_topics({}) + + assert "The available topics at Allora Network are:" in result + assert json.dumps(mock_topics) in result + + +@pytest.mark.asyncio +async def test_get_all_topics_error(provider, mock_client): + """Test error handling in get all topics.""" + error_msg = "API Error" + mock_client.return_value.get_all_topics = AsyncMock(side_effect=Exception(error_msg)) + + result = await provider.get_all_topics({}) + assert "Error getting all topics:" in result + assert error_msg in result + + +@pytest.mark.asyncio +async def test_get_inference_by_topic_id_success(provider, mock_client): + """Test successful get inference by topic ID.""" + mock_topic_id = 1 + mock_inference = MagicMock() + mock_inference.inference_data = { + "network_inference": "0.5", + "network_inference_normalized": "0.5", + "confidence_interval_percentiles": ["0.1", "0.5", "0.9"], + "confidence_interval_values": ["0.1", "0.5", "0.9"], + "topic_id": "1", + "timestamp": 1718198400, + } + + mock_client.return_value.get_inference_by_topic_id = AsyncMock(return_value=mock_inference) + result = await provider.get_inference_by_topic_id({"topic_id": mock_topic_id}) + + assert f"The inference for topic {mock_topic_id} is:" in result + assert json.dumps(mock_inference.inference_data) in result + + +@pytest.mark.asyncio +async def test_get_inference_by_topic_id_error(provider, mock_client): + """Test error handling in get inference by topic ID.""" + mock_topic_id = 1 + error_msg = "API Error" + mock_client.return_value.get_inference_by_topic_id = AsyncMock(side_effect=Exception(error_msg)) + + result = await provider.get_inference_by_topic_id({"topic_id": mock_topic_id}) + assert f"Error getting inference for topic {mock_topic_id}:" in result + assert error_msg in result + + +@pytest.mark.asyncio +async def test_get_price_inference_success(provider, mock_client): + """Test successful get price inference.""" + mock_asset = PriceInferenceToken.BTC + mock_timeframe = PriceInferenceTimeframe.EIGHT_HOURS + mock_inference = MagicMock() + mock_inference.inference_data = { + "network_inference_normalized": "50000.00", + "timestamp": 1718198400, + } + + mock_client.return_value.get_price_inference = AsyncMock(return_value=mock_inference) + result = await provider.get_price_inference( + { + "asset": mock_asset, + "timeframe": mock_timeframe, + } + ) + + expected_response = { + "price": "50000.00", + "timestamp": 1718198400, + "asset": mock_asset.value, + "timeframe": mock_timeframe.value, + } + + assert f"The price inference for {mock_asset.value} ({mock_timeframe.value}) is:" in result + assert json.dumps(expected_response) in result + + +@pytest.mark.asyncio +async def test_get_price_inference_error(provider, mock_client): + """Test error handling in get price inference.""" + mock_asset = PriceInferenceToken.BTC + mock_timeframe = PriceInferenceTimeframe.EIGHT_HOURS + error_msg = "API Error" + mock_client.return_value.get_price_inference = AsyncMock(side_effect=Exception(error_msg)) + + result = await provider.get_price_inference( + { + "asset": mock_asset, + "timeframe": mock_timeframe, + } + ) + assert f"Error getting price inference for {mock_asset.value} ({mock_timeframe.value}):" in result + assert error_msg in result From 677f7fe32f36b86e3f5a4cd92afe3ef4bfdda7af Mon Sep 17 00:00:00 2001 From: Fernando Campos Date: Fri, 7 Mar 2025 18:58:07 -0300 Subject: [PATCH 2/2] Fixing code review findings. --- python/coinbase-agentkit/Makefile | 6 +- .../changelog.d/110.feature.md | 1 + .../coinbase_agentkit/__init__.py | 2 +- .../action_providers/__init__.py | 2 +- .../action_providers/allora/README.md | 137 ++++++ .../allora/allora_action_provider.py | 204 ++++++-- .../action_providers/allora/schemas.py | 15 +- python/coinbase-agentkit/poetry.lock | 328 ++++++++++++- python/coinbase-agentkit/pyproject.toml | 2 +- .../tests/action_providers/allora/README.md | 105 ++++ .../tests/action_providers/allora/conftest.py | 73 +++ .../allora/test_allora_action_provider.py | 143 +++--- .../allora/test_allora_integration.py | 259 ++++++++++ .../examples/langchain-cdp-chatbot/chatbot.py | 2 + .../langchain-cdp-chatbot/poetry.lock | 461 +++++++++++++++++- .../langchain-cdp-chatbot/pyproject.toml | 1 + 16 files changed, 1569 insertions(+), 172 deletions(-) create mode 100644 python/coinbase-agentkit/changelog.d/110.feature.md create mode 100644 python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/README.md create mode 100644 python/coinbase-agentkit/tests/action_providers/allora/README.md create mode 100644 python/coinbase-agentkit/tests/action_providers/allora/conftest.py create mode 100644 python/coinbase-agentkit/tests/action_providers/allora/test_allora_integration.py diff --git a/python/coinbase-agentkit/Makefile b/python/coinbase-agentkit/Makefile index 367e80168..ee990e321 100644 --- a/python/coinbase-agentkit/Makefile +++ b/python/coinbase-agentkit/Makefile @@ -28,7 +28,11 @@ local-docs: docs .PHONY: test test: - poetry run pytest + poetry run pytest -m "not integration" + +.PHONY: test-integration +test-integration: + poetry run pytest -m integration .PHONY: generate-action-provider generate-action-provider: diff --git a/python/coinbase-agentkit/changelog.d/110.feature.md b/python/coinbase-agentkit/changelog.d/110.feature.md new file mode 100644 index 000000000..042eff053 --- /dev/null +++ b/python/coinbase-agentkit/changelog.d/110.feature.md @@ -0,0 +1 @@ +Added Allora Network action provider diff --git a/python/coinbase-agentkit/coinbase_agentkit/__init__.py b/python/coinbase-agentkit/coinbase_agentkit/__init__.py index 2e1fe5daf..bfd02a3e3 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/__init__.py +++ b/python/coinbase-agentkit/coinbase_agentkit/__init__.py @@ -4,6 +4,7 @@ from .action_providers import ( Action, ActionProvider, + allora_action_provider, basename_action_provider, cdp_api_action_provider, cdp_wallet_action_provider, @@ -17,7 +18,6 @@ wallet_action_provider, weth_action_provider, wow_action_provider, - allora_action_provider, ) from .agentkit import AgentKit, AgentKitConfig from .wallet_providers import ( diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py b/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py index 40e711803..72018d6a4 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/__init__.py @@ -2,6 +2,7 @@ from .action_decorator import create_action from .action_provider import Action, ActionProvider +from .allora.allora_action_provider import AlloraActionProvider, allora_action_provider from .basename.basename_action_provider import ( BasenameActionProvider, basename_action_provider, @@ -20,7 +21,6 @@ from .wallet.wallet_action_provider import WalletActionProvider, wallet_action_provider from .weth.weth_action_provider import WethActionProvider, weth_action_provider from .wow.wow_action_provider import WowActionProvider, wow_action_provider -from .allora.allora_action_provider import AlloraActionProvider, allora_action_provider __all__ = [ "Action", diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/README.md b/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/README.md new file mode 100644 index 000000000..368843ce6 --- /dev/null +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/README.md @@ -0,0 +1,137 @@ +# Allora Action Provider + +This directory contains the **AlloraActionProvider** implementation, which enables interaction with the **Allora Network**, allowing AI agents to fetch topics and inferences for prediction markets. + +## Directory Structure + +``` +allora/ +├── allora_action_provider.py # Main provider with Allora functionality +├── schemas.py # Pydantic schemas for action inputs +├── __init__.py # Package exports +└── README.md # This file + +# From python/coinbase-agentkit/ +tests/action_providers/allora/ +├── conftest.py # Test fixtures +├── test_allora_action_provider.py # Tests for Allora provider +``` + +## Actions + +- `get_all_topics`: Fetches all available topics from Allora Network +- `get_inference_by_topic_id`: Fetches inference data for a specific topic +- `get_price_inference`: Fetches price inference for a specific token and timeframe + +## Setup + +To use the Allora action provider: + +```python +from coinbase_agentkit.action_providers.allora import allora_action_provider + +# With default configuration +provider = allora_action_provider() + +# Or with custom configuration +provider_with_config = allora_action_provider( + api_key="your-api-key", # optional, defaults to a public, development-only key + chain_slug="testnet" # optional, defaults to testnet +) +``` + +## Action Details + +### Get All Topics + +Fetches all available topics from Allora Network. Each topic represents a prediction market. + +Example usage: +```python +result = provider.get_all_topics({}) +``` + +Example response: +```json +[ + { + "topic_id": 1, + "topic_name": "Bitcoin 8h", + "description": "Bitcoin price prediction for the next 8 hours", + "epoch_length": 100, + "ground_truth_lag": 10, + "loss_method": "method1", + "worker_submission_window": 50, + "worker_count": 5, + "reputer_count": 3, + "total_staked_allo": 1000, + "total_emissions_allo": 500, + "is_active": true, + "updated_at": "2023-01-01T00:00:00Z" + } +] +``` + +### Get Inference By Topic ID + +Fetches inference data for a specific topic. Requires a topic ID which can be obtained from the get_all_topics action. + +Example usage: +```python +result = provider.get_inference_by_topic_id({"topic_id": 1}) +``` + +Example response: +```json +{ + "network_inference": "0.5", + "network_inference_normalized": "0.5", + "confidence_interval_percentiles": ["0.1", "0.5", "0.9"], + "confidence_interval_percentiles_normalized": ["0.1", "0.5", "0.9"], + "confidence_interval_values": ["0.1", "0.5", "0.9"], + "confidence_interval_values_normalized": ["0.1", "0.5", "0.9"], + "topic_id": "1", + "timestamp": 1718198400, + "extra_data": "extra_data" +} +``` + +### Get Price Inference + +Fetches price inference for a specific token and timeframe. Requires a token symbol from the supported list and a timeframe. + +Example usage: +```python +from allora_sdk.v2.api_client import PriceInferenceToken, PriceInferenceTimeframe + +result = provider.get_price_inference({ + "asset": PriceInferenceToken.BTC, + "timeframe": PriceInferenceTimeframe.EIGHT_HOURS +}) +``` + +Example response: +```json +{ + "price": "50000.00", + "timestamp": 1718198400, + "asset": "BTC", + "timeframe": "8h" +} +``` + +## Adding New Actions + +To add new Allora actions: + +1. Define your action schema in `schemas.py`. See [Defining the input schema](https://github.com/coinbase/agentkit/blob/main/CONTRIBUTING-PYTHON.md#defining-the-input-schema) for more information. +2. Implement the action in `allora_action_provider.py` +3. Add tests in `tests/action_providers/allora/test_allora_action_provider.py` + +## Network Support + +The Allora provider is network-agnostic. + +## Notes + +For more information about Allora Network and its capabilities, visit [Allora Documentation](https://docs.allora.network/). diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/allora_action_provider.py b/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/allora_action_provider.py index 4cbf3d1fc..7e2ad30ff 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/allora_action_provider.py +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/allora_action_provider.py @@ -1,27 +1,53 @@ """Allora Network action provider.""" +import asyncio import json -from typing import Any, Optional +from concurrent.futures import ThreadPoolExecutor +from typing import Any from allora_sdk.v2.api_client import ( AlloraAPIClient, ChainSlug, - PriceInferenceToken, PriceInferenceTimeframe, + PriceInferenceToken, ) +from ...network import Network +from ...wallet_providers import WalletProvider from ..action_decorator import create_action from ..action_provider import ActionProvider from .schemas import GetAllTopicsInput, GetInferenceByTopicIdInput, GetPriceInferenceInput -class AlloraActionProvider(ActionProvider): +def _convert_to_dict(obj: Any) -> dict[str, Any]: + """Convert an object to a dictionary. + + This is needed because the Allora SDK returns objects that are not directly JSON serializable. + + Args: + obj: The object to convert + + Returns: + A dictionary representation of the object + + """ + if hasattr(obj, "__dict__"): + return {k: _convert_to_dict(v) for k, v in obj.__dict__.items() if not k.startswith("_")} + elif isinstance(obj, list): + return [_convert_to_dict(item) for item in obj] + elif isinstance(obj, dict): + return {k: _convert_to_dict(v) for k, v in obj.items()} + else: + return obj + + +class AlloraActionProvider(ActionProvider[WalletProvider]): """Action provider for interacting with Allora Network.""" def __init__( self, - api_key: Optional[str] = None, - chain_slug: Optional[ChainSlug] = None, + api_key: str | None = None, + chain_slug: ChainSlug | None = None, ): """Initialize the Allora action provider. @@ -31,48 +57,76 @@ def __init__( """ super().__init__("allora", []) + + # This is a public, development only key and should be used for testing purposes only. + # It might be changed or revoked in the future. It is also subject to limits and usage policies. + default_api_key = "UP-4151d0cc489a44a7aa5cd7ef" + self.client = AlloraAPIClient( - api_key=api_key or "UP-4151d0cc489a44a7aa5cd7ef", + api_key=api_key or default_api_key, chain_slug=chain_slug or ChainSlug.TESTNET, ) + # Create a thread pool executor for running async code + self._executor = ThreadPoolExecutor(max_workers=5) + + def _run_async(self, coro): + """Run an async coroutine in a synchronous context. + + Args: + coro: The coroutine to run + + Returns: + The result of the coroutine + + """ + loop = asyncio.new_event_loop() + try: + return loop.run_until_complete(coro) + finally: + loop.close() @create_action( name="get_all_topics", description=""" This tool will get all available inference topics from Allora Network. -A successful response will return a message with a list of available topics from Allora Network in JSON format. Example: - [ - { - "topic_id": 1, - "topic_name": "Bitcoin 8h", - "description": "Bitcoin price prediction for the next 8 hours", - "epoch_length": 100, - "ground_truth_lag": 10, - "loss_method": "method1", - "worker_submission_window": 50, - "worker_count": 5, - "reputer_count": 3, - "total_staked_allo": 1000, - "total_emissions_allo": 500, - "is_active": true, - "updated_at": "2023-01-01T00:00:00Z" - } - ] -The description field is a short description of the topic, and the topic_name is the name of the topic. These fields can be used to understand the topic and its purpose. -The topic_id field is the unique identifier for the topic, and can be used to get the inference data for the topic using the get_inference_by_topic_id action. -The is_active field indicates if the topic is currently active and accepting submissions. -The updated_at field is the timestamp of the last update for the topic. +A successful response will return a list of available topics in JSON format. Example: +[ + { + "topic_id": 1, + "topic_name": "Bitcoin 8h", + "description": "Bitcoin price prediction for the next 8 hours", + "epoch_length": 100, + "ground_truth_lag": 10, + "loss_method": "method1", + "worker_submission_window": 50, + "worker_count": 5, + "reputer_count": 3, + "total_staked_allo": 1000, + "total_emissions_allo": 500, + "is_active": true, + "updated_at": "2023-01-01T00:00:00Z" + } +] + +Key fields: +- topic_id: Unique identifier, use with get_inference_by_topic_id action +- topic_name: Name of the topic +- description: Short description of the topic's purpose +- is_active: If true, topic is active and accepting submissions +- updated_at: Timestamp of last update A failure response will return an error message with details. """, schema=GetAllTopicsInput, ) - async def get_all_topics(self, args: dict[str, Any]) -> str: + def get_all_topics(self, args: dict[str, Any]) -> str: """Get all available topics from Allora Network.""" try: - topics = await self.client.get_all_topics() - topics_json = json.dumps(topics) + topics = self._run_async(self.client.get_all_topics()) + # Convert the topics to dictionaries before serializing + topics_dict = [_convert_to_dict(topic) for topic in topics] + topics_json = json.dumps(topics_dict) return f"The available topics at Allora Network are:\n {topics_json}" except Exception as e: return f"Error getting all topics: {e}" @@ -102,11 +156,13 @@ async def get_all_topics(self, args: dict[str, Any]) -> str: """, schema=GetInferenceByTopicIdInput, ) - async def get_inference_by_topic_id(self, args: dict[str, Any]) -> str: + def get_inference_by_topic_id(self, args: dict[str, Any]) -> str: """Get inference data for a specific topic.""" try: - inference = await self.client.get_inference_by_topic_id(args["topic_id"]) - inference_json = json.dumps(inference.inference_data) + inference = self._run_async(self.client.get_inference_by_topic_id(args["topic_id"])) + # Convert the inference data to a dictionary before serializing + inference_dict = _convert_to_dict(inference.inference_data) + inference_json = json.dumps(inference_dict) return f"The inference for topic {args['topic_id']} is:\n {inference_json}" except Exception as e: return f"Error getting inference for topic {args['topic_id']}: {e}" @@ -134,25 +190,77 @@ async def get_inference_by_topic_id(self, args: dict[str, Any]) -> str: """, schema=GetPriceInferenceInput, ) - async def get_price_inference(self, args: dict[str, Any]) -> str: + def get_price_inference(self, args: dict[str, Any]) -> str: """Get price inference for a token/timeframe pair.""" try: - inference = await self.client.get_price_inference( - args["asset"], - args["timeframe"], + # Get the input values + asset = args["asset"] + timeframe = args["timeframe"] + + # Convert asset string to enum if it's a string + if isinstance(asset, str): + try: + # Try to get the enum value directly by name + asset = getattr(PriceInferenceToken, asset.upper()) + except (AttributeError, ValueError): + # Fail explicitly if the asset can't be converted to a valid enum + return f"Error: '{asset}' is not a valid asset. Valid assets are: {', '.join([e.name for e in PriceInferenceToken])}" + elif not isinstance(asset, PriceInferenceToken): + # Fail if the asset is not a string or PriceInferenceToken + return f"Error: Asset must be a string or PriceInferenceToken enum, got {type(asset).__name__}" + + # Convert timeframe string to enum if it's a string + if isinstance(timeframe, str): + try: + # Map common timeframe formats to enum names + timeframe_name_map = { + "5m": "FIVE_MIN", + "8h": "EIGHT_HOURS", + } + enum_name = timeframe_name_map.get(timeframe.lower(), timeframe.upper()) + timeframe = getattr(PriceInferenceTimeframe, enum_name) + except (AttributeError, ValueError): + # Fail explicitly if the timeframe can't be converted to a valid enum + valid_timeframes = [f"{tf.value} ({tf.name})" for tf in PriceInferenceTimeframe] + return f"Error: '{timeframe}' is not a valid timeframe. Valid timeframes are: {', '.join(valid_timeframes)}" + elif not isinstance(timeframe, PriceInferenceTimeframe): + # Fail if the timeframe is not a string or PriceInferenceTimeframe + return f"Error: Timeframe must be a string or PriceInferenceTimeframe enum, got {type(timeframe).__name__}" + + inference = self._run_async( + self.client.get_price_inference( + asset, + timeframe, + ) ) + # Convert the inference data to a dictionary before accessing its fields + inference_dict = _convert_to_dict(inference.inference_data) + + # Get the string values from the enums + asset_value = asset.value + timeframe_value = timeframe.value + response = { - "price": inference.inference_data["network_inference_normalized"], - "timestamp": inference.inference_data["timestamp"], - "asset": args["asset"].value, # Convert enum to string for JSON - "timeframe": args["timeframe"].value, # Convert enum to string for JSON + "price": inference_dict.get("network_inference_normalized", "0"), + "timestamp": inference_dict.get("timestamp", 0), + "asset": asset_value, + "timeframe": timeframe_value, } inference_json = json.dumps(response) - return f"The price inference for {args['asset'].value} ({args['timeframe'].value}) is:\n{inference_json}" + return ( + f"The price inference for {asset_value} ({timeframe_value}) is:\n{inference_json}" + ) except Exception as e: - return f"Error getting price inference for {args['asset'].value} ({args['timeframe'].value}): {e}" + # Use the enum values in error messages + try: + asset_value = asset.value if hasattr(asset, "value") else str(asset) + timeframe_value = timeframe.value if hasattr(timeframe, "value") else str(timeframe) + return f"Error getting price inference for {asset_value} ({timeframe_value}): {e}" + except Exception: + # Fallback if we can't access the values + return f"Error getting price inference: {e}" - def supports_network(self) -> bool: + def supports_network(self, network: Network) -> bool: """Check if the provider supports a given network. Returns: @@ -162,11 +270,13 @@ def supports_network(self) -> bool: return True # Allora service is network-agnostic -def allora_action_provider() -> AlloraActionProvider: +def allora_action_provider( + api_key: str | None = None, chain_slug: ChainSlug | None = None +) -> AlloraActionProvider: """Create a new Allora action provider. Returns: AlloraActionProvider: A new Allora action provider instance. """ - return AlloraActionProvider() + return AlloraActionProvider(api_key=api_key, chain_slug=chain_slug) diff --git a/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/schemas.py b/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/schemas.py index 3e9469deb..2f729a0ee 100644 --- a/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/schemas.py +++ b/python/coinbase-agentkit/coinbase_agentkit/action_providers/allora/schemas.py @@ -1,9 +1,6 @@ """Schemas for Allora action provider.""" -from typing import Any - -from pydantic import BaseModel, Field, field_validator -from allora_sdk.v2.api_client import PriceInferenceToken, PriceInferenceTimeframe +from pydantic import BaseModel, Field class GetAllTopicsInput(BaseModel): @@ -21,16 +18,6 @@ class GetInferenceByTopicIdInput(BaseModel): gt=0, # Must be greater than 0 ) - @field_validator("topic_id", mode="before") - @classmethod - def validate_topic_id(cls, v: Any) -> int: - """Validate topic_id is a positive integer.""" - if not isinstance(v, int) or isinstance(v, bool): - raise ValueError("topic_id must be an integer") - if v <= 0: - raise ValueError("topic_id must be greater than 0") - return v - class GetPriceInferenceInput(BaseModel): """Input schema for getting price inference for a token/timeframe pair.""" diff --git a/python/coinbase-agentkit/poetry.lock b/python/coinbase-agentkit/poetry.lock index b34ae72dc..d2274eaa0 100644 --- a/python/coinbase-agentkit/poetry.lock +++ b/python/coinbase-agentkit/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -6,6 +6,8 @@ version = "2.5.0" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "aiohappyeyeballs-2.5.0-py3-none-any.whl", hash = "sha256:0850b580748c7071db98bffff6d4c94028d0d3035acc20fd721a0ce7e8cac35d"}, {file = "aiohappyeyeballs-2.5.0.tar.gz", hash = "sha256:18fde6204a76deeabc97c48bdd01d5801cfda5d6b9c8bbeb1aaaee9d648ca191"}, @@ -17,6 +19,8 @@ version = "3.11.13" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a4fe27dbbeec445e6e1291e61d61eb212ee9fed6e47998b27de71d70d3e8777d"}, {file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e64ca2dbea28807f8484c13f684a2f761e69ba2640ec49dacd342763cc265ef"}, @@ -120,6 +124,8 @@ version = "1.3.2" description = "aiosignal: a list of registered asynchronous callbacks" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, @@ -134,6 +140,8 @@ version = "1.0.0" description = "A light, configurable Sphinx theme" optional = false python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b"}, {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"}, @@ -188,6 +196,8 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -199,6 +209,8 @@ version = "4.8.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, @@ -221,6 +233,8 @@ version = "1.5.1" description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67"}, {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, @@ -232,6 +246,8 @@ version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\"" files = [ {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, @@ -243,6 +259,8 @@ version = "25.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"}, {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"}, @@ -262,6 +280,8 @@ version = "2.17.0" description = "Internationalization utilities" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, @@ -276,6 +296,8 @@ version = "2.9.3" description = "Generation of mnemonics, seeds, private/public keys and addresses for different types of cryptocurrencies" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "bip_utils-2.9.3-py3-none-any.whl", hash = "sha256:ee26b8417a576c7f89b847da37316db01a5cece1994c1609d37fbeefb91ad45e"}, {file = "bip_utils-2.9.3.tar.gz", hash = "sha256:72a8c95484b57e92311b0b2a3d5195b0ce4395c19a0b157d4a289e8b1300f48a"}, @@ -310,6 +332,8 @@ version = "3.1.1" description = "efficient arrays of booleans -- C extension" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "bitarray-3.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cb630142c0371862e114cc92fb3c7984b72bbbc4c7e7465225402ab8c7737637"}, {file = "bitarray-3.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:737755812c8834077885c0843e80eaaa2bf289c149f40a4ad0ed79e848fcbaf3"}, @@ -447,12 +471,27 @@ files = [ {file = "bitarray-3.1.1.tar.gz", hash = "sha256:a3c1d74ac2c969bac33169286fe601f8a6f4ca0e8f26dbaa22ad61fbf8fcf259"}, ] +[[package]] +name = "cachetools" +version = "5.5.0" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, + {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, +] + [[package]] name = "cattrs" version = "24.1.2" description = "Composable complex class support for attrs and dataclasses." optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "cattrs-24.1.2-py3-none-any.whl", hash = "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0"}, {file = "cattrs-24.1.2.tar.gz", hash = "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85"}, @@ -479,6 +518,8 @@ version = "5.6.5" description = "CBOR (de)serializer with extensive tag support" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "cbor2-5.6.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e16c4a87fc999b4926f5c8f6c696b0d251b4745bc40f6c5aee51d69b30b15ca2"}, {file = "cbor2-5.6.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:87026fc838370d69f23ed8572939bd71cea2b3f6c8f8bb8283f573374b4d7f33"}, @@ -537,6 +578,8 @@ version = "0.21.0" description = "CDP Python SDK" optional = false python-versions = "<4.0,>=3.10" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "cdp_sdk-0.21.0-py3-none-any.whl", hash = "sha256:36a2ec372c79354133f142566674f6f5a21f474d31f378154a3b4e0e0089818a"}, {file = "cdp_sdk-0.21.0.tar.gz", hash = "sha256:6d832189e84cec76c3353f52835ddf06789630325ca5f0ea1a48ad663b698e7d"}, @@ -558,6 +601,8 @@ version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, @@ -569,6 +614,8 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -661,6 +708,8 @@ 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" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -762,6 +811,8 @@ version = "2.0.1" description = "Python bindings for C-KZG-4844" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ckzg-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b7f9ba6d215f8981c5545f952aac84875bd564a63da02fb22a3d1321662ecdc0"}, {file = "ckzg-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8fdec3ff96399acba9baeef9e1b0b5258c08f73245780e6c69f7b73def5e8d0a"}, @@ -865,6 +916,8 @@ version = "8.1.8" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, @@ -879,6 +932,8 @@ version = "20.0.0" description = "Cross-platform Python CFFI bindings for libsecp256k1" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "coincurve-20.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d559b22828638390118cae9372a1bb6f6594f5584c311deb1de6a83163a0919b"}, {file = "coincurve-20.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33d7f6ebd90fcc550f819f7f2cce2af525c342aac07f0ccda46ad8956ad9d99b"}, @@ -945,6 +1000,8 @@ 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" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -956,6 +1013,8 @@ version = "7.6.12" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "coverage-7.6.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:704c8c8c6ce6569286ae9622e534b4f5b9759b6f2cd643f1c1a61f666d534fe8"}, {file = "coverage-7.6.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ad7525bf0241e5502168ae9c643a2f6c219fa0a283001cee4cf23a9b7da75879"}, @@ -1034,6 +1093,8 @@ version = "1.7" description = "CRC Generator" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "crcmod-1.7.tar.gz", hash = "sha256:dc7051a0db5f2bd48665a990d3ec1cc305a466a77358ca4492826f41f283601e"}, ] @@ -1044,6 +1105,8 @@ version = "44.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "cryptography-44.0.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7"}, {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1"}, @@ -1101,6 +1164,8 @@ version = "1.0.1" description = "Cython implementation of Toolz: High performance functional utilities" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "(python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\") and implementation_name == \"cpython\"" 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"}, @@ -1229,6 +1294,8 @@ version = "0.15" description = "On the fly conversion of Python docstrings to markdown" optional = false python-versions = ">=3.6" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "docstring-to-markdown-0.15.tar.gz", hash = "sha256:e146114d9c50c181b1d25505054a8d0f7a476837f0da2c19f07e06eaed52b73d"}, {file = "docstring_to_markdown-0.15-py3-none-any.whl", hash = "sha256:27afb3faedba81e34c33521c32bbd258d7fbb79eedf7d29bc4e81080e854aec0"}, @@ -1240,6 +1307,8 @@ version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, @@ -1251,6 +1320,8 @@ version = "0.19.0" description = "ECDSA cryptographic signature library (pure python)" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.6" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ecdsa-0.19.0-py2.py3-none-any.whl", hash = "sha256:2cea9b88407fdac7bbeca0833b189e4c9c53f2ef1e1eaa29f6224dbc809b707a"}, {file = "ecdsa-0.19.0.tar.gz", hash = "sha256:60eaad1199659900dd0af521ed462b793bbdf867432b3948e87416ae4caf6bf8"}, @@ -1269,6 +1340,8 @@ version = "1.4.1" description = "Ed25519 public-key signatures (BLAKE2b fork)" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ed25519-blake2b-1.4.1.tar.gz", hash = "sha256:731e9f93cd1ac1a64649575f3519a99ffe0bb1e4cf7bf5f5f0be513a39df7363"}, ] @@ -1279,6 +1352,8 @@ 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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -1301,6 +1376,8 @@ version = "0.13.5" description = "eth-account: Sign Ethereum transactions and messages with local private keys" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "eth_account-0.13.5-py3-none-any.whl", hash = "sha256:e43fd30c9a7fabb882b50e8c4c41d4486d2f3478ad97c66bb18cfcc872fdbec8"}, {file = "eth_account-0.13.5.tar.gz", hash = "sha256:010c9ce5f3d2688106cf9bfeb711bb8eaf0154ea6f85325f54fecea85c2b3759"}, @@ -1329,6 +1406,8 @@ version = "0.7.1" description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -1350,6 +1429,8 @@ 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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -1371,6 +1452,8 @@ version = "0.6.1" description = "eth-keys: Common API for Ethereum key operations" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "eth_keys-0.6.1-py3-none-any.whl", hash = "sha256:7deae4cd56e862e099ec58b78176232b931c4ea5ecded2f50c7b1ccbc10c24cf"}, {file = "eth_keys-0.6.1.tar.gz", hash = "sha256:a43e263cbcabfd62fa769168efc6c27b1f5603040e4de22bb84d12567e4fd962"}, @@ -1392,6 +1475,8 @@ version = "2.2.0" description = "eth-rlp: RLP definitions for common Ethereum objects in Python" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -1414,6 +1499,8 @@ version = "5.2.0" description = "eth-typing: Common type annotations for ethereum python packages" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "eth_typing-5.2.0-py3-none-any.whl", hash = "sha256:e1f424e97990fc3c6a1c05a7b0968caed4e20e9c99a4d5f4db3df418e25ddc80"}, {file = "eth_typing-5.2.0.tar.gz", hash = "sha256:28685f7e2270ea0d209b75bdef76d8ecef27703e1a16399f6929820d05071c28"}, @@ -1433,6 +1520,8 @@ version = "5.2.0" description = "eth-utils: Common utility functions for python code that interacts with Ethereum" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "eth_utils-5.2.0-py3-none-any.whl", hash = "sha256:4d43eeb6720e89a042ad5b28d4b2111630ae764f444b85cbafb708d7f076da10"}, {file = "eth_utils-5.2.0.tar.gz", hash = "sha256:17e474eb654df6e18f20797b22c6caabb77415a996b3ba0f3cc8df3437463134"}, @@ -1455,6 +1544,8 @@ version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -1487,6 +1578,8 @@ version = "1.5.0" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, @@ -1588,6 +1681,8 @@ version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, @@ -1599,6 +1694,8 @@ version = "1.3.0" description = "hexbytes: Python `bytes` subclass that decodes hex, with a readable console output" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "hexbytes-1.3.0-py3-none-any.whl", hash = "sha256:83720b529c6e15ed21627962938dc2dec9bb1010f17bbbd66bf1e6a8287d522c"}, {file = "hexbytes-1.3.0.tar.gz", hash = "sha256:4a61840c24b0909a6534350e2d28ee50159ca1c9e89ce275fd31c110312cf684"}, @@ -1615,6 +1712,8 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -1629,6 +1728,8 @@ version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, @@ -1640,6 +1741,8 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -1651,6 +1754,8 @@ version = "0.19.2" description = "An autocompletion tool for Python that can be used for text editors." optional = false python-versions = ">=3.6" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, @@ -1670,6 +1775,8 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -1687,6 +1794,8 @@ version = "2023.0.1" description = "Python implementation of the Language Server Protocol." optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "lsprotocol-2023.0.1-py3-none-any.whl", hash = "sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2"}, {file = "lsprotocol-2023.0.1.tar.gz", hash = "sha256:cc5c15130d2403c18b734304339e51242d3018a05c4f7d0f198ad6e0cd21861d"}, @@ -1702,6 +1811,8 @@ version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, @@ -1726,6 +1837,8 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -1796,6 +1909,8 @@ version = "0.4.2" description = "Collection of plugins for markdown-it-py" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"}, {file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"}, @@ -1815,6 +1930,8 @@ version = "0.1.2" description = "Markdown URL utilities" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -1826,6 +1943,8 @@ version = "6.1.0" description = "multidict implementation" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, @@ -1930,6 +2049,8 @@ version = "1.15.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, @@ -1983,6 +2104,8 @@ version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.5" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -1994,6 +2117,8 @@ version = "4.0.1" description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," optional = false python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d"}, {file = "myst_parser-4.0.1.tar.gz", hash = "sha256:5cfea715e4f3574138aecbf7d54132296bfd72bb614d31168f48c477a830a7c4"}, @@ -2020,6 +2145,8 @@ version = "3.2.2" description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" optional = false python-versions = ">=3.6" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, @@ -2036,6 +2163,8 @@ version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, @@ -2047,6 +2176,8 @@ version = "0.10.0" description = "(Soon to be) the fastest pure-Python PEG parser I could muster" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f"}, {file = "parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c"}, @@ -2061,6 +2192,8 @@ version = "0.8.4" description = "A Python Parser" optional = false python-versions = ">=3.6" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, @@ -2094,6 +2227,8 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -2109,6 +2244,8 @@ version = "0.9.1" description = "A collection of helpful Python tools!" optional = false python-versions = "*" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pockets-0.9.1-py2.py3-none-any.whl", hash = "sha256:68597934193c08a08eb2bf6a1d85593f627c22f9b065cc727a4f03f669d96d86"}, {file = "pockets-0.9.1.tar.gz", hash = "sha256:9320f1a3c6f7a9133fe3b571f283bcf3353cd70249025ae8d618e40e9f7e92b3"}, @@ -2123,6 +2260,8 @@ version = "3.0.50" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.8.0" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "prompt_toolkit-3.0.50-py3-none-any.whl", hash = "sha256:9b6427eb19e479d98acff65196a307c555eb567989e6d88ebbb1b509d9779198"}, {file = "prompt_toolkit-3.0.50.tar.gz", hash = "sha256:544748f3860a2623ca5cd6d2795e7a14f3d0e1c3c9728359013f79877fc89bab"}, @@ -2137,6 +2276,8 @@ version = "0.3.0" description = "Accelerated property cache" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "propcache-0.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:efa44f64c37cc30c9f05932c740a8b40ce359f51882c70883cc95feac842da4d"}, {file = "propcache-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2383a17385d9800b6eb5855c2f05ee550f803878f344f58b6e194de08b96352c"}, @@ -2244,6 +2385,8 @@ version = "0.2.1" description = "Python bindings for schnorrkel RUST crate" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "py_sr25519_bindings-0.2.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10489c399768dc4ac91c90a6c8da60aeb77a48b21a81944244d41b0d4c4be2f"}, {file = "py_sr25519_bindings-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8358a7b3048765008a79733447dfdcafdce3f66859c98634055fee6868252e12"}, @@ -2358,6 +2501,8 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -2369,6 +2514,8 @@ version = "3.21.0" description = "Cryptographic library for Python" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pycryptodome-3.21.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:dad9bf36eda068e89059d1f07408e397856be9511d7113ea4b586642a429a4fd"}, {file = "pycryptodome-3.21.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:a1752eca64c60852f38bb29e2c86fca30d7672c024128ef5d70cc15868fa10f4"}, @@ -2410,6 +2557,8 @@ version = "2.10.4" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pydantic-2.10.4-py3-none-any.whl", hash = "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d"}, {file = "pydantic-2.10.4.tar.gz", hash = "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06"}, @@ -2430,6 +2579,8 @@ version = "2.27.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, @@ -2542,6 +2693,8 @@ version = "1.3.1" description = "A pythonic generic language server (pronounced like 'pie glass')" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pygls-1.3.1-py3-none-any.whl", hash = "sha256:6e00f11efc56321bdeb6eac04f6d86131f654c7d49124344a9ebb968da3dd91e"}, {file = "pygls-1.3.1.tar.gz", hash = "sha256:140edceefa0da0e9b3c533547c892a42a7d2fd9217ae848c330c53d266a55018"}, @@ -2560,6 +2713,8 @@ version = "2.19.1" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, @@ -2574,6 +2729,8 @@ version = "2.10.1" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, @@ -2591,6 +2748,8 @@ version = "1.5.0" description = "Python binding to the Networking and Cryptography (NaCl) library" optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, @@ -2638,6 +2797,8 @@ version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, @@ -2654,32 +2815,14 @@ tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] -[[package]] -name = "pytest-asyncio" -version = "0.23.8" -description = "Pytest support for asyncio" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}, - {file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}, -] - -[package.dependencies] -pytest = ">=7.0.0,<9" - -[package.extras] -docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] -testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] - [[package]] name = "pytest-cov" version = "6.0.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0"}, {file = "pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35"}, @@ -2698,6 +2841,8 @@ 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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -2712,6 +2857,8 @@ 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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -2726,6 +2873,8 @@ version = "1.1.2" description = "JSON RPC 2.0 server library" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "python-lsp-jsonrpc-1.1.2.tar.gz", hash = "sha256:4688e453eef55cd952bff762c705cedefa12055c0aec17a06f595bcc002cc912"}, {file = "python_lsp_jsonrpc-1.1.2-py3-none-any.whl", hash = "sha256:7339c2e9630ae98903fdaea1ace8c47fba0484983794d6aafd0bd8989be2b03c"}, @@ -2743,6 +2892,8 @@ version = "1.12.2" description = "Python Language Server for the Language Server Protocol" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "python_lsp_server-1.12.2-py3-none-any.whl", hash = "sha256:750116459449184ba20811167cdf96f91296ae12f1f65ebd975c5c159388111b"}, {file = "python_lsp_server-1.12.2.tar.gz", hash = "sha256:fea039a36b3132774d0f803671184cf7dde0c688e7b924f23a6359a66094126d"}, @@ -2775,6 +2926,8 @@ 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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pyunormalize-16.0.0-py3-none-any.whl", hash = "sha256:c647d95e5d1e2ea9a2f448d1d95d8518348df24eab5c3fd32d2b5c3300a49152"}, {file = "pyunormalize-16.0.0.tar.gz", hash = "sha256:2e1dfbb4a118154ae26f70710426a52a364b926c9191f764601f5a8cb12761f7"}, @@ -2786,6 +2939,8 @@ version = "308" description = "Python for Window Extensions" optional = false python-versions = "*" +groups = ["main"] +markers = "(python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\") and platform_system == \"Windows\"" files = [ {file = "pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e"}, {file = "pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e"}, @@ -2813,6 +2968,8 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -2875,6 +3032,8 @@ version = "2.1.0" description = "Python library to build pretty command line user prompts ⭐️" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "questionary-2.1.0-py3-none-any.whl", hash = "sha256:44174d237b68bc828e4878c763a9ad6790ee61990e0ae72927694ead57bab8ec"}, {file = "questionary-2.1.0.tar.gz", hash = "sha256:6302cdd645b19667d8f6e6634774e9538bfcd1aad9be287e743d96cacaf95587"}, @@ -2889,6 +3048,8 @@ version = "2024.11.6" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -2992,6 +3153,8 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -3013,6 +3176,8 @@ version = "2.0.0" description = "OAuthlib authentication support for Requests." optional = false python-versions = ">=3.4" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, @@ -3031,6 +3196,8 @@ version = "13.9.4" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, @@ -3050,6 +3217,8 @@ version = "4.1.0" description = "rlp: A package for Recursive Length Prefix encoding and decoding" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "rlp-4.1.0-py3-none-any.whl", hash = "sha256:8eca394c579bad34ee0b937aecb96a57052ff3716e19c7a578883e767bc5da6f"}, {file = "rlp-4.1.0.tar.gz", hash = "sha256:be07564270a96f3e225e2c107db263de96b5bc1f27722d2855bd3459a08e95a9"}, @@ -3070,6 +3239,8 @@ version = "0.7.4" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ruff-0.7.4-py3-none-linux_armv6l.whl", hash = "sha256:a4919925e7684a3f18e18243cd6bea7cfb8e968a6eaa8437971f681b7ec51478"}, {file = "ruff-0.7.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:cfb365c135b830778dda8c04fb7d4280ed0b984e1aec27f574445231e20d6c63"}, @@ -3097,6 +3268,8 @@ version = "0.0.58" description = "A Language Server Protocol implementation for Ruff." optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ruff_lsp-0.0.58-py3-none-any.whl", hash = "sha256:d59f420ef56a58497f646fef0f5b87d6518e3d63e02044e36677cbdc1f9b7717"}, {file = "ruff_lsp-0.0.58.tar.gz", hash = "sha256:378db39955b32260473602b531dc6333d6686d1d8956673ef1c5203e08132032"}, @@ -3118,6 +3291,8 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -3129,6 +3304,8 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -3140,6 +3317,8 @@ version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." optional = false python-versions = "*" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, @@ -3151,6 +3330,8 @@ version = "8.1.3" description = "Python documentation generator" optional = false python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2"}, {file = "sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927"}, @@ -3186,6 +3367,8 @@ version = "2024.10.3" description = "Rebuild Sphinx documentation on changes, with hot reloading in the browser." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sphinx_autobuild-2024.10.3-py3-none-any.whl", hash = "sha256:158e16c36f9d633e613c9aaf81c19b0fc458ca78b112533b20dafcda430d60fa"}, {file = "sphinx_autobuild-2024.10.3.tar.gz", hash = "sha256:248150f8f333e825107b6d4b86113ab28fa51750e5f9ae63b59dc339be951fb1"}, @@ -3208,6 +3391,8 @@ version = "2.5.0" description = "Type hints (PEP 484) support for the Sphinx autodoc extension" optional = false python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sphinx_autodoc_typehints-2.5.0-py3-none-any.whl", hash = "sha256:53def4753239683835b19bfa8b68c021388bd48a096efcb02cdab508ece27363"}, {file = "sphinx_autodoc_typehints-2.5.0.tar.gz", hash = "sha256:259e1026b218d563d72743f417fcc25906a9614897fe37f91bd8d7d58f748c3b"}, @@ -3227,6 +3412,8 @@ version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, @@ -3243,6 +3430,8 @@ version = "2.0.0" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, @@ -3259,6 +3448,8 @@ version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, @@ -3275,6 +3466,8 @@ version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" optional = false python-versions = ">=3.5" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, @@ -3289,6 +3482,8 @@ version = "0.7" description = "Sphinx \"napoleon\" extension." optional = false python-versions = "*" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sphinxcontrib-napoleon-0.7.tar.gz", hash = "sha256:407382beed396e9f2d7f3043fad6afda95719204a1e1a231ac865f40abcbfcf8"}, {file = "sphinxcontrib_napoleon-0.7-py2.py3-none-any.whl", hash = "sha256:711e41a3974bdf110a484aec4c1a556799eb0b3f3b897521a018ad7e2db13fef"}, @@ -3304,6 +3499,8 @@ version = "2.0.0" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, @@ -3320,6 +3517,8 @@ version = "2.0.0" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, @@ -3336,6 +3535,8 @@ version = "0.46.0" description = "The little ASGI library that shines." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "starlette-0.46.0-py3-none-any.whl", hash = "sha256:913f0798bd90ba90a9156383bcf1350a17d6259451d0d8ee27fc0cf2db609038"}, {file = "starlette-0.46.0.tar.gz", hash = "sha256:b359e4567456b28d473d0193f34c0de0ed49710d75ef183a74a5ce0499324f50"}, @@ -3353,6 +3554,8 @@ version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version == \"3.10\"" files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -3394,6 +3597,8 @@ version = "1.0.0" description = "List processing tools and functional utilities" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "(python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\") and (implementation_name == \"cpython\" or implementation_name == \"pypy\")" files = [ {file = "toolz-1.0.0-py3-none-any.whl", hash = "sha256:292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236"}, {file = "toolz-1.0.0.tar.gz", hash = "sha256:2c86e3d9a04798ac556793bced838816296a2f085017664e4995cb40a1047a02"}, @@ -3405,6 +3610,8 @@ version = "24.8.0" description = "Building newsfiles for your project." optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "towncrier-24.8.0-py3-none-any.whl", hash = "sha256:9343209592b839209cdf28c339ba45792fbfe9775b5f9c177462fd693e127d8d"}, {file = "towncrier-24.8.0.tar.gz", hash = "sha256:013423ee7eed102b2f393c287d22d95f66f1a3ea10a4baa82d298001a7f18af3"}, @@ -3418,12 +3625,43 @@ tomli = {version = "*", markers = "python_version < \"3.11\""} [package.extras] dev = ["furo (>=2024.05.06)", "nox", "packaging", "sphinx (>=5)", "twisted"] +[[package]] +name = "tox" +version = "4.23.2" +description = "tox is a generic virtualenv management and test command line tool" +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "tox-4.23.2-py3-none-any.whl", hash = "sha256:452bc32bb031f2282881a2118923176445bac783ab97c874b8770ab4c3b76c38"}, + {file = "tox-4.23.2.tar.gz", hash = "sha256:86075e00e555df6e82e74cfc333917f91ecb47ffbc868dcafbd2672e332f4a2c"}, +] + +[package.dependencies] +cachetools = ">=5.5" +chardet = ">=5.2" +colorama = ">=0.4.6" +filelock = ">=3.16.1" +packaging = ">=24.1" +platformdirs = ">=4.3.6" +pluggy = ">=1.5" +pyproject-api = ">=1.8" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.12.2", markers = "python_version < \"3.11\""} +virtualenv = ">=20.26.6" + +[package.extras] +test = ["devpi-process (>=1.0.2)", "pytest (>=8.3.3)", "pytest-mock (>=3.14)"] + [[package]] name = "tweepy" version = "4.15.0" description = "Twitter library for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "tweepy-4.15.0-py3-none-any.whl", hash = "sha256:64adcea317158937059e4e2897b3ceb750b0c2dd5df58938c2da8f7eb3b88e6a"}, {file = "tweepy-4.15.0.tar.gz", hash = "sha256:1345cbcdf0a75e2d89f424c559fd49fda4d8cd7be25cd5131e3b57bad8a21d76"}, @@ -3447,6 +3685,8 @@ version = "0.9.4" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." optional = false python-versions = ">=3.6" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "typer-0.9.4-py3-none-any.whl", hash = "sha256:aa6c4a4e2329d868b80ecbaf16f807f2b54e192209d7ac9dd42691d63f7a54eb"}, {file = "typer-0.9.4.tar.gz", hash = "sha256:f714c2d90afae3a7929fcd72a3abb08df305e1ff61719381384211c4070af57f"}, @@ -3468,6 +3708,8 @@ version = "2.32.0.20250306" description = "Typing stubs for requests" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "types_requests-2.32.0.20250306-py3-none-any.whl", hash = "sha256:25f2cbb5c8710b2022f8bbee7b2b66f319ef14aeea2f35d80f18c9dbf3b60a0b"}, {file = "types_requests-2.32.0.20250306.tar.gz", hash = "sha256:0962352694ec5b2f95fda877ee60a159abdf84a0fc6fdace599f20acb41a03d1"}, @@ -3482,6 +3724,8 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -3493,6 +3737,8 @@ version = "5.10.0" description = "Ultra fast JSON encoder and decoder for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"}, {file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"}, @@ -3580,6 +3826,8 @@ version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, @@ -3597,6 +3845,8 @@ version = "0.34.0" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4"}, {file = "uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9"}, @@ -3610,12 +3860,36 @@ typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} [package.extras] standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +[[package]] +name = "virtualenv" +version = "20.28.1" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "virtualenv-20.28.1-py3-none-any.whl", hash = "sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb"}, + {file = "virtualenv-20.28.1.tar.gz", hash = "sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + [[package]] name = "watchfiles" version = "1.0.4" description = "Simple, modern and high performance file watching and code reload in python." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "watchfiles-1.0.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ba5bb3073d9db37c64520681dd2650f8bd40902d991e7b4cfaeece3e32561d08"}, {file = "watchfiles-1.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9f25d0ba0fe2b6d2c921cf587b2bf4c451860086534f40c384329fb96e2044d1"}, @@ -3699,6 +3973,8 @@ version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, @@ -3710,6 +3986,8 @@ version = "7.8.0" description = "web3: A Python library for interacting with Ethereum" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "web3-7.8.0-py3-none-any.whl", hash = "sha256:c8771b3d8772f7104a0462804449beb57d36cef7bd8b411140f95a92fc46b559"}, {file = "web3-7.8.0.tar.gz", hash = "sha256:712bc9fd6b1ef6e467ee24c25b581e1951cab2cba17f9f548f12587734f2c857"}, @@ -3743,6 +4021,8 @@ version = "13.1" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -3838,6 +4118,8 @@ version = "1.18.3" description = "Yet another URL library" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, @@ -3929,6 +4211,6 @@ multidict = ">=4.0" propcache = ">=0.2.0" [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = "^3.10" -content-hash = "26c1811879439ad652d0f9b0124e1b86e1f74f2cf351d258b83b2b2048750b86" +content-hash = "11a76a87141dea3ecac2eade46493d3fe263d24558451b1f3789c0156e59f7ce" diff --git a/python/coinbase-agentkit/pyproject.toml b/python/coinbase-agentkit/pyproject.toml index 868be6e27..4f51f638e 100644 --- a/python/coinbase-agentkit/pyproject.toml +++ b/python/coinbase-agentkit/pyproject.toml @@ -27,7 +27,6 @@ ruff = "^0.7.1" mypy = "^1.13.0" pytest = "^8.3.3" pytest-cov = "^6.0.0" -pytest-asyncio = "^0.23.5" sphinx = "^8.0.2" sphinx-autobuild = "^2024.9.19" sphinxcontrib-napoleon = "^0.7" @@ -69,6 +68,7 @@ line-ending = "auto" [tool.ruff.lint.isort] known-first-party = ["coinbase_agentkit, cdp"] +combine-as-imports = true [tool.towncrier] package = "coinbase_agentkit" diff --git a/python/coinbase-agentkit/tests/action_providers/allora/README.md b/python/coinbase-agentkit/tests/action_providers/allora/README.md new file mode 100644 index 000000000..1d05c0570 --- /dev/null +++ b/python/coinbase-agentkit/tests/action_providers/allora/README.md @@ -0,0 +1,105 @@ +# Allora Action Provider Tests + +This directory contains tests for the Allora action provider, which allows interaction with the Allora Network API. + +## Test Types + +There are two types of tests: + +1. **Unit Tests**: These tests use mocks to test the functionality of the Allora action provider without making actual API calls. +2. **Integration Tests**: These tests make actual API calls to the Allora Network API and require an internet connection. + +## Running Tests + +### Prerequisites + +Make sure you have Poetry installed and have installed the project dependencies: + +```bash +# Navigate to the project root +cd python/coinbase-agentkit + +# Install dependencies with Poetry +poetry install +``` + +The tests automatically add the project root to the Python path, so you don't need to do any special setup beyond installing the dependencies. + +### Running Unit Tests + +To run the unit tests: + +```bash +# Using Poetry +poetry run pytest tests/action_providers/allora/test_allora_action_provider.py -v + +# Or using the Makefile (which uses Poetry internally) +make test +``` + +### Running Integration Tests + +Integration tests are automatically skipped when running `make test` or when running pytest without specific flags. This ensures that integration tests don't run accidentally. + +To run the integration tests, you must explicitly request them using the `-m integration` flag: + +```bash +# Using the Makefile +make test-integration + +# Or directly with Poetry +poetry run pytest -m integration tests/action_providers/allora/test_allora_integration.py -v +``` + +## Configuration (Optional) + +By default, the integration tests use the default development API key and testnet configuration provided in the `AlloraActionProvider` class. You don't need to set any environment variables to run the tests. + +If you want to use custom values, you can set the following environment variables: + +- `ALLORA_API_KEY`: Custom API key for Allora Network +- `ALLORA_CHAIN_SLUG`: Chain slug to use (`testnet` or `mainnet`) + +Example with custom values: + +```bash +# Using the Makefile +ALLORA_API_KEY=your-api-key ALLORA_CHAIN_SLUG=testnet make test-integration + +# Or directly with Poetry +ALLORA_API_KEY=your-api-key ALLORA_CHAIN_SLUG=testnet poetry run pytest -m integration tests/action_providers/allora/test_allora_integration.py -v +``` + +## Test Structure + +- `test_allora_action_provider.py`: Unit tests for the Allora action provider. +- `test_allora_integration.py`: Integration tests for the Allora action provider. +- `conftest.py`: Fixtures for both unit tests and integration tests. + +## Adding New Tests + +When adding new tests, follow these guidelines: + +1. For unit tests, use the `provider` fixture from `conftest.py` to get a mocked Allora action provider. +2. For integration tests, use the `integration_provider` fixture from `conftest.py` to get a real Allora action provider. +3. Mark integration tests with the `@pytest.mark.integration` decorator. +4. For integration tests, handle potential API errors gracefully and add appropriate assertions to verify the response structure. + +### Input Parameters + +The Allora action provider requires enum values for the `asset` and `timeframe` parameters when calling the Allora SDK. The provider will attempt to convert string inputs to the appropriate enum values: + +- **asset**: Must be a valid `PriceInferenceToken` enum value. Currently supported: `BTC`, `ETH` +- **timeframe**: Must be a valid `PriceInferenceTimeframe` enum value. Currently supported: `5m`, `8h` + +If a string input cannot be converted to a valid enum value, the provider will return a clear error message listing the supported values. This ensures that only valid inputs are passed to the Allora SDK. + +Example error messages: +- `Error: 'SOL' is not a valid asset. Valid assets are: BTC, ETH` +- `Error: '24h' is not a valid timeframe. Valid timeframes are: 5m (FIVE_MIN), 8h (EIGHT_HOURS)` + +## Notes + +- The integration tests may fail if the Allora Network API is down. +- The integration tests may take longer to run than the unit tests due to network latency. +- The default development API key provided in the AlloraActionProvider class is subject to rate limits. diff --git a/python/coinbase-agentkit/tests/action_providers/allora/conftest.py b/python/coinbase-agentkit/tests/action_providers/allora/conftest.py new file mode 100644 index 000000000..78051c945 --- /dev/null +++ b/python/coinbase-agentkit/tests/action_providers/allora/conftest.py @@ -0,0 +1,73 @@ +"""Fixtures for Allora action provider tests.""" + +import os +import sys +from pathlib import Path +from unittest.mock import AsyncMock, patch + +import pytest +from allora_sdk.v2.api_client import ChainSlug + +# Add the project root to the Python path +project_root = Path(__file__).parent.parent.parent.parent +sys.path.insert(0, str(project_root)) + +from coinbase_agentkit.action_providers.allora.allora_action_provider import ( # noqa: E402 + AlloraActionProvider, +) + + +def pytest_configure(config): + """Register the integration marker.""" + config.addinivalue_line( + "markers", "integration: mark test as an integration test that requires internet connection" + ) + + +@pytest.fixture +def mock_client(): + """Create a mock Allora API client.""" + with patch("allora_sdk.v2.api_client.AlloraAPIClient") as mock: + yield mock + + +@pytest.fixture +def provider(mock_client): + """Create an Allora action provider with a mock client.""" + provider = AlloraActionProvider(api_key="test-api-key", chain_slug=ChainSlug.TESTNET) + provider.client = mock_client.return_value + + # Instead of mocking _run_async, we'll patch it to directly return the value + # that would be returned by the coroutine + def mock_run_async(coro): + # For AsyncMock objects, we need to access their return_value + if isinstance(coro, AsyncMock): + return coro.return_value + # For AsyncMock with side_effect=Exception, we need to raise the exception + try: + return coro + except Exception as e: + raise e + + provider._run_async = mock_run_async + return provider + + +@pytest.fixture +def integration_provider(): + """Create an Allora action provider for integration tests. + + This uses the default API key and testnet configuration from the AlloraActionProvider class. + If you want to use custom values, you can set the ALLORA_API_KEY and ALLORA_CHAIN_SLUG + environment variables. + """ + # Get optional custom values from environment variables + api_key = os.environ.get("ALLORA_API_KEY") + + chain_slug = None + chain_slug_str = os.environ.get("ALLORA_CHAIN_SLUG") + if chain_slug_str and chain_slug_str.lower() == "mainnet": + chain_slug = ChainSlug.MAINNET + + # Create the provider with optional custom values (will use defaults if None) + return AlloraActionProvider(api_key=api_key, chain_slug=chain_slug) diff --git a/python/coinbase-agentkit/tests/action_providers/allora/test_allora_action_provider.py b/python/coinbase-agentkit/tests/action_providers/allora/test_allora_action_provider.py index d392ebaa3..c5c240c8f 100644 --- a/python/coinbase-agentkit/tests/action_providers/allora/test_allora_action_provider.py +++ b/python/coinbase-agentkit/tests/action_providers/allora/test_allora_action_provider.py @@ -1,15 +1,14 @@ """Tests for Allora action provider.""" import json -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock import pytest from allora_sdk.v2.api_client import ( - AlloraAPIClient, - ChainSlug, - PriceInferenceToken, PriceInferenceTimeframe, + PriceInferenceToken, ) +from pydantic import ValidationError from coinbase_agentkit.action_providers.allora.allora_action_provider import AlloraActionProvider from coinbase_agentkit.action_providers.allora.schemas import ( @@ -19,21 +18,6 @@ ) -@pytest.fixture -def mock_client(): - """Create a mock Allora API client.""" - with patch("allora_sdk.v2.api_client.AlloraAPIClient") as mock: - yield mock - - -@pytest.fixture -def provider(mock_client): - """Create an Allora action provider with a mock client.""" - provider = AlloraActionProvider(api_key="test-api-key", chain_slug=ChainSlug.TESTNET) - provider.client = mock_client.return_value - return provider - - def test_get_all_topics_input_schema(): """Test get all topics input schema.""" # Empty input is valid for this schema @@ -44,30 +28,29 @@ def test_get_all_topics_input_schema(): def test_get_inference_by_topic_id_input_schema(): """Test get inference by topic ID input schema.""" # Test valid inputs - valid_inputs = [ - {"topic_id": 1}, - {"topic_id": 100}, - {"topic_id": 999999}, - ] - for input_data in valid_inputs: - parsed_input = GetInferenceByTopicIdInput(**input_data) - assert parsed_input.topic_id == input_data["topic_id"] - - # Test invalid topic IDs - invalid_topic_ids = [ - 0, # Zero is not allowed - -1, # Negative numbers not allowed - "1", # String not allowed - 1.5, # Float not allowed - ] - for topic_id in invalid_topic_ids: - with pytest.raises(ValueError) as exc_info: - GetInferenceByTopicIdInput(topic_id=topic_id) - error_msg = str(exc_info.value) - if isinstance(topic_id, (int, float)) and topic_id <= 0: - assert "greater than 0" in error_msg - else: - assert "must be an integer" in error_msg + valid_inputs = [1, 100, 999999] + for topic_id in valid_inputs: + parsed_input = GetInferenceByTopicIdInput(topic_id=topic_id) + assert parsed_input.topic_id == topic_id + + # Test invalid inputs + # Note: Pydantic will try to convert some types, so we need to test carefully + + # Test value validation (gt=0) + with pytest.raises((ValueError, ValidationError)): + GetInferenceByTopicIdInput(topic_id=0) # Zero is not allowed (gt=0) + + with pytest.raises((ValueError, ValidationError)): + GetInferenceByTopicIdInput(topic_id=-1) # Negative numbers not allowed (gt=0) + + # Test type validation - note that Pydantic will try to convert strings to int if possible + with pytest.raises((ValueError, ValidationError)): + GetInferenceByTopicIdInput(topic_id="not_an_int") # String that can't be converted to int + + # Test float validation - Pydantic might convert some floats to int + # For example, 1.0 will be converted to 1, but 1.5 can't be exactly represented as int + with pytest.raises((ValueError, ValidationError)): + GetInferenceByTopicIdInput(topic_id=1.5) # Float with fractional part def test_get_price_inference_input_schema(): @@ -86,14 +69,13 @@ def test_get_price_inference_input_schema(): assert parsed_input.timeframe == input_data["timeframe"] # Test that empty strings are not allowed (Pydantic's built-in validation) - with pytest.raises(ValueError): + with pytest.raises((ValueError, ValidationError)): GetPriceInferenceInput(asset="", timeframe="5m") - with pytest.raises(ValueError): + with pytest.raises((ValueError, ValidationError)): GetPriceInferenceInput(asset="BTC", timeframe="") -@pytest.mark.asyncio -async def test_get_all_topics_success(provider, mock_client): +def test_get_all_topics_success(provider, mock_client): """Test successful get all topics.""" mock_topics = [ { @@ -113,26 +95,27 @@ async def test_get_all_topics_success(provider, mock_client): } ] - mock_client.return_value.get_all_topics = AsyncMock(return_value=mock_topics) - result = await provider.get_all_topics({}) + # Set up the mock to return the mock_topics directly + mock_client.return_value.get_all_topics.return_value = mock_topics + result = provider.get_all_topics({}) assert "The available topics at Allora Network are:" in result assert json.dumps(mock_topics) in result -@pytest.mark.asyncio -async def test_get_all_topics_error(provider, mock_client): +def test_get_all_topics_error(provider, mock_client): """Test error handling in get all topics.""" error_msg = "API Error" - mock_client.return_value.get_all_topics = AsyncMock(side_effect=Exception(error_msg)) - result = await provider.get_all_topics({}) + # Set up the mock to raise an exception when called + mock_client.return_value.get_all_topics.side_effect = Exception(error_msg) + + result = provider.get_all_topics({}) assert "Error getting all topics:" in result assert error_msg in result -@pytest.mark.asyncio -async def test_get_inference_by_topic_id_success(provider, mock_client): +def test_get_inference_by_topic_id_success(provider, mock_client): """Test successful get inference by topic ID.""" mock_topic_id = 1 mock_inference = MagicMock() @@ -145,27 +128,28 @@ async def test_get_inference_by_topic_id_success(provider, mock_client): "timestamp": 1718198400, } - mock_client.return_value.get_inference_by_topic_id = AsyncMock(return_value=mock_inference) - result = await provider.get_inference_by_topic_id({"topic_id": mock_topic_id}) + # Set up the mock to return the mock_inference directly + mock_client.return_value.get_inference_by_topic_id.return_value = mock_inference + result = provider.get_inference_by_topic_id({"topic_id": mock_topic_id}) assert f"The inference for topic {mock_topic_id} is:" in result assert json.dumps(mock_inference.inference_data) in result -@pytest.mark.asyncio -async def test_get_inference_by_topic_id_error(provider, mock_client): +def test_get_inference_by_topic_id_error(provider, mock_client): """Test error handling in get inference by topic ID.""" mock_topic_id = 1 error_msg = "API Error" - mock_client.return_value.get_inference_by_topic_id = AsyncMock(side_effect=Exception(error_msg)) - result = await provider.get_inference_by_topic_id({"topic_id": mock_topic_id}) + # Set up the mock to raise an exception when called + mock_client.return_value.get_inference_by_topic_id.side_effect = Exception(error_msg) + + result = provider.get_inference_by_topic_id({"topic_id": mock_topic_id}) assert f"Error getting inference for topic {mock_topic_id}:" in result assert error_msg in result -@pytest.mark.asyncio -async def test_get_price_inference_success(provider, mock_client): +def test_get_price_inference_success(provider, mock_client): """Test successful get price inference.""" mock_asset = PriceInferenceToken.BTC mock_timeframe = PriceInferenceTimeframe.EIGHT_HOURS @@ -175,8 +159,9 @@ async def test_get_price_inference_success(provider, mock_client): "timestamp": 1718198400, } - mock_client.return_value.get_price_inference = AsyncMock(return_value=mock_inference) - result = await provider.get_price_inference( + # Set up the mock to return the mock_inference directly + mock_client.return_value.get_price_inference.return_value = mock_inference + result = provider.get_price_inference( { "asset": mock_asset, "timeframe": mock_timeframe, @@ -194,19 +179,37 @@ async def test_get_price_inference_success(provider, mock_client): assert json.dumps(expected_response) in result -@pytest.mark.asyncio -async def test_get_price_inference_error(provider, mock_client): +def test_get_price_inference_error(provider, mock_client): """Test error handling in get price inference.""" mock_asset = PriceInferenceToken.BTC mock_timeframe = PriceInferenceTimeframe.EIGHT_HOURS error_msg = "API Error" - mock_client.return_value.get_price_inference = AsyncMock(side_effect=Exception(error_msg)) - result = await provider.get_price_inference( + # Set up the mock to raise an exception when called + mock_client.return_value.get_price_inference.side_effect = Exception(error_msg) + + result = provider.get_price_inference( { "asset": mock_asset, "timeframe": mock_timeframe, } ) - assert f"Error getting price inference for {mock_asset.value} ({mock_timeframe.value}):" in result + assert ( + f"Error getting price inference for {mock_asset.value} ({mock_timeframe.value}):" in result + ) assert error_msg in result + + +def test_run_async_method(provider): + """Test the _run_async helper method.""" + + # Create a mock coroutine + async def mock_coro(): + return "test_result" + + # Reset the mock to test the actual implementation + provider._run_async = AlloraActionProvider._run_async.__get__(provider, AlloraActionProvider) + + # Test that _run_async correctly runs the coroutine + result = provider._run_async(mock_coro()) + assert result == "test_result" diff --git a/python/coinbase-agentkit/tests/action_providers/allora/test_allora_integration.py b/python/coinbase-agentkit/tests/action_providers/allora/test_allora_integration.py new file mode 100644 index 000000000..5eacf071c --- /dev/null +++ b/python/coinbase-agentkit/tests/action_providers/allora/test_allora_integration.py @@ -0,0 +1,259 @@ +"""Integration tests for Allora action provider. + +These tests interact with the actual Allora API and require an internet connection. +By default, they use the development API key provided in the AlloraActionProvider class. + +IMPORTANT: These tests should ONLY be run explicitly using the integration marker: +pytest -m integration tests/action_providers/allora/test_allora_integration.py -v + +Optional configuration via environment variables: +- ALLORA_API_KEY: Custom API key for Allora Network +- ALLORA_CHAIN_SLUG: Chain slug to use (testnet or mainnet) +""" + +import json + +import pytest + +from coinbase_agentkit.network import Network + +# The fixtures are imported from conftest.py + +# Mark the entire module as integration tests +pytestmark = pytest.mark.integration + + +def test_get_all_topics_integration(integration_provider): + """Test getting all topics from the Allora API.""" + result = integration_provider.get_all_topics({}) + + # Check that the response contains the expected text + assert ( + "The available topics at Allora Network are:" in result + or "Error getting all topics:" in result + ) + + # If there's an error, we can't test further + if "Error getting all topics:" in result: + pytest.skip(f"Skipping due to API error: {result}") + + # Extract the JSON part from the response + json_start = result.find("[") + json_end = result.rfind("]") + 1 + topics_json = result[json_start:json_end] + + # Parse the JSON and check that it's a list + topics = json.loads(topics_json) + assert isinstance(topics, list) + + # If there are topics, check that they have the expected structure + if topics: + topic = topics[0] + assert "topic_id" in topic + assert "topic_name" in topic + assert "description" in topic + assert "is_active" in topic + + +def test_get_inference_by_topic_id_integration(integration_provider): + """Test getting inference by topic ID from the Allora API.""" + # First, get all topics to find a valid topic ID + all_topics_result = integration_provider.get_all_topics({}) + + # If there's an error, we can't test further + if "Error getting all topics:" in all_topics_result: + pytest.skip(f"Skipping due to API error: {all_topics_result}") + + # Extract the JSON part from the response + json_start = all_topics_result.find("[") + json_end = all_topics_result.rfind("]") + 1 + topics_json = all_topics_result[json_start:json_end] + + # Parse the JSON and check that it's a list + topics = json.loads(topics_json) + + # Skip the test if there are no topics + if not topics: + pytest.skip("No topics available for testing") + + # Use the first active topic for testing + active_topics = [t for t in topics if t.get("is_active", False)] + if not active_topics: + pytest.skip("No active topics available for testing") + + topic_id = active_topics[0]["topic_id"] + + # Now test getting inference for this topic + result = integration_provider.get_inference_by_topic_id({"topic_id": topic_id}) + + # Check that the response contains the expected text + assert ( + f"The inference for topic {topic_id} is:" in result + or f"Error getting inference for topic {topic_id}:" in result + ) + + # If there's an error, we can't test further + if f"Error getting inference for topic {topic_id}:" in result: + pytest.skip(f"Skipping due to API error: {result}") + + # Extract the JSON part from the response + json_start = result.find("{") + json_end = result.rfind("}") + 1 + inference_json = result[json_start:json_end] + + # Parse the JSON and check that it has the expected structure + inference = json.loads(inference_json) + assert "topic_id" in inference + assert "timestamp" in inference + # One of these should be present + assert "network_inference" in inference or "network_inference_normalized" in inference + + +def test_get_price_inference_btc_integration(integration_provider): + """Test getting price inference for BTC from the Allora API.""" + # Test with BTC and 8h timeframe using string values + asset = "BTC" + timeframe = "8h" + + result = integration_provider.get_price_inference( + { + "asset": asset, + "timeframe": timeframe, + } + ) + + print(f"Result: {result}") + + # Check that the response contains the expected text or an error + expected_text = f"The price inference for {asset} ({timeframe}) is:" + assert expected_text in result or f"Error getting price inference for {asset}" in result + + # If there's an error, skip the test + if f"Error getting price inference for {asset}" in result: + pytest.skip(f"Skipping due to API error: {result}") + + # Extract the JSON part from the response + json_start = result.find("{") + json_end = result.rfind("}") + 1 + inference_json = result[json_start:json_end] + + # Parse the JSON and check that it has the expected structure + inference = json.loads(inference_json) + assert "price" in inference + assert "timestamp" in inference + assert "asset" in inference + assert "timeframe" in inference + assert inference["asset"] == asset + assert inference["timeframe"] == timeframe + + # Check that the price is a valid number + price = float(inference["price"]) + assert price > 0 + + +def test_get_price_inference_eth_integration(integration_provider): + """Test getting price inference for ETH from the Allora API.""" + # Test with ETH and 8h timeframe using string values + asset = "ETH" + timeframe = "8h" + + result = integration_provider.get_price_inference( + { + "asset": asset, + "timeframe": timeframe, + } + ) + + # Check that the response contains the expected text or an error + expected_text = f"The price inference for {asset} ({timeframe}) is:" + assert expected_text in result or f"Error getting price inference for {asset}" in result + + # If there's an error, we can't test further + if f"Error getting price inference for {asset}" in result: + pytest.skip(f"Skipping due to API error: {result}") + + # Extract the JSON part from the response + json_start = result.find("{") + json_end = result.rfind("}") + 1 + inference_json = result[json_start:json_end] + + # Parse the JSON and check that it has the expected structure + inference = json.loads(inference_json) + assert "price" in inference + assert "timestamp" in inference + assert "asset" in inference + assert "timeframe" in inference + assert inference["asset"] == asset + assert inference["timeframe"] == timeframe + + # Check that the price is a valid number + price = float(inference["price"]) + assert price > 0 + + +def test_error_handling_invalid_topic_id(integration_provider): + """Test error handling when an invalid topic ID is provided.""" + # Use a very large topic ID that is unlikely to exist + invalid_topic_id = 999999999 + + result = integration_provider.get_inference_by_topic_id({"topic_id": invalid_topic_id}) + + # Check that the response contains an error message + assert f"Error getting inference for topic {invalid_topic_id}:" in result + + +def test_supports_network(integration_provider): + """Test that the provider supports all networks.""" + # Create Network instances instead of using enum values + ethereum = Network(protocol_family="ethereum", network_id="ethereum-mainnet", chain_id="1") + polygon = Network(protocol_family="ethereum", network_id="polygon-mainnet", chain_id="137") + solana = Network(protocol_family="solana") + bitcoin = Network(protocol_family="bitcoin") + + # Test with different networks + assert integration_provider.supports_network(ethereum) + assert integration_provider.supports_network(polygon) + assert integration_provider.supports_network(solana) + # The provider should support all networks as it's network-agnostic + assert integration_provider.supports_network(bitcoin) + + +def test_get_price_inference_unsupported_values(integration_provider): + """Test getting price inference with unsupported values.""" + # Test with SOL and 24h timeframe, which are not supported + asset = "SOL" + timeframe = "24h" + + result = integration_provider.get_price_inference( + { + "asset": asset, + "timeframe": timeframe, + } + ) + + # Check that the response contains an error message + assert "Error:" in result + + # Check that the error message mentions SOL is not a valid asset + assert f"'{asset}' is not a valid asset" in result + assert "BTC" in result # Should mention valid assets + assert "ETH" in result # Should mention valid assets + + # Test with BTC and 24h timeframe + asset = "BTC" + timeframe = "24h" + + result = integration_provider.get_price_inference( + { + "asset": asset, + "timeframe": timeframe, + } + ) + + # Check that the response contains an error message + assert "Error:" in result + + # Check that the error message mentions 24h is not a valid timeframe + assert f"'{timeframe}' is not a valid timeframe" in result + assert "5m" in result # Should mention valid timeframes + assert "8h" in result # Should mention valid timeframes diff --git a/python/examples/langchain-cdp-chatbot/chatbot.py b/python/examples/langchain-cdp-chatbot/chatbot.py index 25cc12a88..050a847cf 100644 --- a/python/examples/langchain-cdp-chatbot/chatbot.py +++ b/python/examples/langchain-cdp-chatbot/chatbot.py @@ -8,6 +8,7 @@ AgentKitConfig, CdpWalletProvider, CdpWalletProviderConfig, + allora_action_provider, cdp_api_action_provider, cdp_wallet_action_provider, erc20_action_provider, @@ -55,6 +56,7 @@ def initialize_agent(): pyth_action_provider(), wallet_action_provider(), weth_action_provider(), + allora_action_provider(), ], ) ) diff --git a/python/examples/langchain-cdp-chatbot/poetry.lock b/python/examples/langchain-cdp-chatbot/poetry.lock index 60ab2ce24..199980a1a 100644 --- a/python/examples/langchain-cdp-chatbot/poetry.lock +++ b/python/examples/langchain-cdp-chatbot/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -6,6 +6,8 @@ version = "2.4.6" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "aiohappyeyeballs-2.4.6-py3-none-any.whl", hash = "sha256:147ec992cf873d74f5062644332c539fcd42956dc69453fe5204195e560517e1"}, {file = "aiohappyeyeballs-2.4.6.tar.gz", hash = "sha256:9b05052f9042985d32ecbe4b59a77ae19c006a78f1344d7fdad69d28ded3d0b0"}, @@ -17,6 +19,8 @@ version = "3.11.12" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aa8a8caca81c0a3e765f19c6953416c58e2f4cc1b84829af01dd1c771bb2f91f"}, {file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:84ede78acde96ca57f6cf8ccb8a13fbaf569f6011b9a52f870c662d4dc8cd854"}, @@ -120,6 +124,8 @@ version = "1.3.2" description = "aiosignal: a list of registered asynchronous callbacks" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, @@ -128,12 +134,53 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "allora-sdk" +version = "0.2.0" +description = "Allora Network SDK" +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "allora_sdk-0.2.0-py3-none-any.whl", hash = "sha256:9935a6e1693e347c8f73fccda831c3ff817ff90ba644e32f1aa3534869ebacf5"}, + {file = "allora_sdk-0.2.0.tar.gz", hash = "sha256:849e6da659fce3b5c401e3b58a219165bc222f7b79273b6dcf0e8e3c4b7334e5"}, +] + +[package.dependencies] +aiohttp = "*" +annotated-types = "0.7.0" +cachetools = "5.5.0" +certifi = "2024.12.14" +chardet = "5.2.0" +charset-normalizer = "3.4.1" +colorama = "0.4.6" +distlib = "0.3.9" +filelock = "3.16.1" +idna = "3.10" +packaging = "24.2" +platformdirs = "4.3.6" +pluggy = "1.5.0" +pydantic = "2.10.4" +pydantic-core = "2.27.2" +pyproject-api = "1.8.0" +requests = "2.32.3" +tox = "4.23.2" +typing-extensions = "4.12.2" +urllib3 = "2.3.0" +virtualenv = "20.28.1" + +[package.extras] +dev = ["fastapi", "pytest", "pytest-asyncio", "starlette", "tox"] + [[package]] name = "annotated-types" version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -145,6 +192,8 @@ version = "4.8.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, @@ -167,6 +216,8 @@ version = "1.5.1" description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67"}, {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, @@ -178,6 +229,8 @@ version = "4.0.3" description = "Timeout context manager for asyncio programs" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\"" files = [ {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, @@ -189,6 +242,8 @@ version = "25.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"}, {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"}, @@ -208,6 +263,8 @@ version = "2.9.3" description = "Generation of mnemonics, seeds, private/public keys and addresses for different types of cryptocurrencies" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "bip_utils-2.9.3-py3-none-any.whl", hash = "sha256:ee26b8417a576c7f89b847da37316db01a5cece1994c1609d37fbeefb91ad45e"}, {file = "bip_utils-2.9.3.tar.gz", hash = "sha256:72a8c95484b57e92311b0b2a3d5195b0ce4395c19a0b157d4a289e8b1300f48a"}, @@ -242,6 +299,8 @@ version = "3.0.0" description = "efficient arrays of booleans -- C extension" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "bitarray-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5ddbf71a97ad1d6252e6e93d2d703b624d0a5b77c153b12f9ea87d83e1250e0c"}, {file = "bitarray-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0e7f24a0b01e6e6a0191c50b06ca8edfdec1988d9d2b264d669d2487f4f4680"}, @@ -382,12 +441,27 @@ files = [ {file = "bitarray-3.0.0.tar.gz", hash = "sha256:a2083dc20f0d828a7cdf7a16b20dae56aab0f43dc4f347a3b3039f6577992b03"}, ] +[[package]] +name = "cachetools" +version = "5.5.0" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, + {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, +] + [[package]] name = "cbor2" version = "5.6.5" description = "CBOR (de)serializer with extensive tag support" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "cbor2-5.6.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e16c4a87fc999b4926f5c8f6c696b0d251b4745bc40f6c5aee51d69b30b15ca2"}, {file = "cbor2-5.6.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:87026fc838370d69f23ed8572939bd71cea2b3f6c8f8bb8283f573374b4d7f33"}, @@ -442,13 +516,15 @@ test = ["coverage (>=7)", "hypothesis", "pytest"] [[package]] name = "cdp-sdk" -version = "0.19.0" +version = "0.21.0" description = "CDP Python SDK" optional = false python-versions = "<4.0,>=3.10" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "cdp_sdk-0.19.0-py3-none-any.whl", hash = "sha256:fbb1176e4ff44df233598e71f80f5bccc5c53cc322eb670d35258b67ee2937e1"}, - {file = "cdp_sdk-0.19.0.tar.gz", hash = "sha256:e2f55668f16dfd3329353ddd2fe5bd9c0bd22b2ab0f66b1efa72007e13a71e29"}, + {file = "cdp_sdk-0.21.0-py3-none-any.whl", hash = "sha256:36a2ec372c79354133f142566674f6f5a21f474d31f378154a3b4e0e0089818a"}, + {file = "cdp_sdk-0.21.0.tar.gz", hash = "sha256:6d832189e84cec76c3353f52835ddf06789630325ca5f0ea1a48ad663b698e7d"}, ] [package.dependencies] @@ -463,13 +539,15 @@ web3 = ">=7.6.0,<8.0.0" [[package]] name = "certifi" -version = "2025.1.31" +version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, - {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, + {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, + {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] [[package]] @@ -478,6 +556,8 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -551,12 +631,27 @@ files = [ [package.dependencies] pycparser = "*" +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = false +python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + [[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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -658,6 +753,8 @@ version = "2.0.1" description = "Python bindings for C-KZG-4844" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ckzg-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b7f9ba6d215f8981c5545f952aac84875bd564a63da02fb22a3d1321662ecdc0"}, {file = "ckzg-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8fdec3ff96399acba9baeef9e1b0b5258c08f73245780e6c69f7b73def5e8d0a"}, @@ -757,15 +854,18 @@ files = [ [[package]] name = "coinbase-agentkit" -version = "0.1.4" +version = "0.1.6" description = "Coinbase AgentKit" optional = false python-versions = "^3.10" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [] develop = true [package.dependencies] -cdp-sdk = "0.19.0" +allora-sdk = "^0.2.0" +cdp-sdk = "0.21.0" pydantic = "^2.0" python-dotenv = "^1.0.1" requests = "^2.31.0" @@ -781,6 +881,8 @@ version = "0.1.0" description = "Coinbase AgentKit LangChain extension" optional = false python-versions = "^3.10" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [] develop = true @@ -799,6 +901,8 @@ version = "20.0.0" description = "Cross-platform Python CFFI bindings for libsecp256k1" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "coincurve-20.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d559b22828638390118cae9372a1bb6f6594f5584c311deb1de6a83163a0919b"}, {file = "coincurve-20.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33d7f6ebd90fcc550f819f7f2cce2af525c342aac07f0ccda46ad8956ad9d99b"}, @@ -865,6 +969,8 @@ 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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -876,6 +982,8 @@ version = "1.7" description = "CRC Generator" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "crcmod-1.7.tar.gz", hash = "sha256:dc7051a0db5f2bd48665a990d3ec1cc305a466a77358ca4492826f41f283601e"}, ] @@ -886,6 +994,8 @@ version = "44.0.1" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "cryptography-44.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009"}, {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f"}, @@ -939,6 +1049,8 @@ version = "1.0.1" description = "Cython implementation of Toolz: High performance functional utilities" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "(python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\") and implementation_name == \"cpython\"" 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"}, @@ -1048,12 +1160,27 @@ toolz = ">=0.8.0" [package.extras] cython = ["cython"] +[[package]] +name = "distlib" +version = "0.3.9" +description = "Distribution utilities" +optional = false +python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, + {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, +] + [[package]] name = "distro" version = "1.9.0" description = "Distro - an OS platform information API" optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, @@ -1065,6 +1192,8 @@ version = "0.19.0" description = "ECDSA cryptographic signature library (pure python)" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.6" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ecdsa-0.19.0-py2.py3-none-any.whl", hash = "sha256:2cea9b88407fdac7bbeca0833b189e4c9c53f2ef1e1eaa29f6224dbc809b707a"}, {file = "ecdsa-0.19.0.tar.gz", hash = "sha256:60eaad1199659900dd0af521ed462b793bbdf867432b3948e87416ae4caf6bf8"}, @@ -1083,6 +1212,8 @@ version = "1.4.1" description = "Ed25519 public-key signatures (BLAKE2b fork)" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ed25519-blake2b-1.4.1.tar.gz", hash = "sha256:731e9f93cd1ac1a64649575f3519a99ffe0bb1e4cf7bf5f5f0be513a39df7363"}, ] @@ -1093,6 +1224,8 @@ 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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -1115,6 +1248,8 @@ version = "0.13.5" description = "eth-account: Sign Ethereum transactions and messages with local private keys" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "eth_account-0.13.5-py3-none-any.whl", hash = "sha256:e43fd30c9a7fabb882b50e8c4c41d4486d2f3478ad97c66bb18cfcc872fdbec8"}, {file = "eth_account-0.13.5.tar.gz", hash = "sha256:010c9ce5f3d2688106cf9bfeb711bb8eaf0154ea6f85325f54fecea85c2b3759"}, @@ -1143,6 +1278,8 @@ version = "0.7.1" description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -1164,6 +1301,8 @@ 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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -1185,6 +1324,8 @@ version = "0.6.1" description = "eth-keys: Common API for Ethereum key operations" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "eth_keys-0.6.1-py3-none-any.whl", hash = "sha256:7deae4cd56e862e099ec58b78176232b931c4ea5ecded2f50c7b1ccbc10c24cf"}, {file = "eth_keys-0.6.1.tar.gz", hash = "sha256:a43e263cbcabfd62fa769168efc6c27b1f5603040e4de22bb84d12567e4fd962"}, @@ -1206,6 +1347,8 @@ version = "2.2.0" description = "eth-rlp: RLP definitions for common Ethereum objects in Python" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -1228,6 +1371,8 @@ version = "5.1.0" description = "eth-typing: Common type annotations for ethereum python packages" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "eth_typing-5.1.0-py3-none-any.whl", hash = "sha256:c0d6b93f5385aa84efc4b47ae2bd478da069bc0ffda8b67e0ccb573f43defd29"}, {file = "eth_typing-5.1.0.tar.gz", hash = "sha256:8581f212ee6252aaa285377a77620f6e5f6e16ac3f144c61f098fafd47967b1a"}, @@ -1247,6 +1392,8 @@ version = "5.2.0" description = "eth-utils: Common utility functions for python code that interacts with Ethereum" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "eth_utils-5.2.0-py3-none-any.whl", hash = "sha256:4d43eeb6720e89a042ad5b28d4b2111630ae764f444b85cbafb708d7f076da10"}, {file = "eth_utils-5.2.0.tar.gz", hash = "sha256:17e474eb654df6e18f20797b22c6caabb77415a996b3ba0f3cc8df3437463134"}, @@ -1269,6 +1416,8 @@ version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -1277,12 +1426,32 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "filelock" +version = "3.16.1" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +typing = ["typing-extensions (>=4.12.2)"] + [[package]] name = "frozenlist" version = "1.5.0" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, @@ -1384,6 +1553,8 @@ version = "3.1.1" description = "Lightweight in-process concurrent programming" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "(python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\") and python_version < \"3.14\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")" files = [ {file = "greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563"}, {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83"}, @@ -1470,6 +1641,8 @@ version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, @@ -1481,6 +1654,8 @@ version = "1.3.0" description = "hexbytes: Python `bytes` subclass that decodes hex, with a readable console output" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "hexbytes-1.3.0-py3-none-any.whl", hash = "sha256:83720b529c6e15ed21627962938dc2dec9bb1010f17bbbd66bf1e6a8287d522c"}, {file = "hexbytes-1.3.0.tar.gz", hash = "sha256:4a61840c24b0909a6534350e2d28ee50159ca1c9e89ce275fd31c110312cf684"}, @@ -1497,6 +1672,8 @@ version = "1.0.7" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, @@ -1518,6 +1695,8 @@ version = "0.28.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, @@ -1542,6 +1721,8 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -1556,6 +1737,8 @@ version = "0.8.2" description = "Fast iterable JSON parser." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "jiter-0.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ca8577f6a413abe29b079bc30f907894d7eb07a865c4df69475e868d73e71c7b"}, {file = "jiter-0.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b25bd626bde7fb51534190c7e3cb97cee89ee76b76d7585580e22f34f5e3f393"}, @@ -1641,6 +1824,8 @@ version = "1.33" description = "Apply JSON-Patches (RFC 6902)" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, @@ -1655,6 +1840,8 @@ version = "3.0.0" description = "Identify specific nodes in a JSON document (RFC 6901)" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, @@ -1666,6 +1853,8 @@ version = "0.3.18" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "langchain-0.3.18-py3-none-any.whl", hash = "sha256:1a6e629f02a25962aa5b16932e8f073248104a66804ed5af1f78618ad7c1d38d"}, {file = "langchain-0.3.18.tar.gz", hash = "sha256:311ac227a995545ff7c3f74c7767930c5349edef0b39f19d3105b86d39316b69"}, @@ -1709,6 +1898,8 @@ version = "0.3.34" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "langchain_core-0.3.34-py3-none-any.whl", hash = "sha256:a057ebeddd2158d3be14bde341b25640ddf958b6989bd6e47160396f5a8202ae"}, {file = "langchain_core-0.3.34.tar.gz", hash = "sha256:26504cf1e8e6c310adad907b890d4e3c147581cfa7434114f6dc1134fe4bc6d3"}, @@ -1732,6 +1923,8 @@ version = "0.2.14" description = "An integration package connecting OpenAI and LangChain" optional = false python-versions = "<4.0,>=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "langchain_openai-0.2.14-py3-none-any.whl", hash = "sha256:d232496662f79ece9a11caf7d798ba863e559c771bc366814f7688e0fe664fe8"}, {file = "langchain_openai-0.2.14.tar.gz", hash = "sha256:7a514f309e356b182a337c0ed36ab3fbe34d9834a235a3b85cb7f91ae775d978"}, @@ -1748,6 +1941,8 @@ version = "0.3.6" description = "LangChain text splitting utilities" optional = false python-versions = "<4.0,>=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "langchain_text_splitters-0.3.6-py3-none-any.whl", hash = "sha256:e5d7b850f6c14259ea930be4a964a65fa95d9df7e1dbdd8bad8416db72292f4e"}, {file = "langchain_text_splitters-0.3.6.tar.gz", hash = "sha256:c537972f4b7c07451df431353a538019ad9dadff7a1073ea363946cea97e1bee"}, @@ -1762,6 +1957,8 @@ version = "0.2.71" description = "Building stateful, multi-actor applications with LLMs" optional = false python-versions = "<4.0,>=3.9.0" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "langgraph-0.2.71-py3-none-any.whl", hash = "sha256:6cdcf23b37f6580ba93e75f909d1eaefbbf42cd0e0a98be5db17d2377a711362"}, {file = "langgraph-0.2.71.tar.gz", hash = "sha256:8cdce67f8b011d2d9df5996553fdcb450b4caa756e6940480617e16f1d7a67f3"}, @@ -1778,6 +1975,8 @@ version = "2.0.12" description = "Library with base interfaces for LangGraph checkpoint savers." optional = false python-versions = "<4.0.0,>=3.9.0" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "langgraph_checkpoint-2.0.12-py3-none-any.whl", hash = "sha256:37e45a9b06ee37b9fe705c1f96f72a4ca1730195ca9553f1c1f49a152dbf21ff"}, {file = "langgraph_checkpoint-2.0.12.tar.gz", hash = "sha256:1b7e4967b784e2b66dc38ff6840e929c658c47ee00c28cf0e354b95062060e89"}, @@ -1793,6 +1992,8 @@ version = "0.1.51" description = "SDK for interacting with LangGraph API" optional = false python-versions = "<4.0.0,>=3.9.0" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "langgraph_sdk-0.1.51-py3-none-any.whl", hash = "sha256:ce2b58466d1700d06149782ed113157a8694a6d7932c801f316cd13fab315fe4"}, {file = "langgraph_sdk-0.1.51.tar.gz", hash = "sha256:dea1363e72562cb1e82a2d156be8d5b1a69ff3fe8815eee0e1e7a2f423242ec1"}, @@ -1808,6 +2009,8 @@ version = "0.3.8" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = "<4.0,>=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "langsmith-0.3.8-py3-none-any.whl", hash = "sha256:fbb9dd97b0f090219447fca9362698d07abaeda1da85aa7cc6ec6517b36581b1"}, {file = "langsmith-0.3.8.tar.gz", hash = "sha256:97f9bebe0b7cb0a4f278e6ff30ae7d5ededff3883b014442ec6d7d575b02a0f1"}, @@ -1834,6 +2037,8 @@ version = "1.1.0" description = "MessagePack serializer" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "msgpack-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd"}, {file = "msgpack-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d"}, @@ -1907,6 +2112,8 @@ version = "6.1.0" description = "multidict implementation" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, @@ -2011,6 +2218,8 @@ version = "1.26.4" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\"" files = [ {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, @@ -2056,6 +2265,8 @@ version = "2.2.2" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" +groups = ["main"] +markers = "python_version >= \"3.12\"" files = [ {file = "numpy-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7079129b64cb78bdc8d611d1fd7e8002c0a2565da6a47c4df8062349fee90e3e"}, {file = "numpy-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ec6c689c61df613b783aeb21f945c4cbe6c51c28cb70aae8430577ab39f163e"}, @@ -2120,6 +2331,8 @@ version = "1.61.1" description = "The official Python library for the openai API" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "openai-1.61.1-py3-none-any.whl", hash = "sha256:72b0826240ce26026ac2cd17951691f046e5be82ad122d20a8e1b30ca18bd11e"}, {file = "openai-1.61.1.tar.gz", hash = "sha256:ce1851507218209961f89f3520e06726c0aa7d0512386f0f977e3ac3e4f2472e"}, @@ -2145,6 +2358,8 @@ version = "3.10.15" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "orjson-3.10.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:552c883d03ad185f720d0c09583ebde257e41b9521b74ff40e08b7dec4559c04"}, {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e3e8d438d02e4854f70bfdc03a6bcdb697358dbaa6bcd19cbe24d24ece1f8"}, @@ -2233,6 +2448,8 @@ version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, @@ -2244,6 +2461,8 @@ version = "0.10.0" description = "(Soon to be) the fastest pure-Python PEG parser I could muster" optional = false python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f"}, {file = "parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c"}, @@ -2252,12 +2471,49 @@ files = [ [package.dependencies] regex = ">=2022.3.15" +[[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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +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.2.1" description = "Accelerated property cache" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"}, {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"}, @@ -2349,6 +2605,8 @@ version = "0.2.1" description = "Python bindings for schnorrkel RUST crate" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "py_sr25519_bindings-0.2.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10489c399768dc4ac91c90a6c8da60aeb77a48b21a81944244d41b0d4c4be2f"}, {file = "py_sr25519_bindings-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8358a7b3048765008a79733447dfdcafdce3f66859c98634055fee6868252e12"}, @@ -2463,6 +2721,8 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -2474,6 +2734,8 @@ version = "3.21.0" description = "Cryptographic library for Python" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pycryptodome-3.21.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:dad9bf36eda068e89059d1f07408e397856be9511d7113ea4b586642a429a4fd"}, {file = "pycryptodome-3.21.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:a1752eca64c60852f38bb29e2c86fca30d7672c024128ef5d70cc15868fa10f4"}, @@ -2511,13 +2773,15 @@ files = [ [[package]] name = "pydantic" -version = "2.10.6" +version = "2.10.4" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, - {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, + {file = "pydantic-2.10.4-py3-none-any.whl", hash = "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d"}, + {file = "pydantic-2.10.4.tar.gz", hash = "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06"}, ] [package.dependencies] @@ -2535,6 +2799,8 @@ version = "2.27.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, @@ -2647,6 +2913,8 @@ version = "2.10.1" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, @@ -2664,6 +2932,8 @@ version = "1.5.0" description = "Python binding to the Networking and Cryptography (NaCl) library" optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, @@ -2684,12 +2954,35 @@ cffi = ">=1.4.1" docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] +[[package]] +name = "pyproject-api" +version = "1.8.0" +description = "API to interact with the python pyproject.toml based projects" +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "pyproject_api-1.8.0-py3-none-any.whl", hash = "sha256:3d7d347a047afe796fd5d1885b1e391ba29be7169bd2f102fcd378f04273d228"}, + {file = "pyproject_api-1.8.0.tar.gz", hash = "sha256:77b8049f2feb5d33eefcc21b57f1e279636277a8ac8ad6b5871037b243778496"}, +] + +[package.dependencies] +packaging = ">=24.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2024.8.6)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "pytest (>=8.3.3)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "setuptools (>=75.1)"] + [[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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -2704,6 +2997,8 @@ 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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -2718,6 +3013,8 @@ 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" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pyunormalize-16.0.0-py3-none-any.whl", hash = "sha256:c647d95e5d1e2ea9a2f448d1d95d8518348df24eab5c3fd32d2b5c3300a49152"}, {file = "pyunormalize-16.0.0.tar.gz", hash = "sha256:2e1dfbb4a118154ae26f70710426a52a364b926c9191f764601f5a8cb12761f7"}, @@ -2729,6 +3026,8 @@ version = "308" description = "Python for Window Extensions" optional = false python-versions = "*" +groups = ["main"] +markers = "(python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\") and platform_system == \"Windows\"" files = [ {file = "pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e"}, {file = "pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e"}, @@ -2756,6 +3055,8 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -2818,6 +3119,8 @@ version = "2024.11.6" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -2921,6 +3224,8 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -2942,6 +3247,8 @@ version = "1.0.0" description = "A utility belt for advanced users of python-requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, @@ -2956,6 +3263,8 @@ version = "4.1.0" description = "rlp: A package for Recursive Length Prefix encoding and decoding" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "rlp-4.1.0-py3-none-any.whl", hash = "sha256:8eca394c579bad34ee0b937aecb96a57052ff3716e19c7a578883e767bc5da6f"}, {file = "rlp-4.1.0.tar.gz", hash = "sha256:be07564270a96f3e225e2c107db263de96b5bc1f27722d2855bd3459a08e95a9"}, @@ -2976,6 +3285,8 @@ version = "0.7.4" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ruff-0.7.4-py3-none-linux_armv6l.whl", hash = "sha256:a4919925e7684a3f18e18243cd6bea7cfb8e968a6eaa8437971f681b7ec51478"}, {file = "ruff-0.7.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:cfb365c135b830778dda8c04fb7d4280ed0b984e1aec27f574445231e20d6c63"}, @@ -3003,6 +3314,8 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -3014,6 +3327,8 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -3025,6 +3340,8 @@ version = "2.0.38" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "SQLAlchemy-2.0.38-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5e1d9e429028ce04f187a9f522818386c8b076723cdbe9345708384f49ebcec6"}, {file = "SQLAlchemy-2.0.38-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b87a90f14c68c925817423b0424381f0e16d80fc9a1a1046ef202ab25b19a444"}, @@ -3120,6 +3437,8 @@ version = "9.0.0" description = "Retry code until it succeeds" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "tenacity-9.0.0-py3-none-any.whl", hash = "sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539"}, {file = "tenacity-9.0.0.tar.gz", hash = "sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b"}, @@ -3135,6 +3454,8 @@ version = "0.8.0" description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "tiktoken-0.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b07e33283463089c81ef1467180e3e00ab00d46c2c4bbcef0acab5f771d6695e"}, {file = "tiktoken-0.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9269348cb650726f44dd3bbb3f9110ac19a8dcc8f54949ad3ef652ca22a38e21"}, @@ -3176,23 +3497,99 @@ requests = ">=2.26.0" [package.extras] blobfile = ["blobfile (>=2)"] +[[package]] +name = "tomli" +version = "2.2.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\"" +files = [ + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, +] + [[package]] name = "toolz" version = "1.0.0" description = "List processing tools and functional utilities" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "(python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\") and (implementation_name == \"cpython\" or implementation_name == \"pypy\")" 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 = "tox" +version = "4.23.2" +description = "tox is a generic virtualenv management and test command line tool" +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "tox-4.23.2-py3-none-any.whl", hash = "sha256:452bc32bb031f2282881a2118923176445bac783ab97c874b8770ab4c3b76c38"}, + {file = "tox-4.23.2.tar.gz", hash = "sha256:86075e00e555df6e82e74cfc333917f91ecb47ffbc868dcafbd2672e332f4a2c"}, +] + +[package.dependencies] +cachetools = ">=5.5" +chardet = ">=5.2" +colorama = ">=0.4.6" +filelock = ">=3.16.1" +packaging = ">=24.1" +platformdirs = ">=4.3.6" +pluggy = ">=1.5" +pyproject-api = ">=1.8" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.12.2", markers = "python_version < \"3.11\""} +virtualenv = ">=20.26.6" + +[package.extras] +test = ["devpi-process (>=1.0.2)", "pytest (>=8.3.3)", "pytest-mock (>=3.14)"] + [[package]] name = "tqdm" version = "4.67.1" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, @@ -3214,6 +3611,8 @@ version = "2.32.0.20241016" description = "Typing stubs for requests" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "types-requests-2.32.0.20241016.tar.gz", hash = "sha256:0d9cad2f27515d0e3e3da7134a1b6f28fb97129d86b867f24d9c726452634d95"}, {file = "types_requests-2.32.0.20241016-py3-none-any.whl", hash = "sha256:4195d62d6d3e043a4eaaf08ff8a62184584d2e8684e9d2aa178c7915a7da3747"}, @@ -3228,6 +3627,8 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -3239,6 +3640,8 @@ version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, @@ -3250,12 +3653,36 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "virtualenv" +version = "20.28.1" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" +files = [ + {file = "virtualenv-20.28.1-py3-none-any.whl", hash = "sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb"}, + {file = "virtualenv-20.28.1.tar.gz", hash = "sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + [[package]] name = "web3" version = "7.8.0" description = "web3: A Python library for interacting with Ethereum" optional = false python-versions = "<4,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "web3-7.8.0-py3-none-any.whl", hash = "sha256:c8771b3d8772f7104a0462804449beb57d36cef7bd8b411140f95a92fc46b559"}, {file = "web3-7.8.0.tar.gz", hash = "sha256:712bc9fd6b1ef6e467ee24c25b581e1951cab2cba17f9f548f12587734f2c857"}, @@ -3289,6 +3716,8 @@ version = "13.1" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" 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"}, @@ -3384,6 +3813,8 @@ version = "1.18.3" description = "Yet another URL library" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, @@ -3480,6 +3911,8 @@ version = "0.23.0" description = "Zstandard bindings for Python" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" or python_version == \"3.11\" or python_version >= \"3.12\"" files = [ {file = "zstandard-0.23.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bf0a05b6059c0528477fba9054d09179beb63744355cab9f38059548fedd46a9"}, {file = "zstandard-0.23.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fc9ca1c9718cb3b06634c7c8dec57d24e9438b2aa9a0f02b8bb36bf478538880"}, @@ -3587,6 +4020,6 @@ cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\ cffi = ["cffi (>=1.11)"] [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = "^3.10" -content-hash = "35259a6fe2996705ff7da319dc74d5002d7668c1d9ec42e64fa7b4f614df02a4" +content-hash = "c2f16984e8190f5b58fa2473ce099786feb2e7b2b836a2b1bf2848bdeb2fa9a1" diff --git a/python/examples/langchain-cdp-chatbot/pyproject.toml b/python/examples/langchain-cdp-chatbot/pyproject.toml index 2135e8e08..3b297bffb 100644 --- a/python/examples/langchain-cdp-chatbot/pyproject.toml +++ b/python/examples/langchain-cdp-chatbot/pyproject.toml @@ -13,6 +13,7 @@ langchain-openai = "^0.2.4" langgraph = "^0.2.39" coinbase-agentkit = { path = "../../../python/coinbase-agentkit", develop = true } coinbase-agentkit-langchain = { path = "../../../python/framework-extensions/langchain", develop = true } +allora-sdk = "^0.2.0" [tool.poetry.group.dev.dependencies] ruff = "^0.7.1"