ccxt 4.4.65__py2.py3-none-any.whl → 4.4.67__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 +5 -1
- ccxt/abstract/cryptomus.py +20 -0
- ccxt/abstract/derive.py +117 -0
- ccxt/abstract/tradeogre.py +1 -0
- ccxt/abstract/whitebit.py +16 -0
- ccxt/async_support/__init__.py +5 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +5 -3
- ccxt/async_support/bitget.py +22 -12
- ccxt/async_support/bitrue.py +5 -2
- ccxt/async_support/cryptomus.py +1041 -0
- ccxt/async_support/derive.py +2530 -0
- ccxt/async_support/gate.py +5 -1
- ccxt/async_support/htx.py +19 -5
- ccxt/async_support/tradeogre.py +131 -13
- ccxt/async_support/whitebit.py +276 -2
- ccxt/base/errors.py +0 -6
- ccxt/base/exchange.py +8 -1
- ccxt/binance.py +5 -3
- ccxt/bitget.py +22 -12
- ccxt/bitrue.py +5 -2
- ccxt/cryptomus.py +1041 -0
- ccxt/derive.py +2529 -0
- ccxt/gate.py +5 -1
- ccxt/htx.py +19 -5
- ccxt/pro/__init__.py +3 -1
- ccxt/pro/derive.py +704 -0
- ccxt/pro/gate.py +1 -0
- ccxt/test/tests_async.py +36 -3
- ccxt/test/tests_sync.py +36 -3
- ccxt/tradeogre.py +131 -13
- ccxt/whitebit.py +276 -2
- {ccxt-4.4.65.dist-info → ccxt-4.4.67.dist-info}/METADATA +14 -9
- {ccxt-4.4.65.dist-info → ccxt-4.4.67.dist-info}/RECORD +37 -30
- {ccxt-4.4.65.dist-info → ccxt-4.4.67.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.65.dist-info → ccxt-4.4.67.dist-info}/WHEEL +0 -0
- {ccxt-4.4.65.dist-info → ccxt-4.4.67.dist-info}/top_level.txt +0 -0
ccxt/async_support/gate.py
CHANGED
@@ -1947,7 +1947,11 @@ class gate(Exchange, ImplicitAPI):
|
|
1947
1947
|
"""
|
1948
1948
|
await self.load_markets()
|
1949
1949
|
symbols = self.market_symbols(symbols)
|
1950
|
-
|
1950
|
+
market = None
|
1951
|
+
if symbols is not None:
|
1952
|
+
firstSymbol = self.safe_string(symbols, 0)
|
1953
|
+
market = self.market(firstSymbol)
|
1954
|
+
request, query = self.prepare_request(market, 'swap', params)
|
1951
1955
|
response = await self.publicFuturesGetSettleContracts(self.extend(request, query))
|
1952
1956
|
#
|
1953
1957
|
# [
|
ccxt/async_support/htx.py
CHANGED
@@ -910,6 +910,7 @@ class htx(Exchange, ImplicitAPI):
|
|
910
910
|
'1041': InvalidOrder, # {"status":"error","err_code":1041,"err_msg":"The order amount exceeds the limit(170000Cont), please modify and order again.","ts":1643802784940}
|
911
911
|
'1047': InsufficientFunds, # {"status":"error","err_code":1047,"err_msg":"Insufficient margin available.","ts":1643802672652}
|
912
912
|
'1048': InsufficientFunds, # {"status":"error","err_code":1048,"err_msg":"Insufficient close amount available.","ts":1652772408864}
|
913
|
+
'1061': OrderNotFound, # {"status":"ok","data":{"errors":[{"order_id":"1349442392365359104","err_code":1061,"err_msg":"The order does not exist."}],"successes":""},"ts":1741773744526}
|
913
914
|
'1051': InvalidOrder, # {"status":"error","err_code":1051,"err_msg":"No orders to cancel.","ts":1652552125876}
|
914
915
|
'1066': BadSymbol, # {"status":"error","err_code":1066,"err_msg":"The symbol field cannot be empty. Please re-enter.","ts":1640550819147}
|
915
916
|
'1067': InvalidOrder, # {"status":"error","err_code":1067,"err_msg":"The client_order_id field is invalid. Please re-enter.","ts":1643802119413}
|
@@ -6757,14 +6758,17 @@ class htx(Exchange, ImplicitAPI):
|
|
6757
6758
|
"""
|
6758
6759
|
await self.load_markets()
|
6759
6760
|
symbols = self.market_symbols(symbols)
|
6760
|
-
|
6761
|
-
|
6762
|
-
subType = self.
|
6763
|
-
|
6761
|
+
defaultSubType = self.safe_string(self.options, 'defaultSubType', 'linear')
|
6762
|
+
subType = None
|
6763
|
+
subType, params = self.handle_option_and_params(params, 'fetchFundingRates', 'subType', defaultSubType)
|
6764
|
+
if symbols is not None:
|
6765
|
+
firstSymbol = self.safe_string(symbols, 0)
|
6766
|
+
market = self.market(firstSymbol)
|
6767
|
+
isLinear = market['linear']
|
6768
|
+
subType = 'linear' if isLinear else 'inverse'
|
6764
6769
|
request: dict = {
|
6765
6770
|
# 'contract_code': market['id'],
|
6766
6771
|
}
|
6767
|
-
params = self.omit(params, 'subType')
|
6768
6772
|
response = None
|
6769
6773
|
if subType == 'linear':
|
6770
6774
|
response = await self.contractPublicGetLinearSwapApiV1SwapBatchFundingRate(self.extend(request, params))
|
@@ -7032,6 +7036,7 @@ class htx(Exchange, ImplicitAPI):
|
|
7032
7036
|
if 'status' in response:
|
7033
7037
|
#
|
7034
7038
|
# {"status":"error","err-code":"order-limitorder-amount-min-error","err-msg":"limit order amount error, min: `0.001`","data":null}
|
7039
|
+
# {"status":"ok","data":{"errors":[{"order_id":"1349442392365359104","err_code":1061,"err_msg":"The order does not exist."}],"successes":""},"ts":1741773744526}
|
7035
7040
|
#
|
7036
7041
|
status = self.safe_string(response, 'status')
|
7037
7042
|
if status == 'error':
|
@@ -7047,6 +7052,15 @@ class htx(Exchange, ImplicitAPI):
|
|
7047
7052
|
feedback = self.id + ' ' + body
|
7048
7053
|
code = self.safe_string(response, 'code')
|
7049
7054
|
self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
|
7055
|
+
data = self.safe_dict(response, 'data')
|
7056
|
+
errorsList = self.safe_list(data, 'errors')
|
7057
|
+
if errorsList is not None:
|
7058
|
+
first = self.safe_dict(errorsList, 0)
|
7059
|
+
errcode = self.safe_string(first, 'err_code')
|
7060
|
+
errmessage = self.safe_string(first, 'err_msg')
|
7061
|
+
feedBack = self.id + ' ' + body
|
7062
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], errcode, feedBack)
|
7063
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], errmessage, feedBack)
|
7050
7064
|
return None
|
7051
7065
|
|
7052
7066
|
async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
ccxt/async_support/tradeogre.py
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.tradeogre import ImplicitAPI
|
8
|
-
from ccxt.base.types import Any, IndexType, Int, Market, Num, Order, OrderSide, OrderType, Str, Ticker
|
8
|
+
from ccxt.base.types import Any, IndexType, Int, Market, Num, Order, OrderSide, OrderType, Str, Strings, Ticker, Tickers
|
9
9
|
from typing import List
|
10
10
|
from ccxt.base.errors import ExchangeError
|
11
11
|
from ccxt.base.errors import AuthenticationError
|
@@ -74,7 +74,7 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
74
74
|
'fetchMarkets': True,
|
75
75
|
'fetchMarkOHLCV': False,
|
76
76
|
'fetchMyTrades': False,
|
77
|
-
'fetchOHLCV':
|
77
|
+
'fetchOHLCV': True,
|
78
78
|
'fetchOpenInterest': False,
|
79
79
|
'fetchOpenInterestHistory': False,
|
80
80
|
'fetchOpenOrders': True,
|
@@ -92,7 +92,7 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
92
92
|
'fetchPositionsRisk': False,
|
93
93
|
'fetchPremiumIndexOHLCV': False,
|
94
94
|
'fetchTicker': True,
|
95
|
-
'fetchTickers':
|
95
|
+
'fetchTickers': True,
|
96
96
|
'fetchTrades': True,
|
97
97
|
'fetchTradingLimits': False,
|
98
98
|
'fetchTransactionFee': False,
|
@@ -134,6 +134,7 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
134
134
|
'orders/{market}': 1,
|
135
135
|
'ticker/{market}': 1,
|
136
136
|
'history/{market}': 1,
|
137
|
+
'chart/{interval}/{market}/{timestamp}': 1,
|
137
138
|
},
|
138
139
|
},
|
139
140
|
'private': {
|
@@ -162,6 +163,14 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
162
163
|
'Order not found': BadRequest,
|
163
164
|
},
|
164
165
|
},
|
166
|
+
'timeframes': {
|
167
|
+
'1m': '1m',
|
168
|
+
'15m': '15m',
|
169
|
+
'1h': '1h',
|
170
|
+
'4h': '4h',
|
171
|
+
'1d': '1d',
|
172
|
+
'1w': '1w',
|
173
|
+
},
|
165
174
|
'options': {
|
166
175
|
},
|
167
176
|
'features': {
|
@@ -335,18 +344,72 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
335
344
|
#
|
336
345
|
return self.parse_ticker(response, market)
|
337
346
|
|
347
|
+
async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
348
|
+
"""
|
349
|
+
fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
|
350
|
+
:param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
351
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
352
|
+
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
353
|
+
"""
|
354
|
+
await self.load_markets()
|
355
|
+
symbols = self.market_symbols(symbols)
|
356
|
+
request: dict = {}
|
357
|
+
response = await self.publicGetMarkets(self.extend(request, params))
|
358
|
+
#
|
359
|
+
# [
|
360
|
+
# {
|
361
|
+
# "AAVE-USDT": {
|
362
|
+
# "initialprice": "177.20325711",
|
363
|
+
# "price": "177.20325711",
|
364
|
+
# "high": "177.20325711",
|
365
|
+
# "low": "177.20325711",
|
366
|
+
# "volume": "0.00000000",
|
367
|
+
# "bid": "160.72768581",
|
368
|
+
# "ask": "348.99999999",
|
369
|
+
# "basename": "Aave"
|
370
|
+
# }
|
371
|
+
# },
|
372
|
+
# ...
|
373
|
+
# ]
|
374
|
+
#
|
375
|
+
result: dict = {}
|
376
|
+
for i in range(0, len(response)):
|
377
|
+
entry = response[i]
|
378
|
+
marketIdArray = list(entry.keys())
|
379
|
+
marketId = self.safe_string(marketIdArray, 0)
|
380
|
+
market = self.safe_market(marketId)
|
381
|
+
data = entry[marketId]
|
382
|
+
ticker = self.parse_ticker(data, market)
|
383
|
+
symbol = ticker['symbol']
|
384
|
+
result[symbol] = ticker
|
385
|
+
return self.filter_by_array_tickers(result, 'symbol', symbols)
|
386
|
+
|
338
387
|
def parse_ticker(self, ticker, market: Market = None):
|
339
388
|
#
|
340
|
-
#
|
341
|
-
#
|
342
|
-
#
|
343
|
-
#
|
344
|
-
#
|
345
|
-
#
|
346
|
-
#
|
347
|
-
#
|
348
|
-
#
|
349
|
-
#
|
389
|
+
# fetchTicker:
|
390
|
+
# {
|
391
|
+
# "success":true,
|
392
|
+
# "initialprice":"0.02502002",
|
393
|
+
# "price":"0.02500000",
|
394
|
+
# "high":"0.03102001",
|
395
|
+
# "low":"0.02500000",
|
396
|
+
# "volume":"0.15549958",
|
397
|
+
# "bid":"0.02420000",
|
398
|
+
# "ask":"0.02625000"
|
399
|
+
# }
|
400
|
+
#
|
401
|
+
# fetchTickers:
|
402
|
+
# {
|
403
|
+
# "initialprice": "177.20325711",
|
404
|
+
# "price": "177.20325711",
|
405
|
+
# "high": "177.20325711",
|
406
|
+
# "low": "177.20325711",
|
407
|
+
# "volume": "0.00000000",
|
408
|
+
# "bid": "160.72768581",
|
409
|
+
# "ask": "348.99999999",
|
410
|
+
# "basename": "Aave"
|
411
|
+
# },
|
412
|
+
# ...
|
350
413
|
#
|
351
414
|
return self.safe_ticker({
|
352
415
|
'symbol': self.safe_string(market, 'symbol'),
|
@@ -371,6 +434,61 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
371
434
|
'info': ticker,
|
372
435
|
}, market)
|
373
436
|
|
437
|
+
async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
438
|
+
"""
|
439
|
+
fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
440
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
441
|
+
:param str timeframe: the length of time each candle represents
|
442
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
443
|
+
:param int [limit]: the maximum amount of candles to fetch
|
444
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
445
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
446
|
+
"""
|
447
|
+
await self.load_markets()
|
448
|
+
market = self.market(symbol)
|
449
|
+
request: dict = {
|
450
|
+
'market': market['id'],
|
451
|
+
'interval': self.safe_string(self.timeframes, timeframe, timeframe),
|
452
|
+
}
|
453
|
+
if since is None:
|
454
|
+
raise BadRequest(self.id + ' fetchOHLCV requires a since argument')
|
455
|
+
else:
|
456
|
+
request['timestamp'] = since
|
457
|
+
response = await self.publicGetChartIntervalMarketTimestamp(self.extend(request, params))
|
458
|
+
#
|
459
|
+
# [
|
460
|
+
# [
|
461
|
+
# 1729130040,
|
462
|
+
# 67581.47235999,
|
463
|
+
# 67581.47235999,
|
464
|
+
# 67338.01,
|
465
|
+
# 67338.01,
|
466
|
+
# 6.72168016
|
467
|
+
# ],
|
468
|
+
# ]
|
469
|
+
#
|
470
|
+
return self.parse_ohlcvs(response, market, timeframe, since, limit)
|
471
|
+
|
472
|
+
def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
|
473
|
+
#
|
474
|
+
# [
|
475
|
+
# 1729130040,
|
476
|
+
# 67581.47235999,
|
477
|
+
# 67581.47235999,
|
478
|
+
# 67338.01,
|
479
|
+
# 67338.01,
|
480
|
+
# 6.72168016
|
481
|
+
# ]
|
482
|
+
#
|
483
|
+
return [
|
484
|
+
self.safe_timestamp(ohlcv, 0),
|
485
|
+
self.safe_number(ohlcv, 1),
|
486
|
+
self.safe_number(ohlcv, 3),
|
487
|
+
self.safe_number(ohlcv, 4),
|
488
|
+
self.safe_number(ohlcv, 2),
|
489
|
+
self.safe_number(ohlcv, 5),
|
490
|
+
]
|
491
|
+
|
374
492
|
async def fetch_order_book(self, symbol: str, limit: Int = None, params={}):
|
375
493
|
"""
|
376
494
|
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
ccxt/async_support/whitebit.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.whitebit import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Any, Balances, BorrowInterest, Bool, Currencies, Currency, DepositAddress, Int, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
|
9
|
+
from ccxt.base.types import Any, Balances, BorrowInterest, Bool, Conversion, Currencies, Currency, DepositAddress, FundingHistory, Int, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
12
|
from ccxt.base.errors import AuthenticationError
|
@@ -45,6 +45,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
45
45
|
'cancelAllOrdersAfter': True,
|
46
46
|
'cancelOrder': True,
|
47
47
|
'cancelOrders': False,
|
48
|
+
'createConvertTrade': True,
|
48
49
|
'createMarketBuyOrderWithCost': True,
|
49
50
|
'createMarketOrderWithCost': False,
|
50
51
|
'createMarketSellOrderWithCost': False,
|
@@ -57,6 +58,9 @@ class whitebit(Exchange, ImplicitAPI):
|
|
57
58
|
'fetchBorrowRateHistories': False,
|
58
59
|
'fetchBorrowRateHistory': False,
|
59
60
|
'fetchClosedOrders': True,
|
61
|
+
'fetchConvertQuote': True,
|
62
|
+
'fetchConvertTrade': False,
|
63
|
+
'fetchConvertTradeHistory': True,
|
60
64
|
'fetchCrossBorrowRate': False,
|
61
65
|
'fetchCrossBorrowRates': False,
|
62
66
|
'fetchCurrencies': True,
|
@@ -68,7 +72,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
68
72
|
'fetchDepositsWithdrawals': True,
|
69
73
|
'fetchDepositWithdrawFee': 'emulated',
|
70
74
|
'fetchDepositWithdrawFees': True,
|
71
|
-
'fetchFundingHistory':
|
75
|
+
'fetchFundingHistory': True,
|
72
76
|
'fetchFundingRate': True,
|
73
77
|
'fetchFundingRateHistory': False,
|
74
78
|
'fetchFundingRates': True,
|
@@ -186,6 +190,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
186
190
|
'assets',
|
187
191
|
'collateral/markets',
|
188
192
|
'fee',
|
193
|
+
'orderbook/depth/{market}',
|
189
194
|
'orderbook/{market}',
|
190
195
|
'ticker',
|
191
196
|
'trades/{market}',
|
@@ -194,6 +199,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
194
199
|
'markets',
|
195
200
|
'futures',
|
196
201
|
'platform/status',
|
202
|
+
'mining-pool',
|
197
203
|
],
|
198
204
|
},
|
199
205
|
'private': {
|
@@ -204,6 +210,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
204
210
|
'collateral-account/leverage',
|
205
211
|
'collateral-account/positions/open',
|
206
212
|
'collateral-account/summary',
|
213
|
+
'collateral-account/funding-history',
|
207
214
|
'main-account/address',
|
208
215
|
'main-account/balance',
|
209
216
|
'main-account/create-new-address',
|
@@ -230,6 +237,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
230
237
|
'order/collateral/market',
|
231
238
|
'order/collateral/stop-limit',
|
232
239
|
'order/collateral/trigger-market',
|
240
|
+
'order/collateral/bulk',
|
233
241
|
'order/new',
|
234
242
|
'order/market',
|
235
243
|
'order/stock_market',
|
@@ -241,6 +249,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
241
249
|
'order/kill-switch/status',
|
242
250
|
'order/bulk',
|
243
251
|
'order/modify',
|
252
|
+
'order/conditional-cancel',
|
244
253
|
'orders',
|
245
254
|
'oco-orders',
|
246
255
|
'order/collateral/oco',
|
@@ -259,6 +268,17 @@ class whitebit(Exchange, ImplicitAPI):
|
|
259
268
|
'sub-account/unblock',
|
260
269
|
'sub-account/balances',
|
261
270
|
'sub-account/transfer/history',
|
271
|
+
'sub-account/api-key/create',
|
272
|
+
'sub-account/api-key/edit',
|
273
|
+
'sub-account/api-key/delete',
|
274
|
+
'sub-account/api-key/list',
|
275
|
+
'sub-account/api-key/reset',
|
276
|
+
'sub-account/api-key/ip-address/list',
|
277
|
+
'sub-account/api-key/ip-address/create',
|
278
|
+
'sub-account/api-key/ip-address/delete',
|
279
|
+
'mining/rewards',
|
280
|
+
'market/fee',
|
281
|
+
'conditional-orders',
|
262
282
|
],
|
263
283
|
},
|
264
284
|
},
|
@@ -2515,6 +2535,84 @@ class whitebit(Exchange, ImplicitAPI):
|
|
2515
2535
|
'interval': None,
|
2516
2536
|
}
|
2517
2537
|
|
2538
|
+
async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[FundingHistory]:
|
2539
|
+
"""
|
2540
|
+
fetch the history of funding payments paid and received on self account
|
2541
|
+
|
2542
|
+
https://docs.whitebit.com/private/http-trade-v4/#funding-history
|
2543
|
+
|
2544
|
+
:param str [symbol]: unified market symbol
|
2545
|
+
:param int [since]: the starting timestamp in milliseconds
|
2546
|
+
:param int [limit]: the number of entries to return
|
2547
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2548
|
+
:param int [params.until]: the latest time in ms to fetch funding history for
|
2549
|
+
:returns dict[]: a list of `funding history structures <https://docs.ccxt.com/#/?id=funding-history-structure>`
|
2550
|
+
"""
|
2551
|
+
await self.load_markets()
|
2552
|
+
if symbol is None:
|
2553
|
+
raise ArgumentsRequired(self.id + ' fetchFundingHistory() requires a symbol argument')
|
2554
|
+
market = self.market(symbol)
|
2555
|
+
request: dict = {
|
2556
|
+
'market': market['id'],
|
2557
|
+
}
|
2558
|
+
if since is not None:
|
2559
|
+
request['startDate'] = since
|
2560
|
+
if limit is not None:
|
2561
|
+
request['limit'] = since
|
2562
|
+
request, params = self.handle_until_option('endDate', request, params)
|
2563
|
+
response = await self.v4PrivatePostCollateralAccountFundingHistory(request)
|
2564
|
+
#
|
2565
|
+
# {
|
2566
|
+
# "records": [
|
2567
|
+
# {
|
2568
|
+
# "market": "BTC_PERP",
|
2569
|
+
# "fundingTime": "1708704000000",
|
2570
|
+
# "fundingRate": "0.00017674",
|
2571
|
+
# "fundingAmount": "-0.171053531892",
|
2572
|
+
# "positionAmount": "0.019",
|
2573
|
+
# "settlementPrice": "50938.2",
|
2574
|
+
# "rateCalculatedTime": "1708675200000"
|
2575
|
+
# },
|
2576
|
+
# ],
|
2577
|
+
# "limit": 100,
|
2578
|
+
# "offset": 0
|
2579
|
+
# }
|
2580
|
+
#
|
2581
|
+
data = self.safe_list(response, 'records', [])
|
2582
|
+
return self.parse_funding_histories(data, market, since, limit)
|
2583
|
+
|
2584
|
+
def parse_funding_history(self, contract, market: Market = None):
|
2585
|
+
#
|
2586
|
+
# {
|
2587
|
+
# "market": "BTC_PERP",
|
2588
|
+
# "fundingTime": "1708704000000",
|
2589
|
+
# "fundingRate": "0.00017674",
|
2590
|
+
# "fundingAmount": "-0.171053531892",
|
2591
|
+
# "positionAmount": "0.019",
|
2592
|
+
# "settlementPrice": "50938.2",
|
2593
|
+
# "rateCalculatedTime": "1708675200000"
|
2594
|
+
# }
|
2595
|
+
#
|
2596
|
+
marketId = self.safe_string(contract, 'market')
|
2597
|
+
timestamp = self.safe_integer(contract, 'fundingTime')
|
2598
|
+
return {
|
2599
|
+
'info': contract,
|
2600
|
+
'symbol': self.safe_symbol(marketId, market, None, 'swap'),
|
2601
|
+
'code': None,
|
2602
|
+
'timestamp': timestamp,
|
2603
|
+
'datetime': self.iso8601(timestamp),
|
2604
|
+
'id': None,
|
2605
|
+
'amount': self.safe_number(contract, 'fundingAmount'),
|
2606
|
+
}
|
2607
|
+
|
2608
|
+
def parse_funding_histories(self, contracts, market=None, since: Int = None, limit: Int = None) -> List[FundingHistory]:
|
2609
|
+
result = []
|
2610
|
+
for i in range(0, len(contracts)):
|
2611
|
+
contract = contracts[i]
|
2612
|
+
result.append(self.parse_funding_history(contract, market))
|
2613
|
+
sorted = self.sort_by(result, 'timestamp')
|
2614
|
+
return self.filter_by_since_limit(sorted, since, limit)
|
2615
|
+
|
2518
2616
|
async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
|
2519
2617
|
"""
|
2520
2618
|
fetch history of deposits and withdrawals
|
@@ -2585,6 +2683,182 @@ class whitebit(Exchange, ImplicitAPI):
|
|
2585
2683
|
records = self.safe_list(response, 'records')
|
2586
2684
|
return self.parse_transactions(records, currency, since, limit)
|
2587
2685
|
|
2686
|
+
async def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
|
2687
|
+
"""
|
2688
|
+
fetch a quote for converting from one currency to another
|
2689
|
+
|
2690
|
+
https://docs.whitebit.com/private/http-trade-v4/#convert-estimate
|
2691
|
+
|
2692
|
+
:param str fromCode: the currency that you want to sell and convert from
|
2693
|
+
:param str toCode: the currency that you want to buy and convert into
|
2694
|
+
:param float amount: how much you want to trade in units of the from currency
|
2695
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2696
|
+
:returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
|
2697
|
+
"""
|
2698
|
+
await self.load_markets()
|
2699
|
+
fromCurrency = self.currency(fromCode)
|
2700
|
+
toCurrency = self.currency(toCode)
|
2701
|
+
request: dict = {
|
2702
|
+
'from': fromCode,
|
2703
|
+
'to': toCode,
|
2704
|
+
'amount': self.number_to_string(amount),
|
2705
|
+
'direction': 'from',
|
2706
|
+
}
|
2707
|
+
response = await self.v4PrivatePostConvertEstimate(self.extend(request, params))
|
2708
|
+
#
|
2709
|
+
# {
|
2710
|
+
# "give": "4",
|
2711
|
+
# "receive": "0.00004762",
|
2712
|
+
# "rate": "0.0000119",
|
2713
|
+
# "id": "1740889",
|
2714
|
+
# "expireAt": 1741090147,
|
2715
|
+
# "from": "USDT",
|
2716
|
+
# "to": "BTC"
|
2717
|
+
# }
|
2718
|
+
#
|
2719
|
+
return self.parse_conversion(response, fromCurrency, toCurrency)
|
2720
|
+
|
2721
|
+
async def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
|
2722
|
+
"""
|
2723
|
+
convert from one currency to another
|
2724
|
+
|
2725
|
+
https://docs.whitebit.com/private/http-trade-v4/#convert-confirm
|
2726
|
+
|
2727
|
+
:param str id: the id of the trade that you want to make
|
2728
|
+
:param str fromCode: the currency that you want to sell and convert from
|
2729
|
+
:param str toCode: the currency that you want to buy and convert into
|
2730
|
+
:param float [amount]: how much you want to trade in units of the from currency
|
2731
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2732
|
+
:returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
|
2733
|
+
"""
|
2734
|
+
await self.load_markets()
|
2735
|
+
fromCurrency = self.currency(fromCode)
|
2736
|
+
toCurrency = self.currency(toCode)
|
2737
|
+
request: dict = {
|
2738
|
+
'quoteId': id,
|
2739
|
+
}
|
2740
|
+
response = await self.v4PrivatePostConvertConfirm(self.extend(request, params))
|
2741
|
+
#
|
2742
|
+
# {
|
2743
|
+
# "finalGive": "4",
|
2744
|
+
# "finalReceive": "0.00004772"
|
2745
|
+
# }
|
2746
|
+
#
|
2747
|
+
return self.parse_conversion(response, fromCurrency, toCurrency)
|
2748
|
+
|
2749
|
+
async def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Conversion]:
|
2750
|
+
"""
|
2751
|
+
fetch the users history of conversion trades
|
2752
|
+
|
2753
|
+
https://docs.whitebit.com/private/http-trade-v4/#convert-history
|
2754
|
+
|
2755
|
+
:param str [code]: the unified currency code
|
2756
|
+
:param int [since]: the earliest time in ms to fetch conversions for
|
2757
|
+
:param int [limit]: the maximum number of conversion structures to retrieve, default 20, max 200
|
2758
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2759
|
+
:param str [params.until]: the end time in ms
|
2760
|
+
:param str [params.fromTicker]: the currency that you sold and converted from
|
2761
|
+
:param str [params.toTicker]: the currency that you bought and converted into
|
2762
|
+
:param str [params.quoteId]: the quote id of the conversion
|
2763
|
+
:returns dict[]: a list of `conversion structures <https://docs.ccxt.com/#/?id=conversion-structure>`
|
2764
|
+
"""
|
2765
|
+
await self.load_markets()
|
2766
|
+
request: dict = {}
|
2767
|
+
if code is not None:
|
2768
|
+
request['fromTicker'] = code
|
2769
|
+
if since is not None:
|
2770
|
+
start = self.parse_to_int(since / 1000)
|
2771
|
+
request['from'] = self.number_to_string(start)
|
2772
|
+
if limit is not None:
|
2773
|
+
request['limit'] = limit
|
2774
|
+
request, params = self.handle_until_option('to', request, params, 0.001)
|
2775
|
+
response = await self.v4PrivatePostConvertHistory(self.extend(request, params))
|
2776
|
+
#
|
2777
|
+
# {
|
2778
|
+
# "records": [
|
2779
|
+
# {
|
2780
|
+
# "id": "1741105",
|
2781
|
+
# "path": [
|
2782
|
+
# {
|
2783
|
+
# "from": "USDT",
|
2784
|
+
# "to": "BTC",
|
2785
|
+
# "rate": "0.00001193"
|
2786
|
+
# }
|
2787
|
+
# ],
|
2788
|
+
# "date": 1741090757,
|
2789
|
+
# "give": "4",
|
2790
|
+
# "receive": "0.00004772",
|
2791
|
+
# "rate": "0.00001193"
|
2792
|
+
# }
|
2793
|
+
# ],
|
2794
|
+
# "total": 1,
|
2795
|
+
# "limit": 100,
|
2796
|
+
# "offset": 0
|
2797
|
+
# }
|
2798
|
+
#
|
2799
|
+
rows = self.safe_list(response, 'records', [])
|
2800
|
+
return self.parse_conversions(rows, code, 'fromCurrency', 'toCurrency', since, limit)
|
2801
|
+
|
2802
|
+
def parse_conversion(self, conversion: dict, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
|
2803
|
+
#
|
2804
|
+
# fetchConvertQuote
|
2805
|
+
#
|
2806
|
+
# {
|
2807
|
+
# "give": "4",
|
2808
|
+
# "receive": "0.00004762",
|
2809
|
+
# "rate": "0.0000119",
|
2810
|
+
# "id": "1740889",
|
2811
|
+
# "expireAt": 1741090147,
|
2812
|
+
# "from": "USDT",
|
2813
|
+
# "to": "BTC"
|
2814
|
+
# }
|
2815
|
+
#
|
2816
|
+
# createConvertTrade
|
2817
|
+
#
|
2818
|
+
# {
|
2819
|
+
# "finalGive": "4",
|
2820
|
+
# "finalReceive": "0.00004772"
|
2821
|
+
# }
|
2822
|
+
#
|
2823
|
+
# fetchConvertTradeHistory
|
2824
|
+
#
|
2825
|
+
# {
|
2826
|
+
# "id": "1741105",
|
2827
|
+
# "path": [
|
2828
|
+
# {
|
2829
|
+
# "from": "USDT",
|
2830
|
+
# "to": "BTC",
|
2831
|
+
# "rate": "0.00001193"
|
2832
|
+
# }
|
2833
|
+
# ],
|
2834
|
+
# "date": 1741090757,
|
2835
|
+
# "give": "4",
|
2836
|
+
# "receive": "0.00004772",
|
2837
|
+
# "rate": "0.00001193"
|
2838
|
+
# }
|
2839
|
+
#
|
2840
|
+
path = self.safe_list(conversion, 'path', [])
|
2841
|
+
first = self.safe_dict(path, 0, {})
|
2842
|
+
fromPath = self.safe_string(first, 'from')
|
2843
|
+
toPath = self.safe_string(first, 'to')
|
2844
|
+
timestamp = self.safe_timestamp_2(conversion, 'date', 'expireAt')
|
2845
|
+
fromCoin = self.safe_string(conversion, 'from', fromPath)
|
2846
|
+
fromCode = self.safe_currency_code(fromCoin, fromCurrency)
|
2847
|
+
toCoin = self.safe_string(conversion, 'to', toPath)
|
2848
|
+
toCode = self.safe_currency_code(toCoin, toCurrency)
|
2849
|
+
return {
|
2850
|
+
'info': conversion,
|
2851
|
+
'timestamp': timestamp,
|
2852
|
+
'datetime': self.iso8601(timestamp),
|
2853
|
+
'id': self.safe_string(conversion, 'id'),
|
2854
|
+
'fromCurrency': fromCode,
|
2855
|
+
'fromAmount': self.safe_number_2(conversion, 'give', 'finalGive'),
|
2856
|
+
'toCurrency': toCode,
|
2857
|
+
'toAmount': self.safe_number_2(conversion, 'receive', 'finalReceive'),
|
2858
|
+
'price': self.safe_number(conversion, 'rate'),
|
2859
|
+
'fee': None,
|
2860
|
+
}
|
2861
|
+
|
2588
2862
|
def is_fiat(self, currency: str) -> bool:
|
2589
2863
|
fiatCurrencies = self.safe_value(self.options, 'fiatCurrencies', [])
|
2590
2864
|
return self.in_array(currency, fiatCurrencies)
|
ccxt/base/errors.py
CHANGED
@@ -1,9 +1,3 @@
|
|
1
|
-
# ----------------------------------------------------------------------------
|
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
|
-
# EDIT THE CORRESPONDENT .ts FILE INSTEAD
|
6
|
-
|
7
1
|
error_hierarchy = {
|
8
2
|
'BaseError': {
|
9
3
|
'ExchangeError': {
|
ccxt/base/exchange.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
|
-
__version__ = '4.4.
|
7
|
+
__version__ = '4.4.67'
|
8
8
|
|
9
9
|
# -----------------------------------------------------------------------------
|
10
10
|
|
@@ -1742,9 +1742,15 @@ class Exchange(object):
|
|
1742
1742
|
def create_safe_dictionary(self):
|
1743
1743
|
return {}
|
1744
1744
|
|
1745
|
+
def convert_to_safe_dictionary(self, dictionary):
|
1746
|
+
return dictionary
|
1747
|
+
|
1745
1748
|
def rand_number(self, size):
|
1746
1749
|
return int(''.join([str(random.randint(0, 9)) for _ in range(size)]))
|
1747
1750
|
|
1751
|
+
def binary_length(self, binary):
|
1752
|
+
return len(binary)
|
1753
|
+
|
1748
1754
|
# ########################################################################
|
1749
1755
|
# ########################################################################
|
1750
1756
|
# ########################################################################
|
@@ -2001,6 +2007,7 @@ class Exchange(object):
|
|
2001
2007
|
'watchOHLCV': None,
|
2002
2008
|
'watchOHLCVForSymbols': None,
|
2003
2009
|
'watchOrderBook': None,
|
2010
|
+
'watchBidsAsks': None,
|
2004
2011
|
'watchOrderBookForSymbols': None,
|
2005
2012
|
'watchOrders': None,
|
2006
2013
|
'watchOrdersForSymbols': None,
|