async def _subscribe_channels(self, ws: WSAssistant):
        try:
            symbols = ",".join([await self._connector.exchange_symbol_associated_to_pair(trading_pair=pair)
                                for pair in self._trading_pairs])

            trades_payload = {
                "id": web_utils.next_message_id(),
                "type": "subscribe",
                "topic": f"/market/match:{symbols}",
                "privateChannel": False,
                "response": False,
            }
            subscribe_trade_request: WSJSONRequest = WSJSONRequest(payload=trades_payload)

            order_book_payload = {
                "id": web_utils.next_message_id(),
                "type": "subscribe",
                "topic": f"/market/level2:{symbols}",
                "privateChannel": False,
                "response": False,
            }
            subscribe_orderbook_request: WSJSONRequest = WSJSONRequest(payload=order_book_payload)

            await ws.send(subscribe_trade_request)
            await ws.send(subscribe_orderbook_request)

            self._last_ws_message_sent_timestamp = self._time()
            self.logger().info("Subscribed to public order book and trade channels...")
        except asyncio.CancelledError:
            raise
        except Exception:
            self.logger().exception("Unexpected error occurred subscribing to order book trading and delta streams...")
            raise
Пример #2
0
    async def _subscribe_channels(self, ws: WSAssistant):
        """
        Subscribes to order events and balance events.

        :param ws: the websocket assistant used to connect to the exchange
        """
        try:
            orders_change_payload = {
                "id": web_utils.next_message_id(),
                "type": "subscribe",
                "topic": "/spotMarket/tradeOrders",
                "privateChannel": True,
                "response": False,
            }
            subscribe_order_change_request: WSRequest = WSRequest(payload=orders_change_payload)

            balance_payload = {
                "id": web_utils.next_message_id(),
                "type": "subscribe",
                "topic": "/account/balance",
                "privateChannel": True,
                "response": False,
            }
            subscribe_balance_request: WSRequest = WSRequest(payload=balance_payload)

            await ws.send(subscribe_order_change_request)
            await ws.send(subscribe_balance_request)

            self.logger().info("Subscribed to private order changes and balance updates channels...")
        except asyncio.CancelledError:
            raise
        except Exception:
            self.logger().exception("Unexpected error occurred subscribing to user streams...")
            raise
Пример #3
0
    async def _subscribe_channels(self, ws: WSAssistant):
        """
        Subscribes to the trade events and diff orders events through the provided websocket connection.

        :param ws: the websocket assistant used to connect to the exchange
        """
        try:
            symbols = ",".join([
                await self.exchange_symbol_associated_to_pair(
                    trading_pair=pair,
                    domain=self._domain,
                    api_factory=self._api_factory,
                    throttler=self._throttler,
                    time_synchronizer=self._time_synchronizer)
                for pair in self._trading_pairs
            ])

            trades_payload = {
                "id": web_utils.next_message_id(),
                "type": "subscribe",
                "topic": f"/market/match:{symbols}",
                "privateChannel": False,
                "response": False,
            }
            subscribe_trade_request: WSRequest = WSRequest(
                payload=trades_payload)

            order_book_payload = {
                "id": web_utils.next_message_id(),
                "type": "subscribe",
                "topic": f"/market/level2:{symbols}",
                "privateChannel": False,
                "response": False,
            }
            subscribe_orderbook_request: WSRequest = WSRequest(
                payload=order_book_payload)

            await ws.send(subscribe_trade_request)
            await ws.send(subscribe_orderbook_request)

            self.logger().info(
                "Subscribed to public order book and trade channels...")
        except asyncio.CancelledError:
            raise
        except Exception:
            self.logger().exception(
                "Unexpected error occurred subscribing to order book trading and delta streams..."
            )
            raise
Пример #4
0
    async def listen_for_subscriptions(self):
        """
        Connects to the trade events and order diffs websocket endpoints and listens to the messages sent by the
        exchange. Each message is stored in its own queue.
        """
        ws = None
        while True:
            try:
                connection_info = await web_utils.api_request(
                    path=CONSTANTS.PUBLIC_WS_DATA_PATH_URL,
                    api_factory=self._api_factory,
                    throttler=self._throttler,
                    domain=self._domain,
                    method=RESTMethod.POST,
                )

                ws_url = connection_info["data"]["instanceServers"][0][
                    "endpoint"]
                ping_interval = int(
                    int(connection_info["data"]["instanceServers"][0]
                        ["pingInterval"]) * 0.8 * 1e-3)
                token = connection_info["data"]["token"]

                ws: WSAssistant = await self._api_factory.get_ws_assistant()
                await ws.connect(ws_url=f"{ws_url}?token={token}",
                                 message_timeout=ping_interval)
                await self._subscribe_channels(ws)
                self._last_ws_message_sent_timestamp = self._time()

                while True:
                    try:
                        seconds_until_next_ping = ping_interval - (
                            self._time() -
                            self._last_ws_message_sent_timestamp)
                        await asyncio.wait_for(
                            self._process_ws_messages(websocket_assistant=ws),
                            timeout=seconds_until_next_ping)
                    except asyncio.TimeoutError:
                        payload = {
                            "id": web_utils.next_message_id(),
                            "type": "ping",
                        }
                        ping_request = WSRequest(payload=payload)
                        self._last_ws_message_sent_timestamp = self._time()
                        await ws.send(request=ping_request)

            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().error(
                    "Unexpected error occurred when listening to order book streams. Retrying in 5 seconds...",
                    exc_info=True,
                )
                await self._sleep(5.0)
            finally:
                ws and await ws.disconnect()
Пример #5
0
    async def listen_for_user_stream(self, output: asyncio.Queue):
        """
        Connects to the user private channel in the exchange using a websocket connection. With the established
        connection, listens to all balance events and order updates provided by the exchange and stores them in the
        output queue

        :param output: The queue where all received events should be stored
        """
        ws: Optional[WSAssistant] = None
        while True:
            try:
                connection_info = await web_utils.api_request(
                    path=CONSTANTS.PRIVATE_WS_DATA_PATH_URL,
                    api_factory=self._api_factory,
                    throttler=self._throttler,
                    domain=self._domain,
                    method=RESTMethod.POST,
                    is_auth_required=True,
                )

                ws_url = connection_info["data"]["instanceServers"][0]["endpoint"]
                ping_interval = int(int(connection_info["data"]["instanceServers"][0]["pingInterval"]) * 0.8 * 1e-3)
                token = connection_info["data"]["token"]

                ws = await self._get_ws_assistant()
                await ws.connect(ws_url=f"{ws_url}?token={token}", message_timeout=ping_interval)
                await ws.ping()  # to update last_recv_timestamp
                await self._subscribe_channels(ws)
                self._last_ws_message_sent_timestamp = self._time()

                while True:
                    try:
                        seconds_until_next_ping = ping_interval - (self._time() - self._last_ws_message_sent_timestamp)
                        await asyncio.wait_for(self._process_ws_messages(websocket_assistant=ws, output=output),
                                               timeout=seconds_until_next_ping)
                    except asyncio.TimeoutError:
                        payload = {
                            "id": web_utils.next_message_id(),
                            "type": "ping",
                        }
                        ping_request = WSRequest(payload=payload)
                        self._last_ws_message_sent_timestamp = self._time()
                        await ws.send(request=ping_request)

            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().exception(
                    "Unexpected error occurred when listening to user streams. Retrying in 5 seconds...")
                await self._sleep(5.0)
            finally:
                ws and await ws.disconnect()
 async def _process_websocket_messages(self, websocket_assistant: WSAssistant):
     while True:
         try:
             seconds_until_next_ping = self._ping_interval - (self._time() - self._last_ws_message_sent_timestamp)
             await asyncio.wait_for(super()._process_websocket_messages(websocket_assistant=websocket_assistant),
                                    timeout=seconds_until_next_ping)
         except asyncio.TimeoutError:
             payload = {
                 "id": web_utils.next_message_id(),
                 "type": "ping",
             }
             ping_request = WSJSONRequest(payload=payload)
             self._last_ws_message_sent_timestamp = self._time()
             await websocket_assistant.send(request=ping_request)