ccxt 4.3.15__py2.py3-none-any.whl → 4.3.17__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.

Files changed (68) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/alpaca.py +1 -0
  3. ccxt/ascendex.py +1 -0
  4. ccxt/async_support/__init__.py +1 -1
  5. ccxt/async_support/alpaca.py +1 -0
  6. ccxt/async_support/ascendex.py +1 -0
  7. ccxt/async_support/base/exchange.py +18 -13
  8. ccxt/async_support/binance.py +10 -9
  9. ccxt/async_support/bingx.py +1 -0
  10. ccxt/async_support/bitmex.py +1 -0
  11. ccxt/async_support/bybit.py +11 -7
  12. ccxt/async_support/coinbaseinternational.py +1 -0
  13. ccxt/async_support/coinmetro.py +1 -0
  14. ccxt/async_support/cryptocom.py +1 -0
  15. ccxt/async_support/currencycom.py +1 -0
  16. ccxt/async_support/deribit.py +1 -0
  17. ccxt/async_support/gate.py +1 -0
  18. ccxt/async_support/gemini.py +1 -0
  19. ccxt/async_support/hitbtc.py +1 -0
  20. ccxt/async_support/hollaex.py +1 -0
  21. ccxt/async_support/hyperliquid.py +4 -0
  22. ccxt/async_support/idex.py +1 -0
  23. ccxt/async_support/krakenfutures.py +1 -0
  24. ccxt/async_support/ndax.py +1 -0
  25. ccxt/async_support/okx.py +19 -0
  26. ccxt/async_support/phemex.py +1 -0
  27. ccxt/async_support/poloniex.py +1 -0
  28. ccxt/async_support/probit.py +1 -0
  29. ccxt/async_support/wavesexchange.py +1 -0
  30. ccxt/async_support/woo.py +1 -0
  31. ccxt/async_support/zaif.py +1 -1
  32. ccxt/base/exchange.py +18 -13
  33. ccxt/binance.py +10 -9
  34. ccxt/bingx.py +1 -0
  35. ccxt/bitmex.py +1 -0
  36. ccxt/bybit.py +11 -7
  37. ccxt/coinbaseinternational.py +1 -0
  38. ccxt/coinmetro.py +1 -0
  39. ccxt/cryptocom.py +1 -0
  40. ccxt/currencycom.py +1 -0
  41. ccxt/deribit.py +1 -0
  42. ccxt/gate.py +1 -0
  43. ccxt/gemini.py +1 -0
  44. ccxt/hitbtc.py +1 -0
  45. ccxt/hollaex.py +1 -0
  46. ccxt/hyperliquid.py +4 -0
  47. ccxt/idex.py +1 -0
  48. ccxt/krakenfutures.py +1 -0
  49. ccxt/ndax.py +1 -0
  50. ccxt/okx.py +19 -0
  51. ccxt/phemex.py +1 -0
  52. ccxt/poloniex.py +1 -0
  53. ccxt/pro/__init__.py +1 -1
  54. ccxt/pro/bitfinex2.py +2 -0
  55. ccxt/pro/bitget.py +3 -0
  56. ccxt/pro/bybit.py +3 -3
  57. ccxt/pro/htx.py +2 -0
  58. ccxt/pro/independentreserve.py +2 -0
  59. ccxt/pro/kraken.py +2 -0
  60. ccxt/pro/okx.py +22 -18
  61. ccxt/probit.py +1 -0
  62. ccxt/wavesexchange.py +1 -0
  63. ccxt/woo.py +1 -0
  64. ccxt/zaif.py +1 -1
  65. {ccxt-4.3.15.dist-info → ccxt-4.3.17.dist-info}/METADATA +4 -4
  66. {ccxt-4.3.15.dist-info → ccxt-4.3.17.dist-info}/RECORD +68 -68
  67. {ccxt-4.3.15.dist-info → ccxt-4.3.17.dist-info}/WHEEL +0 -0
  68. {ccxt-4.3.15.dist-info → ccxt-4.3.17.dist-info}/top_level.txt +0 -0
ccxt/binance.py CHANGED
@@ -177,6 +177,7 @@ class binance(Exchange, ImplicitAPI):
177
177
  'reduceMargin': True,
178
178
  'repayCrossMargin': True,
179
179
  'repayIsolatedMargin': True,
180
+ 'sandbox': True,
180
181
  'setLeverage': True,
181
182
  'setMargin': False,
182
183
  'setMarginMode': True,
@@ -2610,7 +2611,7 @@ class binance(Exchange, ImplicitAPI):
2610
2611
  :param dict [params]: extra parameters specific to the exchange API endpoint
2611
2612
  :returns dict: an associative dictionary of currencies
