Skip to content

Commit e41f06b

Browse files
committed
add balance subscription in account websocket client
moves key building of subscription to each class
1 parent 243dbd6 commit e41f06b

File tree

6 files changed

+182
-76
lines changed

6 files changed

+182
-76
lines changed

cryptomarket/websockets/account_client.py

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,30 @@ class AccountClient(ClientAuth):
1212
:param on_error: function called on a websocket error, and called in an authenticated error. it takes one parameter, the error.
1313
:param on_close: function called on the closing event of the websocket. no parameters
1414
"""
15-
def __init__(self, api_key:str, api_secret:str, on_connect:callable=None, on_error:callable=None, on_close:callable=None):
16-
super(AccountClient, self).__init__("wss://api.exchange.cryptomkt.com/api/2/ws/account", api_key, api_secret, on_connect=on_connect, on_error=on_error, on_close=on_close)
15+
def __init__(
16+
self,
17+
api_key:str,
18+
api_secret:str,
19+
on_connect:callable=None,
20+
on_error:callable=None,
21+
on_close:callable=None
22+
):
23+
super(AccountClient, self).__init__(
24+
"wss://api.exchange.cryptomkt.com/api/2/ws/account",
25+
api_key,
26+
api_secret,
27+
subscription_keys={
28+
"unsubscribeBalance":"balance",
29+
"subscribeBalance":"balance",
30+
"balance":"balance",
31+
"subscribeTransactions":"transaction",
32+
"subscribeTransactions":"transaction",
33+
"updateTransaction":"transaction"
34+
},
35+
on_connect=on_connect,
36+
on_error=on_error,
37+
on_close=on_close
38+
)
1739

1840
def get_account_balance(self, callback: callable):
1941
"""Get the user account balance.
@@ -46,15 +68,17 @@ def get_account_balance(self, callback: callable):
4668
"""
4769
self.send_by_id(method='getBalance', callback=callback)
4870

49-
def find_transactions(self,
71+
def find_transactions(
72+
self,
5073
callback: callable,
5174
currency: str = None,
5275
sort: str = None,
5376
since: str = None,
5477
till: str = None,
5578
limit: int = None,
5679
offset: int = None,
57-
show_senders: bool = None):
80+
show_senders: bool = None
81+
):
5882
"""Get a list of transactions of the account. Accepts only filtering by Datetime
5983
6084
https://api.exchange.cryptomkt.com/#find-transactions
@@ -87,15 +111,17 @@ def find_transactions(self,
87111
params = args.DictBuilder().currency(currency).sort(sort).since(since).till(till).limit(limit).offset(offset).show_senders(show_senders).build()
88112
self.send_by_id("findTransactions", callback, params)
89113

90-
def load_transactions(self,
114+
def load_transactions(
115+
self,
91116
callback: callable,
92117
currency: str = None,
93118
sort: str = None,
94119
since: str = None,
95120
till: str = None,
96121
limit: int = None,
97122
offset: int = None,
98-
show_senders: bool = None):
123+
show_senders: bool = None
124+
):
99125
"""Get a list of transactions of the account. Accepts only filtering by Index.
100126
101127
https://api.exchange.cryptomkt.com/#load-transactions
@@ -175,3 +201,42 @@ def unsubscribe_to_transactions(self, callback: callable=None):
175201
:returns: The operation result as result argument for the callback. True if success.
176202
"""
177203
self.send_unsubscription(method='unsubscribeTransactions', callback=callback)
204+
205+
def subscribe_to_balance(self, callback: callable, result_callback: callable=None):
206+
"""Subscribe to the balance of the account.
207+
208+
This subscription aims to provide an easy way to be informed of the current balance state.
209+
If the state has been changed or potentially changed the "balance" event will come with the actual state.
210+
Please be aware that only non-zero values are present.
211+
212+
https://api.exchange.cryptomkt.com/#subscription-to-the-balance
213+
214+
:param callback: A callable to call with each update of the result data. It takes one argument, the balance feed.
215+
:param result_callback: A callable to call with the subscription result. It takes two arguments, err and result. err is None for successful calls, result is None for calls with error: callback(err, result).
216+
217+
:returns: A transaction of the account as feed for the callback.
218+
219+
.. code-block:: python
220+
{
221+
"id": "76b70d1c-3dd7-423e-976e-902e516aae0e",
222+
"index": 7173627250,
223+
"type": "bankToExchange",
224+
"status": "success",
225+
"currency": "BTG",
226+
"amount": "0.00001000",
227+
"createdAt": "2021-01-31T08:19:33.892Z",
228+
"updatedAt": "2021-01-31T08:19:33.967Z"
229+
}
230+
"""
231+
self.send_subscription(method='subscribeBalance', callback=callback, params={}, result_callback=result_callback)
232+
233+
def unsubscribe_to_balance(self, callback: callable=None):
234+
"""unsubscribe to the balance feed.
235+
236+
https://api.exchange.cryptomkt.com/#subscription-to-the-balance
237+
238+
:param callback: Optional. A callable to call with the result data. It takes two arguments, err and result. err is None for successful calls, result is None for calls with error: callback(err, result).
239+
240+
:returns: The operation result as result argument for the callback. True if success.
241+
"""
242+
self.send_unsubscription(method='unsubscribeBalance', callback=callback)

cryptomarket/websockets/client_auth.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,23 @@
88

99

1010
class ClientAuth(ClientBase):
11-
def __init__(self, uri:str, api_key:str, api_secret:str, on_connect=None, on_error=None, on_close=None):
12-
super(ClientAuth, self).__init__(uri, on_connect=on_connect, on_error=on_error, on_close=on_close)
11+
def __init__(
12+
self,
13+
uri:str,
14+
api_key:str,
15+
api_secret:str,
16+
subscription_keys:Dict[str, str]={},
17+
on_connect=None,
18+
on_error=None,
19+
on_close=None
20+
):
21+
super(ClientAuth, self).__init__(
22+
uri,
23+
subscription_keys=subscription_keys,
24+
on_connect=on_connect,
25+
on_error=on_error,
26+
on_close=on_close
27+
)
1328
self.api_key = api_key
1429
self.api_secret = api_secret
1530
self.authed = False

cryptomarket/websockets/client_base.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,21 @@
33
from cryptomarket.exceptions import CryptomarketAPIException
44
from cryptomarket.websockets.callback_cache import CallbackCache
55
from cryptomarket.websockets.manager import WebsocketManager
6+
from types import Dict
67

78

89
class ClientBase:
9-
def __init__(self, uri:str, on_connect=None, on_error=None, on_close=None):
10+
def __init__(
11+
self,
12+
uri:str,
13+
subscription_keys:Dict[str,str]={},
14+
on_connect=None,
15+
on_error=None,
16+
on_close=None
17+
):
1018
self.ws_manager = WebsocketManager(self, uri)
11-
self.callback_cache = CallbackCache()
19+
self.callback_cache = CallbackCache()
20+
self.subscription_keys = subscription_keys
1221

1322
if on_connect is not None: self.on_connect = on_connect
1423
else: self.on_connect = lambda: None
@@ -90,4 +99,6 @@ def handle_response(self, response):
9099
callback(None, result)
91100

92101
def build_key(self, method, params):
93-
return "subscription"
102+
if not method in self.subscription_keys:
103+
return "subscription"
104+
return self.subscription_map[method]

cryptomarket/websockets/methods.py

Lines changed: 0 additions & 39 deletions
This file was deleted.

cryptomarket/websockets/public_client.py

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
import cryptomarket.args as args
44
from cryptomarket.websockets.client_base import ClientBase
5-
from cryptomarket.websockets.methods import (candles_feed, method_key,
6-
orderbook_feed, trades_feed)
75
from cryptomarket.websockets.orderbook_cache import OrderbookCache
86

97

@@ -13,9 +11,43 @@ class PublicClient(ClientBase):
1311
:param callback: A callable to call with the client once the connection is established. if an error ocurrs is return as the fist parameter of the callback: callback(err, client)
1412
"""
1513
def __init__(self, on_connect=None, on_error=None, on_close=None):
16-
super(PublicClient, self).__init__("wss://api.exchange.cryptomkt.com/api/2/ws/public", on_connect=on_connect, on_error=on_error, on_close=on_close)
14+
super(PublicClient, self).__init__(
15+
"wss://api.exchange.cryptomkt.com/api/2/ws/public",
16+
subscription_keys={
17+
# tickers
18+
'subscribeTicker':'tickers',
19+
'unsubscribeTicker':'tickers',
20+
'ticker':'tickers',
21+
# orderbooks
22+
'subscribeOrderbook':'orderbooks',
23+
'unsubscribeOrderbook':'orderbooks',
24+
'snapshotOrderbook':'orderbooks',
25+
'updateOrderbook':'orderbooks',
26+
# trades
27+
'subscribeTrades':'trades',
28+
'unsubscribeTrades':'trades',
29+
'snapshotTrades':'trades',
30+
'updateTrades':'trades',
31+
# candles
32+
'subscribeCandles':'candles',
33+
'unsubscribeCandles':'candles',
34+
'snapshotCandles':'candles',
35+
'updateCandles':'candles',
36+
},
37+
on_connect=on_connect,
38+
on_error=on_error,
39+
on_close=on_close
40+
)
1741
self.ob_cache = OrderbookCache()
42+
43+
def orderbook_feed(self, method):
44+
return method == 'snapshotOrderbook' or method == 'updateOrderbook'
45+
46+
def candles_feed(self, method):
47+
return method == 'snapshotCandles' or method == 'updateCandles'
1848

49+
def trades_feed(self, method):
50+
return method == 'snapshotTrades' or method == 'updateTrades'
1951

2052
def handle_notification(self, message):
2153
params = message['params']
@@ -24,15 +56,15 @@ def handle_notification(self, message):
2456
callback = self.callback_cache.get_subscription_callback(key)
2557
if callback is None: return
2658
subscription_data = None
27-
if orderbook_feed(method):
59+
if self.orderbook_feed(method):
2860
self.ob_cache.update(method, key, params)
2961
if self.ob_cache.orderbook_broken(key):
3062
self.send_by_id('subscribeOrderbook', None, {'symbol':symbol})
3163
self.ob_cache.wait_orderbook(key)
3264
if self.ob_cache.orderbook_wating(key): return
3365
subscription_data = self.ob_cache.get_ob(key)
3466

35-
elif trades_feed(method) or candles_feed(method):
67+
elif self.trades_feed(method) or self.candles_feed(method):
3668
subscription_data = params['data']
3769

3870
else:
@@ -41,7 +73,7 @@ def handle_notification(self, message):
4173
callback(subscription_data)
4274

4375
def build_key(self, method, params):
44-
m_key = method_key(method)
76+
m_key = self.subscription_keys[method]
4577
symbol = params['symbol'] if 'symbol' in params else ''
4678
period = params['period'] if 'period' in params else ''
4779
key = m_key + ':' + symbol + ':' + period

cryptomarket/websockets/trading_client.py

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import cryptomarket.args as args
44
from cryptomarket.websockets.client_auth import ClientAuth
55

6-
76
class TradingClient(ClientAuth):
87
"""TradingClient connects via websocket to cryptomarket to enable the user to manage orders. uses SHA256 as auth method and authenticates automatically.
98
@@ -13,22 +12,43 @@ class TradingClient(ClientAuth):
1312
:param on_error: function called on a websocket error, and called in an authenticated error. it takes one parameter, the error.
1413
:param on_close: function called on the closing event of the websocket. no parameters
1514
"""
16-
def __init__(self, api_key:str, api_secret:str, on_connect:callable=None, on_error:callable=None, on_close:callable=None):
17-
super(TradingClient, self).__init__("wss://api.exchange.cryptomkt.com/api/2/ws/trading", api_key, api_secret, on_connect=on_connect, on_error=on_error, on_close=on_close)
18-
19-
def create_order(self,
20-
client_order_id: str,
21-
symbol: str,
22-
side: str,
23-
quantity: float,
24-
order_type: str = None,
25-
price: float = None,
26-
stop_price: float = None,
27-
time_in_force: str = None,
28-
expire_time: str = None,
29-
strict_validate: bool = False,
30-
post_only: bool = False,
31-
callback: callable = None):
15+
def __init__(
16+
self,
17+
api_key:str,
18+
api_secret:str,
19+
on_connect:callable=None,
20+
on_error:callable=None,
21+
on_close:callable=None
22+
):
23+
super(TradingClient, self).__init__(
24+
"wss://api.exchange.cryptomkt.com/api/2/ws/trading",
25+
api_key,
26+
api_secret,
27+
subscription_keys={
28+
"subscribeReports":"reports",
29+
'activeOrders':'reports',
30+
'report':'reports',
31+
},
32+
on_connect=on_connect,
33+
on_error=on_error,
34+
on_close=on_close
35+
)
36+
37+
def create_order(
38+
self,
39+
client_order_id: str,
40+
symbol: str,
41+
side: str,
42+
quantity: float,
43+
order_type: str = None,
44+
price: float = None,
45+
stop_price: float = None,
46+
time_in_force: str = None,
47+
expire_time: str = None,
48+
strict_validate: bool = False,
49+
post_only: bool = False,
50+
callback: callable = None
51+
):
3252
"""Creates a new order
3353
3454
Requires authentication.
@@ -73,9 +93,11 @@ def create_order(self,
7393
params = builder.strict_validate(strict_validate).post_only(post_only).build()
7494
self.send_by_id(method='newOrder', callback=callback, params=params)
7595

76-
def cancel_order(self,
77-
client_order_id: str,
78-
callback: callable= None):
96+
def cancel_order(
97+
self,
98+
client_order_id: str,
99+
callback: callable= None
100+
):
79101
"""Cancel the order with client_order_id.
80102
81103
Requires authentication.

0 commit comments

Comments
 (0)