ccxt 4.2.58__py2.py3-none-any.whl → 4.2.60__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ccxt might be problematic. Click here for more details.

Files changed (68) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/blofin.py +1 -0
  3. ccxt/abstract/kraken.py +37 -37
  4. ccxt/abstract/wazirx.py +6 -1
  5. ccxt/ascendex.py +10 -12
  6. ccxt/async_support/__init__.py +1 -1
  7. ccxt/async_support/ascendex.py +10 -12
  8. ccxt/async_support/base/exchange.py +1 -1
  9. ccxt/async_support/binance.py +2 -2
  10. ccxt/async_support/bingx.py +40 -4
  11. ccxt/async_support/bitfinex2.py +20 -3
  12. ccxt/async_support/bitget.py +8 -3
  13. ccxt/async_support/bitmart.py +40 -23
  14. ccxt/async_support/bitmex.py +1 -1
  15. ccxt/async_support/blofin.py +53 -3
  16. ccxt/async_support/coinbase.py +21 -12
  17. ccxt/async_support/hitbtc.py +1 -1
  18. ccxt/async_support/htx.py +3 -1
  19. ccxt/async_support/kraken.py +42 -39
  20. ccxt/async_support/kucoinfutures.py +1 -0
  21. ccxt/async_support/lbank.py +1 -1
  22. ccxt/async_support/mexc.py +1 -1
  23. ccxt/async_support/okx.py +1 -1
  24. ccxt/async_support/phemex.py +1 -1
  25. ccxt/async_support/wazirx.py +6 -1
  26. ccxt/async_support/woo.py +148 -76
  27. ccxt/base/exchange.py +3 -1
  28. ccxt/binance.py +2 -2
  29. ccxt/bingx.py +40 -4
  30. ccxt/bitfinex2.py +20 -3
  31. ccxt/bitget.py +8 -3
  32. ccxt/bitmart.py +40 -23
  33. ccxt/bitmex.py +1 -1
  34. ccxt/blofin.py +53 -3
  35. ccxt/coinbase.py +21 -12
  36. ccxt/hitbtc.py +1 -1
  37. ccxt/htx.py +3 -1
  38. ccxt/kraken.py +42 -39
  39. ccxt/kucoinfutures.py +1 -0
  40. ccxt/lbank.py +1 -1
  41. ccxt/mexc.py +1 -1
  42. ccxt/okx.py +1 -1
  43. ccxt/phemex.py +1 -1
  44. ccxt/pro/__init__.py +1 -1
  45. ccxt/pro/binance.py +12 -3
  46. ccxt/pro/bitfinex2.py +1 -1
  47. ccxt/pro/bitget.py +1 -1
  48. ccxt/pro/bitmart.py +44 -78
  49. ccxt/pro/bitvavo.py +1 -1
  50. ccxt/pro/bybit.py +1 -1
  51. ccxt/pro/coinex.py +1 -1
  52. ccxt/pro/cryptocom.py +1 -1
  53. ccxt/pro/deribit.py +188 -84
  54. ccxt/pro/gate.py +1 -1
  55. ccxt/pro/independentreserve.py +1 -1
  56. ccxt/pro/kraken.py +1 -1
  57. ccxt/pro/kucoinfutures.py +1 -1
  58. ccxt/pro/mexc.py +5 -4
  59. ccxt/pro/okx.py +1 -1
  60. ccxt/pro/woo.py +1 -1
  61. ccxt/test/test_async.py +4 -4
  62. ccxt/test/test_sync.py +4 -4
  63. ccxt/wazirx.py +6 -1
  64. ccxt/woo.py +148 -76
  65. {ccxt-4.2.58.dist-info → ccxt-4.2.60.dist-info}/METADATA +4 -4
  66. {ccxt-4.2.58.dist-info → ccxt-4.2.60.dist-info}/RECORD +68 -68
  67. {ccxt-4.2.58.dist-info → ccxt-4.2.60.dist-info}/WHEEL +0 -0
  68. {ccxt-4.2.58.dist-info → ccxt-4.2.60.dist-info}/top_level.txt +0 -0
ccxt/async_support/woo.py CHANGED
@@ -93,10 +93,10 @@ class woo(Exchange, ImplicitAPI):
93
93
  'fetchPositionMode': False,
94
94
  'fetchPositions': True,
95
95
  'fetchPremiumIndexOHLCV': False,
96
- 'fetchStatus': False,
96
+ 'fetchStatus': True,
97
97
  'fetchTicker': False,
98
98
  'fetchTickers': False,
99
- 'fetchTime': False,
99
+ 'fetchTime': True,
100
100
  'fetchTrades': True,
101
101
  'fetchTradingFee': False,
102
102
  'fetchTradingFees': True,
@@ -333,6 +333,60 @@ class woo(Exchange, ImplicitAPI):
333
333
  'precisionMode': TICK_SIZE,
334
334
  })
335
335
 
336
+ async def fetch_status(self, params={}):
337
+ """
338
+ the latest known information on the availability of the exchange API
339
+ :see: https://docs.woo.org/#get-system-maintenance-status-public
340
+ :param dict [params]: extra parameters specific to the exchange API endpoint
341
+ :returns dict: a `status structure <https://docs.ccxt.com/#/?id=exchange-status-structure>`
342
+ """
343
+ response = await self.v1PublicGetSystemInfo(params)
344
+ #
345
+ # {
346
+ # "success": True,
347
+ # "data": {
348
+ # "status": "0",
349
+ # "msg": "System is functioning properly."
350
+ # },
351
+ # "timestamp": "1709274106602"
352
+ # }
353
+ #
354
+ data = self.safe_dict(response, 'data', {})
355
+ status = self.safe_string(data, 'status')
356
+ if status is None:
357
+ status = 'error'
358
+ elif status == '0':
359
+ status = 'ok'
360
+ else:
361
+ status = 'maintenance'
362
+ return {
363
+ 'status': status,
364
+ 'updated': None,
365
+ 'eta': None,
366
+ 'url': None,
367
+ 'info': response,
368
+ }
369
+
370
+ async def fetch_time(self, params={}):
371
+ """
372
+ fetches the current integer timestamp in milliseconds from the exchange server
373
+ :see: https://docs.woo.org/#get-system-maintenance-status-public
374
+ :param dict [params]: extra parameters specific to the exchange API endpoint
375
+ :returns int: the current integer timestamp in milliseconds from the exchange server
376
+ """
377
+ response = await self.v1PublicGetSystemInfo(params)
378
+ #
379
+ # {
380
+ # "success": True,
381
+ # "data": {
382
+ # "status": "0",
383
+ # "msg": "System is functioning properly."
384
+ # },
385
+ # "timestamp": "1709274106602"
386
+ # }
387
+ #
388
+ return self.safe_integer(response, 'timestamp')
389
+
336
390
  async def fetch_markets(self, params={}):
337
391
  """
338
392
  retrieves data on all markets for woo
@@ -361,7 +415,7 @@ class woo(Exchange, ImplicitAPI):
361
415
  # "success": True
362
416
  # }
363
417
  #
364
- data = self.safe_value(response, 'rows', [])
418
+ data = self.safe_list(response, 'rows', [])
365
419
  return self.parse_markets(data)
366
420
 
367
421
  def parse_market(self, market) -> Market:
@@ -491,7 +545,7 @@ class woo(Exchange, ImplicitAPI):
491
545
  # ]
492
546
  # }
493
547
  #
494
- resultResponse = self.safe_value(response, 'rows', {})
548
+ resultResponse = self.safe_list(response, 'rows', [])
495
549
  return self.parse_trades(resultResponse, market, since, limit)
496
550
 
497
551
  def parse_trade(self, trade, market: Market = None) -> Trade:
@@ -603,7 +657,7 @@ class woo(Exchange, ImplicitAPI):
603
657
  # "timestamp": 1673323685109
604
658
  # }
605
659
  #
606
- data = self.safe_value(response, 'data', {})
660
+ data = self.safe_dict(response, 'data', {})
607
661
  maker = self.safe_string(data, 'makerFeeRate')
608
662
  taker = self.safe_string(data, 'takerFeeRate')
609
663
  result = {}
@@ -687,7 +741,7 @@ class woo(Exchange, ImplicitAPI):
687
741
  # "success": True
688
742
  # }
689
743
  #
690
- tokenRows = self.safe_value(tokenResponse, 'rows', [])
744
+ tokenRows = self.safe_list(tokenResponse, 'rows', [])
691
745
  networksByCurrencyId = self.group_by(tokenRows, 'balance_token')
692
746
  currencyIds = list(networksByCurrencyId.keys())
693
747
  for i in range(0, len(currencyIds)):
@@ -831,7 +885,7 @@ class woo(Exchange, ImplicitAPI):
831
885
  :param str [params.trailingTriggerPrice]: the price to trigger a trailing order, default uses the price argument
832
886
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
833
887
  """
834
- reduceOnly = self.safe_value_2(params, 'reduceOnly', 'reduce_only')
888
+ reduceOnly = self.safe_bool_2(params, 'reduceOnly', 'reduce_only')
835
889
  params = self.omit(params, ['reduceOnly', 'reduce_only'])
836
890
  orderType = type.upper()
837
891
  await self.load_markets()
@@ -975,9 +1029,9 @@ class woo(Exchange, ImplicitAPI):
975
1029
  # },
976
1030
  # "timestamp": "1686149372216"
977
1031
  # }
