ccxt 4.4.35__py2.py3-none-any.whl → 4.4.37__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 (55) hide show
  1. ccxt/__init__.py +5 -3
  2. ccxt/abstract/bitfinex.py +136 -65
  3. ccxt/abstract/bitfinex1.py +69 -0
  4. ccxt/abstract/bitopro.py +1 -0
  5. ccxt/abstract/bybit.py +15 -0
  6. ccxt/abstract/defx.py +69 -0
  7. ccxt/abstract/deribit.py +1 -0
  8. ccxt/abstract/gate.py +14 -0
  9. ccxt/abstract/gateio.py +14 -0
  10. ccxt/async_support/__init__.py +5 -3
  11. ccxt/async_support/base/exchange.py +1 -1
  12. ccxt/async_support/bitfinex.py +3005 -1084
  13. ccxt/async_support/bitfinex1.py +1704 -0
  14. ccxt/async_support/bitfinex2.py +18 -13
  15. ccxt/async_support/bitmex.py +103 -1
  16. ccxt/async_support/bitopro.py +21 -4
  17. ccxt/async_support/bitso.py +2 -1
  18. ccxt/async_support/bybit.py +21 -1
  19. ccxt/async_support/coinbase.py +86 -0
  20. ccxt/async_support/defx.py +1981 -0
  21. ccxt/async_support/deribit.py +27 -12
  22. ccxt/async_support/gate.py +15 -1
  23. ccxt/async_support/htx.py +11 -2
  24. ccxt/async_support/hyperliquid.py +124 -14
  25. ccxt/async_support/kraken.py +39 -41
  26. ccxt/async_support/paradex.py +2 -2
  27. ccxt/base/exchange.py +6 -2
  28. ccxt/bitfinex.py +3005 -1084
  29. ccxt/bitfinex1.py +1703 -0
  30. ccxt/bitfinex2.py +18 -13
  31. ccxt/bitmex.py +103 -1
  32. ccxt/bitopro.py +21 -4
  33. ccxt/bitso.py +2 -1
  34. ccxt/bybit.py +21 -1
  35. ccxt/coinbase.py +86 -0
  36. ccxt/defx.py +1980 -0
  37. ccxt/deribit.py +27 -12
  38. ccxt/gate.py +15 -1
  39. ccxt/htx.py +11 -2
  40. ccxt/hyperliquid.py +124 -14
  41. ccxt/kraken.py +39 -41
  42. ccxt/paradex.py +2 -2
  43. ccxt/pro/__init__.py +5 -3
  44. ccxt/pro/bitfinex.py +725 -274
  45. ccxt/pro/bitfinex1.py +635 -0
  46. ccxt/pro/defx.py +832 -0
  47. ccxt/pro/probit.py +1 -0
  48. ccxt/test/tests_async.py +15 -1
  49. ccxt/test/tests_sync.py +15 -1
  50. {ccxt-4.4.35.dist-info → ccxt-4.4.37.dist-info}/METADATA +11 -10
  51. {ccxt-4.4.35.dist-info → ccxt-4.4.37.dist-info}/RECORD +54 -47
  52. ccxt/abstract/bitfinex2.py +0 -140
  53. {ccxt-4.4.35.dist-info → ccxt-4.4.37.dist-info}/LICENSE.txt +0 -0
  54. {ccxt-4.4.35.dist-info → ccxt-4.4.37.dist-info}/WHEEL +0 -0
  55. {ccxt-4.4.35.dist-info → ccxt-4.4.37.dist-info}/top_level.txt +0 -0
ccxt/deribit.py CHANGED
@@ -220,6 +220,7 @@ class deribit(Exchange, ImplicitAPI):
220
220
  'enable_api_key': 1,
221
221
  'get_access_log': 1,
222
222
  'get_account_summary': 1,
223
+ 'get_account_summaries': 1,
223
224
  'get_affiliate_program_info': 1,
224
225
  'get_email_language': 1,
225
226
  'get_new_announcements': 1,
@@ -931,13 +932,20 @@ class deribit(Exchange, ImplicitAPI):
931
932
  result: dict = {
932
933
  'info': balance,
933
934
  }
