commit
59249a8c1e
|
@ -21,14 +21,12 @@ Kucoin broker backend
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
Callable,
|
Callable,
|
||||||
Optional,
|
|
||||||
Literal,
|
Literal,
|
||||||
AsyncGenerator
|
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
|
||||||
import math
|
|
||||||
import base64
|
import base64
|
||||||
import hmac
|
import hmac
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -168,7 +166,7 @@ class BrokerConfig(Struct, frozen=True):
|
||||||
|
|
||||||
|
|
||||||
def get_config() -> BrokerConfig | None:
|
def get_config() -> BrokerConfig | None:
|
||||||
conf, _= config.load()
|
conf, _ = config.load()
|
||||||
|
|
||||||
section = conf.get('kucoin')
|
section = conf.get('kucoin')
|
||||||
|
|
||||||
|
@ -176,7 +174,7 @@ def get_config() -> BrokerConfig | None:
|
||||||
log.warning('No config section found for kucoin in config')
|
log.warning('No config section found for kucoin in config')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return BrokerConfig(**section).typecast()
|
return BrokerConfig(**section).copy()
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
|
@ -209,8 +207,8 @@ class Client:
|
||||||
|
|
||||||
passphrase = base64.b64encode(
|
passphrase = base64.b64encode(
|
||||||
hmac.new(
|
hmac.new(
|
||||||
self._key_secret.encode('utf-8'),
|
self._config.key_secret.encode('utf-8'),
|
||||||
self._key_passphrase.encode('utf-8'),
|
self._config.key_passphrase.encode('utf-8'),
|
||||||
hashlib.sha256,
|
hashlib.sha256,
|
||||||
).digest()
|
).digest()
|
||||||
)
|
)
|
||||||
|
@ -218,7 +216,7 @@ class Client:
|
||||||
return {
|
return {
|
||||||
'KC-API-SIGN': signature,
|
'KC-API-SIGN': signature,
|
||||||
'KC-API-TIMESTAMP': str(pendulum.now().int_timestamp * 1000),
|
'KC-API-TIMESTAMP': str(pendulum.now().int_timestamp * 1000),
|
||||||
'KC-API-KEY': self._key_id,
|
'KC-API-KEY': self._config.key_id,
|
||||||
'KC-API-PASSPHRASE': passphrase,
|
'KC-API-PASSPHRASE': passphrase,
|
||||||
# XXX: Even if using the v1 api - this stays the same
|
# XXX: Even if using the v1 api - this stays the same
|
||||||
'KC-API-KEY-VERSION': '2',
|
'KC-API-KEY-VERSION': '2',
|
||||||
|
@ -249,7 +247,10 @@ class Client:
|
||||||
f'Error making request to {api_url} -> {res.json()["msg"]}')
|
f'Error making request to {api_url} -> {res.json()["msg"]}')
|
||||||
return res.json()['msg']
|
return res.json()['msg']
|
||||||
|
|
||||||
async def _get_ws_token(self, private: bool = False) -> tuple[str, int] | None:
|
async def _get_ws_token(
|
||||||
|
self,
|
||||||
|
private: bool = False,
|
||||||
|
) -> tuple[str, int] | None:
|
||||||
'''
|
'''
|
||||||
Fetch ws token needed for sub access:
|
Fetch ws token needed for sub access:
|
||||||
https://docs.kucoin.com/#apply-connect-token
|
https://docs.kucoin.com/#apply-connect-token
|
||||||
|
@ -275,7 +276,6 @@ class Client:
|
||||||
f'Error making request for Kucoin ws token -> {data.json()["msg"]}'
|
f'Error making request for Kucoin ws token -> {data.json()["msg"]}'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def _get_pairs(
|
async def _get_pairs(
|
||||||
self,
|
self,
|
||||||
) -> dict[str, KucoinMktPair]:
|
) -> dict[str, KucoinMktPair]:
|
||||||
|
@ -462,6 +462,7 @@ async def stream_quotes(
|
||||||
'fqsn': sym,
|
'fqsn': sym,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def subscribe(ws: wsproto.WSConnection):
|
async def subscribe(ws: wsproto.WSConnection):
|
||||||
|
|
||||||
|
@ -553,6 +554,7 @@ def make_sub(sym, connect_id, level='l1') -> dict[str, str | bool] | None:
|
||||||
'response': True,
|
'response': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@trio_async_generator
|
@trio_async_generator
|
||||||
async def stream_messages(ws: NoBsWs, sym: str) -> AsyncGenerator[NoBsWs, dict]:
|
async def stream_messages(ws: NoBsWs, sym: str) -> AsyncGenerator[NoBsWs, dict]:
|
||||||
timeouts = 0
|
timeouts = 0
|
||||||
|
@ -569,7 +571,6 @@ async def stream_messages(ws: NoBsWs, sym: str) -> AsyncGenerator[NoBsWs, dict]:
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
if msg.get('subject'):
|
if msg.get('subject'):
|
||||||
msg = KucoinMsg(**msg)
|
msg = KucoinMsg(**msg)
|
||||||
match msg.subject:
|
match msg.subject:
|
||||||
|
|
Loading…
Reference in New Issue