Skip to content

Commit bc05d7c

Browse files
author
Nicolas Baum
committed
Merge with hummingbot/development
2 parents a565390 + 65e38b5 commit bc05d7c

File tree

85 files changed

+8475
-1481
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+8475
-1481
lines changed

.coveragerc

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ omit =
2626
hummingbot/connector/exchange/paper_trade*
2727
hummingbot/connector/exchange/probit*
2828
hummingbot/connector/gateway*
29+
hummingbot/connector/test_support/*
2930
hummingbot/core/utils/gateway_config_utils.py
3031
hummingbot/core/utils/kill_switch.py
3132
hummingbot/core/utils/wallet_setup.py
@@ -42,6 +43,9 @@ branch = true
4243
fail_under = 70
4344
precision = 2
4445
skip_empty = true
46+
exclude_lines =
47+
@abstractmethod
48+
@abc.abstractmethod
4549

4650
[html]
4751
directory = coverage_html_report

Makefile

+6-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
.PHONY: build
1111

1212
test:
13-
coverage run -m nose --exclude-dir="test/connector" --exclude-dir="test/debug" --exclude-dir="test/mock" --exclude-dir="test/hummingbot/connector/gateway"
13+
coverage run -m nose \
14+
--exclude-dir="test/connector" \
15+
--exclude-dir="test/debug" \
16+
--exclude-dir="test/mock" \
17+
--exclude-dir="test/hummingbot/connector/gateway/amm" \
18+
--exclude-dir="test/hummingbot/connector/gateway/clob"
1419

1520
run_coverage: test
1621
coverage report

bin/docker_connection.py

+15-18
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
import aioprocessing
21
import asyncio
3-
import docker
42
import logging
5-
from multiprocessing import Process
63
import types
7-
from typing import Callable, Dict, Any, List, Generator, Union
4+
from multiprocessing import Process
5+
from typing import Any, Callable, Dict, Generator, List, Union
86

9-
from hummingbot.core.gateway import (
10-
docker_ipc,
11-
get_gateway_container_name,
12-
set_hummingbot_pipe,
13-
)
7+
import aioprocessing
8+
9+
import docker
10+
from hummingbot.core.gateway import set_hummingbot_pipe
1411

1512
logger: logging.Logger = logging.getLogger(__name__)
1613

@@ -136,15 +133,15 @@ def fork_and_start(main_function: Callable):
136133
# run the main function as parent.
137134
main_function()
138135

139-
# stop the gateway container.
140-
try:
141-
asyncio.get_event_loop().run_until_complete(docker_ipc(
142-
"stop",
143-
container=get_gateway_container_name(),
144-
timeout=1
145-
))
146-
except Exception:
147-
pass
136+
# gateway removed
137+
# try:
138+
# asyncio.get_event_loop().run_until_complete(docker_ipc(
139+
# "stop",
140+
# container=get_gateway_container_name(),
141+
# timeout=1
142+
# ))
143+
# except Exception:
144+
# pass
148145
finally:
149146

150147
# close pipes.

bin/hummingbot.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
from hummingbot.client.ui.style import load_style
2222
from hummingbot.core.event.event_listener import EventListener
2323
from hummingbot.core.event.events import HummingbotUIEvent
24-
from hummingbot.core.gateway import start_existing_gateway_container
2524
from hummingbot.core.utils import detect_available_port
2625
from hummingbot.core.utils.async_utils import safe_gather
2726

@@ -65,7 +64,7 @@ async def main_async(client_config_map: ClientConfigAdapter):
6564
start_listener: UIStartListener = UIStartListener(hb)
6665
hb.app.add_listener(HummingbotUIEvent.Start, start_listener)
6766

68-
tasks: List[Coroutine] = [hb.run(), start_existing_gateway_container(client_config_map)]
67+
tasks: List[Coroutine] = [hb.run()]
6968
if client_config_map.debug_console:
7069
if not hasattr(__builtins__, "help"):
7170
import _sitebuiltins

bin/hummingbot_quickstart.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
from hummingbot.client.ui import login_prompt
3131
from hummingbot.client.ui.style import load_style
3232
from hummingbot.core.event.events import HummingbotUIEvent
33-
from hummingbot.core.gateway import start_existing_gateway_container
3433
from hummingbot.core.management.console import start_management_console
3534
from hummingbot.core.utils.async_utils import safe_gather
3635

@@ -121,7 +120,7 @@ async def quick_start(args: argparse.Namespace, secrets_manager: BaseSecretsMana
121120
start_listener: UIStartListener = UIStartListener(hb, is_script=is_script, is_quickstart=True)
122121
hb.app.add_listener(HummingbotUIEvent.Start, start_listener)
123122

124-
tasks: List[Coroutine] = [hb.run(), start_existing_gateway_container(client_config_map)]
123+
tasks: List[Coroutine] = [hb.run()]
125124
if client_config_map.debug_console:
126125
management_port: int = detect_available_port(8211)
127126
tasks.append(start_management_console(locals(), host="localhost", port=management_port))

hummingbot/client/command/config_command.py

-2
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@
6666
"pmm_script_file_path",
6767
"ethereum_chain_name",
6868
"gateway",
69-
"gateway_enabled",
70-
"gateway_cert_passphrase",
7169
"gateway_api_host",
7270
"gateway_api_port",
7371
"rate_oracle_source",

hummingbot/client/command/connect_command.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ async def connect_exchange(self, # type: HummingbotApplication
3838
self.app.hide_input = True
3939
if connector_name == "kraken":
4040
self.notify("Reminder: Please ensure your Kraken API Key Nonce Window is at least 10.")
41-
else:
42-
connector_config = ClientConfigAdapter(AllConnectorSettings.get_connector_config_keys(connector_name))
41+
connector_config = ClientConfigAdapter(AllConnectorSettings.get_connector_config_keys(connector_name))
4342
if Security.connector_config_file_exists(connector_name):
4443
await Security.wait_til_decryption_done()
4544
api_key_config = [

hummingbot/client/command/gateway_command.py

+28-66
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import asyncio
33
import itertools
44
import time
5-
from typing import TYPE_CHECKING, Any, Dict, List, Optional
5+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
66

77
import pandas as pd
88

@@ -13,7 +13,7 @@
1313
from hummingbot.client.ui.completer import load_completer
1414
from hummingbot.client.ui.interface_utils import format_df_for_printout
1515
from hummingbot.connector.connector_status import get_connector_status
16-
from hummingbot.core.gateway import docker_ipc, get_gateway_paths
16+
from hummingbot.core.gateway import get_gateway_paths
1717
from hummingbot.core.gateway.gateway_http_client import GatewayHttpClient
1818
from hummingbot.core.gateway.gateway_status_monitor import GatewayStatus
1919
from hummingbot.core.utils.async_utils import safe_ensure_future
@@ -68,11 +68,6 @@ def gateway_config(self,
6868
else:
6969
safe_ensure_future(self._show_gateway_configuration(key), loop=self.ev_loop)
7070

71-
@staticmethod
72-
async def check_gateway_image(docker_repo: str, docker_tag: str) -> bool:
73-
image_list: List = await docker_ipc("images", name=f"{docker_repo}:{docker_tag}", quiet=True)
74-
return len(image_list) > 0
75-
7671
async def _test_connection(self):
7772
# test that the gateway is running
7873
if await self._get_gateway_instance().ping_gateway():
@@ -103,26 +98,6 @@ async def _generate_certs(
10398
self.notify(f"Gateway SSL certification files are created in {certs_path}.")
10499
self._get_gateway_instance().reload_certs(self.client_config_map)
105100

106-
async def _generate_gateway_confs(
107-
self, # type: HummingbotApplication
108-
container_id: str, conf_path: str = "/usr/src/app/conf"
109-
):
110-
try:
111-
cmd: str = f"./setup/generate_conf.sh {conf_path}"
112-
exec_info = await docker_ipc(method_name="exec_create",
113-
container=container_id,
114-
cmd=cmd,
115-
user="hummingbot")
116-
117-
await docker_ipc(method_name="exec_start",
118-
exec_id=exec_info["Id"],
119-
detach=True)
120-
return
121-
except asyncio.CancelledError:
122-
raise
123-
except Exception:
124-
raise
125-
126101
async def ping_gateway_api(self, max_wait: int) -> bool:
127102
"""
128103
Try to reach the gateway API for up to max_wait seconds
@@ -139,35 +114,7 @@ async def ping_gateway_api(self, max_wait: int) -> bool:
139114

140115
return True
141116

142-
async def ping_gateway_docker_and_api(self, max_wait: int) -> bool:
143-
"""
144-
Try to reach the docker and then the gateway API for up to max_wait seconds
145-
"""
146-
now = int(time.time())
147-
docker_live = await self.ping_gateway_docker()
148-
while not docker_live:
149-
later = int(time.time())
150-
if later - now > max_wait:
151-
return False
152-
await asyncio.sleep(0.5)
153-
docker_live = await self.ping_gateway_docker()
154-
155-
return await self.ping_gateway_api(max_wait)
156-
157-
async def ping_gateway_docker(self) -> bool:
158-
try:
159-
await docker_ipc("version")
160-
return True
161-
except Exception:
162-
return False
163-
164117
async def _gateway_status(self):
165-
can_reach_docker = await self.ping_gateway_docker()
166-
if not can_reach_docker:
167-
self.notify("\nError: It looks like you do not have Docker installed or running. Gateway commands will not "
168-
"work without it. Please install or start Docker and restart Hummingbot.")
169-
return
170-
171118
if self._gateway_monitor.gateway_status is GatewayStatus.ONLINE:
172119
try:
173120
status = await self._get_gateway_instance().get_gateway_status()
@@ -232,7 +179,10 @@ async def _gateway_connect(
232179
available_networks: List[Dict[str, Any]] = connector_config[0]["available_networks"]
233180
trading_type: str = connector_config[0]["trading_type"][0]
234181
additional_spenders: List[str] = connector_config[0].get("additional_spenders", [])
235-
additional_prompts: Dict[str, str] = connector_config[0].get("additional_add_wallet_prompts", {})
182+
additional_prompts: Dict[str, str] = connector_config[0].get( # These will be stored locally.
183+
"additional_add_wallet_prompts", # If Gateway requires additional, prompts with secure info,
184+
{} # a new attribute must be added (e.g. additional_secure_add_wallet_prompts)
185+
)
236186

237187
# ask user to select a chain. Automatically select if there is only one.
238188
chains: List[str] = [d['chain'] for d in available_networks]
@@ -286,7 +236,7 @@ async def _gateway_connect(
286236

287237
# if the user has no wallet, ask them to select one
288238
if len(wallets) < 1 or chain == "near" or len(additional_prompts) != 0:
289-
wallet_address = await self._prompt_for_wallet_address(
239+
wallet_address, additional_prompt_values = await self._prompt_for_wallet_address(
290240
chain=chain, network=network, additional_prompts=additional_prompts
291241
)
292242

@@ -311,9 +261,13 @@ async def _gateway_connect(
311261
wallet_table: List[Dict[str, Any]] = []
312262
for w in wallets:
313263
balances: Dict[str, Any] = await self._get_gateway_instance().get_balances(
314-
chain, network, w, [native_token]
264+
chain, network, w, [native_token], connector
265+
)
266+
balance = (
267+
balances['balances'].get(native_token)
268+
or balances['balances']['total'].get(native_token)
315269
)
316-
wallet_table.append({"balance": balances['balances'][native_token], "address": w})
270+
wallet_table.append({"balance": balance, "address": w})
317271

318272
wallet_df: pd.DataFrame = build_wallet_display(native_token, wallet_table)
319273
self.notify(wallet_df.to_string(index=False))
@@ -332,7 +286,7 @@ async def _gateway_connect(
332286
else:
333287
while True:
334288
try:
335-
wallet_address = await self._prompt_for_wallet_address(
289+
wallet_address, additional_prompt_values = await self._prompt_for_wallet_address(
336290
chain=chain, network=network, additional_prompts=additional_prompts
337291
)
338292
break
@@ -342,16 +296,24 @@ async def _gateway_connect(
342296
# display wallet balance
343297
native_token: str = native_tokens[chain]
344298
balances: Dict[str, Any] = await self._get_gateway_instance().get_balances(
345-
chain, network, wallet_address, [native_token]
299+
chain, network, wallet_address, [native_token], connector
346300
)
347-
wallet_table: List[Dict[str, Any]] = [{"balance": balances['balances'][native_token], "address": wallet_address}]
301+
wallet_table: List[Dict[str, Any]] = [{"balance": balances['balances'].get(native_token) or balances['balances']['total'].get(native_token), "address": wallet_address}]
348302
wallet_df: pd.DataFrame = build_wallet_display(native_token, wallet_table)
349303
self.notify(wallet_df.to_string(index=False))
350304

351305
self.app.clear_input()
352306

353307
# write wallets to Gateway connectors settings.
354-
GatewayConnectionSetting.upsert_connector_spec(connector, chain, network, trading_type, wallet_address, additional_spenders)
308+
GatewayConnectionSetting.upsert_connector_spec(
309+
connector_name=connector,
310+
chain=chain,
311+
network=network,
312+
trading_type=trading_type,
313+
wallet_address=wallet_address,
314+
additional_spenders=additional_spenders,
315+
additional_prompt_values=additional_prompt_values,
316+
)
355317
self.notify(f"The {connector} connector now uses wallet {wallet_address} on {chain}-{network}")
356318

357319
# update AllConnectorSettings and fee overrides.
@@ -369,7 +331,7 @@ async def _prompt_for_wallet_address(
369331
chain: str,
370332
network: str,
371333
additional_prompts: Dict[str, str],
372-
) -> Optional[str]:
334+
) -> Tuple[Optional[str], Dict[str, str]]:
373335
self.app.clear_input()
374336
self.placeholder_mode = True
375337
wallet_private_key = await self.app.prompt(
@@ -392,7 +354,7 @@ async def _prompt_for_wallet_address(
392354
return
393355

394356
for field, prompt in additional_prompts.items():
395-
value = await self.app.prompt(prompt=prompt)
357+
value = await self.app.prompt(prompt=prompt, is_password=True)
396358
self.app.clear_input()
397359
if self.app.to_stop_config:
398360
return
@@ -402,7 +364,7 @@ async def _prompt_for_wallet_address(
402364
chain, network, wallet_private_key, **additional_prompt_values
403365
)
404366
wallet_address: str = response["address"]
405-
return wallet_address
367+
return wallet_address, additional_prompt_values
406368

407369
async def _show_gateway_connector_tokens(
408370
self, # type: HummingbotApplication

hummingbot/client/command/start_command.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def start(self, # type: HummingbotApplication
5757
script: Optional[str] = None,
5858
is_quickstart: Optional[bool] = False):
5959
if threading.current_thread() != threading.main_thread():
60-
self.ev_loop.call_soon_threadsafe(self.start, log_level)
60+
self.ev_loop.call_soon_threadsafe(self.start, log_level, script)
6161
return
6262
safe_ensure_future(self.start_check(log_level, script, is_quickstart), loop=self.ev_loop)
6363

hummingbot/client/config/client_config_map.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,12 @@ def validate_pmm_script_file_path(cls, v: str):
541541

542542

543543
class GatewayConfigMap(BaseClientModel):
544-
gateway_api_host: str = Field(default="localhost")
544+
gateway_api_host: str = Field(
545+
default="localhost",
546+
client_data=ClientFieldData(
547+
prompt=lambda cm: "Please enter your Gateway API host",
548+
),
549+
)
545550
gateway_api_port: str = Field(
546551
default="15888",
547552
client_data=ClientFieldData(

0 commit comments

Comments
 (0)