978
- data = self.safe_value(response, 'data')
1032
+ data = self.safe_dict(response, 'data')
979
1033
  if data is not None:
980
- rows = self.safe_value(data, 'rows', [])
1034
+ rows = self.safe_list(data, 'rows', [])
981
1035
  return self.parse_order(rows[0], market)
982
1036
  order = self.parse_order(response, market)
983
1037
  order['type'] = type
@@ -1062,7 +1116,7 @@ class woo(Exchange, ImplicitAPI):
1062
1116
  # "timestamp": 0
1063
1117
  # }
1064
1118
  #
1065
- data = self.safe_value(response, 'data', {})
1119
+ data = self.safe_dict(response, 'data', {})
1066
1120
  return self.parse_order(data, market)
1067
1121
 
1068
1122
  async def cancel_order(self, id: str, symbol: Str = None, params={}):
@@ -1124,8 +1178,8 @@ class woo(Exchange, ImplicitAPI):
1124
1178
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1125
1179
  """
1126
1180
  await self.load_markets()
1127
- stop = self.safe_value(params, 'stop')
1128
- params = self.omit(params, 'stop')
1181
+ stop = self.safe_bool_2(params, 'stop', 'trigger')
1182
+ params = self.omit(params, ['stop', 'trigger'])
1129
1183
  if stop:
1130
1184
  return await self.v3PrivateDeleteAlgoOrdersPending(params)
1131
1185
  if symbol is None:
@@ -1155,8 +1209,8 @@ class woo(Exchange, ImplicitAPI):
1155
1209
  """
1156
1210
  await self.load_markets()
1157
1211
  market = self.market(symbol) if (symbol is not None) else None
1158
- stop = self.safe_value(params, 'stop')
1159
- params = self.omit(params, 'stop')
1212
+ stop = self.safe_bool_2(params, 'stop', 'trigger')
1213
+ params = self.omit(params, ['stop', 'trigger'])
1160
1214
  request = {}
1161
1215
  clientOrderId = self.safe_string_2(params, 'clOrdID', 'clientOrderId')
1162
1216
  response = None
@@ -1225,9 +1279,9 @@ class woo(Exchange, ImplicitAPI):
1225
1279
  await self.load_markets()
1226
1280
  request = {}
1227
1281
  market: Market = None
1228
- stop = self.safe_value(params, 'stop')
1282
+ stop = self.safe_bool_2(params, 'stop', 'trigger')
1229
1283
  trailing = self.safe_bool(params, 'trailing', False)
1230
- params = self.omit(params, ['stop', 'trailing'])
1284
+ params = self.omit(params, ['stop', 'trailing', 'trigger'])
1231
1285
  if symbol is not None:
1232
1286
  market = self.market(symbol)
1233
1287
  request['symbol'] = market['id']
@@ -1277,7 +1331,7 @@ class woo(Exchange, ImplicitAPI):
1277
1331
  # }
1278
1332
  #
1279
1333
  data = self.safe_value(response, 'data', response)
1280
- orders = self.safe_value(data, 'rows')
1334
+ orders = self.safe_list(data, 'rows')
1281
1335
  return self.parse_orders(orders, market, since, limit, params)
1282
1336
 
1283
1337
  def parse_time_in_force(self, timeInForce):
@@ -1377,7 +1431,7 @@ class woo(Exchange, ImplicitAPI):
1377
1431
  'type': orderType,
1378
1432
  'timeInForce': self.parse_time_in_force(orderType),
1379
1433
  'postOnly': None, # TO_DO
1380
- 'reduceOnly': self.safe_value(order, 'reduce_only'),
1434
+ 'reduceOnly': self.safe_bool(order, 'reduce_only'),
1381
1435
  'side': side,
1382
1436
  'price': price,
1383
1437
  'stopPrice': stopPrice,
@@ -1524,7 +1578,7 @@ class woo(Exchange, ImplicitAPI):
1524
1578
  # }
1525
1579
  # }
1526
1580
  #
1527
- rows = self.safe_value(response, 'rows', [])
1581
+ rows = self.safe_list(response, 'rows', [])
1528
1582
  return self.parse_ohlcvs(rows, market, timeframe, since, limit)
1529
1583
 
1530
1584
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
@@ -1574,7 +1628,7 @@ class woo(Exchange, ImplicitAPI):
1574
1628
  # }
1575
1629
  # ]
1576
1630
  # }
1577
- trades = self.safe_value(response, 'rows', [])
1631
+ trades = self.safe_list(response, 'rows', [])
1578
1632
  return self.parse_trades(trades, market, since, limit, params)
1579
1633
 
1580
1634
  async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
@@ -1618,7 +1672,7 @@ class woo(Exchange, ImplicitAPI):
1618
1672
  # ...
1619
1673
  # ]
1620
1674
  # }