2612
2613
  """
2613
- fetchCurrenciesEnabled = self.safe_value(self.options, 'fetchCurrencies')
2614
+ fetchCurrenciesEnabled = self.safe_bool(self.options, 'fetchCurrencies')
2614
2615
  if not fetchCurrenciesEnabled:
2615
2616
  return None
2616
2617
  # self endpoint requires authentication
@@ -4397,7 +4398,7 @@ class binance(Exchange, ImplicitAPI):
4397
4398
  market = self.safe_market(marketId, market, None, marketType)
4398
4399
  symbol = market['symbol']
4399
4400
  side = None
4400
- buyerMaker = self.safe_value_2(trade, 'm', 'isBuyerMaker')
4401
+ buyerMaker = self.safe_bool_2(trade, 'm', 'isBuyerMaker')
4401
4402
  takerOrMaker = None
4402
4403
  if buyerMaker is not None:
4403
4404
  side = 'sell' if buyerMaker else 'buy' # self is reversed intentionally
@@ -4673,14 +4674,14 @@ class binance(Exchange, ImplicitAPI):
4673
4674
  uppercaseType = 'STOP_LOSS'
4674
4675
  elif uppercaseType == 'LIMIT':
4675
4676
  uppercaseType = 'STOP_LOSS_LIMIT'
4676
- validOrderTypes = self.safe_value(market['info'], 'orderTypes')
4677
+ validOrderTypes = self.safe_list(market['info'], 'orderTypes')
4677
4678
  if not self.in_array(uppercaseType, validOrderTypes):
4678
4679
  if initialUppercaseType != uppercaseType:
4679
4680
  raise InvalidOrder(self.id + ' stopPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders')
4680
4681
  else:
4681
4682
  raise InvalidOrder(self.id + ' ' + type + ' is not a valid order type for the ' + symbol + ' market')
4682
4683
  if clientOrderId is None:
4683
- broker = self.safe_value(self.options, 'broker')
4684
+ broker = self.safe_dict(self.options, 'broker')
4684
4685
  if broker is not None:
4685
4686
  brokerId = self.safe_string(broker, 'spot')
4686
4687
  if brokerId is not None:
@@ -7148,7 +7149,7 @@ class binance(Exchange, ImplicitAPI):
7148
7149
  if until is not None:
7149
7150
  request['endTime'] = until
7150
7151
  raw = self.sapiGetFiatOrders(self.extend(request, params))
7151
- response = self.safe_value(raw, 'data')
7152
+ response = self.safe_list(raw, 'data', [])
7152
7153
  # {
7153
7154
  # "code": "000000",
7154
7155
  # "message": "success",
@@ -7250,7 +7251,7 @@ class binance(Exchange, ImplicitAPI):
7250
7251
  if since is not None:
7251
7252
  request['beginTime'] = since
7252
7253
  raw = self.sapiGetFiatOrders(self.extend(request, params))
7253
- response = self.safe_value(raw, 'data')
7254
+ response = self.safe_list(raw, 'data', [])
7254
7255
  # {
7255
7256
  # "code": "000000",
7256
7257
  # "message": "success",
@@ -7457,7 +7458,7 @@ class binance(Exchange, ImplicitAPI):
7457
7458
  txType = self.safe_string(transaction, 'transactionType')
7458
7459
  if txType is not None:
7459
7460
  type = 'deposit' if (txType == '0') else 'withdrawal'
7460
- legalMoneyCurrenciesById = self.safe_value(self.options, 'legalMoneyCurrenciesById')
7461
+ legalMoneyCurrenciesById = self.safe_dict(self.options, 'legalMoneyCurrenciesById')
7461
7462
  code = self.safe_string(legalMoneyCurrenciesById, code, code)
7462
7463
  status = self.parse_transaction_status_by_type(self.safe_string(transaction, 'status'), type)
7463
7464
  amount = self.safe_number(transaction, 'amount')
@@ -7771,7 +7772,7 @@ class binance(Exchange, ImplicitAPI):
7771
7772
  if subLevel is not None:
7772
7773
  topLevel = topLevel + '/' + subLevel
7773
7774
  impliedNetwork = self.safe_string(reverseNetworks, topLevel)
7774
- impliedNetworks = self.safe_value(self.options, 'impliedNetworks', {
7775
+ impliedNetworks = self.safe_dict(self.options, 'impliedNetworks', {
7775
7776
  'ETH': {'ERC20': 'ETH'},
7776
7777
  'TRX': {'TRC20': 'TRX'},
7777
7778
  })
@@ -8979,7 +8980,7 @@ class binance(Exchange, ImplicitAPI):
8979
8980
  self.load_markets()
8980
8981
  # by default cache the leverage bracket
8981
8982
  # it contains useful stuff like the maintenance margin and initial margin for positions
8982
- leverageBrackets = self.safe_value(self.options, 'leverageBrackets')
8983
+ leverageBrackets = self.safe_dict(self.options, 'leverageBrackets', {})
8983
8984
  if (leverageBrackets is None) or (reload):
8984
8985
  defaultType = self.safe_string(self.options, 'defaultType', 'future')
8985
8986
  type = self.safe_string(params, 'type', defaultType)
ccxt/bingx.py CHANGED
@@ -97,6 +97,7 @@ class bingx(Exchange, ImplicitAPI):
97
97
  'fetchTransfers': True,
98
98
  'fetchWithdrawals': True,
99
99
  'reduceMargin': True,
100
+ 'sandbox': True,
100
101
  'setLeverage': True,
101
102
  'setMargin': True,
102
103
  'setMarginMode': True,
ccxt/bitmex.py CHANGED
@@ -100,6 +100,7 @@ class bitmex(Exchange, ImplicitAPI):
100
100
  'fetchTransfer': False,
101
101
  'fetchTransfers': False,
102
102
  'reduceMargin': None,
103
+ 'sandbox': True,
103
104
  'setLeverage': True,
104
105
  'setMargin': None,
105
106
  'setMarginMode': True,
ccxt/bybit.py CHANGED
@@ -133,6 +133,7 @@ class bybit(Exchange, ImplicitAPI):
133
133
  'fetchVolatilityHistory': True,
134
134
  'fetchWithdrawals': True,
135
135
  'repayCrossMargin': True,
136
+ 'sandbox': True,
136
137
  'setLeverage': True,
137
138
  'setMarginMode': True,
138
139
  'setPositionMode': True,
@@ -1468,6 +1469,7 @@ class bybit(Exchange, ImplicitAPI):
1468
1469
  # "quoteCoin": "USDT",
1469
1470
  # "innovation": "0",
1470
1471
  # "status": "Trading",
1472
+ # "marginTrading": "both",
1471
1473
  # "lotSizeFilter": {
1472
1474
  # "basePrecision": "0.000001",
1473
1475
  # "quotePrecision": "0.00000001",
@@ -1504,7 +1506,9 @@ class bybit(Exchange, ImplicitAPI):
1504
1506
  lotSizeFilter = self.safe_dict(market, 'lotSizeFilter')
1505
1507
  priceFilter = self.safe_dict(market, 'priceFilter')
1506
1508
  quotePrecision = self.safe_number(lotSizeFilter, 'quotePrecision')
1507
- result.append({
1509
+ marginTrading = self.safe_string(market, 'marginTrading', 'none')
1510
+ allowsMargin = marginTrading != 'none'
1511
+ result.append(self.safe_market_structure({
1508
1512
  'id': id,
1509
1513
  'symbol': symbol,
1510
1514
  'base': base,
@@ -1515,7 +1519,7 @@ class bybit(Exchange, ImplicitAPI):
1515
1519
  'settleId': None,
1516
1520
  'type': 'spot',
1517
1521
  'spot': True,
1518
- 'margin': None,
1522
+ 'margin': allowsMargin,
1519
1523
  'swap': False,
1520
1524
  'future': False,
1521
1525
  'option': False,
@@ -1554,7 +1558,7 @@ class bybit(Exchange, ImplicitAPI):
1554
1558
  },
1555
1559
  'created': None,
1556
1560
  'info': market,
1557
- })
1561
+ }))
1558
1562
  return result
1559
1563
 
1560
1564
  def fetch_future_markets(self, params):
@@ -1667,7 +1671,7 @@ class bybit(Exchange, ImplicitAPI):
1667
1671
  if expiry is not None:
1668
1672
  symbol = symbol + '-' + self.yymmdd(expiry)
1669
1673
  contractSize = self.safe_number_2(lotSizeFilter, 'minTradingQty', 'minOrderQty') if inverse else self.parse_number('1')
1670
- result.append({
1674
+ result.append(self.safe_market_structure({
1671
1675
  'id': id,
1672
1676
  'symbol': symbol,
1673
1677
  'base': base,
@@ -1717,7 +1721,7 @@ class bybit(Exchange, ImplicitAPI):
1717
1721
  },
1718
1722
  'created': self.safe_integer(market, 'launchTime'),
1719
1723
  'info': market,
1720
- })
1724
+ }))
1721
1725
  return result
1722
1726
 
1723
1727
  def fetch_option_markets(self, params):
@@ -1795,7 +1799,7 @@ class bybit(Exchange, ImplicitAPI):
1795
1799
  optionLetter = self.safe_string(splitId, 3)
1796
1800
  isActive = (status == 'Trading')
1797
1801
  if isActive or (self.options['loadAllOptions']) or (self.options['loadExpiredOptions']):
1798
- result.append({
1802
+ result.append(self.safe_market_structure({
1799
1803
  'id': id,
1800
1804
  'symbol': base + '/' + quote + ':' + settle + '-' + self.yymmdd(expiry) + '-' + strike + '-' + optionLetter,
1801
1805
  'base': base,
@@ -1845,7 +1849,7 @@ class bybit(Exchange, ImplicitAPI):
1845
1849
  },
1846
1850
  'created': self.safe_integer(market, 'launchTime'),
1847
1851
  'info': market,
1848
- })
1852
+ }))
1849
1853
  return result
1850
1854
 
1851
1855
  def parse_ticker(self, ticker, market: Market = None) -> Ticker:
@@ -113,6 +113,7 @@ class coinbaseinternational(Exchange, ImplicitAPI):
113
113
  'fetchTradingFees': False,
114
114
  'fetchWithdrawals': True,
115
115
  'reduceMargin': False,
116
+ 'sandbox': True,
116
117
  'setLeverage': False,
117
118
  'setMargin': True,
118
119
  'setMarginMode': False,
ccxt/coinmetro.py CHANGED
@@ -122,6 +122,7 @@ class coinmetro(Exchange, ImplicitAPI):
122
122
  'reduceMargin': False,
123
123
  'repayCrossMargin': False,
124
124
  'repayIsolatedMargin': False,
125
+ 'sandbox': True,
125
126
  'setLeverage': False,
126
127
  'setMargin': False,
127
128
  'setMarginMode': False,
ccxt/cryptocom.py CHANGED
@@ -117,6 +117,7 @@ class cryptocom(Exchange, ImplicitAPI):
117
117
  'reduceMargin': False,
118
118
  'repayCrossMargin': False,
119
119
  'repayIsolatedMargin': False,
120
+ 'sandbox': True,
120
121
  'setLeverage': False,
121
122
  'setMarginMode': False,
122
123
  'setPositionMode': False,
ccxt/currencycom.py CHANGED
@@ -114,6 +114,7 @@ class currencycom(Exchange, ImplicitAPI):
114
114
  'fetchWithdrawal': None,
115
115
  'fetchWithdrawals': True,
116
116
  'reduceMargin': None,
117
+ 'sandbox': True,
117
118
  'setLeverage': None,
118
119
  'setMarginMode': None,
119
120
  'setPositionMode': None,
ccxt/deribit.py CHANGED
@@ -107,6 +107,7 @@ class deribit(Exchange, ImplicitAPI):
107
107
  'fetchVolatilityHistory': True,
108
108
  'fetchWithdrawal': False,
109
109
  'fetchWithdrawals': True,
110
+ 'sandbox': True,
110
111
  'transfer': True,
111
112
  'withdraw': True,
112
113
  },
ccxt/gate.py CHANGED
@@ -175,6 +175,7 @@ class gate(Exchange, ImplicitAPI):
175
175
  'reduceMargin': True,
176
176
  'repayCrossMargin': True,
177
177
  'repayIsolatedMargin': True,
178
+ 'sandbox': True,
178
179
  'setLeverage': True,
179
180
  'setMarginMode': False,
180
181
  'setPositionMode': True,
ccxt/gemini.py CHANGED
@@ -95,6 +95,7 @@ class gemini(Exchange, ImplicitAPI):
95
95
  'fetchTransactions': 'emulated',
96
96
  'postOnly': True,
97
97
  'reduceMargin': False,
98
+ 'sandbox': True,
98
99
  'setLeverage': False,
99
100
  'setMarginMode': False,
100
101
  'setPositionMode': False,
ccxt/hitbtc.py CHANGED
@@ -108,6 +108,7 @@ class hitbtc(Exchange, ImplicitAPI):
108
108
  'fetchTransactions': 'emulated',
109
109
  'fetchWithdrawals': True,
110
110
  'reduceMargin': True,
111
+ 'sandbox': True,
111
112
  'setLeverage': True,
112
113
  'setMargin': False,
113
114
  'setMarginMode': False,
ccxt/hollaex.py CHANGED
@@ -96,6 +96,7 @@ class hollaex(Exchange, ImplicitAPI):
96
96
  'fetchWithdrawal': True,
97
97
  'fetchWithdrawals': True,
98
98
  'reduceMargin': False,
99
+ 'sandbox': True,
99
100
  'setLeverage': False,
100
101
  'setMarginMode': False,
101
102
  'setPositionMode': False,
ccxt/hyperliquid.py CHANGED
@@ -113,6 +113,7 @@ class hyperliquid(Exchange, ImplicitAPI):
113
113
  'reduceMargin': True,
114
114
  'repayCrossMargin': False,
115
115
  'repayIsolatedMargin': False,
116
+ 'sandbox': True,
116
117
  'setLeverage': True,
117
118
  'setMarginMode': True,
118
119
  'setPositionMode': False,
@@ -442,6 +443,9 @@ class hyperliquid(Exchange, ImplicitAPI):
442
443
  for i in range(0, len(meta)):
443
444
  market = self.safe_dict(meta, i, {})
444
445
  marketName = self.safe_string(market, 'name')
446
+ if marketName.find('/') < 0:
447
+ # there are some weird spot markets in testnet, eg @2
448
+ continue
445
449
  marketParts = marketName.split('/')
446
450
  baseName = self.safe_string(marketParts, 0)
447
451
  quoteId = self.safe_string(marketParts, 1)
ccxt/idex.py CHANGED
@@ -106,6 +106,7 @@ class idex(Exchange, ImplicitAPI):
106
106
  'fetchWithdrawal': True,
107
107
  'fetchWithdrawals': True,
108
108
  'reduceMargin': False,
109
+ 'sandbox': True,
109
110
  'setLeverage': False,
110
111
  'setMarginMode': False,
111
112
  'setPositionMode': False,
ccxt/krakenfutures.py CHANGED
@@ -86,6 +86,7 @@ class krakenfutures(Exchange, ImplicitAPI):
86
86
  'fetchPremiumIndexOHLCV': False,
87
87
  'fetchTickers': True,
88
88
  'fetchTrades': True,
89
+ 'sandbox': True,
89
90
  'setLeverage': True,
90
91
  'setMarginMode': False,
91
92
  'transfer': True,
ccxt/ndax.py CHANGED
@@ -91,6 +91,7 @@ class ndax(Exchange, ImplicitAPI):
91
91
  'fetchTradingFees': False,
92
92
  'fetchWithdrawals': True,
93
93
  'reduceMargin': False,
94
+ 'sandbox': True,
94
95
  'setLeverage': False,
95
96
  'setMarginMode': False,
96
97
  'setPositionMode': False,
ccxt/okx.py CHANGED
@@ -25,6 +25,7 @@ from ccxt.base.errors import CancelPending
25
25
  from ccxt.base.errors import ContractUnavailable
26
26
  from ccxt.base.errors import NotSupported
27
27
  from ccxt.base.errors import NetworkError
28
+ from ccxt.base.errors import DDoSProtection
28
29
  from ccxt.base.errors import RateLimitExceeded
29
30
  from ccxt.base.errors import ExchangeNotAvailable
30
31
  from ccxt.base.errors import OnMaintenance
@@ -161,6 +162,7 @@ class okx(Exchange, ImplicitAPI):
161
162
  'fetchWithdrawalWhitelist': False,
162
163
  'reduceMargin': True,
163
164
  'repayCrossMargin': True,
165
+ 'sandbox': True,
164
166
  'setLeverage': True,
165
167
  'setMargin': False,
166
168
  'setMarginMode': True,
@@ -911,7 +913,24 @@ class okx(Exchange, ImplicitAPI):
911
913
  '60017': BadRequest, # Invalid url path
912
914
  '60018': BadRequest, # The {0} {1} {2} {3} {4} does not exist
913
915
  '60019': BadRequest, # Invalid op {op}
916
+ '60020': ExchangeError, # APIKey subscription amount exceeds the limit
917
+ '60021': AccountNotEnabled, # This operation does not support multiple accounts login
918
+ '60022': AuthenticationError, # Bulk login partially succeeded
919
+ '60023': DDoSProtection, # Bulk login requests too frequent
920
+ '60024': AuthenticationError, # Wrong passphrase
921
+ '60025': ExchangeError, # Token subscription amount exceeds the limit
922
+ '60026': AuthenticationError, # Batch login by APIKey and token simultaneously is not supported
923
+ '60027': ArgumentsRequired, # Parameter {0} can not be empty
924
+ '60028': NotSupported, # The current operation is not supported by self URL
925
+ '60029': AccountNotEnabled, # Only users who are VIP5 and above in trading fee tier are allowed to subscribe to books-l2-tbt channel
926
+ '60030': AccountNotEnabled, # Only users who are VIP4 and above in trading fee tier are allowed to subscribe to books50-l2-tbt channel
927
+ '60031': AuthenticationError, # The WebSocket endpoint does not support multiple account batch login,
928
+ '60032': AuthenticationError, # API key doesn't exist,
914
929
  '63999': ExchangeError, # Internal system error
930
+ '64000': BadRequest, # Subscription parameter uly is unavailable anymore, please replace uly with instFamily. More details can refer to: https://www.okx.com/help-center/changes-to-v5-api-websocket-subscription-parameter-and-url,
931
+ '64001': BadRequest, # This channel has been migrated to the business URL. Please subscribe using the new URL. More details can refer to: https://www.okx.com/help-center/changes-to-v5-api-websocket-subscription-parameter-and-url,
932
+ '64002': BadRequest, # This channel is not supported by business URL. Please use "/private" URL(for private channels), or "/public" URL(for public channels). More details can refer to: https://www.okx.com/help-center/changes-to-v5-api-websocket-subscription-parameter-and-url,
933
+ '64003': AccountNotEnabled, # Your trading fee tier doesnt meet the requirement to access self channel
915
934
  '70010': BadRequest, # Timestamp parameters need to be in Unix timestamp format in milliseconds.
916
935
  '70013': BadRequest, # endTs needs to be bigger than or equal to beginTs.
917
936
  '70016': BadRequest, # Please specify your instrument settings for at least one instType.
ccxt/phemex.py CHANGED
@@ -96,6 +96,7 @@ class phemex(Exchange, ImplicitAPI):
96
96
  'fetchTransfers': True,
97
97
  'fetchWithdrawals': True,
98
98
  'reduceMargin': False,
99
+ 'sandbox': True,
99
100
  'setLeverage': True,
100
101
  'setMargin': True,
101
102
  'setMarginMode': True,
ccxt/poloniex.py CHANGED
@@ -84,6 +84,7 @@ class poloniex(Exchange, ImplicitAPI):
84
84
  'fetchTransfer': False,
85
85
  'fetchTransfers': False,
86
86
  'fetchWithdrawals': True,
87
+ 'sandbox': True,
87
88
  'transfer': True,
88
89
  'withdraw': True,
89
90
  },
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.15'
7
+ __version__ = '4.3.17'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/bitfinex2.py CHANGED
@@ -642,6 +642,8 @@ class bitfinex2(ccxt.async_support.bitfinex2):
642
642
  responseChecksum = self.safe_integer(message, 2)
643
643
  if responseChecksum != localChecksum:
644
644
  error = InvalidNonce(self.id + ' invalid checksum')
645
+ del client.subscriptions[messageHash]
646
+ del self.orderbooks[symbol]
645
647
  client.reject(error, messageHash)
646
648
 
647
649
  async def watch_balance(self, params={}) -> Balances:
ccxt/pro/bitget.py CHANGED
@@ -541,7 +541,10 @@ class bitget(ccxt.async_support.bitget):
541
541
  responseChecksum = self.safe_integer(rawOrderBook, 'checksum')
542
542
  if calculatedChecksum != responseChecksum:
543
543
  error = InvalidNonce(self.id + ' invalid checksum')
544
+ del client.subscriptions[messageHash]
545
+ del self.orderbooks[symbol]
544
546
  client.reject(error, messageHash)
547
+ return
545
548
  else:
546
549
  orderbook = self.order_book({})
547
550
  parsedOrderbook = self.parse_order_book(rawOrderBook, symbol, timestamp)
ccxt/pro/bybit.py CHANGED
@@ -22,11 +22,11 @@ class bybit(ccxt.async_support.bybit):
22
22
  return self.deep_extend(super(bybit, self).describe(), {
23
23
  'has': {
24
24
  'ws': True,
25
- 'createOrderWs': False, # available only in sandbox
26
- 'editOrderWs': False,
25
+ 'createOrderWs': True,
26
+ 'editOrderWs': True,
27
27
  'fetchOpenOrdersWs': False,
28
28
  'fetchOrderWs': False,
29
- 'cancelOrderWs': False,
29
+ 'cancelOrderWs': True,
30
30
  'cancelOrdersWs': False,
31
31
  'cancelAllOrdersWs': False,
32
32
  'fetchTradesWs': False,
ccxt/pro/htx.py CHANGED
@@ -418,6 +418,8 @@ class htx(ccxt.async_support.htx):
418
418
  self.orderbooks[symbol] = orderbook
419
419
  client.resolve(orderbook, messageHash)
420
420
  except Exception as e:
421
+ del client.subscriptions[messageHash]
422
+ del self.orderbooks[symbol]
421
423
  client.reject(e, messageHash)
422
424
 
423
425
  async def watch_order_book_snapshot(self, client, message, subscription):
@@ -213,6 +213,8 @@ class independentreserve(ccxt.async_support.independentreserve):
213
213
  responseChecksum = self.safe_integer(orderBook, 'Crc32')
214
214
  if calculatedChecksum != responseChecksum:
215
215
  error = InvalidNonce(self.id + ' invalid checksum')
216
+ del client.subscriptions[messageHash]
217
+ del self.orderbooks[symbol]
216
218
  client.reject(error, messageHash)
217
219
  if receivedSnapshot:
218
220
  client.resolve(orderbook, messageHash)
ccxt/pro/kraken.py CHANGED
@@ -734,6 +734,8 @@ class kraken(ccxt.async_support.kraken):
734
734
  localChecksum = self.crc32(payload, False)
735
735
  if localChecksum != c:
736
736
  error = InvalidNonce(self.id + ' invalid checksum')
737
+ del client.subscriptions[messageHash]
738
+ del self.orderbooks[symbol]
737
739
  client.reject(error, messageHash)
738
740
  return
739
741
  orderbook['symbol'] = symbol
ccxt/pro/okx.py CHANGED
@@ -9,6 +9,7 @@ import hashlib
9
9
  from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
+ from ccxt.base.errors import ExchangeError
12
13
  from ccxt.base.errors import AuthenticationError
13
14
  from ccxt.base.errors import ArgumentsRequired
14
15
  from ccxt.base.errors import BadRequest
@@ -424,10 +425,12 @@ class okx(ccxt.async_support.okx):
424
425
 
425
426
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
426
427
  """
428
+ :see: https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-order-book-channel
427
429
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
428
430
  :param str symbol: unified symbol of the market to fetch the order book for
429
431
  :param int [limit]: the maximum amount of order book entries to return
430
432
  :param dict [params]: extra parameters specific to the exchange API endpoint
433
+ :param str [params.depth]: okx order book depth, can be books, books5, books-l2-tbt, books50-l2-tbt, bbo-tbt
431
434
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
432
435
  """
433
436
  #
@@ -457,28 +460,30 @@ class okx(ccxt.async_support.okx):
457
460
 
458
461
  async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
459
462
  """
463
+ :see: https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-order-book-channel
460
464
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
461
465
  :param str[] symbols: unified array of symbols
462
466
  :param int [limit]: 1,5, 400, 50(l2-tbt, vip4+) or 40000(vip5+) the maximum amount of order book entries to return
463
467
  :param dict [params]: extra parameters specific to the exchange API endpoint
468
+ :param str [params.depth]: okx order book depth, can be books, books5, books-l2-tbt, books50-l2-tbt, bbo-tbt
464
469
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
465
470
  """
466
471
  await self.load_markets()
467
472
  symbols = self.market_symbols(symbols)
468
- options = self.safe_value(self.options, 'watchOrderBook', {})
469
- depth = self.safe_string(options, 'depth', 'books')
473
+ depth = None
474
+ depth, params = self.handle_option_and_params(params, 'watchOrderBook', 'depth', 'books')
470
475
  if limit is not None:
471
476
  if limit == 1:
472
477
  depth = 'bbo-tbt'
473
478
  elif limit > 1 and limit <= 5:
474
479
  depth = 'books5'
475
- elif limit == 400:
476
- depth = 'books'
477
480
  elif limit == 50:
478
481
  depth = 'books50-l2-tbt' # Make sure you have VIP4 and above
479
- elif limit == 4000:
480
- depth = 'books-l2-tbt' # Make sure you have VIP5 and above
482
+ elif limit == 400:
483
+ depth = 'books'
481
484
  if (depth == 'books-l2-tbt') or (depth == 'books50-l2-tbt'):
485
+ if not self.check_required_credentials(False):
486
+ raise AuthenticationError(self.id + ' watchOrderBook/watchOrderBookForSymbols requires authentication for self depth. Add credentials or change the depth option to books or books5')
482
487
  await self.authenticate({'access': 'public'})
483
488
  topics = []
484
489
  messageHashes = []
@@ -539,6 +544,8 @@ class okx(ccxt.async_support.okx):
539
544
  storedBids = orderbook['bids']
540
545
  self.handle_deltas(storedAsks, asks)
541
546
  self.handle_deltas(storedBids, bids)
547
+ marketId = self.safe_string(message, 'instId')
548
+ symbol = self.safe_symbol(marketId)
542
549
  checksum = self.safe_bool(self.options, 'checksum', True)
543
550
  if checksum:
544
551
  asksLength = len(storedAsks)
@@ -556,6 +563,8 @@ class okx(ccxt.async_support.okx):
556
563
  localChecksum = self.crc32(payload, True)
557
564
  if responseChecksum != localChecksum:
558
565
  error = InvalidNonce(self.id + ' invalid checksum')
566
+ del client.subscriptions[messageHash]
567
+ del self.orderbooks[symbol]
559
568
  client.reject(error, messageHash)
560
569
  timestamp = self.safe_integer(message, 'ts')
561
570
  orderbook['timestamp'] = timestamp
@@ -648,10 +657,10 @@ class okx(ccxt.async_support.okx):
648
657
  # ]
649
658
  # }
650
659
  #
651
- arg = self.safe_value(message, 'arg', {})
660
+ arg = self.safe_dict(message, 'arg', {})
652
661
  channel = self.safe_string(arg, 'channel')
653
662
  action = self.safe_string(message, 'action')
654
- data = self.safe_value(message, 'data', [])
663
+ data = self.safe_list(message, 'data', [])
655
664
  marketId = self.safe_string(arg, 'instId')
656
665
  market = self.safe_market(marketId)
657
666
  symbol = market['symbol']
@@ -1416,23 +1425,18 @@ class okx(ccxt.async_support.okx):
1416
1425
  # {event: 'error', msg: "Illegal request: {"op":"subscribe","args":["spot/ticker:BTC-USDT"]}", code: "60012"}
1417
1426
  # {event: 'error", msg: "channel:ticker,instId:BTC-USDT doesn"t exist", code: "60018"}
1418
1427
  #
1419
- errorCode = self.safe_integer(message, 'code')
1428
+ errorCode = self.safe_string(message, 'code')
1420
1429
  try:
1421
- if errorCode:
1430
+ if errorCode and errorCode != '0':
1422
1431
  feedback = self.id + ' ' + self.json(message)
1423
1432
  self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
1424
1433
  messageString = self.safe_value(message, 'msg')
1425
1434
  if messageString is not None:
1426
1435
  self.throw_broadly_matched_exception(self.exceptions['broad'], messageString, feedback)
1436
+ raise ExchangeError(feedback)
1427
1437
  except Exception as e:
1428
- if isinstance(e, AuthenticationError):
1429
- messageHash = 'authenticated'
1430
- client.reject(e, messageHash)
1431
- if messageHash in client.subscriptions:
1432
- del client.subscriptions[messageHash]
1433
- return False
1434
- else:
1435
- client.reject(e)
1438
+ client.reject(e)
1439
+ return False
1436
1440
  return message
1437
1441
 
1438
1442
  def handle_message(self, client: Client, message):
ccxt/probit.py CHANGED
@@ -101,6 +101,7 @@ class probit(Exchange, ImplicitAPI):
101
101
  'fetchWithdrawal': False,
102
102
  'fetchWithdrawals': True,
103
103
  'reduceMargin': False,
104
+ 'sandbox': True,
104
105
  'setLeverage': False,
105
106
  'setMarginMode': False,
106
107
  'setPositionMode': False,
ccxt/wavesexchange.py CHANGED
@@ -92,6 +92,7 @@ class wavesexchange(Exchange, ImplicitAPI):
92
92
  'fetchTransfer': False,
93
93
  'fetchTransfers': False,
94
94
  'reduceMargin': False,
95
+ 'sandbox': True,
95
96
  'setLeverage': False,
96
97
  'setMarginMode': False,
97
98
  'setPositionMode': False,
ccxt/woo.py CHANGED
@@ -113,6 +113,7 @@ class woo(Exchange, ImplicitAPI):
113
113
  'fetchTransfers': True,
114
114
  'fetchWithdrawals': True,
115
115
  'reduceMargin': False,
116
+ 'sandbox': True,
116
117
  'setLeverage': True,
117
118
  'setMargin': False,
118
119
  'setPositionMode': True,
ccxt/zaif.py CHANGED
@@ -649,7 +649,7 @@ class zaif(Exchange, ImplicitAPI):
649
649
  }
650
650
 
651
651
  def custom_nonce(self):
652
- num = (self.milliseconds() / str(1000))
652
+ num = self.number_to_string(self.milliseconds() / 1000)
653
653
  nonce = float(num)
654
654
  return format(nonce, '.8f')
655
655
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.3.15
3
+ Version: 4.3.17
4
4
  Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges
5
5
  Home-page: https://ccxt.com
6
6
  Author: Igor Kroitor
@@ -262,13 +262,13 @@ console.log(version, Object.keys(exchanges));
262
262
 
263
263
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
264
264
 
265
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.15/dist/ccxt.browser.js
266
- * unpkg: https://unpkg.com/ccxt@4.3.15/dist/ccxt.browser.js
265
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.17/dist/ccxt.browser.js
266
+ * unpkg: https://unpkg.com/ccxt@4.3.17/dist/ccxt.browser.js
267
267
 
268
268
  CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
269
269
 
270
270
  ```HTML
271
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.15/dist/ccxt.browser.js"></script>
271
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.17/dist/ccxt.browser.js"></script>
272
272
  ```
273
273
 
274
274
  Creates a global `ccxt` object: