Exemple #1
0
    async def _generate_certs(
            self,       # type: HummingbotApplication
            from_client_password: bool = False
    ):
        cert_path: str = get_gateway_paths().local_certs_path.as_posix()
        if not from_client_password:
            if certs_files_exist():
                self.notify(f"Gateway SSL certification files exist in {cert_path}.")
                self.notify("To create new certification files, please first manually delete those files.")
                return

            with begin_placeholder_mode(self):
                while True:
                    pass_phase = await self.app.prompt(
                        prompt='Enter pass phase to generate Gateway SSL certifications  >>> ',
                        is_password=True
                    )
                    if pass_phase is not None and len(pass_phase) > 0:
                        break
                    self.notify("Error: Invalid pass phase")
        else:
            pass_phase = Security.password
        create_self_sign_certs(pass_phase)
        self.notify(f"Gateway SSL certification files are created in {cert_path}.")
        GatewayHttpClient.get_instance().reload_certs()
Exemple #2
0
 def setUpClass(cls) -> None:
     super().setUpClass()
     GatewayHttpClient.__instance = None
     cls._db_path = realpath(
         join(__file__, "../fixtures/gateway_evm_amm_fixture.db"))
     cls._http_player = HttpPlayer(cls._db_path)
     cls._clock: Clock = Clock(ClockMode.REALTIME)
     cls._client_config_map = ClientConfigAdapter(ClientConfigMap())
     cls._connector: GatewayEVMAMM = GatewayEVMAMM(
         client_config_map=cls._client_config_map,
         connector_name="uniswap",
         chain="ethereum",
         network="ropsten",
         wallet_address="0x5821715133bB451bDE2d5BC6a4cE3430a4fdAF92",
         trading_pairs=["DAI-WETH"],
         trading_required=True)
     cls._clock.add_iterator(cls._connector)
     cls._patch_stack = ExitStack()
     cls._patch_stack.enter_context(cls._http_player.patch_aiohttp_client())
     cls._patch_stack.enter_context(
         patch(
             "hummingbot.core.gateway.gateway_http_client.GatewayHttpClient._http_client",
             return_value=ClientSession()))
     cls._patch_stack.enter_context(cls._clock)
     GatewayHttpClient.get_instance(client_config_map=cls._client_config_map
                                    ).base_url = "https://localhost:5000"
     ev_loop.run_until_complete(cls.wait_til_ready())
    async def _monitor_loop(self):
        while True:
            try:
                if await asyncio.wait_for(
                        GatewayHttpClient.get_instance().ping_gateway(),
                        timeout=POLL_TIMEOUT):
                    if self._current_status is Status.OFFLINE:
                        gateway_connectors = await GatewayHttpClient.get_instance(
                        ).get_connectors(fail_silently=True)
                        GATEWAY_CONNECTORS.clear()
                        GATEWAY_CONNECTORS.extend([
                            connector["name"]
                            for connector in gateway_connectors.get(
                                "connectors", [])
                        ])

                        await self.update_gateway_config_key_list()
                    self._current_status = Status.ONLINE
                else:
                    self._current_status = Status.OFFLINE
            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().error(
                    "Unable to find Gateway service. Please check that Gateway service is online. "
                )
                self._current_status = Status.OFFLINE
            await asyncio.sleep(POLL_INTERVAL)
 def setUpClass(cls) -> None:
     super().setUpClass()
     cls._db_path = realpath(
         join(__file__, "../fixtures/gateway_evm_amm_lp_fixture.db"))
     cls._http_player = HttpPlayer(cls._db_path)
     cls._clock: Clock = Clock(ClockMode.REALTIME)
     cls._client_config_map = ClientConfigAdapter(ClientConfigMap())
     cls._connector: GatewayEVMAMMLP = GatewayEVMAMMLP(
         client_config_map=cls._client_config_map,
         connector_name="uniswapLP",
         chain="ethereum",
         network="kovan",
         wallet_address="0xefb7be8631d154d4c0ad8676fec0897b2894fe8f",
         trading_pairs=["COIN1-COIN3"],
         trading_required=True)
     cls._clock.add_iterator(cls._connector)
     cls._patch_stack = ExitStack()
     cls._patch_stack.enter_context(cls._http_player.patch_aiohttp_client())
     cls._patch_stack.enter_context(
         patch(
             "hummingbot.core.gateway.gateway_http_client.GatewayHttpClient._http_client",
             return_value=ClientSession()))
     cls._patch_stack.enter_context(cls._clock)
     GatewayHttpClient.get_instance(client_config_map=cls._client_config_map
                                    ).base_url = "https://localhost:5000"
     ev_loop.run_until_complete(cls.wait_til_ready())
 def setUpClass(cls) -> None:
     cls._db_path = realpath(join(__file__, "../fixtures/gateway_cancel_fixture.db"))
     cls._http_player = HttpPlayer(cls._db_path)
     cls._clock: Clock = Clock(ClockMode.REALTIME)
     cls._client_config_map = ClientConfigAdapter(ClientConfigMap())
     cls._connector: GatewayEVMAMM = GatewayEVMAMM(
         client_config_map=cls._client_config_map,
         connector_name="uniswap",
         chain="ethereum",
         network=NETWORK,
         wallet_address=WALLET_ADDRESS,
         trading_pairs=[TRADING_PAIR],
         trading_required=True
     )
     cls._clock.add_iterator(cls._connector)
     cls._patch_stack = ExitStack()
     cls._patch_stack.enter_context(cls._http_player.patch_aiohttp_client())
     cls._patch_stack.enter_context(
         patch(
             "hummingbot.core.gateway.gateway_http_client.GatewayHttpClient._http_client",
             return_value=ClientSession(),
         )
     )
     cls._patch_stack.enter_context(cls._clock)
     GatewayHttpClient.get_instance().base_url = "https://localhost:5000"
     ev_loop.run_until_complete(cls.wait_til_ready())
    async def update_canceling_transactions(
            self, canceled_tracked_orders: List[GatewayInFlightOrder]):
        """
        Update tracked orders that have a cancel_tx_hash.
        :param canceled_tracked_orders: Canceled tracked_orders (cancel_tx_has is not None).
        """
        if len(canceled_tracked_orders) < 1:
            return

        self.logger().debug(
            "Polling for order status updates of %d canceled orders.",
            len(canceled_tracked_orders))
        update_results: List[Union[Dict[
            str, Any], Exception]] = await safe_gather(*[
                GatewayHttpClient.get_instance().get_transaction_status(
                    self.chain, self.network, tx_hash) for tx_hash in
                [t.cancel_tx_hash for t in canceled_tracked_orders]
            ],
                                                       return_exceptions=True)
        for tracked_order, update_result in zip(canceled_tracked_orders,
                                                update_results):
            if isinstance(update_result, Exception):
                raise update_result
            if "txHash" not in update_result:
                self.logger().error(
                    f"No txHash field for transaction status of {tracked_order.client_order_id}: "
                    f"{update_result}.")
                continue
            if update_result["txStatus"] == 1:
                if update_result["txReceipt"]["status"] == 1:
                    if tracked_order.last_state == "CANCELING":
                        if self.is_amm_order(tracked_order):
                            self.trigger_event(
                                MarketEvent.OrderCancelled,
                                OrderCancelledEvent(
                                    self.current_timestamp,
                                    tracked_order.client_order_id,
                                    tracked_order.exchange_order_id,
                                ))
                            self.logger().info(
                                f"The {tracked_order.trade_type.name} order "
                                f"{tracked_order.client_order_id} has been canceled "
                                f"according to the order status API.")
                        elif self.is_approval_order(tracked_order):
                            token_symbol: str = self.get_token_symbol_from_approval_order_id(
                                tracked_order.client_order_id)
                            self.trigger_event(
                                TokenApprovalEvent.ApprovalCancelled,
                                TokenApprovalCancelledEvent(
                                    self.current_timestamp,
                                    self.connector_name, token_symbol))
                            self.logger().info(
                                f"Token approval for {tracked_order.client_order_id} on "
                                f"{self.connector_name} has been canceled.")
                        tracked_order.last_state = "CANCELED"
                    self.stop_tracking_order(tracked_order.client_order_id)
 async def update_token_approval_status(
         self, tracked_approvals: List[GatewayInFlightOrder]):
     """
     Calls REST API to get status update for each in-flight token approval transaction.
     """
     if len(tracked_approvals) < 1:
         return
     tx_hash_list: List[str] = await safe_gather(*[
         tracked_approval.get_exchange_order_id()
         for tracked_approval in tracked_approvals
     ])
     transaction_states: List[Union[Dict[
         str, Any], Exception]] = await safe_gather(*[
             GatewayHttpClient.get_instance().get_transaction_status(
                 self.chain, self.network, tx_hash)
             for tx_hash in tx_hash_list
         ],
                                                    return_exceptions=True)
     for tracked_approval, transaction_status in zip(
             tracked_approvals, transaction_states):
         token_symbol: str = self.get_token_symbol_from_approval_order_id(
             tracked_approval.client_order_id)
         if isinstance(transaction_status, Exception):
             self.logger().error(
                 f"Error while trying to approve token {token_symbol} for {self.connector_name}: "
                 f"{transaction_status}")
             continue
         if "txHash" not in transaction_status:
             self.logger().error(
                 f"Error while trying to approve token {token_symbol} for {self.connector_name}: "
                 "txHash key not found in transaction status.")
             continue
         if transaction_status["txStatus"] == 1:
             if transaction_status["txReceipt"]["status"] == 1:
                 self.logger().info(
                     f"Token approval for {tracked_approval.client_order_id} on {self.connector_name} "
                     f"successful.")
                 self.trigger_event(
                     TokenApprovalEvent.ApprovalSuccessful,
                     TokenApprovalSuccessEvent(self.current_timestamp,
                                               self.connector_name,
                                               token_symbol))
                 safe_ensure_future(self.update_allowances())
             else:
                 self.logger().warning(
                     f"Token approval for {tracked_approval.client_order_id} on {self.connector_name} failed."
                 )
                 self.trigger_event(
                     TokenApprovalEvent.ApprovalFailed,
                     TokenApprovalFailureEvent(self.current_timestamp,
                                               self.connector_name,
                                               token_symbol))
             self.stop_tracking_order(tracked_approval.client_order_id)
Exemple #8
0
 def setUpClass(cls) -> None:
     super().setUpClass()
     cls._db_path = realpath(
         join(__file__, "../fixtures/gateway_http_client_fixture.db"))
     cls._http_player = HttpPlayer(cls._db_path)
     cls._patch_stack = ExitStack()
     cls._patch_stack.enter_context(cls._http_player.patch_aiohttp_client())
     cls._patch_stack.enter_context(
         patch(
             "hummingbot.core.gateway.gateway_http_client.GatewayHttpClient._http_client",
             return_value=ClientSession()))
     GatewayHttpClient.get_instance().base_url = "https://localhost:5000"
Exemple #9
0
 def _get_gateway_instance(self) -> GatewayHttpClient:
     gateway_instance = GatewayHttpClient.get_instance(self._client_config)
     return gateway_instance
Exemple #10
0
    async def _create_gateway(self):
        gateway_paths: GatewayPaths = get_gateway_paths()
        gateway_container_name: str = get_gateway_container_name()
        gateway_conf_mount_path: str = gateway_paths.mount_conf_path.as_posix()
        certificate_mount_path: str = gateway_paths.mount_certs_path.as_posix()
        logs_mount_path: str = gateway_paths.mount_logs_path.as_posix()
        gateway_port: int = get_default_gateway_port()

        # remove existing container(s)
        try:
            old_container = await docker_ipc(
                "containers",
                all=True,
                filters={"name": gateway_container_name}
            )
            for container in old_container:
                self.notify(f"Removing existing gateway container with id {container['Id']}...")
                await docker_ipc(
                    "remove_container",
                    container["Id"],
                    force=True
                )
        except Exception:
            pass  # silently ignore exception

        await self._generate_certs(from_client_password=True)  # create cert

        if await self.check_gateway_image(GATEWAY_DOCKER_REPO, GATEWAY_DOCKER_TAG):
            self.notify("Found Gateway docker image. No image pull needed.")
        else:
            self.notify("Pulling Gateway docker image...")
            try:
                await self.pull_gateway_docker(GATEWAY_DOCKER_REPO, GATEWAY_DOCKER_TAG)
                self.logger().info("Done pulling Gateway docker image.")
            except Exception as e:
                self.notify("Error pulling Gateway docker image. Try again.")
                self.logger().network("Error pulling Gateway docker image. Try again.",
                                      exc_info=True,
                                      app_warning_msg=str(e))
                return
        self.notify("Creating new Gateway docker container...")
        host_config: Dict[str, Any] = await docker_ipc(
            "create_host_config",
            port_bindings={5000: gateway_port},
            binds={
                gateway_conf_mount_path: {
                    "bind": "/usr/src/app/conf/",
                    "mode": "rw"
                },
                certificate_mount_path: {
                    "bind": "/usr/src/app/certs/",
                    "mode": "rw"
                },
                logs_mount_path: {
                    "bind": "/usr/src/app/logs/",
                    "mode": "rw"
                },
            }
        )
        container_info: Dict[str, str] = await docker_ipc(
            "create_container",
            image=f"{GATEWAY_DOCKER_REPO}:{GATEWAY_DOCKER_TAG}",
            name=gateway_container_name,
            ports=[5000],
            volumes=[
                gateway_conf_mount_path,
                certificate_mount_path,
                logs_mount_path
            ],
            host_config=host_config,
            environment=[f"GATEWAY_PASSPHRASE={Security.password}"]
        )

        self.notify(f"New Gateway docker container id is {container_info['Id']}.")

        # Save the gateway port number, if it's not already there.
        if global_config_map.get("gateway_api_port").value != gateway_port:
            global_config_map["gateway_api_port"].value = gateway_port
            global_config_map["gateway_api_host"].value = "localhost"
            save_to_yml(GLOBAL_CONFIG_PATH, global_config_map)

        GatewayHttpClient.get_instance().base_url = f"https://{global_config_map['gateway_api_host'].value}:" \
                                                    f"{global_config_map['gateway_api_port'].value}"
        await start_gateway()

        # create Gateway configs
        await self._generate_gateway_confs(container_id=container_info["Id"])

        # Restarts the Gateway container to ensure that Gateway server reloads new configs
        try:
            await docker_ipc(method_name="restart",
                             container=container_info["Id"])
        except docker.errors.APIError as e:
            self.notify(f"Error restarting Gateway container. Error: {e}")

        self.notify(f"Loaded new configs into Gateway container {container_info['Id']}")
    MarketEvent,
    TokenApprovalEvent,
    OrderCancelledEvent,
    TokenApprovalCancelledEvent,
)
from hummingbot.core.event.event_logger import EventLogger
from hummingbot.core.gateway.gateway_http_client import GatewayHttpClient
from hummingbot.core.utils.async_utils import safe_ensure_future
from test.mock.http_recorder import HttpRecorder

