ccxt 4.3.3__py2.py3-none-any.whl → 4.3.5__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ccxt might be problematic. Click here for more details.
- ccxt/__init__.py +1 -1
- ccxt/abstract/whitebit.py +22 -1
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +224 -36
- ccxt/async_support/binance.py +19 -14
- ccxt/async_support/kucoin.py +52 -4
- ccxt/async_support/phemex.py +4 -0
- ccxt/async_support/whitebit.py +112 -2
- ccxt/base/exchange.py +230 -4
- ccxt/binance.py +19 -14
- ccxt/kucoin.py +52 -4
- ccxt/phemex.py +4 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +410 -73
- ccxt/pro/cex.py +1 -1
- ccxt/pro/lbank.py +1 -1
- ccxt/pro/woo.py +0 -1
- ccxt/test/test_async.py +15 -17
- ccxt/test/test_sync.py +15 -17
- ccxt/whitebit.py +112 -2
- {ccxt-4.3.3.dist-info → ccxt-4.3.5.dist-info}/METADATA +4 -4
- {ccxt-4.3.3.dist-info → ccxt-4.3.5.dist-info}/RECORD +24 -24
- {ccxt-4.3.3.dist-info → ccxt-4.3.5.dist-info}/WHEEL +0 -0
- {ccxt-4.3.3.dist-info → ccxt-4.3.5.dist-info}/top_level.txt +0 -0
ccxt/pro/binance.py
CHANGED
@@ -46,9 +46,14 @@ class binance(ccxt.async_support.binance):
|
|
46
46
|
'fetchMarketsWs': False,
|
47
47
|
'fetchMyTradesWs': True,
|
48
48
|
'fetchOHLCVWs': True,
|
49
|
+
'fetchOrderBookWs': True,
|
49
50
|
'fetchOpenOrdersWs': True,
|
50
51
|
'fetchOrderWs': True,
|
51
52
|
'fetchOrdersWs': True,
|
53
|
+
'fetchPositionWs': True,
|
54
|
+
'fetchPositionForSymbolWs': True,
|
55
|
+
'fetchPositionsWs': True,
|
56
|
+
'fetchTickerWs': True,
|
52
57
|
'fetchTradesWs': True,
|
53
58
|
'fetchTradingFeesWs': False,
|
54
59
|
'fetchWithdrawalsWs': False,
|
@@ -60,7 +65,10 @@ class binance(ccxt.async_support.binance):
|
|
60
65
|
'margin': 'wss://testnet.binance.vision/ws',
|
61
66
|
'future': 'wss://fstream.binancefuture.com/ws',
|
62
67
|
'delivery': 'wss://dstream.binancefuture.com/ws',
|
63
|
-
'ws':
|
68
|
+
'ws-api': {
|
69
|
+
'spot': 'wss://testnet.binance.vision/ws-api/v3',
|
70
|
+
'future': 'wss://testnet.binancefuture.com/ws-fapi/v1',
|
71
|
+
},
|
64
72
|
},
|
65
73
|
},
|
66
74
|
'api': {
|
@@ -69,7 +77,10 @@ class binance(ccxt.async_support.binance):
|
|
69
77
|
'margin': 'wss://stream.binance.com:9443/ws',
|
70
78
|
'future': 'wss://fstream.binance.com/ws',
|
71
79
|
'delivery': 'wss://dstream.binance.com/ws',
|
72
|
-
'ws':
|
80
|
+
'ws-api': {
|
81
|
+
'spot': 'wss://ws-api.binance.com:443/ws-api/v3',
|
82
|
+
'future': 'wss://ws-fapi.binance.com/ws-fapi/v1',
|
83
|
+
},
|
73
84
|
'papi': 'wss://fstream.binance.com/pm/ws',
|
74
85
|
},
|
75
86
|
},
|
@@ -270,6 +281,75 @@ class binance(ccxt.async_support.binance):
|
|
270
281
|
orderbook = await self.watch_multiple(url, messageHashes, message, messageHashes, subscription)
|
271
282
|
return orderbook.limit()
|
272
283
|
|
284
|
+
async def fetch_order_book_ws(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
285
|
+
"""
|
286
|
+
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
287
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#order-book-2
|
288
|
+
:param str symbol: unified symbol of the market to fetch the order book for
|
289
|
+
:param int [limit]: the maximum amount of order book entries to return
|
290
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
291
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
292
|
+
"""
|
293
|
+
await self.load_markets()
|
294
|
+
market = self.market(symbol)
|
295
|
+
payload = {
|
296
|
+
'symbol': market['id'],
|
297
|
+
}
|
298
|
+
if limit is not None:
|
299
|
+
payload['limit'] = limit
|
300
|
+
marketType = self.get_market_type('fetchOrderBookWs', market, params)
|
301
|
+
if marketType != 'future':
|
302
|
+
raise BadRequest(self.id + ' fetchOrderBookWs only supports swap markets')
|
303
|
+
url = self.urls['api']['ws']['ws-api'][marketType]
|
304
|
+
requestId = self.request_id(url)
|
305
|
+
messageHash = str(requestId)
|
306
|
+
returnRateLimits = False
|
307
|
+
returnRateLimits, params = self.handle_option_and_params(params, 'createOrderWs', 'returnRateLimits', False)
|
308
|
+
payload['returnRateLimits'] = returnRateLimits
|
309
|
+
params = self.omit(params, 'test')
|
310
|
+
message = {
|
311
|
+
'id': messageHash,
|
312
|
+
'method': 'depth',
|
313
|
+
'params': self.sign_params(self.extend(payload, params)),
|
314
|
+
}
|
315
|
+
subscription = {
|
316
|
+
'method': self.handle_fetch_order_book,
|
317
|
+
}
|
318
|
+
orderbook = await self.watch(url, messageHash, message, messageHash, subscription)
|
319
|
+
orderbook['symbol'] = market['symbol']
|
320
|
+
return orderbook
|
321
|
+
|
322
|
+
def handle_fetch_order_book(self, client: Client, message):
|
323
|
+
#
|
324
|
+
# {
|
325
|
+
# "id":"51e2affb-0aba-4821-ba75-f2625006eb43",
|
326
|
+
# "status":200,
|
327
|
+
# "result":{
|
328
|
+
# "lastUpdateId":1027024,
|
329
|
+
# "E":1589436922972,
|
330
|
+
# "T":1589436922959,
|
331
|
+
# "bids":[
|
332
|
+
# [
|
333
|
+
# "4.00000000",
|
334
|
+
# "431.00000000"
|
335
|
+
# ]
|
336
|
+
# ],
|
337
|
+
# "asks":[
|
338
|
+
# [
|
339
|
+
# "4.00000200",
|
340
|
+
# "12.00000000"
|
341
|
+
# ]
|
342
|
+
# ]
|
343
|
+
# }
|
344
|
+
# }
|
345
|
+
#
|
346
|
+
messageHash = self.safe_string(message, 'id')
|
347
|
+
result = self.safe_dict(message, 'result')
|
348
|
+
timestamp = self.safe_integer(result, 'T')
|
349
|
+
orderbook = self.parse_order_book(result, None, timestamp)
|
350
|
+
orderbook['nonce'] = self.safe_integer_2(result, 'lastUpdateId', 'u')
|
351
|
+
client.resolve(orderbook, messageHash)
|
352
|
+
|
273
353
|
async def fetch_order_book_snapshot(self, client, message, subscription):
|
274
354
|
name = self.safe_string(subscription, 'name')
|
275
355
|
symbol = self.safe_string(subscription, 'symbol')
|
@@ -794,6 +874,44 @@ class binance(ccxt.async_support.binance):
|
|
794
874
|
stored.append(parsed)
|
795
875
|
client.resolve(stored, messageHash)
|
796
876
|
|
877
|
+
async def fetch_ticker_ws(self, symbol: str, params={}) -> Ticker:
|
878
|
+
"""
|
879
|
+
fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
880
|
+
:see: https://binance-docs.github.io/apidocs/voptions/en/#24hr-ticker-price-change-statistics
|
881
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
882
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
883
|
+
:param str [params.method]: method to use can be ticker.price or ticker.book
|
884
|
+
:param boolean [params.returnRateLimits]: return the rate limits for the exchange
|
885
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
886
|
+
"""
|
887
|
+
await self.load_markets()
|
888
|
+
market = self.market(symbol)
|
889
|
+
payload = {
|
890
|
+
'symbol': market['id'],
|
891
|
+
}
|
892
|
+
type = self.get_market_type('fetchTickerWs', market, params)
|
893
|
+
if type != 'future':
|
894
|
+
raise BadRequest(self.id + ' fetchTickerWs only supports swap markets')
|
895
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
896
|
+
requestId = self.request_id(url)
|
897
|
+
messageHash = str(requestId)
|
898
|
+
subscription = {
|
899
|
+
'method': self.handle_ticker_ws,
|
900
|
+
}
|
901
|
+
returnRateLimits = False
|
902
|
+
returnRateLimits, params = self.handle_option_and_params(params, 'fetchTickerWs', 'returnRateLimits', False)
|
903
|
+
payload['returnRateLimits'] = returnRateLimits
|
904
|
+
params = self.omit(params, 'test')
|
905
|
+
method = None
|
906
|
+
method, params = self.handle_option_and_params(params, 'fetchTickerWs', 'method', 'ticker.book')
|
907
|
+
message = {
|
908
|
+
'id': messageHash,
|
909
|
+
'method': method,
|
910
|
+
'params': self.sign_params(self.extend(payload, params)),
|
911
|
+
}
|
912
|
+
ticker = await self.watch(url, messageHash, message, messageHash, subscription)
|
913
|
+
return ticker
|
914
|
+
|
797
915
|
async def fetch_ohlcv_ws(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
798
916
|
"""
|
799
917
|
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#klines
|
@@ -810,8 +928,11 @@ class binance(ccxt.async_support.binance):
|
|
810
928
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
811
929
|
"""
|
812
930
|
await self.load_markets()
|
813
|
-
self.
|
814
|
-
|
931
|
+
market = self.market(symbol)
|
932
|
+
marketType = self.get_market_type('fetchOHLCVWs', market, params)
|
933
|
+
if marketType != 'spot' and marketType != 'future':
|
934
|
+
raise BadRequest(self.id + ' fetchOHLCVWs only supports spot or swap markets')
|
935
|
+
url = self.urls['api']['ws']['ws-api'][marketType]
|
815
936
|
requestId = self.request_id(url)
|
816
937
|
messageHash = str(requestId)
|
817
938
|
returnRateLimits = False
|
@@ -1022,6 +1143,22 @@ class binance(ccxt.async_support.binance):
|
|
1022
1143
|
# "v": "2109995.32000000",
|
1023
1144
|
# "q": "2019254.05788000"
|
1024
1145
|
# }
|
1146
|
+
# fetchTickerWs
|
1147
|
+
# {
|
1148
|
+
# "symbol":"BTCUSDT",
|
1149
|
+
# "price":"72606.70",
|
1150
|
+
# "time":1712526204284
|
1151
|
+
# }
|
1152
|
+
# fetchTickerWs - ticker.book
|
1153
|
+
# {
|
1154
|
+
# "lastUpdateId":1027024,
|
1155
|
+
# "symbol":"BTCUSDT",
|
1156
|
+
# "bidPrice":"4.00000000",
|
1157
|
+
# "bidQty":"431.00000000",
|
1158
|
+
# "askPrice":"4.00000200",
|
1159
|
+
# "askQty":"9.00000000",
|
1160
|
+
# "time":1589437530011,
|
1161
|
+
# }
|
1025
1162
|
#
|
1026
1163
|
event = self.safe_string(message, 'e', 'bookTicker')
|
1027
1164
|
if event == '24hrTicker':
|
@@ -1029,24 +1166,24 @@ class binance(ccxt.async_support.binance):
|
|
1029
1166
|
timestamp = None
|
1030
1167
|
if event == 'bookTicker':
|
1031
1168
|
# take the event timestamp, if available, for spot tickers it is not
|
1032
|
-
timestamp = self.
|
1169
|
+
timestamp = self.safe_integer_2(message, 'E', 'time')
|
1033
1170
|
else:
|
1034
1171
|
# take the timestamp of the closing price for candlestick streams
|
1035
|
-
timestamp = self.
|
1036
|
-
marketId = self.
|
1172
|
+
timestamp = self.safe_integer_n(message, ['C', 'E', 'time'])
|
1173
|
+
marketId = self.safe_string_2(message, 's', 'symbol')
|
1037
1174
|
symbol = self.safe_symbol(marketId, None, None, marketType)
|
1038
1175
|
market = self.safe_market(marketId, None, None, marketType)
|
1039
|
-
last = self.
|
1176
|
+
last = self.safe_string_2(message, 'c', 'price')
|
1040
1177
|
return self.safe_ticker({
|
1041
1178
|
'symbol': symbol,
|
1042
1179
|
'timestamp': timestamp,
|
1043
1180
|
'datetime': self.iso8601(timestamp),
|
1044
1181
|
'high': self.safe_string(message, 'h'),
|
1045
1182
|
'low': self.safe_string(message, 'l'),
|
1046
|
-
'bid': self.
|
1047
|
-
'bidVolume': self.
|
1048
|
-
'ask': self.
|
1049
|
-
'askVolume': self.
|
1183
|
+
'bid': self.safe_string_2(message, 'b', 'bidPrice'),
|
1184
|
+
'bidVolume': self.safe_string_2(message, 'B', 'bidQty'),
|
1185
|
+
'ask': self.safe_string_2(message, 'a', 'askPrice'),
|
1186
|
+
'askVolume': self.safe_string_2(message, 'A', 'askQty'),
|
1050
1187
|
'vwap': self.safe_string(message, 'w'),
|
1051
1188
|
'open': self.safe_string(message, 'o'),
|
1052
1189
|
'close': last,
|
@@ -1060,6 +1197,38 @@ class binance(ccxt.async_support.binance):
|
|
1060
1197
|
'info': message,
|
1061
1198
|
}, market)
|
1062
1199
|
|
1200
|
+
def handle_ticker_ws(self, client: Client, message):
|
1201
|
+
#
|
1202
|
+
# ticker.price
|
1203
|
+
# {
|
1204
|
+
# "id":"1",
|
1205
|
+
# "status":200,
|
1206
|
+
# "result":{
|
1207
|
+
# "symbol":"BTCUSDT",
|
1208
|
+
# "price":"73178.50",
|
1209
|
+
# "time":1712527052374
|
1210
|
+
# }
|
1211
|
+
# }
|
1212
|
+
# ticker.book
|
1213
|
+
# {
|
1214
|
+
# "id":"9d32157c-a556-4d27-9866-66760a174b57",
|
1215
|
+
# "status":200,
|
1216
|
+
# "result":{
|
1217
|
+
# "lastUpdateId":1027024,
|
1218
|
+
# "symbol":"BTCUSDT",
|
1219
|
+
# "bidPrice":"4.00000000",
|
1220
|
+
# "bidQty":"431.00000000",
|
1221
|
+
# "askPrice":"4.00000200",
|
1222
|
+
# "askQty":"9.00000000",
|
1223
|
+
# "time":1589437530011 # Transaction time
|
1224
|
+
# }
|
1225
|
+
# }
|
1226
|
+
#
|
1227
|
+
messageHash = self.safe_string(message, 'id')
|
1228
|
+
result = self.safe_value(message, 'result', {})
|
1229
|
+
ticker = self.parse_ws_ticker(result, 'future')
|
1230
|
+
client.resolve(ticker, messageHash)
|
1231
|
+
|
1063
1232
|
def handle_bids_asks(self, client: Client, message):
|
1064
1233
|
#
|
1065
1234
|
# arrives one symbol dict or array of symbol dicts
|
@@ -1317,33 +1486,51 @@ class binance(ccxt.async_support.binance):
|
|
1317
1486
|
"""
|
1318
1487
|
fetch balance and get the amount of funds available for trading or funds locked in orders
|
1319
1488
|
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#account-information-user_data
|
1489
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#account-information-user_data
|
1490
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#futures-account-balance-user_data
|
1320
1491
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1321
1492
|
:param str|None [params.type]: 'future', 'delivery', 'savings', 'funding', or 'spot'
|
1322
1493
|
:param str|None [params.marginMode]: 'cross' or 'isolated', for margin trading, uses self.options.defaultMarginMode if not passed, defaults to None/None/None
|
1323
1494
|
:param str[]|None [params.symbols]: unified market symbols, only used in isolated margin mode
|
1495
|
+
:param str|None [params.method]: method to use. Can be account.balance or account.status
|
1324
1496
|
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
1325
1497
|
"""
|
1326
1498
|
await self.load_markets()
|
1327
|
-
|
1499
|
+
type = self.get_market_type('fetchBalanceWs', None, params)
|
1500
|
+
if type != 'spot' and type != 'future':
|
1501
|
+
raise BadRequest(self.id + ' fetchBalanceWs only supports spot or swap markets')
|
1502
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1328
1503
|
requestId = self.request_id(url)
|
1329
1504
|
messageHash = str(requestId)
|
1330
1505
|
returnRateLimits = False
|
1331
|
-
returnRateLimits, params = self.handle_option_and_params(params, '
|
1506
|
+
returnRateLimits, params = self.handle_option_and_params(params, 'fetchBalanceWs', 'returnRateLimits', False)
|
1332
1507
|
payload = {
|
1333
1508
|
'returnRateLimits': returnRateLimits,
|
1334
1509
|
}
|
1510
|
+
method = None
|
1511
|
+
method, params = self.handle_option_and_params(params, 'fetchBalanceWs', 'method', 'account.status')
|
1335
1512
|
message = {
|
1336
1513
|
'id': messageHash,
|
1337
|
-
'method':
|
1514
|
+
'method': method,
|
1338
1515
|
'params': self.sign_params(self.extend(payload, params)),
|
1339
1516
|
}
|
1340
1517
|
subscription = {
|
1341
|
-
'method': self.handle_balance_ws,
|
1518
|
+
'method': self.handle_account_status_ws if (method == 'account.status') else self.handle_balance_ws,
|
1342
1519
|
}
|
1343
1520
|
return await self.watch(url, messageHash, message, messageHash, subscription)
|
1344
1521
|
|
1345
1522
|
def handle_balance_ws(self, client: Client, message):
|
1346
1523
|
#
|
1524
|
+
#
|
1525
|
+
messageHash = self.safe_string(message, 'id')
|
1526
|
+
result = self.safe_dict(message, 'result', {})
|
1527
|
+
rawBalance = self.safe_list(result, 0, [])
|
1528
|
+
parsedBalances = self.parseBalanceCustom(rawBalance)
|
1529
|
+
client.resolve(parsedBalances, messageHash)
|
1530
|
+
|
1531
|
+
def handle_account_status_ws(self, client: Client, message):
|
1532
|
+
#
|
1533
|
+
# spot
|
1347
1534
|
# {
|
1348
1535
|
# "id": "605a6d20-6588-4cb9-afa0-b0ab087507ba",
|
1349
1536
|
# "status": 200,
|
@@ -1386,12 +1573,97 @@ class binance(ccxt.async_support.binance):
|
|
1386
1573
|
# ]
|
1387
1574
|
# }
|
1388
1575
|
# }
|
1576
|
+
# swap
|
1389
1577
|
#
|
1390
1578
|
messageHash = self.safe_string(message, 'id')
|
1391
|
-
result = self.
|
1392
|
-
parsedBalances = self.
|
1579
|
+
result = self.safe_dict(message, 'result', {})
|
1580
|
+
parsedBalances = self.parseBalanceCustom(result)
|
1393
1581
|
client.resolve(parsedBalances, messageHash)
|
1394
1582
|
|
1583
|
+
async def fetch_position_ws(self, symbol: str, params={}) -> List[Position]:
|
1584
|
+
"""
|
1585
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#position-information-user_data
|
1586
|
+
fetch data on an open position
|
1587
|
+
:param str symbol: unified market symbol of the market the position is held in
|
1588
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1589
|
+
:returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
|
1590
|
+
"""
|
1591
|
+
return await self.fetch_positions_ws([symbol], params)
|
1592
|
+
|
1593
|
+
async def fetch_positions_ws(self, symbols: Strings = None, params={}) -> List[Position]:
|
1594
|
+
"""
|
1595
|
+
fetch all open positions
|
1596
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#position-information-user_data
|
1597
|
+
:param str[] [symbols]: list of unified market symbols
|
1598
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1599
|
+
:param boolean [params.returnRateLimits]: set to True to return rate limit informations, defaults to False.
|
1600
|
+
:returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
|
1601
|
+
"""
|
1602
|
+
await self.load_markets()
|
1603
|
+
symbols = self.market_symbols(symbols, 'swap', True, True, True)
|
1604
|
+
url = self.urls['api']['ws']['ws-api']['future']
|
1605
|
+
requestId = self.request_id(url)
|
1606
|
+
messageHash = str(requestId)
|
1607
|
+
payload = {}
|
1608
|
+
if symbols is not None:
|
1609
|
+
symbolsLength = len(symbols)
|
1610
|
+
if symbolsLength == 1:
|
1611
|
+
payload['symbol'] = self.market_id(symbols[0])
|
1612
|
+
returnRateLimits = False
|
1613
|
+
returnRateLimits, params = self.handle_option_and_params(params, 'fetchPositionsWs', 'returnRateLimits', False)
|
1614
|
+
payload['returnRateLimits'] = returnRateLimits
|
1615
|
+
message = {
|
1616
|
+
'id': messageHash,
|
1617
|
+
'method': 'account.position',
|
1618
|
+
'params': self.sign_params(self.extend(payload, params)),
|
1619
|
+
}
|
1620
|
+
subscription = {
|
1621
|
+
'method': self.handle_positions_ws,
|
1622
|
+
}
|
1623
|
+
result = await self.watch(url, messageHash, message, messageHash, subscription)
|
1624
|
+
return self.filter_by_array_positions(result, 'symbol', symbols, False)
|
1625
|
+
|
1626
|
+
def handle_positions_ws(self, client: Client, message):
|
1627
|
+
#
|
1628
|
+
# {
|
1629
|
+
# id: '1',
|
1630
|
+
# status: 200,
|
1631
|
+
# result: [
|
1632
|
+
# {
|
1633
|
+
# symbol: 'BTCUSDT',
|
1634
|
+
# positionAmt: '-0.014',
|
1635
|
+
# entryPrice: '42901.1',
|
1636
|
+
# breakEvenPrice: '30138.83333142',
|
1637
|
+
# markPrice: '71055.98470333',
|
1638
|
+
# unRealizedProfit: '-394.16838584',
|
1639
|
+
# liquidationPrice: '137032.02272908',
|
1640
|
+
# leverage: '123',
|
1641
|
+
# maxNotionalValue: '50000',
|
1642
|
+
# marginType: 'cross',
|
1643
|
+
# isolatedMargin: '0.00000000',
|
1644
|
+
# isAutoAddMargin: 'false',
|
1645
|
+
# positionSide: 'BOTH',
|
1646
|
+
# notional: '-994.78378584',
|
1647
|
+
# isolatedWallet: '0',
|
1648
|
+
# updateTime: 1708906343111,
|
1649
|
+
# isolated: False,
|
1650
|
+
# adlQuantile: 2
|
1651
|
+
# },
|
1652
|
+
# ...
|
1653
|
+
# ]
|
1654
|
+
# }
|
1655
|
+
#
|
1656
|
+
#
|
1657
|
+
messageHash = self.safe_string(message, 'id')
|
1658
|
+
result = self.safe_list(message, 'result', [])
|
1659
|
+
positions = []
|
1660
|
+
for i in range(0, len(result)):
|
1661
|
+
parsed = self.parse_position_risk(result[i])
|
1662
|
+
entryPrice = self.safe_string(parsed, 'entryPrice')
|
1663
|
+
if (entryPrice != '0') and (entryPrice != '0.0') and (entryPrice != '0.00000000'):
|
1664
|
+
positions.append(parsed)
|
1665
|
+
client.resolve(positions, messageHash)
|
1666
|
+
|
1395
1667
|
async def watch_balance(self, params={}) -> Balances:
|
1396
1668
|
"""
|
1397
1669
|
watch balance and get the amount of funds available for trading or funds locked in orders
|
@@ -1418,7 +1690,7 @@ class binance(ccxt.async_support.binance):
|
|
1418
1690
|
client = self.client(url)
|
1419
1691
|
self.set_balance_cache(client, type, isPortfolioMargin)
|
1420
1692
|
self.set_positions_cache(client, type, None, isPortfolioMargin)
|
1421
|
-
options = self.
|
1693
|
+
options = self.safe_dict(self.options, 'watchBalance')
|
1422
1694
|
fetchBalanceSnapshot = self.safe_bool(options, 'fetchBalanceSnapshot', False)
|
1423
1695
|
awaitBalanceSnapshot = self.safe_bool(options, 'awaitBalanceSnapshot', True)
|
1424
1696
|
if fetchBalanceSnapshot and awaitBalanceSnapshot:
|
@@ -1485,7 +1757,7 @@ class binance(ccxt.async_support.binance):
|
|
1485
1757
|
# }
|
1486
1758
|
# }
|
1487
1759
|
#
|
1488
|
-
wallet = self.
|
1760
|
+
wallet = self.safe_string(self.options, 'wallet', 'wb') # cw for cross wallet
|
1489
1761
|
# each account is connected to a different endpoint
|
1490
1762
|
# and has exactly one subscriptionhash which is the account type
|
1491
1763
|
subscriptions = list(client.subscriptions.keys())
|
@@ -1509,8 +1781,8 @@ class binance(ccxt.async_support.binance):
|
|
1509
1781
|
account['free'] = delta
|
1510
1782
|
self.balance[accountType][code] = account
|
1511
1783
|
else:
|
1512
|
-
message = self.
|
1513
|
-
B = self.
|
1784
|
+
message = self.safe_dict(message, 'a', message)
|
1785
|
+
B = self.safe_list(message, 'B')
|
1514
1786
|
for i in range(0, len(B)):
|
1515
1787
|
entry = B[i]
|
1516
1788
|
currencyId = self.safe_string(entry, 'a')
|
@@ -1526,26 +1798,21 @@ class binance(ccxt.async_support.binance):
|
|
1526
1798
|
self.balance[accountType] = self.safe_balance(self.balance[accountType])
|
1527
1799
|
client.resolve(self.balance[accountType], messageHash)
|
1528
1800
|
|
1529
|
-
def
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
type =
|
1538
|
-
|
1539
|
-
if defaultType == 'spot':
|
1540
|
-
return
|
1541
|
-
raise BadRequest(self.id + ' ' + method + ' only supports spot markets')
|
1542
|
-
market = self.market(symbol)
|
1543
|
-
if not market['spot']:
|
1544
|
-
raise BadRequest(self.id + ' ' + method + ' only supports spot markets')
|
1801
|
+
def get_market_type(self, method, market, params={}):
|
1802
|
+
type = None
|
1803
|
+
type, params = self.handle_market_type_and_params(method, market, params)
|
1804
|
+
subType = None
|
1805
|
+
subType, params = self.handle_sub_type_and_params(method, market, params)
|
1806
|
+
if self.isLinear(type, subType):
|
1807
|
+
type = 'future'
|
1808
|
+
elif self.isInverse(type, subType):
|
1809
|
+
type = 'delivery'
|
1810
|
+
return type
|
1545
1811
|
|
1546
1812
|
async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
|
1547
1813
|
"""
|
1548
1814
|
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#place-new-order-trade
|
1815
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#new-order-trade-2
|
1549
1816
|
create a trade order
|
1550
1817
|
:param str symbol: unified symbol of the market to create an order in
|
1551
1818
|
:param str type: 'market' or 'limit'
|
@@ -1554,14 +1821,18 @@ class binance(ccxt.async_support.binance):
|
|
1554
1821
|
:param float|None [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
1555
1822
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1556
1823
|
:param boolean params['test']: test order, default False
|
1824
|
+
:param boolean params['returnRateLimits']: set to True to return rate limit information, default False
|
1557
1825
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1558
1826
|
"""
|
1559
1827
|
await self.load_markets()
|
1560
|
-
self.
|
1561
|
-
|
1828
|
+
market = self.market(symbol)
|
1829
|
+
marketType = self.get_market_type('createOrderWs', market, params)
|
1830
|
+
if marketType != 'spot' and marketType != 'future':
|
1831
|
+
raise BadRequest(self.id + ' createOrderWs only supports spot or swap markets')
|
1832
|
+
url = self.urls['api']['ws']['ws-api'][marketType]
|
1562
1833
|
requestId = self.request_id(url)
|
1563
1834
|
messageHash = str(requestId)
|
1564
|
-
sor = self.
|
1835
|
+
sor = self.safe_bool_2(params, 'sor', 'SOR', False)
|
1565
1836
|
params = self.omit(params, 'sor', 'SOR')
|
1566
1837
|
payload = self.create_order_request(symbol, type, side, amount, price, params)
|
1567
1838
|
returnRateLimits = False
|
@@ -1633,7 +1904,7 @@ class binance(ccxt.async_support.binance):
|
|
1633
1904
|
# }
|
1634
1905
|
#
|
1635
1906
|
messageHash = self.safe_string(message, 'id')
|
1636
|
-
result = self.
|
1907
|
+
result = self.safe_dict(message, 'result', {})
|
1637
1908
|
order = self.parse_order(result)
|
1638
1909
|
client.resolve(order, messageHash)
|
1639
1910
|
|
@@ -1676,7 +1947,7 @@ class binance(ccxt.async_support.binance):
|
|
1676
1947
|
# }
|
1677
1948
|
#
|
1678
1949
|
messageHash = self.safe_string(message, 'id')
|
1679
|
-
result = self.
|
1950
|
+
result = self.safe_list(message, 'result', [])
|
1680
1951
|
orders = self.parse_orders(result)
|
1681
1952
|
client.resolve(orders, messageHash)
|
1682
1953
|
|
@@ -1684,6 +1955,7 @@ class binance(ccxt.async_support.binance):
|
|
1684
1955
|
"""
|
1685
1956
|
edit a trade order
|
1686
1957
|
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#cancel-and-replace-order-trade
|
1958
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#modify-order-trade-2
|
1687
1959
|
:param str id: order id
|
1688
1960
|
:param str symbol: unified symbol of the market to create an order in
|
1689
1961
|
:param str type: 'market' or 'limit'
|
@@ -1694,17 +1966,24 @@ class binance(ccxt.async_support.binance):
|
|
1694
1966
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1695
1967
|
"""
|
1696
1968
|
await self.load_markets()
|
1697
|
-
self.
|
1698
|
-
|
1969
|
+
market = self.market(symbol)
|
1970
|
+
marketType = self.get_market_type('editOrderWs', market, params)
|
1971
|
+
if marketType != 'spot' and marketType != 'future':
|
1972
|
+
raise BadRequest(self.id + ' editOrderWs only supports spot or swap markets')
|
1973
|
+
url = self.urls['api']['ws']['ws-api'][marketType]
|
1699
1974
|
requestId = self.request_id(url)
|
1700
1975
|
messageHash = str(requestId)
|
1701
|
-
payload =
|
1976
|
+
payload = None
|
1977
|
+
if marketType == 'spot':
|
1978
|
+
payload = self.editSpotOrderRequest(id, symbol, type, side, amount, price, params)
|
1979
|
+
elif marketType == 'future':
|
1980
|
+
payload = self.editContractOrderRequest(id, symbol, type, side, amount, price, params)
|
1702
1981
|
returnRateLimits = False
|
1703
1982
|
returnRateLimits, params = self.handle_option_and_params(params, 'editOrderWs', 'returnRateLimits', False)
|
1704
1983
|
payload['returnRateLimits'] = returnRateLimits
|
1705
1984
|
message = {
|
1706
1985
|
'id': messageHash,
|
1707
|
-
'method': 'order.cancelReplace',
|
1986
|
+
'method': 'order.modify' if (marketType == 'future') else 'order.cancelReplace',
|
1708
1987
|
'params': self.sign_params(self.extend(payload, params)),
|
1709
1988
|
}
|
1710
1989
|
subscription = {
|
@@ -1714,6 +1993,7 @@ class binance(ccxt.async_support.binance):
|
|
1714
1993
|
|
1715
1994
|
def handle_edit_order_ws(self, client: Client, message):
|
1716
1995
|
#
|
1996
|
+
# spot
|
1717
1997
|
# {
|
1718
1998
|
# "id": 1,
|
1719
1999
|
# "status": 200,
|
@@ -1778,16 +2058,52 @@ class binance(ccxt.async_support.binance):
|
|
1778
2058
|
# }
|
1779
2059
|
# ]
|
1780
2060
|
# }
|
2061
|
+
# swap
|
2062
|
+
# {
|
2063
|
+
# "id":"1",
|
2064
|
+
# "status":200,
|
2065
|
+
# "result":{
|
2066
|
+
# "orderId":667061487,
|
2067
|
+
# "symbol":"LTCUSDT",
|
2068
|
+
# "status":"NEW",
|
2069
|
+
# "clientOrderId":"x-xcKtGhcu91a74c818749ee42c0f70",
|
2070
|
+
# "price":"82.00",
|
2071
|
+
# "avgPrice":"0.00",
|
2072
|
+
# "origQty":"1.000",
|
2073
|
+
# "executedQty":"0.000",
|
2074
|
+
# "cumQty":"0.000",
|
2075
|
+
# "cumQuote":"0.00000",
|
2076
|
+
# "timeInForce":"GTC",
|
2077
|
+
# "type":"LIMIT",
|
2078
|
+
# "reduceOnly":false,
|
2079
|
+
# "closePosition":false,
|
2080
|
+
# "side":"BUY",
|
2081
|
+
# "positionSide":"BOTH",
|
2082
|
+
# "stopPrice":"0.00",
|
2083
|
+
# "workingType":"CONTRACT_PRICE",
|
2084
|
+
# "priceProtect":false,
|
2085
|
+
# "origType":"LIMIT",
|
2086
|
+
# "priceMatch":"NONE",
|
2087
|
+
# "selfTradePreventionMode":"NONE",
|
2088
|
+
# "goodTillDate":0,
|
2089
|
+
# "updateTime":1712918927511
|
2090
|
+
# }
|
2091
|
+
# }
|
1781
2092
|
#
|
1782
2093
|
messageHash = self.safe_string(message, 'id')
|
1783
|
-
result = self.
|
1784
|
-
|
1785
|
-
order =
|
2094
|
+
result = self.safe_dict(message, 'result', {})
|
2095
|
+
newSpotOrder = self.safe_dict(result, 'newOrderResponse')
|
2096
|
+
order = None
|
2097
|
+
if newSpotOrder is not None:
|
2098
|
+
order = self.parse_order(newSpotOrder)
|
2099
|
+
else:
|
2100
|
+
order = self.parse_order(result)
|
1786
2101
|
client.resolve(order, messageHash)
|
1787
2102
|
|
1788
2103
|
async def cancel_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
|
1789
2104
|
"""
|
1790
2105
|
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#cancel-order-trade
|
2106
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#cancel-order-trade-2
|
1791
2107
|
cancel multiple orders
|
1792
2108
|
:param str id: order id
|
1793
2109
|
:param str symbol: unified market symbol, default is None
|
@@ -1798,8 +2114,9 @@ class binance(ccxt.async_support.binance):
|
|
1798
2114
|
await self.load_markets()
|
1799
2115
|
if symbol is None:
|
1800
2116
|
raise BadRequest(self.id + ' cancelOrderWs requires a symbol')
|
1801
|
-
self.
|
1802
|
-
|
2117
|
+
market = self.market(symbol)
|
2118
|
+
type = self.get_market_type('cancelOrderWs', market, params)
|
2119
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1803
2120
|
requestId = self.request_id(url)
|
1804
2121
|
messageHash = str(requestId)
|
1805
2122
|
returnRateLimits = False
|
@@ -1808,7 +2125,7 @@ class binance(ccxt.async_support.binance):
|
|
1808
2125
|
'symbol': self.market_id(symbol),
|
1809
2126
|
'returnRateLimits': returnRateLimits,
|
1810
2127
|
}
|
1811
|
-
clientOrderId = self.
|
2128
|
+
clientOrderId = self.safe_string_2(params, 'origClientOrderId', 'clientOrderId')
|
1812
2129
|
if clientOrderId is not None:
|
1813
2130
|
payload['origClientOrderId'] = clientOrderId
|
1814
2131
|
else:
|
@@ -1833,7 +2150,11 @@ class binance(ccxt.async_support.binance):
|
|
1833
2150
|
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1834
2151
|
"""
|
1835
2152
|
await self.load_markets()
|
1836
|
-
|
2153
|
+
market = self.market(symbol)
|
2154
|
+
type = self.get_market_type('cancelAllOrdersWs', market, params)
|
2155
|
+
if type != 'spot' and type != 'future':
|
2156
|
+
raise BadRequest(self.id + ' cancelAllOrdersWs only supports spot or swap markets')
|
2157
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1837
2158
|
requestId = self.request_id(url)
|
1838
2159
|
messageHash = str(requestId)
|
1839
2160
|
returnRateLimits = False
|
@@ -1855,6 +2176,7 @@ class binance(ccxt.async_support.binance):
|
|
1855
2176
|
async def fetch_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
|
1856
2177
|
"""
|
1857
2178
|
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#query-order-user_data
|
2179
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#query-order-user_data-2
|
1858
2180
|
fetches information on an order made by the user
|
1859
2181
|
:param str symbol: unified symbol of the market the order was made in
|
1860
2182
|
:param dict params: extra parameters specific to the exchange API endpoint
|
@@ -1863,8 +2185,11 @@ class binance(ccxt.async_support.binance):
|
|
1863
2185
|
await self.load_markets()
|
1864
2186
|
if symbol is None:
|
1865
2187
|
raise BadRequest(self.id + ' cancelOrderWs requires a symbol')
|
1866
|
-
self.
|
1867
|
-
|
2188
|
+
market = self.market(symbol)
|
2189
|
+
type = self.get_market_type('fetchOrderWs', market, params)
|
2190
|
+
if type != 'spot' and type != 'future':
|
2191
|
+
raise BadRequest(self.id + ' fetchOrderWs only supports spot or swap markets')
|
2192
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1868
2193
|
requestId = self.request_id(url)
|
1869
2194
|
messageHash = str(requestId)
|
1870
2195
|
returnRateLimits = False
|
@@ -1873,7 +2198,7 @@ class binance(ccxt.async_support.binance):
|
|
1873
2198
|
'symbol': self.market_id(symbol),
|
1874
2199
|
'returnRateLimits': returnRateLimits,
|
1875
2200
|
}
|
1876
|
-
clientOrderId = self.
|
2201
|
+
clientOrderId = self.safe_string_2(params, 'origClientOrderId', 'clientOrderId')
|
1877
2202
|
if clientOrderId is not None:
|
1878
2203
|
payload['origClientOrderId'] = clientOrderId
|
1879
2204
|
else:
|
@@ -1905,8 +2230,11 @@ class binance(ccxt.async_support.binance):
|
|
1905
2230
|
await self.load_markets()
|
1906
2231
|
if symbol is None:
|
1907
2232
|
raise BadRequest(self.id + ' fetchOrdersWs requires a symbol')
|
1908
|
-
self.
|
1909
|
-
|
2233
|
+
market = self.market(symbol)
|
2234
|
+
type = self.get_market_type('fetchOrdersWs', market, params)
|
2235
|
+
if type != 'spot':
|
2236
|
+
raise BadRequest(self.id + ' fetchOrdersWs only supports spot markets')
|
2237
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1910
2238
|
requestId = self.request_id(url)
|
1911
2239
|
messageHash = str(requestId)
|
1912
2240
|
returnRateLimits = False
|
@@ -1955,8 +2283,11 @@ class binance(ccxt.async_support.binance):
|
|
1955
2283
|
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1956
2284
|
"""
|
1957
2285
|
await self.load_markets()
|
1958
|
-
self.
|
1959
|
-
|
2286
|
+
market = self.market(symbol)
|
2287
|
+
type = self.get_market_type('fetchOpenOrdersWs', market, params)
|
2288
|
+
if type != 'spot' and type != 'future':
|
2289
|
+
raise BadRequest(self.id + ' fetchOpenOrdersWs only supports spot or swap markets')
|
2290
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1960
2291
|
requestId = self.request_id(url)
|
1961
2292
|
messageHash = str(requestId)
|
1962
2293
|
returnRateLimits = False
|
@@ -2157,7 +2488,7 @@ class binance(ccxt.async_support.binance):
|
|
2157
2488
|
'type': type,
|
2158
2489
|
'timeInForce': timeInForce,
|
2159
2490
|
'postOnly': None,
|
2160
|
-
'reduceOnly': self.
|
2491
|
+
'reduceOnly': self.safe_bool(order, 'R'),
|
2161
2492
|
'side': side,
|
2162
2493
|
'price': price,
|
2163
2494
|
'stopPrice': stopPrice,
|
@@ -2256,7 +2587,7 @@ class binance(ccxt.async_support.binance):
|
|
2256
2587
|
#
|
2257
2588
|
e = self.safe_string(message, 'e')
|
2258
2589
|
if e == 'ORDER_TRADE_UPDATE':
|
2259
|
-
message = self.
|
2590
|
+
message = self.safe_dict(message, 'o', message)
|
2260
2591
|
self.handle_my_trade(client, message)
|
2261
2592
|
self.handle_order(client, message)
|
2262
2593
|
|
@@ -2383,8 +2714,8 @@ class binance(ccxt.async_support.binance):
|
|
2383
2714
|
if not (accountType in self.positions):
|
2384
2715
|
self.positions[accountType] = ArrayCacheBySymbolBySide()
|
2385
2716
|
cache = self.positions[accountType]
|
2386
|
-
data = self.
|
2387
|
-
rawPositions = self.
|
2717
|
+
data = self.safe_dict(message, 'a', {})
|
2718
|
+
rawPositions = self.safe_list(data, 'P', [])
|
2388
2719
|
newPositions = []
|
2389
2720
|
for i in range(0, len(rawPositions)):
|
2390
2721
|
rawPosition = rawPositions[i]
|
@@ -2471,8 +2802,11 @@ class binance(ccxt.async_support.binance):
|
|
2471
2802
|
await self.load_markets()
|
2472
2803
|
if symbol is None:
|
2473
2804
|
raise BadRequest(self.id + ' fetchMyTradesWs requires a symbol')
|
2474
|
-
self.
|
2475
|
-
|
2805
|
+
market = self.market(symbol)
|
2806
|
+
type = self.get_market_type('fetchMyTradesWs', market, params)
|
2807
|
+
if type != 'spot' and type != 'future':
|
2808
|
+
raise BadRequest(self.id + ' fetchMyTradesWs does not support ' + type + ' markets')
|
2809
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
2476
2810
|
requestId = self.request_id(url)
|
2477
2811
|
messageHash = str(requestId)
|
2478
2812
|
returnRateLimits = False
|
@@ -2515,8 +2849,11 @@ class binance(ccxt.async_support.binance):
|
|
2515
2849
|
await self.load_markets()
|
2516
2850
|
if symbol is None:
|
2517
2851
|
raise BadRequest(self.id + ' fetchTradesWs() requires a symbol argument')
|
2518
|
-
self.
|
2519
|
-
|
2852
|
+
market = self.market(symbol)
|
2853
|
+
type = self.get_market_type('fetchTradesWs', market, params)
|
2854
|
+
if type != 'spot' and type != 'future':
|
2855
|
+
raise BadRequest(self.id + ' fetchTradesWs does not support ' + type + ' markets')
|
2856
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
2520
2857
|
requestId = self.request_id(url)
|
2521
2858
|
messageHash = str(requestId)
|
2522
2859
|
returnRateLimits = False
|
@@ -2585,7 +2922,7 @@ class binance(ccxt.async_support.binance):
|
|
2585
2922
|
# }
|
2586
2923
|
#
|
2587
2924
|
messageHash = self.safe_string(message, 'id')
|
2588
|
-
result = self.
|
2925
|
+
result = self.safe_list(message, 'result', [])
|
2589
2926
|
trades = self.parse_trades(result)
|
2590
2927
|
client.resolve(trades, messageHash)
|
2591
2928
|
|
@@ -2641,7 +2978,7 @@ class binance(ccxt.async_support.binance):
|
|
2641
2978
|
if executionType == 'TRADE':
|
2642
2979
|
trade = self.parse_ws_trade(message)
|
2643
2980
|
orderId = self.safe_string(trade, 'order')
|
2644
|
-
tradeFee = self.
|
2981
|
+
tradeFee = self.safe_dict(trade, 'fee', {})
|
2645
2982
|
tradeFee = self.extend({}, tradeFee)
|
2646
2983
|
symbol = self.safe_string(trade, 'symbol')
|
2647
2984
|
if orderId is not None and tradeFee is not None and symbol is not None:
|
@@ -2676,7 +3013,7 @@ class binance(ccxt.async_support.binance):
|
|
2676
3013
|
else:
|
2677
3014
|
order['fee'] = tradeFee
|
2678
3015
|
# save self trade in the order
|
2679
|
-
orderTrades = self.
|
3016
|
+
orderTrades = self.safe_list(order, 'trades', [])
|
2680
3017
|
orderTrades.append(trade)
|
2681
3018
|
order['trades'] = orderTrades
|
2682
3019
|
# don't append twice cause it breaks newUpdates mode
|
@@ -2735,7 +3072,7 @@ class binance(ccxt.async_support.binance):
|
|
2735
3072
|
#
|
2736
3073
|
id = self.safe_string(message, 'id')
|
2737
3074
|
rejected = False
|
2738
|
-
error = self.
|
3075
|
+
error = self.safe_dict(message, 'error', {})
|
2739
3076
|
code = self.safe_integer(error, 'code')
|
2740
3077
|
msg = self.safe_string(error, 'msg')
|
2741
3078
|
try:
|