ccxt 4.4.64__py2.py3-none-any.whl → 4.4.68__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. ccxt/__init__.py +5 -3
  2. ccxt/abstract/cryptomus.py +20 -0
  3. ccxt/abstract/derive.py +117 -0
  4. ccxt/abstract/tradeogre.py +1 -0
  5. ccxt/abstract/whitebit.py +16 -0
  6. ccxt/async_support/__init__.py +5 -3
  7. ccxt/async_support/base/exchange.py +6 -5
  8. ccxt/async_support/binance.py +5 -3
  9. ccxt/async_support/bitget.py +22 -12
  10. ccxt/async_support/bitrue.py +6 -3
  11. ccxt/async_support/bybit.py +1 -1
  12. ccxt/async_support/coinbase.py +73 -2
  13. ccxt/async_support/cryptocom.py +2 -0
  14. ccxt/async_support/cryptomus.py +1041 -0
  15. ccxt/async_support/derive.py +2530 -0
  16. ccxt/async_support/gate.py +5 -1
  17. ccxt/async_support/htx.py +19 -5
  18. ccxt/async_support/hyperliquid.py +108 -68
  19. ccxt/async_support/luno.py +113 -1
  20. ccxt/async_support/paradex.py +51 -12
  21. ccxt/async_support/tradeogre.py +132 -13
  22. ccxt/async_support/whitebit.py +276 -2
  23. ccxt/base/errors.py +0 -6
  24. ccxt/base/exchange.py +13 -4
  25. ccxt/binance.py +5 -3
  26. ccxt/bitget.py +22 -12
  27. ccxt/bitrue.py +6 -3
  28. ccxt/bybit.py +1 -1
  29. ccxt/coinbase.py +73 -2
  30. ccxt/cryptocom.py +2 -0
  31. ccxt/cryptomus.py +1041 -0
  32. ccxt/derive.py +2529 -0
  33. ccxt/gate.py +5 -1
  34. ccxt/htx.py +19 -5
  35. ccxt/hyperliquid.py +108 -68
  36. ccxt/luno.py +113 -1
  37. ccxt/paradex.py +51 -12
  38. ccxt/pro/__init__.py +3 -3
  39. ccxt/pro/bybit.py +3 -2
  40. ccxt/pro/derive.py +704 -0
  41. ccxt/pro/gate.py +5 -2
  42. ccxt/pro/hyperliquid.py +3 -3
  43. ccxt/test/tests_async.py +36 -3
  44. ccxt/test/tests_sync.py +36 -3
  45. ccxt/tradeogre.py +132 -13
  46. ccxt/whitebit.py +276 -2
  47. {ccxt-4.4.64.dist-info → ccxt-4.4.68.dist-info}/METADATA +16 -12
  48. {ccxt-4.4.64.dist-info → ccxt-4.4.68.dist-info}/RECORD +51 -48
  49. ccxt/abstract/currencycom.py +0 -68
  50. ccxt/async_support/currencycom.py +0 -2070
  51. ccxt/currencycom.py +0 -2070
  52. ccxt/pro/currencycom.py +0 -536
  53. {ccxt-4.4.64.dist-info → ccxt-4.4.68.dist-info}/LICENSE.txt +0 -0
  54. {ccxt-4.4.64.dist-info → ccxt-4.4.68.dist-info}/WHEEL +0 -0
  55. {ccxt-4.4.64.dist-info → ccxt-4.4.68.dist-info}/top_level.txt +0 -0
@@ -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': False,
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': False,
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}': 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
- # "success":true,
342
- # "initialprice":"0.02502002",
343
- # "price":"0.02500000",
344
- # "high":"0.03102001",
345
- # "low":"0.02500000",
346
- # "volume":"0.15549958",
347
- # "bid":"0.02420000",
348
- # "ask":"0.02625000"
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,62 @@ 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
+ :param int [params.until]: timestamp of the latest candle in ms
446
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
447
+ """
448
+ await self.load_markets()
449
+ market = self.market(symbol)
450
+ request: dict = {
451
+ 'market': market['id'],
452
+ 'interval': self.safe_string(self.timeframes, timeframe, timeframe),
453
+ }
454
+ until = self.safe_integer(params, 'until')
455
+ if until is not None:
456
+ params = self.omit(params, 'until')
457
+ request['timestamp'] = until
458
+ response = await self.publicGetChartIntervalMarket(self.extend(request, params))
459
+ #
460
+ # [
461
+ # [
462
+ # 1729130040,
463
+ # 67581.47235999,
464
+ # 67581.47235999,
465
+ # 67338.01,
466
+ # 67338.01,
467
+ # 6.72168016
468
+ # ],
469
+ # ]
470
+ #
471
+ return self.parse_ohlcvs(response, market, timeframe, since, limit)
472
+
473
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
474
+ #
475
+ # [
476
+ # 1729130040,
477
+ # 67581.47235999,
478
+ # 67581.47235999,
479
+ # 67338.01,
480
+ # 67338.01,
481
+ # 6.72168016
482
+ # ]
483
+ #
484
+ return [
485
+ self.safe_timestamp(ohlcv, 0),
486
+ self.safe_number(ohlcv, 1),
487
+ self.safe_number(ohlcv, 3),
488
+ self.safe_number(ohlcv, 4),
489
+ self.safe_number(ohlcv, 2),
490
+ self.safe_number(ohlcv, 5),
491
+ ]
492
+
374
493
  async def fetch_order_book(self, symbol: str, limit: Int = None, params={}):
375
494
  """
