ccxt 4.4.34__py2.py3-none-any.whl → 4.4.35__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.
Files changed (46) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/bingx.py +1 -0
  3. ccxt/abstract/bitpanda.py +0 -12
  4. ccxt/abstract/bitrue.py +3 -3
  5. ccxt/abstract/okx.py +1 -0
  6. ccxt/abstract/onetrading.py +0 -12
  7. ccxt/abstract/xt.py +5 -5
  8. ccxt/async_support/__init__.py +1 -1
  9. ccxt/async_support/base/exchange.py +1 -1
  10. ccxt/async_support/bingx.py +324 -138
  11. ccxt/async_support/bitmex.py +1 -1
  12. ccxt/async_support/bitrue.py +2 -2
  13. ccxt/async_support/btcmarkets.py +3 -3
  14. ccxt/async_support/btcturk.py +19 -19
  15. ccxt/async_support/gate.py +142 -39
  16. ccxt/async_support/hyperliquid.py +68 -11
  17. ccxt/async_support/idex.py +3 -4
  18. ccxt/async_support/kraken.py +58 -49
  19. ccxt/async_support/kucoin.py +1 -1
  20. ccxt/async_support/okx.py +1 -0
  21. ccxt/async_support/onetrading.py +47 -369
  22. ccxt/async_support/xt.py +10 -10
  23. ccxt/base/exchange.py +2 -1
  24. ccxt/bingx.py +324 -138
  25. ccxt/bitmex.py +1 -1
  26. ccxt/bitrue.py +2 -2
  27. ccxt/btcmarkets.py +3 -3
  28. ccxt/btcturk.py +19 -19
  29. ccxt/gate.py +142 -39
  30. ccxt/hyperliquid.py +68 -11
  31. ccxt/idex.py +3 -4
  32. ccxt/kraken.py +58 -49
  33. ccxt/kucoin.py +1 -1
  34. ccxt/okx.py +1 -0
  35. ccxt/onetrading.py +47 -369
  36. ccxt/pro/__init__.py +1 -1
  37. ccxt/pro/bitrue.py +13 -11
  38. ccxt/pro/probit.py +54 -66
  39. ccxt/test/tests_async.py +29 -2
  40. ccxt/test/tests_sync.py +29 -2
  41. ccxt/xt.py +10 -10
  42. {ccxt-4.4.34.dist-info → ccxt-4.4.35.dist-info}/METADATA +4 -4
  43. {ccxt-4.4.34.dist-info → ccxt-4.4.35.dist-info}/RECORD +46 -46
  44. {ccxt-4.4.34.dist-info → ccxt-4.4.35.dist-info}/LICENSE.txt +0 -0
  45. {ccxt-4.4.34.dist-info → ccxt-4.4.35.dist-info}/WHEEL +0 -0
  46. {ccxt-4.4.34.dist-info → ccxt-4.4.35.dist-info}/top_level.txt +0 -0
ccxt/pro/probit.py CHANGED
@@ -41,15 +41,6 @@ class probit(ccxt.async_support.probit):
41
41
  'filter': 'order_books_l2',
42
42
  'interval': 100, # or 500
43
43
  },
44
- 'watchTrades': {
45
- 'filter': 'recent_trades',
46
- },
47
- 'watchTicker': {
48
- 'filter': 'ticker',
49
- },
50
- 'watchOrders': {
51
- 'channel': 'open_order',
52
- },
53
44
  },
54
45
  'streaming': {
55
46
  },
@@ -66,13 +57,7 @@ class probit(ccxt.async_support.probit):
66
57
  """
67
58
  await self.authenticate(params)
68
59
  messageHash = 'balance'
69
- url = self.urls['api']['ws']
70
- subscribe: dict = {
71
- 'type': 'subscribe',
72
- 'channel': 'balance',
73
- }
74
- request = self.extend(subscribe, params)
75
- return await self.watch(url, messageHash, request, messageHash)
60
+ return await self.subscribe_private(messageHash, 'balance', params)
76
61
 
77
62
  def handle_balance(self, client: Client, message):
78
63
  #
@@ -130,9 +115,8 @@ class probit(ccxt.async_support.probit):
130
115
  :param int [params.interval]: Unit time to synchronize market information(ms). Available units: 100, 500
131
116
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
132
117
  """