934
- currencyId = self.safe_string(balance, 'currency')
935
- currencyCode = self.safe_currency_code(currencyId)
936
- account = self.account()
937
- account['free'] = self.safe_string(balance, 'available_funds')
938
- account['used'] = self.safe_string(balance, 'maintenance_margin')
939
- account['total'] = self.safe_string(balance, 'equity')
940
- result[currencyCode] = account
935
+ summaries = []
936
+ if 'summaries' in balance:
937
+ summaries = self.safe_list(balance, 'summaries')
938
+ else:
939
+ summaries = [balance]
940
+ for i in range(0, len(summaries)):
941
+ data = summaries[i]
942
+ currencyId = self.safe_string(data, 'currency')
943
+ currencyCode = self.safe_currency_code(currencyId)
944
+ account = self.account()
945
+ account['free'] = self.safe_string(data, 'available_funds')
946
+ account['used'] = self.safe_string(data, 'maintenance_margin')
947
+ account['total'] = self.safe_string(data, 'equity')
948
+ result[currencyCode] = account
941
949
  return self.safe_balance(result)
942
950
 
943
951
  def fetch_balance(self, params={}) -> Balances:
@@ -945,17 +953,24 @@ class deribit(Exchange, ImplicitAPI):
945
953
  query for balance and get the amount of funds available for trading or funds locked in orders
946
954
 
947
955
  https://docs.deribit.com/#private-get_account_summary
956
+ https://docs.deribit.com/#private-get_account_summaries
948
957
 
949
958
  :param dict [params]: extra parameters specific to the exchange API endpoint
959
+ :param str [params.code]: unified currency code of the currency for the balance, if defined 'privateGetGetAccountSummary' will be used, otherwise 'privateGetGetAccountSummaries' will be used
950
960
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
951
961
  """
952
962
  self.load_markets()
953
- code = self.code_from_options('fetchBalance', params)
954
- currency = self.currency(code)
963
+ code = self.safe_string(params, 'code')
964
+ params = self.omit(params, 'code')
955
965
  request: dict = {
956
- 'currency': currency['id'],
957
966
  }
958
- response = self.privateGetGetAccountSummary(self.extend(request, params))
967
+ if code is not None:
968
+ request['currency'] = self.currency_id(code)
969
+ response = None
970
+ if code is None:
971
+ response = self.privateGetGetAccountSummaries(params)
972
+ else:
973
+ response = self.privateGetGetAccountSummary(self.extend(request, params))
959
974
  #
960
975
  # {
961
976
  # "jsonrpc": "2.0",
@@ -998,7 +1013,7 @@ class deribit(Exchange, ImplicitAPI):
998
1013
  # "testnet": False
999
1014
  # }
1000
1015
  #
1001
- result = self.safe_value(response, 'result', {})
1016
+ result = self.safe_dict(response, 'result', {})
1002
1017
  return self.parse_balance(result)
1003
1018
 
1004
1019
  def create_deposit_address(self, code: str, params={}):
ccxt/gate.py CHANGED
@@ -40,7 +40,7 @@ class gate(Exchange, ImplicitAPI):
40
40
  'certified': True,
41
41
  'pro': True,
42
42
  'urls': {
43
- 'logo': 'https://user-images.githubusercontent.com/1294454/31784029-0313c702-b509-11e7-9ccc-bc0da6a0e435.jpg',
43
+ 'logo': 'https://github.com/user-attachments/assets/64f988c5-07b6-4652-b5c1-679a6bf67c85',
44
44
  'doc': 'https://www.gate.io/docs/developers/apiv4/en/',
45
45
  'www': 'https://gate.io/',
46
46
  'api': {
@@ -239,6 +239,7 @@ class gate(Exchange, ImplicitAPI):
239
239
  '{settle}/contract_stats': 1,
240
240
  '{settle}/index_constituents/{index}': 1,
241
241
  '{settle}/liq_orders': 1,
242
+ '{settle}/risk_limit_tiers': 1,
242
243
  },
243
244
  },
244
245
  'delivery': {
@@ -280,6 +281,7 @@ class gate(Exchange, ImplicitAPI):
280
281
  'withdrawals': {
281
282
  'post': {
282
283
  'withdrawals': 20, # 1r/s cost = 20 / 1 = 20
284
+ 'push': 1,
283
285
  },
284
286
  'delete': {
285
287
  'withdrawals/{withdrawal_id}': 1,
@@ -291,6 +293,7 @@ class gate(Exchange, ImplicitAPI):
291
293
  'withdrawals': 1,
292
294
  'deposits': 1,
293
295
  'sub_account_transfers': 1,
296
+ 'order_status': 1,
294
297
  'withdraw_status': 1,
295
298
  'sub_account_balances': 2.5,
296
299
  'sub_account_margin_balances': 2.5,
@@ -301,6 +304,7 @@ class gate(Exchange, ImplicitAPI):
301
304
  'total_balance': 2.5,
302
305
  'small_balance': 1,
303
306
  'small_balance_history': 1,
307
+ 'push': 1,
304
308
  },
305
309
  'post': {
306
310
  'transfers': 2.5, # 8r/s cost = 20 / 8 = 2.5
@@ -343,11 +347,14 @@ class gate(Exchange, ImplicitAPI):
343
347
  'risk_units': 20 / 15,
344
348
  'unified_mode': 20 / 15,
345
349
  'loan_margin_tiers': 20 / 15,
350
+ 'leverage/user_currency_config': 20 / 15,
351
+ 'leverage/user_currency_setting': 20 / 15,
346
352
  },
347
353
  'post': {
348
354
  'account_mode': 20 / 15,
349
355
  'loans': 200 / 15, # 15r/10s cost = 20 / 1.5 = 13.33
350
356
  'portfolio_calculator': 20 / 15,
357
+ 'leverage/user_currency_setting': 20 / 15,
351
358
  },
352
359
  'put': {
353
360
  'unified_mode': 20 / 15,
@@ -527,9 +534,13 @@ class gate(Exchange, ImplicitAPI):
527
534
  'orders': 20 / 15,
528
535
  'orders/{order_id}': 20 / 15,
529
536
  'my_trades': 20 / 15,
537
+ 'mmp': 20 / 15,
530
538
  },
531
539
  'post': {
532
540
  'orders': 20 / 15,
541
+ 'countdown_cancel_all': 20 / 15,
542
+ 'mmp': 20 / 15,
543
+ 'mmp/reset': 20 / 15,
533
544
  },
534
545
  'delete': {
535
546
  'orders': 20 / 15,
@@ -573,6 +584,7 @@ class gate(Exchange, ImplicitAPI):
573
584
  'multi_collateral/currencies': 20 / 15,
574
585
  'multi_collateral/ltv': 20 / 15,
575
586
  'multi_collateral/fixed_rate': 20 / 15,
587
+ 'multi_collateral/current_rate': 20 / 15,
576
588
  },
577
589
  'post': {
578
590
  'collateral/orders': 20 / 15,
@@ -586,8 +598,10 @@ class gate(Exchange, ImplicitAPI):
586
598
  'account': {
587
599
  'get': {
588
600
  'detail': 20 / 15,
601
+ 'rate_limit': 20 / 15,
589
602
  'stp_groups': 20 / 15,
590
603
  'stp_groups/{stp_id}/users': 20 / 15,
604
+ 'stp_groups/debit_fee': 20 / 15,
591
605
  },
592
606
  'post': {
593
607
  'stp_groups': 20 / 15,
ccxt/htx.py CHANGED
@@ -5091,17 +5091,23 @@ class htx(Exchange, ImplicitAPI):
5091
5091
  params = self.omit(params, ['clientOrderId'])
5092
5092
  if type == 'limit' or type == 'ioc' or type == 'fok' or type == 'post_only':
5093
5093
  request['price'] = self.price_to_precision(symbol, price)
5094
+ reduceOnly = self.safe_bool_2(params, 'reduceOnly', 'reduce_only', False)
5094
5095
  if not isStopLossTriggerOrder and not isTakeProfitTriggerOrder:
5095
- reduceOnly = self.safe_value_2(params, 'reduceOnly', 'reduce_only', False)
5096
5096
  if reduceOnly:
5097
5097
  request['reduce_only'] = 1
5098
5098
  request['lever_rate'] = self.safe_integer_n(params, ['leverRate', 'lever_rate', 'leverage'], 1)
5099
5099
  if not isTrailingPercentOrder:
5100
5100
  request['order_price_type'] = type
5101
+ hedged = self.safe_bool(params, 'hedged', False)
5102
+ if hedged:
5103
+ if reduceOnly:
5104
+ request['offset'] = 'close'
5105
+ else:
5106
+ request['offset'] = 'open'
5101
5107
  broker = self.safe_value(self.options, 'broker', {})
5102
5108
  brokerId = self.safe_string(broker, 'id')
5103
5109
  request['channel_code'] = brokerId
5104
- params = self.omit(params, ['reduceOnly', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'triggerType', 'leverRate', 'timeInForce', 'leverage', 'trailingPercent', 'trailingTriggerPrice'])
5110
+ params = self.omit(params, ['reduceOnly', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'triggerType', 'leverRate', 'timeInForce', 'leverage', 'trailingPercent', 'trailingTriggerPrice', 'hedged'])
5105
5111
  return self.extend(request, params)
5106
5112
 
5107
5113
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
@@ -5115,6 +5121,8 @@ class htx(Exchange, ImplicitAPI):
5115
5121
  https://huobiapi.github.io/docs/usdt_swap/v1/en/#cross-place-trigger-order # usdt-m swap cross trigger
5116
5122
  https://huobiapi.github.io/docs/usdt_swap/v1/en/#isolated-place-an-order # usdt-m swap isolated
5117
5123
  https://huobiapi.github.io/docs/usdt_swap/v1/en/#isolated-place-trigger-order # usdt-m swap isolated trigger
5124
+ https://huobiapi.github.io/docs/usdt_swap/v1/en/#isolated-set-a-take-profit-and-stop-loss-order-for-an-existing-position
5125
+ https://huobiapi.github.io/docs/usdt_swap/v1/en/#cross-set-a-take-profit-and-stop-loss-order-for-an-existing-position
5118
5126
  https://huobiapi.github.io/docs/dm/v1/en/#place-an-order # coin-m futures
5119
5127
  https://huobiapi.github.io/docs/dm/v1/en/#place-trigger-order # coin-m futures contract trigger
5120
5128
 
@@ -5136,6 +5144,7 @@ class htx(Exchange, ImplicitAPI):
5136
5144
  :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
5137
5145
  :param float [params.trailingPercent]: *contract only* the percent to trail away from the current market price
5138
5146
  :param float [params.trailingTriggerPrice]: *contract only* the price to trigger a trailing order, default uses the price argument
5147
+ :param bool [params.hedged]: *contract only* True for hedged mode, False for one way mode, default is False
5139
5148
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
5140
5149
  """