376
495
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
@@ -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': False,
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.64'
7
+ __version__ = '4.4.68'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -21,6 +21,7 @@ from ccxt.base.errors import ArgumentsRequired
21
21
  from ccxt.base.errors import BadSymbol
22
22
  from ccxt.base.errors import NullResponse
23
23
  from ccxt.base.errors import RateLimitExceeded
24
+ from ccxt.base.errors import OperationFailed
24
25
  from ccxt.base.errors import BadRequest
25
26
  from ccxt.base.errors import BadResponse
26
27
  from ccxt.base.errors import InvalidProxySettings
@@ -1742,9 +1743,15 @@ class Exchange(object):
1742
1743
  def create_safe_dictionary(self):
1743
1744
  return {}
1744
1745
 
1746
+ def convert_to_safe_dictionary(self, dictionary):
1747
+ return dictionary
1748
+
1745
1749
  def rand_number(self, size):
1746
1750
  return int(''.join([str(random.randint(0, 9)) for _ in range(size)]))
1747
1751
 
1752
+ def binary_length(self, binary):
1753
+ return len(binary)
1754
+
1748
1755
  # ########################################################################
1749
1756
  # ########################################################################
1750
1757
  # ########################################################################
@@ -2001,6 +2008,7 @@ class Exchange(object):
2001
2008
  'watchOHLCV': None,
2002
2009
  'watchOHLCVForSymbols': None,
2003
2010
  'watchOrderBook': None,
2011
+ 'watchBidsAsks': None,
2004
2012
  'watchOrderBookForSymbols': None,
2005
2013
  'watchOrders': None,
2006
2014
  'watchOrdersForSymbols': None,
@@ -4344,14 +4352,15 @@ class Exchange(object):
4344
4352
  try:
4345
4353
  return self.fetch(request['url'], request['method'], request['headers'], request['body'])
4346
4354
  except Exception as e:
4347
- if isinstance(e, NetworkError):
4355
+ if isinstance(e, OperationFailed):
4348
4356
  if i < retries:
4349
4357
  if self.verbose:
4350
4358
  self.log('Request failed with the error: ' + str(e) + ', retrying ' + (i + str(1)) + ' of ' + str(retries) + '...')
4351
4359
  if (retryDelay is not None) and (retryDelay != 0):
4352
4360
  self.sleep(retryDelay)
4353
- # continue #check self
4354
- if i >= retries:
4361
+ else:
4362
+ raise e
4363
+ else:
4355
4364
  raise e
4356
4365
  return None # self line is never reached, but exists for c# value return requirement
4357
4366
 
ccxt/binance.py CHANGED
@@ -6167,7 +6167,8 @@ class binance(Exchange, ImplicitAPI):
6167
6167
  # don't handle/omit params here, omitting happens inside createOrderRequest
6168
6168
  marketType = self.safe_string(params, 'type', market['type'])
6169
6169
  marginMode = self.safe_string(params, 'marginMode')
6170
- isPortfolioMargin = self.safe_bool_2(params, 'papi', 'portfolioMargin', False)
6170
+ porfolioOptionsValue = self.safe_bool_2(self.options, 'papi', 'portfolioMargin', False)
6171
+ isPortfolioMargin = self.safe_bool_2(params, 'papi', 'portfolioMargin', porfolioOptionsValue)
6171
6172
  triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
6172
6173
  stopLossPrice = self.safe_string(params, 'stopLossPrice')
6173
6174
  takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
@@ -6179,8 +6180,9 @@ class binance(Exchange, ImplicitAPI):
6179
6180
  sor = self.safe_bool_2(params, 'sor', 'SOR', False)
6180
6181
  test = self.safe_bool(params, 'test', False)
6181
6182
  params = self.omit(params, ['sor', 'SOR', 'test'])
6182
- if isPortfolioMargin:
6183
- params['portfolioMargin'] = isPortfolioMargin
6183
+ # if isPortfolioMargin:
6184
+ # params['portfolioMargin'] = isPortfolioMargin
6185
+ # }
6184
6186
  request = self.create_order_request(symbol, type, side, amount, price, params)
6185
6187
  response = None
6186
6188
  if market['option']: