ccxt 4.4.75__py2.py3-none-any.whl → 4.4.78__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 (111) hide show
  1. ccxt/__init__.py +3 -3
  2. ccxt/abstract/apex.py +31 -0
  3. ccxt/abstract/myokx.py +4 -0
  4. ccxt/abstract/okx.py +4 -0
  5. ccxt/abstract/upbit.py +51 -37
  6. ccxt/abstract/xt.py +3 -0
  7. ccxt/apex.py +1884 -0
  8. ccxt/ascendex.py +2 -2
  9. ccxt/async_support/__init__.py +3 -3
  10. ccxt/async_support/apex.py +1884 -0
  11. ccxt/async_support/ascendex.py +2 -2
  12. ccxt/async_support/base/exchange.py +2 -2
  13. ccxt/async_support/binance.py +39 -217
  14. ccxt/async_support/bingx.py +1 -1
  15. ccxt/async_support/bitfinex.py +2 -2
  16. ccxt/async_support/bitflyer.py +2 -2
  17. ccxt/async_support/bitget.py +135 -65
  18. ccxt/async_support/bitmart.py +2 -2
  19. ccxt/async_support/bitmex.py +6 -6
  20. ccxt/async_support/bitrue.py +48 -0
  21. ccxt/async_support/cex.py +1 -1
  22. ccxt/async_support/coinbase.py +29 -4
  23. ccxt/async_support/coincatch.py +66 -0
  24. ccxt/async_support/coinex.py +3 -1
  25. ccxt/async_support/coinlist.py +85 -2
  26. ccxt/async_support/cryptocom.py +2 -2
  27. ccxt/async_support/defx.py +1 -1
  28. ccxt/async_support/delta.py +1 -1
  29. ccxt/async_support/deribit.py +2 -2
  30. ccxt/async_support/derive.py +2 -2
  31. ccxt/async_support/digifinex.py +2 -2
  32. ccxt/async_support/gate.py +1 -1
  33. ccxt/async_support/hitbtc.py +5 -2
  34. ccxt/async_support/htx.py +2 -2
  35. ccxt/async_support/hyperliquid.py +13 -6
  36. ccxt/async_support/kraken.py +2 -2
  37. ccxt/async_support/krakenfutures.py +2 -2
  38. ccxt/async_support/kucoinfutures.py +2 -2
  39. ccxt/async_support/mexc.py +50 -52
  40. ccxt/async_support/okx.py +21 -9
  41. ccxt/async_support/oxfun.py +2 -2
  42. ccxt/async_support/paradex.py +5 -10
  43. ccxt/async_support/phemex.py +4 -3
  44. ccxt/async_support/poloniex.py +3 -3
  45. ccxt/async_support/probit.py +1 -0
  46. ccxt/async_support/tradeogre.py +2 -1
  47. ccxt/async_support/upbit.py +265 -89
  48. ccxt/async_support/vertex.py +2 -2
  49. ccxt/async_support/whitebit.py +1 -0
  50. ccxt/async_support/woo.py +5 -3
  51. ccxt/async_support/woofipro.py +2 -2
  52. ccxt/async_support/xt.py +115 -5
  53. ccxt/base/exchange.py +76 -3
  54. ccxt/binance.py +39 -217
  55. ccxt/bingx.py +1 -1
  56. ccxt/bitfinex.py +2 -2
  57. ccxt/bitflyer.py +2 -2
  58. ccxt/bitget.py +135 -65
  59. ccxt/bitmart.py +2 -2
  60. ccxt/bitmex.py +6 -6
  61. ccxt/bitrue.py +48 -0
  62. ccxt/cex.py +1 -1
  63. ccxt/coinbase.py +29 -4
  64. ccxt/coincatch.py +66 -0
  65. ccxt/coinex.py +3 -1
  66. ccxt/coinlist.py +85 -2
  67. ccxt/cryptocom.py +2 -2
  68. ccxt/defx.py +1 -1
  69. ccxt/delta.py +1 -1
  70. ccxt/deribit.py +2 -2
  71. ccxt/derive.py +2 -2
  72. ccxt/digifinex.py +2 -2
  73. ccxt/gate.py +1 -1
  74. ccxt/hitbtc.py +5 -2
  75. ccxt/htx.py +2 -2
  76. ccxt/hyperliquid.py +13 -6
  77. ccxt/kraken.py +2 -2
  78. ccxt/krakenfutures.py +2 -2
  79. ccxt/kucoinfutures.py +2 -2
  80. ccxt/mexc.py +50 -52
  81. ccxt/okx.py +21 -9
  82. ccxt/oxfun.py +2 -2
  83. ccxt/paradex.py +5 -10
  84. ccxt/phemex.py +4 -3
  85. ccxt/poloniex.py +3 -3
  86. ccxt/pro/__init__.py +5 -1
  87. ccxt/pro/apex.py +984 -0
  88. ccxt/pro/coinbase.py +4 -6
  89. ccxt/pro/gate.py +22 -2
  90. ccxt/pro/hollaex.py +2 -2
  91. ccxt/pro/hyperliquid.py +1 -1
  92. ccxt/pro/p2b.py +2 -2
  93. ccxt/pro/tradeogre.py +272 -0
  94. ccxt/probit.py +1 -0
  95. ccxt/test/tests_async.py +27 -0
  96. ccxt/test/tests_sync.py +27 -0
  97. ccxt/tradeogre.py +2 -1
  98. ccxt/upbit.py +265 -89
  99. ccxt/vertex.py +2 -2
  100. ccxt/whitebit.py +1 -0
  101. ccxt/woo.py +5 -3
  102. ccxt/woofipro.py +2 -2
  103. ccxt/xt.py +115 -5
  104. {ccxt-4.4.75.dist-info → ccxt-4.4.78.dist-info}/METADATA +4 -4
  105. {ccxt-4.4.75.dist-info → ccxt-4.4.78.dist-info}/RECORD +108 -106
  106. ccxt/abstract/ace.py +0 -15
  107. ccxt/ace.py +0 -1152
  108. ccxt/async_support/ace.py +0 -1152
  109. {ccxt-4.4.75.dist-info → ccxt-4.4.78.dist-info}/LICENSE.txt +0 -0
  110. {ccxt-4.4.75.dist-info → ccxt-4.4.78.dist-info}/WHEEL +0 -0
  111. {ccxt-4.4.75.dist-info → ccxt-4.4.78.dist-info}/top_level.txt +0 -0
