ccxt 4.3.40__py2.py3-none-any.whl → 4.3.42__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 (68) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/binance.py +2 -0
  3. ccxt/abstract/binancecoinm.py +2 -0
  4. ccxt/abstract/binanceus.py +2 -0
  5. ccxt/abstract/binanceusdm.py +2 -0
  6. ccxt/abstract/okx.py +7 -0
  7. ccxt/async_support/__init__.py +1 -1
  8. ccxt/async_support/base/exchange.py +1 -1
  9. ccxt/async_support/binance.py +3 -0
  10. ccxt/async_support/bitfinex2.py +1 -1
  11. ccxt/async_support/bithumb.py +9 -1
  12. ccxt/async_support/bitmart.py +191 -100
  13. ccxt/async_support/bitstamp.py +38 -2
  14. ccxt/async_support/blockchaincom.py +11 -7
  15. ccxt/async_support/coinex.py +1 -1
  16. ccxt/async_support/coinlist.py +19 -1
  17. ccxt/async_support/coinmate.py +19 -3
  18. ccxt/async_support/coinone.py +1 -1
  19. ccxt/async_support/coinspot.py +11 -2
  20. ccxt/async_support/independentreserve.py +33 -1
  21. ccxt/async_support/indodax.py +43 -2
  22. ccxt/async_support/kraken.py +30 -3
  23. ccxt/async_support/krakenfutures.py +55 -1
  24. ccxt/async_support/kucoin.py +59 -2
  25. ccxt/async_support/okx.py +7 -0
  26. ccxt/async_support/upbit.py +13 -8
  27. ccxt/async_support/woo.py +6 -2
  28. ccxt/base/exchange.py +1 -1
  29. ccxt/binance.py +3 -0
  30. ccxt/bitfinex2.py +1 -1
  31. ccxt/bithumb.py +9 -1
  32. ccxt/bitmart.py +191 -100
  33. ccxt/bitstamp.py +38 -2
  34. ccxt/blockchaincom.py +11 -7
  35. ccxt/coinex.py +1 -1
  36. ccxt/coinlist.py +19 -1
  37. ccxt/coinmate.py +19 -3
  38. ccxt/coinone.py +1 -1
  39. ccxt/coinspot.py +11 -2
  40. ccxt/independentreserve.py +33 -1
  41. ccxt/indodax.py +43 -2
  42. ccxt/kraken.py +30 -3
  43. ccxt/krakenfutures.py +55 -1
  44. ccxt/kucoin.py +59 -2
  45. ccxt/okx.py +7 -0
  46. ccxt/pro/__init__.py +1 -1
  47. ccxt/pro/alpaca.py +5 -5
  48. ccxt/pro/ascendex.py +3 -3
  49. ccxt/pro/bingx.py +258 -42
  50. ccxt/pro/bitget.py +11 -5
  51. ccxt/pro/bitrue.py +3 -4
  52. ccxt/pro/currencycom.py +6 -5
  53. ccxt/pro/exmo.py +5 -6
  54. ccxt/pro/gemini.py +4 -3
  55. ccxt/pro/independentreserve.py +7 -7
  56. ccxt/pro/lbank.py +4 -4
  57. ccxt/pro/mexc.py +1 -1
  58. ccxt/pro/phemex.py +5 -5
  59. ccxt/pro/probit.py +4 -4
  60. ccxt/pro/upbit.py +299 -4
  61. ccxt/pro/wazirx.py +12 -12
  62. ccxt/pro/woo.py +1 -1
  63. ccxt/upbit.py +13 -8
  64. ccxt/woo.py +6 -2
  65. {ccxt-4.3.40.dist-info → ccxt-4.3.42.dist-info}/METADATA +4 -4
  66. {ccxt-4.3.40.dist-info → ccxt-4.3.42.dist-info}/RECORD +68 -68
  67. {ccxt-4.3.40.dist-info → ccxt-4.3.42.dist-info}/WHEEL +0 -0
  68. {ccxt-4.3.40.dist-info → ccxt-4.3.42.dist-info}/top_level.txt +0 -0
ccxt/pro/probit.py CHANGED
@@ -428,10 +428,10 @@ class probit(ccxt.async_support.probit):
428
428
  symbol = self.safe_symbol(marketId)
429
429
  dataBySide = self.group_by(orderBook, 'side')
430
430
  messageHash = 'orderbook:' + symbol
431
- orderbook = self.safe_value(self.orderbooks, symbol)
432
- if orderbook is None:
433
- orderbook = self.order_book({})
434
- self.orderbooks[symbol] = orderbook
431
+ # orderbook = self.safe_value(self.orderbooks, symbol)
432
+ if not (symbol in self.orderbooks):
433
+ self.orderbooks[symbol] = self.order_book({})
434
+ orderbook = self.orderbooks[symbol]
435
435
  reset = self.safe_bool(message, 'reset', False)
436
436
  if reset:
437
437
  snapshot = self.parse_order_book(dataBySide, symbol, None, 'buy', 'sell', 'price', 'quantity')
ccxt/pro/upbit.py CHANGED
@@ -4,8 +4,8 @@
4
4
  # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
5
 
6
6
  import ccxt.async_support
7
- from ccxt.async_support.base.ws.cache import ArrayCache
8
- from ccxt.base.types import Int, OrderBook, Ticker, Trade
7
+ from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById
8
+ from ccxt.base.types import Balances, Int, Order, OrderBook, Str, Ticker, Trade
9
9
  from ccxt.async_support.base.ws.client import Client
10
10
  from typing import List
11
11
 
@@ -19,10 +19,13 @@ class upbit(ccxt.async_support.upbit):
19
19
  'watchOrderBook': True,
20
20
  'watchTicker': True,
21
21
  'watchTrades': True,
22
+ 'watchOrders': True,
23
+ 'watchMyTrades': True,
24
+ 'watchBalance': True,
22
25
  },
23
26
  'urls': {
24
27
  'api': {
25
- 'ws': 'wss://api.upbit.com/websocket/v1',
28
+ 'ws': 'wss://{hostname}/websocket/v1',
26
29
  },
27
30
  },
