ccxt 4.4.61__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/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/kraken.py +2 -2
- ccxt/phemex.py +221 -5
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +25 -11
- 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.61.dist-info → ccxt-4.4.62.dist-info}/METADATA +4 -4
- {ccxt-4.4.61.dist-info → ccxt-4.4.62.dist-info}/RECORD +25 -25
- {ccxt-4.4.61.dist-info → ccxt-4.4.62.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.61.dist-info → ccxt-4.4.62.dist-info}/WHEEL +0 -0
- {ccxt-4.4.61.dist-info → ccxt-4.4.62.dist-info}/top_level.txt +0 -0
ccxt/__init__.py
CHANGED
ccxt/abstract/bybit.py
CHANGED
@@ -48,6 +48,7 @@ class ImplicitAPI:
|
|
48
48
|
public_get_v5_spot_lever_token_info = publicGetV5SpotLeverTokenInfo = Entry('v5/spot-lever-token/info', 'public', 'GET', {'cost': 5})
|
49
49
|
public_get_v5_spot_lever_token_reference = publicGetV5SpotLeverTokenReference = Entry('v5/spot-lever-token/reference', 'public', 'GET', {'cost': 5})
|
50
50
|
public_get_v5_spot_margin_trade_data = publicGetV5SpotMarginTradeData = Entry('v5/spot-margin-trade/data', 'public', 'GET', {'cost': 5})
|
51
|
+
public_get_v5_spot_margin_trade_collateral = publicGetV5SpotMarginTradeCollateral = Entry('v5/spot-margin-trade/collateral', 'public', 'GET', {'cost': 5})
|
51
52
|
public_get_v5_spot_cross_margin_trade_data = publicGetV5SpotCrossMarginTradeData = Entry('v5/spot-cross-margin-trade/data', 'public', 'GET', {'cost': 5})
|
52
53
|
public_get_v5_spot_cross_margin_trade_pledge_token = publicGetV5SpotCrossMarginTradePledgeToken = Entry('v5/spot-cross-margin-trade/pledge-token', 'public', 'GET', {'cost': 5})
|
53
54
|
public_get_v5_spot_cross_margin_trade_borrow_token = publicGetV5SpotCrossMarginTradeBorrowToken = Entry('v5/spot-cross-margin-trade/borrow-token', 'public', 'GET', {'cost': 5})
|
ccxt/async_support/__init__.py
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# -----------------------------------------------------------------------------
|
4
4
|
|
5
|
-
__version__ = '4.4.
|
5
|
+
__version__ = '4.4.62'
|
6
6
|
|
7
7
|
# -----------------------------------------------------------------------------
|
8
8
|
|
@@ -74,18 +74,20 @@ class Exchange(BaseExchange):
|
|
74
74
|
self.verify = config.get('verify', self.verify)
|
75
75
|
self.own_session = 'session' not in config
|
76
76
|
self.cafile = config.get('cafile', certifi.where())
|
77
|
+
self.throttler = None
|
77
78
|
super(Exchange, self).__init__(config)
|
78
|
-
self.throttle = None
|
79
|
-
self.init_rest_rate_limiter()
|
80
79
|
self.markets_loading = None
|
81
80
|
self.reloading_markets = False
|
82
81
|
|
83
|
-
def init_rest_rate_limiter(self):
|
84
|
-
self.throttle = Throttler(self.tokenBucket, self.asyncio_loop)
|
85
|
-
|
86
82
|
def get_event_loop(self):
|
87
83
|
return self.asyncio_loop
|
88
84
|
|
85
|
+
def init_throttler(self, cost=None):
|
86
|
+
self.throttler = Throttler(self.tokenBucket, self.asyncio_loop)
|
87
|
+
|
88
|
+
async def throttle(self, cost=None):
|
89
|
+
return await self.throttler(cost)
|
90
|
+
|
89
91
|
def get_session(self):
|
90
92
|
return self.session
|
91
93
|
|
@@ -107,7 +109,7 @@ class Exchange(BaseExchange):
|
|
107
109
|
self.asyncio_loop = asyncio.get_running_loop()
|
108
110
|
else:
|
109
111
|
self.asyncio_loop = asyncio.get_event_loop()
|
110
|
-
self.
|
112
|
+
self.throttler.loop = self.asyncio_loop
|
111
113
|
|
112
114
|
if self.ssl_context is None:
|
113
115
|
# Create our SSL context object with our CA cert file
|
ccxt/async_support/bingx.py
CHANGED
@@ -4455,13 +4455,12 @@ class bingx(Exchange, ImplicitAPI):
|
|
4455
4455
|
:param boolean [params.twap]: if fetching twap orders
|
4456
4456
|
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
4457
4457
|
"""
|
4458
|
-
if symbol is None:
|
4459
|
-
raise ArgumentsRequired(self.id + ' fetchClosedOrders() requires a symbol argument')
|
4460
4458
|
await self.load_markets()
|
4461
|
-
market =
|
4462
|
-
request: dict = {
|
4463
|
-
|
4464
|
-
|
4459
|
+
market = None
|
4460
|
+
request: dict = {}
|
4461
|
+
if symbol is not None:
|
4462
|
+
market = self.market(symbol)
|
4463
|
+
request['symbol'] = market['id']
|
4465
4464
|
type = None
|
4466
4465
|
subType = None
|
4467
4466
|
standard = None
|
ccxt/async_support/bybit.py
CHANGED
@@ -74,7 +74,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
74
74
|
'createTrailingAmountOrder': True,
|
75
75
|
'createTriggerOrder': True,
|
76
76
|
'editOrder': True,
|
77
|
+
'editOrders': True,
|
77
78
|
'fetchBalance': True,
|
79
|
+
'fetchBidsAsks': 'emulated',
|
78
80
|
'fetchBorrowInterest': False, # temporarily disabled, doesn't work
|
79
81
|
'fetchBorrowRateHistories': False,
|
80
82
|
'fetchBorrowRateHistory': False,
|
@@ -255,6 +257,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
255
257
|
'v5/spot-lever-token/reference': 5,
|
256
258
|
# spot margin trade
|
257
259
|
'v5/spot-margin-trade/data': 5,
|
260
|
+
'v5/spot-margin-trade/collateral': 5,
|
258
261
|
'v5/spot-cross-margin-trade/data': 5,
|
259
262
|
'v5/spot-cross-margin-trade/pledge-token': 5,
|
260
263
|
'v5/spot-cross-margin-trade/borrow-token': 5,
|
@@ -1240,6 +1243,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
1240
1243
|
'fetchOHLCV': {
|
1241
1244
|
'limit': 1000,
|
1242
1245
|
},
|
1246
|
+
'editOrders': {
|
1247
|
+
'max': 10,
|
1248
|
+
},
|
1243
1249
|
},
|
1244
1250
|
'spot': {
|
1245
1251
|
'extends': 'default',
|
@@ -2463,6 +2469,20 @@ class bybit(Exchange, ImplicitAPI):
|
|
2463
2469
|
tickerList = self.safe_list(result, 'list', [])
|
2464
2470
|
return self.parse_tickers(tickerList, parsedSymbols)
|
2465
2471
|
|
2472
|
+
async def fetch_bids_asks(self, symbols: Strings = None, params={}):
|
2473
|
+
"""
|
2474
|
+
fetches the bid and ask price and volume for multiple markets
|
2475
|
+
|
2476
|
+
https://bybit-exchange.github.io/docs/v5/market/tickers
|
2477
|
+
|
2478
|
+
:param str[]|None symbols: unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
|
2479
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2480
|
+
:param str [params.subType]: *contract only* 'linear', 'inverse'
|
2481
|
+
:param str [params.baseCoin]: *option only* base coin, default is 'BTC'
|
2482
|
+
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
2483
|
+
"""
|
2484
|
+
return await self.fetch_tickers(symbols, params)
|
2485
|
+
|
2466
2486
|
def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
|
2467
2487
|
#
|
2468
2488
|
# [
|
@@ -3985,13 +4005,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
3985
4005
|
price = self.safe_value(rawOrder, 'price')
|
3986
4006
|
orderParams = self.safe_dict(rawOrder, 'params', {})
|
3987
4007
|
orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams, isUta)
|
4008
|
+
del orderRequest['category']
|
3988
4009
|
ordersRequests.append(orderRequest)
|
3989
4010
|
symbols = self.market_symbols(orderSymbols, None, False, True, True)
|
3990
4011
|
market = self.market(symbols[0])
|
4012
|
+
unifiedMarginStatus = self.safe_integer(self.options, 'unifiedMarginStatus', 3)
|
3991
4013
|
category = None
|
3992
4014
|
category, params = self.get_bybit_type('createOrders', market, params)
|
3993
|
-
if category == 'inverse':
|
3994
|
-
raise NotSupported(self.id + ' createOrders does not allow inverse orders')
|
4015
|
+
if (category == 'inverse') and (unifiedMarginStatus < 5):
|
4016
|
+
raise NotSupported(self.id + ' createOrders does not allow inverse orders for non UTA2.0 account')
|
3995
4017
|
request: dict = {
|
3996
4018
|
'category': category,
|
3997
4019
|
'request': ordersRequests,
|
@@ -4158,6 +4180,91 @@ class bybit(Exchange, ImplicitAPI):
|
|
4158
4180
|
'id': self.safe_string(result, 'orderId'),
|
4159
4181
|
})
|
4160
4182
|
|
4183
|
+
async def edit_orders(self, orders: List[OrderRequest], params={}):
|
4184
|
+
"""
|
4185
|
+
edit a list of trade orders
|
4186
|
+
|
4187
|
+
https://bybit-exchange.github.io/docs/v5/order/batch-amend
|
4188
|
+
|
4189
|
+
:param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
|
4190
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4191
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
4192
|
+
"""
|
4193
|
+
await self.load_markets()
|
4194
|
+
ordersRequests = []
|
4195
|
+
orderSymbols = []
|
4196
|
+
for i in range(0, len(orders)):
|
4197
|
+
rawOrder = orders[i]
|
4198
|
+
symbol = self.safe_string(rawOrder, 'symbol')
|
4199
|
+
orderSymbols.append(symbol)
|
4200
|
+
id = self.safe_string(rawOrder, 'id')
|
4201
|
+
type = self.safe_string(rawOrder, 'type')
|
4202
|
+
side = self.safe_string(rawOrder, 'side')
|
4203
|
+
amount = self.safe_value(rawOrder, 'amount')
|
4204
|
+
price = self.safe_value(rawOrder, 'price')
|
4205
|
+
orderParams = self.safe_dict(rawOrder, 'params', {})
|
4206
|
+
orderRequest = self.edit_order_request(id, symbol, type, side, amount, price, orderParams)
|
4207
|
+
del orderRequest['category']
|
4208
|
+
ordersRequests.append(orderRequest)
|
4209
|
+
orderSymbols = self.market_symbols(orderSymbols, None, False, True, True)
|
4210
|
+
market = self.market(orderSymbols[0])
|
4211
|
+
unifiedMarginStatus = self.safe_integer(self.options, 'unifiedMarginStatus', 3)
|
4212
|
+
category = None
|
4213
|
+
category, params = self.get_bybit_type('editOrders', market, params)
|
4214
|
+
if (category == 'inverse') and (unifiedMarginStatus < 5):
|
4215
|
+
raise NotSupported(self.id + ' editOrders does not allow inverse orders for non UTA2.0 account')
|
4216
|
+
request: dict = {
|
4217
|
+
'category': category,
|
4218
|
+
'request': ordersRequests,
|
4219
|
+
}
|
4220
|
+
response = await self.privatePostV5OrderAmendBatch(self.extend(request, params))
|
4221
|
+
result = self.safe_dict(response, 'result', {})
|
4222
|
+
data = self.safe_list(result, 'list', [])
|
4223
|
+
retInfo = self.safe_dict(response, 'retExtInfo', {})
|
4224
|
+
codes = self.safe_list(retInfo, 'list', [])
|
4225
|
+
# self.extend the error with the unsuccessful orders
|
4226
|
+
for i in range(0, len(codes)):
|
4227
|
+
code = codes[i]
|
4228
|
+
retCode = self.safe_integer(code, 'code')
|
4229
|
+
if retCode != 0:
|
4230
|
+
data[i] = self.extend(data[i], code)
|
4231
|
+
#
|
4232
|
+
# {
|
4233
|
+
# "retCode": 0,
|
4234
|
+
# "retMsg": "OK",
|
4235
|
+
# "result": {
|
4236
|
+
# "list": [
|
4237
|
+
# {
|
4238
|
+
# "category": "option",
|
4239
|
+
# "symbol": "ETH-30DEC22-500-C",
|
4240
|
+
# "orderId": "b551f227-7059-4fb5-a6a6-699c04dbd2f2",
|
4241
|
+
# "orderLinkId": ""
|
4242
|
+
# },
|
4243
|
+
# {
|
4244
|
+
# "category": "option",
|
4245
|
+
# "symbol": "ETH-30DEC22-700-C",
|
4246
|
+
# "orderId": "fa6a595f-1a57-483f-b9d3-30e9c8235a52",
|
4247
|
+
# "orderLinkId": ""
|
4248
|
+
# }
|
4249
|
+
# ]
|
4250
|
+
# },
|
4251
|
+
# "retExtInfo": {
|
4252
|
+
# "list": [
|
4253
|
+
# {
|
4254
|
+
# "code": 0,
|
4255
|
+
# "msg": "OK"
|
4256
|
+
# },
|
4257
|
+
# {
|
4258
|
+
# "code": 0,
|
4259
|
+
# "msg": "OK"
|
4260
|
+
# }
|
4261
|
+
# ]
|
4262
|
+
# },
|
4263
|
+
# "time": 1672222808060
|
4264
|
+
# }
|
4265
|
+
#
|
4266
|
+
return self.parse_orders(data)
|
4267
|
+
|
4161
4268
|
def cancel_order_request(self, id: str, symbol: Str = None, params={}):
|
4162
4269
|
market = self.market(symbol)
|
4163
4270
|
request: dict = {
|
ccxt/async_support/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/async_support/phemex.py
CHANGED
@@ -7,7 +7,7 @@ from ccxt.async_support.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') or (type == '
|
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 = await 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
|
+
async 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
|
+
await 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 = await 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
|
+
async 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
|
+
await 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 = await 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
|
+
async 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
|
+
await 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 = await 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/async_support/whitebit.py
CHANGED
@@ -1150,6 +1150,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
1150
1150
|
# "clientOrderId": "customId11",
|
1151
1151
|
# "role": 2, # 1 = maker, 2 = taker
|
1152
1152
|
# "deal": "0.00419198" # amount in money
|
1153
|
+
# "feeAsset": "USDT"
|
1153
1154
|
# }
|
1154
1155
|
#
|
1155
1156
|
# fetchMyTrades
|
@@ -1165,6 +1166,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
1165
1166
|
# "deal": "9.981007",
|
1166
1167
|
# "fee": "0.009981007",
|
1167
1168
|
# "orderId": 58166729555,
|
1169
|
+
# "feeAsset": "USDT"
|
1168
1170
|
# }
|
1169
1171
|
#
|
1170
1172
|
market = self.safe_market(None, market)
|
@@ -1185,7 +1187,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
1185
1187
|
if feeCost is not None:
|
1186
1188
|
fee = {
|
1187
1189
|
'cost': feeCost,
|
1188
|
-
'currency':
|
1190
|
+
'currency': self.safe_currency_code(self.safe_string(trade, 'feeAsset')),
|
1189
1191
|
}
|
1190
1192
|
return self.safe_trade({
|
1191
1193
|
'info': trade,
|