Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hummingbot-api-openapi.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion hummingbot_api_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
from .sync_client import SyncHummingbotAPIClient
from .ws import MarketDataWebSocket, ExecutorsWebSocket, WebSocketRouter

__version__ = "1.5.7"
__version__ = "1.5.8"
__all__ = ["HummingbotAPIClient", "SyncHummingbotAPIClient", "MarketDataWebSocket", "ExecutorsWebSocket", "WebSocketRouter"]
11 changes: 0 additions & 11 deletions hummingbot_api_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
GatewayCLMMRouter,
MarketDataRouter,
PortfolioRouter,
RateOracleRouter,
ScriptsRouter,
TradingRouter
)
Expand Down Expand Up @@ -49,7 +48,6 @@ def __init__(
self._gateway_amm: Optional[GatewayAMMRouter] = None
self._market_data: Optional[MarketDataRouter] = None
self._portfolio: Optional[PortfolioRouter] = None
self._rate_oracle: Optional[RateOracleRouter] = None
self._scripts: Optional[ScriptsRouter] = None
self._trading: Optional[TradingRouter] = None
self._ws: Optional[WebSocketRouter] = None
Expand Down Expand Up @@ -77,7 +75,6 @@ async def init(self) -> None:
self._gateway_amm = GatewayAMMRouter(self._session, self.base_url)
self._market_data = MarketDataRouter(self._session, self.base_url)
self._portfolio = PortfolioRouter(self._session, self.base_url)
self._rate_oracle = RateOracleRouter(self._session, self.base_url)
self._scripts = ScriptsRouter(self._session, self.base_url)
self._trading = TradingRouter(self._session, self.base_url)
self._ws = WebSocketRouter(self._session, self.base_url, self._username, self._password)
Expand All @@ -101,7 +98,6 @@ async def close(self) -> None:
self._gateway_amm = None
self._market_data = None
self._portfolio = None
self._rate_oracle = None
self._scripts = None
self._trading = None
self._ws = None
Expand Down Expand Up @@ -204,13 +200,6 @@ def portfolio(self) -> PortfolioRouter:
raise RuntimeError("Client not initialized. Call await client.init() first.")
return self._portfolio

@property
def rate_oracle(self) -> RateOracleRouter:
"""Access the rate oracle router."""
if self._rate_oracle is None:
raise RuntimeError("Client not initialized. Call await client.init() first.")
return self._rate_oracle

@property
def scripts(self) -> ScriptsRouter:
"""Access the scripts router."""
Expand Down
2 changes: 0 additions & 2 deletions hummingbot_api_client/routers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from .gateway_amm import GatewayAMMRouter
from .market_data import MarketDataRouter
from .portfolio import PortfolioRouter
from .rate_oracle import RateOracleRouter
from .scripts import ScriptsRouter
from .trading import TradingRouter

Expand All @@ -33,7 +32,6 @@
"GatewayAMMRouter",
"MarketDataRouter",
"PortfolioRouter",
"RateOracleRouter",
"ScriptsRouter",
"TradingRouter"
]
6 changes: 4 additions & 2 deletions hummingbot_api_client/routers/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import Optional
from typing import Optional, Union
import aiohttp

QueryParams = Union[dict, list]


class BaseRouter:
def __init__(self, session: aiohttp.ClientSession, base_url: str):
Expand Down Expand Up @@ -57,7 +59,7 @@ async def _get(self, path: str, params: Optional[dict] = None):
)
return await response.json()

async def _post(self, path: str, json: Optional[dict] = None, params: Optional[dict] = None) -> dict:
async def _post(self, path: str, json: Optional[dict] = None, params: Optional[QueryParams] = None) -> dict:
"""Perform a POST request and return JSON response."""
url = f"{self.base_url}/{path.lstrip('/')}"
async with self.session.post(url, json=json, params=params) as response:
Expand Down
30 changes: 0 additions & 30 deletions hummingbot_api_client/routers/bot_orchestration.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,36 +88,6 @@ async def stop_bot(
}
return await self._post("/bot-orchestration/stop-bot", json=stop_bot_action)

async def import_strategy_for_bot(
self,
bot_name: str,
strategy: str
) -> Dict[str, Any]:
"""
Import a strategy configuration for a bot.

Args:
bot_name: Name of the bot instance
strategy: Strategy name to import
"""
data = {"strategy": strategy}
return await self._post(f"/bot-orchestration/{bot_name}/import-strategy", json=data)

async def configure_bot(
self,
bot_name: str,
params: Dict[str, Any]
) -> Dict[str, Any]:
"""
Configure bot parameters.

Args:
bot_name: Name of the bot instance
params: Dictionary of configuration parameters
"""
data = {"params": params}
return await self._post(f"/bot-orchestration/{bot_name}/config", json=data)