1621
- trades = self.safe_value(response, 'rows', [])
1675
+ trades = self.safe_list(response, 'rows', [])
1622
1676
  return self.parse_trades(trades, market, since, limit, params)
1623
1677
 
1624
1678
  async def fetch_accounts(self, params={}):
@@ -1644,7 +1698,7 @@ class woo(Exchange, ImplicitAPI):
1644
1698
  # "success": True
1645
1699
  # }
1646
1700
  #
1647
- rows = self.safe_value(response, 'rows', [])
1701
+ rows = self.safe_list(response, 'rows', [])
1648
1702
  return self.parse_accounts(rows, params)
1649
1703
 
1650
1704
  def parse_account(self, account):
@@ -1696,14 +1750,14 @@ class woo(Exchange, ImplicitAPI):
1696
1750
  # "timestamp": 1673323746259
1697
1751
  # }
1698
1752
  #
1699
- data = self.safe_value(response, 'data')
1753
+ data = self.safe_dict(response, 'data')
1700
1754
  return self.parse_balance(data)
1701
1755
 
1702
1756
  def parse_balance(self, response) -> Balances:
1703
1757
  result = {
1704
1758
  'info': response,
1705
1759
  }
1706
- balances = self.safe_value(response, 'holding', [])
1760
+ balances = self.safe_list(response, 'holding', [])
1707
1761
  for i in range(0, len(balances)):
1708
1762
  balance = balances[i]
1709
1763
  code = self.safe_currency_code(self.safe_string(balance, 'token'))
@@ -1959,6 +2013,7 @@ class woo(Exchange, ImplicitAPI):
1959
2013
 
1960
2014
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
1961
2015
  """
2016
+ :see: https://docs.woo.org/#get-transfer-history
1962
2017
  transfer currency internally between wallets on the same account
1963
2018
  :param str code: unified currency code
1964
2019
  :param float amount: amount to transfer
@@ -1971,7 +2026,7 @@ class woo(Exchange, ImplicitAPI):
1971
2026
  currency = self.currency(code)
1972
2027
  request = {
1973
2028
  'token': currency['id'],
1974
- 'amount': self.parse_number(amount),
2029
+ 'amount': self.parse_to_numeric(amount),
1975
2030
  'from_application_id': fromAccount,
1976
2031
  'to_application_id': toAccount,
1977
2032
  }
@@ -1983,7 +2038,7 @@ class woo(Exchange, ImplicitAPI):
1983
2038
  # }
1984
2039
  #
1985
2040
  transfer = self.parse_transfer(response, currency)
1986
- transferOptions = self.safe_value(self.options, 'transfer', {})
2041
+ transferOptions = self.safe_dict(self.options, 'transfer', {})
1987
2042
  fillResponseFromRequest = self.safe_bool(transferOptions, 'fillResponseFromRequest', True)
1988
2043
  if fillResponseFromRequest:
1989
2044
  transfer['amount'] = amount
@@ -1994,41 +2049,68 @@ class woo(Exchange, ImplicitAPI):
1994
2049
  async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
1995
2050
  """
1996
2051
  fetch a history of internal transfers made on an account
2052
+ :see: https://docs.woo.org/#get-transfer-history
1997
2053
  :param str code: unified currency code of the currency transferred
1998
2054
  :param int [since]: the earliest time in ms to fetch transfers for
1999
2055
  :param int [limit]: the maximum number of transfers structures to retrieve
2000
2056
  :param dict [params]: extra parameters specific to the exchange API endpoint
2057
+ :param int [params.until]: the latest time in ms to fetch entries for
2001
2058
  :returns dict[]: a list of `transfer structures <https://docs.ccxt.com/#/?id=transfer-structure>`
