ccxt 4.3.2__py2.py3-none-any.whl → 4.3.4__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.
@@ -315,6 +315,7 @@ class hyperliquid(Exchange, ImplicitAPI):
315
315
  # ]
316
316
  # ]
317
317
  #
318
+ #
318
319
  meta = self.safe_dict(response, 0, {})
319
320
  meta = self.safe_list(meta, 'universe', [])
320
321
  assetCtxs = self.safe_dict(response, 1, {})
@@ -373,10 +374,70 @@ class hyperliquid(Exchange, ImplicitAPI):
373
374
  # },
374
375
  # ],
375
376
  # ]
377
+ # mainnet
378
+ # [
379
+ # {
380
+ # "canonical_tokens2":[
381
+ # 0,
382
+ # 1
383
+ # ],
384
+ # "spot_infos":[
385
+ # {
386
+ # "name":"PURR/USDC",
387
+ # "tokens":[
388
+ # 1,
389
+ # 0
390
+ # ]
391
+ # }
392
+ # ],
393
+ # "token_id_to_token":[
394
+ # [
395
+ # "0x6d1e7cde53ba9467b783cb7c530ce054",
396
+ # 0
397
+ # ],
398
+ # [
399
+ # "0xc1fb593aeffbeb02f85e0308e9956a90",
400
+ # 1
401
+ # ]
402
+ # ],
403
+ # "token_infos":[
404
+ # {
405
+ # "deployer":null,
406
+ # "spec":{
407
+ # "name":"USDC",
408
+ # "szDecimals":"8",
409
+ # "weiDecimals":"8"
410
+ # },
411
+ # "spots":[
412
+ # ]
413
+ # },
414
+ # {
415
+ # "deployer":null,
416
+ # "spec":{
417
+ # "name":"PURR",
418
+ # "szDecimals":"0",
419
+ # "weiDecimals":"5"
420
+ # },
421
+ # "spots":[
422
+ # 0
423
+ # ]
424
+ # }
425
+ # ]
426
+ # },
427
+ # [
428
+ # {
429
+ # "dayNtlVlm":"35001170.16631",
430
+ # "markPx":"0.15743",
431
+ # "midPx":"0.157555",
432
+ # "prevDayPx":"0.158"
433
+ # }
434
+ # ]
435
+ # ]
376
436
  #
437
+ # response differs depending on the environment(mainnet vs sandbox)
377
438
  first = self.safe_dict(response, 0, {})
378
- meta = self.safe_list(first, 'universe', [])
379
- tokens = self.safe_list(first, 'tokens', [])
439
+ meta = self.safe_list_2(first, 'universe', 'spot_infos', [])
440
+ tokens = self.safe_list_2(first, 'tokens', 'token_infos', [])
380
441
  markets = []
381
442
  for i in range(0, len(meta)):
382
443
  market = self.safe_dict(meta, i, {})
@@ -392,14 +453,16 @@ class hyperliquid(Exchange, ImplicitAPI):
392
453
  maker = self.safe_number(fees, 'maker')
393
454
  tokensPos = self.safe_list(market, 'tokens', [])
394
455
  baseTokenPos = self.safe_integer(tokensPos, 0)
395
- quoteTokenPos = self.safe_integer(tokensPos, 1)
456
+ # quoteTokenPos = self.safe_integer(tokensPos, 1)
396
457
  baseTokenInfo = self.safe_dict(tokens, baseTokenPos, {})
397
- quoteTokenInfo = self.safe_dict(tokens, quoteTokenPos, {})
398
- baseDecimals = self.safe_string(baseTokenInfo, 'szDecimals')
399
- quoteDecimals = self.safe_integer(quoteTokenInfo, 'szDecimals')
458
+ # quoteTokenInfo = self.safe_dict(tokens, quoteTokenPos, {})
459
+ innerBaseTokenInfo = self.safe_dict(baseTokenInfo, 'spec', baseTokenInfo)
460
+ # innerQuoteTokenInfo = self.safe_dict(quoteTokenInfo, 'spec', quoteTokenInfo)
461
+ amountPrecision = self.parse_number(self.parse_precision(self.safe_string(innerBaseTokenInfo, 'szDecimals')))
462
+ # quotePrecision = self.parse_number(self.parse_precision(self.safe_string(innerQuoteTokenInfo, 'szDecimals')))
400
463
  baseId = self.number_to_string(i + 10000)
401
464
  markets.append(self.safe_market_structure({
402
- 'id': baseId,
465
+ 'id': marketName,
403
466
  'symbol': symbol,
404
467
  'base': base,
405
468
  'quote': quote,
@@ -409,14 +472,15 @@ class hyperliquid(Exchange, ImplicitAPI):
409
472
  'settleId': None,
410
473
  'type': 'spot',
411
474
  'spot': True,
475
+ 'subType': None,
412
476
  'margin': None,
413
477
  'swap': False,
414
478
  'future': False,
415
479
  'option': False,
416
480
  'active': True,
417
481
  'contract': False,
418
- 'linear': True,
419
- 'inverse': False,
482
+ 'linear': None,
483
+ 'inverse': None,
420
484
  'taker': taker,
421
485
  'maker': maker,
422
486
  'contractSize': None,
@@ -425,8 +489,8 @@ class hyperliquid(Exchange, ImplicitAPI):
425
489
  'strike': None,
426
490
  'optionType': None,
427
491
  'precision': {
428
- 'amount': self.parse_number(self.parse_precision(baseDecimals)), # decimal places
429
- 'price': quoteDecimals, # significant digits
492
+ 'amount': amountPrecision, # decimal places
493
+ 'price': 5, # significant digits
430
494
  },
431
495
  'limits': {
432
496
  'leverage': {
@@ -633,7 +697,7 @@ class hyperliquid(Exchange, ImplicitAPI):
633
697
  market = self.market(symbol)
634
698
  request = {
635
699
  'type': 'l2Book',
636
- 'coin': market['base'],
700
+ 'coin': market['base'] if market['swap'] else market['id'],
637
701
  }
638
702
  response = await self.publicPostInfo(self.extend(request, params))
639
703
  #
@@ -689,7 +753,7 @@ class hyperliquid(Exchange, ImplicitAPI):
689
753
  request = {
690
754
  'type': 'candleSnapshot',
691
755
  'req': {
692
- 'coin': market['base'],
756
+ 'coin': market['base'] if market['swap'] else market['id'],
693
757
  'interval': timeframe,
694
758
  'startTime': since,
695
759
  'endTime': until,
@@ -792,6 +856,9 @@ class hyperliquid(Exchange, ImplicitAPI):
792
856
  return self.parse_trades(response, market, since, limit)
793
857
 
794
858
  def amount_to_precision(self, symbol, amount):
859
+ market = self.market(symbol)
860
+ if market['spot']:
861
+ return super(hyperliquid, self).amount_to_precision(symbol, amount)
795
862
  return self.decimal_to_precision(amount, ROUND, self.markets[symbol]['precision']['amount'], self.precisionMode)
796
863
 
797
864
  def price_to_precision(self, symbol: str, price) -> str:
@@ -2222,6 +2289,11 @@ class hyperliquid(Exchange, ImplicitAPI):
2222
2289
  return [self.walletAddress, params]
2223
2290
  raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a user parameter inside \'params\' or the wallet address set')
2224
2291
 
2292
+ def coin_to_market_id(self, coin: Str):
2293
+ if coin.find('/') > -1:
2294
+ return coin # spot
2295
+ return coin + '/USDC:USDC'
2296
+
2225
2297
  def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
2226
2298
  if not response:
2227
2299
  return None # fallback to default error handler
ccxt/async_support/okx.py CHANGED
@@ -87,6 +87,8 @@ class okx(Exchange, ImplicitAPI):
87
87
  'fetchClosedOrders': True,
88
88
  'fetchConvertCurrencies': True,
89
89
  'fetchConvertQuote': True,
90
+ 'fetchConvertTrade': True,
91
+ 'fetchConvertTradeHistory': True,
90
92
  'fetchCrossBorrowRate': True,
91
93
  'fetchCrossBorrowRates': True,
92
94
  'fetchCurrencies': True,
@@ -7203,6 +7205,96 @@ class okx(Exchange, ImplicitAPI):
7203
7205
  toCurrency = self.currency(toCurrencyId)
7204
7206
  return self.parse_conversion(result, fromCurrency, toCurrency)
7205
7207
 
7208
+ async def fetch_convert_trade(self, id: str, code: Str = None, params={}) -> Conversion:
7209
+ """
7210
+ fetch the data for a conversion trade
7211
+ :see: https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-convert-history
7212
+ :param str id: the id of the trade that you want to fetch
7213
+ :param str [code]: the unified currency code of the conversion trade
7214
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7215
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
7216
+ """
7217
+ await self.load_markets()
7218
+ request = {
7219
+ 'clTReqId': id,
7220
+ }
7221
+ response = await self.privateGetAssetConvertHistory(self.extend(request, params))
7222
+ #
7223
+ # {
7224
+ # "code": "0",
7225
+ # "data": [
7226
+ # {
7227
+ # "clTReqId": "",
7228
+ # "instId": "ETH-USDT",
7229
+ # "side": "buy",
7230
+ # "fillPx": "2932.401044",
7231
+ # "baseCcy": "ETH",
7232
+ # "quoteCcy": "USDT",
7233
+ # "fillBaseSz": "0.01023052",
7234
+ # "state": "fullyFilled",
7235
+ # "tradeId": "trader16461885203381437",
7236
+ # "fillQuoteSz": "30",
7237
+ # "ts": "1646188520000"
7238
+ # }
7239
+ # ],
7240
+ # "msg": ""
7241
+ # }
7242
+ #
7243
+ data = self.safe_list(response, 'data', [])
7244
+ result = self.safe_dict(data, 0, {})
7245
+ fromCurrencyId = self.safe_string(result, 'baseCcy')
7246
+ toCurrencyId = self.safe_string(result, 'quoteCcy')
7247
+ fromCurrency = None
7248
+ toCurrency = None
7249
+ if fromCurrencyId is not None:
7250
+ fromCurrency = self.currency(fromCurrencyId)
7251
+ if toCurrencyId is not None:
7252
+ toCurrency = self.currency(toCurrencyId)
7253
+ return self.parse_conversion(result, fromCurrency, toCurrency)
7254
+
7255
+ async def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Conversion]:
7256
+ """
7257
+ fetch the users history of conversion trades
7258
+ :see: https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-convert-history
7259
+ :param str [code]: the unified currency code
7260
+ :param int [since]: the earliest time in ms to fetch conversions for
7261
+ :param int [limit]: the maximum number of conversion structures to retrieve
7262
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7263
+ :param int [params.until]: timestamp in ms of the latest conversion to fetch
7264
+ :returns dict[]: a list of `conversion structures <https://docs.ccxt.com/#/?id=conversion-structure>`
7265
+ """
7266
+ await self.load_markets()
7267
+ request = {}
7268
+ request, params = self.handle_until_option('after', request, params)
7269
+ if since is not None:
7270
+ request['before'] = since
7271
+ if limit is not None:
7272
+ request['limit'] = limit
7273
+ response = await self.privateGetAssetConvertHistory(self.extend(request, params))
7274
+ #
7275
+ # {
7276
+ # "code": "0",
7277
+ # "data": [
7278
+ # {
7279
+ # "clTReqId": "",
7280
+ # "instId": "ETH-USDT",
7281
+ # "side": "buy",
7282
+ # "fillPx": "2932.401044",
7283
+ # "baseCcy": "ETH",
7284
+ # "quoteCcy": "USDT",
7285
+ # "fillBaseSz": "0.01023052",
7286
+ # "state": "fullyFilled",
7287
+ # "tradeId": "trader16461885203381437",
7288
+ # "fillQuoteSz": "30",
7289
+ # "ts": "1646188520000"
7290
+ # }
7291
+ # ],
7292
+ # "msg": ""
7293
+ # }
7294
+ #
7295
+ rows = self.safe_list(response, 'data', [])
7296
+ return self.parse_conversions(rows, 'baseCcy', 'quoteCcy', since, limit)
7297
+
7206
7298
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
7207
7299
  #
7208
7300
  # fetchConvertQuote
@@ -7240,6 +7332,22 @@ class okx(Exchange, ImplicitAPI):
7240
7332
  # "ts": "1646188520338"
7241
7333
  # }
7242
7334
  #
7335
+ # fetchConvertTrade, fetchConvertTradeHistory
7336
+ #
7337
+ # {
7338
+ # "clTReqId": "",
7339
+ # "instId": "ETH-USDT",
7340
+ # "side": "buy",
7341
+ # "fillPx": "2932.401044",
7342
+ # "baseCcy": "ETH",
7343
+ # "quoteCcy": "USDT",
7344
+ # "fillBaseSz": "0.01023052",
7345
+ # "state": "fullyFilled",
7346
+ # "tradeId": "trader16461885203381437",
7347
+ # "fillQuoteSz": "30",
7348
+ # "ts": "1646188520000"
7349
+ # }
7350
+ #
7243
7351
  timestamp = self.safe_integer_2(conversion, 'quoteTime', 'ts')
7244
7352
  fromCoin = self.safe_string(conversion, 'baseCcy')
7245
7353
  fromCode = self.safe_currency_code(fromCoin, fromCurrency)
@@ -2699,11 +2699,15 @@ class phemex(Exchange, ImplicitAPI):
2699
2699
  raise ArgumentsRequired(self.id + ' cancelAllOrders() requires a symbol argument')
2700
2700
  await self.load_markets()
2701
2701
  market = self.market(symbol)
2702
+ stop = self.safe_value_2(params, 'stop', 'trigger', False)
2703
+ params = self.omit(params, 'stop', 'trigger')
2702
2704
  request = {
2703
2705
  'symbol': market['id'],
2704
2706
  # 'untriggerred': False, # False to cancel non-conditional orders, True to cancel conditional orders
2705
2707
  # 'text': 'up to 40 characters max',
2706
2708
  }
2709
+ if stop:
2710
+ request['untriggerred'] = stop
2707
2711
  response = None
2708
2712
  if market['settle'] == 'USDT':
2709
2713
  response = await self.privateDeleteGOrdersAll(self.extend(request, params))
@@ -383,8 +383,15 @@ class poloniexfutures(Exchange, ImplicitAPI):
383
383
  marketId = self.safe_string(ticker, 'symbol')
384
384
  symbol = self.safe_symbol(marketId, market)
385
385
  timestampString = self.safe_string(ticker, 'ts')
386
- # check timestamp bcz bug: https://app.travis-ci.com/github/ccxt/ccxt/builds/269959181#L4011
387
- multiplier = 0.00001 if (len(timestampString) == 18) else 0.000001
386
+ # check timestamp bcz bug: https://app.travis-ci.com/github/ccxt/ccxt/builds/269959181#L4011 and also 17 digits occured
387
+ multiplier = None
388
+ if len(timestampString) == 17:
389
+ multiplier = 0.0001
390
+ elif len(timestampString) == 18:
391
+ multiplier = 0.00001
392
+ else:
393
+ # 19 length default
394
+ multiplier = 0.000001
388
395
  timestamp = self.safe_integer_product(ticker, 'ts', multiplier)
389
396
  last = self.safe_string_2(ticker, 'price', 'lastPrice')
390
397
  percentage = Precise.string_mul(self.safe_string(ticker, 'priceChgPct'), '100')
ccxt/async_support/woo.py CHANGED
@@ -69,6 +69,8 @@ class woo(Exchange, ImplicitAPI):
69
69
  'fetchClosedOrders': True,
70
70
  'fetchConvertCurrencies': True,
71
71
  'fetchConvertQuote': True,
72
+ 'fetchConvertTrade': True,
73
+ 'fetchConvertTradeHistory': True,
72
74
  'fetchCurrencies': True,
73
75
  'fetchDepositAddress': True,
74
76
  'fetchDeposits': True,
@@ -2853,6 +2855,88 @@ class woo(Exchange, ImplicitAPI):
2853
2855
  data = self.safe_dict(response, 'data', {})
2854
2856
  return self.parse_conversion(data)
2855
2857
 
2858
+ async def fetch_convert_trade(self, id: str, code: Str = None, params={}) -> Conversion:
2859
+ """
2860
+ fetch the data for a conversion trade
2861
+ :see: https://docs.woo.org/#get-quote-trade
2862
+ :param str id: the id of the trade that you want to fetch
2863
+ :param str [code]: the unified currency code of the conversion trade
2864
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2865
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
2866
+ """
2867
+ await self.load_markets()
2868
+ request = {
2869
+ 'quoteId': id,
2870
+ }
2871
+ response = await self.v3PrivateGetConvertTrade(self.extend(request, params))
2872
+ #
2873
+ # {
2874
+ # "success": True,
2875
+ # "data": {
2876
+ # "quoteId": 12,
2877
+ # "buyAsset": "",
2878
+ # "sellAsset": "",
2879
+ # "buyAmount": 12.11,
2880
+ # "sellAmount": 12.11,
2881
+ # "tradeStatus": 12,
2882
+ # "createdTime": ""
2883
+ # }
2884
+ # }
2885
+ #
2886
+ data = self.safe_dict(response, 'data', {})
2887
+ fromCurrencyId = self.safe_string(data, 'sellAsset')
2888
+ toCurrencyId = self.safe_string(data, 'buyAsset')
2889
+ fromCurrency = None
2890
+ toCurrency = None
2891
+ if fromCurrencyId is not None:
2892
+ fromCurrency = self.currency(fromCurrencyId)
2893
+ if toCurrencyId is not None:
2894
+ toCurrency = self.currency(toCurrencyId)
2895
+ return self.parse_conversion(data, fromCurrency, toCurrency)
2896
+
2897
+ async def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Conversion]:
2898
+ """
2899
+ fetch the users history of conversion trades
2900
+ :see: https://docs.woo.org/#get-quote-trades
2901
+ :param str [code]: the unified currency code
2902
+ :param int [since]: the earliest time in ms to fetch conversions for
2903
+ :param int [limit]: the maximum number of conversion structures to retrieve
2904
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2905
+ :param int [params.until]: timestamp in ms of the latest conversion to fetch
2906
+ :returns dict[]: a list of `conversion structures <https://docs.ccxt.com/#/?id=conversion-structure>`
2907
+ """
2908
+ await self.load_markets()
2909
+ request = {}
2910
+ request, params = self.handle_until_option('endTime', request, params)
2911
+ if since is not None:
2912
+ request['startTime'] = since
2913
+ if limit is not None:
2914
+ request['size'] = limit
2915
+ response = await self.v3PrivateGetConvertTrades(self.extend(request, params))
2916
+ #
2917
+ # {
2918
+ # "success": True,
2919
+ # "data": {
2920
+ # "count": 12,
2921
+ # "tradeVos":[
2922
+ # {
2923
+ # "quoteId": 12,
2924
+ # "buyAsset": "",
2925
+ # "sellAsset": "",
2926
+ # "buyAmount": 12.11,
2927
+ # "sellAmount": 12.11,
2928
+ # "tradeStatus": 12,
2929
+ # "createdTime": ""
2930
+ # }
2931
+ # ...
2932
+ # ]
2933
+ # }
2934
+ # }
2935
+ #
2936
+ data = self.safe_dict(response, 'data', {})
2937
+ rows = self.safe_list(data, 'tradeVos', [])
2938
+ return self.parse_conversions(rows, 'sellAsset', 'buyAsset', since, limit)
2939
+
2856
2940
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
2857
2941
  #
2858
2942
  # fetchConvertQuote
@@ -2877,10 +2961,22 @@ class woo(Exchange, ImplicitAPI):
2877
2961
  # "rftAccepted": 1 # 1 -> success; 2 -> processing; 3 -> fail
2878
2962
  # }
2879
2963
  #
2880
- timestamp = self.safe_integer(conversion, 'expireTimestamp')
2881
- fromCoin = self.safe_string(conversion, 'sellToken')
2882
- fromCode = self.safe_currency_code(fromCoin, fromCurrency)
2883
- to = self.safe_string(conversion, 'buyToken')
2964
+ # fetchConvertTrade, fetchConvertTradeHistory
2965
+ #
2966
+ # {
2967
+ # "quoteId": 12,
2968
+ # "buyAsset": "",
2969
+ # "sellAsset": "",
2970
+ # "buyAmount": 12.11,
2971
+ # "sellAmount": 12.11,
2972
+ # "tradeStatus": 12,
2973
+ # "createdTime": ""
2974
+ # }
2975
+ #
2976
+ timestamp = self.safe_integer_2(conversion, 'expireTimestamp', 'createdTime')
2977
+ fromCurr = self.safe_string_2(conversion, 'sellToken', 'buyAsset')
2978
+ fromCode = self.safe_currency_code(fromCurr, fromCurrency)
2979
+ to = self.safe_string_2(conversion, 'buyToken', 'sellAsset')
2884
2980
  toCode = self.safe_currency_code(to, toCurrency)
2885
2981
  return {
2886
2982
  'info': conversion,
@@ -2888,9 +2984,9 @@ class woo(Exchange, ImplicitAPI):
2888
2984
  'datetime': self.iso8601(timestamp),
2889
2985
  'id': self.safe_string(conversion, 'quoteId'),
2890
2986
  'fromCurrency': fromCode,
2891
- 'fromAmount': self.safe_number(conversion, 'sellQuantity'),
2987
+ 'fromAmount': self.safe_number_2(conversion, 'sellQuantity', 'sellAmount'),
2892
2988
  'toCurrency': toCode,
2893
- 'toAmount': self.safe_number(conversion, 'buyQuantity'),
2989
+ 'toAmount': self.safe_number_2(conversion, 'buyQuantity', 'buyAmount'),
2894
2990
  'price': self.safe_number(conversion, 'buyPrice'),
2895
2991
  'fee': None,
2896
2992
  }
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.2'
7
+ __version__ = '4.3.4'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -5454,6 +5454,25 @@ class Exchange(object):
5454
5454
  def parse_leverage(self, leverage, market: Market = None):
5455
5455
  raise NotSupported(self.id + ' parseLeverage() is not supported yet')
5456
5456
 
5457
+ def parse_conversions(self, conversions: List[Any], fromCurrencyKey: Str = None, toCurrencyKey: Str = None, since: Int = None, limit: Int = None, params={}):
5458
+ conversions = self.to_array(conversions)
5459
+ result = []
5460
+ fromCurrency = None
5461
+ toCurrency = None
5462
+ for i in range(0, len(conversions)):
5463
+ entry = conversions[i]
5464
+ fromId = self.safe_string(entry, fromCurrencyKey)
5465
+ toId = self.safe_string(entry, toCurrencyKey)
5466
+ if fromId is not None:
5467
+ fromCurrency = self.currency(fromId)
5468
+ if toId is not None:
5469
+ toCurrency = self.currency(toId)
5470
+ conversion = self.extend(self.parseConversion(entry, fromCurrency, toCurrency), params)
5471
+ result.append(conversion)
5472
+ sorted = self.sort_by(result, 'timestamp')
5473
+ code = fromCurrency['code'] if (fromCurrency is not None) else None
5474
+ return self.filter_by_currency_since_limit(sorted, code, since, limit)
5475
+
5457
5476
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None):
5458
5477
  raise NotSupported(self.id + ' parseConversion() is not supported yet')
5459
5478