Skip to content

Commit

Permalink
feat: Add Python implementation of 1inch plugin (#218)
Browse files Browse the repository at this point in the history
* feat: Add Python implementation of 1inch plugin

- Create Python plugin structure mirroring coingecko plugin
- Implement get_balances functionality from TypeScript version
- Add proper parameter validation and error handling
- Include documentation and configuration details

Co-Authored-By: Agus Armellini Fischer <[email protected]>

* Update pyproject.toml

* refactor: rename package to goat-plugin-1inch and update plugin structure

- Rename package from goat-plugin-oneinch to goat-plugin-1inch
- Update directory structure from oneinch to inch1
- Update __init__.py to match coingecko plugin structure
- Add OneInchPluginOptions and OneInchPlugin classes

Co-Authored-By: Agus Armellini Fischer <[email protected]>

* Update __init__.py

---------

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
3 people authored Jan 13, 2025
1 parent e5c84ec commit 7d63e9e
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 0 deletions.
52 changes: 52 additions & 0 deletions python/src/plugins/1inch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# 1inch Plugin for GOAT

This plugin provides integration with the 1inch API for the GOAT SDK.

## Features

- Get token balances and allowances for a wallet address on a specific chain

## Installation

```bash
pip install goat-plugin-1inch
```

## Usage

```python
from goat_plugins.inch1 import OneInchService

# Initialize the service with your API key
service = OneInchService(api_key="your_api_key")

# Get balances for a wallet
balances = await service.get_aggregated_balances({
"wallet_address": "0x...",
"chain_id": 1 # Ethereum mainnet
})
```

## Configuration

The plugin requires a 1inch API key to function. You can obtain one from the [1inch Developer Portal](https://portal.1inch.dev/).

Set your API key when initializing the service:

```python
service = OneInchService(api_key="your_api_key")
```

## Development

To set up the development environment:

1. Clone the repository
2. Install dependencies with Poetry:
```bash
poetry install
```
3. Run tests:
```bash
poetry run pytest
```
21 changes: 21 additions & 0 deletions python/src/plugins/1inch/goat_plugins/inch1/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from dataclasses import dataclass

from goat.classes.plugin_base import PluginBase
from .service import OneInchService


@dataclass
class OneInchPluginOptions:
api_key: str


class OneInchPlugin(PluginBase):
def __init__(self, options: OneInchPluginOptions):
super().__init__("1inch", [OneInchService(options.api_key)])

def supports_chain(self, chain) -> bool:
return True


def inch1(options: OneInchPluginOptions) -> OneInchPlugin:
return OneInchPlugin(options)
12 changes: 12 additions & 0 deletions python/src/plugins/1inch/goat_plugins/inch1/parameters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from pydantic import BaseModel, Field
from typing import Optional

class GetBalancesParameters(BaseModel):
wallet_address: str = Field(
...,
description="The wallet address to check balances for"
)
chain_id: int = Field(
1, # Default to Ethereum mainnet
description="The chain ID to query balances on (e.g., 1 for Ethereum mainnet)"
)
36 changes: 36 additions & 0 deletions python/src/plugins/1inch/goat_plugins/inch1/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import aiohttp
from typing import Optional
from goat.decorators.tool import Tool
from .parameters import GetBalancesParameters

class OneInchService:
def __init__(self, api_key: Optional[str] = None):
self.api_key = api_key
self.base_url = "https://api.1inch.dev"

@Tool({
"name": "1inch.get_balances",
"description": "Get the balances of a wallet address on a specific chain",
"parameters_schema": GetBalancesParameters
})
async def get_aggregated_balances(self, parameters: dict):
"""Get token balances and allowances for a wallet address on a specific chain."""
wallet_address = parameters.get("wallet_address")
if not wallet_address:
raise ValueError("wallet_address is required")

chain_id = parameters.get("chain_id", 1) # Default to Ethereum mainnet

url = f"{self.base_url}/balance/v1.2/{chain_id}/balances/{wallet_address}"

headers = {
"Accept": "application/json"
}
if self.api_key:
headers["Authorization"] = f"Bearer {self.api_key}"

async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers) as response:
if not response.ok:
raise Exception(f"Failed to fetch balances: {response.status} {await response.text()}")
return await response.json()
43 changes: 43 additions & 0 deletions python/src/plugins/1inch/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[tool.poetry]
name = "goat-plugin-1inch"
version = "0.1.0"
description = "1inch plugin for GOAT SDK"
authors = ["GOAT SDK Team"]
readme = "README.md"
keywords = ["goat", "sdk", "web3", "agents", "ai", "1inch"]
homepage = "https://ohmygoat.dev/"
repository = "https://github.com/goat-sdk/goat"
packages = [
{ include = "goat_plugins/inch1" },
]

[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"

0 comments on commit 7d63e9e

Please sign in to comment.