Exemplo n.º 1
0
    def setUp(self) -> None:
        super().setUp()
        self.api_key = "testApiKey"
        self.passphrase = "testPassphrase"
        self.secret_key = "testSecretKey"

        self.mock_time_provider = MagicMock()
        self.mock_time_provider.time.return_value = 1000

        self.auth = KucoinAuth(
            api_key=self.api_key,
            passphrase=self.passphrase,
            secret_key=self.secret_key,
            time_provider=self.mock_time_provider,
        )
    def setUp(self) -> None:
        super().setUp()
        self.log_records = []
        self.listening_task: Optional[asyncio.Task] = None
        self.mocking_assistant = NetworkMockingAssistant()

        self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self.mock_time_provider = MagicMock()
        self.mock_time_provider.time.return_value = 1000
        self.auth = KucoinAuth(
            self.api_key,
            self.api_passphrase,
            self.api_secret_key,
            time_provider=self.mock_time_provider)

        client_config_map = ClientConfigAdapter(ClientConfigMap())
        self.connector = KucoinExchange(
            client_config_map=client_config_map,
            kucoin_api_key="",
            kucoin_passphrase="",
            kucoin_secret_key="",
            trading_pairs=[],
            trading_required=False)

        self.data_source = KucoinAPIUserStreamDataSource(
            auth=self.auth,
            trading_pairs=[self.trading_pair],
            connector=self.connector,
            api_factory=self.connector._web_assistants_factory)

        self.data_source.logger().setLevel(1)
        self.data_source.logger().addHandler(self)
Exemplo n.º 3
0
    async def get_snapshot(
        cls,
        client: aiohttp.ClientSession,
        trading_pair: str,
        auth: KucoinAuth = None,
        throttler: Optional[AsyncThrottler] = None,
    ) -> Dict[str, Any]:
        throttler = throttler or cls._get_throttler_instance()
        params: Dict = {
            "symbol": convert_to_exchange_trading_pair(trading_pair)
        }

        if auth is not None:
            url = CONSTANTS.BASE_PATH_URL + CONSTANTS.SNAPSHOT_PATH_URL
            limit_id = CONSTANTS.SNAPSHOT_PATH_URL
        else:
            url = CONSTANTS.BASE_PATH_URL + CONSTANTS.SNAPSHOT_NO_AUTH_PATH_URL
            limit_id = CONSTANTS.SNAPSHOT_NO_AUTH_PATH_URL
        path_url = f"{URL(url).path}?{urlencode(params)}"
        headers = auth.add_auth_to_params("get", path_url) if auth else None

        async with throttler.execute_task(limit_id):
            async with client.get(url, params=params,
                                  headers=headers) as response:
                response: aiohttp.ClientResponse = response
                if response.status != 200:
                    raise IOError(
                        f"Error fetching Kucoin market snapshot for {trading_pair}. "
                        f"HTTP status is {response.status}.")
                data: Dict[str, Any] = await response.json()
                return data
    def setUp(self) -> None:
        super().setUp()
        self.log_records = []
        self.listening_task: Optional[asyncio.Task] = None
        self.mocking_assistant = NetworkMockingAssistant()

        self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self.mock_time_provider = MagicMock()
        self.mock_time_provider.time.return_value = 1000
        self.auth = KucoinAuth(self.api_key,
                               self.api_passphrase,
                               self.api_secret_key,
                               time_provider=self.mock_time_provider)
        self.time_synchronizer = TimeSynchronizer()
        self.time_synchronizer.add_time_offset_ms_sample(0)

        self.api_factory = web_utils.build_api_factory(
            throttler=self.throttler,
            time_synchronizer=self.time_synchronizer,
            auth=self.auth)

        self.data_source = KucoinAPIUserStreamDataSource(
            throttler=self.throttler, api_factory=self.api_factory)

        self.data_source.logger().setLevel(1)
        self.data_source.logger().addHandler(self)
Exemplo n.º 5
0
 def setUp(self) -> None:
     super().setUp()
     self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
     self.auth = KucoinAuth(self.api_key, self.api_passphrase,
                            self.api_secret_key)
     self.ob_data_source = KucoinAPIOrderBookDataSource(
         self.throttler, [self.trading_pair], self.auth)
 def setUp(self) -> None:
     super().setUp()
     self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
     self.auth = KucoinAuth(self.api_key, self.api_passphrase,
                            self.api_secret_key)
     self.data_source = KucoinAPIUserStreamDataSource(
         self.throttler, self.auth)
     self.mocking_assistant = NetworkMockingAssistant()
 def setUpClass(cls):
     cls.ev_loop: asyncio.BaseEventLoop = asyncio.get_event_loop()
     cls.kucoin_auth = KucoinAuth(conf.kucoin_api_key,
                                  conf.kucoin_passphrase,
                                  conf.kucoin_secret_key)
     cls.user_stream_tracker: KucoinUserStreamTracker = KucoinUserStreamTracker(
         kucoin_auth=cls.kucoin_auth)
     cls.user_stream_tracker_task: asyncio.Task = safe_ensure_future(
         cls.user_stream_tracker.start())