async def stop_and_archive_bot(
self,
bot_name: str,
Expand Down
40 changes: 26 additions & 14 deletions hummingbot_api_client/routers/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async def is_running(self) -> bool:

async def get_available_images(self, image_name: Optional[str]) -> Dict[str, Any]:
"""Get available Docker images matching the specified name."""
return await self._get(f"/docker/available-images", params={"image_name": image_name})
return await self._get("/docker/available-images/", params={"image_name": image_name})

async def get_active_containers(self, name_filter: Optional[str] = None) -> Dict[str, Any]:
"""Get all currently active (running) Docker containers."""
Expand All @@ -29,27 +29,39 @@ async def clean_exited_containers(self) -> Dict[str, Any]:
return await self._post("/docker/clean-exited-containers")

# Container Management
async def get_container_status(self, container_name: str) -> Dict[str, Any]:
"""Get detailed status information for a specific container."""
return await self._get(f"/docker/container/{container_name}/status")

#
# There is no per-container status route. Read a container's state from
# get_active_containers() / get_exited_containers(), both of which take a
# name_filter.
async def start_container(self, container_name: str) -> Dict[str, Any]:
"""Start a stopped container."""
return await self._post(f"/docker/container/{container_name}/start")
return await self._post(f"/docker/start-container/{container_name}")

async def stop_container(self, container_name: str) -> Dict[str, Any]:
"""Stop a running container."""
return await self._post(f"/docker/container/{container_name}/stop")

async def remove_container(self, container_name: str, force: bool = False) -> Dict[str, Any]:
"""Remove a container."""
params = {"force": force} if force else None
return await self._delete(f"/docker/container/{container_name}", params=params)
return await self._post(f"/docker/stop-container/{container_name}")

async def remove_container(
self,
container_name: str,
archive_locally: bool = True,
s3_bucket: Optional[str] = None,
) -> Dict[str, Any]:
"""Remove a Hummingbot container, archiving its bot data first.

The route only accepts containers named `hummingbot-*`: removal is bound up
with archiving the instance's data, which only those have.
"""
params: Dict[str, Any] = {"archive_locally": archive_locally}
if s3_bucket:
params["s3_bucket"] = s3_bucket
return await self._post(f"/docker/remove-container/{container_name}", params=params)

# Image Management
async def pull_image(self, image_name: str, tag: str = "latest") -> Dict[str, Any]:
"""Pull a Docker image from registry."""
return await self._post("/docker/pull-image/", json={"name": image_name, "tag": tag})
# The route takes one `image_name` carrying the tag, not a name/tag pair.
return await self._post("/docker/pull-image/", json={"image_name": f"{image_name}:{tag}"})

async def get_pull_status(self) -> Dict[str, Any]:
"""Get the status of image pull operations."""
Expand Down
61 changes: 0 additions & 61 deletions hummingbot_api_client/routers/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,67 +160,6 @@ async def list_pools(
params={"connector_name": connector_name, "network": network}
)

async def add_pool(
self,
connector_name: str,
pool_type: str,
network: str,
base: str,
quote: str,
address: str
) -> Dict[str, Any]:
"""
Add a custom liquidity pool.

Args:
connector_name: DEX connector name
pool_type: Type of pool
network: Network name
base: Base token symbol
quote: Quote token symbol
address: Pool address
"""
pool_data = {
"connector_name": connector_name,
"type": pool_type,
"network": network,
"base": base,
"quote": quote,
"address": address
}
return await self._post("/gateway/pools", json=pool_data)

async def delete_pool(
self,
connector: str,
network: str,
pool_type: str,
address: str
) -> Dict[str, Any]:
"""
Delete a liquidity pool from Gateway's pool list.

Args:
connector: DEX connector (e.g., 'meteora', 'raydium', 'uniswap')
network: Network name (e.g., 'mainnet-beta', 'mainnet')
pool_type: Pool type (e.g., 'CLMM', 'AMM')
address: Pool contract address to remove

Example:
await client.gateway.delete_pool(
connector='meteora',
network='mainnet-beta',
pool_type='CLMM',
address='2sf5NYcY4zUPXUSmG6f66mskb24t5F8S11pC1Nz5nQT3'
)
"""
params = {
"connector_name": connector,
"network": network,
"pool_type": pool_type.lower() # Gateway expects lowercase (amm, clmm)
}
return await self._delete(f"/gateway/pools/{address}", params=params)

# ============================================
# Networks (Primary Endpoints)
# ============================================
Expand Down
Loading