133
- filter = None
134
- filter, params = self.handle_option_and_params(params, 'watchTicker', 'filter', 'ticker')
135
- return await self.subscribe_order_book(symbol, 'ticker', filter, params)
118
+ channel = 'ticker'
119
+ return await self.subscribe_public('watchTicker', symbol, 'ticker', channel, params)
136
120
 
137
121
  def handle_ticker(self, client: Client, message):
138
122
  #
@@ -175,9 +159,8 @@ class probit(ccxt.async_support.probit):
175
159
  :param int [params.interval]: Unit time to synchronize market information(ms). Available units: 100, 500
176
160
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
177
161
  """
178
- filter = None
179
- filter, params = self.handle_option_and_params(params, 'watchTrades', 'filter', 'recent_trades')
180
- trades = await self.subscribe_order_book(symbol, 'trades', filter, params)
162
+ channel = 'recent_trades'
163
+ trades = await self.subscribe_public('watchTrades', symbol, 'trades', channel, params)
181
164
  if self.newUpdates:
182
165
  limit = trades.getLimit(symbol, limit)
183
166
  return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
@@ -207,10 +190,11 @@ class probit(ccxt.async_support.probit):
207
190
  symbol = self.safe_symbol(marketId)
208
191
  market = self.safe_market(marketId)
209
192
  trades = self.safe_value(message, 'recent_trades', [])
210
- reset = self.safe_bool(message, 'reset', False)
193
+ if self.safe_bool(message, 'reset', False):
194
+ return # see comment in handleMessage
211
195
  messageHash = 'trades:' + symbol
212
196
  stored = self.safe_value(self.trades, symbol)
213
- if stored is None or reset:
197
+ if stored is None:
214
198
  limit = self.safe_integer(self.options, 'tradesLimit', 1000)
215
199
  stored = ArrayCache(limit)
216
200
  self.trades[symbol] = stored
@@ -235,19 +219,11 @@ class probit(ccxt.async_support.probit):
235
219
  """
236
220
  await self.load_markets()
237
221
  await self.authenticate(params)
238
- messageHash = 'myTrades'
222
+ messageHash = 'trades'
239
223
  if symbol is not None:
240
- market = self.market(symbol)
241
- symbol = market['symbol']
224
+ symbol = self.safe_symbol(symbol)
242
225
  messageHash = messageHash + ':' + symbol
243
- url = self.urls['api']['ws']
244
- channel = 'trade_history'
245
- message: dict = {
246
- 'type': 'subscribe',
247
- 'channel': channel,
248
- }
249
- request = self.extend(message, params)
250
- trades = await self.watch(url, messageHash, request, channel)
226
+ trades = await self.subscribe_private(messageHash, 'trade_history', params)
251
227
  if self.newUpdates:
252
228
  limit = trades.getLimit(symbol, limit)
253
229
  return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
@@ -276,10 +252,11 @@ class probit(ccxt.async_support.probit):
276
252
  length = len(rawTrades)
277
253
  if length == 0:
278
254
  return
279
- reset = self.safe_bool(message, 'reset', False)
280
- messageHash = 'myTrades'
255
+ if self.safe_bool(message, 'reset', False):
256
+ return # see comment in handleMessage
257
+ messageHash = 'trades'
281
258
  stored = self.myTrades
282
- if (stored is None) or reset:
259
+ if stored is None:
283
260
  limit = self.safe_integer(self.options, 'tradesLimit', 1000)
284
261
  stored = ArrayCacheBySymbolById(limit)
285
262
  self.myTrades = stored
@@ -287,9 +264,15 @@ class probit(ccxt.async_support.probit):
287
264
  tradeSymbols: dict = {}
288
265
  for j in range(0, len(trades)):
289
266
  trade = trades[j]
267
+ # don't include 'executed' state, because it's just blanket state of the trade, emited before actual trade event
268
+ if self.safe_string(trade['info'], 'status') == 'executed':
269
+ continue
290
270
  tradeSymbols[trade['symbol']] = True
291
271
  stored.append(trade)
292
272
  unique = list(tradeSymbols.keys())
273
+ uniqueLength = len(unique)
274
+ if uniqueLength == 0:
275
+ return
293
276
  for i in range(0, len(unique)):
294
277
  symbol = unique[i]
295
278
  symbolSpecificMessageHash = messageHash + ':' + symbol
@@ -310,20 +293,11 @@ class probit(ccxt.async_support.probit):
310
293
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
311
294
  """
312
295
  await self.authenticate(params)
313
- url = self.urls['api']['ws']
314
296
  messageHash = 'orders'
315
297
  if symbol is not None:
316
- market = self.market(symbol)
317
- symbol = market['symbol']
298
+ symbol = self.safe_symbol(symbol)
318
299
  messageHash = messageHash + ':' + symbol
319
- channel = None
320
- channel, params = self.handle_option_and_params(params, 'watchOrders', 'channel', 'open_order')
321
- subscribe: dict = {
322
- 'type': 'subscribe',
323
- 'channel': channel,
324
- }
325
- request = self.extend(subscribe, params)
326
- orders = await self.watch(url, messageHash, request, channel)
300
+ orders = await self.subscribe_private(messageHash, 'open_order', params)
327
301
  if self.newUpdates:
328
302
  limit = orders.getLimit(symbol, limit)
329
303
  return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
@@ -388,39 +362,49 @@ class probit(ccxt.async_support.probit):
388
362
  :param dict [params]: extra parameters specific to the exchange API endpoint
389
363
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
390
364
  """
391
- filter = None
392
- filter, params = self.handle_option_and_params(params, 'watchOrderBook', 'filter', 'order_books')
393
- orderbook = await self.subscribe_order_book(symbol, 'orderbook', filter, params)
365
+ channel = None
366
+ channel, params = self.handle_option_and_params(params, 'watchOrderBook', 'filter', 'order_books')
367
+ orderbook = await self.subscribe_public('watchOrderBook', symbol, 'orderbook', channel, params)
394
368
  return orderbook.limit()
395
369
 
396
- async def subscribe_order_book(self, symbol: str, messageHash, filter, params={}):
370
+ async def subscribe_private(self, messageHash, channel, params):
371
+ url = self.urls['api']['ws']
372
+ subscribe: dict = {
373
+ 'type': 'subscribe',
374
+ 'channel': channel,
375
+ }
376
+ request = self.extend(subscribe, params)
377
+ subscribeHash = messageHash
378
+ return await self.watch(url, messageHash, request, subscribeHash)
379
+
380
+ async def subscribe_public(self, methodName: str, symbol: str, dataType, filter, params={}):
397
381
  await self.load_markets()
398
382
  market = self.market(symbol)
399
383
  symbol = market['symbol']
400
384
  url = self.urls['api']['ws']
401
385
  client = self.client(url)
402
- interval = None
403
- interval, params = self.handle_option_and_params(params, 'watchOrderBook', 'interval', 100)
404
- subscriptionHash = 'marketdata:' + symbol
405
- messageHash = messageHash + ':' + symbol
386
+ subscribeHash = 'marketdata:' + symbol
387
+ messageHash = dataType + ':' + symbol
406
388
  filters = {}
407
- if subscriptionHash in client.subscriptions:
389
+ if subscribeHash in client.subscriptions:
408
390
  # already subscribed
409
- filters = client.subscriptions[subscriptionHash]
391
+ filters = client.subscriptions[subscribeHash]
410
392
  if not (filter in filters):
411
393
  # resubscribe
412
- del client.subscriptions[subscriptionHash]
394
+ del client.subscriptions[subscribeHash]
413
395
  filters[filter] = True
414
396
  keys = list(filters.keys())