Exemplo n.º 8
0
    async def get_snapshot(client: aiohttp.ClientSession, trading_pair: str, auth: KucoinAuth) -> Dict[str, Any]:
        params: Dict = {"symbol": convert_to_exchange_trading_pair(trading_pair)}

        path_url = f"/api/v3/market/orderbook/level2?{urlencode(params)}"

        headers = auth.add_auth_to_params("get", path_url)

        async with client.get(SNAPSHOT_REST_URL, params=params, headers=headers) as response:
            response: aiohttp.ClientResponse = response
            if response.status != 200:
                raise IOError(f"Error fetching Kucoin market snapshot for {trading_pair}. "
                              f"HTTP status is {response.status}.")
            data: Dict[str, Any] = await response.json()
            return data
Exemplo n.º 9
0
    def __init__(self,
                 kucoin_api_key: str,
                 kucoin_passphrase: str,
                 kucoin_secret_key: str,
                 trading_pairs: Optional[List[str]] = None,
                 trading_required: bool = True,
                 domain: str = CONSTANTS.DEFAULT_DOMAIN):

        self._domain = domain
        self._time_synchronizer = TimeSynchronizer()
        super().__init__()
        self._auth = KucoinAuth(
            api_key=kucoin_api_key,
            passphrase=kucoin_passphrase,
            secret_key=kucoin_secret_key,
            time_provider=self._time_synchronizer)
        self._throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self._api_factory = web_utils.build_api_factory(
            throttler=self._throttler,
            time_synchronizer=self._time_synchronizer,
            domain=self._domain,
            auth=self._auth)
        self._last_poll_timestamp = 0
        self._last_timestamp = 0
        self._trading_pairs = trading_pairs
        self._order_book_tracker = OrderBookTracker(
            data_source=KucoinAPIOrderBookDataSource(
                trading_pairs=trading_pairs,
                domain=self._domain,
                api_factory=self._api_factory,
                throttler=self._throttler,
                time_synchronizer=self._time_synchronizer),
            trading_pairs=trading_pairs,
            domain=self._domain)
        self._user_stream_tracker = UserStreamTracker(
            data_source=KucoinAPIUserStreamDataSource(
                domain=self._domain,
                api_factory=self._api_factory,
                throttler=self._throttler))
        self._poll_notifier = asyncio.Event()
        self._status_polling_task = None
        self._user_stream_tracker_task = None
        self._user_stream_event_listener_task = None
        self._trading_rules_polling_task = None
        self._trading_fees_polling_task = None
        self._trading_required = trading_required
        self._trading_rules = {}
        self._trading_fees = {}
        self._order_tracker: ClientOrderTracker = ClientOrderTracker(connector=self)
    async def get_snapshot(client: aiohttp.ClientSession,
                           trading_pair: str,
                           auth: KucoinAuth = None) -> Dict[str, Any]:
        params: Dict = {
            "symbol": convert_to_exchange_trading_pair(trading_pair)
        }

        url = SNAPSHOT_REST_URL if auth else SNAPSHOT_REST_URL_NO_AUTH
        path_url = f"{URL(url).path}?{urlencode(params)}"
        headers = auth.add_auth_to_params("get", path_url) if auth else None

        async with client.get(url, params=params, headers=headers) as response:
            response: aiohttp.ClientResponse = response
            if response.status != 200:
                raise IOError(
                    f"Error fetching Kucoin market snapshot for {trading_pair}. "
                    f"HTTP status is {response.status}.")
            data: Dict[str, Any] = await response.json()
            return data
Exemplo n.º 11
0
class KucoinAuthTests(TestCase):
    def setUp(self) -> None:
        super().setUp()
        self.api_key = "testApiKey"
        self.passphrase = "testPassphrase"
        self.secret_key = "testSecretKey"

        self.mock_time_provider = MagicMock()
        self.mock_time_provider.time.return_value = 1000

        self.auth = KucoinAuth(
            api_key=self.api_key,
            passphrase=self.passphrase,
            secret_key=self.secret_key,
            time_provider=self.mock_time_provider,
        )

    def async_run_with_timeout(self, coroutine: Awaitable, timeout: int = 1):
        ret = asyncio.get_event_loop().run_until_complete(
            asyncio.wait_for(coroutine, timeout))
        return ret

    def _sign(self, message: str, key: str) -> str:
        signed_message = base64.b64encode(
            hmac.new(key.encode("utf-8"), message.encode("utf-8"),
                     hashlib.sha256).digest())
        return signed_message.decode("utf-8")

    def test_add_auth_headers_to_get_request_without_params(self):
        request = RESTRequest(method=RESTMethod.GET,
                              url="https://test.url/api/endpoint",
                              is_auth_required=True,
                              throttler_limit_id="/api/endpoint")

        self.async_run_with_timeout(self.auth.rest_authenticate(request))

        self.assertEqual(self.api_key, request.headers["KC-API-KEY"])
        self.assertEqual("1000000", request.headers["KC-API-TIMESTAMP"])
        self.assertEqual("2", request.headers["KC-API-KEY-VERSION"])
        expected_signature = self._sign("1000000" + "GET" +
                                        request.throttler_limit_id,
                                        key=self.secret_key)
        self.assertEqual(expected_signature, request.headers["KC-API-SIGN"])
        expected_passphrase = self._sign(self.passphrase, key=self.secret_key)
        self.assertEqual(expected_passphrase,
                         request.headers["KC-API-PASSPHRASE"])

        self.assertEqual(CONSTANTS.HB_PARTNER_ID,
                         request.headers["KC-API-PARTNER"])
        expected_partner_signature = self._sign(
            "1000000" + CONSTANTS.HB_PARTNER_ID + self.api_key,
            key=CONSTANTS.HB_PARTNER_KEY)
        self.assertEqual(expected_partner_signature,
                         request.headers["KC-API-PARTNER-SIGN"])

    def test_add_auth_headers_to_get_request_with_params(self):
        request = RESTRequest(method=RESTMethod.GET,
                              url="https://test.url/api/endpoint",
                              params={
                                  "param_z": "value_param_z",
                                  "param_a": "value_param_a"
                              },
                              is_auth_required=True,
                              throttler_limit_id="/api/endpoint")

        self.async_run_with_timeout(self.auth.rest_authenticate(request))

        self.assertEqual(self.api_key, request.headers["KC-API-KEY"])
        self.assertEqual("1000000", request.headers["KC-API-TIMESTAMP"])
        self.assertEqual("2", request.headers["KC-API-KEY-VERSION"])
        full_endpoint = f"{request.throttler_limit_id}?param_a=value_param_a&param_z=value_param_z"
        expected_signature = self._sign("1000000" + "GET" + full_endpoint,
                                        key=self.secret_key)
        self.assertEqual(expected_signature, request.headers["KC-API-SIGN"])
        expected_passphrase = self._sign(self.passphrase, key=self.secret_key)
        self.assertEqual(expected_passphrase,
                         request.headers["KC-API-PASSPHRASE"])

        self.assertEqual(CONSTANTS.HB_PARTNER_ID,
                         request.headers["KC-API-PARTNER"])
        expected_partner_signature = self._sign(
            "1000000" + CONSTANTS.HB_PARTNER_ID + self.api_key,
            key=CONSTANTS.HB_PARTNER_KEY)
        self.assertEqual(expected_partner_signature,
                         request.headers["KC-API-PARTNER-SIGN"])

    def test_add_auth_headers_to_post_request(self):
        body = {"param_z": "value_param_z", "param_a": "value_param_a"}
        request = RESTRequest(method=RESTMethod.POST,
                              url="https://test.url/api/endpoint",
                              data=json.dumps(body),
                              is_auth_required=True,
                              throttler_limit_id="/api/endpoint")

        self.async_run_with_timeout(self.auth.rest_authenticate(request))

        self.assertEqual(self.api_key, request.headers["KC-API-KEY"])
        self.assertEqual("1000000", request.headers["KC-API-TIMESTAMP"])
        self.assertEqual("2", request.headers["KC-API-KEY-VERSION"])
        expected_signature = self._sign(
            "1000000" + "POST" + request.throttler_limit_id + json.dumps(body),
            key=self.secret_key)
        self.assertEqual(expected_signature, request.headers["KC-API-SIGN"])
        expected_passphrase = self._sign(self.passphrase, key=self.secret_key)
        self.assertEqual(expected_passphrase,
                         request.headers["KC-API-PASSPHRASE"])

        self.assertEqual(CONSTANTS.HB_PARTNER_ID,
                         request.headers["KC-API-PARTNER"])
        expected_partner_signature = self._sign(
            "1000000" + CONSTANTS.HB_PARTNER_ID + self.api_key,
            key=CONSTANTS.HB_PARTNER_KEY)
        self.assertEqual(expected_partner_signature,
                         request.headers["KC-API-PARTNER-SIGN"])

    def test_no_auth_added_to_wsrequest(self):
        payload = {"param1": "value_param_1"}
        request = WSRequest(payload=payload, is_auth_required=True)

        self.async_run_with_timeout(self.auth.ws_authenticate(request))

        self.assertEqual(payload, request.payload)
Exemplo n.º 12
0
 def authenticator(self):
     return KucoinAuth(api_key=self.kucoin_api_key,
                       passphrase=self.kucoin_passphrase,
                       secret_key=self.kucoin_secret_key,
                       time_provider=self._time_synchronizer)