WALLET_ADDRESS = "0x5821715133bB451bDE2d5BC6a4cE3430a4fdAF92"
NETWORK = "ropsten"
TRADING_PAIR = "WETH-DAI"
MAX_FEE_PER_GAS = 2000
MAX_PRIORITY_FEE_PER_GAS = 200
gateway_http_client: GatewayHttpClient = GatewayHttpClient.get_instance()


class GatewayCancelDataCollector:
    fixture_path: str = realpath(
        join(__file__, "../fixtures/gateway_cancel_fixture.db"))

    def __init__(self):
        self._clock: Clock = Clock(ClockMode.REALTIME)
        self._connector: GatewayEVMAMM = GatewayEVMAMM(
            "uniswap",
            "ethereum",
            NETWORK,
            WALLET_ADDRESS,
            trading_pairs=[TRADING_PAIR],
            trading_required=True)
    async def update_order_status(self,
                                  tracked_orders: List[GatewayInFlightOrder]):
        """
        Calls REST API to get status update for each in-flight amm orders.
        """
        if len(tracked_orders) < 1:
            return

        # split canceled and non-canceled orders
        tx_hash_list: List[str] = await safe_gather(*[
            tracked_order.get_exchange_order_id()
            for tracked_order in tracked_orders
        ])
        self.logger().debug("Polling for order status updates of %d orders.",
                            len(tracked_orders))
        update_results: List[Union[Dict[
            str, Any], Exception]] = await safe_gather(*[
                GatewayHttpClient.get_instance().get_transaction_status(
                    self.chain, self.network, tx_hash)
                for tx_hash in tx_hash_list
            ],
                                                       return_exceptions=True)
        for tracked_order, update_result in zip(tracked_orders,
                                                update_results):
            if isinstance(update_result, Exception):
                raise update_result
            if "txHash" not in update_result:
                self.logger().error(
                    f"No txHash field for transaction status of {tracked_order.client_order_id}: "
                    f"{update_result}.")
                continue
            if update_result["txStatus"] == 1:
                if update_result["txReceipt"]["status"] == 1:
                    gas_used: int = update_result["txReceipt"]["gasUsed"]
                    gas_price: Decimal = tracked_order.gas_price
                    fee: Decimal = Decimal(str(gas_used)) * Decimal(
                        str(gas_price)) / Decimal(str(1e9))
                    self.trigger_event(
                        MarketEvent.OrderFilled,
                        OrderFilledEvent(
                            self.current_timestamp,
                            tracked_order.client_order_id,
                            tracked_order.trading_pair,
                            tracked_order.trade_type,
                            tracked_order.order_type,
                            Decimal(str(tracked_order.price)),
                            Decimal(str(tracked_order.amount)),
                            AddedToCostTradeFee(flat_fees=[
                                TokenAmount(tracked_order.fee_asset,
                                            Decimal(str(fee)))
                            ]),
                            exchange_trade_id=tracked_order.exchange_order_id))
                    tracked_order.last_state = "FILLED"
                    event_tag: MarketEvent = (
                        MarketEvent.BuyOrderCompleted
                        if tracked_order.trade_type is TradeType.BUY else
                        MarketEvent.SellOrderCompleted)
                    event_class: Union[Type[BuyOrderCompletedEvent],
                                       Type[SellOrderCompletedEvent]] = (
                                           BuyOrderCompletedEvent
                                           if tracked_order.trade_type is
                                           TradeType.BUY else
                                           SellOrderCompletedEvent)
                    self.trigger_event(
                        event_tag,
                        event_class(
                            timestamp=self.current_timestamp,
                            order_id=tracked_order.client_order_id,
                            base_asset=tracked_order.base_asset,
                            quote_asset=tracked_order.quote_asset,
                            base_asset_amount=tracked_order.
                            executed_amount_base,
                            quote_asset_amount=tracked_order.
                            executed_amount_quote,
                            order_type=tracked_order.order_type,
                            exchange_order_id=tracked_order.exchange_order_id))
                else:
                    self.logger().info(
                        f"The market order {tracked_order.client_order_id} has failed according to order status API. "
                    )
                    self.trigger_event(
                        MarketEvent.OrderFailure,
                        MarketOrderFailureEvent(self.current_timestamp,
                                                tracked_order.client_order_id,
                                                tracked_order.order_type))
                self.stop_tracking_order(tracked_order.client_order_id)
Exemple #13
0
 def _get_gateway_instance(
     self  # type: HummingbotApplication
 ) -> GatewayHttpClient:
     gateway_instance = GatewayHttpClient.get_instance(self.client_config_map)
     return gateway_instance
Exemple #14
0
async def main():
    client_config_map: ClientConfigAdapter = load_client_config_map_from_file()
    await read_system_configs_from_yml()
    client_config_map.gateway.gateway_api_port = 5000

    fixture_db_path: str = realpath(join(__file__, "../fixtures/gateway_http_client_fixture.db"))
    http_recorder: HttpRecorder = HttpRecorder(fixture_db_path)
    with http_recorder.patch_aiohttp_client():
        gateway_http_client: GatewayHttpClient = GatewayHttpClient()

        print("ping gateway:", await gateway_http_client.ping_gateway())
        print("gateway status:", await gateway_http_client.get_gateway_status())
        print("add wallet:",
              await gateway_http_client.add_wallet(
                  "ethereum",
                  "ropsten",
                  "0000000000000000000000000000000000000000000000000000000000000001"        # noqa: mock
              ))
        print("get wallets:", await gateway_http_client.get_wallets())
        print("get connectors:", await gateway_http_client.get_connectors())
        print("set configuration:", await gateway_http_client.update_config("telemetry.enabled", False))
        print("get configuration:", await gateway_http_client.get_configuration())
        print("get tokens:", await gateway_http_client.get_tokens("ethereum", "ropsten"))
        print("get network status:", await gateway_http_client.get_network_status("ethereum", "ropsten"))
        print("get price:",
              await gateway_http_client.get_price(
                  "ethereum",
                  "ropsten",
                  "uniswap",
                  "DAI",
                  "WETH",
                  Decimal(1000),
                  TradeType.BUY
              ))
        print("get balances:",
              await gateway_http_client.get_balances(
                  "ethereum",
                  "ropsten",
                  "0x5821715133bB451bDE2d5BC6a4cE3430a4fdAF92",
                  ["WETH", "DAI"],
              ))
        print("get transaction status:",
              await gateway_http_client.get_transaction_status(
                  "ethereum",
                  "ropsten",
                  "0xa8d428627dc7f453be79a32129dc18ea29d1a715249a4a5762ca6273da5d96e3"      # noqa: mock
              ))
        print("get transaction status:",
              await gateway_http_client.get_transaction_status(
                  "ethereum",
                  "ropsten",
                  "0xa8d428627dc7f453be79a32129dc18ea29d1a715249a4a5762ca6273da5d96e1"      # noqa: mock
              ))
        print("get evm nonce:",
              await gateway_http_client.get_evm_nonce(
                  "ethereum",
                  "ropsten",
                  "0x5821715133bB451bDE2d5BC6a4cE3430a4fdAF92"
              ))
        print("approve WETH:",
              await gateway_http_client.approve_token(
                  "ethereum",
                  "ropsten",
                  "0x5821715133bB451bDE2d5BC6a4cE3430a4fdAF92",
                  "WETH",
                  "uniswap",
                  2
              ))
        print("approve DAI:",
              await gateway_http_client.approve_token(
                  "ethereum",
                  "ropsten",
                  "0x5821715133bB451bDE2d5BC6a4cE3430a4fdAF92",
                  "DAI",
                  "uniswap",
                  3
              ))
        print("get WETH, DAI allowance:",
              await gateway_http_client.get_allowances(
                  "ethereum",
                  "ropsten",
                  "0x5821715133bB451bDE2d5BC6a4cE3430a4fdAF92",
                  ["WETH", "DAI"],
                  "uniswap"
              ))
        print("buy DAI with WETH:",
              await gateway_http_client.amm_trade(
                  "ethereum",
                  "ropsten",
                  "uniswap",
                  "0x5821715133bB451bDE2d5BC6a4cE3430a4fdAF92",
                  "DAI",
                  "WETH",
                  TradeType.BUY,
                  Decimal(1000),
                  Decimal("0.00266"),
                  4
              ))