Skip to content

Commit 39668c0

Browse files
authored
Merge pull request #17 from hummingbot/feat/network-pools-api
feat: add network pool endpoints and executor logs
2 parents 51c64f7 + 628d65f commit 39668c0

3 files changed

Lines changed: 240 additions & 1 deletion

File tree

hummingbot_api_client/routers/accounts.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,24 @@ async def remove_gateway_wallet(
7979

8080
async def list_gateway_wallets(self) -> List[Dict]:
8181
"""List all wallets."""
82-
return await self._get("/accounts/gateway/wallets/")
82+
return await self._get("/accounts/gateway/wallets/")
83+
84+
async def set_default_gateway_wallet(
85+
self,
86+
chain: str,
87+
address: str
88+
) -> Dict[str, Any]:
89+
"""
90+
Set a wallet as the default for a chain.
91+
92+
Args:
93+
chain: Blockchain chain (e.g., 'solana', 'ethereum')
94+
address: Wallet address to set as default
95+
96+
Returns:
97+
Success message with chain and address
98+
"""
99+
return await self._post(
100+
"/accounts/gateway/wallet/set-default",
101+
json={"chain": chain, "address": address}
102+
)

hummingbot_api_client/routers/executors.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,32 @@ async def get_executor(self, executor_id: str) -> Dict[str, Any]:
149149
"""
150150
return await self._get(f"/executors/{executor_id}")
151151

152+
async def get_executor_logs(
153+
self,
154+
executor_id: str,
155+
limit: int = 100,
156+
level: Optional[str] = None
157+
) -> Dict[str, Any]:
158+
"""
159+
Get logs for a specific executor.
160+
161+
Args:
162+
executor_id: The executor ID to get logs for
163+
limit: Maximum number of log entries to return (default 100)
164+
level: Filter by log level (e.g., 'INFO', 'WARNING', 'ERROR')
165+
166+
Returns:
167+
Executor log entries
168+
169+
Example:
170+
logs = await client.executors.get_executor_logs("exec_123", limit=50)
171+
logs = await client.executors.get_executor_logs("exec_123", level="ERROR")
172+
"""
173+
params = {"limit": limit}
174+
if level is not None:
175+
params["level"] = level
176+
return await self._get(f"/executors/{executor_id}/logs", params=params)
177+
152178
async def stop_executor(
153179
self,
154180
executor_id: str,

hummingbot_api_client/routers/gateway.py

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,40 @@ async def update_connector_config(
9191
"""
9292
return await self._post(f"/gateway/connectors/{connector_name}", json=config_updates)
9393

94+
# ============================================
95+
# API Keys
96+
# ============================================
97+
98+
async def get_api_keys(self) -> Dict[str, Any]:
99+
"""
100+
Get all configured API keys from Gateway.
101+
102+
Returns a dict mapping provider name to API key value.
103+
104+
Example:
105+
api_keys = await client.gateway.get_api_keys()
106+
# Returns: {"helius": "abc123", "infura": "xyz789", "coingecko": "...", "etherscan": ""}
107+
"""
108+
return await self._get("/gateway/apiKeys")
109+
110+
async def update_api_keys(self, api_keys: Dict[str, str]) -> Dict[str, Any]:
111+
"""
112+
Update API keys in Gateway configuration.
113+
114+
Args:
115+
api_keys: Dict mapping provider name to API key value
116+
(e.g., {"helius": "abc123", "infura": "xyz789"})
117+
118+
Note: After updating API keys, restart Gateway for changes to take effect.
119+
120+
Example:
121+
await client.gateway.update_api_keys({
122+
"helius": "new-helius-key",
123+
"infura": "new-infura-key"
124+
})
125+
"""
126+
return await self._post("/gateway/apiKeys", json={"api_keys": api_keys})
127+
94128
# ============================================
95129
# Chains (Networks) and Tokens
96130
# ============================================
@@ -304,6 +338,165 @@ async def delete_token(
304338
"""
305339
return await self._delete(f"/gateway/networks/{network_id}/tokens/{token_address}")
306340

341+
async def save_network_token(
342+
self,
343+
network_id: str,
344+
token_address: str
345+
) -> Dict[str, Any]:
346+
"""
347+
Save a token by address - auto-fetches token info from GeckoTerminal.
348+
349+
This is the simplest way to add a token. Just provide the address and
350+
the API will fetch symbol, name, and decimals automatically.
351+
352+
Args:
353+
network_id: Network ID in format 'chain-network' (e.g., 'solana-mainnet-beta')
354+
token_address: Token contract address
355+
356+
Example:
357+
await client.gateway.save_network_token(
358+
network_id='solana-mainnet-beta',
359+
token_address='9QFfgxdSqH5zT7j6rZb1y6SZhw2aFtcQu2r6BuYpump'
360+
)
361+
"""
362+
return await self._post(f"/gateway/networks/{network_id}/tokens/save/{token_address}")
363+
364+
# ============================================
365+
# Network Pools (Primary Pool Endpoints)
366+
# ============================================
367+
368+
async def get_network_pools(
369+
self,
370+
network_id: str,
371+
connector: Optional[str] = None,
372+
pool_type: Optional[str] = None,
373+
search: Optional[str] = None
374+
) -> Dict[str, Any]:
375+
"""
376+
Get pools for a specific network.
377+
378+
Args:
379+
network_id: Network ID in format 'chain-network' (e.g., 'solana-mainnet-beta')
380+
connector: Optional filter by connector (e.g., 'raydium', 'meteora', 'uniswap')
381+
pool_type: Optional filter by type ('amm' or 'clmm')
382+
search: Optional search by trading pair or address
383+
384+
Example:
385+
await client.gateway.get_network_pools(
386+
network_id='solana-mainnet-beta',
387+
connector='raydium',
388+
pool_type='clmm'
389+
)
390+
"""
391+
params = {}
392+
if connector:
393+
params["connector"] = connector
394+
if pool_type:
395+
params["pool_type"] = pool_type.lower()
396+
if search:
397+
params["search"] = search
398+
return await self._get(f"/gateway/networks/{network_id}/pools", params=params or None)
399+
400+
async def add_network_pool(
401+
self,
402+
network_id: str,
403+
connector_name: str,
404+
pool_type: str,
405+
address: str,
406+
base: Optional[str] = None,
407+
quote: Optional[str] = None,
408+
base_address: Optional[str] = None,
409+
quote_address: Optional[str] = None,
410+
fee_pct: Optional[float] = None
411+
) -> Dict[str, Any]:
412+
"""
413+
Add a pool to a specific network.
414+
415+
Args:
416+
network_id: Network ID in format 'chain-network' (e.g., 'solana-mainnet-beta')
417+
connector_name: DEX connector name (e.g., 'raydium', 'meteora')
418+
pool_type: Pool type ('amm' or 'clmm')
419+
address: Pool contract address
420+
base: Optional base token symbol
421+
quote: Optional quote token symbol
422+
base_address: Optional base token address
423+
quote_address: Optional quote token address
424+
fee_pct: Optional fee percentage
425+
426+
Example:
427+
await client.gateway.add_network_pool(
428+
network_id='solana-mainnet-beta',
429+
connector_name='raydium',
430+
pool_type='clmm',
431+
address='58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2'
432+
)
433+
"""
434+
pool_data = {
435+
"connector_name": connector_name,
436+
"type": pool_type.lower(),
437+
"address": address
438+
}
439+
if base:
440+
pool_data["base"] = base
441+
if quote:
442+
pool_data["quote"] = quote
443+
if base_address:
444+
pool_data["base_address"] = base_address
445+
if quote_address:
446+
pool_data["quote_address"] = quote_address
447+
if fee_pct is not None:
448+
pool_data["fee_pct"] = fee_pct
449+
450+
return await self._post(f"/gateway/networks/{network_id}/pools", json=pool_data)
451+
452+
async def delete_network_pool(
453+
self,
454+
network_id: str,
455+
address: str,
456+
pool_type: Optional[str] = None
457+
) -> Dict[str, Any]:
458+
"""
459+
Delete a pool from a specific network.
460+
461+
Args:
462+
network_id: Network ID in format 'chain-network' (e.g., 'solana-mainnet-beta')
463+
address: Pool contract address to remove
464+
pool_type: Optional pool type ('amm' or 'clmm')
465+
466+
Example:
467+
await client.gateway.delete_network_pool(
468+
network_id='solana-mainnet-beta',
469+
address='58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2'
470+
)
471+
"""
472+
params = {}
473+
if pool_type:
474+
params["pool_type"] = pool_type.lower()
475+
return await self._delete(f"/gateway/networks/{network_id}/pools/{address}", params=params or None)
476+
477+
async def save_network_pool(
478+
self,
479+
network_id: str,
480+
pool_address: str
481+
) -> Dict[str, Any]:
482+
"""
483+
Save a pool by address - auto-fetches pool info from the blockchain.
484+
485+
This is the simplest way to add a pool. Just provide the address and
486+
the API will fetch connector, type, tokens, and fees automatically.
487+
488+
Args:
489+
network_id: Network ID in format 'chain-network' (e.g., 'solana-mainnet-beta')
490+
pool_address: Pool contract address
491+
492+
Example:
493+
await client.gateway.save_network_pool(
494+
network_id='solana-mainnet-beta',
495+
pool_address='58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2'
496+
)
497+
"""
498+
return await self._post(f"/gateway/networks/{network_id}/pools/save/{pool_address}")
499+
307500
# ============================================
308501
# Wallets
309502
# ============================================

0 commit comments

Comments
 (0)