From c7f6b1aad131cf234e34e4a47fc09977a1deeba8 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Tue, 28 Apr 2026 09:29:47 -0700 Subject: [PATCH 1/3] feat: add network pool endpoints and executor logs Gateway Router: - Add get_network_pools() for network-based pool queries - Add add_network_pool() for adding pools by network_id - Add delete_network_pool() for removing pools by network_id Executors Router: - Add get_executor_logs() for fetching executor log entries These changes align with hummingbot-api updates that organize pools by network (chain-network format) instead of by connector. Co-Authored-By: Claude Opus 4.5 --- hummingbot_api_client/routers/executors.py | 26 +++++ hummingbot_api_client/routers/gateway.py | 113 +++++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/hummingbot_api_client/routers/executors.py b/hummingbot_api_client/routers/executors.py index 9295199..44f6a05 100644 --- a/hummingbot_api_client/routers/executors.py +++ b/hummingbot_api_client/routers/executors.py @@ -149,6 +149,32 @@ async def get_executor(self, executor_id: str) -> Dict[str, Any]: """ return await self._get(f"/executors/{executor_id}") + async def get_executor_logs( + self, + executor_id: str, + limit: int = 100, + level: Optional[str] = None + ) -> Dict[str, Any]: + """ + Get logs for a specific executor. + + Args: + executor_id: The executor ID to get logs for + limit: Maximum number of log entries to return (default 100) + level: Filter by log level (e.g., 'INFO', 'WARNING', 'ERROR') + + Returns: + Executor log entries + + Example: + logs = await client.executors.get_executor_logs("exec_123", limit=50) + logs = await client.executors.get_executor_logs("exec_123", level="ERROR") + """ + params = {"limit": limit} + if level is not None: + params["level"] = level + return await self._get(f"/executors/{executor_id}/logs", params=params) + async def stop_executor( self, executor_id: str, diff --git a/hummingbot_api_client/routers/gateway.py b/hummingbot_api_client/routers/gateway.py index 01d36cd..b3026bb 100644 --- a/hummingbot_api_client/routers/gateway.py +++ b/hummingbot_api_client/routers/gateway.py @@ -304,6 +304,119 @@ async def delete_token( """ return await self._delete(f"/gateway/networks/{network_id}/tokens/{token_address}") + # ============================================ + # Network Pools (Primary Pool Endpoints) + # ============================================ + + async def get_network_pools( + self, + network_id: str, + connector: Optional[str] = None, + pool_type: Optional[str] = None, + search: Optional[str] = None + ) -> Dict[str, Any]: + """ + Get pools for a specific network. + + Args: + network_id: Network ID in format 'chain-network' (e.g., 'solana-mainnet-beta') + connector: Optional filter by connector (e.g., 'raydium', 'meteora', 'uniswap') + pool_type: Optional filter by type ('amm' or 'clmm') + search: Optional search by trading pair or address + + Example: + await client.gateway.get_network_pools( + network_id='solana-mainnet-beta', + connector='raydium', + pool_type='clmm' + ) + """ + params = {} + if connector: + params["connector"] = connector + if pool_type: + params["pool_type"] = pool_type.lower() + if search: + params["search"] = search + return await self._get(f"/gateway/networks/{network_id}/pools", params=params or None) + + async def add_network_pool( + self, + network_id: str, + connector_name: str, + pool_type: str, + address: str, + base: Optional[str] = None, + quote: Optional[str] = None, + base_address: Optional[str] = None, + quote_address: Optional[str] = None, + fee_pct: Optional[float] = None + ) -> Dict[str, Any]: + """ + Add a pool to a specific network. + + Args: + network_id: Network ID in format 'chain-network' (e.g., 'solana-mainnet-beta') + connector_name: DEX connector name (e.g., 'raydium', 'meteora') + pool_type: Pool type ('amm' or 'clmm') + address: Pool contract address + base: Optional base token symbol + quote: Optional quote token symbol + base_address: Optional base token address + quote_address: Optional quote token address + fee_pct: Optional fee percentage + + Example: + await client.gateway.add_network_pool( + network_id='solana-mainnet-beta', + connector_name='raydium', + pool_type='clmm', + address='58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2' + ) + """ + pool_data = { + "connector_name": connector_name, + "type": pool_type.lower(), + "address": address + } + if base: + pool_data["base"] = base + if quote: + pool_data["quote"] = quote + if base_address: + pool_data["base_address"] = base_address + if quote_address: + pool_data["quote_address"] = quote_address + if fee_pct is not None: + pool_data["fee_pct"] = fee_pct + + return await self._post(f"/gateway/networks/{network_id}/pools", json=pool_data) + + async def delete_network_pool( + self, + network_id: str, + address: str, + pool_type: Optional[str] = None + ) -> Dict[str, Any]: + """ + Delete a pool from a specific network. + + Args: + network_id: Network ID in format 'chain-network' (e.g., 'solana-mainnet-beta') + address: Pool contract address to remove + pool_type: Optional pool type ('amm' or 'clmm') + + Example: + await client.gateway.delete_network_pool( + network_id='solana-mainnet-beta', + address='58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2' + ) + """ + params = {} + if pool_type: + params["pool_type"] = pool_type.lower() + return await self._delete(f"/gateway/networks/{network_id}/pools/{address}", params=params or None) + # ============================================ # Wallets # ============================================ From 2fca7a717c3acff5a41980abc1cf5b78a2f4a5b2 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Wed, 6 May 2026 16:52:27 -0700 Subject: [PATCH 2/3] Add save_network_token/pool and set_default_gateway_wallet methods - Add save_network_token() to auto-fetch and save token details - Add save_network_pool() to auto-fetch and save pool details - Add set_default_gateway_wallet() for setting default wallet per chain Co-Authored-By: Claude Opus 4.5 --- hummingbot_api_client/routers/accounts.py | 22 ++++++++++- hummingbot_api_client/routers/gateway.py | 46 +++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/hummingbot_api_client/routers/accounts.py b/hummingbot_api_client/routers/accounts.py index 5fdafde..7f5b144 100644 --- a/hummingbot_api_client/routers/accounts.py +++ b/hummingbot_api_client/routers/accounts.py @@ -79,4 +79,24 @@ async def remove_gateway_wallet( async def list_gateway_wallets(self) -> List[Dict]: """List all wallets.""" - return await self._get("/accounts/gateway/wallets/") \ No newline at end of file + return await self._get("/accounts/gateway/wallets/") + + async def set_default_gateway_wallet( + self, + chain: str, + address: str + ) -> Dict[str, Any]: + """ + Set a wallet as the default for a chain. + + Args: + chain: Blockchain chain (e.g., 'solana', 'ethereum') + address: Wallet address to set as default + + Returns: + Success message with chain and address + """ + return await self._post( + "/accounts/gateway/wallet/set-default", + json={"chain": chain, "address": address} + ) \ No newline at end of file diff --git a/hummingbot_api_client/routers/gateway.py b/hummingbot_api_client/routers/gateway.py index b3026bb..a2f7385 100644 --- a/hummingbot_api_client/routers/gateway.py +++ b/hummingbot_api_client/routers/gateway.py @@ -304,6 +304,29 @@ async def delete_token( """ return await self._delete(f"/gateway/networks/{network_id}/tokens/{token_address}") + async def save_network_token( + self, + network_id: str, + token_address: str + ) -> Dict[str, Any]: + """ + Save a token by address - auto-fetches token info from GeckoTerminal. + + This is the simplest way to add a token. Just provide the address and + the API will fetch symbol, name, and decimals automatically. + + Args: + network_id: Network ID in format 'chain-network' (e.g., 'solana-mainnet-beta') + token_address: Token contract address + + Example: + await client.gateway.save_network_token( + network_id='solana-mainnet-beta', + token_address='9QFfgxdSqH5zT7j6rZb1y6SZhw2aFtcQu2r6BuYpump' + ) + """ + return await self._post(f"/gateway/networks/{network_id}/tokens/save/{token_address}") + # ============================================ # Network Pools (Primary Pool Endpoints) # ============================================ @@ -417,6 +440,29 @@ async def delete_network_pool( params["pool_type"] = pool_type.lower() return await self._delete(f"/gateway/networks/{network_id}/pools/{address}", params=params or None) + async def save_network_pool( + self, + network_id: str, + pool_address: str + ) -> Dict[str, Any]: + """ + Save a pool by address - auto-fetches pool info from the blockchain. + + This is the simplest way to add a pool. Just provide the address and + the API will fetch connector, type, tokens, and fees automatically. + + Args: + network_id: Network ID in format 'chain-network' (e.g., 'solana-mainnet-beta') + pool_address: Pool contract address + + Example: + await client.gateway.save_network_pool( + network_id='solana-mainnet-beta', + pool_address='58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2' + ) + """ + return await self._post(f"/gateway/networks/{network_id}/pools/save/{pool_address}") + # ============================================ # Wallets # ============================================ From 628d65f8f08cc9ce9bf7b35046f133370af5014c Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Thu, 7 May 2026 19:33:31 -0700 Subject: [PATCH 3/3] feat(gateway): add API keys management methods - Add get_api_keys() to retrieve all configured API keys - Add update_api_keys() to update API keys Co-Authored-By: Claude Opus 4.5 --- hummingbot_api_client/routers/gateway.py | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/hummingbot_api_client/routers/gateway.py b/hummingbot_api_client/routers/gateway.py index a2f7385..fe2f033 100644 --- a/hummingbot_api_client/routers/gateway.py +++ b/hummingbot_api_client/routers/gateway.py @@ -91,6 +91,40 @@ async def update_connector_config( """ return await self._post(f"/gateway/connectors/{connector_name}", json=config_updates) + # ============================================ + # API Keys + # ============================================ + + async def get_api_keys(self) -> Dict[str, Any]: + """ + Get all configured API keys from Gateway. + + Returns a dict mapping provider name to API key value. + + Example: + api_keys = await client.gateway.get_api_keys() + # Returns: {"helius": "abc123", "infura": "xyz789", "coingecko": "...", "etherscan": ""} + """ + return await self._get("/gateway/apiKeys") + + async def update_api_keys(self, api_keys: Dict[str, str]) -> Dict[str, Any]: + """ + Update API keys in Gateway configuration. + + Args: + api_keys: Dict mapping provider name to API key value + (e.g., {"helius": "abc123", "infura": "xyz789"}) + + Note: After updating API keys, restart Gateway for changes to take effect. + + Example: + await client.gateway.update_api_keys({ + "helius": "new-helius-key", + "infura": "new-infura-key" + }) + """ + return await self._post("/gateway/apiKeys", json={"api_keys": api_keys}) + # ============================================ # Chains (Networks) and Tokens # ============================================