2002
2059
  """
2003
- request = {
2004
- 'type': 'COLLATERAL',
2005
- }
2006
- currency, rows = await self.get_asset_history_rows(code, since, limit, self.extend(request, params))
2007
- return self.parse_transfers(rows, currency, since, limit, params)
2060
+ request = {}
2061
+ if limit is not None:
2062
+ request['size'] = limit
2063
+ if since is not None:
2064
+ request['start_t'] = since
2065
+ until = self.safe_integer_2(params, 'until', 'till') # unified in milliseconds
2066
+ params = self.omit(params, ['until', 'till'])
2067
+ if until is not None:
2068
+ request['end_t'] = until
2069
+ response = await self.v1PrivateGetAssetMainSubTransferHistory(self.extend(request, params))
2070
+ #
2071
+ # {
2072
+ # "rows": [
2073
+ # {
2074
+ # "id": 46704,
2075
+ # "token": "USDT",
2076
+ # "amount": 30000.00000000,
2077
+ # "status": "COMPLETED",
2078
+ # "from_application_id": "0f1bd3cd-dba2-4563-b8bb-0adb1bfb83a3",
2079
+ # "to_application_id": "c01e6940-a735-4022-9b6c-9d3971cdfdfa",
2080
+ # "from_user": "LeverageLow",
2081
+ # "to_user": "dev",
2082
+ # "created_time": "1709022325.427",
2083
+ # "updated_time": "1709022325.542"
2084
+ # }
2085
+ # ],
2086
+ # "meta": {
2087
+ # "total": 50,
2088
+ # "records_per_page": 25,
2089
+ # "current_page": 1
2090
+ # },
2091
+ # "success": True
2092
+ # }
2093
+ #
2094
+ data = self.safe_list(response, 'rows', [])
2095
+ return self.parse_transfers(data, None, since, limit, params)
2008
2096
 
2009
2097
  def parse_transfer(self, transfer, currency: Currency = None):
2010
2098
  #
2011
- # getAssetHistoryRows
2012
- # {
2013
- # "created_time": "1579399877.041", # Unix epoch time in seconds
2014
- # "updated_time": "1579399877.041", # Unix epoch time in seconds
2015
- # "id": "202029292829292",
2016
- # "external_id": "202029292829292",
2017
- # "application_id": null,
2018
- # "token": "ETH",
2019
- # "target_address": "0x31d64B3230f8baDD91dE1710A65DF536aF8f7cDa",
2020
- # "source_address": "0x70fd25717f769c7f9a46b319f0f9103c0d887af0",
2021
- # "extra": "",
2022
- # "type": "BALANCE",
2023
- # "token_side": "DEPOSIT",
2024
- # "amount": 1000,
2025
- # "tx_id": "0x8a74c517bc104c8ebad0c3c3f64b1f302ed5f8bca598ae4459c63419038106b6",
2026
- # "fee_token": null,
2027
- # "fee_amount": null,
2028
- # "status": "CONFIRMING"
2029
- # }
2099
+ # fetchTransfers
2100
+ # {
2101
+ # "id": 46704,
2102
+ # "token": "USDT",
2103
+ # "amount": 30000.00000000,
2104
+ # "status": "COMPLETED",
2105
+ # "from_application_id": "0f1bd3cd-dba2-4563-b8bb-0adb1bfb83a3",
2106
+ # "to_application_id": "c01e6940-a735-4022-9b6c-9d3971cdfdfa",
2107
+ # "from_user": "LeverageLow",
2108
+ # "to_user": "dev",
2109
+ # "created_time": "1709022325.427",
2110
+ # "updated_time": "1709022325.542"
2111
+ # }
2030
2112
  #
2031
- # v1PrivatePostAssetMainSubTransfer
2113
+ # transfer
2032
2114
  # {
2033
2115
  # "success": True,
2034
2116
  # "id": 200
@@ -2037,19 +2119,8 @@ class woo(Exchange, ImplicitAPI):
2037
2119
  networkizedCode = self.safe_string(transfer, 'token')
2038
2120
  currencyDefined = self.get_currency_from_chaincode(networkizedCode, currency)
2039
2121
  code = currencyDefined['code']
2040
- movementDirection = self.safe_string_lower(transfer, 'token_side')
2041
- if movementDirection == 'withdraw':
2042
- movementDirection = 'withdrawal'
2043
- fromAccount: Str = None
2044
- toAccount: Str = None
2045
- if movementDirection == 'withdraw':
2046
- fromAccount = None
2047
- toAccount = 'spot'
2048
- elif movementDirection == 'deposit':
2049
- fromAccount = 'spot'
2050
- toAccount = None
2051
2122
  timestamp = self.safe_timestamp(transfer, 'created_time')
2052
- success = self.safe_value(transfer, 'success')
2123
+ success = self.safe_bool(transfer, 'success')
2053
2124
  status: Str = None
2054
2125
  if success is not None:
2055
2126
  status = 'ok' if success else 'failed'
@@ -2059,8 +2130,8 @@ class woo(Exchange, ImplicitAPI):
2059
2130
  'datetime': self.iso8601(timestamp),
2060
2131
  'currency': code,
2061
2132
  'amount': self.safe_number(transfer, 'amount'),
2062
- 'fromAccount': fromAccount,
2063
- 'toAccount': toAccount,
2133
+ 'fromAccount': self.safe_string(transfer, 'from_application_id'),
2134
+ 'toAccount': self.safe_string(transfer, 'to_application_id'),
2064
2135
  'status': self.parse_transfer_status(self.safe_string(transfer, 'status', status)),
2065
2136
  'info': transfer,
2066
2137
  }
@@ -2095,11 +2166,11 @@ class woo(Exchange, ImplicitAPI):
2095
2166
  }
2096
2167
  if tag is not None:
2097
2168
  request['extra'] = tag
2098
- networks = self.safe_value(self.options, 'networks', {})
2099
- currencyNetworks = self.safe_value(currency, 'networks', {})
2169
+ networks = self.safe_dict(self.options, 'networks', {})
2170
+ currencyNetworks = self.safe_dict(currency, 'networks', {})
2100
2171
  network = self.safe_string_upper(params, 'network')
2101
2172
  networkId = self.safe_string(networks, network, network)
2102
- coinNetwork = self.safe_value(currencyNetworks, networkId, {})
2173
+ coinNetwork = self.safe_dict(currencyNetworks, networkId, {})
2103
2174
  coinNetworkId = self.safe_string(coinNetwork, 'id')
2104
2175
  if coinNetworkId is None:
2105
2176
  raise BadRequest(self.id + ' withdraw() require network parameter')
@@ -2179,7 +2250,7 @@ class woo(Exchange, ImplicitAPI):
2179
2250
  else:
2180
2251
  self.check_required_credentials()
2181
2252
  if method == 'POST' and (path == 'algo/order' or path == 'order'):
2182
- isSandboxMode = self.safe_value(self.options, 'sandboxMode', False)
2253
+ isSandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
2183
2254
  if not isSandboxMode:
2184
2255
  applicationId = 'bc830de7-50f3-460b-9ee0-f430f83f9dad'
2185
2256
  brokerId = self.safe_string(self.options, 'brokerId', applicationId)
@@ -2212,7 +2283,8 @@ class woo(Exchange, ImplicitAPI):
2212
2283
  if method == 'POST' or method == 'PUT' or method == 'DELETE':
2213
2284
  body = auth
2214
2285
  else:
2215
- url += '?' + auth
2286
+ if params:
2287
+ url += '?' + auth
2216
2288
  auth += '|' + ts
2217
2289
  headers['content-type'] = 'application/x-www-form-urlencoded'
2218
2290
  headers['x-api-signature'] = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256)
@@ -2225,7 +2297,7 @@ class woo(Exchange, ImplicitAPI):
2225
2297
  # 400 Bad Request {"success":false,"code":-1012,"message":"Amount is required for buy market orders when margin disabled."}
2226
2298
  # {"code":"-1011","message":"The system is under maintenance.","success":false}
2227
2299
  #
2228
- success = self.safe_value(response, 'success')
2300
+ success = self.safe_bool(response, 'success')
2229
2301
  errorCode = self.safe_string(response, 'code')
2230
2302
  if not success:
2231
2303
  feedback = self.id + ' ' + self.json(response)
@@ -2298,7 +2370,7 @@ class woo(Exchange, ImplicitAPI):
2298
2370
  # "success":true
2299
2371
  # }
2300
2372
  #
2301
- result = self.safe_value(response, 'rows', [])
2373
+ result = self.safe_list(response, 'rows', [])
2302
2374
  return self.parse_incomes(result, market, since, limit)
2303
2375
 
2304
2376
  def parse_funding_rate(self, fundingRate, market: Market = None):
@@ -2379,7 +2451,7 @@ class woo(Exchange, ImplicitAPI):
2379
2451
  # "timestamp":1653633985646
2380
2452
  # }
2381
2453
  #
2382
- rows = self.safe_value(response, 'rows', {})
2454
+ rows = self.safe_list(response, 'rows', [])
2383
2455
  result = self.parse_funding_rates(rows)
2384
2456
  return self.filter_by_array(result, 'symbol', symbols)
2385
2457
 
@@ -2428,7 +2500,7 @@ class woo(Exchange, ImplicitAPI):
2428
2500
  # "timestamp":1653640814885
2429
2501
  # }
2430
2502
  #
2431
- result = self.safe_value(response, 'rows')
2503
+ result = self.safe_list(response, 'rows')
2432
2504
  rates = []
2433
2505
  for i in range(0, len(result)):
2434
2506
  entry = result[i]
@@ -2582,8 +2654,8 @@ class woo(Exchange, ImplicitAPI):
2582
2654
  # "timestamp": 1673323880342
2583
2655
  # }
2584
2656
  #
2585
- result = self.safe_value(response, 'data', {})
2586
- positions = self.safe_value(result, 'positions', [])
2657
+ result = self.safe_dict(response, 'data', {})
2658
+ positions = self.safe_list(result, 'positions', [])
2587
2659
  return self.parse_positions(positions, symbols)
2588
2660
 
2589
2661
  def parse_position(self, position, market: Market = None):
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.58'
7
+ __version__ = '4.2.60'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -3825,6 +3825,8 @@ class Exchange(object):
3825
3825
  if value is not None:
3826
3826
  params = self.omit(params, [optionName, defaultOptionName])
3827
3827
  else:
3828
+ # handle routed methods like "watchTrades > watchTradesForSymbols"(or "watchTicker > watchTickers")
3829
+ methodName, params = self.handleParamString(params, 'callerMethodName', methodName)
3828
3830
  # check if exchange has properties for self method
3829
3831
  exchangeWideMethodOptions = self.safe_value(self.options, methodName)
3830
3832
  if exchangeWideMethodOptions is not None:
ccxt/binance.py CHANGED
@@ -4626,7 +4626,7 @@ class binance(Exchange, ImplicitAPI):
4626
4626
  stopPriceIsRequired = False
4627
4627
  quantityIsRequired = False
4628
4628
  if uppercaseType == 'MARKET':
4629
- quoteOrderQty = self.safe_value(self.options, 'quoteOrderQty', True)
4629
+ quoteOrderQty = self.safe_bool(self.options, 'quoteOrderQty', True)
4630
4630
  if quoteOrderQty:
4631
4631
  quoteOrderQtyNew = self.safe_value_2(params, 'quoteOrderQty', 'cost')
4632
4632
  precision = market['precision']['price']
@@ -9546,7 +9546,7 @@ class binance(Exchange, ImplicitAPI):
9546
9546
  # POST https://fapi.binance.com/fapi/v1/marginType 400 Bad Request
9547
9547
  # binanceusdm
9548
9548
  if isinstance(e, MarginModeAlreadySet):
9549
- throwMarginModeAlreadySet = self.safe_value(self.options, 'throwMarginModeAlreadySet', False)
9549
+ throwMarginModeAlreadySet = self.safe_bool(self.options, 'throwMarginModeAlreadySet', False)
9550
9550
  if throwMarginModeAlreadySet:
9551
9551
  raise e
9552
9552
  else:
ccxt/bingx.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bingx import ImplicitAPI
8
8
  import hashlib
9
9
  import numbers
10
- from ccxt.base.types import Balances, Currency, Int, Leverage, Market, Order, TransferEntry, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction
10
+ from ccxt.base.types import Balances, Currency, Int, Leverage, MarginMode, Market, Order, TransferEntry, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -72,6 +72,7 @@ class bingx(Exchange, ImplicitAPI):
72
72
  'fetchFundingRates': True,
73
73
  'fetchLeverage': True,
74
74
  'fetchLiquidations': False,
75
+ 'fetchMarginMode': True,
75
76
  'fetchMarkets': True,
76
77
  'fetchMarkOHLCV': True,
77
78
  'fetchMyLiquidations': True,
@@ -457,7 +458,7 @@ class bingx(Exchange, ImplicitAPI):
457
458
  """
