ccxt 4.4.69__py2.py3-none-any.whl → 4.4.71__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 (65) hide show
  1. ccxt/__init__.py +1 -3
  2. ccxt/abstract/bingx.py +1 -0
  3. ccxt/abstract/bitmart.py +1 -0
  4. ccxt/abstract/bybit.py +4 -0
  5. ccxt/abstract/myokx.py +3 -0
  6. ccxt/abstract/okx.py +3 -0
  7. ccxt/abstract/poloniex.py +36 -0
  8. ccxt/abstract/tradeogre.py +1 -1
  9. ccxt/async_support/__init__.py +1 -3
  10. ccxt/async_support/base/exchange.py +3 -3
  11. ccxt/async_support/binance.py +107 -102
  12. ccxt/async_support/bingx.py +64 -42
  13. ccxt/async_support/bitget.py +47 -265
  14. ccxt/async_support/bitmart.py +12 -1
  15. ccxt/async_support/bitopro.py +1 -0
  16. ccxt/async_support/bitrue.py +1 -0
  17. ccxt/async_support/bybit.py +7 -0
  18. ccxt/async_support/cex.py +1 -0
  19. ccxt/async_support/coinbase.py +23 -4
  20. ccxt/async_support/coinbaseexchange.py +1 -0
  21. ccxt/async_support/deribit.py +1 -0
  22. ccxt/async_support/hashkey.py +4 -2
  23. ccxt/async_support/hyperliquid.py +16 -7
  24. ccxt/async_support/kraken.py +77 -5
  25. ccxt/async_support/kucoin.py +4 -2
  26. ccxt/async_support/mexc.py +8 -4
  27. ccxt/async_support/okx.py +62 -46
  28. ccxt/async_support/poloniex.py +1263 -85
  29. ccxt/async_support/tradeogre.py +20 -4
  30. ccxt/async_support/whitebit.py +4 -2
  31. ccxt/base/exchange.py +23 -4
  32. ccxt/base/types.py +28 -0
  33. ccxt/binance.py +107 -102
  34. ccxt/bingx.py +64 -42
  35. ccxt/bitget.py +47 -265
  36. ccxt/bitmart.py +12 -1
  37. ccxt/bitopro.py +1 -0
  38. ccxt/bitrue.py +1 -0
  39. ccxt/bybit.py +7 -0
  40. ccxt/cex.py +1 -0
  41. ccxt/coinbase.py +23 -4
  42. ccxt/coinbaseexchange.py +1 -0
  43. ccxt/deribit.py +1 -0
  44. ccxt/hashkey.py +4 -2
  45. ccxt/hyperliquid.py +16 -7
  46. ccxt/kraken.py +77 -5
  47. ccxt/kucoin.py +4 -2
  48. ccxt/mexc.py +8 -4
  49. ccxt/okx.py +62 -46
  50. ccxt/poloniex.py +1262 -85
  51. ccxt/pro/__init__.py +1 -3
  52. ccxt/pro/binance.py +102 -102
  53. ccxt/pro/bingx.py +62 -51
  54. ccxt/pro/bitget.py +28 -3
  55. ccxt/pro/bybit.py +81 -37
  56. ccxt/test/tests_async.py +4 -3
  57. ccxt/test/tests_sync.py +4 -3
  58. ccxt/tradeogre.py +20 -4
  59. ccxt/whitebit.py +4 -2
  60. {ccxt-4.4.69.dist-info → ccxt-4.4.71.dist-info}/METADATA +6 -9
  61. {ccxt-4.4.69.dist-info → ccxt-4.4.71.dist-info}/RECORD +64 -65
  62. ccxt/abstract/poloniexfutures.py +0 -48
  63. {ccxt-4.4.69.dist-info → ccxt-4.4.71.dist-info}/LICENSE.txt +0 -0
  64. {ccxt-4.4.69.dist-info → ccxt-4.4.71.dist-info}/WHEEL +0 -0
  65. {ccxt-4.4.69.dist-info → ccxt-4.4.71.dist-info}/top_level.txt +0 -0
ccxt/pro/bingx.py CHANGED
@@ -639,60 +639,67 @@ class bingx(ccxt.async_support.bingx):
639
639
  #
640
640
  # spot
641
641
  #
642
- # {
643
- # "code": 0,
644
- # "dataType": "BTC-USDT@depth20",
645
- # "data": {
646
- # "bids": [
647
- # ['28852.9', "34.2621"],
648
- # ...
649
- # ],
650
- # "asks": [
651
- # ['28864.9', "23.4079"],
652
- # ...
653
- # ]
654
- # },
655
- # "dataType": "BTC-USDT@depth20",
656
- # "success": True
657
- # }
642
+ # {
643
+ # "code":0,
644
+ # "data":
645
+ # {
646
+ # "asks":[
647
+ # ["84119.73","0.000011"],
648
+ # ["84116.52","0.000014"],
649
+ # ["84116.40","0.000039"]
650
+ # ],
651
+ # "bids":[
652
+ # ["83656.98","2.570805"],
653
+ # ["83655.51","0.000347"],
654
+ # ["83654.59","0.000082"]
655
+ # ],
656
+ # "lastUpdateId":13565694850
657
+ # },
658
+ # "dataType":"BTC-USDT@depth100",
659
+ # "success":true,
660
+ # "timestamp":1743241379958
661
+ # }
658
662
  #
659
663
  # linear swap
660
664
  #
661
- # {
662
- # "code": 0,
663
- # "dataType": "BTC-USDT@depth20@100ms", #or "all@depth20@100ms"
664
- # "data": {
665
- # "bids": [
666
- # ['28852.9', "34.2621"],
667
- # ...
668
- # ],
669
- # "asks": [
670
- # ['28864.9', "23.4079"],
671
- # ...
672
- # ],
673
- # "symbol": "BTC-USDT", # self key exists only in "all" subscription
674
- # }
675
- # }
665
+ # {
666
+ # "code":0,
667
+ # "dataType":"BTC-USDT@depth100@500ms",
668
+ # "ts":1743241563651,
669
+ # "data":
670
+ # {
671
+ # "bids":[
672
+ # ["83363.2","0.1908"],
673
+ # ["83360.0","0.0003"],
674
+ # ["83356.5","0.0245"],
675
+ # ],
676
+ # "asks":[
677
+ # ["83495.0","0.0024"],
678
+ # ["83490.0","0.0001"],
679
+ # ["83488.0","0.0004"],
680
+ # ]
681
+ # }
682
+ # }
676
683
  #
677
684
  # inverse swap
678
685
  #
679
686
  # {
680
- # "code": 0,
681
- # "dataType": "BTC-USD@depth100",
682
- # "data": {
683
- # {
684
- # "symbol": "BTC-USD",
685
- # "bids": [
686
- # {"p": "58074.2", "a": "1.422318", "v": "826.0"},
687
- # ...
688
- # ],
689
- # "asks": [
690
- # {"p": "62878.0", "a": "0.001590", "v": "1.0"},
691
- # ...
692
- # ],
693
- # "aggPrecision": "0.1",
694
- # "timestamp": 1723705093529
695
- # }
687
+ # "code":0,
688
+ # "dataType":"BTC-USD@depth100",
689
+ # "data":{
690
+ # "symbol":"BTC-USD",
691
+ # "bids":[
692
+ # {"p":"83411.2","a":"2.979216","v":"2485.0"},
693
+ # {"p":"83411.1","a":"1.592114","v":"1328.0"},
694
+ # {"p":"83410.8","a":"2.656730","v":"2216.0"},
695
+ # ],
696
+ # "asks":[
697
+ # {"p":"88200.0","a":"0.344671","v":"304.0"},
698
+ # {"p":"88023.8","a":"0.045442","v":"40.0"},
699
+ # {"p":"88001.0","a":"0.003409","v":"3.0"},
700
+ # ],
701
+ # "aggPrecision":"0.1",
702
+ # "timestamp":1743242290710
696
703
  # }
697
704
  # }
698
705
  #
@@ -706,7 +713,8 @@ class bingx(ccxt.async_support.bingx):
706
713
  marketType = 'swap' if isSwap else 'spot'
707
714
  market = self.safe_market(marketId, None, None, marketType)
708
715
  symbol = market['symbol']
709
- if self.safe_value(self.orderbooks, symbol) is None:
716
+ orderbook = self.safe_value(self.orderbooks, symbol)
717
+ if orderbook is None:
710
718
  # limit = [5, 10, 20, 50, 100]
711
719
  subscriptionHash = dataType
712
720
  subscription = client.subscriptions[subscriptionHash]
