ccxt 4.4.91__py2.py3-none-any.whl → 4.4.93__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 (57) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/lbank.py +2 -1
  3. ccxt/ascendex.py +9 -8
  4. ccxt/async_support/__init__.py +1 -1
  5. ccxt/async_support/ascendex.py +9 -8
  6. ccxt/async_support/base/exchange.py +4 -1
  7. ccxt/async_support/base/ws/client.py +4 -1
  8. ccxt/async_support/binance.py +42 -1
  9. ccxt/async_support/bitmart.py +7 -0
  10. ccxt/async_support/bitmex.py +3 -3
  11. ccxt/async_support/bitvavo.py +7 -1
  12. ccxt/async_support/bybit.py +81 -8
  13. ccxt/async_support/coinbaseexchange.py +53 -0
  14. ccxt/async_support/coincheck.py +45 -4
  15. ccxt/async_support/coinex.py +16 -12
  16. ccxt/async_support/cryptomus.py +30 -52
  17. ccxt/async_support/deribit.py +6 -6
  18. ccxt/async_support/exmo.py +70 -50
  19. ccxt/async_support/htx.py +1 -1
  20. ccxt/async_support/hyperliquid.py +2 -1
  21. ccxt/async_support/krakenfutures.py +1 -1
  22. ccxt/async_support/kucoin.py +12 -14
  23. ccxt/async_support/latoken.py +19 -71
  24. ccxt/async_support/lbank.py +115 -35
  25. ccxt/async_support/okx.py +151 -2
  26. ccxt/async_support/paradex.py +54 -0
  27. ccxt/async_support/phemex.py +3 -3
  28. ccxt/base/exchange.py +69 -30
  29. ccxt/base/types.py +1 -0
  30. ccxt/binance.py +42 -1
  31. ccxt/bitmart.py +7 -0
  32. ccxt/bitmex.py +3 -3
  33. ccxt/bitvavo.py +7 -1
  34. ccxt/bybit.py +81 -8
  35. ccxt/coinbaseexchange.py +53 -0
  36. ccxt/coincheck.py +45 -4
  37. ccxt/coinex.py +16 -12
  38. ccxt/cryptomus.py +30 -52
  39. ccxt/deribit.py +6 -6
  40. ccxt/exmo.py +70 -50
  41. ccxt/htx.py +1 -1
  42. ccxt/hyperliquid.py +2 -1
  43. ccxt/krakenfutures.py +1 -1
  44. ccxt/kucoin.py +12 -14
  45. ccxt/latoken.py +19 -71
  46. ccxt/lbank.py +115 -35
  47. ccxt/okx.py +151 -2
  48. ccxt/paradex.py +54 -0
  49. ccxt/phemex.py +3 -3
  50. ccxt/pro/__init__.py +1 -1
  51. ccxt/pro/bitstamp.py +48 -16
  52. ccxt/pro/bybit.py +5 -5
  53. {ccxt-4.4.91.dist-info → ccxt-4.4.93.dist-info}/METADATA +4 -4
  54. {ccxt-4.4.91.dist-info → ccxt-4.4.93.dist-info}/RECORD +57 -57
  55. {ccxt-4.4.91.dist-info → ccxt-4.4.93.dist-info}/LICENSE.txt +0 -0
  56. {ccxt-4.4.91.dist-info → ccxt-4.4.93.dist-info}/WHEEL +0 -0
  57. {ccxt-4.4.91.dist-info → ccxt-4.4.93.dist-info}/top_level.txt +0 -0
ccxt/kucoin.py CHANGED
@@ -1396,35 +1396,31 @@ class kucoin(Exchange, ImplicitAPI):
1396
1396
  # }
1397
1397
  #
1398
1398
  currenciesData = self.safe_list(response, 'data', [])
1399
+ brokenCurrencies = self.safe_list(self.options, 'brokenCurrencies', ['00', 'OPEN_ERROR', 'HUF', 'BDT'])
1400
+ otherFiats = self.safe_list(self.options, 'fiats', ['KWD', 'IRR', 'PKR'])
1399
1401
  result: dict = {}
1400
1402
  for i in range(0, len(currenciesData)):
1401
1403
  entry = currenciesData[i]
1402
1404
  id = self.safe_string(entry, 'currency')
1403
- name = self.safe_string(entry, 'fullName')
1405
+ if self.in_array(id, brokenCurrencies):
1406
+ continue # skip buggy entries: https://t.me/KuCoin_API/217798
1404
1407
  code = self.safe_currency_code(id)
1405
1408
  networks: dict = {}
1406
1409
  chains = self.safe_list(entry, 'chains', [])