28
31
  'options': {
@@ -35,7 +38,9 @@ class upbit(ccxt.async_support.upbit):
35
38
  market = self.market(symbol)
36
39
  symbol = market['symbol']
37
40
  marketId = market['id']
38
- url = self.urls['api']['ws']
41
+ url = self.implode_params(self.urls['api']['ws'], {
42
+ 'hostname': self.hostname,
43
+ })
39
44
  self.options[channel] = self.safe_value(self.options, channel, {})
40
45
  self.options[channel][symbol] = True
41
46
  symbols = list(self.options[channel].keys())
@@ -57,6 +62,7 @@ class upbit(ccxt.async_support.upbit):
57
62
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
58
63
  """
59
64
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
65
+ :see: https://global-docs.upbit.com/reference/websocket-ticker
60
66
  :param str symbol: unified symbol of the market to fetch the ticker for
61
67
  :param dict [params]: extra parameters specific to the exchange API endpoint
62
68
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -66,6 +72,7 @@ class upbit(ccxt.async_support.upbit):
66
72
  async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
67
73
  """
68
74
  get the list of most recent trades for a particular symbol
75
+ :see: https://global-docs.upbit.com/reference/websocket-trade
69
76
  :param str symbol: unified symbol of the market to fetch trades for
70
77
  :param int [since]: timestamp in ms of the earliest trade to fetch
71
78
  :param int [limit]: the maximum amount of trades to fetch
@@ -82,6 +89,7 @@ class upbit(ccxt.async_support.upbit):
82
89
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
83
90
  """
84
91
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
92
+ :see: https://global-docs.upbit.com/reference/websocket-orderbook
85
93
  :param str symbol: unified symbol of the market to fetch the order book for
86
94
  :param int [limit]: the maximum amount of order book entries to return
87
95
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -213,11 +221,298 @@ class upbit(ccxt.async_support.upbit):
213
221
  messageHash = 'trade:' + marketId
214
222
  client.resolve(stored, messageHash)
215
223
 
224
+ async def authenticate(self, params={}):
225
+ self.check_required_credentials()
226
+ wsOptions: dict = self.safe_dict(self.options, 'ws', {})
227
+ authenticated = self.safe_string(wsOptions, 'token')
228
+ if authenticated is None:
229
+ auth: dict = {
230
+ 'access_key': self.apiKey,
231
+ 'nonce': self.uuid(),
232
+ }
233
+ token = self.jwt(auth, self.encode(self.secret), 'sha256', False)
234
+ wsOptions['token'] = token
235
+ wsOptions['options'] = {
236
+ 'headers': {
237
+ 'authorization': 'Bearer ' + token,
238
+ },
239
+ }
240
+ self.options['ws'] = wsOptions
241
+ url = self.urls['api']['ws'] + '/private'
242
+ client = self.client(url)
243
+ return client
244
+
245
+ async def watch_private(self, symbol, channel, messageHash, params={}):
246
+ await self.authenticate()
247
+ request = {
248
+ 'type': channel,
249
+ }
250
+ if symbol is not None:
251
+ await self.load_markets()
252
+ market = self.market(symbol)
253
+ symbol = market['symbol']
254
+ symbols = [symbol]
255
+ marketIds = self.market_ids(symbols)
256
+ request['codes'] = marketIds
257
+ messageHash = messageHash + ':' + symbol
258
+ url = self.implode_params(self.urls['api']['ws'], {
259
+ 'hostname': self.hostname,
260
+ })
261
+ url += '/private'
262
+ message = [
263
+ {
264
+ 'ticket': self.uuid(),
265
+ },
266
+ request,
267
+ ]
268
+ return await self.watch(url, messageHash, message, messageHash)
269
+
270
+ async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
271
+ """
272
+ watches information on multiple orders made by the user
273
+ :see: https://global-docs.upbit.com/reference/websocket-myorder
274
+ :param str symbol: unified market symbol of the market orders were made in
275
+ :param int [since]: the earliest time in ms to fetch orders for
276
+ :param int [limit]: the maximum number of order structures to retrieve
277
+ :param dict [params]: extra parameters specific to the exchange API endpoint
278
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
279
+ """
280
+ await self.load_markets()
281
+ channel = 'myOrder'
282
+ messageHash = 'myOrder'
283
+ orders = await self.watch_private(symbol, channel, messageHash)
284
+ if self.newUpdates:
285
+ limit = orders.getLimit(symbol, limit)
286
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
287
+
288
+ async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
289
+ """
290
+ watches information on multiple trades made by the user
291
+ :see: https://global-docs.upbit.com/reference/websocket-myorder
292
+ :param str symbol: unified market symbol of the market orders were made in
293
+ :param int [since]: the earliest time in ms to fetch orders for
294
+ :param int [limit]: the maximum number of order structures to retrieve
295
+ :param dict [params]: extra parameters specific to the exchange API endpoint
296
+ :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
297
+ """
298
+ await self.load_markets()
299
+ channel = 'myOrder'
300
+ messageHash = 'myTrades'
301
+ trades = await self.watch_private(symbol, channel, messageHash)
302
+ if self.newUpdates:
303
+ limit = trades.getLimit(symbol, limit)
304
+ return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
305
+
306
+ def parse_ws_order_status(self, status: Str):
307
+ statuses: dict = {
308
+ 'wait': 'open',
309
+ 'done': 'closed',
310
+ 'cancel': 'canceled',
311
+ 'watch': 'open', # not sure what self status means
312
+ 'trade': 'open',
313
+ }
314
+ return self.safe_string(statuses, status, status)
315
+
316
+ def parse_ws_order(self, order, market=None):
317
+ #
318
+ # {
319
+ # "type": "myOrder",
320
+ # "code": "SGD-XRP",
321
+ # "uuid": "ac2dc2a3-fce9-40a2-a4f6-5987c25c438f",
322
+ # "ask_bid": "BID",
323
+ # "order_type": "limit",
324
+ # "state": "trade",
325
+ # "price": 0.001453,
326
+ # "avg_price": 0.00145372,
327
+ # "volume": 30925891.29839369,
328
+ # "remaining_volume": 29968038.09235948,
329
+ # "executed_volume": 30925891.29839369,
330
+ # "trades_count": 1,
331
+ # "reserved_fee": 44.23943970238218,
332
+ # "remaining_fee": 21.77177967409916,
333
+ # "paid_fee": 22.467660028283017,
334
+ # "locked": 43565.33112787242,
335
+ # "executed_funds": 44935.32005656603,
336
+ # "order_timestamp": 1710751590000,
337
+ # "timestamp": 1710751597500,
338
+ # "stream_type": "REALTIME"
339
+ # }
340
+ #
341
+ id = self.safe_string(order, 'uuid')
342
+ side = self.safe_string_lower(order, 'ask_bid')
343
+ if side == 'bid':
344
+ side = 'buy'
345
+ else:
346
+ side = 'sell'
347
+ timestamp = self.parse8601(self.safe_string(order, 'order_timestamp'))
348
+ status = self.parse_ws_order_status(self.safe_string(order, 'state'))
349
+ marketId = self.safe_string(order, 'code')
350
+ market = self.safe_market(marketId, market)
351
+ fee = None
352
+ feeCost = self.safe_string(order, 'paid_fee')
353
+ if feeCost is not None:
354
+ fee = {
355
+ 'currency': market['quote'],
356
+ 'cost': feeCost,
357
+ }
358
+ return self.safe_order({
359
+ 'info': order,
360
+ 'id': id,
361
+ 'clientOrderId': None,
362
+ 'timestamp': timestamp,
363
+ 'datetime': self.iso8601(timestamp),
364
+ 'lastTradeTimestamp': self.safe_string(order, 'trade_timestamp'),
365
+ 'symbol': market['symbol'],
366
+ 'type': self.safe_string(order, 'order_type'),
367
+ 'timeInForce': self.safe_string(order, 'time_in_force'),
368
+ 'postOnly': None,
369
+ 'side': side,
370
+ 'price': self.safe_string(order, 'price'),
371
+ 'stopPrice': None,
372
+ 'triggerPrice': None,
373
+ 'cost': self.safe_string(order, 'executed_funds'),
374
+ 'average': self.safe_string(order, 'avg_price'),
375
+ 'amount': self.safe_string(order, 'volume'),
376
+ 'filled': self.safe_string(order, 'executed_volume'),
377
+ 'remaining': self.safe_string(order, 'remaining_volume'),
378
+ 'status': status,
379
+ 'fee': fee,
380
+ 'trades': None,
381
+ })
382
+
383
+ def parse_ws_trade(self, trade, market=None):
384
+ # see: parseWsOrder
385
+ side = self.safe_string_lower(trade, 'ask_bid')
386
+ if side == 'bid':
387
+ side = 'buy'
388
+ else:
389
+ side = 'sell'
390
+ timestamp = self.parse8601(self.safe_string(trade, 'trade_timestamp'))
391
+ marketId = self.safe_string(trade, 'code')
392
+ market = self.safe_market(marketId, market)
393
+ fee = None
394
+ feeCost = self.safe_string(trade, 'paid_fee')
395
+ if feeCost is not None:
396
+ fee = {
397
+ 'currency': market['quote'],
398
+ 'cost': feeCost,
399
+ }
400
+ return self.safe_trade({
401
+ 'id': self.safe_string(trade, 'trade_uuid'),
402
+ 'timestamp': timestamp,
403
+ 'datetime': self.iso8601(timestamp),
404
+ 'symbol': market['symbol'],
405
+ 'side': side,
406
+ 'price': self.safe_string(trade, 'price'),
407
+ 'amount': self.safe_string(trade, 'volume'),
408
+ 'cost': self.safe_string(trade, 'executed_funds'),
409
+ 'order': self.safe_string(trade, 'uuid'),
410
+ 'takerOrMaker': None,
411
+ 'type': self.safe_string(trade, 'order_type'),
412
+ 'fee': fee,
413
+ 'info': trade,
414
+ }, market)
415
+
416
+ def handle_my_order(self, client: Client, message):
417
+ # see: parseWsOrder
418
+ tradeId = self.safe_string(message, 'trade_uuid')
419
+ if tradeId is not None:
420
+ self.handle_my_trade(client, message)
421
+ self.handle_order(client, message)
422
+
423
+ def handle_my_trade(self, client: Client, message):
424
+ # see: parseWsOrder
425
+ myTrades = self.myTrades
426
+ if myTrades is None:
427
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
428
+ myTrades = ArrayCacheBySymbolById(limit)
429
+ trade = self.parse_ws_trade(message)
430
+ myTrades.append(trade)
431
+ messageHash = 'myTrades'
432
+ client.resolve(myTrades, messageHash)
433
+ messageHash = 'myTrades:' + trade['symbol']
434
+ client.resolve(myTrades, messageHash)
435
+
436
+ def handle_order(self, client: Client, message):
437
+ parsed = self.parse_ws_order(message)
438
+ symbol = self.safe_string(parsed, 'symbol')
439
+ orderId = self.safe_string(parsed, 'id')
440
+ if self.orders is None:
441
+ limit = self.safe_integer(self.options, 'ordersLimit', 1000)
442
+ self.orders = ArrayCacheBySymbolById(limit)
443
+ cachedOrders = self.orders
444
+ orders = self.safe_value(cachedOrders.hashmap, symbol, {})
445
+ order = self.safe_value(orders, orderId)
446
+ if order is not None:
447
+ fee = self.safe_value(order, 'fee')
448
+ if fee is not None:
449
+ parsed['fee'] = fee
450
+ fees = self.safe_value(order, 'fees')
451
+ if fees is not None:
452
+ parsed['fees'] = fees
453
+ parsed['trades'] = self.safe_value(order, 'trades')
454
+ parsed['timestamp'] = self.safe_integer(order, 'timestamp')
455
+ parsed['datetime'] = self.safe_string(order, 'datetime')
456
+ cachedOrders.append(parsed)
457
+ messageHash = 'myOrder'
458
+ client.resolve(self.orders, messageHash)
459
+ messageHash = messageHash + ':' + symbol
460
+ client.resolve(self.orders, messageHash)
461
+
462
+ async def watch_balance(self, params={}) -> Balances:
463
+ """
464
+ :see: https://global-docs.upbit.com/reference/websocket-myasset
465
+ query for balance and get the amount of funds available for trading or funds locked in orders
466
+ :param dict [params]: extra parameters specific to the exchange API endpoint
467
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
468
+ """
469
+ await self.load_markets()
470
+ channel = 'myAsset'
471
+ messageHash = 'myAsset'
472
+ return await self.watch_private(None, channel, messageHash)
473
+
474
+ def handle_balance(self, client: Client, message):
475
+ #
476
+ # {
477
+ # "type": "myAsset",
478
+ # "asset_uuid": "e635f223-1609-4969-8fb6-4376937baad6",
479
+ # "assets": [
480
+ # {
481
+ # "currency": "SGD",
482
+ # "balance": 1386929.37231066771348207123,
483
+ # "locked": 10329.670127489597585685
484
+ # }
485
+ # ],
486
+ # "asset_timestamp": 1710146517259,
487
+ # "timestamp": 1710146517267,
488
+ # "stream_type": "REALTIME"
489
+ # }
490
+ #
491
+ data = self.safe_list(message, 'assets', [])
492
+ timestamp = self.safe_integer(message, 'timestamp')
493
+ self.balance['timestamp'] = timestamp
494
+ self.balance['datetime'] = self.iso8601(timestamp)
495
+ for i in range(0, len(data)):
496
+ balance = data[i]
497
+ currencyId = self.safe_string(balance, 'currency')
498
+ code = self.safe_currency_code(currencyId)
499
+ available = self.safe_string(balance, 'balance')
500
+ frozen = self.safe_string(balance, 'locked')
501
+ account = self.account()
502
+ account['free'] = available
503
+ account['used'] = frozen
504
+ self.balance[code] = account
505
+ self.balance = self.safe_balance(self.balance)
506
+ messageHash = self.safe_string(message, 'type')
507
+ client.resolve(self.balance, messageHash)
508
+
216
509
  def handle_message(self, client: Client, message):
217
510
  methods: dict = {
218
511
  'ticker': self.handle_ticker,
219
512
  'orderbook': self.handle_order_book,
220
513
  'trade': self.handle_trades,
514
+ 'myOrder': self.handle_my_order,
515
+ 'myAsset': self.handle_balance,
221
516
  }
222
517
  methodName = self.safe_string(message, 'type')
223
518
  method = self.safe_value(methods, methodName)
ccxt/pro/wazirx.py CHANGED
@@ -505,20 +505,20 @@ class wazirx(ccxt.async_support.wazirx):
505
505
  market = self.safe_market(marketId)
506
506
  symbol = market['symbol']
507
507
  messageHash = 'orderbook:' + symbol
508
- currentOrderBook = self.safe_value(self.orderbooks, symbol)
509
- if currentOrderBook is None:
508
+ # currentOrderBook = self.safe_value(self.orderbooks, symbol)
509
+ if not (symbol in self.orderbooks):
510
510
  snapshot = self.parse_order_book(data, symbol, timestamp, 'b', 'a')
511
- orderBook = self.order_book(snapshot)
512
- self.orderbooks[symbol] = orderBook
511
+ self.orderbooks[symbol] = self.order_book(snapshot)
513
512
  else:
514
- asks = self.safe_value(data, 'a', [])
515
- bids = self.safe_value(data, 'b', [])
516
- self.handle_deltas(currentOrderBook['asks'], asks)
517
- self.handle_deltas(currentOrderBook['bids'], bids)
518
- currentOrderBook['nonce'] = timestamp
519
- currentOrderBook['timestamp'] = timestamp
520
- currentOrderBook['datetime'] = self.iso8601(timestamp)
521
- self.orderbooks[symbol] = currentOrderBook
513
+ orderbook = self.orderbooks[symbol]
514
+ asks = self.safe_list(data, 'a', [])
515
+ bids = self.safe_list(data, 'b', [])
516
+ self.handle_deltas(orderbook['asks'], asks)
517
+ self.handle_deltas(orderbook['bids'], bids)
518
+ orderbook['nonce'] = timestamp
519
+ orderbook['timestamp'] = timestamp
520
+ orderbook['datetime'] = self.iso8601(timestamp)
521
+ self.orderbooks[symbol] = orderbook
522
522
  client.resolve(self.orderbooks[symbol], messageHash)
523
523
 
524
524
  async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
ccxt/pro/woo.py CHANGED
@@ -582,7 +582,7 @@ class woo(ccxt.async_support.woo):
582
582
  :param int [limit]: the maximum number of order structures to retrieve
583
583
  :param dict [params]: extra parameters specific to the exchange API endpoint
584
584
  :param bool [params.trigger]: True if trigger order
585
- :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
585
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
586
586
  """
587
587
  await self.load_markets()
588
588
  trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
ccxt/upbit.py CHANGED
@@ -1782,23 +1782,28 @@ class upbit(Exchange, ImplicitAPI):
1782
1782
  url += '?' + self.urlencode(query)
1783
1783
  if api == 'private':
1784
1784
  self.check_required_credentials()
1785
+ headers = {}
1785
1786
  nonce = self.uuid()
1786
1787
  request: dict = {
1787
1788
  'access_key': self.apiKey,
1788
1789
  'nonce': nonce,
1789
1790
  }
1790
- if query:
1791
- auth = self.urlencode(query)
1791
+ hasQuery = query
1792
+ auth = None
1793
+ if (method != 'GET') and (method != 'DELETE'):
1794
+ body = self.json(params)
1795
+ headers['Content-Type'] = 'application/json'
1796
+ if hasQuery:
1797
+ auth = self.urlencode(query)
1798
+ else:
1799
+ if hasQuery:
1800
+ auth = self.urlencode(self.keysort(query))
1801
+ if auth is not None:
1792
1802
  hash = self.hash(self.encode(auth), 'sha512')
1793
1803
  request['query_hash'] = hash
1794
1804
  request['query_hash_alg'] = 'SHA512'
1795
1805
  token = self.jwt(request, self.encode(self.secret), 'sha256')
1796
- headers = {
1797
- 'Authorization': 'Bearer ' + token,
1798
- }
1799
- if (method != 'GET') and (method != 'DELETE'):
1800
- body = self.json(params)
1801
- headers['Content-Type'] = 'application/json'
1806
+ headers['Authorization'] = 'Bearer ' + token
1802
1807
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
1803
1808
 
1804
1809
  def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
ccxt/woo.py CHANGED
@@ -1212,7 +1212,9 @@ class woo(Exchange, ImplicitAPI):
1212
1212
  # "status":"CANCEL_ALL_SENT"
1213
1213
  # }
1214
1214
  #
1215
- return response
1215
+ return [
1216
+ self.safe_order(response),
1217
+ ]
1216
1218
 
1217
1219
  def cancel_all_orders_after(self, timeout: Int, params={}):
1218
1220
  """
@@ -1237,7 +1239,9 @@ class woo(Exchange, ImplicitAPI):
1237
1239
  # "timestamp": 1711534302943
1238
1240
  # }
1239
1241
  #
1240
- return response
1242
+ return [
1243
+ self.safe_order(response),
1244
+ ]
1241
1245
 
1242
1246
  def fetch_order(self, id: str, symbol: Str = None, params={}):
1243
1247
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.3.40
3
+ Version: 4.3.42
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
@@ -266,13 +266,13 @@ console.log(version, Object.keys(exchanges));
266
266
 
267
267
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
268
268
 
269
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.40/dist/ccxt.browser.min.js
270
- * unpkg: https://unpkg.com/ccxt@4.3.40/dist/ccxt.browser.min.js
269
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.42/dist/ccxt.browser.min.js
270
+ * unpkg: https://unpkg.com/ccxt@4.3.42/dist/ccxt.browser.min.js
271
271
 
272
272
  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.
273
273
 
274
274
  ```HTML
275
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.40/dist/ccxt.browser.min.js"></script>
275
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.42/dist/ccxt.browser.min.js"></script>
276
276
  ```
277
277
 
278
278
  Creates a global `ccxt` object: