ccxt 4.4.85__py2.py3-none-any.whl → 4.4.87__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.
- ccxt/__init__.py +7 -5
- ccxt/abstract/modetrade.py +119 -0
- ccxt/abstract/myokx.py +2 -0
- ccxt/abstract/okx.py +2 -0
- ccxt/abstract/okxus.py +349 -0
- ccxt/ascendex.py +187 -151
- ccxt/async_support/__init__.py +7 -5
- ccxt/async_support/ascendex.py +187 -151
- ccxt/async_support/base/exchange.py +30 -26
- ccxt/async_support/bequant.py +1 -1
- ccxt/async_support/binance.py +1 -1
- ccxt/async_support/bitget.py +4 -4
- ccxt/async_support/bitmart.py +1 -1
- ccxt/async_support/bitteam.py +31 -0
- ccxt/async_support/{huobijp.py → bittrade.py} +11 -11
- ccxt/async_support/coinbase.py +2 -5
- ccxt/async_support/coinmetro.py +3 -0
- ccxt/async_support/deribit.py +4 -5
- ccxt/async_support/gate.py +91 -73
- ccxt/async_support/hollaex.py +106 -49
- ccxt/async_support/htx.py +30 -51
- ccxt/async_support/hyperliquid.py +36 -20
- ccxt/async_support/kraken.py +5 -8
- ccxt/async_support/mexc.py +2 -2
- ccxt/async_support/modetrade.py +2727 -0
- ccxt/async_support/ndax.py +25 -24
- ccxt/async_support/okcoin.py +12 -29
- ccxt/async_support/okx.py +99 -3
- ccxt/async_support/okxus.py +54 -0
- ccxt/async_support/onetrading.py +10 -7
- ccxt/async_support/oxfun.py +40 -110
- ccxt/async_support/paradex.py +6 -0
- ccxt/async_support/phemex.py +4 -6
- ccxt/async_support/poloniex.py +172 -159
- ccxt/async_support/probit.py +18 -47
- ccxt/async_support/timex.py +5 -10
- ccxt/async_support/vertex.py +3 -4
- ccxt/async_support/whitebit.py +41 -11
- ccxt/async_support/woo.py +101 -75
- ccxt/async_support/woofipro.py +25 -20
- ccxt/async_support/xt.py +31 -41
- ccxt/base/exchange.py +12 -9
- ccxt/bequant.py +1 -1
- ccxt/binance.py +1 -1
- ccxt/bitget.py +4 -4
- ccxt/bitmart.py +1 -1
- ccxt/bitteam.py +31 -0
- ccxt/{huobijp.py → bittrade.py} +11 -11
- ccxt/coinbase.py +2 -5
- ccxt/coinmetro.py +3 -0
- ccxt/deribit.py +4 -5
- ccxt/gate.py +91 -73
- ccxt/hollaex.py +106 -49
- ccxt/htx.py +30 -51
- ccxt/hyperliquid.py +36 -20
- ccxt/kraken.py +5 -8
- ccxt/mexc.py +2 -2
- ccxt/modetrade.py +2727 -0
- ccxt/ndax.py +25 -24
- ccxt/okcoin.py +12 -29
- ccxt/okx.py +99 -3
- ccxt/okxus.py +54 -0
- ccxt/onetrading.py +10 -7
- ccxt/oxfun.py +40 -110
- ccxt/paradex.py +6 -0
- ccxt/phemex.py +4 -6
- ccxt/poloniex.py +172 -159
- ccxt/pro/__init__.py +101 -3
- ccxt/pro/binance.py +1 -0
- ccxt/pro/{huobijp.py → bittrade.py} +3 -3
- ccxt/pro/luno.py +6 -5
- ccxt/pro/mexc.py +2 -0
- ccxt/pro/modetrade.py +1271 -0
- ccxt/pro/okxus.py +38 -0
- ccxt/probit.py +18 -47
- ccxt/test/tests_async.py +17 -1
- ccxt/test/tests_sync.py +17 -1
- ccxt/timex.py +5 -10
- ccxt/vertex.py +3 -4
- ccxt/whitebit.py +41 -11
- ccxt/woo.py +100 -75
- ccxt/woofipro.py +24 -20
- ccxt/xt.py +31 -41
- {ccxt-4.4.85.dist-info → ccxt-4.4.87.dist-info}/METADATA +19 -8
- {ccxt-4.4.85.dist-info → ccxt-4.4.87.dist-info}/RECORD +89 -84
- ccxt/abstract/kuna.py +0 -182
- ccxt/async_support/kuna.py +0 -1935
- ccxt/kuna.py +0 -1935
- /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
- {ccxt-4.4.85.dist-info → ccxt-4.4.87.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.85.dist-info → ccxt-4.4.87.dist-info}/WHEEL +0 -0
- {ccxt-4.4.85.dist-info → ccxt-4.4.87.dist-info}/top_level.txt +0 -0
ccxt/async_support/ascendex.py
CHANGED
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
|
|
7
7
|
from ccxt.abstract.ascendex import ImplicitAPI
|
8
8
|
import asyncio
|
9
9
|
import hashlib
|
10
|
-
from ccxt.base.types import Account, Any, Balances,
|
10
|
+
from ccxt.base.types import Account, Any, Balances, Currencies, Currency, DepositAddress, Int, Leverage, Leverages, LeverageTier, LeverageTiers, MarginMode, MarginModes, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
13
13
|
from ccxt.base.errors import AuthenticationError
|
@@ -478,6 +478,7 @@ class ascendex(Exchange, ImplicitAPI):
|
|
478
478
|
'broad': {},
|
479
479
|
},
|
480
480
|
'commonCurrencies': {
|
481
|
+
'XBT': 'XBT', # self is not BTC ! just another token
|
481
482
|
'BOND': 'BONDED',
|
482
483
|
'BTCBEAR': 'BEAR',
|
483
484
|
'BTCBULL': 'BULL',
|
@@ -498,112 +499,82 @@ class ascendex(Exchange, ImplicitAPI):
|
|
498
499
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
499
500
|
:returns dict: an associative dictionary of currencies
|
500
501
|
"""
|
501
|
-
|
502
|
-
#
|
503
|
-
# {
|
504
|
-
# "code":0,
|
505
|
-
# "data":[
|
506
|
-
# {
|
507
|
-
# "assetCode" : "LTCBULL",
|
508
|
-
# "assetName" : "3X Long LTC Token",
|
509
|
-
# "precisionScale" : 9,
|
510
|
-
# "nativeScale" : 4,
|
511
|
-
# "withdrawalFee" : "0.2",
|
512
|
-
# "minWithdrawalAmt" : "1.0",
|
513
|
-
# "status" : "Normal"
|
514
|
-
# },
|
515
|
-
# ]
|
516
|
-
# }
|
517
|
-
#
|
518
|
-
marginPromise = self.v1PublicGetMarginAssets(params)
|
519
|
-
#
|
520
|
-
# {
|
521
|
-
# "code":0,
|
522
|
-
# "data":[
|
523
|
-
# {
|
524
|
-
# "assetCode":"BTT",
|
525
|
-
# "displayName": "BTT",
|
526
|
-
# "borrowAssetCode":"BTT-B",
|
527
|
-
# "interestAssetCode":"BTT-I",
|
528
|
-
# "nativeScale":0,
|
529
|
-
# "numConfirmations":1,
|
530
|
-
# "withdrawFee":"100.0",
|
531
|
-
# "minWithdrawalAmt":"1000.0",
|
532
|
-
# "statusCode":"Normal",
|
533
|
-
# "statusMessage":"",
|
534
|
-
# "interestRate":"0.001"
|
535
|
-
# }
|
536
|
-
# ]
|
537
|
-
# }
|
538
|
-
#
|
539
|
-
cashPromise = self.v1PublicGetCashAssets(params)
|
502
|
+
response = await self.v2PublicGetAssets(params)
|
540
503
|
#
|
541
|
-
#
|
542
|
-
#
|
543
|
-
#
|
544
|
-
#
|
545
|
-
#
|
546
|
-
#
|
547
|
-
#
|
548
|
-
#
|
549
|
-
#
|
550
|
-
#
|
551
|
-
#
|
552
|
-
#
|
553
|
-
#
|
504
|
+
# {
|
505
|
+
# "code": "0",
|
506
|
+
# "data": [
|
507
|
+
# {
|
508
|
+
# "assetCode": "USDT",
|
509
|
+
# "assetName": "Tether",
|
510
|
+
# "precisionScale": 9,
|
511
|
+
# "nativeScale": 4,
|
512
|
+
# "blockChain": [
|
513
|
+
# {
|
514
|
+
# "chainName": "Solana",
|
515
|
+
# "withdrawFee": "2.0",
|
516
|
+
# "allowDeposit": True,
|
517
|
+
# "allowWithdraw": True,
|
518
|
+
# "minDepositAmt": "0.01",
|
519
|
+
# "minWithdrawal": "4.0",
|
520
|
+
# "numConfirmations": 1
|
521
|
+
# },
|
522
|
+
# ...
|
523
|
+
# ]
|
524
|
+
# },
|
554
525
|
# ]
|
555
|
-
#
|
526
|
+
# }
|
556
527
|
#
|
557
|
-
|
558
|
-
assetsData = self.safe_list(assets, 'data', [])
|
559
|
-
marginData = self.safe_list(margin, 'data', [])
|
560
|
-
cashData = self.safe_list(cash, 'data', [])
|
561
|
-
assetsById = self.index_by(assetsData, 'assetCode')
|
562
|
-
marginById = self.index_by(marginData, 'assetCode')
|
563
|
-
cashById = self.index_by(cashData, 'assetCode')
|
564
|
-
dataById = self.deep_extend(assetsById, marginById, cashById)
|
565
|
-
ids = list(dataById.keys())
|
528
|
+
data = self.safe_list(response, 'data', [])
|
566
529
|
result: dict = {}
|
567
|
-
for i in range(0, len(
|
568
|
-
|
569
|
-
|
530
|
+
for i in range(0, len(data)):
|
531
|
+
currency = data[i]
|
532
|
+
id = self.safe_string(currency, 'assetCode')
|
570
533
|
code = self.safe_currency_code(id)
|
571
|
-
|
572
|
-
precision = self.parse_number(self.parse_precision(
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
534
|
+
chains = self.safe_list(currency, 'blockChain', [])
|
535
|
+
precision = self.parse_number(self.parse_precision(self.safe_string(currency, 'nativeScale')))
|
536
|
+
networks = {}
|
537
|
+
for j in range(0, len(chains)):
|
538
|
+
networkEtnry = chains[j]
|
539
|
+
networkId = self.safe_string(networkEtnry, 'chainName')
|
540
|
+
networkCode = self.network_code_to_id(networkId)
|
541
|
+
networks[networkCode] = {
|
542
|
+
'fee': self.safe_number(networkEtnry, 'withdrawFee'),
|
543
|
+
'active': None,
|
544
|
+
'withdraw': self.safe_bool(networkEtnry, 'allowWithdraw'),
|
545
|
+
'deposit': self.safe_bool(networkEtnry, 'allowDeposit'),
|
546
|
+
'precision': precision,
|
547
|
+
'limits': {
|
548
|
+
'amount': {
|
549
|
+
'min': None,
|
550
|
+
'max': None,
|
551
|
+
},
|
552
|
+
'withdraw': {
|
553
|
+
'min': self.safe_number(networkEtnry, 'minWithdrawal'),
|
554
|
+
'max': None,
|
555
|
+
},
|
556
|
+
'deposit': {
|
557
|
+
'min': self.safe_number(networkEtnry, 'minDepositAmt'),
|
558
|
+
'max': None,
|
559
|
+
},
|
560
|
+
},
|
561
|
+
}
|
562
|
+
# todo type: if chainsLength == 0 and (assetName.endswith(' Staking') or assetName.find(' Reward ') >= 0 or assetName.find('Slot Auction') >= 0 or assetName.find(' Freeze Asset') >= 0):
|
563
|
+
result[code] = self.safe_currency_structure({
|
593
564
|
'id': id,
|
594
565
|
'code': code,
|
595
566
|
'info': currency,
|
596
567
|
'type': None,
|
597
|
-
'margin':
|
568
|
+
'margin': None,
|
598
569
|
'name': self.safe_string(currency, 'assetName'),
|
599
|
-
'active':
|
600
|
-
'deposit':
|
601
|
-
'withdraw':
|
602
|
-
'fee':
|
570
|
+
'active': None,
|
571
|
+
'deposit': None,
|
572
|
+
'withdraw': None,
|
573
|
+
'fee': None,
|
603
574
|
'precision': precision,
|
604
575
|
'limits': {
|
605
576
|
'amount': {
|
606
|
-
'min':
|
577
|
+
'min': None,
|
607
578
|
'max': None,
|
608
579
|
},
|
609
580
|
'withdraw': {
|
@@ -611,8 +582,8 @@ class ascendex(Exchange, ImplicitAPI):
|
|
611
582
|
'max': None,
|
612
583
|
},
|
613
584
|
},
|
614
|
-
'networks':
|
615
|
-
}
|
585
|
+
'networks': networks,
|
586
|
+
})
|
616
587
|
return result
|
617
588
|
|
618
589
|
async def fetch_markets(self, params={}) -> List[Market]:
|
@@ -621,6 +592,12 @@ class ascendex(Exchange, ImplicitAPI):
|
|
621
592
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
622
593
|
:returns dict[]: an array of objects representing market data
|
623
594
|
"""
|
595
|
+
spotPromise = self.fetch_spot_markets(params)
|
596
|
+
contractPromise = self.fetch_contract_markets(params)
|
597
|
+
spotMarkets, contractMarkets = await asyncio.gather(*[spotPromise, contractPromise])
|
598
|
+
return self.array_concat(spotMarkets, contractMarkets)
|
599
|
+
|
600
|
+
async def fetch_spot_markets(self, params={}) -> List[Market]:
|
624
601
|
productsPromise = self.v1PublicGetProducts(params)
|
625
602
|
#
|
626
603
|
# {
|
@@ -672,7 +649,91 @@ class ascendex(Exchange, ImplicitAPI):
|
|
672
649
|
# ]
|
673
650
|
# }
|
674
651
|
#
|
675
|
-
|
652
|
+
products, cash = await asyncio.gather(*[productsPromise, cashPromise])
|
653
|
+
productsData = self.safe_list(products, 'data', [])
|
654
|
+
productsById = self.index_by(productsData, 'symbol')
|
655
|
+
cashData = self.safe_list(cash, 'data', [])
|
656
|
+
cashAndPerpetualsById = self.index_by(cashData, 'symbol')
|
657
|
+
dataById = self.deep_extend(productsById, cashAndPerpetualsById)
|
658
|
+
ids = list(dataById.keys())
|
659
|
+
result = []
|
660
|
+
for i in range(0, len(ids)):
|
661
|
+
id = ids[i]
|
662
|
+
if id.find('-PERP') >= 0:
|
663
|
+
continue # skip perpetuals, endpoint returns them
|
664
|
+
market = dataById[id]
|
665
|
+
status = self.safe_string(market, 'status')
|
666
|
+
domain = self.safe_string(market, 'domain')
|
667
|
+
active = False
|
668
|
+
if ((status == 'Normal') or (status == 'InternalTrading')) and (domain != 'LeveragedETF'):
|
669
|
+
active = True
|
670
|
+
minQty = self.safe_number(market, 'minQty')
|
671
|
+
maxQty = self.safe_number(market, 'maxQty')
|
672
|
+
minPrice = self.safe_number(market, 'tickSize')
|
673
|
+
maxPrice: Num = None
|
674
|
+
underlying = self.safe_string_2(market, 'underlying', 'symbol')
|
675
|
+
parts = underlying.split('/')
|
676
|
+
baseId = self.safe_string(parts, 0)
|
677
|
+
quoteId = self.safe_string(parts, 1)
|
678
|
+
base = self.safe_currency_code(baseId)
|
679
|
+
quote = self.safe_currency_code(quoteId)
|
680
|
+
fee = self.safe_number(market, 'commissionReserveRate')
|
681
|
+
marginTradable = self.safe_bool(market, 'marginTradable', False)
|
682
|
+
result.append({
|
683
|
+
'id': id,
|
684
|
+
'symbol': base + '/' + quote,
|
685
|
+
'base': base,
|
686
|
+
'baseId': baseId,
|
687
|
+
'quote': quote,
|
688
|
+
'quoteId': quoteId,
|
689
|
+
'settle': None,
|
690
|
+
'settleId': None,
|
691
|
+
'type': 'spot',
|
692
|
+
'spot': True,
|
693
|
+
'margin': marginTradable,
|
694
|
+
'swap': False,
|
695
|
+
'future': False,
|
696
|
+
'option': False,
|
697
|
+
'active': active,
|
698
|
+
'contract': False,
|
699
|
+
'linear': None,
|
700
|
+
'inverse': None,
|
701
|
+
'taker': fee,
|
702
|
+
'maker': fee,
|
703
|
+
'contractSize': None,
|
704
|
+
'expiry': None,
|
705
|
+
'expiryDatetime': None,
|
706
|
+
'strike': None,
|
707
|
+
'optionType': None,
|
708
|
+
'precision': {
|
709
|
+
'amount': self.safe_number(market, 'lotSize'),
|
710
|
+
'price': self.safe_number(market, 'tickSize'),
|
711
|
+
},
|
712
|
+
'limits': {
|
713
|
+
'leverage': {
|
714
|
+
'min': None,
|
715
|
+
'max': None,
|
716
|
+
},
|
717
|
+
'amount': {
|
718
|
+
'min': minQty,
|
719
|
+
'max': maxQty,
|
720
|
+
},
|
721
|
+
'price': {
|
722
|
+
'min': minPrice,
|
723
|
+
'max': maxPrice,
|
724
|
+
},
|
725
|
+
'cost': {
|
726
|
+
'min': self.safe_number(market, 'minNotional'),
|
727
|
+
'max': self.safe_number(market, 'maxNotional'),
|
728
|
+
},
|
729
|
+
},
|
730
|
+
'created': self.safe_integer(market, 'tradingStartTime'),
|
731
|
+
'info': market,
|
732
|
+
})
|
733
|
+
return result
|
734
|
+
|
735
|
+
async def fetch_contract_markets(self, params={}) -> List[Market]:
|
736
|
+
contracts = await self.v2PublicGetFuturesContract(params)
|
676
737
|
#
|
677
738
|
# {
|
678
739
|
# "code": 0,
|
@@ -685,9 +746,9 @@ class ascendex(Exchange, ImplicitAPI):
|
|
685
746
|
# "underlying": "BTC/USDT",
|
686
747
|
# "tradingStartTime": 1579701600000,
|
687
748
|
# "priceFilter": {
|
688
|
-
# "minPrice": "1",
|
749
|
+
# "minPrice": "0.1",
|
689
750
|
# "maxPrice": "1000000",
|
690
|
-
# "tickSize": "1"
|
751
|
+
# "tickSize": "0.1"
|
691
752
|
# },
|
692
753
|
# "lotSizeFilter": {
|
693
754
|
# "minQty": "0.0001",
|
@@ -710,50 +771,25 @@ class ascendex(Exchange, ImplicitAPI):
|
|
710
771
|
# ]
|
711
772
|
# }
|
712
773
|
#
|
713
|
-
|
714
|
-
productsData = self.safe_list(products, 'data', [])
|
715
|
-
productsById = self.index_by(productsData, 'symbol')
|
716
|
-
cashData = self.safe_list(cash, 'data', [])
|
717
|
-
perpetualsData = self.safe_list(perpetuals, 'data', [])
|
718
|
-
cashAndPerpetualsData = self.array_concat(cashData, perpetualsData)
|
719
|
-
cashAndPerpetualsById = self.index_by(cashAndPerpetualsData, 'symbol')
|
720
|
-
dataById = self.deep_extend(productsById, cashAndPerpetualsById)
|
721
|
-
ids = list(dataById.keys())
|
774
|
+
data = self.safe_list(contracts, 'data', [])
|
722
775
|
result = []
|
723
|
-
for i in range(0, len(
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
settle = self.safe_currency_code(settleId)
|
728
|
-
status = self.safe_string(market, 'status')
|
729
|
-
domain = self.safe_string(market, 'domain')
|
730
|
-
active = False
|
731
|
-
if ((status == 'Normal') or (status == 'InternalTrading')) and (domain != 'LeveragedETF'):
|
732
|
-
active = True
|
733
|
-
spot = settle is None
|
734
|
-
swap = not spot
|
735
|
-
linear = True if swap else None
|
736
|
-
minQty = self.safe_number(market, 'minQty')
|
737
|
-
maxQty = self.safe_number(market, 'maxQty')
|
738
|
-
minPrice = self.safe_number(market, 'tickSize')
|
739
|
-
maxPrice: Num = None
|
740
|
-
underlying = self.safe_string_2(market, 'underlying', 'symbol')
|
776
|
+
for i in range(0, len(data)):
|
777
|
+
market = data[i]
|
778
|
+
id = self.safe_string(market, 'symbol')
|
779
|
+
underlying = self.safe_string(market, 'underlying')
|
741
780
|
parts = underlying.split('/')
|
742
781
|
baseId = self.safe_string(parts, 0)
|
743
|
-
quoteId = self.safe_string(parts, 1)
|
744
782
|
base = self.safe_currency_code(baseId)
|
783
|
+
quoteId = self.safe_string(parts, 1)
|
745
784
|
quote = self.safe_currency_code(quoteId)
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
maxPrice = self.safe_number(priceFilter, 'maxPrice')
|
754
|
-
symbol = base + '/' + quote + ':' + settle
|
785
|
+
settleId = self.safe_string(market, 'settlementAsset')
|
786
|
+
settle = self.safe_currency_code(settleId)
|
787
|
+
linear = settle == quote
|
788
|
+
inverse = settle == base
|
789
|
+
symbol = base + '/' + quote + ':' + settle
|
790
|
+
priceFilter = self.safe_dict(market, 'priceFilter')
|
791
|
+
lotSizeFilter = self.safe_dict(market, 'lotSizeFilter')
|
755
792
|
fee = self.safe_number(market, 'commissionReserveRate')
|
756
|
-
marginTradable = self.safe_bool(market, 'marginTradable', False)
|
757
793
|
result.append({
|
758
794
|
'id': id,
|
759
795
|
'symbol': symbol,
|
@@ -763,26 +799,26 @@ class ascendex(Exchange, ImplicitAPI):
|
|
763
799
|
'baseId': baseId,
|
764
800
|
'quoteId': quoteId,
|
765
801
|
'settleId': settleId,
|
766
|
-
'type': 'swap'
|
767
|
-
'spot':
|
768
|
-
'margin':
|
769
|
-
'swap':
|
802
|
+
'type': 'swap',
|
803
|
+
'spot': False,
|
804
|
+
'margin': None,
|
805
|
+
'swap': True,
|
770
806
|
'future': False,
|
771
807
|
'option': False,
|
772
|
-
'active':
|
773
|
-
'contract':
|
808
|
+
'active': self.safe_string(market, 'status') == 'Normal',
|
809
|
+
'contract': True,
|
774
810
|
'linear': linear,
|
775
|
-
'inverse':
|
811
|
+
'inverse': inverse,
|
776
812
|
'taker': fee,
|
777
813
|
'maker': fee,
|
778
|
-
'contractSize': self.parse_number('1')
|
814
|
+
'contractSize': self.parse_number('1'),
|
779
815
|
'expiry': None,
|
780
816
|
'expiryDatetime': None,
|
781
817
|
'strike': None,
|
782
818
|
'optionType': None,
|
783
819
|
'precision': {
|
784
|
-
'amount': self.safe_number(
|
785
|
-
'price': self.safe_number(
|
820
|
+
'amount': self.safe_number(lotSizeFilter, 'lotSize'),
|
821
|
+
'price': self.safe_number(priceFilter, 'tickSize'),
|
786
822
|
},
|
787
823
|
'limits': {
|
788
824
|
'leverage': {
|
@@ -790,12 +826,12 @@ class ascendex(Exchange, ImplicitAPI):
|
|
790
826
|
'max': None,
|
791
827
|
},
|
792
828
|
'amount': {
|
793
|
-
'min': minQty,
|
794
|
-
'max': maxQty,
|
829
|
+
'min': self.safe_number(lotSizeFilter, 'minQty'),
|
830
|
+
'max': self.safe_number(lotSizeFilter, 'maxQty'),
|
795
831
|
},
|
796
832
|
'price': {
|
797
|
-
'min': minPrice,
|
798
|
-
'max': maxPrice,
|
833
|
+
'min': self.safe_number(priceFilter, 'minPrice'),
|
834
|
+
'max': self.safe_number(priceFilter, 'maxPrice'),
|
799
835
|
},
|
800
836
|
'cost': {
|
801
837
|
'min': self.safe_number(market, 'minNotional'),
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# -----------------------------------------------------------------------------
|
4
4
|
|
5
|
-
__version__ = '4.4.
|
5
|
+
__version__ = '4.4.87'
|
6
6
|
|
7
7
|
# -----------------------------------------------------------------------------
|
8
8
|
|
@@ -176,15 +176,7 @@ class Exchange(BaseExchange):
|
|
176
176
|
if (socksProxy not in self.socks_proxy_sessions):
|
177
177
|
# Create our SSL context object with our CA cert file
|
178
178
|
self.open() # ensure `asyncio_loop` is set
|
179
|
-
|
180
|
-
socksProxy,
|
181
|
-
# extra args copied from self.open()
|
182
|
-
ssl=self.ssl_context,
|
183
|
-
loop=self.asyncio_loop,
|
184
|
-
enable_cleanup_closed=True
|
185
|
-
)
|
186
|
-
self.socks_proxy_sessions[socksProxy] = aiohttp.ClientSession(loop=self.asyncio_loop, connector=self.aiohttp_socks_connector, trust_env=self.aiohttp_trust_env)
|
187
|
-
proxy_session = self.socks_proxy_sessions[socksProxy]
|
179
|
+
proxy_session = self.get_socks_proxy_session(socksProxy)
|
188
180
|
# add aiohttp_proxy for python as exclusion
|
189
181
|
elif self.aiohttp_proxy:
|
190
182
|
final_proxy = self.aiohttp_proxy
|
@@ -267,6 +259,20 @@ class Exchange(BaseExchange):
|
|
267
259
|
return http_response
|
268
260
|
return response.content
|
269
261
|
|
262
|
+
def get_socks_proxy_session(self, socksProxy):
|
263
|
+
if (self.socks_proxy_sessions is None):
|
264
|
+
self.socks_proxy_sessions = {}
|
265
|
+
if (socksProxy not in self.socks_proxy_sessions):
|
266
|
+
self.aiohttp_socks_connector = ProxyConnector.from_url(
|
267
|
+
socksProxy,
|
268
|
+
# extra args copied from self.open()
|
269
|
+
ssl=self.ssl_context,
|
270
|
+
loop=self.asyncio_loop,
|
271
|
+
enable_cleanup_closed=True
|
272
|
+
)
|
273
|
+
self.socks_proxy_sessions[socksProxy] = aiohttp.ClientSession(loop=self.asyncio_loop, connector=self.aiohttp_socks_connector, trust_env=self.aiohttp_trust_env)
|
274
|
+
return self.socks_proxy_sessions[socksProxy]
|
275
|
+
|
270
276
|
async def load_markets_helper(self, reload=False, params={}):
|
271
277
|
if not reload:
|
272
278
|
if self.markets:
|
@@ -411,19 +417,12 @@ class Exchange(BaseExchange):
|
|
411
417
|
# we use aiohttp instead of fastClient now because of this
|
412
418
|
# https://github.com/ccxt/ccxt/pull/25995
|
413
419
|
self.clients[url] = AiohttpClient(url, on_message, on_error, on_close, on_connected, options)
|
414
|
-
|
420
|
+
# set http/s proxy (socks proxy should be set in other place)
|
421
|
+
httpProxy, httpsProxy, socksProxy = self.check_ws_proxy_settings()
|
422
|
+
if (httpProxy or httpsProxy):
|
423
|
+
self.clients[url].proxy = httpProxy if httpProxy else httpsProxy
|
415
424
|
return self.clients[url]
|
416
425
|
|
417
|
-
def get_ws_proxy(self):
|
418
|
-
httpProxy, httpsProxy, socksProxy = self.check_ws_proxy_settings()
|
419
|
-
if httpProxy:
|
420
|
-
return httpProxy
|
421
|
-
elif httpsProxy:
|
422
|
-
return httpsProxy
|
423
|
-
elif socksProxy:
|
424
|
-
return socksProxy
|
425
|
-
return None
|
426
|
-
|
427
426
|
def delay(self, timeout, method, *args):
|
428
427
|
return self.asyncio_loop.call_later(timeout / 1000, self.spawn, method, *args)
|
429
428
|
|
@@ -486,8 +485,13 @@ class Exchange(BaseExchange):
|
|
486
485
|
if not subscribed:
|
487
486
|
client.subscriptions[subscribe_hash] = subscription or True
|
488
487
|
|
488
|
+
selected_session = self.session
|
489
|
+
# http/s proxy is being set in other places
|
490
|
+
httpProxy, httpsProxy, socksProxy = self.check_ws_proxy_settings()
|
491
|
+
if (socksProxy):
|
492
|
+
selected_session = self.get_socks_proxy_session(socksProxy)
|
489
493
|
connected = client.connected if client.connected.done() \
|
490
|
-
else asyncio.ensure_future(client.connect(
|
494
|
+
else asyncio.ensure_future(client.connect(selected_session, backoff_delay))
|
491
495
|
|
492
496
|
def after(fut):
|
493
497
|
# todo: decouple signing from subscriptions
|
@@ -899,15 +903,15 @@ class Exchange(BaseExchange):
|
|
899
903
|
if self.enableRateLimit:
|
900
904
|
cost = self.calculate_rate_limiter_cost(api, method, path, params, config)
|
901
905
|
await self.throttle(cost)
|
906
|
+
retries = None
|
907
|
+
retries, params = self.handle_option_and_params(params, path, 'maxRetriesOnFailure', 0)
|
908
|
+
retryDelay = None
|
909
|
+
retryDelay, params = self.handle_option_and_params(params, path, 'maxRetriesOnFailureDelay', 0)
|
902
910
|
self.lastRestRequestTimestamp = self.milliseconds()
|
903
911
|
request = self.sign(path, api, method, params, headers, body)
|
904
912
|
self.last_request_headers = request['headers']
|
905
913
|
self.last_request_body = request['body']
|
906
914
|
self.last_request_url = request['url']
|
907
|
-
retries = None
|
908
|
-
retries, params = self.handle_option_and_params(params, path, 'maxRetriesOnFailure', 0)
|
909
|
-
retryDelay = None
|
910
|
-
retryDelay, params = self.handle_option_and_params(params, path, 'maxRetriesOnFailureDelay', 0)
|
911
915
|
for i in range(0, retries + 1):
|
912
916
|
try:
|
913
917
|
return await self.fetch(request['url'], request['method'], request['headers'], request['body'])
|
ccxt/async_support/bequant.py
CHANGED
@@ -14,8 +14,8 @@ class bequant(hitbtc, ImplicitAPI):
|
|
14
14
|
return self.deep_extend(super(bequant, self).describe(), {
|
15
15
|
'id': 'bequant',
|
16
16
|
'name': 'Bequant',
|
17
|
-
'countries': ['MT'], # Malta
|
18
17
|
'pro': True,
|
18
|
+
'countries': ['MT'], # Malta
|
19
19
|
'urls': {
|
20
20
|
'logo': 'https://github.com/user-attachments/assets/0583ef1f-29fe-4b7c-8189-63565a0e2867',
|
21
21
|
'api': {
|
ccxt/async_support/binance.py
CHANGED
@@ -5024,13 +5024,13 @@ class binance(Exchange, ImplicitAPI):
|
|
5024
5024
|
postOnly = self.is_post_only(initialUppercaseType == 'MARKET', initialUppercaseType == 'LIMIT_MAKER', params)
|
5025
5025
|
if postOnly:
|
5026
5026
|
uppercaseType = 'LIMIT_MAKER'
|
5027
|
-
request['type'] = uppercaseType
|
5028
5027
|
triggerPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
|
5029
5028
|
if triggerPrice is not None:
|
5030
5029
|
if uppercaseType == 'MARKET':
|
5031
5030
|
uppercaseType = 'STOP_LOSS'
|
5032
5031
|
elif uppercaseType == 'LIMIT':
|
5033
5032
|
uppercaseType = 'STOP_LOSS_LIMIT'
|
5033
|
+
request['type'] = uppercaseType
|
5034
5034
|
validOrderTypes = self.safe_list(market['info'], 'orderTypes')
|
5035
5035
|
if not self.in_array(uppercaseType, validOrderTypes):
|
5036
5036
|
if initialUppercaseType != uppercaseType:
|
ccxt/async_support/bitget.py
CHANGED
@@ -2371,7 +2371,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
2371
2371
|
'coin': currency['id'],
|
2372
2372
|
'address': address,
|
2373
2373
|
'chain': networkId,
|
2374
|
-
'size': amount,
|
2374
|
+
'size': self.currency_to_precision(code, amount, networkCode),
|
2375
2375
|
'transferType': 'on_chain',
|
2376
2376
|
}
|
2377
2377
|
if tag is not None:
|
@@ -2395,8 +2395,6 @@ class bitget(Exchange, ImplicitAPI):
|
|
2395
2395
|
fillResponseFromRequest = self.safe_bool(withdrawOptions, 'fillResponseFromRequest', True)
|
2396
2396
|
if fillResponseFromRequest:
|
2397
2397
|
result['currency'] = code
|
2398
|
-
result['timestamp'] = self.milliseconds()
|
2399
|
-
result['datetime'] = self.iso8601(self.milliseconds())
|
2400
2398
|
result['amount'] = amount
|
2401
2399
|
result['tag'] = tag
|
2402
2400
|
result['address'] = address
|
@@ -2514,7 +2512,9 @@ class bitget(Exchange, ImplicitAPI):
|
|
2514
2512
|
status = self.safe_string(transaction, 'status')
|
2515
2513
|
tag = self.safe_string(transaction, 'tag')
|
2516
2514
|
feeCostString = self.safe_string(transaction, 'fee')
|
2517
|
-
feeCostAbsString =
|
2515
|
+
feeCostAbsString = None
|
2516
|
+
if feeCostString is not None:
|
2517
|
+
feeCostAbsString = Precise.string_abs(feeCostString)
|
2518
2518
|
fee = None
|
2519
2519
|
amountString = self.safe_string(transaction, 'size')
|
2520
2520
|
if feeCostAbsString is not None:
|
ccxt/async_support/bitmart.py
CHANGED
@@ -2306,7 +2306,7 @@ class bitmart(Exchange, ImplicitAPI):
|
|
2306
2306
|
code = self.safe_currency_code(currencyId)
|
2307
2307
|
account = self.account()
|
2308
2308
|
account['free'] = self.safe_string_2(balance, 'available', 'available_balance')
|
2309
|
-
account['used'] = self.
|
2309
|
+
account['used'] = self.safe_string_n(balance, ['unAvailable', 'frozen', 'frozen_balance'])
|
2310
2310
|
result[code] = account
|
2311
2311
|
return self.safe_balance(result)
|
2312
2312
|
|