ccxt/async_support/xt.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.xt import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Any, Currencies, Currency, DepositAddress, Int, LedgerEntry, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderSide, OrderType, Str, Tickers, FundingRate, Transaction, TransferEntry
10
+ from ccxt.base.types import Any, Currencies, Currency, DepositAddress, Int, LedgerEntry, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderSide, OrderType, Position, Str, Tickers, FundingRate, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -59,7 +59,7 @@ class xt(Exchange, ImplicitAPI):
59
59
  'createOrder': True,
60
60
  'createPostOnlyOrder': False,
61
61
  'createReduceOnlyOrder': True,
62
- 'editOrder': False,
62
+ 'editOrder': True,
63
63
  'fetchAccounts': False,
64
64
  'fetchBalance': True,
65
65
  'fetchBidsAsks': True,
@@ -246,6 +246,9 @@ class xt(Exchange, ImplicitAPI):
246
246
  'open-order': 1,
247
247
  'order/{orderId}': 1,
248
248
  },
249
+ 'put': {
250
+ 'order/{orderId}': 1,
251
+ },
249
252
  },
250
253
  'linear': {
251
254
  'get': {
@@ -280,6 +283,7 @@ class xt(Exchange, ImplicitAPI):
280
283
  'future/trade/v1/order/cancel-all': 1,
281
284
  'future/trade/v1/order/create': 1,
282
285
  'future/trade/v1/order/create-batch': 1,
286
+ 'future/trade/v1/order/update': 1,
283
287
  'future/user/v1/account/open': 1,
284
288
  'future/user/v1/position/adjust-leverage': 1,
285
289
  'future/user/v1/position/auto-margin': 1,
@@ -323,6 +327,7 @@ class xt(Exchange, ImplicitAPI):
323
327
  'future/trade/v1/order/cancel-all': 1,
324
328
  'future/trade/v1/order/create': 1,
325
329
  'future/trade/v1/order/create-batch': 1,
330
+ 'future/trade/v1/order/update': 1,
326
331
  'future/user/v1/account/open': 1,
327
332
  'future/user/v1/position/adjust-leverage': 1,
328
333
  'future/user/v1/position/auto-margin': 1,
@@ -957,6 +962,12 @@ class xt(Exchange, ImplicitAPI):
957
962
  },
958
963
  },
959
964
  }
965
+ typeRaw = self.safe_string(entry, 'type')
966
+ type: Str = None
967
+ if typeRaw == 'FT':
968
+ type = 'crypto'
969
+ else:
970
+ type = 'other'
960
971
  result[code] = {
961
972
  'info': entry,
962
973
  'id': currencyId,
@@ -968,6 +979,7 @@ class xt(Exchange, ImplicitAPI):
968
979
  'deposit': deposit,
969
980
  'withdraw': withdraw,
970
981
  'networks': networks,
982
+ 'type': type,
971
983
  'limits': {
972
984
  'amount': {
973
985
  'min': None,
@@ -3338,7 +3350,7 @@ class xt(Exchange, ImplicitAPI):
3338
3350
  # "cancelId": "208322474307982720"
3339
3351
  # }
3340
3352
  #
3341
- # swap and future: createOrder, cancelOrder
3353
+ # swap and future: createOrder, cancelOrder, editOrder
3342
3354
  #
3343
3355
  # {
3344
3356
  # "returnCode": 0,
@@ -3443,6 +3455,14 @@ class xt(Exchange, ImplicitAPI):
3443
3455
  # "createdTime": 1681273420039
3444
3456
  # }
3445
3457
  #
3458
+ # spot editOrder
3459
+ #
3460
+ # {
3461
+ # "orderId": "484203027161892224",
3462
+ # "modifyId": "484203544105344000",
3463
+ # "clientModifyId": null
3464
+ # }
3465
+ #
3446
3466
  marketId = self.safe_string(order, 'symbol')
3447
3467
  marketType = ('result' in order) or 'contract' if ('positionSide' in order) else 'spot'
3448
3468
  market = self.safe_market(marketId, market, None, marketType)
@@ -3456,7 +3476,7 @@ class xt(Exchange, ImplicitAPI):
3456
3476
  return self.safe_order({
3457
3477
  'info': order,
3458
3478
  'id': self.safe_string_n(order, ['orderId', 'result', 'cancelId', 'entrustId', 'profitId']),
3459
- 'clientOrderId': self.safe_string(order, 'clientOrderId'),
3479
+ 'clientOrderId': self.safe_string_2(order, 'clientOrderId', 'clientModifyId'),
3460
3480
  'timestamp': timestamp,
3461
3481
  'datetime': self.iso8601(timestamp),
3462
3482
  'lastTradeTimestamp': lastUpdatedTimestamp,
@@ -4474,7 +4494,7 @@ class xt(Exchange, ImplicitAPI):
4474
4494
  return self.parse_position(entry, marketInner)
4475
4495
  return None
4476
4496
 
4477
- async def fetch_positions(self, symbols: List[str] = None, params={}):
4497
+ async def fetch_positions(self, symbols: List[str] = None, params={}) -> List[Position]:
4478
4498
  """
4479
4499
  fetch all open positions
4480
4500
 
@@ -4679,6 +4699,94 @@ class xt(Exchange, ImplicitAPI):
4679
4699
  #
4680
4700
  return response # unify return type
4681
4701
 
4702
+ async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
4703
+ """
4704
+ cancels an order and places a new order
4705
+
4706
+ https://doc.xt.com/#orderorderUpdate
4707
+ https://doc.xt.com/#futures_orderupdate
4708
+ https://doc.xt.com/#futures_entrustupdateProfit
4709
+
4710
+ :param str id: order id
4711
+ :param str symbol: unified symbol of the market to create an order in
4712
+ :param str type: 'market' or 'limit'
4713
+ :param str side: 'buy' or 'sell'
4714
+ :param float amount: how much of the currency you want to trade in units of the base currency
4715
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
4716
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4717
+ :param float [params.stopLoss]: price to set a stop-loss on an open position
4718
+ :param float [params.takeProfit]: price to set a take-profit on an open position
4719
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
4720
+ """
4721
+ if amount is None:
4722
+ raise ArgumentsRequired(self.id + ' editOrder() requires an amount argument')
4723
+ await self.load_markets()
4724
+ market = self.market(symbol)
4725
+ request = {}
4726
+ stopLoss = self.safe_number_2(params, 'stopLoss', 'triggerStopPrice')
4727
+ takeProfit = self.safe_number_2(params, 'takeProfit', 'triggerProfitPrice')
4728
+ params = self.omit(params, ['stopLoss', 'takeProfit'])
4729
+ isStopLoss = (stopLoss is not None)
4730
+ isTakeProfit = (takeProfit is not None)
4731
+ if isStopLoss or isTakeProfit:
4732
+ request['profitId'] = id
4733
+ else:
4734
+ request['orderId'] = id
4735
+ request['price'] = self.price_to_precision(symbol, price)
4736
+ response = None
4737
+ if market['swap']:
4738
+ if isStopLoss:
4739
+ request['triggerStopPrice'] = self.price_to_precision(symbol, stopLoss)
4740
+ elif takeProfit is not None:
4741
+ request['triggerProfitPrice'] = self.price_to_precision(symbol, takeProfit)
4742
+ else:
4743
+ request['origQty'] = self.amount_to_precision(symbol, amount)
4744
+ subType = None
4745
+ subType, params = self.handle_sub_type_and_params('editOrder', market, params)
4746
+ if subType == 'inverse':
4747
+ if isStopLoss or isTakeProfit:
4748
+ response = await self.privateInversePostFutureTradeV1EntrustUpdateProfitStop(self.extend(request, params))
4749
+ else:
4750
+ response = await self.privateInversePostFutureTradeV1OrderUpdate(self.extend(request, params))
4751
+ #
4752
+ # {
4753
+ # "returnCode": 0,
4754
+ # "msgInfo": "success",
4755
+ # "error": null,
4756
+ # "result": "483869474947826752"
4757
+ # }
4758
+ #
4759
+ else:
4760
+ if isStopLoss or isTakeProfit:
4761
+ response = await self.privateLinearPostFutureTradeV1EntrustUpdateProfitStop(self.extend(request, params))
4762
+ else:
4763
+ response = await self.privateLinearPostFutureTradeV1OrderUpdate(self.extend(request, params))
4764
+ #
4765
+ # {
4766
+ # "returnCode": 0,
4767
+ # "msgInfo": "success",
4768
+ # "error": null,
4769
+ # "result": "483869474947826752"
4770
+ # }
4771
+ #
4772
+ else:
4773
+ request['quantity'] = self.amount_to_precision(symbol, amount)
4774
+ response = await self.privateSpotPutOrderOrderId(self.extend(request, params))
4775
+ #
4776
+ # {
4777
+ # "rc": 0,
4778
+ # "mc": "SUCCESS",
4779
+ # "ma": [],
4780
+ # "result": {
4781
+ # "orderId": "484203027161892224",
4782
+ # "modifyId": "484203544105344000",
4783
+ # "clientModifyId": null
4784
+ # }
4785
+ # }
4786
+ #
4787
+ result = response if (market['swap']) else self.safe_dict(response, 'result', {})
4788
+ return self.parse_order(result, market)
4789
+
4682
4790
  def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
4683
4791
  #
4684
4792
  # spot: error
@@ -4776,6 +4884,8 @@ class xt(Exchange, ImplicitAPI):
4776
4884
  else:
4777
4885
  body['media'] = id
4778
4886
  isUndefinedBody = ((method == 'GET') or (path == 'order/{orderId}') or (path == 'ws-token'))
4887
+ if (method == 'PUT') and (endpoint == 'spot'):
4888
+ isUndefinedBody = False
4779
4889
  body = None if isUndefinedBody else self.json(body)
4780
4890
  payloadString = None
4781
4891
  if (endpoint == 'spot') or (endpoint == 'user'):
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.75'
7
+ __version__ = '4.4.78'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -67,6 +67,10 @@ from ccxt.static_dependencies.starknet.hash.address import compute_address
67
67
  from ccxt.static_dependencies.starknet.hash.selector import get_selector_from_name
68
68
  from ccxt.static_dependencies.starknet.hash.utils import message_signature, private_to_stark_key
69
69
  from ccxt.static_dependencies.starknet.utils.typed_data import TypedData as TypedDataDataclass
70
+ try:
71
+ import apexpro.zklink_sdk as zklink_sdk
72
+ except ImportError:
73
+ zklink_sdk = None
70
74
 
71
75
  # -----------------------------------------------------------------------------
72
76
 
@@ -509,7 +513,7 @@ class Exchange(object):
509
513
  proxyUrl = self.check_proxy_url_settings(url, method, headers, body)
510
514
  if proxyUrl is not None:
511
515
  request_headers.update({'Origin': self.origin})
512
- url = proxyUrl + url
516
+ url = proxyUrl + self.url_encoder_for_proxy_url(url)
513
517
  # proxy agents
514
518
  proxies = None # set default
515
519
  httpProxy, httpsProxy, socksProxy = self.check_proxy_settings(url, method, headers, body)
@@ -1755,6 +1759,69 @@ class Exchange(object):
1755
1759
  def binary_length(self, binary):
1756
1760
  return len(binary)
1757
1761
 
1762
+ def get_zk_contract_signature_obj(self, seeds: str, params={}):
1763
+ if zklink_sdk is None:
1764
+ raise Exception('zklink_sdk is not installed, please do pip3 install apexomni-arm or apexomni-x86-mac or apexomni-x86-windows-linux')
1765
+
1766
+ slotId = self.safe_string(params, 'slotId')
1767
+ nonceInt = int(self.remove0x_prefix(self.hash(self.encode(slotId), 'sha256', 'hex')), 16)
1768
+
1769
+ maxUint64 = 18446744073709551615
1770
+ maxUint32 = 4294967295
1771
+
1772
+ slotId = (nonceInt % maxUint64) / maxUint32
1773
+ nonce = nonceInt % maxUint32
1774
+ accountId = int(self.safe_string(params, 'accountId'), 10) % maxUint32
1775
+
1776
+ priceStr = (Decimal(self.safe_string(params, 'price')) * Decimal(10) ** Decimal('18')).quantize(Decimal(0), rounding='ROUND_DOWN')
1777
+ sizeStr = (Decimal(self.safe_string(params, 'size')) * Decimal(10) ** Decimal('18')).quantize(Decimal(0), rounding='ROUND_DOWN')
1778
+
1779
+ takerFeeRateStr = (Decimal(self.safe_string(params, 'takerFeeRate')) * Decimal(10000)).quantize(Decimal(0), rounding='ROUND_UP')
1780
+ makerFeeRateStr = (Decimal(self.safe_string(params, 'makerFeeRate')) * Decimal(10000)).quantize(Decimal(0), rounding='ROUND_UP')
1781
+
1782
+ builder = zklink_sdk.ContractBuilder(
1783
+ int(accountId), int(0), int(slotId), int(nonce), int(self.safe_number(params, 'pairId')),
1784
+ sizeStr.__str__(), priceStr.__str__(), self.safe_string(params, 'direction') == "BUY",
1785
+ int(takerFeeRateStr), int(makerFeeRateStr), False)
1786
+
1787
+
1788
+ tx = zklink_sdk.Contract(builder)
1789
+ seedsByte = bytes.fromhex(seeds.removeprefix('0x'))
1790
+ signerSeed = zklink_sdk.ZkLinkSigner().new_from_seed(seedsByte)
1791
+ auth_data = signerSeed.sign_musig(tx.get_bytes())
1792
+ signature = auth_data.signature
1793
+ return signature
1794
+
1795
+ def get_zk_transfer_signature_obj(self, seeds: str, params={}):
1796
+ if zklink_sdk is None:
1797
+ raise Exception('zklink_sdk is not installed, please do pip3 install apexomni-arm or apexomni-x86-mac or apexomni-x86-windows-linux')
1798
+
1799
+ nonce = self.safe_string(params, 'nonce', '0')
1800
+ if self.safe_bool(params, 'isContract'):
1801
+ formattedUint32 = '4294967295'
1802
+ formattedNonce = int(self.remove0x_prefix(self.hash(self.encode(nonce), 'sha256', 'hex')), 16)
1803
+ nonce = Precise.string_mod(str(formattedNonce), formattedUint32)
1804
+
1805
+ tx_builder = zklink_sdk.TransferBuilder(
1806
+ int(self.safe_number(params, 'zkAccountId', 0)),
1807
+ self.safe_string(params, 'receiverAddress'),
1808
+ int(self.safe_number(params, 'subAccountId', 0)),
1809
+ int(self.safe_number(params, 'receiverSubAccountId', 0)),
1810
+ int(self.safe_number(params, 'tokenId', 0)),
1811
+ self.safe_string(params, 'amount', '0'),
1812
+ self.safe_string(params, 'fee', '0'),
1813
+ self.parse_to_int(nonce),
1814
+ int(self.safe_number(params, 'timestampSeconds', 0))
1815
+ )
1816
+
1817
+ tx = zklink_sdk.Transfer(tx_builder)
1818
+ seedsByte = bytes.fromhex(seeds.removeprefix('0x'))
1819
+ signerSeed = zklink_sdk.ZkLinkSigner().new_from_seed(seedsByte)
1820
+ auth_data = signerSeed.sign_musig(tx.get_bytes())
1821
+ signature = auth_data.signature
1822
+ return signature
1823
+
1824
+
1758
1825
  # ########################################################################
1759
1826
  # ########################################################################
1760
1827
  # ########################################################################
@@ -2254,6 +2321,12 @@ class Exchange(object):
2254
2321
  raise InvalidProxySettings(self.id + ' you have multiple conflicting proxy settings(' + joinedProxyNames + '), please use only one from : proxyUrl, proxy_url, proxyUrlCallback, proxy_url_callback')
2255
2322
  return proxyUrl
2256
2323
 
2324
+ def url_encoder_for_proxy_url(self, targetUrl: str):
2325
+ # to be overriden
2326
+ includesQuery = targetUrl.find('?') >= 0
2327
+ finalUrl = self.encode_uri_component(targetUrl) if includesQuery else targetUrl
2328
+ return finalUrl
2329
+
2257
2330
  def check_proxy_settings(self, url: Str = None, method: Str = None, headers=None, body=None):
2258
2331
  usedProxies = []
2259
2332
  httpProxy = None
@@ -2947,7 +3020,7 @@ class Exchange(object):
2947
3020
  # find lowest precision(which is more desired)
2948
3021
  precision = self.safe_string(network, 'precision')
2949
3022
  precisionMain = self.safe_string(currency, 'precision')
2950
- if precisionMain is None or Precise.string_lt(precision, precisionMain):
3023
+ if precisionMain is None or Precise.string_gt(precision, precisionMain):
2951
3024
  currency['precision'] = self.parse_number(precision)
2952
3025
  # limits
2953
3026
  limits = self.safe_dict(network, 'limits')
ccxt/binance.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.binance import ImplicitAPI
8
8
  import hashlib
9
9
  import json
10
- from ccxt.base.types import Any, Balances, BorrowInterest, Conversion, CrossBorrowRate, Currencies, Currency, DepositAddress, Greeks, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, Leverage, Leverages, LeverageTier, LeverageTiers, LongShortRatio, MarginMode, MarginModes, MarginModification, Market, Num, Option, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, MarketInterface, TransferEntry
10
+ from ccxt.base.types import Any, Balances, BorrowInterest, Conversion, CrossBorrowRate, Currencies, Currency, DepositAddress, Greeks, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, Leverage, Leverages, LeverageTier, LeverageTiers, LongShortRatio, MarginMode, MarginModes, MarginModification, Market, Num, Option, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, MarketInterface, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -43,7 +43,7 @@ class binance(Exchange, ImplicitAPI):
43
43
  return self.deep_extend(super(binance, self).describe(), {
44
44
  'id': 'binance',
45
45
  'name': 'Binance',
46
- 'countries': ['JP', 'MT'], # Japan, Malta
46
+ 'countries': [], # Japan
47
47
  'rateLimit': 50,
48
48
  'certified': True,
49
49
  'pro': True,
@@ -1356,195 +1356,8 @@ class binance(Exchange, ImplicitAPI):
1356
1356
  'SPL': 'SOL', # temporarily keep support for SPL(old name)
1357
1357
  'SOL': 'SOL', # we shouldn't rename SOL
1358
1358
  },
1359
- # keeping self object for backward-compatibility
1360
- 'reverseNetworks': {
1361
- 'tronscan.org': 'TRC20',
1362
- 'etherscan.io': 'ERC20',
1363
- 'bscscan.com': 'BSC',
1364
- 'explorer.binance.org': 'BEP2',
1365
- 'bithomp.com': 'XRP',
1366
- 'bloks.io': 'EOS',
1367
- 'stellar.expert': 'XLM',
1368
- 'blockchair.com/bitcoin': 'BTC',
1369
- 'blockchair.com/bitcoin-cash': 'BCH',
1370
- 'blockchair.com/ecash': 'XEC',
1371
- 'explorer.litecoin.net': 'LTC',
1372
- 'explorer.avax.network': 'AVAX',
1373
- 'solscan.io': 'SOL',
1374
- 'polkadot.subscan.io': 'DOT',
1375
- 'dashboard.internetcomputer.org': 'ICP',
1376
- 'explorer.chiliz.com': 'CHZ',
1377
- 'cardanoscan.io': 'ADA',
1378
- 'mainnet.theoan.com': 'AION',
1379
- 'algoexplorer.io': 'ALGO',
1380
- 'explorer.ambrosus.com': 'AMB',
1381
- 'viewblock.io/zilliqa': 'ZIL',
1382
- 'viewblock.io/arweave': 'AR',
1383
- 'explorer.ark.io': 'ARK',
1384
- 'atomscan.com': 'ATOM',
1385
- 'www.mintscan.io': 'CTK',
1386
- 'explorer.bitcoindiamond.org': 'BCD',
1387
- 'btgexplorer.com': 'BTG',
1388
- 'bts.ai': 'BTS',
1389
- 'explorer.celo.org': 'CELO',
1390
- 'explorer.nervos.org': 'CKB',
1391
- 'cerebro.cortexlabs.ai': 'CTXC',
1392
- 'chainz.cryptoid.info': 'VIA',
1393
- 'explorer.dcrdata.org': 'DCR',
1394
- 'digiexplorer.info': 'DGB',
1395
- 'dock.subscan.io': 'DOCK',
1396
- 'dogechain.info': 'DOGE',
1397
- 'explorer.elrond.com': 'EGLD',
1398
- 'blockscout.com': 'ETC',
1399
- 'explore-fetchhub.fetch.ai': 'FET',
1400
- 'filfox.info': 'FIL',
1401
- 'fio.bloks.io': 'FIO',
1402
- 'explorer.firo.org': 'FIRO',
1403
- 'neoscan.io': 'NEO',
1404
- 'ftmscan.com': 'FTM',
1405
- 'explorer.gochain.io': 'GO',
1406
- 'block.gxb.io': 'GXS',
1407
- 'hash-hash.info': 'HBAR',
1408
- 'www.hiveblockexplorer.com': 'HIVE',
1409
- 'explorer.helium.com': 'HNT',
1410
- 'tracker.icon.foundation': 'ICX',
1411
- 'www.iostabc.com': 'IOST',
1412
- 'explorer.iota.org': 'IOTA',
1413
- 'iotexscan.io': 'IOTX',
1414
- 'irishub.iobscan.io': 'IRIS',
1415
- 'kava.mintscan.io': 'KAVA',
1416
- 'scope.klaytn.com': 'KLAY',
1417
- 'kmdexplorer.io': 'KMD',
1418
- 'kusama.subscan.io': 'KSM',
1419
- 'explorer.lto.network': 'LTO',
1420
- 'polygonscan.com': 'POLYGON',
1421
- 'explorer.ont.io': 'ONT',
1422
- 'minaexplorer.com': 'MINA',
1423
- 'nanolooker.com': 'NANO',
1424
- 'explorer.nebulas.io': 'NAS',
1425
- 'explorer.nbs.plus': 'NBS',
1426
- 'explorer.nebl.io': 'NEBL',
1427
- 'nulscan.io': 'NULS',
1428
- 'nxscan.com': 'NXS',
1429
- 'explorer.harmony.one': 'ONE',
1430
- 'explorer.poa.network': 'POA',
1431
- 'qtum.info': 'QTUM',
1432
- 'explorer.rsk.co': 'RSK',
1433
- 'www.oasisscan.com': 'ROSE',
1434
- 'ravencoin.network': 'RVN',
1435
- 'sc.tokenview.com': 'SC',
1436
- 'secretnodes.com': 'SCRT',
1437
- 'explorer.skycoin.com': 'SKY',
1438
- 'steemscan.com': 'STEEM',
1439
- 'explorer.stacks.co': 'STX',
1440
- 'www.thetascan.io': 'THETA',
1441
- 'scan.tomochain.com': 'TOMO',
1442
- 'explore.vechain.org': 'VET',
1443
- 'explorer.vite.net': 'VITE',
1444
- 'www.wanscan.org': 'WAN',
1445
- 'wavesexplorer.com': 'WAVES',
1446
- 'wax.eosx.io': 'WAXP',
1447
- 'waltonchain.pro': 'WTC',
1448
- 'chain.nem.ninja': 'XEM',
1449
- 'verge-blockchain.info': 'XVG',
1450
- 'explorer.yoyow.org': 'YOYOW',
1451
- 'explorer.zcha.in': 'ZEC',
1452
- 'explorer.zensystem.io': 'ZEN',
1453
- },
1454
1359
  'networksById': {
1455
1360
  'SOL': 'SOL', # temporary fix for SPL definition
1456
- 'tronscan.org': 'TRC20',
1457
- 'etherscan.io': 'ERC20',
1458
- 'bscscan.com': 'BSC',
1459
- 'explorer.binance.org': 'BEP2',
1460
- 'bithomp.com': 'XRP',
1461
- 'bloks.io': 'EOS',
1462
- 'stellar.expert': 'XLM',
1463
- 'blockchair.com/bitcoin': 'BTC',
1464
- 'blockchair.com/bitcoin-cash': 'BCH',
1465
- 'blockchair.com/ecash': 'XEC',
1466
- 'explorer.litecoin.net': 'LTC',
1467
- 'explorer.avax.network': 'AVAX',
1468
- 'solscan.io': 'SOL',
1469
- 'polkadot.subscan.io': 'DOT',
1470
- 'dashboard.internetcomputer.org': 'ICP',
1471
- 'explorer.chiliz.com': 'CHZ',
1472
- 'cardanoscan.io': 'ADA',
1473
- 'mainnet.theoan.com': 'AION',
1474
- 'algoexplorer.io': 'ALGO',
1475
- 'explorer.ambrosus.com': 'AMB',
1476
- 'viewblock.io/zilliqa': 'ZIL',
1477
- 'viewblock.io/arweave': 'AR',
1478
- 'explorer.ark.io': 'ARK',
1479
- 'atomscan.com': 'ATOM',
1480
- 'www.mintscan.io': 'CTK',
1481
- 'explorer.bitcoindiamond.org': 'BCD',
1482
- 'btgexplorer.com': 'BTG',
1483
- 'bts.ai': 'BTS',
1484
- 'explorer.celo.org': 'CELO',
1485
- 'explorer.nervos.org': 'CKB',
1486
- 'cerebro.cortexlabs.ai': 'CTXC',
1487
- 'chainz.cryptoid.info': 'VIA',
1488
- 'explorer.dcrdata.org': 'DCR',
1489
- 'digiexplorer.info': 'DGB',
1490
- 'dock.subscan.io': 'DOCK',
1491
- 'dogechain.info': 'DOGE',
1492
- 'explorer.elrond.com': 'EGLD',
1493
- 'blockscout.com': 'ETC',
1494
- 'explore-fetchhub.fetch.ai': 'FET',
1495
- 'filfox.info': 'FIL',
1496
- 'fio.bloks.io': 'FIO',
1497
- 'explorer.firo.org': 'FIRO',
1498
- 'neoscan.io': 'NEO',
1499
- 'ftmscan.com': 'FTM',
1500
- 'explorer.gochain.io': 'GO',
1501
- 'block.gxb.io': 'GXS',
1502
- 'hash-hash.info': 'HBAR',
1503
- 'www.hiveblockexplorer.com': 'HIVE',
1504
- 'explorer.helium.com': 'HNT',
1505
- 'tracker.icon.foundation': 'ICX',
1506
- 'www.iostabc.com': 'IOST',
1507
- 'explorer.iota.org': 'IOTA',
1508
- 'iotexscan.io': 'IOTX',
1509
- 'irishub.iobscan.io': 'IRIS',
1510
- 'kava.mintscan.io': 'KAVA',
1511
- 'scope.klaytn.com': 'KLAY',
1512
- 'kmdexplorer.io': 'KMD',
1513
- 'kusama.subscan.io': 'KSM',
1514
- 'explorer.lto.network': 'LTO',
1515
- 'polygonscan.com': 'POLYGON',
1516
- 'explorer.ont.io': 'ONT',
1517
- 'minaexplorer.com': 'MINA',
1518
- 'nanolooker.com': 'NANO',
1519
- 'explorer.nebulas.io': 'NAS',
1520
- 'explorer.nbs.plus': 'NBS',
1521
- 'explorer.nebl.io': 'NEBL',
1522
- 'nulscan.io': 'NULS',
1523
- 'nxscan.com': 'NXS',
1524
- 'explorer.harmony.one': 'ONE',
1525
- 'explorer.poa.network': 'POA',
1526
- 'qtum.info': 'QTUM',
1527
- 'explorer.rsk.co': 'RSK',
1528
- 'www.oasisscan.com': 'ROSE',
1529
- 'ravencoin.network': 'RVN',
1530
- 'sc.tokenview.com': 'SC',
1531
- 'secretnodes.com': 'SCRT',
1532
- 'explorer.skycoin.com': 'SKY',
1533
- 'steemscan.com': 'STEEM',
1534
- 'explorer.stacks.co': 'STX',
1535
- 'www.thetascan.io': 'THETA',
1536
- 'scan.tomochain.com': 'TOMO',
1537
- 'explore.vechain.org': 'VET',
1538
- 'explorer.vite.net': 'VITE',
1539
- 'www.wanscan.org': 'WAN',
1540
- 'wavesexplorer.com': 'WAVES',
1541
- 'wax.eosx.io': 'WAXP',
1542
- 'waltonchain.pro': 'WTC',
1543
- 'chain.nem.ninja': 'XEM',
1544
- 'verge-blockchain.info': 'XVG',
1545
- 'explorer.yoyow.org': 'YOYOW',
1546
- 'explorer.zcha.in': 'ZEC',
1547
- 'explorer.zensystem.io': 'ZEN',
1548
1361
  },
1549
1362
  'impliedNetworks': {
1550
1363
  'ETH': {'ERC20': 'ETH'},
@@ -8706,39 +8519,19 @@ class binance(Exchange, ImplicitAPI):
8706
8519
  def parse_deposit_address(self, response, currency: Currency = None) -> DepositAddress:
8707
8520
  #
8708
8521
  # {
8709
- # "currency": "XRP",
8522
+ # "coin": "XRP",
8710
8523
  # "address": "rEb8TK3gBgk5auZkwc6sHnwrGVJH8DuaLh",
8711
8524
  # "tag": "108618262",
8712
- # "info": {
8713
- # "coin": "XRP",
8714
- # "address": "rEb8TK3gBgk5auZkwc6sHnwrGVJH8DuaLh",
8715
- # "tag": "108618262",
8716
- # "url": "https://bithomp.com/explorer/rEb8TK3gBgk5auZkwc6sHnwrGVJH8DuaLh"
8717
- # }
8525
+ # "url": "https://bithomp.com/explorer/rEb8TK3gBgk5auZkwc6sHnwrGVJH8DuaLh"
8718
8526
  # }
8719
8527
  #
8720
- info = self.safe_dict(response, 'info', {})
8721
- url = self.safe_string(info, 'url')
8528
+ url = self.safe_string(response, 'url')
8722
8529
  address = self.safe_string(response, 'address')
8723
8530
  currencyId = self.safe_string(response, 'currency')
8724
8531
  code = self.safe_currency_code(currencyId, currency)
8725
- impliedNetwork = None
8726
- if url is not None:
8727
- reverseNetworks = self.safe_dict(self.options, 'reverseNetworks', {})
8728
- parts = url.split('/')
8729
- topLevel = self.safe_string(parts, 2)
8730
- if (topLevel == 'blockchair.com') or (topLevel == 'viewblock.io'):
8731
- subLevel = self.safe_string(parts, 3)
8732
- if subLevel is not None:
8733
- topLevel = topLevel + '/' + subLevel
8734
- impliedNetwork = self.safe_string(reverseNetworks, topLevel)
8735
- impliedNetworks = self.safe_dict(self.options, 'impliedNetworks', {
8736
- 'ETH': {'ERC20': 'ETH'},
8737
- 'TRX': {'TRC20': 'TRX'},
8738
- })
8739
- if code in impliedNetworks:
8740
- conversion = self.safe_dict(impliedNetworks, code, {})
8741
- impliedNetwork = self.safe_string(conversion, impliedNetwork, impliedNetwork)
8532
+ # deposit-address endpoint provides only network url(not network ID/CODE)
8533
+ # so we should map the url to network(their data is inside currencies)
8534
+ networkCode = self.get_network_code_by_network_url(code, url)
8742
8535
  tag = self.safe_string(response, 'tag', '')
8743
8536
  if len(tag) == 0:
8744
8537
  tag = None
@@ -8746,7 +8539,7 @@ class binance(Exchange, ImplicitAPI):
8746
8539
  return {
8747
8540
  'info': response,
8748
8541
  'currency': code,
8749
- 'network': impliedNetwork,
8542
+ 'network': networkCode,
8750
8543
  'address': address,
8751
8544
  'tag': tag,
8752
8545
  }
@@ -10317,7 +10110,7 @@ class binance(Exchange, ImplicitAPI):
10317
10110
  'percentage': None,
10318
10111
  })
10319
10112
 
10320
- def fetch_positions(self, symbols: Strings = None, params={}):
10113
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
10321
10114
  """
10322
10115
  fetch all open positions
10323
10116
 
@@ -11294,6 +11087,35 @@ class binance(Exchange, ImplicitAPI):
11294
11087
  }
11295
11088
  return self.safe_string(ledgerType, type, type)
11296
11089
 
11090
+ def get_network_code_by_network_url(self, currencyCode: str, depositUrl: Str = None) -> Str:
11091
+ # depositUrl is like : https://bscscan.com/address/0xEF238AB229342849..
11092
+ if depositUrl is None:
11093
+ return None
11094
+ networkCode = None
11095
+ currency = self.currency(currencyCode)
11096
+ networks = self.safe_dict(currency, 'networks', {})
11097
+ networkCodes = list(networks.keys())
11098
+ for i in range(0, len(networkCodes)):
11099
+ currentNetworkCode = networkCodes[i]
11100
+ info = self.safe_dict(networks[currentNetworkCode], 'info', {})
11101
+ siteUrl = self.safe_string(info, 'contractAddressUrl')
11102
+ # check if url matches the field's value
11103
+ if siteUrl is not None and depositUrl.startswith(self.get_base_domain_from_url(siteUrl)):
11104
+ networkCode = currentNetworkCode
11105
+ return networkCode
11106
+
11107
+ def get_base_domain_from_url(self, url: Str) -> Str:
11108
+ if url is None:
11109
+ return None
11110
+ urlParts = url.split('/')
11111
+ scheme = self.safe_string(urlParts, 0)
11112
+ if scheme is None:
11113
+ return None
11114
+ domain = self.safe_string(urlParts, 2)
11115
+ if domain is None:
11116
+ return None
11117
+ return scheme + '//' + domain + '/'
11118
+
11297
11119
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
11298
11120
  urls = self.urls
11299
11121
  if not (api in urls['api']):
ccxt/bingx.py CHANGED
@@ -2371,7 +2371,7 @@ class bingx(Exchange, ImplicitAPI):
2371
2371
  positions = self.parse_positions(records)
2372
2372
  return self.filter_by_symbol_since_limit(positions, symbol, since, limit)
2373
2373
 
2374
- def fetch_positions(self, symbols: Strings = None, params={}):
2374
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2375
2375
  """
2376
2376
  fetch all open positions
2377
2377