458
459
  if not self.check_required_credentials(False):
459
460
  return None
460
- isSandbox = self.safe_value(self.options, 'sandboxMode', False)
461
+ isSandbox = self.safe_bool(self.options, 'sandboxMode', False)
461
462
  if isSandbox:
462
463
  return None
463
464
  response = self.walletsV1PrivateGetCapitalConfigGetall(params)
@@ -692,7 +693,7 @@ class bingx(Exchange, ImplicitAPI):
692
693
  :returns dict[]: an array of objects representing market data
693
694
  """
694
695
  requests = [self.fetch_swap_markets(params)]
695
- isSandbox = self.safe_value(self.options, 'sandboxMode', False)
696
+ isSandbox = self.safe_bool(self.options, 'sandboxMode', False)
696
697
  if not isSandbox:
697
698
  requests.append(self.fetch_spot_markets(params)) # sandbox is swap only
698
699
  promises = requests
@@ -3898,11 +3899,46 @@ class bingx(Exchange, ImplicitAPI):
3898
3899
  data = self.safe_dict(response, 'data')
3899
3900
  return self.parse_order(data, market)
3900
3901
 
3902
+ def fetch_margin_mode(self, symbol: str, params={}) -> MarginMode:
3903
+ """
3904
+ fetches the margin mode of the trading pair
3905
+ :see: https://bingx-api.github.io/docs/#/en-us/swapV2/trade-api.html#Query%20Margin%20Mode
3906
+ :param str symbol: unified symbol of the market to fetch the margin mode for
3907
+ :param dict [params]: extra parameters specific to the exchange API endpoint
3908
+ :returns dict: Struct of MarginMode
3909
+ """
3910
+ self.load_markets()
3911
+ market = self.market(symbol)
3912
+ request: dict = {
3913
+ 'symbol': market['id'],
3914
+ }
3915
+ response = self.swapV2PrivateGetTradeMarginType(self.extend(request, params))
3916
+ #
3917
+ # {
3918
+ # "code": 0,
3919
+ # "msg": "",
3920
+ # "data": {
3921
+ # "marginType": "CROSSED"
3922
+ # }
3923
+ # }
3924
+ #
3925
+ data = self.safe_dict(response, 'data', {})
3926
+ return self.parse_margin_mode(data, market)
3927
+
3928
+ def parse_margin_mode(self, marginMode, market=None) -> MarginMode:
3929
+ marginType = self.safe_string_lower(marginMode, 'marginType')
3930
+ marginType = 'cross' if (marginType == 'crossed') else marginType
3931
+ return {
3932
+ 'info': marginMode,
3933
+ 'symbol': market['symbol'],
3934
+ 'marginMode': marginType,
3935
+ }
3936
+
3901
3937
  def sign(self, path, section='public', method='GET', params={}, headers=None, body=None):
3902
3938
  type = section[0]
3903
3939
  version = section[1]
3904
3940
  access = section[2]
3905
- isSandbox = self.safe_value(self.options, 'sandboxMode', False)
3941
+ isSandbox = self.safe_bool(self.options, 'sandboxMode', False)
3906
3942
  if isSandbox and (type != 'swap'):
3907
3943
  raise NotSupported(self.id + ' does not have a testnet/sandbox URL for ' + type + ' endpoints')
3908
3944
  url = self.implode_hostname(self.urls['api'][type])
ccxt/bitfinex2.py CHANGED
@@ -46,8 +46,8 @@ class bitfinex2(Exchange, ImplicitAPI):
46
46
  'spot': True,
47
47
  'margin': True,
48
48
  'swap': True,
49
- 'future': None,
50
- 'option': None,
49
+ 'future': False,
50
+ 'option': False,
51
51
  'addMargin': False,
52
52
  'borrowCrossMargin': False,
53
53
  'borrowIsolatedMargin': False,
@@ -58,6 +58,7 @@ class bitfinex2(Exchange, ImplicitAPI):
58
58
  'createLimitOrder': True,
59
59
  'createMarketOrder': True,
60
60
  'createOrder': True,
61
+ 'createPostOnlyOrder': True,
61
62
  'createReduceOnlyOrder': True,
62
63
  'createStopLimitOrder': True,
63
64
  'createStopMarketOrder': True,
@@ -68,8 +69,11 @@ class bitfinex2(Exchange, ImplicitAPI):
68
69
  'editOrder': True,
69
70
  'fetchBalance': True,
70
71
  'fetchBorrowInterest': False,
72
+ 'fetchBorrowRate': False,
71
73
  'fetchBorrowRateHistories': False,
72
74
  'fetchBorrowRateHistory': False,
75
+ 'fetchBorrowRates': False,
76
+ 'fetchBorrowRatesPerSymbol': False,
73
77
  'fetchClosedOrder': True,
74
78
  'fetchClosedOrders': True,
75
79
  'fetchCrossBorrowRate': False,
@@ -98,6 +102,8 @@ class bitfinex2(Exchange, ImplicitAPI):
98
102
  'fetchOpenOrder': True,
99
103
  'fetchOpenOrders': True,
100
104
  'fetchOrder': True,
105
+ 'fetchOrderBook': True,
106
+ 'fetchOrderBooks': False,
101
107
  'fetchOrderTrades': True,
102
108
  'fetchPosition': False,
103
109
  'fetchPositionMode': False,
@@ -117,6 +123,8 @@ class bitfinex2(Exchange, ImplicitAPI):
117
123
  'setMargin': True,
118
124
  'setMarginMode': False,
119
125
  'setPositionMode': False,
126
+ 'signIn': False,
127
+ 'transfer': True,
120
128
  'withdraw': True,
121
129
  },
122
130
  'timeframes': {
@@ -1484,7 +1492,16 @@ class bitfinex2(Exchange, ImplicitAPI):
1484
1492
  :param float amount: how much you want to trade in units of the base currency
1485
1493
  :param float [price]: the price of the order, in units of the quote currency, ignored in market orders
1486
1494
  :param dict [params]: extra parameters specific to the exchange API endpoint
1487
- :returns dict: request to be sent to the exchange
1495
+ :param float [params.stopPrice]: The price at which a trigger order is triggered at
1496
+ :param str [params.timeInForce]: "GTC", "IOC", "FOK", or "PO"
1497
+ :param bool [params.postOnly]:
1498
+ :param bool [params.reduceOnly]: Ensures that the executed order does not flip the opened position.
1499
+ :param int [params.flags]: additional order parameters: 4096(Post Only), 1024(Reduce Only), 16384(OCO), 64(Hidden), 512(Close), 524288(No Var Rates)
1500
+ :param int [params.lev]: leverage for a derivative order, supported by derivative symbol orders only. The value should be between 1 and 100 inclusive.
1501
+ :param str [params.price_traling]: The trailing price for a trailing stop order
1502
+ :param str [params.price_aux_limit]: Order price for stop limit orders
1503
+ :param str [params.price_oco_stop]: OCO stop price
1504
+ :returns dict: an `order structure <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
1488
1505
  """
1489
1506
  market = self.market(symbol)
1490
1507
  amountString = self.amount_to_precision(symbol, amount)