示例#1
0
    async def _authenticate(self, ws: NdaxWebSocketAdaptor):
        """
        Authenticates user to websocket
        """
        try:
            auth_payload: Dict[
                str, Any] = self._auth_assistant.get_ws_auth_payload()
            async with self._throttler.execute_task(
                    CONSTANTS.AUTHENTICATE_USER_ENDPOINT_NAME):
                await ws.send_request(
                    CONSTANTS.AUTHENTICATE_USER_ENDPOINT_NAME, auth_payload)
            auth_resp = await ws.receive()
            auth_payload: Dict[str, Any] = ws.payload_from_raw_message(
                auth_resp.data)

            if not auth_payload["Authenticated"]:
                self.logger().error(f"Response: {auth_payload}", exc_info=True)
                raise Exception(
                    "Could not authenticate websocket connection with NDAX")

            auth_user = auth_payload.get("User")
            self._account_id = auth_user.get("AccountId")
            self._oms_id = auth_user.get("OMSId")

        except asyncio.CancelledError:
            raise
        except Exception as ex:
            self.logger().error(
                f"Error occurred when authenticating to user stream ({ex})",
                exc_info=True)
            raise
示例#2
0
    def test_get_payload_from_raw_received_message(self, mock_ws):
        throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        mock_ws.return_value = self.mocking_assistant.create_websocket_mock()
        payload = {"Key1": True, "Key2": "Value2"}
        message = {"m": 1, "i": 1, "n": "Endpoint", "o": json.dumps(payload)}
        raw_message = json.dumps(message)

        adaptor = NdaxWebSocketAdaptor(throttler,
                                       websocket=mock_ws.return_value)
        extracted_payload = adaptor.payload_from_raw_message(
            raw_message=raw_message)

        self.assertEqual(payload, extracted_payload)
