Skip to content

Commit 1e3c612

Browse files
author
Sam McHardy
authored
Merge pull request sammchardy#430 from sapph1re/margin_socket_user_data
start_margin_socket() to listen for userData on margin account
2 parents 81cd618 + 81c4dae commit 1e3c612

2 files changed

Lines changed: 66 additions & 1 deletion

File tree

binance/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2936,7 +2936,7 @@ def margin_stream_get_listen_key(self):
29362936
:raises: BinanceRequestException, BinanceAPIException
29372937
29382938
"""
2939-
res = self._request_margin_api('post', 'userDataStream', signed=True)
2939+
res = self._request_margin_api('post', 'userDataStream', signed=True, data={})
29402940
return res['listenKey']
29412941

29422942
def margin_stream_keepalive(self, listenKey):

binance/websockets.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ def __init__(self, client, user_timeout=DEFAULT_USER_TIMEOUT):
8585
self._user_timer = None
8686
self._user_listen_key = None
8787
self._user_callback = None
88+
self._margin_timer = None
89+
self._margin_listen_key = None
90+
self._margin_callback = None
8891
self._client = client
8992
self._user_timeout = user_timeout
9093

@@ -447,6 +450,24 @@ def start_user_socket(self, callback):
447450
conn_key = self._start_user_socket(user_listen_key, callback)
448451
return conn_key
449452

453+
def start_margin_socket(self, callback):
454+
"""Start a websocket for margin data
455+
456+
https://github.com/binance-exchange/binance-official-api-docs/blob/master/user-data-stream.md
457+
458+
:param callback: callback function to handle messages
459+
:type callback: function
460+
461+
:returns: connection key string if successful, False otherwise
462+
463+
Message Format - see Binance API docs for all types
464+
"""
465+
# Get the user margin listen key
466+
margin_listen_key = self._client.margin_stream_get_listen_key()
467+
# and start the socket with this specific key
468+
conn_key = self._start_margin_socket(margin_listen_key, callback)
469+
return conn_key
470+
450471
def _start_user_socket(self, user_listen_key, callback):
451472
# With this function we can start a user socket with a specific key
452473
if self._user_listen_key:
@@ -461,14 +482,34 @@ def _start_user_socket(self, user_listen_key, callback):
461482
if conn_key:
462483
# start timer to keep socket alive
463484
self._start_user_timer()
485+
return conn_key
464486

487+
def _start_margin_socket(self, margin_listen_key, callback):
488+
# With this function we can start a user margin socket with a specific key
489+
if self._margin_listen_key:
490+
# cleanup any sockets with this key
491+
for conn_key in self._conns:
492+
if len(conn_key) >= 60 and conn_key[:60] == self._margin_listen_key:
493+
self.stop_socket(conn_key)
494+
break
495+
self._margin_listen_key = margin_listen_key
496+
self._margin_callback = callback
497+
conn_key = self._start_socket(self._margin_listen_key, callback)
498+
if conn_key:
499+
# start timer to keep socket alive
500+
self._start_margin_timer()
465501
return conn_key
466502

467503
def _start_user_timer(self):
468504
self._user_timer = threading.Timer(self._user_timeout, self._keepalive_user_socket)
469505
self._user_timer.setDaemon(True)
470506
self._user_timer.start()
471507

508+
def _start_margin_timer(self):
509+
self._margin_timer = threading.Timer(self._user_timeout, self._keepalive_margin_socket)
510+
self._margin_timer.setDaemon(True)
511+
self._margin_timer.start()
512+
472513
def _keepalive_user_socket(self):
473514
user_listen_key = self._client.stream_get_listen_key()
474515
# check if they key changed and
@@ -481,6 +522,18 @@ def _keepalive_user_socket(self):
481522
# Restart timer only if the user listen key is not changed
482523
self._start_user_timer()
483524

525+
def _keepalive_margin_socket(self):
526+
margin_listen_key = self._client.stream_get_listen_key()
527+
# check if they key changed and
528+
if margin_listen_key != self._margin_listen_key:
529+
# Start a new socket with the key received
530+
# `_start_margin_socket` automatically cleanup open sockets
531+
# and starts timer to keep socket alive
532+
self._start_margin_socket(margin_listen_key, self._margin_callback)
533+
else:
534+
# Restart timer only if the margin listen key is not changed
535+
self._start_margin_timer()
536+
484537
def stop_socket(self, conn_key):
485538
"""Stop a websocket given the connection key
486539
@@ -501,6 +554,10 @@ def stop_socket(self, conn_key):
501554
if len(conn_key) >= 60 and conn_key[:60] == self._user_listen_key:
502555
self._stop_user_socket()
503556

557+
# or a margin stream socket
558+
if len(conn_key) >= 60 and conn_key[:60] == self._margin_listen_key:
559+
self._stop_margin_socket()
560+
504561
def _stop_user_socket(self):
505562
if not self._user_listen_key:
506563
return
@@ -509,6 +566,14 @@ def _stop_user_socket(self):
509566
self._user_timer = None
510567
self._user_listen_key = None
511568

569+
def _stop_margin_socket(self):
570+
if not self._margin_listen_key:
571+
return
572+
# stop the timer
573+
self._margin_timer.cancel()
574+
self._margin_timer = None
575+
self._margin_listen_key = None
576+
512577
def run(self):
513578
try:
514579
reactor.run(installSignalHandlers=False)

0 commit comments

Comments
 (0)