@@ -714,12 +722,15 @@ class bingx(ccxt.async_support.bingx):
714
722
  self.orderbooks[symbol] = self.order_book({}, limit)
715
723
  orderbook = self.orderbooks[symbol]
716
724
  snapshot = None
725
+ timestamp = self.safe_integer_2(message, 'timestamp', 'ts')
726
+ timestamp = self.safe_integer_2(data, 'timestamp', 'ts', timestamp)
717
727
  if market['inverse']:
718
- snapshot = self.parse_order_book(data, symbol, None, 'bids', 'asks', 'p', 'a')
728
+ snapshot = self.parse_order_book(data, symbol, timestamp, 'bids', 'asks', 'p', 'a')
719
729
  else:
720
- snapshot = self.parse_order_book(data, symbol, None, 'bids', 'asks', 0, 1)
730
+ snapshot = self.parse_order_book(data, symbol, timestamp, 'bids', 'asks', 0, 1)
731
+ nonce = self.safe_integer(data, 'lastUpdateId')
732
+ snapshot['nonce'] = nonce
721
733
  orderbook.reset(snapshot)
722
- self.orderbooks[symbol] = orderbook
723
734
  messageHash = self.get_message_hash('orderbook', symbol)
724
735
  client.resolve(orderbook, messageHash)
725
736
  # resolve for "all"
ccxt/pro/bitget.py CHANGED
@@ -52,6 +52,10 @@ class bitget(ccxt.async_support.bitget):
52
52
  'public': 'wss://ws.bitget.com/v2/ws/public',
53
53
  'private': 'wss://ws.bitget.com/v2/ws/private',
54
54
  },
55
+ 'demo': {
56
+ 'public': 'wss://wspap.bitget.com/v2/ws/public',
57
+ 'private': 'wss://wspap.bitget.com/v2/ws/private',
58
+ },
55
59
  },
56
60
  },