示例#3
0
    def test_listening_process_authenticates_and_subscribes_to_events(
            self, ws_connect_mock):
        messages = asyncio.Queue()
        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock(
        )
        initial_last_recv_time = self.data_source.last_recv_time

        self.listening_task = asyncio.get_event_loop().create_task(
            self.data_source.listen_for_user_stream(asyncio.get_event_loop(),
                                                    messages))
        # Add the authentication response for the websocket
        self.mocking_assistant.add_websocket_aiohttp_message(
            ws_connect_mock.return_value, self._authentication_response(True))
        # Add a dummy message for the websocket to read and include in the "messages" queue
        self.mocking_assistant.add_websocket_aiohttp_message(
            ws_connect_mock.return_value, json.dumps('dummyMessage'))

        first_received_message = asyncio.get_event_loop().run_until_complete(
            messages.get())

        self.assertEqual('dummyMessage', first_received_message)

        self.assertTrue(
            self._is_logged('INFO', "Authenticating to User Stream..."))
        self.assertTrue(
            self._is_logged('INFO',
                            "Successfully authenticated to User Stream."))
        self.assertTrue(
            self._is_logged('INFO', "Successfully subscribed to user events."))

        sent_messages = self.mocking_assistant.json_messages_sent_through_websocket(
            ws_connect_mock.return_value)
        self.assertEqual(2, len(sent_messages))
        authentication_request = sent_messages[0]
        subscription_request = sent_messages[1]
        self.assertEqual(
            CONSTANTS.AUTHENTICATE_USER_ENDPOINT_NAME,
            NdaxWebSocketAdaptor.endpoint_from_raw_message(
                json.dumps(authentication_request)))
        self.assertEqual(
            CONSTANTS.SUBSCRIBE_ACCOUNT_EVENTS_ENDPOINT_NAME,
            NdaxWebSocketAdaptor.endpoint_from_raw_message(
                json.dumps(subscription_request)))
        subscription_payload = NdaxWebSocketAdaptor.payload_from_raw_message(
            json.dumps(subscription_request))
        expected_payload = {"AccountId": self.account_id, "OMSId": self.oms_id}
        self.assertEqual(expected_payload, subscription_payload)

        self.assertGreater(self.data_source.last_recv_time,
                           initial_last_recv_time)
    def test_get_payload_from_raw_received_message(self):
        throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        ws = AsyncMock()
        payload = {"Key1": True,
                   "Key2": "Value2"}
        message = {"m": 1,
                   "i": 1,
                   "n": "Endpoint",
                   "o": json.dumps(payload)}
        raw_message = json.dumps(message)

        adaptor = NdaxWebSocketAdaptor(throttler, websocket=ws)
        extracted_payload = adaptor.payload_from_raw_message(raw_message=raw_message)

        self.assertEqual(payload, extracted_payload)
    async def listen_for_order_book_diffs(self, ev_loop: asyncio.BaseEventLoop,
                                          output: asyncio.Queue):
        """
        Listen for orderbook diffs using WebSocket API.
        """
        if not len(self._trading_pair_id_map) > 0:
            await self.init_trading_pair_ids(self._domain, self._throttler,
                                             self._shared_client)

        while True:
            try:
                ws_adaptor: NdaxWebSocketAdaptor = await self._create_websocket_connection(
                )
                for trading_pair in self._trading_pairs:
                    payload = {
                        "OMSId": 1,
                        "Symbol":
                        convert_to_exchange_trading_pair(trading_pair),
                        "Depth": 200
                    }
                    async with self._throttler.execute_task(
                            CONSTANTS.WS_ORDER_BOOK_CHANNEL):
                        await ws_adaptor.send_request(
                            endpoint_name=CONSTANTS.WS_ORDER_BOOK_CHANNEL,
                            payload=payload)
                async for raw_msg in ws_adaptor.iter_messages():
                    payload = NdaxWebSocketAdaptor.payload_from_raw_message(
                        raw_msg)
                    msg_event: str = NdaxWebSocketAdaptor.endpoint_from_raw_message(
                        raw_msg)
                    if msg_event in [
                            CONSTANTS.WS_ORDER_BOOK_CHANNEL,
                            CONSTANTS.WS_ORDER_BOOK_L2_UPDATE_EVENT
                    ]:
                        msg_data: List[NdaxOrderBookEntry] = [
                            NdaxOrderBookEntry(*entry) for entry in payload
                        ]
                        msg_timestamp: int = int(time.time() * 1e3)
                        msg_product_code: int = msg_data[0].productPairCode

                        content = {"data": msg_data}
                        msg_trading_pair: Optional[str] = None

                        for trading_pair, instrument_id in self._trading_pair_id_map.items(
                        ):
                            if msg_product_code == instrument_id:
                                msg_trading_pair = trading_pair
                                break

                        if msg_trading_pair:
                            metadata = {
                                "trading_pair": msg_trading_pair,
                                "instrument_id": msg_product_code,
                            }

                            order_book_message = None
                            if msg_event == CONSTANTS.WS_ORDER_BOOK_CHANNEL:
                                order_book_message: NdaxOrderBookMessage = NdaxOrderBook.snapshot_message_from_exchange(
                                    msg=content,
                                    timestamp=msg_timestamp,
                                    metadata=metadata)
                            elif msg_event == CONSTANTS.WS_ORDER_BOOK_L2_UPDATE_EVENT:
                                order_book_message: NdaxOrderBookMessage = NdaxOrderBook.diff_message_from_exchange(
                                    msg=content,
                                    timestamp=msg_timestamp,
                                    metadata=metadata)
                            self._last_traded_prices[
                                order_book_message.
                                trading_pair] = order_book_message.last_traded_price
                            await output.put(order_book_message)

            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().network(
                    "Unexpected error with WebSocket connection.",
                    exc_info=True,
                    app_warning_msg=
                    "Unexpected error with WebSocket connection. Retrying in 30 seconds. "
                    "Check network connection.")
                if ws_adaptor:
                    await ws_adaptor.close()
                await self._sleep(30.0)