-
Notifications
You must be signed in to change notification settings - Fork 163
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add Python implementation of Allora plugin (#217)
* feat: Add Python implementation of Allora plugin - Create Python version of Allora plugin with same functionality as TypeScript version - Implement price prediction functionality for BTC and ETH - Support 5m and 8h timeframes - Match CoinGecko plugin structure - Add Poetry build configuration Co-Authored-By: Agus Armellini Fischer <[email protected]> * chore: add changeset for allora python plugin Co-Authored-By: Agus Armellini Fischer <[email protected]> * Delete .changeset/allora-python-plugin.md --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Agus Armellini Fischer <[email protected]> Co-authored-by: Agus <[email protected]>
- Loading branch information
1 parent
e7223f1
commit e5c84ec
Showing
4 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from dataclasses import dataclass | ||
from typing import Optional | ||
|
||
from goat.classes.plugin_base import PluginBase | ||
from .service import AlloraService | ||
|
||
|
||
@dataclass | ||
class AlloraPluginOptions: | ||
api_key: Optional[str] = None | ||
api_root: str = "https://api.upshot.xyz/v2/allora" | ||
|
||
|
||
class AlloraPlugin(PluginBase): | ||
def __init__(self, options: AlloraPluginOptions): | ||
super().__init__("allora", [AlloraService(options.api_key, options.api_root)]) | ||
|
||
def supports_chain(self, chain) -> bool: | ||
return True | ||
|
||
|
||
def allora(options: AlloraPluginOptions) -> AlloraPlugin: | ||
return AlloraPlugin(options) |
21 changes: 21 additions & 0 deletions
21
python/src/plugins/allora/goat_plugins/allora/parameters.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from pydantic import BaseModel, Field | ||
from enum import Enum | ||
|
||
|
||
class AlloraPricePredictionToken(str, Enum): | ||
BTC = "BTC" | ||
ETH = "ETH" | ||
|
||
|
||
class AlloraPricePredictionTimeframe(str, Enum): | ||
FIVE_MIN = "5m" | ||
EIGHT_HOUR = "8h" | ||
|
||
|
||
class GetAlloraPricePredictionParameters(BaseModel): | ||
ticker: AlloraPricePredictionToken = Field( | ||
description="The ticker of the currency for which to fetch a price prediction (BTC or ETH)." | ||
) | ||
timeframe: AlloraPricePredictionTimeframe = Field( | ||
description='The timeframe for the prediction (currently, either "5m" or "8h").' | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import aiohttp | ||
from typing import Optional | ||
from goat.decorators.tool import Tool | ||
from .parameters import GetAlloraPricePredictionParameters, AlloraPricePredictionToken, AlloraPricePredictionTimeframe | ||
|
||
|
||
class AlloraService: | ||
def __init__(self, api_key: Optional[str] = None, api_root: str = "https://api.upshot.xyz/v2/allora"): | ||
self.api_key = api_key | ||
self.api_root = api_root.rstrip('/') # Remove trailing slash if present | ||
|
||
@Tool({ | ||
"description": "Fetch a future price prediction for BTC or ETH for a given timeframe (5m or 8h)", | ||
"parameters_schema": GetAlloraPricePredictionParameters | ||
}) | ||
async def get_price_prediction(self, parameters: dict): | ||
"""Fetch a future price prediction for a crypto asset from Allora Network""" | ||
# Default to ethereum-11155111 (Sepolia) as in TypeScript version | ||
signature_format = "ethereum-11155111" | ||
|
||
headers = { | ||
"Content-Type": "application/json", | ||
"Accept": "application/json" | ||
} | ||
if self.api_key: | ||
headers["x-api-key"] = self.api_key | ||
|
||
# Extract parameters | ||
ticker = parameters["ticker"] | ||
timeframe = parameters["timeframe"] | ||
|
||
# Construct URL following TypeScript pattern | ||
url = f"{self.api_root}/consumer/price/{signature_format}/{ticker}/{timeframe}" | ||
|
||
async with aiohttp.ClientSession() as session: | ||
async with session.get(url, headers=headers) as response: | ||
if not response.ok: | ||
raise Exception( | ||
f"Allora plugin: error requesting price prediction: url={url} " | ||
f"status={response.status} body={await response.text()}" | ||
) | ||
|
||
data = await response.json() | ||
|
||
# Validate response structure | ||
if not data.get("data", {}).get("inference_data"): | ||
raise Exception(f"API response missing data: {data}") | ||
|
||
return data["data"]["inference_data"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
[tool.poetry] | ||
name = "goat-sdk-plugin-allora" | ||
version = "0.1.0" | ||
description = "Goat plugin for Allora Network price predictions" | ||
authors = ["GOAT SDK Team"] | ||
readme = "README.md" | ||
keywords = ["goat", "sdk", "web3", "agents", "ai", "allora", "prediction"] | ||
homepage = "https://ohmygoat.dev/" | ||
repository = "https://github.com/goat-sdk/goat" | ||
packages = [ | ||
{ include = "goat_plugins/allora" }, | ||
] | ||
|
||
[tool.poetry.dependencies] | ||
python = "^3.10" | ||
aiohttp = "^3.8.6" | ||
goat-sdk = "^0.1.1" | ||
|
||
[tool.poetry.group.test.dependencies] | ||
pytest = "^8.3.4" | ||
pytest-asyncio = "^0.25.0" | ||
|
||
[tool.poetry.urls] | ||
"Bug Tracker" = "https://github.com/goat-sdk/goat/issues" | ||
|
||
[tool.pytest.ini_options] | ||
addopts = [ | ||
"--import-mode=importlib", | ||
] | ||
pythonpath = "src" | ||
asyncio_default_fixture_loop_scope = "function" | ||
|
||
[build-system] | ||
requires = ["poetry-core"] | ||
build-backend = "poetry.core.masonry.api" | ||
|
||
[tool.poetry.group.dev.dependencies] | ||
ruff = "^0.8.6" | ||
goat-sdk = { path = "../../goat-sdk", develop = true } | ||
|
||
[tool.ruff] | ||
line-length = 120 | ||
target-version = "py312" |