5141
5150
  self.load_markets()
ccxt/hyperliquid.py CHANGED
@@ -225,6 +225,96 @@ class hyperliquid(Exchange, ImplicitAPI):
225
225
  'defaultSlippage': 0.05,
226
226
  'zeroAddress': '0x0000000000000000000000000000000000000000',
227
227
  },
228
+ 'features': {
229
+ 'default': {
230
+ 'sandbox': True,
231
+ 'createOrder': {
232
+ 'marginMode': False,
233
+ 'triggerPrice': False,
234
+ 'triggerPriceType': None,
235
+ 'triggerDirection': False,
236
+ 'stopLossPrice': False,
237
+ 'takeProfitPrice': False,
238
+ 'attachedStopLossTakeProfit': None,
239
+ 'timeInForce': {
240
+ 'GTC': True,
241
+ 'IOC': True,
242
+ 'FOK': False,
243
+ 'PO': True,
244
+ 'GTD': False,
245
+ },
246
+ 'hedged': False,
247
+ 'trailing': False,
248
+ },
249
+ 'createOrders': {
250
+ 'max': 1000,
251
+ },
252
+ 'fetchMyTrades': {
253
+ 'marginMode': False,
254
+ 'limit': 2000,
255
+ 'daysBack': None,
256
+ 'untilDays': None,
257
+ },
258
+ 'fetchOrder': {
259
+ 'marginMode': False,
260
+ 'trigger': False,
261
+ 'trailing': False,
262
+ },
263
+ 'fetchOpenOrders': {
264
+ 'marginMode': False,
265
+ 'limit': 2000,
266
+ 'trigger': False,
267
+ 'trailing': False,
268
+ },
269
+ 'fetchOrders': {
270
+ 'marginMode': False,
271
+ 'limit': 2000,
272
+ 'daysBack': None,
273
+ 'untilDays': None,
274
+ 'trigger': False,
275
+ 'trailing': False,
276
+ },
277
+ 'fetchClosedOrders': {
278
+ 'marginMode': False,
279
+ 'limit': 2000,
280
+ 'daysBackClosed': None,
281
+ 'daysBackCanceled': None,
282
+ 'untilDays': None,
283
+ 'trigger': False,
284
+ 'trailing': False,
285
+ },
286
+ 'fetchOHLCV': {
287
+ 'limit': 5000,
288
+ },
289
+ },
290
+ 'spot': {
291
+ 'extends': 'default',
292
+ },
293
+ 'forPerps': {
294
+ 'extends': 'default',
295
+ 'createOrder': {
296
+ 'stopLossPrice': True,
297
+ 'takeProfitPrice': True,
298
+ 'attachedStopLossTakeProfit': None, # todo, in two orders
299
+ },
300
+ },
301
+ 'swap': {
302
+ 'linear': {
303
+ 'extends': 'forPerps',
304
+ },
305
+ 'inverse': {
306
+ 'extends': 'forPerps',
307
+ },
308
+ },
309
+ 'future': {
310
+ 'linear': {
311
+ 'extends': 'forPerps',
312
+ },
313
+ 'inverse': {
314
+ 'extends': 'forPerps',
315
+ },
316
+ },
317
+ },
228
318
  })
229
319
 
230
320
  def set_sandbox_mode(self, enabled):
@@ -502,7 +592,7 @@ class hyperliquid(Exchange, ImplicitAPI):
502
592
  pricePrecision = self.calculate_price_precision(price, amountPrecision, 8)
503
593
  pricePrecisionStr = self.number_to_string(pricePrecision)
504
594
  # quotePrecision = self.parse_number(self.parse_precision(self.safe_string(innerQuoteTokenInfo, 'szDecimals')))
505
- baseId = self.number_to_string(i + 10000)
595
+ baseId = self.number_to_string(index + 10000)
506
596
  markets.append(self.safe_market_structure({
507
597
  'id': marketName,
508
598
  'symbol': symbol,
@@ -1191,7 +1281,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1191
1281
  signature = self.sign_message(msg, self.privateKey)
1192
1282
  return signature
1193
1283
 
1194
- def build_transfer_sig(self, message):
1284
+ def build_usd_send_sig(self, message):
1195
1285
  messageTypes: dict = {
1196
1286
  'HyperliquidTransaction:UsdSend': [
1197
1287
  {'name': 'hyperliquidChain', 'type': 'string'},
@@ -1202,6 +1292,17 @@ class hyperliquid(Exchange, ImplicitAPI):
1202
1292
  }
1203
1293
  return self.sign_user_signed_action(messageTypes, message)
1204
1294
 
1295
+ def build_usd_class_send_sig(self, message):
1296
+ messageTypes: dict = {
1297
+ 'HyperliquidTransaction:UsdClassTransfer': [
1298
+ {'name': 'hyperliquidChain', 'type': 'string'},
1299
+ {'name': 'amount', 'type': 'string'},
1300
+ {'name': 'toPerp', 'type': 'bool'},
1301
+ {'name': 'nonce', 'type': 'uint64'},
1302
+ ],
1303
+ }
1304
+ return self.sign_user_signed_action(messageTypes, message)
1305
+
1205
1306
  def build_withdraw_sig(self, message):
1206
1307
  messageTypes: dict = {
1207
1308
  'HyperliquidTransaction:Withdraw': [
@@ -2589,25 +2690,34 @@ class hyperliquid(Exchange, ImplicitAPI):
2589
2690
  # handle swap <> spot account transfer
2590
2691
  if not self.in_array(toAccount, ['spot', 'swap', 'perp']):
2591
2692
  raise NotSupported(self.id + 'transfer() only support spot <> swap transfer')
2693
+ strAmount = self.number_to_string(amount)
2592
2694
  vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
2593
2695
  params = self.omit(params, 'vaultAddress')
2696
+ if vaultAddress is not None:
2697
+ strAmount = strAmount + ' subaccount:' + vaultAddress
2594
2698
  toPerp = (toAccount == 'perp') or (toAccount == 'swap')
2595
- action: dict = {
2596
- 'type': 'spotUser',
2597
- 'classTransfer': {
2598
- 'usdc': amount,
2699
+ transferPayload: dict = {
2700
+ 'hyperliquidChain': 'Testnet' if isSandboxMode else 'Mainnet',
2701
+ 'amount': strAmount,
2702
+ 'toPerp': toPerp,
2703
+ 'nonce': nonce,
2704
+ }
2705
+ transferSig = self.build_usd_class_send_sig(transferPayload)
2706
+ transferRequest: dict = {
2707
+ 'action': {
2708
+ 'hyperliquidChain': transferPayload['hyperliquidChain'],
2709
+ 'signatureChainId': '0x66eee',
2710
+ 'type': 'usdClassTransfer',
2711
+ 'amount': strAmount,
2599
2712
  'toPerp': toPerp,
2713
+ 'nonce': nonce,
2600
2714
  },
2601
- }
2602
- signature = self.sign_l1_action(action, nonce, vaultAddress)
2603
- innerRequest: dict = {
2604
- 'action': action,
2605
2715
  'nonce': nonce,
2606
- 'signature': signature,
2716
+ 'signature': transferSig,
2607
2717
  }
2608
2718
  if vaultAddress is not None:
2609
- innerRequest['vaultAddress'] = vaultAddress
2610
- transferResponse = self.privatePostExchange(innerRequest)
2719
+ transferRequest['vaultAddress'] = vaultAddress
2720
+ transferResponse = self.privatePostExchange(transferRequest)
2611
2721
  return transferResponse
2612
2722
  # handle sub-account/different account transfer
2613
2723
  self.check_address(toAccount)
@@ -2621,7 +2731,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2621
2731
  'amount': self.number_to_string(amount),
2622
2732
  'time': nonce,
2623
2733
  }
2624
- sig = self.build_transfer_sig(payload)
2734
+ sig = self.build_usd_send_sig(payload)
2625
2735
  request: dict = {
2626
2736
  'action': {
2627
2737
  'hyperliquidChain': payload['hyperliquidChain'],
ccxt/kraken.py CHANGED
@@ -447,31 +447,43 @@ class kraken(Exchange, ImplicitAPI):
447
447
  },
448
448
  'precisionMode': TICK_SIZE,
449
449
  'exceptions': {
450
- 'EQuery:Invalid asset pair': BadSymbol, # {"error":["EQuery:Invalid asset pair"]}
451
- 'EAPI:Invalid key': AuthenticationError,
452
- 'EFunding:Unknown withdraw key': InvalidAddress, # {"error":["EFunding:Unknown withdraw key"]}
453
- 'EFunding:Invalid amount': InsufficientFunds,
454
- 'EService:Unavailable': ExchangeNotAvailable,
455
- 'EDatabase:Internal error': ExchangeNotAvailable,
456
- 'EService:Busy': ExchangeNotAvailable,
457
- 'EQuery:Unknown asset': BadSymbol, # {"error":["EQuery:Unknown asset"]}
458
- 'EAPI:Rate limit exceeded': DDoSProtection,
459
- 'EOrder:Rate limit exceeded': DDoSProtection,
460
- 'EGeneral:Internal error': ExchangeNotAvailable,
461
- 'EGeneral:Temporary lockout': DDoSProtection,
462
- 'EGeneral:Permission denied': PermissionDenied,
463
- 'EGeneral:Invalid arguments:price': InvalidOrder,
464
- 'EOrder:Unknown order': InvalidOrder,
465
- 'EOrder:Invalid price:Invalid price argument': InvalidOrder,
466
- 'EOrder:Order minimum not met': InvalidOrder,
467
- 'EGeneral:Invalid arguments': BadRequest,
468
- 'ESession:Invalid session': AuthenticationError,
469
- 'EAPI:Invalid nonce': InvalidNonce,
470
- 'EFunding:No funding method': BadRequest, # {"error":"EFunding:No funding method"}
471
- 'EFunding:Unknown asset': BadSymbol, # {"error":["EFunding:Unknown asset"]}
472
- 'EService:Market in post_only mode': OnMaintenance, # {"error":["EService:Market in post_only mode"]}
473
- 'EGeneral:Too many requests': DDoSProtection, # {"error":["EGeneral:Too many requests"]}
474
- 'ETrade:User Locked': AccountSuspended, # {"error":["ETrade:User Locked"]}
450
+ 'exact': {
451
+ 'EQuery:Invalid asset pair': BadSymbol, # {"error":["EQuery:Invalid asset pair"]}
452
+ 'EAPI:Invalid key': AuthenticationError,
453
+ 'EFunding:Unknown withdraw key': InvalidAddress, # {"error":["EFunding:Unknown withdraw key"]}
454
+ 'EFunding:Invalid amount': InsufficientFunds,
455
+ 'EService:Unavailable': ExchangeNotAvailable,
456
+ 'EDatabase:Internal error': ExchangeNotAvailable,
457
+ 'EService:Busy': ExchangeNotAvailable,
458
+ 'EQuery:Unknown asset': BadSymbol, # {"error":["EQuery:Unknown asset"]}
459
+ 'EAPI:Rate limit exceeded': DDoSProtection,
460
+ 'EOrder:Rate limit exceeded': DDoSProtection,
461
+ 'EGeneral:Internal error': ExchangeNotAvailable,
462
+ 'EGeneral:Temporary lockout': DDoSProtection,
463
+ 'EGeneral:Permission denied': PermissionDenied,
464
+ 'EGeneral:Invalid arguments:price': InvalidOrder,
465
+ 'EOrder:Unknown order': InvalidOrder,
466
+ 'EOrder:Invalid price:Invalid price argument': InvalidOrder,
467
+ 'EOrder:Order minimum not met': InvalidOrder,
468
+ 'EOrder:Insufficient funds': InsufficientFunds,
469
+ 'EGeneral:Invalid arguments': BadRequest,
470
+ 'ESession:Invalid session': AuthenticationError,
471
+ 'EAPI:Invalid nonce': InvalidNonce,
472
+ 'EFunding:No funding method': BadRequest, # {"error":"EFunding:No funding method"}
473
+ 'EFunding:Unknown asset': BadSymbol, # {"error":["EFunding:Unknown asset"]}
474
+ 'EService:Market in post_only mode': OnMaintenance, # {"error":["EService:Market in post_only mode"]}
475
+ 'EGeneral:Too many requests': DDoSProtection, # {"error":["EGeneral:Too many requests"]}
476
+ 'ETrade:User Locked': AccountSuspended, # {"error":["ETrade:User Locked"]}
477
+ },
478
+ 'broad': {
479
+ ':Invalid order': InvalidOrder,
480
+ ':Invalid arguments:volume': InvalidOrder,
481
+ ':Invalid arguments:viqc': InvalidOrder,
482
+ ':Invalid nonce': InvalidNonce,
483
+ ':IInsufficient funds': InsufficientFunds,
484
+ ':Cancel pending': CancelPending,
485
+ ':Rate limit exceeded': RateLimitExceeded,
486
+ },
475
487
  },
476
488
  })
477
489
 
@@ -3064,21 +3076,6 @@ class kraken(Exchange, ImplicitAPI):
3064
3076
  def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
3065
3077
  if code == 520:
3066
3078
  raise ExchangeNotAvailable(self.id + ' ' + str(code) + ' ' + reason)
3067
- # todo: rewrite self for "broad" exceptions matching
3068
- if body.find('Invalid order') >= 0:
3069
- raise InvalidOrder(self.id + ' ' + body)
3070
- if body.find('Invalid nonce') >= 0:
3071
- raise InvalidNonce(self.id + ' ' + body)
3072
- if body.find('Insufficient funds') >= 0:
3073
- raise InsufficientFunds(self.id + ' ' + body)
3074
- if body.find('Cancel pending') >= 0:
3075
- raise CancelPending(self.id + ' ' + body)
3076
- if body.find('Invalid arguments:volume') >= 0:
3077
- raise InvalidOrder(self.id + ' ' + body)
3078
- if body.find('Invalid arguments:viqc') >= 0:
3079
- raise InvalidOrder(self.id + ' ' + body)
3080
- if body.find('Rate limit exceeded') >= 0:
3081
- raise RateLimitExceeded(self.id + ' ' + body)
3082
3079
  if response is None:
3083
3080
  return None
3084
3081
  if body[0] == '{':
@@ -3089,6 +3086,7 @@ class kraken(Exchange, ImplicitAPI):
3089
3086
  message = self.id + ' ' + body
3090
3087
  for i in range(0, len(response['error'])):
3091
3088
  error = response['error'][i]
3092
- self.throw_exactly_matched_exception(self.exceptions, error, message)
3089
+ self.throw_exactly_matched_exception(self.exceptions['exact'], error, message)
3090
+ self.throw_exactly_matched_exception(self.exceptions['broad'], error, message)
3093
3091
  raise ExchangeError(message)
3094
3092
  return None
ccxt/paradex.py CHANGED
@@ -276,6 +276,7 @@ class paradex(Exchange, ImplicitAPI):
276
276
  'commonCurrencies': {
277
277
  },
278
278
  'options': {
279
+ 'paradexAccount': None, # add {"privateKey": A, "publicKey": B, "address": C}
279
280
  'broker': 'CCXT',
280
281
  },
281
282
  })
@@ -964,10 +965,10 @@ class paradex(Exchange, ImplicitAPI):
964
965
  }
965
966
 
966
967
  def retrieve_account(self):
967
- self.check_required_credentials()
968
968
  cachedAccount: dict = self.safe_dict(self.options, 'paradexAccount')
969
969
  if cachedAccount is not None:
970
970
  return cachedAccount
971
+ self.check_required_credentials()
971
972
  systemConfig = self.get_system_config()
972
973
  domain = self.prepare_paradex_domain(True)
973
974
  messageTypes = {
@@ -1956,7 +1957,6 @@ class paradex(Exchange, ImplicitAPI):
1956
1957
  if query:
1957
1958
  url += '?' + self.urlencode(query)
1958
1959
  elif api == 'private':
1959
- self.check_required_credentials()
1960
1960
  headers = {
1961
1961
  'Accept': 'application/json',
1962
1962
  'PARADEX-PARTNER': self.safe_string(self.options, 'broker', 'CCXT'),
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.35'
7
+ __version__ = '4.4.37'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
@@ -22,7 +22,7 @@ from ccxt.pro.binanceusdm import binanceusdm # noqa
22
22
  from ccxt.pro.bingx import bingx # noqa: F401
23
23
  from ccxt.pro.bitcoincom import bitcoincom # noqa: F401
24
24
  from ccxt.pro.bitfinex import bitfinex # noqa: F401
25
- from ccxt.pro.bitfinex2 import bitfinex2 # noqa: F401
25
+ from ccxt.pro.bitfinex1 import bitfinex1 # noqa: F401
26
26
  from ccxt.pro.bitget import bitget # noqa: F401
27
27
  from ccxt.pro.bithumb import bithumb # noqa: F401
28
28
  from ccxt.pro.bitmart import bitmart # noqa: F401
@@ -46,6 +46,7 @@ from ccxt.pro.coinex import coinex # noqa
46
46
  from ccxt.pro.coinone import coinone # noqa: F401
47
47
  from ccxt.pro.cryptocom import cryptocom # noqa: F401
48
48
  from ccxt.pro.currencycom import currencycom # noqa: F401
49
+ from ccxt.pro.defx import defx # noqa: F401
49
50
  from ccxt.pro.deribit import deribit # noqa: F401
50
51
  from ccxt.pro.exmo import exmo # noqa: F401
51
52
  from ccxt.pro.gate import gate # noqa: F401
@@ -97,7 +98,7 @@ exchanges = [
97
98
  'bingx',
98
99
  'bitcoincom',
99
100
  'bitfinex',
100
- 'bitfinex2',
101
+ 'bitfinex1',
101
102
  'bitget',
102
103
  'bithumb',
103
104
  'bitmart',
@@ -121,6 +122,7 @@ exchanges = [
121
122
  'coinone',
122
123
  'cryptocom',
123
124
  'currencycom',
125
+ 'defx',
124
126
  'deribit',
125
127
  'exmo',
126
128
  'gate',