ccxt 4.3.62__py2.py3-none-any.whl → 4.3.64__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.
- ccxt/__init__.py +2 -1
- ccxt/abstract/binance.py +5 -5
- ccxt/abstract/binancecoinm.py +5 -5
- ccxt/abstract/binanceus.py +5 -5
- ccxt/abstract/binanceusdm.py +5 -5
- ccxt/abstract/cryptocom.py +11 -0
- ccxt/abstract/kucoin.py +1 -0
- ccxt/abstract/kucoinfutures.py +1 -0
- ccxt/abstract/woo.py +3 -0
- ccxt/ace.py +33 -15
- ccxt/alpaca.py +1 -0
- ccxt/async_support/__init__.py +2 -1
- ccxt/async_support/ace.py +33 -15
- ccxt/async_support/alpaca.py +1 -0
- ccxt/async_support/base/exchange.py +4 -4
- ccxt/async_support/binance.py +6 -9
- ccxt/async_support/bingx.py +534 -152
- ccxt/async_support/bitfinex.py +1 -1
- ccxt/async_support/bitfinex2.py +1 -1
- ccxt/async_support/coinbaseinternational.py +1 -1
- ccxt/async_support/cryptocom.py +17 -2
- ccxt/async_support/independentreserve.py +103 -1
- ccxt/async_support/kucoin.py +2 -0
- ccxt/async_support/mercado.py +5 -1
- ccxt/async_support/whitebit.py +1 -1
- ccxt/async_support/woo.py +321 -81
- ccxt/async_support/xt.py +3 -3
- ccxt/async_support/yobit.py +1 -1
- ccxt/async_support/zonda.py +1 -1
- ccxt/base/errors.py +8 -1
- ccxt/base/exchange.py +11 -5
- ccxt/binance.py +6 -9
- ccxt/bingx.py +534 -152
- ccxt/bitfinex.py +1 -1
- ccxt/bitfinex2.py +1 -1
- ccxt/coinbaseinternational.py +1 -1
- ccxt/cryptocom.py +17 -2
- ccxt/independentreserve.py +103 -1
- ccxt/kucoin.py +2 -0
- ccxt/mercado.py +5 -1
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +56 -35
- ccxt/pro/bitfinex2.py +6 -4
- ccxt/pro/bitget.py +5 -2
- ccxt/pro/bitmart.py +3 -3
- ccxt/pro/bitvavo.py +1 -1
- ccxt/pro/bybit.py +41 -18
- ccxt/pro/cryptocom.py +7 -2
- ccxt/pro/gate.py +7 -4
- ccxt/pro/gemini.py +4 -2
- ccxt/pro/htx.py +5 -1
- ccxt/pro/independentreserve.py +6 -4
- ccxt/pro/kraken.py +79 -6
- ccxt/pro/okx.py +5 -5
- ccxt/pro/onetrading.py +3 -2
- ccxt/pro/oxfun.py +1 -1
- ccxt/pro/poloniexfutures.py +5 -2
- ccxt/pro/vertex.py +3 -2
- ccxt/pro/woo.py +2 -1
- ccxt/pro/woofipro.py +3 -2
- ccxt/test/tests_async.py +3 -3
- ccxt/test/tests_helpers.py +1 -1
- ccxt/test/tests_init.py +3 -3
- ccxt/test/tests_sync.py +3 -3
- ccxt/whitebit.py +1 -1
- ccxt/woo.py +321 -81
- ccxt/xt.py +3 -3
- ccxt/yobit.py +1 -1
- ccxt/zonda.py +1 -1
- {ccxt-4.3.62.dist-info → ccxt-4.3.64.dist-info}/METADATA +4 -4
- {ccxt-4.3.62.dist-info → ccxt-4.3.64.dist-info}/RECORD +74 -74
- {ccxt-4.3.62.dist-info → ccxt-4.3.64.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.3.62.dist-info → ccxt-4.3.64.dist-info}/WHEEL +0 -0
- {ccxt-4.3.62.dist-info → ccxt-4.3.64.dist-info}/top_level.txt +0 -0
ccxt/pro/gate.py
CHANGED
@@ -14,7 +14,7 @@ from ccxt.base.errors import AuthenticationError
|
|
14
14
|
from ccxt.base.errors import ArgumentsRequired
|
15
15
|
from ccxt.base.errors import BadRequest
|
16
16
|
from ccxt.base.errors import NotSupported
|
17
|
-
from ccxt.base.errors import
|
17
|
+
from ccxt.base.errors import ChecksumError
|
18
18
|
from ccxt.base.precise import Precise
|
19
19
|
|
20
20
|
|
@@ -105,6 +105,7 @@ class gate(ccxt.async_support.gate):
|
|
105
105
|
'interval': '100ms',
|
106
106
|
'snapshotDelay': 10, # how many deltas to cache before fetching a snapshot
|
107
107
|
'snapshotMaxRetries': 3,
|
108
|
+
'checksum': True,
|
108
109
|
},
|
109
110
|
'watchBalance': {
|
110
111
|
'settle': 'usdt', # or btc
|
@@ -460,10 +461,12 @@ class gate(ccxt.async_support.gate):
|
|
460
461
|
elif nonce >= deltaStart - 1:
|
461
462
|
self.handle_delta(storedOrderBook, delta)
|
462
463
|
else:
|
463
|
-
error = InvalidNonce(self.id + ' orderbook update has a nonce bigger than u')
|
464
464
|
del client.subscriptions[messageHash]
|
465
465
|
del self.orderbooks[symbol]
|
466
|
-
|
466
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
467
|
+
if checksum:
|
468
|
+
error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
469
|
+
client.reject(error, messageHash)
|
467
470
|
client.resolve(storedOrderBook, messageHash)
|
468
471
|
|
469
472
|
def get_cache_index(self, orderBook, cache):
|
@@ -1192,7 +1195,7 @@ class gate(ccxt.async_support.gate):
|
|
1192
1195
|
elif event == 'finish':
|
1193
1196
|
status = self.safe_string(parsed, 'status')
|
1194
1197
|
if status is None:
|
1195
|
-
left = self.
|
1198
|
+
left = self.safe_integer(info, 'left')
|
1196
1199
|
parsed['status'] = 'closed' if (left == 0) else 'canceled'
|
1197
1200
|
stored.append(parsed)
|
1198
1201
|
symbol = parsed['symbol']
|
ccxt/pro/gemini.py
CHANGED
@@ -11,6 +11,7 @@ from ccxt.async_support.base.ws.client import Client
|
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
13
13
|
from ccxt.base.errors import NotSupported
|
14
|
+
from ccxt.base.precise import Precise
|
14
15
|
|
15
16
|
|
16
17
|
class gemini(ccxt.async_support.gemini):
|
@@ -445,9 +446,10 @@ class gemini(ccxt.async_support.gemini):
|
|
445
446
|
entry = rawBidAskChanges[i]
|
446
447
|
rawSide = self.safe_string(entry, 'side')
|
447
448
|
price = self.safe_number(entry, 'price')
|
448
|
-
|
449
|
-
if
|
449
|
+
sizeString = self.safe_string(entry, 'remaining')
|
450
|
+
if Precise.string_eq(sizeString, '0'):
|
450
451
|
continue
|
452
|
+
size = self.parse_number(sizeString)
|
451
453
|
if rawSide == 'bid':
|
452
454
|
currentBidAsk['bid'] = price
|
453
455
|
currentBidAsk['bidVolume'] = size
|
ccxt/pro/htx.py
CHANGED
@@ -16,6 +16,7 @@ from ccxt.base.errors import BadRequest
|
|
16
16
|
from ccxt.base.errors import BadSymbol
|
17
17
|
from ccxt.base.errors import NetworkError
|
18
18
|
from ccxt.base.errors import InvalidNonce
|
19
|
+
from ccxt.base.errors import ChecksumError
|
19
20
|
|
20
21
|
|
21
22
|
class htx(ccxt.async_support.htx):
|
@@ -109,6 +110,7 @@ class htx(ccxt.async_support.htx):
|
|
109
110
|
'api': 'api', # or api-aws for clients hosted on AWS
|
110
111
|
'watchOrderBook': {
|
111
112
|
'maxRetries': 3,
|
113
|
+
'checksum': True,
|
112
114
|
},
|
113
115
|
'ws': {
|
114
116
|
'gunzip': True,
|
@@ -549,7 +551,9 @@ class htx(ccxt.async_support.htx):
|
|
549
551
|
orderbook.reset(snapshot)
|
550
552
|
orderbook['nonce'] = version
|
551
553
|
if (prevSeqNum is not None) and prevSeqNum > orderbook['nonce']:
|
552
|
-
|
554
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
555
|
+
if checksum:
|
556
|
+
raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
553
557
|
spotConditon = market['spot'] and (prevSeqNum == orderbook['nonce'])
|
554
558
|
nonSpotCondition = market['contract'] and (version - 1 == orderbook['nonce'])
|
555
559
|
if spotConditon or nonSpotCondition:
|
ccxt/pro/independentreserve.py
CHANGED
@@ -9,7 +9,7 @@ from ccxt.base.types import Int, OrderBook, Trade
|
|
9
9
|
from ccxt.async_support.base.ws.client import Client
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import NotSupported
|
12
|
-
from ccxt.base.errors import
|
12
|
+
from ccxt.base.errors import ChecksumError
|
13
13
|
|
14
14
|
|
15
15
|
class independentreserve(ccxt.async_support.independentreserve):
|
@@ -33,7 +33,9 @@ class independentreserve(ccxt.async_support.independentreserve):
|
|
33
33
|
},
|
34
34
|
},
|
35
35
|
'options': {
|
36
|
-
'
|
36
|
+
'watchOrderBook': {
|
37
|
+
'checksum': True, # TODO: currently only working for snapshot
|
38
|
+
},
|
37
39
|
},
|
38
40
|
'streaming': {
|
39
41
|
},
|
@@ -196,7 +198,7 @@ class independentreserve(ccxt.async_support.independentreserve):
|
|
196
198
|
self.handle_deltas(orderbook['bids'], bids)
|
197
199
|
orderbook['timestamp'] = timestamp
|
198
200
|
orderbook['datetime'] = self.iso8601(timestamp)
|
199
|
-
checksum = self.
|
201
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
200
202
|
if checksum and receivedSnapshot:
|
201
203
|
storedAsks = orderbook['asks']
|
202
204
|
storedBids = orderbook['bids']
|
@@ -212,7 +214,7 @@ class independentreserve(ccxt.async_support.independentreserve):
|
|
212
214
|
calculatedChecksum = self.crc32(payload, True)
|
213
215
|
responseChecksum = self.safe_integer(orderBook, 'Crc32')
|
214
216
|
if calculatedChecksum != responseChecksum:
|
215
|
-
error =
|
217
|
+
error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
216
218
|
del client.subscriptions[messageHash]
|
217
219
|
del self.orderbooks[symbol]
|
218
220
|
client.reject(error, messageHash)
|
ccxt/pro/kraken.py
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
import ccxt.async_support
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
|
8
|
-
from ccxt.base.types import Int, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade
|
8
|
+
from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade
|
9
9
|
from ccxt.async_support.base.ws.client import Client
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
@@ -20,7 +20,7 @@ from ccxt.base.errors import OrderNotFound
|
|
20
20
|
from ccxt.base.errors import NotSupported
|
21
21
|
from ccxt.base.errors import RateLimitExceeded
|
22
22
|
from ccxt.base.errors import ExchangeNotAvailable
|
23
|
-
from ccxt.base.errors import
|
23
|
+
from ccxt.base.errors import ChecksumError
|
24
24
|
from ccxt.base.precise import Precise
|
25
25
|
|
26
26
|
|
@@ -30,7 +30,7 @@ class kraken(ccxt.async_support.kraken):
|
|
30
30
|
return self.deep_extend(super(kraken, self).describe(), {
|
31
31
|
'has': {
|
32
32
|
'ws': True,
|
33
|
-
'watchBalance':
|
33
|
+
'watchBalance': True,
|
34
34
|
'watchMyTrades': True,
|
35
35
|
'watchOHLCV': True,
|
36
36
|
'watchOrderBook': True,
|
@@ -53,6 +53,7 @@ class kraken(ccxt.async_support.kraken):
|
|
53
53
|
'ws': {
|
54
54
|
'public': 'wss://ws.kraken.com',
|
55
55
|
'private': 'wss://ws-auth.kraken.com',
|
56
|
+
'privateV2': 'wss://ws-auth.kraken.com/v2',
|
56
57
|
'beta': 'wss://beta-ws.kraken.com',
|
57
58
|
'beta-private': 'wss://beta-ws-auth.kraken.com',
|
58
59
|
},
|
@@ -66,7 +67,9 @@ class kraken(ccxt.async_support.kraken):
|
|
66
67
|
'OHLCVLimit': 1000,
|
67
68
|
'ordersLimit': 1000,
|
68
69
|
'symbolsByOrderId': {},
|
69
|
-
'
|
70
|
+
'watchOrderBook': {
|
71
|
+
'checksum': True,
|
72
|
+
},
|
70
73
|
},
|
71
74
|
'exceptions': {
|
72
75
|
'ws': {
|
@@ -715,7 +718,7 @@ class kraken(ccxt.async_support.kraken):
|
|
715
718
|
example = self.safe_value(b, 0)
|
716
719
|
# don't remove self line or I will poop on your face
|
717
720
|
orderbook.limit()
|
718
|
-
checksum = self.
|
721
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
719
722
|
if checksum:
|
720
723
|
priceString = self.safe_string(example, 0)
|
721
724
|
amountString = self.safe_string(example, 1)
|
@@ -734,7 +737,7 @@ class kraken(ccxt.async_support.kraken):
|
|
734
737
|
payload = ''.join(payloadArray)
|
735
738
|
localChecksum = self.crc32(payload, False)
|
736
739
|
if localChecksum != c:
|
737
|
-
error =
|
740
|
+
error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
738
741
|
del client.subscriptions[messageHash]
|
739
742
|
del self.orderbooks[symbol]
|
740
743
|
client.reject(error, messageHash)
|
@@ -1247,6 +1250,68 @@ class kraken(ccxt.async_support.kraken):
|
|
1247
1250
|
url = self.urls['api']['ws']['public']
|
1248
1251
|
return await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), messageHashes, subscriptionArgs)
|
1249
1252
|
|
1253
|
+
async def watch_balance(self, params={}) -> Balances:
|
1254
|
+
"""
|
1255
|
+
watch balance and get the amount of funds available for trading or funds locked in orders
|
1256
|
+
:see: https://docs.kraken.com/api/docs/websocket-v2/balances
|
1257
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1258
|
+
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
1259
|
+
"""
|
1260
|
+
await self.load_markets()
|
1261
|
+
token = await self.authenticate()
|
1262
|
+
messageHash = 'balances'
|
1263
|
+
url = self.urls['api']['ws']['privateV2']
|
1264
|
+
requestId = self.request_id()
|
1265
|
+
subscribe: dict = {
|
1266
|
+
'method': 'subscribe',
|
1267
|
+
'req_id': requestId,
|
1268
|
+
'params': {
|
1269
|
+
'channel': 'balances',
|
1270
|
+
'token': token,
|
1271
|
+
},
|
1272
|
+
}
|
1273
|
+
request = self.deep_extend(subscribe, params)
|
1274
|
+
return await self.watch(url, messageHash, request, messageHash)
|
1275
|
+
|
1276
|
+
def handle_balance(self, client: Client, message):
|
1277
|
+
#
|
1278
|
+
# {
|
1279
|
+
# "channel": "balances",
|
1280
|
+
# "data": [
|
1281
|
+
# {
|
1282
|
+
# "asset": "BTC",
|
1283
|
+
# "asset_class": "currency",
|
1284
|
+
# "balance": 1.2,
|
1285
|
+
# "wallets": [
|
1286
|
+
# {
|
1287
|
+
# "type": "spot",
|
1288
|
+
# "id": "main",
|
1289
|
+
# "balance": 1.2
|
1290
|
+
# }
|
1291
|
+
# ]
|
1292
|
+
# }
|
1293
|
+
# ],
|
1294
|
+
# "type": "snapshot",
|
1295
|
+
# "sequence": 1
|
1296
|
+
# }
|
1297
|
+
#
|
1298
|
+
data = self.safe_list(message, 'data', [])
|
1299
|
+
result: dict = {'info': message}
|
1300
|
+
for i in range(0, len(data)):
|
1301
|
+
currencyId = self.safe_string(data[i], 'asset')
|
1302
|
+
code = self.safe_currency_code(currencyId)
|
1303
|
+
account = self.account()
|
1304
|
+
eq = self.safe_string(data[i], 'balance')
|
1305
|
+
account['total'] = eq
|
1306
|
+
result[code] = account
|
1307
|
+
type = 'spot'
|
1308
|
+
balance = self.safe_balance(result)
|
1309
|
+
oldBalance = self.safe_value(self.balance, type, {})
|
1310
|
+
newBalance = self.deep_extend(oldBalance, balance)
|
1311
|
+
self.balance[type] = self.safe_balance(newBalance)
|
1312
|
+
channel = self.safe_string(message, 'channel')
|
1313
|
+
client.resolve(self.balance[type], channel)
|
1314
|
+
|
1250
1315
|
def get_message_hash(self, unifiedElementName: str, subChannelName: Str = None, symbol: Str = None):
|
1251
1316
|
# unifiedElementName can be : orderbook, trade, ticker, bidask ...
|
1252
1317
|
# subChannelName only applies to channel that needs specific variation(i.e. depth_50, depth_100..) to be selected
|
@@ -1340,6 +1405,14 @@ class kraken(ccxt.async_support.kraken):
|
|
1340
1405
|
if method is not None:
|
1341
1406
|
method(client, message, subscription)
|
1342
1407
|
else:
|
1408
|
+
channel = self.safe_string(message, 'channel')
|
1409
|
+
if channel is not None:
|
1410
|
+
methods: dict = {
|
1411
|
+
'balances': self.handle_balance,
|
1412
|
+
}
|
1413
|
+
method = self.safe_value(methods, channel)
|
1414
|
+
if method is not None:
|
1415
|
+
method(client, message)
|
1343
1416
|
if self.handle_error_message(client, message):
|
1344
1417
|
event = self.safe_string(message, 'event')
|
1345
1418
|
methods: dict = {
|
ccxt/pro/okx.py
CHANGED
@@ -13,7 +13,7 @@ from ccxt.base.errors import ExchangeError
|
|
13
13
|
from ccxt.base.errors import AuthenticationError
|
14
14
|
from ccxt.base.errors import ArgumentsRequired
|
15
15
|
from ccxt.base.errors import BadRequest
|
16
|
-
from ccxt.base.errors import
|
16
|
+
from ccxt.base.errors import ChecksumError
|
17
17
|
|
18
18
|
|
19
19
|
class okx(ccxt.async_support.okx):
|
@@ -56,6 +56,7 @@ class okx(ccxt.async_support.okx):
|
|
56
56
|
},
|
57
57
|
'options': {
|
58
58
|
'watchOrderBook': {
|
59
|
+
'checksum': True,
|
59
60
|
#
|
60
61
|
# bbo-tbt
|
61
62
|
# 1. Newly added channel that sends tick-by-tick Level 1 data
|
@@ -103,7 +104,6 @@ class okx(ccxt.async_support.okx):
|
|
103
104
|
'ws': {
|
104
105
|
# 'inflate': True,
|
105
106
|
},
|
106
|
-
'checksum': True,
|
107
107
|
},
|
108
108
|
'streaming': {
|
109
109
|
# okex does not support built-in ws protocol-level ping-pong
|
@@ -861,7 +861,7 @@ class okx(ccxt.async_support.okx):
|
|
861
861
|
self.handle_deltas(storedBids, bids)
|
862
862
|
marketId = self.safe_string(message, 'instId')
|
863
863
|
symbol = self.safe_symbol(marketId)
|
864
|
-
checksum = self.
|
864
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
865
865
|
if checksum:
|
866
866
|
asksLength = len(storedAsks)
|
867
867
|
bidsLength = len(storedBids)
|
@@ -877,7 +877,7 @@ class okx(ccxt.async_support.okx):
|
|
877
877
|
responseChecksum = self.safe_integer(message, 'checksum')
|
878
878
|
localChecksum = self.crc32(payload, True)
|
879
879
|
if responseChecksum != localChecksum:
|
880
|
-
error =
|
880
|
+
error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
881
881
|
del client.subscriptions[messageHash]
|
882
882
|
del self.orderbooks[symbol]
|
883
883
|
client.reject(error, messageHash)
|
@@ -1645,7 +1645,7 @@ class okx(ccxt.async_support.okx):
|
|
1645
1645
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1646
1646
|
:returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1647
1647
|
"""
|
1648
|
-
idsLength = len(ids)
|
1648
|
+
idsLength: number = len(ids)
|
1649
1649
|
if idsLength > 20:
|
1650
1650
|
raise BadRequest(self.id + ' cancelOrdersWs() accepts up to 20 ids at a time')
|
1651
1651
|
if symbol is None:
|
ccxt/pro/onetrading.py
CHANGED
@@ -10,6 +10,7 @@ from ccxt.async_support.base.ws.client import Client
|
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
12
|
from ccxt.base.errors import NotSupported
|
13
|
+
from ccxt.base.precise import Precise
|
13
14
|
|
14
15
|
|
15
16
|
class onetrading(ccxt.async_support.onetrading):
|
@@ -934,9 +935,9 @@ class onetrading(ccxt.async_support.onetrading):
|
|
934
935
|
previousOrderArray = self.filter_by_array(self.orders, 'id', orderId, False)
|
935
936
|
previousOrder = self.safe_value(previousOrderArray, 0, {})
|
936
937
|
symbol = previousOrder['symbol']
|
937
|
-
filled = self.
|
938
|
+
filled = self.safe_string(update, 'filled_amount')
|
938
939
|
status = self.parse_ws_order_status(updateType)
|
939
|
-
if updateType == 'ORDER_CLOSED' and filled
|
940
|
+
if updateType == 'ORDER_CLOSED' and Precise.string_eq(filled, '0'):
|
940
941
|
status = 'canceled'
|
941
942
|
orderObject: dict = {
|
942
943
|
'id': orderId,
|
ccxt/pro/oxfun.py
CHANGED
@@ -854,7 +854,7 @@ class oxfun(ccxt.async_support.oxfun):
|
|
854
854
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
855
855
|
:returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
856
856
|
"""
|
857
|
-
idsLength = len(ids)
|
857
|
+
idsLength: number = len(ids)
|
858
858
|
if idsLength > 20:
|
859
859
|
raise BadRequest(self.id + ' cancelOrdersWs() accepts up to 20 ids at a time')
|
860
860
|
if symbol is None:
|
ccxt/pro/poloniexfutures.py
CHANGED
@@ -10,7 +10,7 @@ from ccxt.async_support.base.ws.client import Client
|
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import AuthenticationError
|
12
12
|
from ccxt.base.errors import BadRequest
|
13
|
-
from ccxt.base.errors import
|
13
|
+
from ccxt.base.errors import ChecksumError
|
14
14
|
|
15
15
|
|
16
16
|
class poloniexfutures(ccxt.async_support.poloniexfutures):
|
@@ -57,6 +57,7 @@ class poloniexfutures(ccxt.async_support.poloniexfutures):
|
|
57
57
|
'method': '/contractMarket/level2', # can also be '/contractMarket/level3v2'
|
58
58
|
'snapshotDelay': 5,
|
59
59
|
'snapshotMaxRetries': 3,
|
60
|
+
'checksum': True,
|
60
61
|
},
|
61
62
|
'streamLimit': 5, # called tunnels by poloniexfutures docs
|
62
63
|
'streamBySubscriptionsHash': {},
|
@@ -822,7 +823,9 @@ class poloniexfutures(ccxt.async_support.poloniexfutures):
|
|
822
823
|
if nonce > sequence:
|
823
824
|
return
|
824
825
|
if nonce != lastSequence:
|
825
|
-
|
826
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
827
|
+
if checksum:
|
828
|
+
raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(''))
|
826
829
|
changes = self.safe_list(delta, 'changes')
|
827
830
|
for i in range(0, len(changes)):
|
828
831
|
change = changes[i]
|
ccxt/pro/vertex.py
CHANGED
@@ -798,9 +798,10 @@ class vertex(ccxt.async_support.vertex):
|
|
798
798
|
#
|
799
799
|
marketId = self.safe_string(order, 'product_id')
|
800
800
|
timestamp = self.parse_to_int(Precise.string_div(self.safe_string(order, 'timestamp'), '1000000'))
|
801
|
-
|
801
|
+
remainingString = self.convertFromX18(self.safe_string(order, 'amount'))
|
802
|
+
remaining = self.parse_to_numeric(remainingString)
|
802
803
|
status = self.parse_ws_order_status(self.safe_string(order, 'reason'))
|
803
|
-
if
|
804
|
+
if Precise.string_eq(remainingString, '0') and status == 'open':
|
804
805
|
status = 'closed'
|
805
806
|
market = self.safe_market(marketId, market)
|
806
807
|
symbol = market['symbol']
|
ccxt/pro/woo.py
CHANGED
@@ -638,9 +638,10 @@ class woo(ccxt.async_support.woo):
|
|
638
638
|
'cost': self.safe_string(order, 'totalFee'),
|
639
639
|
'currency': self.safe_string(order, 'feeAsset'),
|
640
640
|
}
|
641
|
+
priceString = self.safe_string(order, 'price')
|
641
642
|
price = self.safe_number(order, 'price')
|
642
643
|
avgPrice = self.safe_number(order, 'avgPrice')
|
643
|
-
if (
|
644
|
+
if Precise.string_eq(priceString, '0') and (avgPrice is not None):
|
644
645
|
price = avgPrice
|
645
646
|
amount = self.safe_float(order, 'quantity')
|
646
647
|
side = self.safe_string_lower(order, 'side')
|
ccxt/pro/woofipro.py
CHANGED
@@ -363,7 +363,7 @@ class woofipro(ccxt.async_support.woofipro):
|
|
363
363
|
:param int [since]: the earliest time in ms to fetch trades for
|
364
364
|
:param int [limit]: the maximum number of trade structures to retrieve
|
365
365
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
366
|
-
:returns dict[]: a list of
|
366
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
367
367
|
"""
|
368
368
|
await self.load_markets()
|
369
369
|
market = self.market(symbol)
|
@@ -686,9 +686,10 @@ class woofipro(ccxt.async_support.woofipro):
|
|
686
686
|
'cost': self.safe_string(order, 'totalFee'),
|
687
687
|
'currency': self.safe_string(order, 'feeAsset'),
|
688
688
|
}
|
689
|
+
priceString = self.safe_string(order, 'price')
|
689
690
|
price = self.safe_number(order, 'price')
|
690
691
|
avgPrice = self.safe_number(order, 'avgPrice')
|
691
|
-
if (
|
692
|
+
if Precise.string_eq(priceString, '0') and (avgPrice is not None):
|
692
693
|
price = avgPrice
|
693
694
|
amount = self.safe_string(order, 'quantity')
|
694
695
|
side = self.safe_string_lower(order, 'side')
|
ccxt/test/tests_async.py
CHANGED
@@ -818,7 +818,7 @@ class testMainClass(baseMainTestClass):
|
|
818
818
|
new_input.append(current)
|
819
819
|
return new_input
|
820
820
|
|
821
|
-
async def
|
821
|
+
async def test_request_statically(self, exchange, method, data, type, skip_keys):
|
822
822
|
output = None
|
823
823
|
request_url = None
|
824
824
|
try:
|
@@ -850,7 +850,7 @@ class testMainClass(baseMainTestClass):
|
|
850
850
|
unified_result_sync = call_exchange_method_dynamically_sync(exchange, method, self.sanitize_data_input(data['input']))
|
851
851
|
self.assert_static_response_output(mocked_exchange, skip_keys, unified_result_sync, expected_result)
|
852
852
|
except Exception as e:
|
853
|
-
self.
|
853
|
+
self.response_tests_failed = True
|
854
854
|
error_message = '[' + self.lang + '][STATIC_RESPONSE_TEST_FAILURE]' + '[' + self.exchange_hint(exchange) + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
|
855
855
|
dump('[TEST_FAILURE]' + error_message)
|
856
856
|
set_fetch_response(exchange, None) # reset state
|
@@ -929,7 +929,7 @@ class testMainClass(baseMainTestClass):
|
|
929
929
|
continue
|
930
930
|
type = exchange.safe_string(exchange_data, 'outputType')
|
931
931
|
skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
|
932
|
-
await self.
|
932
|
+
await self.test_request_statically(exchange, method, result, type, skip_keys)
|
933
933
|
# reset options
|
934
934
|
# exchange.options = exchange.deepExtend (oldExchangeOptions, {});
|
935
935
|
exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
|
ccxt/test/tests_helpers.py
CHANGED
@@ -73,7 +73,6 @@ parser.add_argument('--requestTests', action='store_true', help='run response te
|
|
73
73
|
parser.add_argument('--sync', action='store_true', help='is sync')
|
74
74
|
parser.add_argument('--baseTests', action='store_true', help='is base tests')
|
75
75
|
parser.add_argument('--exchangeTests', action='store_true', help='is exchange tests')
|
76
|
-
parser.add_argument('--nonce', type=int, help='integer')
|
77
76
|
parser.add_argument('exchange', type=str, help='exchange id in lowercase', nargs='?')
|
78
77
|
parser.add_argument('symbol', type=str, help='symbol in uppercase', nargs='?')
|
79
78
|
parser.parse_args(namespace=argv)
|
@@ -279,6 +278,7 @@ def set_fetch_response(exchange: ccxt.Exchange, data):
|
|
279
278
|
return exchange
|
280
279
|
|
281
280
|
|
281
|
+
argvExchange = argv.exchange
|
282
282
|
argvSymbol = argv.symbol if argv.symbol and '/' in argv.symbol else None
|
283
283
|
# in python, we check it through "symbol" arg (as opposed to JS/PHP) because argvs were already built above
|
284
284
|
argvMethod = argv.symbol if argv.symbol and '()' in argv.symbol else None
|
ccxt/test/tests_init.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
from tests_helpers import get_cli_arg_value, is_synchronous,
|
3
|
+
from tests_helpers import get_cli_arg_value, is_synchronous, argvExchange, argvSymbol, argvMethod
|
4
4
|
|
5
5
|
try:
|
6
6
|
import asyncio
|
@@ -29,7 +29,7 @@ if (isBaseTests):
|
|
29
29
|
# ###### exchange tests #######
|
30
30
|
if (is_synchronous):
|
31
31
|
from tests_sync import testMainClass as testMainClassSync
|
32
|
-
testMainClassSync().init(
|
32
|
+
testMainClassSync().init(argvExchange, argvSymbol, argvMethod)
|
33
33
|
else:
|
34
34
|
from tests_async import testMainClass as testMainClassAsync
|
35
|
-
asyncio.run(testMainClassAsync().init(
|
35
|
+
asyncio.run(testMainClassAsync().init(argvExchange, argvSymbol, argvMethod))
|
ccxt/test/tests_sync.py
CHANGED
@@ -815,7 +815,7 @@ class testMainClass(baseMainTestClass):
|
|
815
815
|
new_input.append(current)
|
816
816
|
return new_input
|
817
817
|
|
818
|
-
def
|
818
|
+
def test_request_statically(self, exchange, method, data, type, skip_keys):
|
819
819
|
output = None
|
820
820
|
request_url = None
|
821
821
|
try:
|
@@ -847,7 +847,7 @@ class testMainClass(baseMainTestClass):
|
|
847
847
|
unified_result_sync = call_exchange_method_dynamically_sync(exchange, method, self.sanitize_data_input(data['input']))
|
848
848
|
self.assert_static_response_output(mocked_exchange, skip_keys, unified_result_sync, expected_result)
|
849
849
|
except Exception as e:
|
850
|
-
self.
|
850
|
+
self.response_tests_failed = True
|
851
851
|
error_message = '[' + self.lang + '][STATIC_RESPONSE_TEST_FAILURE]' + '[' + self.exchange_hint(exchange) + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
|
852
852
|
dump('[TEST_FAILURE]' + error_message)
|
853
853
|
set_fetch_response(exchange, None) # reset state
|
@@ -926,7 +926,7 @@ class testMainClass(baseMainTestClass):
|
|
926
926
|
continue
|
927
927
|
type = exchange.safe_string(exchange_data, 'outputType')
|
928
928
|
skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
|
929
|
-
self.
|
929
|
+
self.test_request_statically(exchange, method, result, type, skip_keys)
|
930
930
|
# reset options
|
931
931
|
# exchange.options = exchange.deepExtend (oldExchangeOptions, {});
|
932
932
|
exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
|
ccxt/whitebit.py
CHANGED
@@ -2404,7 +2404,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
2404
2404
|
records = self.safe_list(response, 'records')
|
2405
2405
|
return self.parse_transactions(records, currency, since, limit)
|
2406
2406
|
|
2407
|
-
def is_fiat(self, currency):
|
2407
|
+
def is_fiat(self, currency: str):
|
2408
2408
|
fiatCurrencies = self.safe_value(self.options, 'fiatCurrencies', [])
|
2409
2409
|
return self.in_array(currency, fiatCurrencies)
|
2410
2410
|
|