415
- message: dict = {
397
+ interval = None
398
+ interval, params = self.handle_option_and_params(params, methodName, 'interval', 100)
399
+ request: dict = {
400
+ 'type': 'subscribe',
416
401
  'channel': 'marketdata',
417
- 'interval': interval,
418
402
  'market_id': market['id'],
419
- 'type': 'subscribe',
420
403
  'filter': keys,
404
+ 'interval': interval,
421
405
  }
422
- request = self.extend(message, params)
423
- return await self.watch(url, messageHash, request, messageHash, filters)
406
+ request = self.extend(request, params)
407
+ return await self.watch(url, messageHash, request, subscribeHash, filters)
424
408
 
425
409
  def handle_order_book(self, client: Client, message, orderBook):
426
410
  #
@@ -493,7 +477,8 @@ class probit(ccxt.async_support.probit):
493
477
  result = self.safe_string(message, 'result')
494
478
  future = client.subscriptions['authenticated']
495
479
  if result == 'ok':
496
- future.resolve(True)
480
+ messageHash = 'authenticated'
481
+ client.resolve(message, messageHash)
497
482
  else:
498
483
  future.reject(message)
499
484
  del client.subscriptions['authenticated']
@@ -521,6 +506,9 @@ class probit(ccxt.async_support.probit):
521
506
  # }
522
507
  # }
523
508
  #
509
+ # Note about 'reset' field
510
+ # 'reset': True field - it happens once after initial subscription, which just returns old items by the moment of subscription(like "fetchMyTrades" does)
511
+ #
524
512
  errorCode = self.safe_string(message, 'errorCode')
525
513
  if errorCode is not None:
526
514
  self.handle_error_message(client, message)
ccxt/test/tests_async.py CHANGED
@@ -714,7 +714,7 @@ class testMainClass:
714
714
  result[key] = value
715
715
  return result
716
716
 
717
- def assert_new_and_stored_output(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
717
+ def assert_new_and_stored_output_inner(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
718
718
  if is_null_value(new_output) and is_null_value(stored_output):
719
719
  return True
720
720
  if not new_output and not stored_output:
@@ -796,6 +796,25 @@ class testMainClass:
796
796
  self.assert_static_error(numeric_new_output == numeric_stored_output, message_error, stored_output, new_output, asserting_key)
797
797
  return True # c# requ
798
798
 
799
+ def assert_new_and_stored_output(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
800
+ try:
801
+ return self.assert_new_and_stored_output_inner(exchange, skip_keys, new_output, stored_output, strict_type_check, asserting_key)
802
+ except Exception as e:
803
+ if self.info:
804
+ error_message = self.var_to_string(new_output) + '(calculated)' + ' != ' + self.var_to_string(stored_output) + '(stored)'
805
+ dump('[TEST_FAILURE_DETAIL]' + error_message)
806
+ raise e
807
+
808
+ def var_to_string(self, obj=None):
809
+ new_string = None
810
+ if obj is None:
811
+ new_string = 'undefined'
812
+ elif is_null_value(obj):
813
+ new_string = 'null'
814
+ else:
815
+ new_string = json_stringify(obj)
816
+ return new_string
817
+
799
818
  def assert_static_request_output(self, exchange, type, skip_keys, stored_url, request_url, stored_output, new_output):
800
819
  if stored_url != request_url:
801
820
  # remove the host part from the url
@@ -1064,7 +1083,15 @@ class testMainClass:
1064
1083
  promises.append(self.test_exchange_request_statically(exchange_name, exchange_data, test_name))
1065
1084
  else:
1066
1085
  promises.append(self.test_exchange_response_statically(exchange_name, exchange_data, test_name))
1067
- await asyncio.gather(*promises)
1086
+ try:
1087
+ await asyncio.gather(*promises)
1088
+ except Exception as e:
1089
+ if type == 'request':
1090
+ self.request_tests_failed = True
1091
+ else:
1092
+ self.response_tests_failed = True
1093
+ error_message = '[' + self.lang + '][STATIC_REQUEST]' + '[' + exchange.id + ']' + str(e)
1094
+ dump('[TEST_FAILURE]' + error_message)
1068
1095
  if self.request_tests_failed or self.response_tests_failed:
1069
1096
  exit_script(1)
1070
1097
  else:
ccxt/test/tests_sync.py CHANGED
@@ -711,7 +711,7 @@ class testMainClass:
711
711
  result[key] = value
712
712
  return result
713
713
 
714
- def assert_new_and_stored_output(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
714
+ def assert_new_and_stored_output_inner(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
715
715
  if is_null_value(new_output) and is_null_value(stored_output):
716
716
  return True
717
717
  if not new_output and not stored_output:
@@ -793,6 +793,25 @@ class testMainClass:
793
793
  self.assert_static_error(numeric_new_output == numeric_stored_output, message_error, stored_output, new_output, asserting_key)
794
794
  return True # c# requ
795
795
 
796
+ def assert_new_and_stored_output(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
797
+ try:
798
+ return self.assert_new_and_stored_output_inner(exchange, skip_keys, new_output, stored_output, strict_type_check, asserting_key)
799
+ except Exception as e:
800
+ if self.info:
801
+ error_message = self.var_to_string(new_output) + '(calculated)' + ' != ' + self.var_to_string(stored_output) + '(stored)'
802
+ dump('[TEST_FAILURE_DETAIL]' + error_message)
803
+ raise e
804
+
805
+ def var_to_string(self, obj=None):
806
+ new_string = None
807
+ if obj is None:
808
+ new_string = 'undefined'
809
+ elif is_null_value(obj):
810
+ new_string = 'null'
811
+ else:
812
+ new_string = json_stringify(obj)
813
+ return new_string
814
+
796
815
  def assert_static_request_output(self, exchange, type, skip_keys, stored_url, request_url, stored_output, new_output):
797
816
  if stored_url != request_url:
798
817
  # remove the host part from the url
@@ -1061,7 +1080,15 @@ class testMainClass:
1061
1080
  promises.append(self.test_exchange_request_statically(exchange_name, exchange_data, test_name))
1062
1081
  else:
1063
1082
  promises.append(self.test_exchange_response_statically(exchange_name, exchange_data, test_name))
1064
- (promises)
1083
+ try:
1084
+ (promises)
1085
+ except Exception as e:
1086
+ if type == 'request':
1087
+ self.request_tests_failed = True
1088
+ else:
1089
+ self.response_tests_failed = True
1090
+ error_message = '[' + self.lang + '][STATIC_REQUEST]' + '[' + exchange.id + ']' + str(e)
1091
+ dump('[TEST_FAILURE]' + error_message)
1065
1092
  if self.request_tests_failed or self.response_tests_failed:
1066
1093
  exit_script(1)
1067
1094
  else:
ccxt/xt.py CHANGED
@@ -156,16 +156,16 @@ class xt(Exchange, ImplicitAPI):
156
156
  'spot': {
157
157
  'get': {
158
158
  'currencies': 1,
159
- 'depth': 0.05,
160
- 'kline': 0.1,
161
- 'symbol': 1, # 0.1 for a single symbol
162
- 'ticker': 1, # 0.1 for a single symbol
163
- 'ticker/book': 1, # 0.1 for a single symbol
164
- 'ticker/price': 1, # 0.1 for a single symbol
165
- 'ticker/24h': 1, # 0.1 for a single symbol
159
+ 'depth': 10,
160
+ 'kline': 1,
161
+ 'symbol': 1, # 1 for a single symbol
162
+ 'ticker': 1, # 1 for a single symbol
163
+ 'ticker/book': 1, # 1 for a single symbol
164
+ 'ticker/price': 1, # 1 for a single symbol
165
+ 'ticker/24h': 1, # 1 for a single symbol
166
166
  'time': 1,
167
- 'trade/history': 0.1,
168
- 'trade/recent': 0.1,
167
+ 'trade/history': 1,
168
+ 'trade/recent': 1,
169
169
  'wallet/support/currency': 1,
170
170
  },
171
171
  },
@@ -235,7 +235,7 @@ class xt(Exchange, ImplicitAPI):
235
235
  },
236
236
  'post': {
237
237
  'order': 0.2,
238
- 'withdraw': 1,
238
+ 'withdraw': 10,
239
239
  'balance/transfer': 1,
240
240
  'balance/account/transfer': 1,
241
241
  'ws-token': 1,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.4.34
3
+ Version: 4.4.35
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
@@ -274,13 +274,13 @@ console.log(version, Object.keys(exchanges));
274
274
 
275
275
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
276
276
 
277
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.34/dist/ccxt.browser.min.js
278
- * unpkg: https://unpkg.com/ccxt@4.4.34/dist/ccxt.browser.min.js
277
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.35/dist/ccxt.browser.min.js
278
+ * unpkg: https://unpkg.com/ccxt@4.4.35/dist/ccxt.browser.min.js
279
279
 
280
280
  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.
281
281
 
282
282
  ```HTML
283
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.34/dist/ccxt.browser.min.js"></script>
283
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.35/dist/ccxt.browser.min.js"></script>
284
284
  ```
285
285
 
286
286
  Creates a global `ccxt` object: