ccxt 4.4.60__py2.py3-none-any.whl → 4.4.62__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 +1 -1
- ccxt/abstract/bybit.py +1 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +9 -7
- ccxt/async_support/bingx.py +5 -6
- ccxt/async_support/bybit.py +109 -2
- ccxt/async_support/gate.py +76 -13
- ccxt/async_support/kraken.py +2 -2
- ccxt/async_support/phemex.py +221 -5
- ccxt/async_support/whitebit.py +3 -1
- ccxt/base/exchange.py +53 -26
- ccxt/bingx.py +5 -6
- ccxt/bybit.py +109 -2
- ccxt/gate.py +76 -13
- ccxt/kraken.py +2 -2
- ccxt/phemex.py +221 -5
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +25 -11
- ccxt/pro/gate.py +32 -0
- ccxt/pro/lbank.py +10 -4
- ccxt/pro/myokx.py +10 -1
- ccxt/test/tests_init.py +2 -1
- ccxt/whitebit.py +3 -1
- {ccxt-4.4.60.dist-info → ccxt-4.4.62.dist-info}/METADATA +4 -4
- {ccxt-4.4.60.dist-info → ccxt-4.4.62.dist-info}/RECORD +28 -28
- {ccxt-4.4.60.dist-info → ccxt-4.4.62.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.60.dist-info → ccxt-4.4.62.dist-info}/WHEEL +0 -0
- {ccxt-4.4.60.dist-info → ccxt-4.4.62.dist-info}/top_level.txt +0 -0
ccxt/gate.py
CHANGED
@@ -674,23 +674,67 @@ class gate(Exchange, ImplicitAPI):
|
|
674
674
|
},
|
675
675
|
'createMarketBuyOrderRequiresPrice': True,
|
676
676
|
'networks': {
|
677
|
-
'
|
678
|
-
'
|
679
|
-
'
|
677
|
+
'BTC': 'BTC',
|
678
|
+
'BRC20': 'BTCBRC', # for eg: ORDI, RATS, ...
|
679
|
+
'ETH': 'ETH',
|
680
|
+
'ERC20': 'ETH',
|
681
|
+
'TRX': 'TRX',
|
682
|
+
'TRC20': 'TRX',
|
683
|
+
'HECO': 'HT',
|
684
|
+
'HRC20': 'HT',
|
685
|
+
'BSC': 'BSC',
|
680
686
|
'BEP20': 'BSC',
|
687
|
+
'SOL': 'SOL',
|
688
|
+
'POLYGON': 'POL',
|
689
|
+
'MATIC': 'POL',
|
690
|
+
'OP': 'OPETH',
|
691
|
+
'OPTIMISM': 'OPETH',
|
692
|
+
'ADA': 'ADA', # CARDANO
|
693
|
+
'AVAXC': 'AVAX_C',
|
694
|
+
'NEAR': 'NEAR',
|
695
|
+
'ARBONE': 'ARBEVM',
|
696
|
+
'BASE': 'BASEEVM',
|
697
|
+
'SUI': 'SUI',
|
698
|
+
'CRONOS': 'CRO',
|
699
|
+
'CRO': 'CRO',
|
700
|
+
'APT': 'APT',
|
701
|
+
'SCROLL': 'SCROLLETH',
|
702
|
+
'TAIKO': 'TAIKOETH',
|
703
|
+
'HYPE': 'HYPE',
|
704
|
+
'ALGO': 'ALGO',
|
705
|
+
# KAVA: ['KAVA', 'KAVAEVM']
|
706
|
+
# SEI: ['SEI', 'SEIEVM']
|
707
|
+
'LINEA': 'LINEAETH',
|
708
|
+
'BLAST': 'BLASTETH',
|
709
|
+
'XLM': 'XLM',
|
710
|
+
'RSK': 'RBTC',
|
711
|
+
'TON': 'TON',
|
712
|
+
'MNT': 'MNT',
|
713
|
+
# 'RUNE': 'BTCRUNES', probably, cant verify atm
|
714
|
+
'CELO': 'CELO',
|
715
|
+
'HBAR': 'HBAR',
|
716
|
+
# 'FTM': SONIC REBRAND, todo
|
717
|
+
'ZKSERA': 'ZKSERA',
|
718
|
+
'KLAY': 'KLAY',
|
681
719
|
'EOS': 'EOS',
|
682
|
-
'
|
720
|
+
'ACA': 'ACA',
|
721
|
+
# TLOS: ['TLOS', 'TLOSEVM']
|
722
|
+
# ASTR: ['ASTR', 'ASTREVM']
|
723
|
+
# CFX: ['CFX', 'CFXEVM']
|
724
|
+
'XTZ': 'XTZ',
|
725
|
+
'EGLD': 'EGLD',
|
726
|
+
'GLMR': 'GLMR',
|
727
|
+
'AURORA': 'AURORAEVM',
|
728
|
+
# others
|
729
|
+
'KON': 'KONET',
|
683
730
|
'GATECHAIN': 'GTEVM',
|
684
|
-
'HRC20': 'HT',
|
685
731
|
'KUSAMA': 'KSMSM',
|
686
|
-
'NEAR': 'NEAR',
|
687
732
|
'OKC': 'OKT',
|
688
|
-
'
|
689
|
-
'POLKADOT': 'DOTSM',
|
690
|
-
'TRC20': 'TRX',
|
733
|
+
'POLKADOT': 'DOTSM', # todo: DOT for main DOT
|
691
734
|
'LUNA': 'LUNC',
|
692
|
-
|
693
|
-
|
735
|
+
},
|
736
|
+
'networksById': {
|
737
|
+
'OPETH': 'OP',
|
694
738
|
},
|
695
739
|
'timeInForce': {
|
696
740
|
'GTC': 'gtc',
|
@@ -3525,6 +3569,7 @@ class gate(Exchange, ImplicitAPI):
|
|
3525
3569
|
#
|
3526
3570
|
# public
|
3527
3571
|
#
|
3572
|
+
# spot:
|
3528
3573
|
# {
|
3529
3574
|
# "id": "1334253759",
|
3530
3575
|
# "create_time": "1626342738",
|
@@ -3535,6 +3580,18 @@ class gate(Exchange, ImplicitAPI):
|
|
3535
3580
|
# "price": "32452.16"
|
3536
3581
|
# }
|
3537
3582
|
#
|
3583
|
+
# swap:
|
3584
|
+
#
|
3585
|
+
# {
|
3586
|
+
# "id": "442288327",
|
3587
|
+
# "contract": "BTC_USDT",
|
3588
|
+
# "create_time": "1739814676.707",
|
3589
|
+
# "create_time_ms": "1739814676.707",
|
3590
|
+
# "size": "-105",
|
3591
|
+
# "price": "95594.8"
|
3592
|
+
# }
|
3593
|
+
#
|
3594
|
+
#
|
3538
3595
|
# public ws
|
3539
3596
|
#
|
3540
3597
|
# {
|
@@ -3611,8 +3668,14 @@ class gate(Exchange, ImplicitAPI):
|
|
3611
3668
|
# }
|
3612
3669
|
#
|
3613
3670
|
id = self.safe_string_2(trade, 'id', 'trade_id')
|
3614
|
-
timestamp =
|
3615
|
-
|
3671
|
+
timestamp: Int = None
|
3672
|
+
msString = self.safe_string(trade, 'create_time_ms')
|
3673
|
+
if msString is not None:
|
3674
|
+
msString = Precise.string_mul(msString, '1000')
|
3675
|
+
msString = msString[0:13]
|
3676
|
+
timestamp = self.parse_to_int(msString)
|
3677
|
+
else:
|
3678
|
+
timestamp = self.safe_timestamp_2(trade, 'time', 'create_time')
|
3616
3679
|
marketId = self.safe_string_2(trade, 'currency_pair', 'contract')
|
3617
3680
|
marketType = 'contract' if ('contract' in trade) else 'spot'
|
3618
3681
|
market = self.safe_market(marketId, market, '_', marketType)
|
ccxt/kraken.py
CHANGED
@@ -981,9 +981,9 @@ class kraken(Exchange, ImplicitAPI):
|
|
981
981
|
'high': self.safe_string(high, 1),
|
982
982
|
'low': self.safe_string(low, 1),
|
983
983
|
'bid': self.safe_string(bid, 0),
|
984
|
-
'bidVolume':
|
984
|
+
'bidVolume': self.safe_string(bid, 2),
|
985
985
|
'ask': self.safe_string(ask, 0),
|
986
|
-
'askVolume':
|
986
|
+
'askVolume': self.safe_string(ask, 2),
|
987
987
|
'vwap': vwap,
|
988
988
|
'open': self.safe_string(ticker, 'o'),
|
989
989
|
'close': last,
|
ccxt/phemex.py
CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
|
|
7
7
|
from ccxt.abstract.phemex import ImplicitAPI
|
8
8
|
import hashlib
|
9
9
|
import numbers
|
10
|
-
from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, Transaction, TransferEntry
|
10
|
+
from ccxt.base.types import Any, Balances, Conversion, Currencies, Currency, DepositAddress, Int, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, Transaction, TransferEntry
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
13
13
|
from ccxt.base.errors import AuthenticationError
|
@@ -50,6 +50,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
50
50
|
'cancelAllOrders': True,
|
51
51
|
'cancelOrder': True,
|
52
52
|
'closePosition': False,
|
53
|
+
'createConvertTrade': True,
|
53
54
|
'createOrder': True,
|
54
55
|
'createReduceOnlyOrder': True,
|
55
56
|
'createStopLimitOrder': True,
|
@@ -60,6 +61,9 @@ class phemex(Exchange, ImplicitAPI):
|
|
60
61
|
'fetchBorrowRateHistories': False,
|
61
62
|
'fetchBorrowRateHistory': False,
|
62
63
|
'fetchClosedOrders': True,
|
64
|
+
'fetchConvertQuote': True,
|
65
|
+
'fetchConvertTrade': False,
|
66
|
+
'fetchConvertTradeHistory': True,
|
63
67
|
'fetchCrossBorrowRate': False,
|
64
68
|
'fetchCrossBorrowRates': False,
|
65
69
|
'fetchCurrencies': True,
|
@@ -1078,7 +1082,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
1078
1082
|
for i in range(0, len(products)):
|
1079
1083
|
market = products[i]
|
1080
1084
|
type = self.safe_string_lower(market, 'type')
|
1081
|
-
if (type == 'perpetual') or (type == 'perpetualv2'):
|
1085
|
+
if (type == 'perpetual') or (type == 'perpetualv2') or (type == 'perpetualpilot'):
|
1082
1086
|
id = self.safe_string(market, 'symbol')
|
1083
1087
|
riskLimitValues = self.safe_value(riskLimitsById, id, {})
|
1084
1088
|
market = self.extend(market, riskLimitValues)
|
@@ -1254,7 +1258,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
1254
1258
|
precise.decimals = precise.decimals - scale
|
1255
1259
|
precise.reduce()
|
1256
1260
|
preciseString = str(precise)
|
1257
|
-
return self.
|
1261
|
+
return self.parse_to_numeric(preciseString)
|
1258
1262
|
|
1259
1263
|
def to_ev(self, amount, market: Market = None):
|
1260
1264
|
if (amount is None) or (market is None):
|
@@ -2547,7 +2551,6 @@ class phemex(Exchange, ImplicitAPI):
|
|
2547
2551
|
market = self.market(symbol)
|
2548
2552
|
requestSide = self.capitalize(side)
|
2549
2553
|
type = self.capitalize(type)
|
2550
|
-
reduceOnly = self.safe_bool(params, 'reduceOnly')
|
2551
2554
|
request: dict = {
|
2552
2555
|
# common
|
2553
2556
|
'symbol': market['id'],
|
@@ -2630,8 +2633,10 @@ class phemex(Exchange, ImplicitAPI):
|
|
2630
2633
|
posSide = self.safe_string_lower(params, 'posSide')
|
2631
2634
|
if posSide is None:
|
2632
2635
|
if hedged:
|
2636
|
+
reduceOnly = self.safe_bool(params, 'reduceOnly')
|
2633
2637
|
if reduceOnly:
|
2634
2638
|
side = 'sell' if (side == 'buy') else 'buy'
|
2639
|
+
params = self.omit(params, 'reduceOnly')
|
2635
2640
|
posSide = 'Long' if (side == 'buy') else 'Short'
|
2636
2641
|
else:
|
2637
2642
|
posSide = 'Merged'
|
@@ -2709,7 +2714,6 @@ class phemex(Exchange, ImplicitAPI):
|
|
2709
2714
|
else:
|
2710
2715
|
request['stopLossEp'] = self.to_ep(stopLossPrice, market)
|
2711
2716
|
params = self.omit(params, 'stopLossPrice')
|
2712
|
-
params = self.omit(params, 'reduceOnly')
|
2713
2717
|
response = None
|
2714
2718
|
if market['settle'] == 'USDT':
|
2715
2719
|
response = self.privatePostGOrders(self.extend(request, params))
|
@@ -4760,6 +4764,218 @@ class phemex(Exchange, ImplicitAPI):
|
|
4760
4764
|
'datetime': self.iso8601(timestamp),
|
4761
4765
|
}, market)
|
4762
4766
|
|
4767
|
+
def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
|
4768
|
+
"""
|
4769
|
+
fetch a quote for converting from one currency to another
|
4770
|
+
|
4771
|
+
https://phemex-docs.github.io/#rfq-quote
|
4772
|
+
|
4773
|
+
:param str fromCode: the currency that you want to sell and convert from
|
4774
|
+
:param str toCode: the currency that you want to buy and convert into
|
4775
|
+
:param float amount: how much you want to trade in units of the from currency
|
4776
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4777
|
+
:returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
|
4778
|
+
"""
|
4779
|
+
self.load_markets()
|
4780
|
+
fromCurrency = self.currency(fromCode)
|
4781
|
+
toCurrency = self.currency(toCode)
|
4782
|
+
valueScale = self.safe_integer(fromCurrency, 'valueScale')
|
4783
|
+
request: dict = {
|
4784
|
+
'fromCurrency': fromCode,
|
4785
|
+
'toCurrency': toCode,
|
4786
|
+
'fromAmountEv': self.to_en(amount, valueScale),
|
4787
|
+
}
|
4788
|
+
response = self.privateGetAssetsQuote(self.extend(request, params))
|
4789
|
+
#
|
4790
|
+
# {
|
4791
|
+
# "code": 0,
|
4792
|
+
# "msg": "OK",
|
4793
|
+
# "data": {
|
4794
|
+
# "code": "GIF...AAA",
|
4795
|
+
# "quoteArgs": {
|
4796
|
+
# "origin": 10,
|
4797
|
+
# "price": "0.00000939",
|
4798
|
+
# "proceeds": "0.00000000",
|
4799
|
+
# "ttlMs": 7000,
|
4800
|
+
# "expireAt": 1739875826009,
|
4801
|
+
# "requestAt": 1739875818009,
|
4802
|
+
# "quoteAt": 1739875816594
|
4803
|
+
# }
|
4804
|
+
# }
|
4805
|
+
# }
|
4806
|
+
#
|
4807
|
+
data = self.safe_dict(response, 'data', {})
|
4808
|
+
return self.parse_conversion(data, fromCurrency, toCurrency)
|
4809
|
+
|
4810
|
+
def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
|
4811
|
+
"""
|
4812
|
+
convert from one currency to another
|
4813
|
+
|
4814
|
+
https://phemex-docs.github.io/#convert
|
4815
|
+
|
4816
|
+
:param str id: the id of the trade that you want to make
|
4817
|
+
:param str fromCode: the currency that you want to sell and convert from
|
4818
|
+
:param str toCode: the currency that you want to buy and convert into
|
4819
|
+
:param float [amount]: how much you want to trade in units of the from currency
|
4820
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4821
|
+
:returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
|
4822
|
+
"""
|
4823
|
+
self.load_markets()
|
4824
|
+
fromCurrency = self.currency(fromCode)
|
4825
|
+
toCurrency = self.currency(toCode)
|
4826
|
+
valueScale = self.safe_integer(fromCurrency, 'valueScale')
|
4827
|
+
request: dict = {
|
4828
|
+
'code': id,
|
4829
|
+
'fromCurrency': fromCode,
|
4830
|
+
'toCurrency': toCode,
|
4831
|
+
}
|
4832
|
+
if amount is not None:
|
4833
|
+
request['fromAmountEv'] = self.to_en(amount, valueScale)
|
4834
|
+
response = self.privatePostAssetsConvert(self.extend(request, params))
|
4835
|
+
#
|
4836
|
+
# {
|
4837
|
+
# "code": 0,
|
4838
|
+
# "msg": "OK",
|
4839
|
+
# "data": {
|
4840
|
+
# "moveOp": 0,
|
4841
|
+
# "fromCurrency": "USDT",
|
4842
|
+
# "toCurrency": "BTC",
|
4843
|
+
# "fromAmountEv": 4000000000,
|
4844
|
+
# "toAmountEv": 41511,
|
4845
|
+
# "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
|
4846
|
+
# "status": 10
|
4847
|
+
# }
|
4848
|
+
# }
|
4849
|
+
#
|
4850
|
+
data = self.safe_dict(response, 'data', {})
|
4851
|
+
fromCurrencyId = self.safe_string(data, 'fromCurrency')
|
4852
|
+
fromResult = self.safe_currency(fromCurrencyId, fromCurrency)
|
4853
|
+
toCurrencyId = self.safe_string(data, 'toCurrency')
|
4854
|
+
to = self.safe_currency(toCurrencyId, toCurrency)
|
4855
|
+
return self.parse_conversion(data, fromResult, to)
|
4856
|
+
|
4857
|
+
def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Conversion]:
|
4858
|
+
"""
|
4859
|
+
fetch the users history of conversion trades
|
4860
|
+
|
4861
|
+
https://phemex-docs.github.io/#query-convert-history
|
4862
|
+
|
4863
|
+
:param str [code]: the unified currency code
|
4864
|
+
:param int [since]: the earliest time in ms to fetch conversions for
|
4865
|
+
:param int [limit]: the maximum number of conversion structures to retrieve, default 20, max 200
|
4866
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4867
|
+
:param str [params.until]: the end time in ms
|
4868
|
+
:param str [params.fromCurrency]: the currency that you sold and converted from
|
4869
|
+
:param str [params.toCurrency]: the currency that you bought and converted into
|
4870
|
+
:returns dict[]: a list of `conversion structures <https://docs.ccxt.com/#/?id=conversion-structure>`
|
4871
|
+
"""
|
4872
|
+
self.load_markets()
|
4873
|
+
request: dict = {}
|
4874
|
+
if code is not None:
|
4875
|
+
request['fromCurrency'] = code
|
4876
|
+
if since is not None:
|
4877
|
+
request['startTime'] = since
|
4878
|
+
if limit is not None:
|
4879
|
+
request['limit'] = limit
|
4880
|
+
request, params = self.handle_until_option('endTime', request, params)
|
4881
|
+
response = self.privateGetAssetsConvert(self.extend(request, params))
|
4882
|
+
#
|
4883
|
+
# {
|
4884
|
+
# "code": 0,
|
4885
|
+
# "msg": "OK",
|
4886
|
+
# "data": {
|
4887
|
+
# "total": 2,
|
4888
|
+
# "rows": [
|
4889
|
+
# {
|
4890
|
+
# "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
|
4891
|
+
# "createTime": 1739882294000,
|
4892
|
+
# "fromCurrency": "USDT",
|
4893
|
+
# "toCurrency": "BTC",
|
4894
|
+
# "fromAmountEv": 4000000000,
|
4895
|
+
# "toAmountEv": 41511,
|
4896
|
+
# "status": 10,
|
4897
|
+
# "conversionRate": 1037,
|
4898
|
+
# "errorCode": 0
|
4899
|
+
# },
|
4900
|
+
# ]
|
4901
|
+
# }
|
4902
|
+
# }
|
4903
|
+
#
|
4904
|
+
data = self.safe_dict(response, 'data', {})
|
4905
|
+
rows = self.safe_list(data, 'rows', [])
|
4906
|
+
return self.parse_conversions(rows, code, 'fromCurrency', 'toCurrency', since, limit)
|
4907
|
+
|
4908
|
+
def parse_conversion(self, conversion: dict, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
|
4909
|
+
#
|
4910
|
+
# fetchConvertQuote
|
4911
|
+
#
|
4912
|
+
# {
|
4913
|
+
# "code": "GIF...AAA",
|
4914
|
+
# "quoteArgs": {
|
4915
|
+
# "origin": 10,
|
4916
|
+
# "price": "0.00000939",
|
4917
|
+
# "proceeds": "0.00000000",
|
4918
|
+
# "ttlMs": 7000,
|
4919
|
+
# "expireAt": 1739875826009,
|
4920
|
+
# "requestAt": 1739875818009,
|
4921
|
+
# "quoteAt": 1739875816594
|
4922
|
+
# }
|
4923
|
+
# }
|
4924
|
+
#
|
4925
|
+
# createConvertTrade
|
4926
|
+
#
|
4927
|
+
# {
|
4928
|
+
# "moveOp": 0,
|
4929
|
+
# "fromCurrency": "USDT",
|
4930
|
+
# "toCurrency": "BTC",
|
4931
|
+
# "fromAmountEv": 4000000000,
|
4932
|
+
# "toAmountEv": 41511,
|
4933
|
+
# "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
|
4934
|
+
# "status": 10
|
4935
|
+
# }
|
4936
|
+
#
|
4937
|
+
# fetchConvertTradeHistory
|
4938
|
+
#
|
4939
|
+
# {
|
4940
|
+
# "linkKey": "45c8ed8e-d3f4-472d-8262-e464e8c46247",
|
4941
|
+
# "createTime": 1739882294000,
|
4942
|
+
# "fromCurrency": "USDT",
|
4943
|
+
# "toCurrency": "BTC",
|
4944
|
+
# "fromAmountEv": 4000000000,
|
4945
|
+
# "toAmountEv": 41511,
|
4946
|
+
# "status": 10,
|
4947
|
+
# "conversionRate": 1037,
|
4948
|
+
# "errorCode": 0
|
4949
|
+
# }
|
4950
|
+
#
|
4951
|
+
quoteArgs = self.safe_dict(conversion, 'quoteArgs', {})
|
4952
|
+
requestTime = self.safe_integer(quoteArgs, 'requestAt')
|
4953
|
+
timestamp = self.safe_integer(conversion, 'createTime', requestTime)
|
4954
|
+
fromCoin = self.safe_string(conversion, 'fromCurrency', self.safe_string(fromCurrency, 'code'))
|
4955
|
+
fromCode = self.safe_currency_code(fromCoin, fromCurrency)
|
4956
|
+
toCoin = self.safe_string(conversion, 'toCurrency', self.safe_string(toCurrency, 'code'))
|
4957
|
+
toCode = self.safe_currency_code(toCoin, toCurrency)
|
4958
|
+
fromValueScale = self.safe_integer(fromCurrency, 'valueScale')
|
4959
|
+
toValueScale = self.safe_integer(toCurrency, 'valueScale')
|
4960
|
+
fromAmount = self.from_en(self.safe_string(conversion, 'fromAmountEv'), fromValueScale)
|
4961
|
+
if fromAmount is None and quoteArgs is not None:
|
4962
|
+
fromAmount = self.from_en(self.safe_string(quoteArgs, 'origin'), fromValueScale)
|
4963
|
+
toAmount = self.from_en(self.safe_string(conversion, 'toAmountEv'), toValueScale)
|
4964
|
+
if toAmount is None and quoteArgs is not None:
|
4965
|
+
toAmount = self.from_en(self.safe_string(quoteArgs, 'proceeds'), toValueScale)
|
4966
|
+
return {
|
4967
|
+
'info': conversion,
|
4968
|
+
'timestamp': timestamp,
|
4969
|
+
'datetime': self.iso8601(timestamp),
|
4970
|
+
'id': self.safe_string(conversion, 'code'),
|
4971
|
+
'fromCurrency': fromCode,
|
4972
|
+
'fromAmount': self.parse_number(fromAmount),
|
4973
|
+
'toCurrency': toCode,
|
4974
|
+
'toAmount': self.parse_number(toAmount),
|
4975
|
+
'price': self.safe_number(quoteArgs, 'price'),
|
4976
|
+
'fee': None,
|
4977
|
+
}
|
4978
|
+
|
4763
4979
|
def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
4764
4980
|
if response is None:
|
4765
4981
|
return None # fallback to default error handler
|
ccxt/pro/__init__.py
CHANGED
ccxt/pro/binance.py
CHANGED
@@ -78,6 +78,7 @@ class binance(ccxt.async_support.binance):
|
|
78
78
|
'ws-api': {
|
79
79
|
'spot': 'wss://testnet.binance.vision/ws-api/v3',
|
80
80
|
'future': 'wss://testnet.binancefuture.com/ws-fapi/v1',
|
81
|
+
'delivery': 'wss://testnet.binancefuture.com/ws-dapi/v1',
|
81
82
|
},
|
82
83
|
},
|
83
84
|
},
|
@@ -90,6 +91,7 @@ class binance(ccxt.async_support.binance):
|
|
90
91
|
'ws-api': {
|
91
92
|
'spot': 'wss://ws-api.binance.com:443/ws-api/v3',
|
92
93
|
'future': 'wss://ws-fapi.binance.com/ws-fapi/v1',
|
94
|
+
'delivery': 'wss://ws-dapi.binance.com/ws-dapi/v1',
|
93
95
|
},
|
94
96
|
'papi': 'wss://fstream.binance.com/pm/ws',
|
95
97
|
},
|
@@ -2334,6 +2336,7 @@ class binance(ccxt.async_support.binance):
|
|
2334
2336
|
|
2335
2337
|
https://developers.binance.com/docs/derivatives/usds-margined-futures/account/websocket-api/Futures-Account-Balance
|
2336
2338
|
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#account-information-user_data
|
2339
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/account/websocket-api
|
2337
2340
|
|
2338
2341
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2339
2342
|
:param str|None [params.type]: 'future', 'delivery', 'savings', 'funding', or 'spot'
|
@@ -2344,7 +2347,7 @@ class binance(ccxt.async_support.binance):
|
|
2344
2347
|
"""
|
2345
2348
|
await self.load_markets()
|
2346
2349
|
type = self.get_market_type('fetchBalanceWs', None, params)
|
2347
|
-
if type != 'spot' and type != 'future':
|
2350
|
+
if type != 'spot' and type != 'future' and type != 'delivery':
|
2348
2351
|
raise BadRequest(self.id + ' fetchBalanceWs only supports spot or swap markets')
|
2349
2352
|
url = self.urls['api']['ws']['ws-api'][type]
|
2350
2353
|
requestId = self.request_id(url)
|
@@ -2450,6 +2453,7 @@ class binance(ccxt.async_support.binance):
|
|
2450
2453
|
fetch all open positions
|
2451
2454
|
|
2452
2455
|
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Position-Information
|
2456
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Position-Information
|
2453
2457
|
|
2454
2458
|
:param str[] [symbols]: list of unified market symbols
|
2455
2459
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -2458,15 +2462,20 @@ class binance(ccxt.async_support.binance):
|
|
2458
2462
|
:returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
|
2459
2463
|
"""
|
2460
2464
|
await self.load_markets()
|
2461
|
-
symbols = self.market_symbols(symbols, 'swap', True, True, True)
|
2462
|
-
url = self.urls['api']['ws']['ws-api']['future']
|
2463
|
-
requestId = self.request_id(url)
|
2464
|
-
messageHash = str(requestId)
|
2465
2465
|
payload: dict = {}
|
2466
|
+
market = None
|
2467
|
+
symbols = self.market_symbols(symbols, 'swap', True, True, True)
|
2466
2468
|
if symbols is not None:
|
2467
2469
|
symbolsLength = len(symbols)
|
2468
2470
|
if symbolsLength == 1:
|
2469
|
-
|
2471
|
+
market = self.market(symbols[0])
|
2472
|
+
payload['symbol'] = market['id']
|
2473
|
+
type = self.get_market_type('fetchPositionsWs', market, params)
|
2474
|
+
if type != 'future' and type != 'delivery':
|
2475
|
+
raise BadRequest(self.id + ' fetchPositionsWs only supports swap markets')
|
2476
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
2477
|
+
requestId = self.request_id(url)
|
2478
|
+
messageHash = str(requestId)
|
2470
2479
|
returnRateLimits = False
|
2471
2480
|
returnRateLimits, params = self.handle_option_and_params(params, 'fetchPositionsWs', 'returnRateLimits', False)
|
2472
2481
|
payload['returnRateLimits'] = returnRateLimits
|
@@ -2675,6 +2684,7 @@ class binance(ccxt.async_support.binance):
|
|
2675
2684
|
|
2676
2685
|
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#place-new-order-trade
|
2677
2686
|
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/New-Order
|
2687
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api
|
2678
2688
|
|
2679
2689
|
:param str symbol: unified symbol of the market to create an order in
|
2680
2690
|
:param str type: 'market' or 'limit'
|
@@ -2689,7 +2699,7 @@ class binance(ccxt.async_support.binance):
|
|
2689
2699
|
await self.load_markets()
|
2690
2700
|
market = self.market(symbol)
|
2691
2701
|
marketType = self.get_market_type('createOrderWs', market, params)
|
2692
|
-
if marketType != 'spot' and marketType != 'future':
|
2702
|
+
if marketType != 'spot' and marketType != 'future' and marketType != 'delivery':
|
2693
2703
|
raise BadRequest(self.id + ' createOrderWs only supports spot or swap markets')
|
2694
2704
|
url = self.urls['api']['ws']['ws-api'][marketType]
|
2695
2705
|
requestId = self.request_id(url)
|
@@ -2819,6 +2829,7 @@ class binance(ccxt.async_support.binance):
|
|
2819
2829
|
|
2820
2830
|
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#cancel-and-replace-order-trade
|
2821
2831
|
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Modify-Order
|
2832
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Modify-Order
|
2822
2833
|
|
2823
2834
|
:param str id: order id
|
2824
2835
|
:param str symbol: unified symbol of the market to create an order in
|
@@ -2832,22 +2843,23 @@ class binance(ccxt.async_support.binance):
|
|
2832
2843
|
await self.load_markets()
|
2833
2844
|
market = self.market(symbol)
|
2834
2845
|
marketType = self.get_market_type('editOrderWs', market, params)
|
2835
|
-
if marketType != 'spot' and marketType != 'future':
|
2846
|
+
if marketType != 'spot' and marketType != 'future' and marketType != 'delivery':
|
2836
2847
|
raise BadRequest(self.id + ' editOrderWs only supports spot or swap markets')
|
2837
2848
|
url = self.urls['api']['ws']['ws-api'][marketType]
|
2838
2849
|
requestId = self.request_id(url)
|
2839
2850
|
messageHash = str(requestId)
|
2851
|
+
isSwap = (marketType == 'future' or marketType == 'delivery')
|
2840
2852
|
payload = None
|
2841
2853
|
if marketType == 'spot':
|
2842
2854
|
payload = self.editSpotOrderRequest(id, symbol, type, side, amount, price, params)
|
2843
|
-
elif
|
2855
|
+
elif isSwap:
|
2844
2856
|
payload = self.editContractOrderRequest(id, symbol, type, side, amount, price, params)
|
2845
2857
|
returnRateLimits = False
|
2846
2858
|
returnRateLimits, params = self.handle_option_and_params(params, 'editOrderWs', 'returnRateLimits', False)
|
2847
2859
|
payload['returnRateLimits'] = returnRateLimits
|
2848
2860
|
message: dict = {
|
2849
2861
|
'id': messageHash,
|
2850
|
-
'method': 'order.modify' if (
|
2862
|
+
'method': 'order.modify' if (isSwap) else 'order.cancelReplace',
|
2851
2863
|
'params': self.sign_params(self.extend(payload, params)),
|
2852
2864
|
}
|
2853
2865
|
subscription: dict = {
|
@@ -2970,6 +2982,7 @@ class binance(ccxt.async_support.binance):
|
|
2970
2982
|
|
2971
2983
|
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#cancel-order-trade
|
2972
2984
|
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Cancel-Order
|
2985
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Cancel-Order
|
2973
2986
|
|
2974
2987
|
:param str id: order id
|
2975
2988
|
:param str [symbol]: unified market symbol, default is None
|
@@ -3047,6 +3060,7 @@ class binance(ccxt.async_support.binance):
|
|
3047
3060
|
|
3048
3061
|
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#query-order-user_data
|
3049
3062
|
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Query-Order
|
3063
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Query-Order
|
3050
3064
|
|
3051
3065
|
:param str id: order id
|
3052
3066
|
:param str [symbol]: unified symbol of the market the order was made in
|
@@ -3058,7 +3072,7 @@ class binance(ccxt.async_support.binance):
|
|
3058
3072
|
raise BadRequest(self.id + ' cancelOrderWs requires a symbol')
|
3059
3073
|
market = self.market(symbol)
|
3060
3074
|
type = self.get_market_type('fetchOrderWs', market, params)
|
3061
|
-
if type != 'spot' and type != 'future':
|
3075
|
+
if type != 'spot' and type != 'future' and type != 'delivery':
|
3062
3076
|
raise BadRequest(self.id + ' fetchOrderWs only supports spot or swap markets')
|
3063
3077
|
url = self.urls['api']['ws']['ws-api'][type]
|
3064
3078
|
requestId = self.request_id(url)
|
ccxt/pro/gate.py
CHANGED
@@ -1493,6 +1493,27 @@ class gate(ccxt.async_support.gate):
|
|
1493
1493
|
# data: {errs: {label: 'AUTHENTICATION_FAILED', message: 'Not login'}},
|
1494
1494
|
# request_id: '10406147'
|
1495
1495
|
# }
|
1496
|
+
# {
|
1497
|
+
# "time": 1739853211,
|
1498
|
+
# "time_ms": 1739853211201,
|
1499
|
+
# "id": 1,
|
1500
|
+
# "conn_id": "62f2c1dabbe186d7",
|
1501
|
+
# "trace_id": "cdb02a8c0b61086b2fe6f8fad2f98c54",
|
1502
|
+
# "channel": "spot.trades",
|
1503
|
+
# "event": "subscribe",
|
1504
|
+
# "payload": [
|
1505
|
+
# "LUNARLENS_USDT",
|
1506
|
+
# "ETH_USDT"
|
1507
|
+
# ],
|
1508
|
+
# "error": {
|
1509
|
+
# "code": 2,
|
1510
|
+
# "message": "unknown currency pair: LUNARLENS_USDT"
|
1511
|
+
# },
|
1512
|
+
# "result": {
|
1513
|
+
# "status": "fail"
|
1514
|
+
# },
|
1515
|
+
# "requestId": "cdb02a8c0b61086b2fe6f8fad2f98c54"
|
1516
|
+
# }
|
1496
1517
|
#
|
1497
1518
|
data = self.safe_dict(message, 'data')
|
1498
1519
|
errs = self.safe_dict(data, 'errs')
|
@@ -1511,6 +1532,17 @@ class gate(ccxt.async_support.gate):
|
|
1511
1532
|
client.reject(e, messageHash)
|
1512
1533
|
if (messageHash is not None) and (messageHash in client.subscriptions):
|
1513
1534
|
del client.subscriptions[messageHash]
|
1535
|
+
# remove subscriptions for watchSymbols
|
1536
|
+
channel = self.safe_string(message, 'channel')
|
1537
|
+
if (channel is not None) and (channel.find('.') > 0):
|
1538
|
+
parsedChannel = channel.split('.')
|
1539
|
+
payload = self.safe_list(message, 'payload', [])
|
1540
|
+
for i in range(0, len(payload)):
|
1541
|
+
marketType = parsedChannel[0] == 'swap' if 'futures' else parsedChannel[0]
|
1542
|
+
symbol = self.safe_symbol(payload[i], None, '_', marketType)
|
1543
|
+
messageHashSymbol = parsedChannel[1] + ':' + symbol
|
1544
|
+
if (messageHashSymbol is not None) and (messageHashSymbol in client.subscriptions):
|
1545
|
+
del client.subscriptions[messageHashSymbol]
|
1514
1546
|
if (id is not None) and (id in client.subscriptions):
|
1515
1547
|
del client.subscriptions[id]
|
1516
1548
|
return True
|
ccxt/pro/lbank.py
CHANGED
@@ -429,7 +429,7 @@ class lbank(ccxt.async_support.lbank):
|
|
429
429
|
# "volume":6.3607,
|
430
430
|
# "amount":77148.9303,
|
431
431
|
# "price":12129,
|
432
|
-
# "direction":"sell", #
|
432
|
+
# "direction":"sell", # buy, sell, buy_market, sell_market, buy_maker, sell_maker, buy_ioc, sell_ioc, buy_fok, sell_fok
|
433
433
|
# "TS":"2019-06-28T19:55:49.460"
|
434
434
|
# },
|
435
435
|
# "type":"trade",
|
@@ -467,7 +467,7 @@ class lbank(ccxt.async_support.lbank):
|
|
467
467
|
# "volume":6.3607,
|
468
468
|
# "amount":77148.9303,
|
469
469
|
# "price":12129,
|
470
|
-
# "direction":"sell", #
|
470
|
+
# "direction":"sell", # buy, sell, buy_market, sell_market, buy_maker, sell_maker, buy_ioc, sell_ioc, buy_fok, sell_fok
|
471
471
|
# "TS":"2019-06-28T19:55:49.460"
|
472
472
|
# }
|
473
473
|
#
|
@@ -475,8 +475,14 @@ class lbank(ccxt.async_support.lbank):
|
|
475
475
|
datetime = (self.iso8601(timestamp)) if (timestamp is not None) else (self.safe_string(trade, 'TS'))
|
476
476
|
if timestamp is None:
|
477
477
|
timestamp = self.parse8601(datetime)
|
478
|
-
|
479
|
-
|
478
|
+
rawSide = self.safe_string_2(trade, 'direction', 3)
|
479
|
+
parts = rawSide.split('_')
|
480
|
+
firstPart = self.safe_string(parts, 0)
|
481
|
+
secondPart = self.safe_string(parts, 1)
|
482
|
+
side = firstPart
|
483
|
+
# reverse if it was 'maker'
|
484
|
+
if secondPart is not None and secondPart == 'maker':
|
485
|
+
side = 'sell' if (side == 'buy') else 'buy'
|
480
486
|
return self.safe_trade({
|
481
487
|
'timestamp': timestamp,
|
482
488
|
'datetime': datetime,
|