1407
- rawPrecision = self.safe_string(entry, 'precision')
1408
- precision = self.parse_number(self.parse_precision(rawPrecision))
1409
1410
  chainsLength = len(chains)
1410
- if not chainsLength:
1411
- # one buggy coin, which doesn't contain info https://t.me/KuCoin_API/173118
1412
- continue
1413
1411
  for j in range(0, chainsLength):
1414
1412
  chain = chains[j]
1415
1413
  chainId = self.safe_string(chain, 'chainId')
1416
1414
  networkCode = self.network_id_to_code(chainId, code)
1417
- chainWithdrawEnabled = self.safe_bool(chain, 'isWithdrawEnabled', False)
1418
- chainDepositEnabled = self.safe_bool(chain, 'isDepositEnabled', False)
1419
1415
  networks[networkCode] = {
1420
1416
  'info': chain,
1421
1417
  'id': chainId,
1422
1418
  'name': self.safe_string(chain, 'chainName'),
1423
1419
  'code': networkCode,
1424
- 'active': chainWithdrawEnabled and chainDepositEnabled,
1420
+ 'active': None,
1425
1421
  'fee': self.safe_number(chain, 'withdrawalMinFee'),
1426
- 'deposit': chainDepositEnabled,
1427
- 'withdraw': chainWithdrawEnabled,
1422
+ 'deposit': self.safe_bool(chain, 'isDepositEnabled'),
1423
+ 'withdraw': self.safe_bool(chain, 'isWithdrawEnabled'),
1428
1424
  'precision': self.parse_number(self.parse_precision(self.safe_string(chain, 'withdrawPrecision'))),
1429
1425
  'limits': {
1430
1426
  'withdraw': {
@@ -1438,10 +1434,12 @@ class kucoin(Exchange, ImplicitAPI):
1438
1434
  },
1439
1435
  }
1440
1436
  # kucoin has determined 'fiat' currencies with below logic
1441
- isFiat = (rawPrecision == '2') and (chainsLength == 0)
1437
+ rawPrecision = self.safe_string(entry, 'precision')
1438
+ precision = self.parse_number(self.parse_precision(rawPrecision))
1439
+ isFiat = self.in_array(id, otherFiats) or ((rawPrecision == '2') and (chainsLength == 0))
1442
1440
  result[code] = self.safe_currency_structure({
1443
1441
  'id': id,
1444
- 'name': name,
1442
+ 'name': self.safe_string(entry, 'fullName'),
1445
1443
  'code': code,
1446
1444
  'type': 'fiat' if isFiat else 'crypto',
1447
1445
  'precision': precision,
@@ -2627,7 +2625,7 @@ class kucoin(Exchange, ImplicitAPI):
2627
2625
  """
2628
2626
  self.load_markets()
2629
2627
  request: dict = {}
2630
- trigger = self.safe_bool(params, 'stop', False)
2628
+ trigger = self.safe_bool_2(params, 'trigger', 'stop', False)
2631
2629
  hf = None
2632
2630
  hf, params = self.handle_hf_and_params(params)
2633
2631
  params = self.omit(params, 'stop')
ccxt/latoken.py CHANGED
@@ -247,6 +247,8 @@ class latoken(Exchange, ImplicitAPI):
247
247
  'fetchTradingFee': {
248
248
  'method': 'fetchPrivateTradingFee', # or 'fetchPublicTradingFee'
249
249
  },
250
+ 'timeDifference': 0, # the difference between system clock and exchange clock
251
+ 'adjustForTimeDifference': True, # controls the adjustment logic upon instantiation
250
252
  },
251
253
  'features': {
252
254
  'spot': {
@@ -347,39 +349,6 @@ class latoken(Exchange, ImplicitAPI):
347
349
  :param dict [params]: extra parameters specific to the exchange API endpoint
348
350
  :returns dict[]: an array of objects representing market data
349
351
  """
350
- currencies = self.fetch_currencies_from_cache(params)
351
- #
352
- # [
353
- # {
354
- # "id":"1a075819-9e0b-48fc-8784-4dab1d186d6d",
355
- # "status":"CURRENCY_STATUS_ACTIVE",
356
- # "type":"CURRENCY_TYPE_ALTERNATIVE", # CURRENCY_TYPE_CRYPTO, CURRENCY_TYPE_IEO
357
- # "name":"MyCryptoBank",
358
- # "tag":"MCB",
359
- # "description":"",
360
- # "logo":"",
361
- # "decimals":18,
362
- # "created":1572912000000,
363
- # "tier":1,
364
- # "assetClass":"ASSET_CLASS_UNKNOWN",
365
- # "minTransferAmount":0
366
- # },
367
- # {
368
- # "id":"db02758e-2507-46a5-a805-7bc60355b3eb",
369
- # "status":"CURRENCY_STATUS_ACTIVE",
370
- # "type":"CURRENCY_TYPE_FUTURES_CONTRACT",
371
- # "name":"BTC USDT Futures Contract",
372
- # "tag":"BTCUSDT",
373
- # "description":"",
374
- # "logo":"",
375
- # "decimals":8,
376
- # "created":1589459984395,
377
- # "tier":1,
378
- # "assetClass":"ASSET_CLASS_UNKNOWN",
379
- # "minTransferAmount":0
380
- # },
381
- # ]
382
- #
383
352
  response = self.publicGetPair(params)
384
353
  #
385
354
  # [
@@ -401,8 +370,9 @@ class latoken(Exchange, ImplicitAPI):
401
370
  # }
402
371
  # ]
403
372
  #
404
- if self.safe_value(self.options, 'adjustForTimeDifference', True):
373
+ if self.safe_bool(self.options, 'adjustForTimeDifference', False):
405
374
  self.load_time_difference()
375
+ currencies = self.safe_dict(self.options, 'cachedCurrencies', {})
406
376
  currenciesById = self.index_by(currencies, 'id')
407
377
  result = []
408
378
  for i in range(0, len(response)):
@@ -411,11 +381,13 @@ class latoken(Exchange, ImplicitAPI):
411
381
  # the exchange shows them inverted
412
382
  baseId = self.safe_string(market, 'baseCurrency')
413
383
  quoteId = self.safe_string(market, 'quoteCurrency')
414
- baseCurrency = self.safe_value(currenciesById, baseId)
415
- quoteCurrency = self.safe_value(currenciesById, quoteId)
416
- if baseCurrency is not None and quoteCurrency is not None:
417
- base = self.safe_currency_code(self.safe_string(baseCurrency, 'tag'))
418
- quote = self.safe_currency_code(self.safe_string(quoteCurrency, 'tag'))
384
+ baseCurrency = self.safe_dict(currenciesById, baseId)
385
+ quoteCurrency = self.safe_dict(currenciesById, quoteId)
386
+ baseCurrencyInfo = self.safe_dict(baseCurrency, 'info')
387
+ quoteCurrencyInfo = self.safe_dict(quoteCurrency, 'info')
388
+ if baseCurrencyInfo is not None and quoteCurrencyInfo is not None:
389
+ base = self.safe_currency_code(self.safe_string(baseCurrencyInfo, 'tag'))
390
+ quote = self.safe_currency_code(self.safe_string(quoteCurrencyInfo, 'tag'))
419
391
  lowercaseQuote = quote.lower()
420
392
  capitalizedQuote = self.capitalize(lowercaseQuote)
421
393
  status = self.safe_string(market, 'status')
@@ -470,28 +442,13 @@ class latoken(Exchange, ImplicitAPI):
470
442
  })
471
443
  return result
472
444
 
473
- def fetch_currencies_from_cache(self, params={}):
474
- # self method is now redundant
475
- # currencies are now fetched before markets
476
- options = self.safe_value(self.options, 'fetchCurrencies', {})
477
- timestamp = self.safe_integer(options, 'timestamp')
478
- expires = self.safe_integer(options, 'expires', 1000)
479
- now = self.milliseconds()
480
- if (timestamp is None) or ((now - timestamp) > expires):
481
- response = self.publicGetCurrency(params)
482
- self.options['fetchCurrencies'] = self.extend(options, {
483
- 'response': response,
484
- 'timestamp': now,
485
- })
486
- return self.safe_value(self.options['fetchCurrencies'], 'response')
487
-
488
445
  def fetch_currencies(self, params={}) -> Currencies:
489
446
  """
490
447
  fetches all available currencies on an exchange
491
448
  :param dict [params]: extra parameters specific to the exchange API endpoint
492
449
  :returns dict: an associative dictionary of currencies
493
450
  """
494
- response = self.fetch_currencies_from_cache(params)
451
+ response = self.publicGetCurrency(params)
495
452
  #
496
453
  # [
497
454
  # {
@@ -530,27 +487,18 @@ class latoken(Exchange, ImplicitAPI):
530
487
  id = self.safe_string(currency, 'id')
531
488
  tag = self.safe_string(currency, 'tag')
532
489
  code = self.safe_currency_code(tag)
533
- fee = self.safe_number(currency, 'fee')
534
490
  currencyType = self.safe_string(currency, 'type')
535
- type = None
536
- if currencyType == 'CURRENCY_TYPE_ALTERNATIVE':
537
- type = 'other'
538
- else:
539
- # CURRENCY_TYPE_CRYPTO and CURRENCY_TYPE_IEO are all cryptos
540
- type = 'crypto'
541
- status = self.safe_string(currency, 'status')
542
- active = (status == 'CURRENCY_STATUS_ACTIVE')
543
- name = self.safe_string(currency, 'name')
544
- result[code] = {
491
+ isCrypto = (currencyType == 'CURRENCY_TYPE_CRYPTO' or currencyType == 'CURRENCY_TYPE_IEO')
492
+ result[code] = self.safe_currency_structure({
545
493
  'id': id,
546
494
  'code': code,
547
495
  'info': currency,
548
- 'name': name,
549
- 'type': type,
550
- 'active': active,
496
+ 'name': self.safe_string(currency, 'name'),
497
+ 'type': 'crypto' if isCrypto else 'other',
498
+ 'active': self.safe_string(currency, 'status') == 'CURRENCY_STATUS_ACTIVE',
551
499
  'deposit': None,
552
500
  'withdraw': None,
553
- 'fee': fee,
501
+ 'fee': self.safe_number(currency, 'fee'),
554
502
  'precision': self.parse_number(self.parse_precision(self.safe_string(currency, 'decimals'))),
555
503
  'limits': {
556
504
  'amount': {
@@ -563,7 +511,7 @@ class latoken(Exchange, ImplicitAPI):
563
511
  },
564
512
  },
565
513
  'networks': {},
566
- }
514
+ })
567
515
  return result
568
516
 
569
517
  def fetch_balance(self, params={}) -> Balances:
ccxt/lbank.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.lbank import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Any, Balances, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction
9
+ from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -61,6 +61,7 @@ class lbank(Exchange, ImplicitAPI):
61
61
  'fetchClosedOrders': False,
62
62
  'fetchCrossBorrowRate': False,
63
63
  'fetchCrossBorrowRates': False,
64
+ 'fetchCurrencies': True,
64
65
  'fetchDepositAddress': True,
65
66
  'fetchDepositAddresses': False,
66
67
  'fetchDepositAddressesByNetwork': False,
@@ -135,7 +136,8 @@ class lbank(Exchange, ImplicitAPI):
135
136
  'currencyPairs': 2.5,
136
137
  'accuracy': 2.5,
137
138
  'usdToCny': 2.5,
138
- 'withdrawConfigs': 2.5,
139
+ 'assetConfigs': 2.5,
140
+ 'withdrawConfigs': 2.5 * 1.5, # frequently rate-limits, so increase self endpoint RL
139
141
  'timestamp': 2.5,
140
142
  'ticker/24hr': 2.5,
141
143
  'ticker': 2.5,
@@ -221,6 +223,7 @@ class lbank(Exchange, ImplicitAPI):
221
223
  },
222
224
  },
223
225
  'commonCurrencies': {
226
+ 'XBT': 'XBT', # not BTC!
224
227
  'HIT': 'Hiver',
225
228
  'VET_ERC20': 'VEN',
226
229
  'PNT': 'Penta',
@@ -288,21 +291,12 @@ class lbank(Exchange, ImplicitAPI):
288
291
  # ptx: 1
289
292
  # }
290
293
  },
291
- 'inverse-networks': {
294
+ 'networksById': {
292
295
  'erc20': 'ERC20',
293
296
  'trc20': 'TRC20',
294
- 'omni': 'OMNI',
295
- 'asa': 'ASA',
296
- 'bep20(bsc)': 'BSC',
297
- 'bep20': 'BSC',
298
- 'heco': 'HT',
299
- 'bep2': 'BNB',
300
- 'btc': 'BTC',
301
- 'dogecoin': 'DOGE',
302
- 'matic': 'MATIC',
303
- 'oec': 'OEC',
304
- 'btctron': 'BTCTRON',
305
- 'xrp': 'XRP',
297
+ 'TRX': 'TRC20',
298
+ 'bep20(bsc)': 'BEP20',
299
+ 'bep20': 'BEP20',
306
300
  },
307
301
  'defaultNetworks': {
308
302
  'USDT': 'TRC20',
@@ -423,6 +417,104 @@ class lbank(Exchange, ImplicitAPI):
423
417
  #
424
418
  return self.safe_integer(response, 'data')
425
419
 
420
+ def fetch_currencies(self, params={}) -> Currencies:
421
+ """
422
+ fetches all available currencies on an exchange
423
+ :param dict [params]: extra parameters specific to the exchange API endpoint
424
+ :returns dict: an associative dictionary of currencies
425
+ """
426
+ response = self.spotPublicGetWithdrawConfigs(params)
427
+ #
428
+ # {
429
+ # "msg": "Success",
430
+ # "result": "true",
431
+ # "data": [
432
+ # {
433
+ # "amountScale": "4",
434
+ # "chain": "bep20(bsc)",
435
+ # "assetCode": "usdt",
436
+ # "min": "10",
437
+ # "transferAmtScale": "4",
438
+ # "canWithDraw": True,
439
+ # "fee": "0.0000",
440
+ # "minTransfer": "0.0001",
441
+ # "type": "1"
442
+ # },
443
+ # {
444
+ # "amountScale": "4",
445
+ # "chain": "trc20",
446
+ # "assetCode": "usdt",
447
+ # "min": "1",
448
+ # "transferAmtScale": "4",
449
+ # "canWithDraw": True,
450
+ # "fee": "1.0000",
451
+ # "minTransfer": "0.0001",
452
+ # "type": "1"
453
+ # },
454
+ # ...
455
+ # ],
456
+ # "error_code": "0",
457
+ # "ts": "1747973911431"
458
+ # }
459
+ #
460
+ currenciesData = self.safe_list(response, 'data', [])
461
+ grouped = self.group_by(currenciesData, 'assetCode')
462
+ groupedKeys = list(grouped.keys())
463
+ result: dict = {}
464
+ for i in range(0, len(groupedKeys)):
465
+ id = str((groupedKeys[i])) # some currencies are numeric
466
+ code = self.safe_currency_code(id)
467
+ networksRaw = grouped[id]
468
+ networks = {}
469
+ for j in range(0, len(networksRaw)):
470
+ networkEntry = networksRaw[j]
471
+ networkId = self.safe_string(networkEntry, 'chain')
472
+ networkCode = self.network_id_to_code(networkId)
473
+ networks[networkCode] = {
474
+ 'id': networkId,
475
+ 'network': networkCode,
476
+ 'limits': {
477
+ 'withdraw': {
478
+ 'min': self.safe_number(networkEntry, 'min'),
479
+ 'max': None,
480
+ },
481
+ 'deposit': {
482
+ 'min': self.safe_number(networkEntry, 'minTransfer'),
483
+ 'max': None,
484
+ },
485
+ },
486
+ 'active': None,
487
+ 'deposit': None,
488
+ 'withdraw': self.safe_bool(networkEntry, 'canWithDraw'),
489
+ 'fee': self.safe_number(networkEntry, 'fee'),
490
+ 'precision': self.parse_number(self.parse_precision(self.safe_string(networkEntry, 'transferAmtScale'))),
491
+ 'info': networkEntry,
492
+ }
493
+ result[code] = self.safe_currency_structure({
494
+ 'id': id,
495
+ 'code': code,
496
+ 'precision': None,
497
+ 'type': None,
498
+ 'name': None,
499
+ 'active': None,
500
+ 'deposit': None,
501
+ 'withdraw': None,
502
+ 'fee': None,
503
+ 'limits': {
504
+ 'withdraw': {
505
+ 'min': None,
506
+ 'max': None,
507
+ },
508
+ 'deposit': {
509
+ 'min': None,
510
+ 'max': None,
511
+ },
512
+ },
513
+ 'networks': networks,
514
+ 'info': networksRaw,
515
+ })
516
+ return result
517
+
426
518
  def fetch_markets(self, params={}) -> List[Market]:
427
519
  """
428
520
  retrieves data on all markets for lbank
@@ -582,7 +674,7 @@ class lbank(Exchange, ImplicitAPI):
582
674
  'active': True,
583
675
  'contract': True,
584
676
  'linear': True,
585
- 'inverse': None,
677
+ 'inverse': False,
586
678
  'contractSize': self.safe_number(market, 'volumeMultiple'),
587
679
  'expiry': None,
588
680
  'expiryDatetime': None,
@@ -2097,13 +2189,10 @@ class lbank(Exchange, ImplicitAPI):
2097
2189
  result = self.safe_value(response, 'data')
2098
2190
  address = self.safe_string(result, 'address')
2099
2191
  tag = self.safe_string(result, 'memo')
2100
- networkId = self.safe_string(result, 'netWork')
2101
- inverseNetworks = self.safe_value(self.options, 'inverse-networks', {})
2102
- networkCode = self.safe_string_upper(inverseNetworks, networkId, networkId)
2103
2192
  return {
2104
2193
  'info': response,
2105
2194
  'currency': code,
2106
- 'network': networkCode,
2195
+ 'network': self.network_id_to_code(self.safe_string(result, 'netWork')),
2107
2196
  'address': address,
2108
2197
  'tag': tag,
2109
2198
  }
@@ -2137,12 +2226,10 @@ class lbank(Exchange, ImplicitAPI):
2137
2226
  result = self.safe_value(response, 'data')
2138
2227
  address = self.safe_string(result, 'address')
2139
2228
  tag = self.safe_string(result, 'memo')
2140
- inverseNetworks = self.safe_value(self.options, 'inverse-networks', {})
2141
- networkCode = self.safe_string_upper(inverseNetworks, network, network)
2142
2229
  return {
2143
2230
  'info': response,
2144
2231
  'currency': code,
2145
- 'network': networkCode, # will be None if not specified in request
2232
+ 'network': None,
2146
2233
  'address': address,
2147
2234
  'tag': tag,
2148
2235
  }
@@ -2262,9 +2349,6 @@ class lbank(Exchange, ImplicitAPI):
2262
2349
  type = 'withdrawal'
2263
2350
  txid = self.safe_string(transaction, 'txId')
2264
2351
  timestamp = self.safe_integer_2(transaction, 'insertTime', 'applyTime')
2265
- networks = self.safe_value(self.options, 'inverse-networks', {})
2266
- networkId = self.safe_string(transaction, 'networkName')
2267
- network = self.safe_string(networks, networkId, networkId)
2268
2352
  address = self.safe_string(transaction, 'address')
2269
2353
  addressFrom = None
2270
2354
  addressTo = None
@@ -2289,7 +2373,7 @@ class lbank(Exchange, ImplicitAPI):
2289
2373
  'txid': txid,
2290
2374
  'timestamp': timestamp,
2291
2375
  'datetime': self.iso8601(timestamp),
2292
- 'network': network,
2376
+ 'network': self.network_id_to_code(self.safe_string(transaction, 'networkName')),
2293
2377
  'address': address,
2294
2378
  'addressTo': addressTo,
2295
2379
  'addressFrom': addressFrom,
@@ -2482,10 +2566,9 @@ class lbank(Exchange, ImplicitAPI):
2482
2566
  withdrawFees[code] = {}
2483
2567
  for j in range(0, len(networkList)):
2484
2568
  networkEntry = networkList[j]
2485
- networkId = self.safe_string(networkEntry, 'name')
2486
- networkCode = self.safe_string(self.options['inverse-networks'], networkId, networkId)
2487
2569
  fee = self.safe_number(networkEntry, 'withdrawFee')
2488
2570
  if fee is not None:
2571
+ networkCode = self.network_id_to_code(self.safe_string(networkEntry, 'name'))
2489
2572
  withdrawFees[code][networkCode] = fee
2490
2573
  return {
2491
2574
  'withdraw': withdrawFees,
@@ -2533,8 +2616,7 @@ class lbank(Exchange, ImplicitAPI):
2533
2616
  if canWithdraw == 'true':
2534
2617
  currencyId = self.safe_string(item, 'assetCode')
2535
2618
  codeInner = self.safe_currency_code(currencyId)
2536
- chain = self.safe_string(item, 'chain')
2537
- network = self.safe_string(self.options['inverse-networks'], chain, chain)
2619
+ network = self.network_id_to_code(self.safe_string(item, 'chain'))
2538
2620
  if network is None:
2539
2621
  network = codeInner
2540
2622
  fee = self.safe_string(item, 'fee')
@@ -2675,8 +2757,7 @@ class lbank(Exchange, ImplicitAPI):
2675
2757
  else:
2676
2758
  resultCodeInfo = result[code]['info']
2677
2759
  resultCodeInfo.append(fee)
2678
- chain = self.safe_string(fee, 'chain')
2679
- networkCode = self.safe_string(self.options['inverse-networks'], chain, chain)
2760
+ networkCode = self.network_id_to_code(self.safe_string(fee, 'chain'))
2680
2761
  if networkCode is not None:
2681
2762
  result[code]['networks'][networkCode] = {
2682
2763
  'withdraw': {
@@ -2726,8 +2807,7 @@ class lbank(Exchange, ImplicitAPI):
2726
2807
  networkList = self.safe_value(fee, 'networkList', [])
2727
2808
  for j in range(0, len(networkList)):
2728
2809
  networkEntry = networkList[j]
2729
- networkId = self.safe_string(networkEntry, 'name')
2730
- networkCode = self.safe_string_upper(self.options['inverse-networks'], networkId, networkId)
2810
+ networkCode = self.network_id_to_code(self.safe_string(networkEntry, 'name'))
2731
2811
  withdrawFee = self.safe_number(networkEntry, 'withdrawFee')
2732
2812
  isDefault = self.safe_value(networkEntry, 'isDefault')
2733
2813
  if withdrawFee is not None:
ccxt/okx.py CHANGED
@@ -80,6 +80,7 @@ class okx(Exchange, ImplicitAPI):
80
80
  'createTriggerOrder': True,
81
81
  'editOrder': True,
82
82
  'fetchAccounts': True,
83
+ 'fetchAllGreeks': True,
83
84
  'fetchBalance': True,
84
85
  'fetchBidsAsks': None,
85
86
  'fetchBorrowInterest': True,
@@ -3613,6 +3614,84 @@ class okx(Exchange, ImplicitAPI):
3613
3614
  # "uTime": "1621910749815"
3614
3615
  # }
3615
3616
  #
3617
+ # watchOrders & fetchClosedOrders
3618
+ #
3619
+ # {
3620
+ # "algoClOrdId": "",
3621
+ # "algoId": "",
3622
+ # "attachAlgoClOrdId": "",
3623
+ # "attachAlgoOrds": [],
3624
+ # "cancelSource": "",
3625
+ # "cancelSourceReason": "", # not present in WS, but present in fetchClosedOrders
3626
+ # "category": "normal",
3627
+ # "ccy": "", # empty in WS, but eg. `USDT` in fetchClosedOrders
3628
+ # "clOrdId": "",
3629
+ # "cTime": "1751705801423",
3630
+ # "feeCcy": "USDT",
3631
+ # "instId": "LINK-USDT-SWAP",
3632
+ # "instType": "SWAP",
3633
+ # "isTpLimit": "false",
3634
+ # "lever": "3",
3635
+ # "linkedAlgoOrd": {"algoId": ""},
3636
+ # "ordId": "2657625147249614848",
3637
+ # "ordType": "limit",
3638
+ # "posSide": "net",
3639
+ # "px": "13.142",
3640
+ # "pxType": "",
3641
+ # "pxUsd": "",
3642
+ # "pxVol": "",
3643
+ # "quickMgnType": "",
3644
+ # "rebate": "0",
3645
+ # "rebateCcy": "USDT",
3646
+ # "reduceOnly": "true",
3647
+ # "side": "sell",
3648
+ # "slOrdPx": "",
3649
+ # "slTriggerPx": "",
3650
+ # "slTriggerPxType": "",
3651
+ # "source": "",
3652
+ # "stpId": "",
3653
+ # "stpMode": "cancel_maker",
3654
+ # "sz": "0.1",
3655
+ # "tag": "",
3656
+ # "tdMode": "isolated",
3657
+ # "tgtCcy": "",
3658
+ # "tpOrdPx": "",
3659
+ # "tpTriggerPx": "",
3660
+ # "tpTriggerPxType": "",
3661
+ # "uTime": "1751705807467",
3662
+ # "reqId": "", # field present only in WS
3663
+ # "msg": "", # field present only in WS
3664
+ # "amendResult": "", # field present only in WS
3665
+ # "amendSource": "", # field present only in WS
3666
+ # "code": "0", # field present only in WS
3667
+ # "fillFwdPx": "", # field present only in WS
3668
+ # "fillMarkVol": "", # field present only in WS
3669
+ # "fillPxUsd": "", # field present only in WS
3670
+ # "fillPxVol": "", # field present only in WS
3671
+ # "lastPx": "13.142", # field present only in WS
3672
+ # "notionalUsd": "1.314515408", # field present only in WS
3673
+ #
3674
+ # #### these below fields are empty on first omit from websocket, because of "creation" event. however, if order is executed, it also immediately sends another update with these fields filled ###
3675
+ #
3676
+ # "pnl": "-0.0001",
3677
+ # "accFillSz": "0.1",
3678
+ # "avgPx": "13.142",
3679
+ # "state": "filled",
3680
+ # "fee": "-0.00026284",
3681
+ # "fillPx": "13.142",
3682
+ # "tradeId": "293429690",
3683
+ # "fillSz": "0.1",
3684
+ # "fillTime": "1751705807467",
3685
+ # "fillNotionalUsd": "1.314515408", # field present only in WS
3686
+ # "fillPnl": "-0.0001", # field present only in WS
3687
+ # "fillFee": "-0.00026284", # field present only in WS
3688
+ # "fillFeeCcy": "USDT", # field present only in WS
3689
+ # "execType": "M", # field present only in WS
3690
+ # "fillMarkPx": "13.141", # field present only in WS
3691
+ # "fillIdxPx": "13.147" # field present only in WS
3692
+ # }
3693
+ #
3694
+ #
3616
3695
  # Algo Order fetchOpenOrders, fetchCanceledOrders, fetchClosedOrders
3617
3696
  #
3618
3697
  # {
@@ -4893,7 +4972,7 @@ class okx(Exchange, ImplicitAPI):
4893
4972
  fee = self.safe_string(params, 'fee')
4894
4973
  if fee is None:
4895
4974
  currencies = self.fetch_currencies()
4896
- self.currencies = self.deep_extend(self.currencies, currencies)
4975
+ self.currencies = self.map_to_safe_map(self.deep_extend(self.currencies, currencies))
4897
4976
  targetNetwork = self.safe_dict(currency['networks'], self.network_id_to_code(network), {})
4898
4977
  fee = self.safe_string(targetNetwork, 'fee')
4899
4978
  if fee is None:
@@ -6843,7 +6922,7 @@ class okx(Exchange, ImplicitAPI):
6843
6922
 
6844
6923
  def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
6845
6924
  """
6846
- fetch the interest owed by the user for borrowing currency for margin trading
6925
+ fetch the interest owed b the user for borrowing currency for margin trading
6847
6926
 
6848
6927
  https://www.okx.com/docs-v5/en/#rest-api-account-get-interest-accrued-data
6849
6928
 
@@ -7547,6 +7626,76 @@ class okx(Exchange, ImplicitAPI):
7547
7626
  return self.parse_greeks(entry, market)
7548
7627
  return None
7549
7628
 
7629
+ def fetch_all_greeks(self, symbols: Strings = None, params={}) -> List[Greeks]:
7630
+ """
7631
+ fetches all option contracts greeks, financial metrics used to measure the factors that affect the price of an options contract
7632
+
7633
+ https://www.okx.com/docs-v5/en/#public-data-rest-api-get-option-market-data
7634
+
7635
+ :param str[] [symbols]: unified symbols of the markets to fetch greeks for, all markets are returned if not assigned
7636
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7637
+ :param str params['uly']: Underlying, either uly or instFamily is required
7638
+ :param str params['instFamily']: Instrument family, either uly or instFamily is required
7639
+ :returns dict: a `greeks structure <https://docs.ccxt.com/#/?id=greeks-structure>`
7640
+ """
7641
+ self.load_markets()
7642
+ request: dict = {}
7643
+ symbols = self.market_symbols(symbols, None, True, True, True)
7644
+ symbolsLength = None
7645
+ if symbols is not None:
7646
+ symbolsLength = len(symbols)
7647
+ if (symbols is None) or (symbolsLength != 1):
7648
+ uly = self.safe_string(params, 'uly')
7649
+ if uly is not None:
7650
+ request['uly'] = uly
7651
+ instFamily = self.safe_string(params, 'instFamily')
7652
+ if instFamily is not None:
7653
+ request['instFamily'] = instFamily
7654
+ if (uly is None) and (instFamily is None):
7655
+ raise BadRequest(self.id + ' fetchAllGreeks() requires either a uly or instFamily parameter')
7656
+ market = None
7657
+ if symbols is not None:
7658
+ if symbolsLength == 1:
7659
+ market = self.market(symbols[0])
7660
+ marketId = market['id']
7661
+ optionParts = marketId.split('-')
7662
+ request['uly'] = market['info']['uly']
7663
+ request['instFamily'] = market['info']['instFamily']
7664
+ request['expTime'] = self.safe_string(optionParts, 2)
7665
+ params = self.omit(params, ['uly', 'instFamily'])
7666
+ response = self.publicGetPublicOptSummary(self.extend(request, params))
7667
+ #
7668
+ # {
7669
+ # "code": "0",
7670
+ # "data": [
7671
+ # {
7672
+ # "askVol": "0",
7673
+ # "bidVol": "0",
7674
+ # "delta": "0.5105464486882039",
7675
+ # "deltaBS": "0.7325502184143025",
7676
+ # "fwdPx": "37675.80158694987186",
7677
+ # "gamma": "-0.13183515090501083",
7678
+ # "gammaBS": "0.000024139685826358558",
7679
+ # "instId": "BTC-USD-240329-32000-C",
7680
+ # "instType": "OPTION",
7681
+ # "lever": "4.504428015946619",
7682
+ # "markVol": "0.5916253554539876",
7683
+ # "realVol": "0",
7684
+ # "theta": "-0.0004202992014012855",
7685
+ # "thetaBS": "-18.52354631567909",
7686
+ # "ts": "1699586421976",
7687
+ # "uly": "BTC-USD",
7688
+ # "vega": "0.0020207455080045846",
7689
+ # "vegaBS": "74.44022302387287",
7690
+ # "volLv": "0.5948549730405797"
7691
+ # },
7692
+ # ],
7693
+ # "msg": ""
7694
+ # }
7695
+ #
7696
+ data = self.safe_list(response, 'data', [])
7697
+ return self.parse_all_greeks(data, symbols)
7698
+
7550
7699
  def parse_greeks(self, greeks: dict, market: Market = None) -> Greeks:
7551
7700
  #
7552
7701
  # {