57
61
  'options': {
@@ -1125,7 +1129,7 @@ class bitget(ccxt.async_support.bitget):
1125
1129
  instType = 'SPOT'
1126
1130
  else:
1127
1131
  instType, params = self.get_inst_type(market, params)
1128
- if type == 'spot':
1132
+ if type == 'spot' and (symbol is not None):
1129
1133
  subscriptionHash = subscriptionHash + ':' + symbol
1130
1134
  if isTrigger:
1131
1135
  subscriptionHash = subscriptionHash + ':stop' # we don't want to re-use the same subscription hash for stop orders
@@ -1697,6 +1701,11 @@ class bitget(ccxt.async_support.bitget):
1697
1701
 
1698
1702
  async def watch_public(self, messageHash, args, params={}):
1699
1703
  url = self.urls['api']['ws']['public']
1704
+ sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
1705
+ if sandboxMode:
1706
+ instType = self.safe_string(args, 'instType')
1707
+ if (instType != 'SCOIN-FUTURES') and (instType != 'SUSDT-FUTURES') and (instType != 'SUSDC-FUTURES'):
1708
+ url = self.urls['api']['demo']['public']
1700
1709
  request: dict = {
1701
1710
  'op': 'subscribe',
1702
1711
  'args': [args],
@@ -1706,6 +1715,11 @@ class bitget(ccxt.async_support.bitget):
1706
1715
 
1707
1716
  async def un_watch_public(self, messageHash, args, params={}):
1708
1717
  url = self.urls['api']['ws']['public']
1718
+ sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
1719
+ if sandboxMode:
1720
+ instType = self.safe_string(args, 'instType')
1721
+ if (instType != 'SCOIN-FUTURES') and (instType != 'SUSDT-FUTURES') and (instType != 'SUSDC-FUTURES'):
1722
+ url = self.urls['api']['demo']['public']
1709
1723
  request: dict = {
1710
1724
  'op': 'unsubscribe',
1711
1725
  'args': [args],
@@ -1715,6 +1729,12 @@ class bitget(ccxt.async_support.bitget):
1715
1729
 
1716
1730
  async def watch_public_multiple(self, messageHashes, argsArray, params={}):
1717
1731
  url = self.urls['api']['ws']['public']
1732
+ sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
1733
+ if sandboxMode:
1734
+ argsArrayFirst = self.safe_dict(argsArray, 0, {})
1735
+ instType = self.safe_string(argsArrayFirst, 'instType')
1736
+ if (instType != 'SCOIN-FUTURES') and (instType != 'SUSDT-FUTURES') and (instType != 'SUSDC-FUTURES'):
1737
+ url = self.urls['api']['demo']['public']
1718
1738
  request: dict = {
1719
1739
  'op': 'subscribe',
1720
1740
  'args': argsArray,
@@ -1724,7 +1744,7 @@ class bitget(ccxt.async_support.bitget):
1724
1744
 
1725
1745
  async def authenticate(self, params={}):
1726
1746
  self.check_required_credentials()
1727
- url = self.urls['api']['ws']['private']
1747
+ url = self.safe_string(params, 'url')
1728
1748
  client = self.client(url)
1729
1749
  messageHash = 'authenticated'
1730
1750
  future = client.future(messageHash)
@@ -1750,8 +1770,13 @@ class bitget(ccxt.async_support.bitget):
1750
1770
  return await future
1751
1771
 
1752
1772
  async def watch_private(self, messageHash, subscriptionHash, args, params={}):
1753
- await self.authenticate()
1754
1773
  url = self.urls['api']['ws']['private']
1774
+ sandboxMode = self.safe_bool_2(self.options, 'sandboxMode', 'sandbox', False)
1775
+ if sandboxMode:
1776
+ instType = self.safe_string(args, 'instType')
1777
+ if (instType != 'SCOIN-FUTURES') and (instType != 'SUSDT-FUTURES') and (instType != 'SUSDC-FUTURES'):
1778
+ url = self.urls['api']['demo']['private']
1779
+ await self.authenticate({'url': url})
1755
1780
  request: dict = {
1756
1781
  'op': 'subscribe',
1757
1782
  'args': [args],
ccxt/pro/bybit.py CHANGED
@@ -1494,6 +1494,7 @@ class bybit(ccxt.async_support.bybit):
1494
1494
  :param int [since]: the earliest time in ms to fetch liquidations for
1495
1495
  :param int [limit]: the maximum number of liquidation structures to retrieve
1496
1496
  :param dict [params]: exchange specific parameters for the bitmex api endpoint
1497
+ :param str [params.method]: exchange specific method, supported: liquidation, allLiquidation
1497
1498
  :returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
1498
1499
  """
1499
1500
  await self.load_markets()
@@ -1501,8 +1502,10 @@ class bybit(ccxt.async_support.bybit):
1501
1502
  symbol = market['symbol']
1502
1503
  url = await self.get_url_by_market_type(symbol, False, 'watchLiquidations', params)
1503
1504
  params = self.clean_params(params)
1505
+ method = None
1506
+ method, params = self.handle_option_and_params(params, 'watchLiquidations', 'method', 'liquidation')
1504
1507
  messageHash = 'liquidations::' + symbol
1505
- topic = 'liquidation.' + market['id']
1508
+ topic = method + '.' + market['id']
1506
1509
  newLiquidation = await self.watch_topics(url, [messageHash], [topic], params)
1507
1510
  if self.newUpdates:
1508
1511
  return newLiquidation
@@ -1510,52 +1513,92 @@ class bybit(ccxt.async_support.bybit):
1510
1513
 
1511
1514
  def handle_liquidation(self, client: Client, message):
1512
1515
  #
1513
- # {
1514
- # "data": {
1515
- # "price": "0.03803",
1516
- # "side": "Buy",
1517
- # "size": "1637",
1518
- # "symbol": "GALAUSDT",
1519
- # "updatedTime": 1673251091822
1520
- # },
1521
- # "topic": "liquidation.GALAUSDT",
1522
- # "ts": 1673251091822,
1523
- # "type": "snapshot"
1524
- # }
1516
+ # {
1517
+ # "data": {
1518
+ # "price": "0.03803",
1519
+ # "side": "Buy",
1520
+ # "size": "1637",
1521
+ # "symbol": "GALAUSDT",
1522
+ # "updatedTime": 1673251091822
1523
+ # },
1524
+ # "topic": "liquidation.GALAUSDT",
1525
+ # "ts": 1673251091822,
1526
+ # "type": "snapshot"
1527
+ # }
1525
1528
  #
1526
- rawLiquidation = self.safe_dict(message, 'data', {})
1527
- marketId = self.safe_string(rawLiquidation, 'symbol')
1528
- market = self.safe_market(marketId, None, '', 'contract')
1529
- symbol = market['symbol']
1530
- liquidation = self.parse_ws_liquidation(rawLiquidation, market)
1531
- liquidations = self.safe_value(self.liquidations, symbol)
1532
- if liquidations is None:
1533
- limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
1534
- liquidations = ArrayCache(limit)
1535
- liquidations.append(liquidation)
1536
- self.liquidations[symbol] = liquidations
1537
- client.resolve([liquidation], 'liquidations')
1538
- client.resolve([liquidation], 'liquidations::' + symbol)
1529
+ # {
1530
+ # "topic": "allLiquidation.ROSEUSDT",
1531
+ # "type": "snapshot",
1532
+ # "ts": 1739502303204,
1533
+ # "data": [
1534
+ # {
1535
+ # "T": 1739502302929,
1536
+ # "s": "ROSEUSDT",
1537
+ # "S": "Sell",
1538
+ # "v": "20000",
1539
+ # "p": "0.04499"
1540
+ # }
1541
+ # ]
1542
+ # }
1543
+ #
1544
+ if isinstance(message['data'], list):
1545
+ rawLiquidations = self.safe_list(message, 'data', [])
1546
+ for i in range(0, len(rawLiquidations)):
1547
+ rawLiquidation = rawLiquidations[i]
1548
+ marketId = self.safe_string(rawLiquidation, 's')
1549
+ market = self.safe_market(marketId, None, '', 'contract')
1550
+ symbol = market['symbol']
1551
+ liquidation = self.parse_ws_liquidation(rawLiquidation, market)
1552
+ liquidations = self.safe_value(self.liquidations, symbol)
1553
+ if liquidations is None:
1554
+ limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
1555
+ liquidations = ArrayCache(limit)
1556
+ liquidations.append(liquidation)
1557
+ self.liquidations[symbol] = liquidations
1558
+ client.resolve([liquidation], 'liquidations')
1559
+ client.resolve([liquidation], 'liquidations::' + symbol)
1560
+ else:
1561
+ rawLiquidation = self.safe_dict(message, 'data', {})
1562
+ marketId = self.safe_string(rawLiquidation, 'symbol')
1563
+ market = self.safe_market(marketId, None, '', 'contract')
1564
+ symbol = market['symbol']
1565
+ liquidation = self.parse_ws_liquidation(rawLiquidation, market)
1566
+ liquidations = self.safe_value(self.liquidations, symbol)
1567
+ if liquidations is None:
1568
+ limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
1569
+ liquidations = ArrayCache(limit)
1570
+ liquidations.append(liquidation)
1571
+ self.liquidations[symbol] = liquidations
1572
+ client.resolve([liquidation], 'liquidations')
1573
+ client.resolve([liquidation], 'liquidations::' + symbol)
1539
1574
 
1540
1575
  def parse_ws_liquidation(self, liquidation, market=None):
1541
1576
  #
1542
- # {
1543
- # "price": "0.03803",
1544
- # "side": "Buy",
1545
- # "size": "1637",
1546
- # "symbol": "GALAUSDT",
1547
- # "updatedTime": 1673251091822
1548
- # }
1577
+ # {
1578
+ # "price": "0.03803",
1579
+ # "side": "Buy",
1580
+ # "size": "1637",
1581
+ # "symbol": "GALAUSDT",
1582
+ # "updatedTime": 1673251091822
1583
+ # }
1584
+ #
1585
+ # {
1586
+ # "T": 1739502302929,
1587
+ # "s": "ROSEUSDT",
1588
+ # "S": "Sell",
1589
+ # "v": "20000",
1590
+ # "p": "0.04499"
1591
+ # }
1549
1592
  #
1550
- marketId = self.safe_string(liquidation, 'symbol')
1593
+ marketId = self.safe_string_2(liquidation, 'symbol', 's')
1551
1594
  market = self.safe_market(marketId, market, '', 'contract')
1552
- timestamp = self.safe_integer(liquidation, 'updatedTime')
1595
+ timestamp = self.safe_integer_2(liquidation, 'updatedTime', 'T')
1553
1596
  return self.safe_liquidation({
1554
1597
  'info': liquidation,
1555
1598
  'symbol': market['symbol'],
1556
- 'contracts': self.safe_number(liquidation, 'size'),
1599
+ 'contracts': self.safe_number_2(liquidation, 'size', 'v'),
1557
1600
  'contractSize': self.safe_number(market, 'contractSize'),
1558
- 'price': self.safe_number(liquidation, 'price'),
1601
+ 'price': self.safe_number_2(liquidation, 'price', 'p'),
1559
1602
  'baseValue': None,
1560
1603
  'quoteValue': None,
1561
1604
  'timestamp': timestamp,
@@ -2318,6 +2361,7 @@ class bybit(ccxt.async_support.bybit):
2318
2361
  'user.openapi.perp.trade': self.handle_my_trades,
2319
2362
  'position': self.handle_positions,
2320
2363
  'liquidation': self.handle_liquidation,
2364
+ 'allLiquidation': self.handle_liquidation,
2321
2365
  'pong': self.handle_pong,
2322
2366
  'order.create': self.handle_order_ws,
2323
2367
  'order.amend': self.handle_order_ws,
ccxt/test/tests_async.py CHANGED
@@ -765,8 +765,8 @@ class testMainClass:
765
765
  self.assert_new_and_stored_output(exchange, skip_keys, new_item, stored_item, strict_type_check)
766
766
  else:
767
767
  # built-in types like strings, numbers, booleans
768
- sanitized_new_output = None if (not new_output) else new_output # we store undefined as nulls in the json file so we need to convert it back
769
- sanitized_stored_output = None if (not stored_output) else stored_output
768
+ sanitized_new_output = None if (is_null_value(new_output)) else new_output # we store undefined as nulls in the json file so we need to convert it back
769
+ sanitized_stored_output = None if (is_null_value(stored_output)) else stored_output
770
770
  new_output_string = str(sanitized_new_output) if sanitized_new_output else 'undefined'
771
771
  stored_output_string = str(sanitized_stored_output) if sanitized_stored_output else 'undefined'
772
772
  message_error = 'output value mismatch:' + new_output_string + ' != ' + stored_output_string
@@ -787,7 +787,7 @@ class testMainClass:
787
787
  is_string = is_computed_string or is_stored_string
788
788
  is_undefined = is_computed_undefined or is_stored_undefined # undefined is a perfetly valid value
789
789
  if is_boolean or is_string or is_undefined:
790
- if self.lang == 'C#':
790
+ if (self.lang == 'C#') or (self.lang == 'GO'):
791
791
  # tmp c# number comparsion
792
792
  is_number = False
793
793
  try:
@@ -935,6 +935,7 @@ class testMainClass:
935
935
  def init_offline_exchange(self, exchange_name):
936
936
  markets = self.load_markets_from_file(exchange_name)
937
937
  currencies = self.load_currencies_from_file(exchange_name)
938
+ # we add "proxy" 2 times to intentionally trigger InvalidProxySettings
938
939
  exchange = init_exchange(exchange_name, {
939
940
  'markets': markets,
940
941
  'currencies': currencies,
ccxt/test/tests_sync.py CHANGED
@@ -762,8 +762,8 @@ class testMainClass:
762
762
  self.assert_new_and_stored_output(exchange, skip_keys, new_item, stored_item, strict_type_check)
763
763
  else:
764
764
  # built-in types like strings, numbers, booleans
765
- sanitized_new_output = None if (not new_output) else new_output # we store undefined as nulls in the json file so we need to convert it back
766
- sanitized_stored_output = None if (not stored_output) else stored_output
765
+ sanitized_new_output = None if (is_null_value(new_output)) else new_output # we store undefined as nulls in the json file so we need to convert it back
766
+ sanitized_stored_output = None if (is_null_value(stored_output)) else stored_output
767
767
  new_output_string = str(sanitized_new_output) if sanitized_new_output else 'undefined'
768
768
  stored_output_string = str(sanitized_stored_output) if sanitized_stored_output else 'undefined'
769
769
  message_error = 'output value mismatch:' + new_output_string + ' != ' + stored_output_string
@@ -784,7 +784,7 @@ class testMainClass:
784
784
  is_string = is_computed_string or is_stored_string
785
785
  is_undefined = is_computed_undefined or is_stored_undefined # undefined is a perfetly valid value
786
786
  if is_boolean or is_string or is_undefined:
787
- if self.lang == 'C#':
787
+ if (self.lang == 'C#') or (self.lang == 'GO'):
788
788
  # tmp c# number comparsion
789
789
  is_number = False
790
790
  try:
@@ -932,6 +932,7 @@ class testMainClass:
932
932
  def init_offline_exchange(self, exchange_name):
933
933
  markets = self.load_markets_from_file(exchange_name)
934
934
  currencies = self.load_currencies_from_file(exchange_name)
935
+ # we add "proxy" 2 times to intentionally trigger InvalidProxySettings
935
936
  exchange = init_exchange(exchange_name, {
936
937
  'markets': markets,
937
938
  'currencies': currencies,
ccxt/tradeogre.py CHANGED
@@ -140,7 +140,6 @@ class tradeogre(Exchange, ImplicitAPI):
140
140
  },
141
141
  'private': {
142
142
  'get': {
143
- 'account/balance': 1,
144
143
  'account/balances': 1,
145
144
  'account/order/{uuid}': 1,
146
145
  },
@@ -150,6 +149,7 @@ class tradeogre(Exchange, ImplicitAPI):
150
149
  'order/cancel': 1,
151
150
  'orders': 1,
152
151
  'account/orders': 1,
152
+ 'account/balance': 1,
153
153
  },
154
154
  },
155
155
  },
@@ -588,10 +588,26 @@ class tradeogre(Exchange, ImplicitAPI):
588
588
  """
589
589
  query for balance and get the amount of funds available for trading or funds locked in orders
590
590
  :param dict [params]: extra parameters specific to the exchange API endpoint
591
+ :param str [params.currency]: currency to fetch the balance for
591
592
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
592
593
  """
593
594
  self.load_markets()
594
- response = self.privateGetAccountBalances(params)
595
+ response = None
596
+ currency = self.safe_string(params, 'currency')
597
+ if currency is not None:
598
+ response = self.privatePostAccountBalance(params)
599
+ singleCurrencyresult: dict = {
600
+ 'info': response,
601
+ }
602
+ code = self.safe_currency_code(currency)
603
+ account = {
604
+ 'total': self.safe_number(response, 'balance'),
605
+ 'free': self.safe_number(response, 'available'),
606
+ }
607
+ singleCurrencyresult[code] = account
608
+ return self.safe_balance(singleCurrencyresult)
609
+ else:
610
+ response = self.privateGetAccountBalances(params)
595
611
  result = self.safe_dict(response, 'balances', {})
596
612
  return self.parse_balance(result)
597
613
 
@@ -744,11 +760,11 @@ class tradeogre(Exchange, ImplicitAPI):
744
760
  'side': self.safe_string(order, 'type'),
745
761
  'price': self.safe_string(order, 'price'),
746
762
  'triggerPrice': None,
747
- 'amount': self.safe_string(order, 'quantity'),
763
+ 'amount': None,
748
764
  'cost': None,
749
765
  'average': None,
750
766
  'filled': self.safe_string(order, 'fulfilled'),
751
- 'remaining': None,
767
+ 'remaining': self.safe_string(order, 'quantity'),
752
768
  'status': None,
753
769
  'fee': {
754
770
  'currency': None,
ccxt/whitebit.py CHANGED
@@ -1342,9 +1342,11 @@ class whitebit(Exchange, ImplicitAPI):
1342
1342
  :param dict [params]: extra parameters specific to the exchange API endpoint
1343
1343
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1344
1344
  """
1345
- params['cost'] = cost
1345
+ req = {
1346
+ 'cost': cost,
1347
+ }
1346
1348
  # only buy side is supported
1347
- return self.create_order(symbol, 'market', side, 0, None, params)
1349
+ return self.create_order(symbol, 'market', side, 0, None, self.extend(req, params))
1348
1350
 
1349
1351
  def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}) -> Order:
1350
1352
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.4.69
3
+ Version: 4.4.71
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
@@ -49,9 +49,9 @@ Requires-Dist: mypy==1.6.1; extra == "type"
49
49
 
50
50
  # CCXT – CryptoCurrency eXchange Trading Library
51
51
 
52
- [![NPM Downloads](https://img.shields.io/npm/dy/ccxt.svg)](https://www.npmjs.com/package/ccxt) [![npm](https://img.shields.io/npm/v/ccxt.svg)](https://npmjs.com/package/ccxt) [![PyPI](https://img.shields.io/pypi/v/ccxt.svg)](https://pypi.python.org/pypi/ccxt) [![NuGet version](https://img.shields.io/nuget/v/ccxt)](https://www.nuget.org/packages/ccxt) [![GoDoc](https://pkg.go.dev/badge/github.com/ccxt/ccxt/go/v4?utm_source=godoc)](https://godoc.org/github.com/ccxt/ccxt/go/v4) [![Discord](https://img.shields.io/discord/690203284119617602?logo=discord&logoColor=white)](https://discord.gg/ccxt) [![Supported Exchanges](https://img.shields.io/badge/exchanges-111-blue.svg)](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) [![Follow CCXT at x.com](https://img.shields.io/twitter/follow/ccxt_official.svg?style=social&label=CCXT)](https://x.com/ccxt_official)
52
+ [![NPM Downloads](https://img.shields.io/npm/dy/ccxt.svg)](https://www.npmjs.com/package/ccxt) [![npm](https://img.shields.io/npm/v/ccxt.svg)](https://npmjs.com/package/ccxt) [![PyPI](https://img.shields.io/pypi/v/ccxt.svg)](https://pypi.python.org/pypi/ccxt) [![NuGet version](https://img.shields.io/nuget/v/ccxt)](https://www.nuget.org/packages/ccxt) [![GoDoc](https://pkg.go.dev/badge/github.com/ccxt/ccxt/go/v4?utm_source=godoc)](https://godoc.org/github.com/ccxt/ccxt/go/v4) [![Discord](https://img.shields.io/discord/690203284119617602?logo=discord&logoColor=white)](https://discord.gg/ccxt) [![Supported Exchanges](https://img.shields.io/badge/exchanges-110-blue.svg)](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) [![Follow CCXT at x.com](https://img.shields.io/twitter/follow/ccxt_official.svg?style=social&label=CCXT)](https://x.com/ccxt_official)
53
53
 
54
- A JavaScript / Python / PHP / C# / Go library for cryptocurrency trading and e-commerce with support for many bitcoin/ether/altcoin exchange markets and merchant APIs.
54
+ A `JavaScript` / `Python` / `PHP` / `C#` / `Go` library for cryptocurrency trading and e-commerce with support for many bitcoin/ether/altcoin exchange markets and merchant APIs.
55
55
 
56
56
  ### [Install](#install) · [Usage](#usage) · [Manual](https://github.com/ccxt/ccxt/wiki) · [FAQ](https://github.com/ccxt/ccxt/wiki/FAQ) · [Examples](https://github.com/ccxt/ccxt/tree/master/examples) · [Contributing](https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md) · [Social](#social)
57
57
 
@@ -70,9 +70,6 @@ Current feature list:
70
70
 
71
71
  ## Sponsored Promotion
72
72
 
73
- [![Gate-3rd-Trading-Carnival](https://github.com/user-attachments/assets/6cbb4055-97a8-4985-8c55-0056b4a8612c)](https://www.gate.io/activities/ccxt-trading-competition)
74
-
75
-
76
73
  ## See Also
77
74
 
78
75
  - <sub>[![TabTrader](https://user-images.githubusercontent.com/1294454/66755907-9c3e8880-eea1-11e9-846e-0bff349ceb87.png)](https://tab-trader.com/?utm_source=ccxt)</sub> **[TabTrader](https://tab-trader.com/?utm_source=ccxt)** – trading on all exchanges in one app. Available on **[Android](https://play.google.com/store/apps/details?id=com.tabtrader.android&referrer=utm_source%3Dccxt)** and **[iOS](https://itunes.apple.com/app/apple-store/id1095716562?mt=8)**!
@@ -278,13 +275,13 @@ console.log(version, Object.keys(exchanges));
278
275
 
279
276
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
280
277
 
281
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.69/dist/ccxt.browser.min.js
282
- * unpkg: https://unpkg.com/ccxt@4.4.69/dist/ccxt.browser.min.js
278
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.71/dist/ccxt.browser.min.js
279
+ * unpkg: https://unpkg.com/ccxt@4.4.71/dist/ccxt.browser.min.js
283
280
 
284
281
  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.
285
282
 
286
283
  ```HTML
287
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.69/dist/ccxt.browser.min.js"></script>
284
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.71/dist/ccxt.browser.min.js"></script>
288
285
  ```
289
286
 
290
287
  Creates a global `ccxt` object: