ccxt 4.4.86__py2.py3-none-any.whl → 4.4.88__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 (58) hide show
  1. ccxt/__init__.py +5 -1
  2. ccxt/abstract/modetrade.py +119 -0
  3. ccxt/abstract/okxus.py +349 -0
  4. ccxt/async_support/__init__.py +5 -1
  5. ccxt/async_support/base/exchange.py +8 -5
  6. ccxt/async_support/binance.py +1 -1
  7. ccxt/async_support/bitteam.py +31 -0
  8. ccxt/async_support/bybit.py +19 -57
  9. ccxt/async_support/coinmetro.py +3 -0
  10. ccxt/async_support/gate.py +91 -73
  11. ccxt/async_support/htx.py +10 -8
  12. ccxt/async_support/hyperliquid.py +32 -16
  13. ccxt/async_support/kraken.py +5 -8
  14. ccxt/async_support/modetrade.py +2727 -0
  15. ccxt/async_support/okx.py +90 -3
  16. ccxt/async_support/okxus.py +54 -0
  17. ccxt/async_support/paradex.py +4 -1
  18. ccxt/async_support/phemex.py +4 -6
  19. ccxt/async_support/poloniex.py +172 -159
  20. ccxt/async_support/probit.py +18 -47
  21. ccxt/async_support/timex.py +5 -10
  22. ccxt/async_support/vertex.py +3 -4
  23. ccxt/async_support/whitebit.py +41 -11
  24. ccxt/async_support/woo.py +101 -75
  25. ccxt/async_support/woofipro.py +25 -20
  26. ccxt/async_support/xt.py +31 -41
  27. ccxt/base/exchange.py +13 -9
  28. ccxt/binance.py +1 -1
  29. ccxt/bitteam.py +31 -0
  30. ccxt/bybit.py +19 -57
  31. ccxt/coinmetro.py +3 -0
  32. ccxt/gate.py +91 -73
  33. ccxt/htx.py +10 -8
  34. ccxt/hyperliquid.py +32 -16
  35. ccxt/kraken.py +5 -8
  36. ccxt/modetrade.py +2727 -0
  37. ccxt/okx.py +90 -3
  38. ccxt/okxus.py +54 -0
  39. ccxt/paradex.py +4 -1
  40. ccxt/phemex.py +4 -6
  41. ccxt/poloniex.py +172 -159
  42. ccxt/pro/__init__.py +69 -1
  43. ccxt/pro/modetrade.py +1271 -0
  44. ccxt/pro/okxus.py +38 -0
  45. ccxt/probit.py +18 -47
  46. ccxt/test/tests_async.py +17 -1
  47. ccxt/test/tests_sync.py +17 -1
  48. ccxt/timex.py +5 -10
  49. ccxt/vertex.py +3 -4
  50. ccxt/whitebit.py +41 -11
  51. ccxt/woo.py +100 -75
  52. ccxt/woofipro.py +24 -20
  53. ccxt/xt.py +31 -41
  54. {ccxt-4.4.86.dist-info → ccxt-4.4.88.dist-info}/METADATA +18 -6
  55. {ccxt-4.4.86.dist-info → ccxt-4.4.88.dist-info}/RECORD +58 -50
  56. {ccxt-4.4.86.dist-info → ccxt-4.4.88.dist-info}/LICENSE.txt +0 -0
  57. {ccxt-4.4.86.dist-info → ccxt-4.4.88.dist-info}/WHEEL +0 -0
  58. {ccxt-4.4.86.dist-info → ccxt-4.4.88.dist-info}/top_level.txt +0 -0
ccxt/pro/okxus.py ADDED
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ from ccxt.pro.okx import okx
7
+ from ccxt.base.types import Any
8
+
9
+
10
+ class okxus(okx):
11
+
12
+ def describe(self) -> Any:
13
+ return self.deep_extend(super(okxus, self).describe(), {
14
+ 'id': 'okxus',
15
+ 'name': 'OKX(US)',
16
+ 'hostname': 'us.okx.com',
17
+ 'urls': {
18
+ 'api': {
19
+ 'rest': 'https://{hostname}',
20
+ 'ws': 'wss://wsus.okx.com:8443/ws/v5',
21
+ },
22
+ 'www': 'https://app.okx.com',
23
+ 'doc': 'https://app.okx.com/docs-v5/en/#overview',
24
+ 'fees': 'https://app.okx.com/pages/products/fees.html',
25
+ 'referral': {
26
+ 'url': 'https://www.app.okx.com/join/CCXT2023',
27
+ 'discount': 0.2,
28
+ },
29
+ 'test': {
30
+ 'ws': 'wss://wsuspap.okx.com:8443/ws/v5',
31
+ },
32
+ },
33
+ 'has': {
34
+ 'swap': False,
35
+ 'future': False,
36
+ 'option': False,
37
+ },
38
+ })
ccxt/probit.py CHANGED
@@ -483,32 +483,23 @@ class probit(Exchange, ImplicitAPI):
483
483
  # ]
484
484
  # }
485
485
  #
486
- currencies = self.safe_value(response, 'data', [])
486
+ currencies = self.safe_list(response, 'data', [])
487
487
  result: dict = {}
488
488
  for i in range(0, len(currencies)):
489
489
  currency = currencies[i]
490
490
  id = self.safe_string(currency, 'id')
491
491
  code = self.safe_currency_code(id)
492
- displayName = self.safe_value(currency, 'display_name')
492
+ displayName = self.safe_dict(currency, 'display_name')
493
493
  name = self.safe_string(displayName, 'en-us')
494
- platforms = self.safe_value(currency, 'platform', [])
494
+ platforms = self.safe_list(currency, 'platform', [])
495
495
  platformsByPriority = self.sort_by(platforms, 'priority')
496
- platform = None
497
496
  networkList: dict = {}
498
497
  for j in range(0, len(platformsByPriority)):
499
498
  network = platformsByPriority[j]
500
499
  idInner = self.safe_string(network, 'id')
501
500
  networkCode = self.network_id_to_code(idInner)
502
- currentDepositSuspended = self.safe_value(network, 'deposit_suspended')
503
- currentWithdrawalSuspended = self.safe_value(network, 'withdrawal_suspended')
504
- currentDeposit = not currentDepositSuspended
505
- currentWithdraw = not currentWithdrawalSuspended
506
- currentActive = currentDeposit and currentWithdraw
507
- if currentActive:
508
- platform = network
509
- precision = self.parse_precision(self.safe_string(network, 'precision'))
510
- withdrawFee = self.safe_value(network, 'withdrawal_fee', [])
511
- networkFee = self.safe_value(withdrawFee, 0, {})
501
+ withdrawFee = self.safe_list(network, 'withdrawal_fee', [])
502
+ networkFee = self.safe_dict(withdrawFee, 0, {})
512
503
  for k in range(0, len(withdrawFee)):
513
504
  withdrawPlatform = withdrawFee[k]
514
505
  feeCurrencyId = self.safe_string(withdrawPlatform, 'currency_id')
@@ -518,11 +509,11 @@ class probit(Exchange, ImplicitAPI):
518
509
  networkList[networkCode] = {
519
510
  'id': idInner,
520
511
  'network': networkCode,
521
- 'active': currentActive,
522
- 'deposit': currentDeposit,
523
- 'withdraw': currentWithdraw,
512
+ 'active': None,
513
+ 'deposit': not self.safe_bool(network, 'deposit_suspended'),
514
+ 'withdraw': not self.safe_bool(network, 'withdrawal_suspended'),
524
515
  'fee': self.safe_number(networkFee, 'amount'),
525
- 'precision': self.parse_number(precision),
516
+ 'precision': self.parse_number(self.parse_precision(self.safe_string(network, 'precision'))),
526
517
  'limits': {
527
518
  'withdraw': {
528
519
  'min': self.safe_number(network, 'min_withdrawal_amount'),
@@ -535,53 +526,33 @@ class probit(Exchange, ImplicitAPI):
535
526
  },
536
527
  'info': network,
537
528
  }
538
- if platform is None:
539
- platform = self.safe_value(platformsByPriority, 0, {})
540
- depositSuspended = self.safe_value(platform, 'deposit_suspended')
541
- withdrawalSuspended = self.safe_value(platform, 'withdrawal_suspended')
542
- deposit = not depositSuspended
543
- withdraw = not withdrawalSuspended
544
- active = deposit and withdraw
545
- withdrawalFees = self.safe_value(platform, 'withdrawal_fee', {})
546
- fees = []
547
- # sometimes the withdrawal fee is an empty object
548
- # [{'amount': '0.015', 'priority': 1, 'currency_id': 'ETH'}, {}]
549
- for j in range(0, len(withdrawalFees)):
550
- withdrawalFeeInner = withdrawalFees[j]
551
- amount = self.safe_number(withdrawalFeeInner, 'amount')
552
- priority = self.safe_integer(withdrawalFeeInner, 'priority')
553
- if (amount is not None) and (priority is not None):
554
- fees.append(withdrawalFeeInner)
555
- withdrawalFeesByPriority = self.sort_by(fees, 'priority')
556
- withdrawalFee = self.safe_value(withdrawalFeesByPriority, 0, {})
557
- fee = self.safe_number(withdrawalFee, 'amount')
558
- result[code] = {
529
+ result[code] = self.safe_currency_structure({
559
530
  'id': id,
560
531
  'code': code,
561
532
  'info': currency,
562
533
  'name': name,
563
- 'active': active,
564
- 'deposit': deposit,
565
- 'withdraw': withdraw,
534
+ 'active': None,
535
+ 'deposit': None,
536
+ 'withdraw': None,
566
537
  'type': 'crypto',
567
- 'fee': fee,
568
- 'precision': self.parse_number(self.parse_precision(self.safe_string(platform, 'precision'))),
538
+ 'fee': None,
539
+ 'precision': None,
569
540
  'limits': {
570
541
  'amount': {
571
542
  'min': None,
572
543
  'max': None,
573
544
  },
574
545
  'deposit': {
575
- 'min': self.safe_number(platform, 'min_deposit_amount'),
546
+ 'min': None,
576
547
  'max': None,
577
548
  },
578
549
  'withdraw': {
579
- 'min': self.safe_number(platform, 'min_withdrawal_amount'),
550
+ 'min': None,
580
551
  'max': None,
581
552
  },
582
553
  },
583
554
  'networks': networkList,
584
- }
555
+ })
585
556
  return result
586
557
 
587
558
  def parse_balance(self, response) -> Balances:
ccxt/test/tests_async.py CHANGED
@@ -1173,7 +1173,7 @@ class testMainClass:
1173
1173
  # -----------------------------------------------------------------------------
1174
1174
  # --- Init of brokerId tests functions-----------------------------------------
1175
1175
  # -----------------------------------------------------------------------------
1176
- promises = [self.test_binance(), self.test_okx(), self.test_cryptocom(), self.test_bybit(), self.test_kucoin(), self.test_kucoinfutures(), self.test_bitget(), self.test_mexc(), self.test_htx(), self.test_woo(), self.test_bitmart(), self.test_coinex(), self.test_bingx(), self.test_phemex(), self.test_blofin(), self.test_hyperliquid(), self.test_coinbaseinternational(), self.test_coinbase_advanced(), self.test_woofi_pro(), self.test_oxfun(), self.test_xt(), self.test_vertex(), self.test_paradex(), self.test_hashkey(), self.test_coincatch(), self.test_defx(), self.test_cryptomus(), self.test_derive()]
1176
+ promises = [self.test_binance(), self.test_okx(), self.test_cryptocom(), self.test_bybit(), self.test_kucoin(), self.test_kucoinfutures(), self.test_bitget(), self.test_mexc(), self.test_htx(), self.test_woo(), self.test_bitmart(), self.test_coinex(), self.test_bingx(), self.test_phemex(), self.test_blofin(), self.test_hyperliquid(), self.test_coinbaseinternational(), self.test_coinbase_advanced(), self.test_woofi_pro(), self.test_oxfun(), self.test_xt(), self.test_vertex(), self.test_paradex(), self.test_hashkey(), self.test_coincatch(), self.test_defx(), self.test_cryptomus(), self.test_derive(), self.test_mode_trade()]
1177
1177
  await asyncio.gather(*promises)
1178
1178
  success_message = '[' + self.lang + '][TEST_SUCCESS] brokerId tests passed.'
1179
1179
  dump('[INFO]' + success_message)
@@ -1727,3 +1727,19 @@ class testMainClass:
1727
1727
  if not is_sync():
1728
1728
  await close(exchange)
1729
1729
  return True
1730
+
1731
+ async def test_mode_trade(self):
1732
+ exchange = self.init_offline_exchange('modetrade')
1733
+ exchange.secret = 'secretsecretsecretsecretsecretsecretsecrets'
1734
+ id = 'CCXTMODE'
1735
+ await exchange.load_markets()
1736
+ request = None
1737
+ try:
1738
+ await exchange.create_order('BTC/USDC:USDC', 'limit', 'buy', 1, 20000)
1739
+ except Exception as e:
1740
+ request = json_parse(exchange.last_request_body)
1741
+ broker_id = request['order_tag']
1742
+ assert broker_id == id, 'modetrade - id: ' + id + ' different from broker_id: ' + broker_id
1743
+ if not is_sync():
1744
+ await close(exchange)
1745
+ return True
ccxt/test/tests_sync.py CHANGED
@@ -1170,7 +1170,7 @@ class testMainClass:
1170
1170
  # -----------------------------------------------------------------------------
1171
1171
  # --- Init of brokerId tests functions-----------------------------------------
1172
1172
  # -----------------------------------------------------------------------------
1173
- promises = [self.test_binance(), self.test_okx(), self.test_cryptocom(), self.test_bybit(), self.test_kucoin(), self.test_kucoinfutures(), self.test_bitget(), self.test_mexc(), self.test_htx(), self.test_woo(), self.test_bitmart(), self.test_coinex(), self.test_bingx(), self.test_phemex(), self.test_blofin(), self.test_hyperliquid(), self.test_coinbaseinternational(), self.test_coinbase_advanced(), self.test_woofi_pro(), self.test_oxfun(), self.test_xt(), self.test_vertex(), self.test_paradex(), self.test_hashkey(), self.test_coincatch(), self.test_defx(), self.test_cryptomus(), self.test_derive()]
1173
+ promises = [self.test_binance(), self.test_okx(), self.test_cryptocom(), self.test_bybit(), self.test_kucoin(), self.test_kucoinfutures(), self.test_bitget(), self.test_mexc(), self.test_htx(), self.test_woo(), self.test_bitmart(), self.test_coinex(), self.test_bingx(), self.test_phemex(), self.test_blofin(), self.test_hyperliquid(), self.test_coinbaseinternational(), self.test_coinbase_advanced(), self.test_woofi_pro(), self.test_oxfun(), self.test_xt(), self.test_vertex(), self.test_paradex(), self.test_hashkey(), self.test_coincatch(), self.test_defx(), self.test_cryptomus(), self.test_derive(), self.test_mode_trade()]
1174
1174
  (promises)
1175
1175
  success_message = '[' + self.lang + '][TEST_SUCCESS] brokerId tests passed.'
1176
1176
  dump('[INFO]' + success_message)
@@ -1724,3 +1724,19 @@ class testMainClass:
1724
1724
  if not is_sync():
1725
1725
  close(exchange)
1726
1726
  return True
1727
+
1728
+ def test_mode_trade(self):
1729
+ exchange = self.init_offline_exchange('modetrade')
1730
+ exchange.secret = 'secretsecretsecretsecretsecretsecretsecrets'
1731
+ id = 'CCXTMODE'
1732
+ exchange.load_markets()
1733
+ request = None
1734
+ try:
1735
+ exchange.create_order('BTC/USDC:USDC', 'limit', 'buy', 1, 20000)
1736
+ except Exception as e:
1737
+ request = json_parse(exchange.last_request_body)
1738
+ broker_id = request['order_tag']
1739
+ assert broker_id == id, 'modetrade - id: ' + id + ' different from broker_id: ' + broker_id
1740
+ if not is_sync():
1741
+ close(exchange)
1742
+ return True
ccxt/timex.py CHANGED
@@ -1393,11 +1393,6 @@ class timex(Exchange, ImplicitAPI):
1393
1393
  #
1394
1394
  id = self.safe_string(currency, 'symbol')
1395
1395
  code = self.safe_currency_code(id)
1396
- name = self.safe_string(currency, 'name')
1397
- depositEnabled = self.safe_value(currency, 'depositEnabled')
1398
- withdrawEnabled = self.safe_value(currency, 'withdrawalEnabled')
1399
- isActive = self.safe_value(currency, 'active')
1400
- active = depositEnabled and withdrawEnabled and isActive
1401
1396
  # fee = self.safe_number(currency, 'withdrawalFee')
1402
1397
  feeString = self.safe_string(currency, 'withdrawalFee')
1403
1398
  tradeDecimals = self.safe_integer(currency, 'tradeDecimals')
@@ -1419,14 +1414,14 @@ class timex(Exchange, ImplicitAPI):
1419
1414
  'code': code,
1420
1415
  'info': currency,
1421
1416
  'type': None,
1422
- 'name': name,
1423
- 'active': active,
1424
- 'deposit': depositEnabled,
1425
- 'withdraw': withdrawEnabled,
1417
+ 'name': self.safe_string(currency, 'name'),
1418
+ 'active': self.safe_bool(currency, 'active'),
1419
+ 'deposit': self.safe_bool(currency, 'depositEnabled'),
1420
+ 'withdraw': self.safe_bool(currency, 'withdrawalEnabled'),
1426
1421
  'fee': fee,
1427
1422
  'precision': self.parse_number(self.parse_precision(self.safe_string(currency, 'decimals'))),
1428
1423
  'limits': {
1429
- 'withdraw': {'min': fee, 'max': None},
1424
+ 'withdraw': {'min': None, 'max': None},
1430
1425
  'amount': {'min': None, 'max': None},
1431
1426
  },
1432
1427
  'networks': {},
ccxt/vertex.py CHANGED
@@ -457,11 +457,10 @@ class vertex(Exchange, ImplicitAPI):
457
457
  tickerId = self.safe_string(data, 'ticker_id')
458
458
  if (tickerId is not None) and (tickerId.find('PERP') > 0):
459
459
  continue
460
- id = self.safe_string(data, 'product_id')
461
460
  name = self.safe_string(data, 'symbol')
462
461
  code = self.safe_currency_code(name)
463
- result[code] = {
464
- 'id': id,
462
+ result[code] = self.safe_currency_structure({
463
+ 'id': self.safe_string(data, 'product_id'),
465
464
  'name': name,
466
465
  'code': code,
467
466
  'precision': None,
@@ -481,7 +480,7 @@ class vertex(Exchange, ImplicitAPI):
481
480
  'max': None,
482
481
  },
483
482
  },
484
- }
483
+ })
485
484
  return result
486
485
 
487
486
  def parse_market(self, market) -> Market:
ccxt/whitebit.py CHANGED
@@ -623,25 +623,51 @@ class whitebit(Exchange, ImplicitAPI):
623
623
  for i in range(0, len(ids)):
624
624
  id = ids[i]
625
625
  currency = response[id]
626
- # breaks down in Python due to utf8 encoding issues on the exchange side
627
- # name = self.safe_string(currency, 'name')
628
- canDeposit = self.safe_bool(currency, 'can_deposit', True)
629
- canWithdraw = self.safe_bool(currency, 'can_withdraw', True)
630
- active = canDeposit and canWithdraw
626
+ # name = self.safe_string(currency, 'name') # breaks down in Python due to utf8 encoding issues on the exchange side
631
627
  code = self.safe_currency_code(id)
632
628
  hasProvider = ('providers' in currency)
633
- result[code] = {
629
+ networks = {}
630
+ rawNetworks = self.safe_dict(currency, 'networks', {})
631
+ depositsNetworks = self.safe_list(rawNetworks, 'deposits', [])
632
+ withdrawsNetworks = self.safe_list(rawNetworks, 'withdraws', [])
633
+ networkLimits = self.safe_dict(currency, 'limits', {})
634
+ depositLimits = self.safe_dict(networkLimits, 'deposit', {})
635
+ withdrawLimits = self.safe_dict(networkLimits, 'withdraw', {})
636
+ allNetworks = self.array_concat(depositsNetworks, withdrawsNetworks)
637
+ for j in range(0, len(allNetworks)):
638
+ networkId = allNetworks[j]
639
+ networkCode = self.network_id_to_code(networkId)
640
+ networks[networkCode] = {
641
+ 'id': networkId,
642
+ 'network': networkCode,
643
+ 'active': None,
644
+ 'deposit': self.in_array(networkId, depositsNetworks),
645
+ 'withdraw': self.in_array(networkId, withdrawsNetworks),
646
+ 'fee': None,
647
+ 'precision': None,
648
+ 'limits': {
649
+ 'deposit': {
650
+ 'min': self.safe_number(depositLimits, 'min', None),
651
+ 'max': self.safe_number(depositLimits, 'max', None),
652
+ },
653
+ 'withdraw': {
654
+ 'min': self.safe_number(withdrawLimits, 'min', None),
655
+ 'max': self.safe_number(withdrawLimits, 'max', None),
656
+ },
657
+ },
658
+ }
659
+ result[code] = self.safe_currency_structure({
634
660
  'id': id,
635
661
  'code': code,
636
662
  'info': currency, # the original payload
637
663
  'name': None, # see the comment above
638
- 'active': active,
639
- 'deposit': canDeposit,
640
- 'withdraw': canWithdraw,
664
+ 'active': None,
665
+ 'deposit': self.safe_bool(currency, 'can_deposit'),
666
+ 'withdraw': self.safe_bool(currency, 'can_withdraw'),
641
667
  'fee': None,
642
668
  'networks': None, # todo
643
669
  'type': 'fiat' if hasProvider else 'crypto',
644
- 'precision': None,
670
+ 'precision': self.parse_number(self.parse_precision(self.safe_string(currency, 'currency_precision'))),
645
671
  'limits': {
646
672
  'amount': {
647
673
  'min': None,
@@ -651,8 +677,12 @@ class whitebit(Exchange, ImplicitAPI):
651
677
  'min': self.safe_number(currency, 'min_withdraw'),
652
678
  'max': self.safe_number(currency, 'max_withdraw'),
653
679
  },
680
+ 'deposit': {
681
+ 'min': self.safe_number(currency, 'min_deposit'),
682
+ 'max': self.safe_number(currency, 'max_deposit'),
683
+ },
654
684
  },
655
- }
685
+ })
656
686
  return result
657
687
 
658
688
  def fetch_transaction_fees(self, codes: Strings = None, params={}):
ccxt/woo.py CHANGED
@@ -311,6 +311,11 @@ class woo(Exchange, ImplicitAPI):
311
311
  'TRC20': 'TRON',
312
312
  'ERC20': 'ETH',
313
313
  'BEP20': 'BSC',
314
+ 'ARB': 'Arbitrum',
315
+ },
316
+ 'networksById': {
317
+ 'TRX': 'TRC20',
318
+ 'TRON': 'TRC20',
314
319
  },
315
320
  # override defaultNetworkCodePriorities for a specific currency
316
321
  'defaultNetworkCodeForCurrencies': {
@@ -817,33 +822,45 @@ class woo(Exchange, ImplicitAPI):
817
822
  :returns dict: an associative dictionary of currencies
818
823
  """
819
824
  result: dict = {}
820
- tokenResponse = self.v1PublicGetToken(params)
825
+ tokenResponsePromise = self.v1PublicGetToken(params)
821
826
  #
822
- # {
823
- # "rows": [
827
+ # {
828
+ # "rows": [
824
829
  # {
825
830
  # "token": "ETH_USDT",
826
831
  # "fullname": "Tether",
827
- # "decimals": 6,
832
+ # "network": "ETH",
833
+ # "decimals": "6",
834
+ # "delisted": False,
828
835
  # "balance_token": "USDT",
829
- # "created_time": "0",
830
- # "updated_time": "0"
836
+ # "created_time": "1710123398",
837
+ # "updated_time": "1746528481",
838
+ # "can_collateral": True,
839
+ # "can_short": True
831
840
  # },
832
841
  # {
833
842
  # "token": "BSC_USDT",
834
843
  # "fullname": "Tether",
835
- # "decimals": 18,
844
+ # "network": "BSC",
845
+ # "decimals": "18",
846
+ # "delisted": False,
836
847
  # "balance_token": "USDT",
837
- # "created_time": "0",
838
- # "updated_time": "0"
848
+ # "created_time": "1710123395",
849
+ # "updated_time": "1746528601",
850
+ # "can_collateral": True,
851
+ # "can_short": True
839
852
  # },
840
853
  # {
841
- # "token": "ZEC",
842
- # "fullname": "ZCash",
843
- # "decimals": 8,
844
- # "balance_token": "ZEC",
845
- # "created_time": "0",
846
- # "updated_time": "0"
854
+ # "token": "ALGO",
855
+ # "fullname": "Algorand",
856
+ # "network": "ALGO",
857
+ # "decimals": "6",
858
+ # "delisted": False,
859
+ # "balance_token": "ALGO",
860
+ # "created_time": "1710123394",
861
+ # "updated_time": "1723087518",
862
+ # "can_collateral": True,
863
+ # "can_short": True
847
864
  # },
848
865
  # ...
849
866
  # ],
@@ -851,58 +868,66 @@ class woo(Exchange, ImplicitAPI):
851
868
  # }
852
869
  #
853
870
  # only make one request for currrencies...
854
- # tokenNetworkResponse = self.v1PublicGetTokenNetwork(params)
871
+ tokenNetworkResponsePromise = self.v1PublicGetTokenNetwork(params)
855
872
  #
856
873
  # {
857
874
  # "rows": [
858
875
  # {
859
876
  # "protocol": "ERC20",
877
+ # "network": "ETH",
860
878
  # "token": "USDT",
861
- # "name": "Ethereum",
862
- # "minimum_withdrawal": 30,
863
- # "withdrawal_fee": 25,
864
- # "allow_deposit": 1,
865
- # "allow_withdraw": 1
879
+ # "name": "Ethereum(ERC20)",
880
+ # "minimum_withdrawal": "10.00000000",
881
+ # "withdrawal_fee": "2.00000000",
882
+ # "allow_deposit": "1",
883
+ # "allow_withdraw": "1"
866
884
  # },
867
885
  # {
868
886
  # "protocol": "TRC20",
887
+ # "network": "TRX",
869
888
  # "token": "USDT",
870
- # "name": "Tron",
871
- # "minimum_withdrawal": 30,
872
- # "withdrawal_fee": 1,
873
- # "allow_deposit": 1,
874
- # "allow_withdraw": 1
889
+ # "name": "Tron(TRC20)",
890
+ # "minimum_withdrawal": "10.00000000",
891
+ # "withdrawal_fee": "4.50000000",
892
+ # "allow_deposit": "1",
893
+ # "allow_withdraw": "1"
875
894
  # },
876
895
  # ...
877
896
  # ],
878
897
  # "success": True
879
898
  # }
880
899
  #
900
+ tokenResponse, tokenNetworkResponse = [tokenResponsePromise, tokenNetworkResponsePromise]
881
901
  tokenRows = self.safe_list(tokenResponse, 'rows', [])
882
- networksByCurrencyId = self.group_by(tokenRows, 'balance_token')
883
- currencyIds = list(networksByCurrencyId.keys())
902
+ tokenNetworkRows = self.safe_list(tokenNetworkResponse, 'rows', [])
903
+ networksById = self.group_by(tokenNetworkRows, 'token')
904
+ tokensById = self.group_by(tokenRows, 'balance_token')
905
+ currencyIds = list(tokensById.keys())
884
906
  for i in range(0, len(currencyIds)):
885
907
  currencyId = currencyIds[i]
886
- networks = networksByCurrencyId[currencyId]
887
908
  code = self.safe_currency_code(currencyId)
888
- name: Str = None
889
- minPrecision = None
909
+ tokensByNetworkId = self.index_by(tokensById[currencyId], 'network')
910
+ chainsByNetworkId = self.index_by(networksById[currencyId], 'network')
911
+ keys = list(chainsByNetworkId.keys())
890
912
  resultingNetworks: dict = {}
891
- for j in range(0, len(networks)):
892
- network = networks[j]
893
- name = self.safe_string(network, 'fullname')
894
- networkId = self.safe_string(network, 'token')
895
- splitted = networkId.split('_')
896
- unifiedNetwork = splitted[0]
897
- precision = self.parse_precision(self.safe_string(network, 'decimals'))
898
- if precision is not None:
899
- minPrecision = precision if (minPrecision is None) else Precise.string_min(precision, minPrecision)
900
- resultingNetworks[unifiedNetwork] = {
913
+ for j in range(0, len(keys)):
914
+ networkId = keys[j]
915
+ tokenEntry = self.safe_dict(tokensByNetworkId, networkId, {})
916
+ networkEntry = self.safe_dict(chainsByNetworkId, networkId, {})
917
+ networkCode = self.network_id_to_code(networkId, code)
918
+ specialNetworkId = self.safe_string(tokenEntry, 'token')
919
+ resultingNetworks[networkCode] = {
901
920
  'id': networkId,
902
- 'network': unifiedNetwork,
921
+ 'currencyNetworkId': specialNetworkId, # exchange uses special crrency-ids(coin + network junction)
922
+ 'network': networkCode,
923
+ 'active': None,
924
+ 'deposit': self.safe_string(networkEntry, 'allow_deposit') == '1',
925
+ 'withdraw': self.safe_string(networkEntry, 'allow_withdraw') == '1',
926
+ 'fee': self.safe_number(networkEntry, 'withdrawal_fee'),
927
+ 'precision': self.parse_number(self.parse_precision(self.safe_string(tokenEntry, 'decimals'))),
903
928
  'limits': {
904
929
  'withdraw': {
905
- 'min': None,
930
+ 'min': self.safe_number(networkEntry, 'minimum_withdrawal'),
906
931
  'max': None,
907
932
  },
908
933
  'deposit': {
@@ -910,18 +935,13 @@ class woo(Exchange, ImplicitAPI):
910
935
  'max': None,
911
936
  },
912
937
  },
913
- 'active': None,
914
- 'deposit': None,
915
- 'withdraw': None,
916
- 'fee': None,
917
- 'precision': self.parse_number(precision),
918
- 'info': network,
938
+ 'info': [networkEntry, tokenEntry],
919
939
  }
920
- result[code] = {
940
+ result[code] = self.safe_currency_structure({
921
941
  'id': currencyId,
922
- 'name': name,
942
+ 'name': None,
923
943
  'code': code,
924
- 'precision': self.parse_number(minPrecision),
944
+ 'precision': None,
925
945
  'active': None,
926
946
  'fee': None,
927
947
  'networks': resultingNetworks,
@@ -938,8 +958,8 @@ class woo(Exchange, ImplicitAPI):
938
958
  'max': None,
939
959
  },
940
960
  },
941
- 'info': networks,
942
- }
961
+ 'info': [tokensByNetworkId, chainsByNetworkId],
962
+ })
943
963
  return result
944
964
 
945
965
  def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
@@ -1511,7 +1531,7 @@ class woo(Exchange, ImplicitAPI):
1511
1531
  if limit is not None:
1512
1532
  request['size'] = limit
1513
1533
  else:
1514
- request['size'] = 500
1534
+ request['size'] = 50 if trailing else 500
1515
1535
  if trigger:
1516
1536
  request['algoType'] = 'stop'
1517
1537
  elif trailing:
@@ -2071,12 +2091,10 @@ class woo(Exchange, ImplicitAPI):
2071
2091
  # self method is TODO because of networks unification
2072
2092
  self.load_markets()
2073
2093
  currency = self.currency(code)
2074
- networkCodeDefault = self.default_network_code_for_currency(code)
2075
- networkCode = self.safe_string(params, 'network', networkCodeDefault)
2076
- params = self.omit(params, 'network')
2077
- codeForExchange = networkCode + '_' + currency['code']
2094
+ specialNetworkId: Str = None
2095
+ specialNetworkId, params = self.get_dedicated_network_id(currency, params)
2078
2096
  request: dict = {
2079
- 'token': codeForExchange,
2097
+ 'token': specialNetworkId,
2080
2098
  }
2081
2099
  response = self.v1PrivateGetAssetDeposit(self.extend(request, params))
2082
2100
  # {
@@ -2084,15 +2102,28 @@ class woo(Exchange, ImplicitAPI):
2084
2102
  # "address": "3Jmtjx5544T4smrit9Eroe4PCrRkpDeKjP",
2085
2103
  # "extra": ''
2086
2104
  # }
2087
- tag = self.safe_string(response, 'extra')
2088
- address = self.safe_string(response, 'address')
2105
+ return self.parse_deposit_address(response, currency)
2106
+
2107
+ def get_dedicated_network_id(self, currency, params: dict) -> Any:
2108
+ networkCode = None
2109
+ networkCode, params = self.handle_network_code_and_params(params)
2110
+ networkCode = self.network_id_to_code(networkCode, currency['code'])
2111
+ networkEntry = self.safe_dict(currency['networks'], networkCode)
2112
+ if networkEntry is None:
2113
+ supportedNetworks = list(currency['networks'].keys())
2114
+ raise BadRequest(self.id + ' can not determine a network code, please provide unified "network" param, one from the following: ' + self.json(supportedNetworks))
2115
+ currentyNetworkId = self.safe_string(networkEntry, 'currencyNetworkId')
2116
+ return [currentyNetworkId, params]
2117
+
2118
+ def parse_deposit_address(self, depositEntry, currency: Currency = None) -> DepositAddress:
2119
+ address = self.safe_string(depositEntry, 'address')
2089
2120
  self.check_address(address)
2090
2121
  return {
2091
- 'info': response,
2092
- 'currency': code,
2093
- 'network': networkCode,
2122
+ 'info': depositEntry,
2123
+ 'currency': self.safe_string(currency, 'code'),
2124
+ 'network': None,
2094
2125
  'address': address,
2095
- 'tag': tag,
2126
+ 'tag': self.safe_string(depositEntry, 'extra'),
2096
2127
  }
2097
2128
 
2098
2129
  def get_asset_history_rows(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> Any:
@@ -2484,15 +2515,9 @@ class woo(Exchange, ImplicitAPI):
2484
2515
  }
2485
2516
  if tag is not None:
2486
2517
  request['extra'] = tag
2487
- networks = self.safe_dict(self.options, 'networks', {})
2488
- currencyNetworks = self.safe_dict(currency, 'networks', {})
2489
- network = self.safe_string_upper(params, 'network')
2490
- networkId = self.safe_string(networks, network, network)
2491
- coinNetwork = self.safe_dict(currencyNetworks, networkId, {})
2492
- coinNetworkId = self.safe_string(coinNetwork, 'id')
2493
- if coinNetworkId is None:
2494
- raise BadRequest(self.id + ' withdraw() require network parameter')
2495
- request['token'] = coinNetworkId
2518
+ specialNetworkId: Str = None
2519
+ specialNetworkId, params = self.get_dedicated_network_id(currency, params)
2520
+ request['token'] = specialNetworkId
2496
2521
  response = self.v1PrivatePostAssetWithdraw(self.extend(request, params))
2497
2522
  #
2498
2523
  # {