Add back static API version in headers
parent
1a655b7e39
commit
109e7d7b43
|
@ -18,7 +18,7 @@
|
||||||
Kucoin broker backend
|
Kucoin broker backend
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Any, Optional, Literal
|
from typing import Any, Optional, Literal, AsyncGenerator
|
||||||
from contextlib import asynccontextmanager as acm
|
from contextlib import asynccontextmanager as acm
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import time
|
import time
|
||||||
|
@ -26,6 +26,7 @@ import math
|
||||||
import base64
|
import base64
|
||||||
import hmac
|
import hmac
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import wsproto
|
||||||
|
|
||||||
import asks
|
import asks
|
||||||
import tractor
|
import tractor
|
||||||
|
@ -39,6 +40,10 @@ from piker._cacheables import open_cached_client
|
||||||
from piker.log import get_logger
|
from piker.log import get_logger
|
||||||
from ._util import DataUnavailable
|
from ._util import DataUnavailable
|
||||||
from piker.pp import config
|
from piker.pp import config
|
||||||
|
from ..data._web_bs import (
|
||||||
|
open_autorecon_ws,
|
||||||
|
NoBsWs,
|
||||||
|
)
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
_ohlc_dtype = [
|
_ohlc_dtype = [
|
||||||
|
@ -53,6 +58,21 @@ _ohlc_dtype = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_config() -> dict[str, Any]:
|
||||||
|
conf, path = config.load()
|
||||||
|
|
||||||
|
section = conf.get("kucoin")
|
||||||
|
|
||||||
|
# TODO: document why we send this, basically because logging params for cryptofeed
|
||||||
|
conf["log"] = {}
|
||||||
|
conf["log"]["disabled"] = True
|
||||||
|
breakpoint()
|
||||||
|
if section is None:
|
||||||
|
log.warning("No config section found for kucoin in config")
|
||||||
|
|
||||||
|
return section
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._pairs: dict[str, any] = {}
|
self._pairs: dict[str, any] = {}
|
||||||
|
@ -64,9 +84,11 @@ class Client:
|
||||||
|
|
||||||
config = get_config()
|
config = get_config()
|
||||||
|
|
||||||
if ("key_id" in config) and \
|
if (
|
||||||
("key_secret" in config) and \
|
("key_id" in config)
|
||||||
("key_passphrase" in config):
|
and ("key_secret" in config)
|
||||||
|
and ("key_passphrase" in config)
|
||||||
|
):
|
||||||
self._authenticated = True
|
self._authenticated = True
|
||||||
self._key_id = config["key_id"]
|
self._key_id = config["key_id"]
|
||||||
self._key_secret = config["key_secret"]
|
self._key_secret = config["key_secret"]
|
||||||
|
@ -74,30 +96,30 @@ class Client:
|
||||||
|
|
||||||
def _gen_auth_req_headers(
|
def _gen_auth_req_headers(
|
||||||
self,
|
self,
|
||||||
action: Literal["POST", "GET", "PUT", "DELETE"],
|
action: Literal["POST", "GET"],
|
||||||
endpoint: str,
|
endpoint: str,
|
||||||
api_v: str = "v2",
|
api_v: str = "v2",
|
||||||
):
|
):
|
||||||
'''
|
"""
|
||||||
https://docs.kucoin.com/#authentication
|
https://docs.kucoin.com/#authentication
|
||||||
'''
|
"""
|
||||||
now = int(time.time() * 1000)
|
now = int(time.time() * 1000)
|
||||||
path = f'/api/{api_v}{endpoint}'
|
path = f"/api/{api_v}{endpoint}"
|
||||||
str_to_sign = str(now) + action + path
|
str_to_sign = str(now) + action + path
|
||||||
|
|
||||||
signature = base64.b64encode(
|
signature = base64.b64encode(
|
||||||
hmac.new(
|
hmac.new(
|
||||||
self._key_secret.encode('utf-8'),
|
self._key_secret.encode("utf-8"),
|
||||||
str_to_sign.encode('utf-8'),
|
str_to_sign.encode("utf-8"),
|
||||||
hashlib.sha256
|
hashlib.sha256,
|
||||||
).digest()
|
).digest()
|
||||||
)
|
)
|
||||||
|
|
||||||
passphrase = base64.b64encode(
|
passphrase = base64.b64encode(
|
||||||
hmac.new(
|
hmac.new(
|
||||||
self._key_secret.encode('utf-8'),
|
self._key_secret.encode("utf-8"),
|
||||||
self._key_passphrase.encode('utf-8'),
|
self._key_passphrase.encode("utf-8"),
|
||||||
hashlib.sha256
|
hashlib.sha256,
|
||||||
).digest()
|
).digest()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -106,17 +128,16 @@ class Client:
|
||||||
"KC-API-TIMESTAMP": str(now),
|
"KC-API-TIMESTAMP": str(now),
|
||||||
"KC-API-KEY": self._key_id,
|
"KC-API-KEY": self._key_id,
|
||||||
"KC-API-PASSPHRASE": passphrase,
|
"KC-API-PASSPHRASE": passphrase,
|
||||||
"KC-API-KEY-VERSION": api_v[1]
|
"KC-API-KEY-VERSION": "2",
|
||||||
}
|
}
|
||||||
|
|
||||||
async def _request(
|
async def _request(
|
||||||
self,
|
self,
|
||||||
action: Literal["POST", "GET", "PUT", "DELETE"],
|
action: Literal["POST", "GET"],
|
||||||
endpoint: str,
|
endpoint: str,
|
||||||
api_v: str = "v2",
|
api_v: str = "v2",
|
||||||
headers: dict = {}
|
headers: dict = {},
|
||||||
) -> Any:
|
) -> Any:
|
||||||
|
|
||||||
if self._authenticated:
|
if self._authenticated:
|
||||||
headers = self._gen_auth_req_headers(action, endpoint, api_v)
|
headers = self._gen_auth_req_headers(action, endpoint, api_v)
|
||||||
|
|
||||||
|
@ -129,6 +150,11 @@ class Client:
|
||||||
print(f'KUCOIN ERROR: {res.json()["msg"]}')
|
print(f'KUCOIN ERROR: {res.json()["msg"]}')
|
||||||
breakpoint()
|
breakpoint()
|
||||||
|
|
||||||
|
async def _get_ws_token(self, private: bool) -> str:
|
||||||
|
token_type = "private" if private else "public"
|
||||||
|
token = await self._request("POST", f"/bullet-{token_type}", "v1")
|
||||||
|
return token
|
||||||
|
|
||||||
async def get_pairs(
|
async def get_pairs(
|
||||||
self,
|
self,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
|
@ -175,6 +201,7 @@ class Client:
|
||||||
|
|
||||||
async def last_trades(self, sym: str):
|
async def last_trades(self, sym: str):
|
||||||
trades = await self._request("GET", f"/accounts/ledgers?currency={sym}", "v1")
|
trades = await self._request("GET", f"/accounts/ledgers?currency={sym}", "v1")
|
||||||
|
breakpoint()
|
||||||
return trades.items
|
return trades.items
|
||||||
|
|
||||||
async def get_bars(
|
async def get_bars(
|
||||||
|
@ -247,21 +274,6 @@ def fqsn_to_cf_sym(fqsn: str, pairs: dict[str, any]) -> str:
|
||||||
return pair_data["baseCurrency"] + "-" + pair_data["quoteCurrency"]
|
return pair_data["baseCurrency"] + "-" + pair_data["quoteCurrency"]
|
||||||
|
|
||||||
|
|
||||||
def get_config() -> dict[str, Any]:
|
|
||||||
conf, path = config.load()
|
|
||||||
|
|
||||||
section = conf.get('kucoin')
|
|
||||||
|
|
||||||
# TODO: document why we send this, basically because logging params for cryptofeed
|
|
||||||
conf["log"] = {}
|
|
||||||
conf["log"]["disabled"] = True
|
|
||||||
|
|
||||||
if section is None:
|
|
||||||
log.warning("No config section found for deribit in kucoin")
|
|
||||||
|
|
||||||
return section
|
|
||||||
|
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def get_client():
|
async def get_client():
|
||||||
client = Client()
|
client = Client()
|
||||||
|
@ -312,6 +324,23 @@ async def stream_quotes(
|
||||||
|
|
||||||
last_trades = await client.last_trades(sym)
|
last_trades = await client.last_trades(sym)
|
||||||
|
|
||||||
|
# @acm
|
||||||
|
# async def subscribe(ws: wsproto.WSConnection):
|
||||||
|
|
||||||
|
token = await client._get_ws_token(True)
|
||||||
|
async with open_autorecon_ws(
|
||||||
|
f"wss://ws-api-spot.kucoin.com/?token=={token}&[connectId={12345}]"
|
||||||
|
) as ws:
|
||||||
|
msg_gen = stream_messageS(ws)
|
||||||
|
|
||||||
|
|
||||||
|
async def stream_messageS(ws: NoBsWs) -> AsyncGenerator[NoBsWs, dict]:
|
||||||
|
timeouts = 0
|
||||||
|
while True:
|
||||||
|
with trio.move_on_after(3) as cs:
|
||||||
|
msg = await ws.recv_msg()
|
||||||
|
print(f"msg: {msg}")
|
||||||
|
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def open_history_client(
|
async def open_history_client(
|
||||||
|
|
Loading…
Reference in New Issue