ccxt 4.2.93 → 4.2.95

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 (60) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.js +1055 -366
  3. package/dist/ccxt.browser.min.js +3 -3
  4. package/dist/cjs/ccxt.js +1 -1
  5. package/dist/cjs/src/base/Exchange.js +22 -1
  6. package/dist/cjs/src/base/errors.js +25 -64
  7. package/dist/cjs/src/base/ws/OrderBookSide.js +5 -0
  8. package/dist/cjs/src/binance.js +63 -2
  9. package/dist/cjs/src/bitget.js +139 -0
  10. package/dist/cjs/src/bitstamp.js +6 -0
  11. package/dist/cjs/src/coinex.js +61 -55
  12. package/dist/cjs/src/gemini.js +2 -1
  13. package/dist/cjs/src/htx.js +127 -125
  14. package/dist/cjs/src/okx.js +193 -40
  15. package/dist/cjs/src/pro/coinbase.js +18 -0
  16. package/dist/cjs/src/pro/kraken.js +107 -17
  17. package/dist/cjs/src/pro/krakenfutures.js +117 -40
  18. package/dist/cjs/src/pro/kucoin.js +30 -19
  19. package/dist/cjs/src/woo.js +139 -0
  20. package/examples/js/cli.js +4 -1
  21. package/examples/ts/cli.ts +4 -1
  22. package/js/ccxt.d.ts +4 -4
  23. package/js/ccxt.js +3 -3
  24. package/js/src/abstract/binance.d.ts +1 -0
  25. package/js/src/abstract/binancecoinm.d.ts +1 -0
  26. package/js/src/abstract/binanceus.d.ts +1 -0
  27. package/js/src/abstract/binanceusdm.d.ts +1 -0
  28. package/js/src/abstract/bitstamp.d.ts +6 -0
  29. package/js/src/base/Exchange.d.ts +8 -2
  30. package/js/src/base/Exchange.js +22 -1
  31. package/js/src/base/errorHierarchy.d.ts +1 -1
  32. package/js/src/base/errorHierarchy.js +1 -1
  33. package/js/src/base/errors.d.ts +26 -26
  34. package/js/src/base/errors.js +26 -66
  35. package/js/src/base/types.d.ts +12 -0
  36. package/js/src/base/ws/OrderBook.d.ts +7 -0
  37. package/js/src/base/ws/OrderBook.js +1 -6
  38. package/js/src/base/ws/OrderBookSide.d.ts +9 -3
  39. package/js/src/base/ws/OrderBookSide.js +6 -1
  40. package/js/src/binance.d.ts +1 -0
  41. package/js/src/binance.js +63 -2
  42. package/js/src/bitget.d.ts +4 -1
  43. package/js/src/bitget.js +139 -0
  44. package/js/src/bitstamp.js +6 -0
  45. package/js/src/coinex.js +61 -55
  46. package/js/src/gemini.js +2 -1
  47. package/js/src/htx.d.ts +1 -0
  48. package/js/src/htx.js +128 -126
  49. package/js/src/okx.d.ts +4 -1
  50. package/js/src/okx.js +193 -40
  51. package/js/src/pro/coinbase.js +18 -0
  52. package/js/src/pro/kraken.d.ts +6 -1
  53. package/js/src/pro/kraken.js +107 -17
  54. package/js/src/pro/krakenfutures.d.ts +8 -2
  55. package/js/src/pro/krakenfutures.js +117 -40
  56. package/js/src/pro/kucoin.js +30 -19
  57. package/js/src/woo.d.ts +4 -1
  58. package/js/src/woo.js +139 -0
  59. package/package.json +1 -1
  60. package/skip-tests.json +5 -0
@@ -7639,6 +7639,8 @@ class Exchange {
7639
7639
  'fetchClosedOrder': undefined,
7640
7640
  'fetchClosedOrders': undefined,
7641
7641
  'fetchClosedOrdersWs': undefined,
7642
+ 'fetchConvertCurrencies': undefined,
7643
+ 'fetchConvertQuote': undefined,
7642
7644
  'fetchCrossBorrowRate': undefined,
7643
7645
  'fetchCrossBorrowRates': undefined,
7644
7646
  'fetchCurrencies': 'emulated',
@@ -10398,6 +10400,16 @@ class Exchange {
10398
10400
  }
10399
10401
  return result;
10400
10402
  }
10403
+ marketsForSymbols(symbols = undefined) {
10404
+ if (symbols === undefined) {
10405
+ return symbols;
10406
+ }
10407
+ const result = [];
10408
+ for (let i = 0; i < symbols.length; i++) {
10409
+ result.push(this.market(symbols[i]));
10410
+ }
10411
+ return result;
10412
+ }
10401
10413
  marketSymbols(symbols = undefined, type = undefined, allowEmpty = true, sameTypeOnly = false, sameSubTypeOnly = false) {
10402
10414
  if (symbols === undefined) {
10403
10415
  if (!allowEmpty) {
@@ -11746,6 +11758,9 @@ class Exchange {
11746
11758
  async fetchOption(symbol, params = {}) {
11747
11759
  throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' fetchOption() is not supported yet');
11748
11760
  }
11761
+ async fetchConvertQuote(fromCode, toCode, amount = undefined, params = {}) {
11762
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' fetchConvertQuote() is not supported yet');
11763
+ }
11749
11764
  async fetchDepositsWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
11750
11765
  /**
11751
11766
  * @method
@@ -12294,6 +12309,9 @@ class Exchange {
12294
12309
  const fees = await this.fetchTradingFees(params);
12295
12310
  return this.safeDict(fees, symbol);
12296
12311
  }
12312
+ async fetchConvertCurrencies(params = {}) {
12313
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' fetchConvertCurrencies() is not supported yet');
12314
+ }
12297
12315
  parseOpenInterest(interest, market = undefined) {
12298
12316
  throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' parseOpenInterest () is not supported yet');
12299
12317
  }
@@ -12991,7 +13009,10 @@ class Exchange {
12991
13009
  return leverageStructures;
12992
13010
  }
12993
13011
  parseLeverage(leverage, market = undefined) {
12994
- throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' parseLeverage() is not supported yet');
13012
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' parseLeverage () is not supported yet');
13013
+ }
13014
+ parseConversion(conversion, fromCurrency = undefined, toCurrency = undefined) {
13015
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' parseConversion () is not supported yet');
12995
13016
  }
12996
13017
  convertExpireDate(date) {
12997
13018
  // parse YYMMDD to datetime string
@@ -13406,74 +13427,37 @@ __webpack_require__.r(__webpack_exports__);
13406
13427
  /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
13407
13428
  /* harmony export */ });
13408
13429
  /* eslint-disable max-classes-per-file */
13409
- // import { errorHierarchy } from './errorHierarchy.js';
13410
- // Commented out since I'm not sure this is mandatory anymore
13411
- // and does not work out of the box with esm
13412
- // /* ------------------------------------------------------------------------ */
13413
- // function subclass (BaseClass, classes, namespace = {}) {
13414
- // for (const [className, subclasses] of Object.entries (classes)) {
13415
- // const Class = Object.assign (namespace, {
13416
- // /* By creating a named property, we trick compiler to assign our class constructor function a name.
13417
- // Otherwise, all our error constructors would be shown as [Function: Error] in the debugger! And
13418
- // the super-useful `e.constructor.name` magic wouldn't work — we then would have no chance to
13419
- // obtain a error type string from an error instance programmatically! */
13420
- // [className]: class extends BaseClass {
13421
- // constructor (message) {
13422
- // super (message)
13423
- // /* A workaround to make `instanceof` work on custom Error classes in transpiled ES5.
13424
- // See my blog post for the explanation of this hack:
13425
- // https://medium.com/@xpl/javascript-deriving-from-error-properly-8d2f8f315801 */
13426
- // this.constructor = Class
13427
- // this.__proto__ = Class.prototype
13428
- // this.name = className
13429
- // this.message = message
13430
- // // https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work
13431
- // Object.setPrototypeOf (this, Class.prototype)
13432
- // }
13433
- // }
13434
- // })[className]
13435
- // subclass (Class, subclasses, namespace)
13436
- // }
13437
- // return namespace
13438
- // }
13439
13430
  class BaseError extends Error {
13440
13431
  constructor(message) {
13441
13432
  super(message);
13442
13433
  this.name = 'BaseError';
13443
13434
  }
13444
13435
  }
13445
- // Exchange Error errors
13446
- class ExchangeError extends Error {
13436
+ class ExchangeError extends BaseError {
13447
13437
  constructor(message) {
13448
13438
  super(message);
13449
13439
  this.name = 'ExchangeError';
13450
13440
  }
13451
13441
  }
13452
- class ExchangeClosedByUser extends Error {
13453
- constructor(message) {
13454
- super(message);
13455
- this.name = 'ExchangeClosedByUser';
13456
- }
13457
- }
13458
13442
  class AuthenticationError extends ExchangeError {
13459
13443
  constructor(message) {
13460
13444
  super(message);
13461
13445
  this.name = 'AuthenticationError';
13462
13446
  }
13463
13447
  }
13464
- class PermissionDenied extends ExchangeError {
13448
+ class PermissionDenied extends AuthenticationError {
13465
13449
  constructor(message) {
13466
13450
  super(message);
13467
13451
  this.name = 'PermissionDenied';
13468
13452
  }
13469
13453
  }
13470
- class AccountNotEnabled extends ExchangeError {
13454
+ class AccountNotEnabled extends PermissionDenied {
13471
13455
  constructor(message) {
13472
13456
  super(message);
13473
13457
  this.name = 'AccountNotEnabled';
13474
13458
  }
13475
13459
  }
13476
- class AccountSuspended extends ExchangeError {
13460
+ class AccountSuspended extends AuthenticationError {
13477
13461
  constructor(message) {
13478
13462
  super(message);
13479
13463
  this.name = 'AccountSuspended';
@@ -13491,16 +13475,16 @@ class BadRequest extends ExchangeError {
13491
13475
  this.name = 'BadRequest';
13492
13476
  }
13493
13477
  }
13494
- class OperationRejected extends ExchangeError {
13478
+ class BadSymbol extends BadRequest {
13495
13479
  constructor(message) {
13496
13480
  super(message);
13497
- this.name = 'OperationRejected';
13481
+ this.name = 'BadSymbol';
13498
13482
  }
13499
13483
  }
13500
- class BadSymbol extends BadRequest {
13484
+ class OperationRejected extends ExchangeError {
13501
13485
  constructor(message) {
13502
13486
  super(message);
13503
- this.name = 'BadSymbol';
13487
+ this.name = 'OperationRejected';
13504
13488
  }
13505
13489
  }
13506
13490
  class NoChange extends OperationRejected {
@@ -13521,7 +13505,7 @@ class BadResponse extends ExchangeError {
13521
13505
  this.name = 'BadResponse';
13522
13506
  }
13523
13507
  }
13524
- class NullResponse extends ExchangeError {
13508
+ class NullResponse extends BadResponse {
13525
13509
  constructor(message) {
13526
13510
  super(message);
13527
13511
  this.name = 'NullResponse';
@@ -13551,12 +13535,6 @@ class InvalidOrder extends ExchangeError {
13551
13535
  this.name = 'InvalidOrder';
13552
13536
  }
13553
13537
  }
13554
- class ContractUnavailable extends InvalidOrder {
13555
- constructor(message) {
13556
- super(message);
13557
- this.name = 'ContractUnavailable';
13558
- }
13559
- }
13560
13538
  class OrderNotFound extends InvalidOrder {
13561
13539
  constructor(message) {
13562
13540
  super(message);
@@ -13593,25 +13571,36 @@ class DuplicateOrderId extends InvalidOrder {
13593
13571
  this.name = 'DuplicateOrderId';
13594
13572
  }
13595
13573
  }
13574
+ class ContractUnavailable extends InvalidOrder {
13575
+ constructor(message) {
13576
+ super(message);
13577
+ this.name = 'ContractUnavailable';
13578
+ }
13579
+ }
13596
13580
  class NotSupported extends ExchangeError {
13597
13581
  constructor(message) {
13598
13582
  super(message);
13599
13583
  this.name = 'NotSupported';
13600
13584
  }
13601
13585
  }
13602
- class OperationFailed extends BaseError {
13586
+ class ProxyError extends ExchangeError {
13603
13587
  constructor(message) {
13604
13588
  super(message);
13605
- this.name = 'OperationFailed';
13589
+ this.name = 'ProxyError';
13606
13590
  }
13607
13591
  }
13608
- class ProxyError extends ExchangeError {
13592
+ class ExchangeClosedByUser extends ExchangeError {
13593
+ constructor(message) {
13594
+ super(message);
13595
+ this.name = 'ExchangeClosedByUser';
13596
+ }
13597
+ }
13598
+ class OperationFailed extends BaseError {
13609
13599
  constructor(message) {
13610
13600
  super(message);
13611
13601
  this.name = 'OperationFailed';
13612
13602
  }
13613
13603
  }
13614
- // Network error
13615
13604
  class NetworkError extends OperationFailed {
13616
13605
  constructor(message) {
13617
13606
  super(message);
@@ -13654,16 +13643,8 @@ class RequestTimeout extends NetworkError {
13654
13643
  this.name = 'RequestTimeout';
13655
13644
  }
13656
13645
  }
13657
- /* ------------------------------------------------------------------------ */
13658
- // export default subclass (
13659
- // // Root class
13660
- // Error,
13661
- // // Derived class hierarchy
13662
- // errorHierarchy
13663
- // )
13664
- const errors = { BaseError, ExchangeClosedByUser, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
13665
13646
 
13666
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (errors);
13647
+ /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, ProxyError, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout });
13667
13648
 
13668
13649
 
13669
13650
  /***/ }),
@@ -16026,6 +16007,11 @@ class IndexedOrderBook extends OrderBook {
16026
16007
  // Author: github.com/frosty00
16027
16008
  // Email: carlo.revelli@berkeley.edu
16028
16009
  //
16010
+ /**
16011
+ *
16012
+ * @param array
16013
+ * @param x
16014
+ */
16029
16015
  function bisectLeft(array, x) {
16030
16016
  let low = 0;
16031
16017
  let high = array.length - 1;
@@ -18738,6 +18724,8 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
18738
18724
  'fetchCanceledOrders': 'emulated',
18739
18725
  'fetchClosedOrder': false,
18740
18726
  'fetchClosedOrders': 'emulated',
18727
+ 'fetchConvertCurrencies': true,
18728
+ 'fetchConvertQuote': false,
18741
18729
  'fetchCrossBorrowRate': true,
18742
18730
  'fetchCrossBorrowRates': false,
18743
18731
  'fetchCurrencies': true,
@@ -19637,6 +19625,7 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
19637
19625
  },
19638
19626
  'post': {
19639
19627
  'order/oco': 0.2,
19628
+ 'orderList/oco': 0.2,
19640
19629
  'sor/order': 0.2,
19641
19630
  'sor/order/test': 0.2,
19642
19631
  'order': 0.2,
@@ -22904,11 +22893,14 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
22904
22893
  'interval': this.safeString(this.timeframes, timeframe, timeframe),
22905
22894
  'limit': limit,
22906
22895
  };
22896
+ const marketId = market['id'];
22907
22897
  if (price === 'index') {
22908
- request['pair'] = market['id']; // Index price takes this argument instead of symbol
22898
+ const parts = marketId.split('_');
22899
+ const pair = this.safeString(parts, 0);
22900
+ request['pair'] = pair; // Index price takes this argument instead of symbol
22909
22901
  }
22910
22902
  else {
22911
- request['symbol'] = market['id'];
22903
+ request['symbol'] = marketId;
22912
22904
  }
22913
22905
  // const duration = this.parseTimeframe (timeframe);
22914
22906
  if (since !== undefined) {
@@ -31253,6 +31245,61 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
31253
31245
  const modifications = this.parseMarginModifications(response);
31254
31246
  return this.filterBySymbolSinceLimit(modifications, symbol, since, limit);
31255
31247
  }
31248
+ async fetchConvertCurrencies(params = {}) {
31249
+ /**
31250
+ * @method
31251
+ * @name binance#fetchConvertCurrencies
31252
+ * @description fetches all available currencies that can be converted
31253
+ * @see https://binance-docs.github.io/apidocs/spot/en/#query-order-quantity-precision-per-asset-user_data
31254
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
31255
+ * @returns {object} an associative dictionary of currencies
31256
+ */
31257
+ await this.loadMarkets();
31258
+ const response = await this.sapiGetConvertAssetInfo(params);
31259
+ //
31260
+ // [
31261
+ // {
31262
+ // "asset": "BTC",
31263
+ // "fraction": 8
31264
+ // },
31265
+ // ]
31266
+ //
31267
+ const result = {};
31268
+ for (let i = 0; i < response.length; i++) {
31269
+ const entry = response[i];
31270
+ const id = this.safeString(entry, 'asset');
31271
+ const code = this.safeCurrencyCode(id);
31272
+ result[code] = {
31273
+ 'info': entry,
31274
+ 'id': id,
31275
+ 'code': code,
31276
+ 'networks': undefined,
31277
+ 'type': undefined,
31278
+ 'name': undefined,
31279
+ 'active': undefined,
31280
+ 'deposit': undefined,
31281
+ 'withdraw': undefined,
31282
+ 'fee': undefined,
31283
+ 'precision': this.safeInteger(entry, 'fraction'),
31284
+ 'limits': {
31285
+ 'amount': {
31286
+ 'min': undefined,
31287
+ 'max': undefined,
31288
+ },
31289
+ 'withdraw': {
31290
+ 'min': undefined,
31291
+ 'max': undefined,
31292
+ },
31293
+ 'deposit': {
31294
+ 'min': undefined,
31295
+ 'max': undefined,
31296
+ },
31297
+ },
31298
+ 'created': undefined,
31299
+ };
31300
+ }
31301
+ return result;
31302
+ }
31256
31303
  }
31257
31304
 
31258
31305
 
@@ -45895,6 +45942,8 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
45895
45942
  'fetchCanceledAndClosedOrders': true,
45896
45943
  'fetchCanceledOrders': true,
45897
45944
  'fetchClosedOrders': true,
45945
+ 'fetchConvertCurrencies': true,
45946
+ 'fetchConvertQuote': true,
45898
45947
  'fetchCrossBorrowRate': true,
45899
45948
  'fetchCrossBorrowRates': false,
45900
45949
  'fetchCurrencies': true,
@@ -54274,6 +54323,143 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
54274
54323
  'marginMode': marginType,
54275
54324
  };
54276
54325
  }
54326
+ async fetchConvertQuote(fromCode, toCode, amount = undefined, params = {}) {
54327
+ /**
54328
+ * @method
54329
+ * @name bitget#fetchConvertQuote
54330
+ * @description fetch a quote for converting from one currency to another
54331
+ * @see https://www.bitget.com/api-doc/common/convert/Get-Quoted-Price
54332
+ * @param {string} fromCode the currency that you want to sell and convert from
54333
+ * @param {string} toCode the currency that you want to buy and convert into
54334
+ * @param {float} [amount] how much you want to trade in units of the from currency
54335
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
54336
+ * @returns {object} a [conversion structure]{@link https://docs.ccxt.com/#/?id=conversion-structure}
54337
+ */
54338
+ await this.loadMarkets();
54339
+ const request = {
54340
+ 'fromCoin': fromCode.toUpperCase(),
54341
+ 'toCoin': toCode.toUpperCase(),
54342
+ 'fromCoinSize': this.numberToString(amount),
54343
+ };
54344
+ const response = await this.privateConvertGetV2ConvertQuotedPrice(this.extend(request, params));
54345
+ //
54346
+ // {
54347
+ // "code": "00000",
54348
+ // "msg": "success",
54349
+ // "requestTime": 1712121940158,
54350
+ // "data": {
54351
+ // "fromCoin": "USDT",
54352
+ // "fromCoinSize": "5",
54353
+ // "cnvtPrice": "0.9993007892377704",
54354
+ // "toCoin": "USDC",
54355
+ // "toCoinSize": "4.99650394",
54356
+ // "traceId": "1159288930228187140",
54357
+ // "fee": "0"
54358
+ // }
54359
+ // }
54360
+ //
54361
+ const data = this.safeDict(response, 'data', {});
54362
+ const fromCurrencyId = this.safeString(data, 'fromCoin', fromCode);
54363
+ const fromCurrency = this.currency(fromCurrencyId);
54364
+ const toCurrencyId = this.safeString(data, 'toCoin', toCode);
54365
+ const toCurrency = this.currency(toCurrencyId);
54366
+ return this.parseConversion(data, fromCurrency, toCurrency);
54367
+ }
54368
+ parseConversion(conversion, fromCurrency = undefined, toCurrency = undefined) {
54369
+ //
54370
+ // fetchConvertQuote
54371
+ //
54372
+ // {
54373
+ // "fromCoin": "USDT",
54374
+ // "fromCoinSize": "5",
54375
+ // "cnvtPrice": "0.9993007892377704",
54376
+ // "toCoin": "USDC",
54377
+ // "toCoinSize": "4.99650394",
54378
+ // "traceId": "1159288930228187140",
54379
+ // "fee": "0"
54380
+ // }
54381
+ //
54382
+ const timestamp = this.safeInteger(conversion, 'ts');
54383
+ const fromCoin = this.safeString(conversion, 'fromCoin');
54384
+ const fromCode = this.safeCurrencyCode(fromCoin, fromCurrency);
54385
+ const to = this.safeString(conversion, 'toCoin');
54386
+ const toCode = this.safeCurrencyCode(to, toCurrency);
54387
+ return {
54388
+ 'info': conversion,
54389
+ 'timestamp': timestamp,
54390
+ 'datetime': this.iso8601(timestamp),
54391
+ 'id': this.safeString(conversion, 'traceId'),
54392
+ 'fromCurrency': fromCode,
54393
+ 'fromAmount': this.safeNumber(conversion, 'fromCoinSize'),
54394
+ 'toCurrency': toCode,
54395
+ 'toAmount': this.safeNumber(conversion, 'toCoinSize'),
54396
+ 'price': this.safeNumber(conversion, 'cnvtPrice'),
54397
+ 'fee': this.safeNumber(conversion, 'fee'),
54398
+ };
54399
+ }
54400
+ async fetchConvertCurrencies(params = {}) {
54401
+ /**
54402
+ * @method
54403
+ * @name bitget#fetchConvertCurrencies
54404
+ * @description fetches all available currencies that can be converted
54405
+ * @see https://www.bitget.com/api-doc/common/convert/Get-Convert-Currencies
54406
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
54407
+ * @returns {object} an associative dictionary of currencies
54408
+ */
54409
+ await this.loadMarkets();
54410
+ const response = await this.privateConvertGetV2ConvertCurrencies(params);
54411
+ //
54412
+ // {
54413
+ // "code": "00000",
54414
+ // "msg": "success",
54415
+ // "requestTime": 1712121755897,
54416
+ // "data": [
54417
+ // {
54418
+ // "coin": "BTC",
54419
+ // "available": "0.00009850",
54420
+ // "maxAmount": "0.756266",
54421
+ // "minAmount": "0.00001"
54422
+ // },
54423
+ // ]
54424
+ // }
54425
+ //
54426
+ const result = {};
54427
+ const data = this.safeList(response, 'data', []);
54428
+ for (let i = 0; i < data.length; i++) {
54429
+ const entry = data[i];
54430
+ const id = this.safeString(entry, 'coin');
54431
+ const code = this.safeCurrencyCode(id);
54432
+ result[code] = {
54433
+ 'info': entry,
54434
+ 'id': id,
54435
+ 'code': code,
54436
+ 'networks': undefined,
54437
+ 'type': undefined,
54438
+ 'name': undefined,
54439
+ 'active': undefined,
54440
+ 'deposit': undefined,
54441
+ 'withdraw': this.safeNumber(entry, 'available'),
54442
+ 'fee': undefined,
54443
+ 'precision': undefined,
54444
+ 'limits': {
54445
+ 'amount': {
54446
+ 'min': this.safeNumber(entry, 'minAmount'),
54447
+ 'max': this.safeNumber(entry, 'maxAmount'),
54448
+ },
54449
+ 'withdraw': {
54450
+ 'min': undefined,
54451
+ 'max': undefined,
54452
+ },
54453
+ 'deposit': {
54454
+ 'min': undefined,
54455
+ 'max': undefined,
54456
+ },
54457
+ },
54458
+ 'created': undefined,
54459
+ };
54460
+ }
54461
+ return result;
54462
+ }
54277
54463
  handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
54278
54464
  if (!response) {
54279
54465
  return undefined; // fallback to default error handler
@@ -70122,6 +70308,12 @@ class bitstamp extends _abstract_bitstamp_js__WEBPACK_IMPORTED_MODULE_0__/* ["de
70122
70308
  'blur_address/': 1,
70123
70309
  'vext_withdrawal/': 1,
70124
70310
  'vext_address/': 1,
70311
+ 'cspr_withdrawal/': 1,
70312
+ 'cspr_address/': 1,
70313
+ 'vchf_withdrawal/': 1,
70314
+ 'vchf_address/': 1,
70315
+ 'veur_withdrawal/': 1,
70316
+ 'veur_address/': 1,
70125
70317
  },
70126
70318
  },
70127
70319
  },
@@ -104241,8 +104433,8 @@ class coinex extends _abstract_coinex_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
104241
104433
  * @method
104242
104434
  * @name coinex#fetchOrderBook
104243
104435
  * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
104244
- * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot001_market004_market_depth
104245
- * @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http010_market_depth
104436
+ * @see https://docs.coinex.com/api/v2/spot/market/http/list-market-depth
104437
+ * @see https://docs.coinex.com/api/v2/futures/market/http/list-market-depth
104246
104438
  * @param {string} symbol unified symbol of the market to fetch the order book for
104247
104439
  * @param {int} [limit] the maximum amount of order book entries to return
104248
104440
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -104254,65 +104446,71 @@ class coinex extends _abstract_coinex_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
104254
104446
  limit = 20; // default
104255
104447
  }
104256
104448
  const request = {
104257
- 'market': this.marketId(symbol),
104258
- 'merge': '0',
104259
- 'limit': limit.toString(),
104449
+ 'market': market['id'],
104450
+ 'limit': limit,
104451
+ 'interval': '0',
104260
104452
  };
104261
104453
  let response = undefined;
104262
104454
  if (market['swap']) {
104263
- response = await this.v1PerpetualPublicGetMarketDepth(this.extend(request, params));
104455
+ response = await this.v2PublicGetFuturesDepth(this.extend(request, params));
104456
+ //
104457
+ // {
104458
+ // "code": 0,
104459
+ // "data": {
104460
+ // "depth": {
104461
+ // "asks": [
104462
+ // ["70851.94", "0.2119"],
104463
+ // ["70851.95", "0.0004"],
104464
+ // ["70851.96", "0.0004"]
104465
+ // ],
104466
+ // "bids": [
104467
+ // ["70851.93", "1.0314"],
104468
+ // ["70850.93", "0.0021"],
104469
+ // ["70850.42", "0.0306"]
104470
+ // ],
104471
+ // "checksum": 2956436260,
104472
+ // "last": "70851.94",
104473
+ // "updated_at": 1712824003252
104474
+ // },
104475
+ // "is_full": true,
104476
+ // "market": "BTCUSDT"
104477
+ // },
104478
+ // "message": "OK"
104479
+ // }
104480
+ //
104264
104481
  }
104265
104482
  else {
104266
- response = await this.v1PublicGetMarketDepth(this.extend(request, params));
104483
+ response = await this.v2PublicGetSpotDepth(this.extend(request, params));
104484
+ //
104485
+ // {
104486
+ // "code": 0,
104487
+ // "data": {
104488
+ // "depth": {
104489
+ // "asks": [
104490
+ // ["70875.31", "0.28670282"],
104491
+ // ["70875.32", "0.31008114"],
104492
+ // ["70875.42", "0.05876653"]
104493
+ // ],
104494
+ // "bids": [
104495
+ // ["70855.3", "0.00632222"],
104496
+ // ["70855.29", "0.36216834"],
104497
+ // ["70855.17", "0.10166802"]
104498
+ // ],
104499
+ // "checksum": 2313816665,
104500
+ // "last": "70857.19",
104501
+ // "updated_at": 1712823790987
104502
+ // },
104503
+ // "is_full": true,
104504
+ // "market": "BTCUSDT"
104505
+ // },
104506
+ // "message": "OK"
104507
+ // }
104508
+ //
104267
104509
  }
104268
- //
104269
- // Spot
104270
- //
104271
- // {
104272
- // "code": 0,
104273
- // "data": {
104274
- // "asks": [
104275
- // ["41056.33", "0.31727613"],
104276
- // ["41056.34", "1.05657294"],
104277
- // ["41056.35", "0.02346648"]
104278
- // ],
104279
- // "bids": [
104280
- // ["41050.61", "0.40618608"],
104281
- // ["41046.98", "0.13800000"],
104282
- // ["41046.56", "0.22579234"]
104283
- // ],
104284
- // "last": "41050.61",
104285
- // "time": 1650573220346
104286
- // },
104287
- // "message": "OK"
104288
- // }
104289
- //
104290
- // Swap
104291
- //
104292
- // {
104293
- // "code": 0,
104294
- // "data": {
104295
- // "asks": [
104296
- // ["40620.90", "0.0384"],
104297
- // ["40625.50", "0.0219"],
104298
- // ["40625.90", "0.3506"]
104299
- // ],
104300
- // "bids": [
104301
- // ["40620.89", "19.6861"],
104302
- // ["40620.80", "0.0012"],
104303
- // ["40619.87", "0.0365"]
104304
- // ],
104305
- // "last": "40620.89",
104306
- // "time": 1650587672406,
104307
- // "sign_price": "40619.32",
104308
- // "index_price": "40609.93"
104309
- // },
104310
- // "message": "OK"
104311
- // }
104312
- //
104313
- const result = this.safeValue(response, 'data', {});
104314
- const timestamp = this.safeInteger(result, 'time');
104315
- return this.parseOrderBook(result, symbol, timestamp);
104510
+ const data = this.safeDict(response, 'data', {});
104511
+ const depth = this.safeDict(data, 'depth', {});
104512
+ const timestamp = this.safeInteger(depth, 'updated_at');
104513
+ return this.parseOrderBook(depth, symbol, timestamp);
104316
104514
  }
104317
104515
  parseTrade(trade, market = undefined) {
104318
104516
  //
@@ -145528,7 +145726,8 @@ class gemini extends _abstract_gemini_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
145528
145726
  for (let i = 0; i < quoteQurrencies.length; i++) {
145529
145727
  const quoteCurrency = quoteQurrencies[i];
145530
145728
  if (marketIdWithoutPerp.endsWith(quoteCurrency)) {
145531
- baseId = marketIdWithoutPerp.replace(quoteCurrency, '');
145729
+ const quoteLength = this.parseToInt(-1 * quoteCurrency.length);
145730
+ baseId = marketIdWithoutPerp.slice(0, quoteLength);
145532
145731
  quoteId = quoteCurrency;
145533
145732
  if (isPerp) {
145534
145733
  settleId = quoteCurrency; // always same
@@ -153364,14 +153563,8 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
153364
153563
  'fetchMarkets': {
153365
153564
  'types': {
153366
153565
  'spot': true,
153367
- 'future': {
153368
- 'linear': true,
153369
- 'inverse': true,
153370
- },
153371
- 'swap': {
153372
- 'linear': true,
153373
- 'inverse': true,
153374
- },
153566
+ 'linear': true,
153567
+ 'inverse': true,
153375
153568
  },
153376
153569
  },
153377
153570
  'fetchOHLCV': {
@@ -154038,25 +154231,23 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154038
154231
  * @param {object} [params] extra parameters specific to the exchange API endpoint
154039
154232
  * @returns {object[]} an array of objects representing market data
154040
154233
  */
154041
- const options = this.safeValue(this.options, 'fetchMarkets', {});
154042
- const types = this.safeValue(options, 'types', {});
154234
+ let types = undefined;
154235
+ [types, params] = this.handleOptionAndParams(params, 'fetchMarkets', 'types', {});
154043
154236
  let allMarkets = [];
154044
154237
  let promises = [];
154045
154238
  const keys = Object.keys(types);
154046
154239
  for (let i = 0; i < keys.length; i++) {
154047
- const type = keys[i];
154048
- const value = this.safeValue(types, type);
154049
- if (value === true) {
154050
- promises.push(this.fetchMarketsByTypeAndSubType(type, undefined, params));
154051
- }
154052
- else if (value) {
154053
- const subKeys = Object.keys(value);
154054
- for (let j = 0; j < subKeys.length; j++) {
154055
- const subType = subKeys[j];
154056
- const subValue = this.safeValue(value, subType);
154057
- if (subValue) {
154058
- promises.push(this.fetchMarketsByTypeAndSubType(type, subType, params));
154059
- }
154240
+ const key = keys[i];
154241
+ if (this.safeBool(types, key)) {
154242
+ if (key === 'spot') {
154243
+ promises.push(this.fetchMarketsByTypeAndSubType('spot', undefined, params));
154244
+ }
154245
+ else if (key === 'linear') {
154246
+ promises.push(this.fetchMarketsByTypeAndSubType(undefined, 'linear', params));
154247
+ }
154248
+ else if (key === 'inverse') {
154249
+ promises.push(this.fetchMarketsByTypeAndSubType('swap', 'inverse', params));
154250
+ promises.push(this.fetchMarketsByTypeAndSubType('future', 'inverse', params));
154060
154251
  }
154061
154252
  }
154062
154253
  }
@@ -154067,35 +154258,25 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154067
154258
  return allMarkets;
154068
154259
  }
154069
154260
  async fetchMarketsByTypeAndSubType(type, subType, params = {}) {
154070
- const query = this.omit(params, ['type', 'subType']);
154071
- const spot = (type === 'spot');
154072
- const contract = (type !== 'spot');
154073
- const future = (type === 'future');
154074
- const swap = (type === 'swap');
154075
- let linear = undefined;
154076
- let inverse = undefined;
154261
+ const isSpot = (type === 'spot');
154077
154262
  const request = {};
154078
154263
  let response = undefined;
154079
- if (contract) {
154080
- linear = (subType === 'linear');
154081
- inverse = (subType === 'inverse');
154082
- if (linear) {
154083
- if (future) {
154084
- request['business_type'] = 'futures';
154085
- }
154086
- response = await this.contractPublicGetLinearSwapApiV1SwapContractInfo(this.extend(request, query));
154264
+ if (!isSpot) {
154265
+ if (subType === 'linear') {
154266
+ request['business_type'] = 'all'; // override default to fetch all linear markets
154267
+ response = await this.contractPublicGetLinearSwapApiV1SwapContractInfo(this.extend(request, params));
154087
154268
  }
154088
- else if (inverse) {
154089
- if (future) {
154090
- response = await this.contractPublicGetApiV1ContractContractInfo(this.extend(request, query));
154269
+ else if (subType === 'inverse') {
154270
+ if (type === 'future') {
154271
+ response = await this.contractPublicGetApiV1ContractContractInfo(this.extend(request, params));
154091
154272
  }
154092
- else if (swap) {
154093
- response = await this.contractPublicGetSwapApiV1SwapContractInfo(this.extend(request, query));
154273
+ else if (type === 'swap') {
154274
+ response = await this.contractPublicGetSwapApiV1SwapContractInfo(this.extend(request, params));
154094
154275
  }
154095
154276
  }
154096
154277
  }
154097
154278
  else {
154098
- response = await this.spotPublicGetV1CommonSymbols(this.extend(request, query));
154279
+ response = await this.spotPublicGetV1CommonSymbols(this.extend(request, params));
154099
154280
  }
154100
154281
  //
154101
154282
  // spot
@@ -154135,75 +154316,58 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154135
154316
  // ]
154136
154317
  // }
154137
154318
  //
154138
- // inverse future
154319
+ // inverse (swap & future)
154139
154320
  //
154140
154321
  // {
154141
154322
  // "status":"ok",
154142
154323
  // "data":[
154143
154324
  // {
154144
154325
  // "symbol":"BTC",
154145
- // "contract_code":"BTC211126",
154146
- // "contract_type":"this_week",
154147
- // "contract_size":100.000000000000000000,
154148
- // "price_tick":0.010000000000000000,
154149
- // "delivery_date":"20211126",
154150
- // "delivery_time":"1637913600000",
154326
+ // "contract_code":"BTC211126", /// BTC-USD in swap
154327
+ // "contract_type":"this_week", // only in future
154328
+ // "contract_size":100,
154329
+ // "price_tick":0.1,
154330
+ // "delivery_date":"20211126", // only in future
154331
+ // "delivery_time":"1637913600000", // empty in swap
154151
154332
  // "create_date":"20211112",
154152
154333
  // "contract_status":1,
154153
- // "settlement_time":"1637481600000"
154334
+ // "settlement_time":"1637481600000" // only in future
154335
+ // "settlement_date":"16xxxxxxxxxxx" // only in swap
154154
154336
  // },
154337
+ // ...
154155
154338
  // ],
154156
154339
  // "ts":1637474595140
154157
154340
  // }
154158
154341
  //
154159
- // linear futures
154342
+ // linear (swap & future)
154160
154343
  //
154161
154344
  // {
154162
154345
  // "status":"ok",
154163
154346
  // "data":[
154164
154347
  // {
154165
154348
  // "symbol":"BTC",
154166
- // "contract_code":"BTC-USDT-211231",
154167
- // "contract_size":0.001000000000000000,
154168
- // "price_tick":0.100000000000000000,
154169
- // "delivery_date":"20211231",
154170
- // "delivery_time":"1640937600000",
154349
+ // "contract_code":"BTC-USDT-211231", // or "BTC-USDT" in swap
154350
+ // "contract_size":0.001,
154351
+ // "price_tick":0.1,
154352
+ // "delivery_date":"20211231", // empty in swap
154353
+ // "delivery_time":"1640937600000", // empty in swap
154171
154354
  // "create_date":"20211228",
154172
154355
  // "contract_status":1,
154173
154356
  // "settlement_date":"1640764800000",
154174
- // "support_margin_mode":"cross",
154175
- // "business_type":"futures",
154357
+ // "support_margin_mode":"cross", // "all" or "cross"
154358
+ // "business_type":"futures", // "swap" or "futures"
154176
154359
  // "pair":"BTC-USDT",
154177
- // "contract_type":"this_week" // next_week, quarter
154178
- // },
154360
+ // "contract_type":"this_week", // "swap", "this_week", "next_week", "quarter"
154361
+ // "trade_partition":"USDT",
154362
+ // }
154179
154363
  // ],
154180
154364
  // "ts":1640736207263
154181
154365
  // }
154182
154366
  //
154183
- // swaps
154184
- //
154185
- // {
154186
- // "status":"ok",
154187
- // "data":[
154188
- // {
154189
- // "symbol":"BTC",
154190
- // "contract_code":"BTC-USDT",
154191
- // "contract_size":0.001000000000000000,
154192
- // "price_tick":0.100000000000000000,
154193
- // "delivery_time":"",
154194
- // "create_date":"20201021",
154195
- // "contract_status":1,
154196
- // "settlement_date":"1637481600000",
154197
- // "support_margin_mode":"all", // isolated
154198
- // },
154199
- // ],
154200
- // "ts":1637474774467
154201
- // }
154202
- //
154203
- const markets = this.safeValue(response, 'data', []);
154367
+ const markets = this.safeList(response, 'data', []);
154204
154368
  const numMarkets = markets.length;
154205
154369
  if (numMarkets < 1) {
154206
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.NetworkError(this.id + ' fetchMarkets() returned an empty response: ' + this.json(markets));
154370
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.OperationFailed(this.id + ' fetchMarkets() returned an empty response: ' + this.json(response));
154207
154371
  }
154208
154372
  const result = [];
154209
154373
  for (let i = 0; i < markets.length; i++) {
@@ -154213,16 +154377,31 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154213
154377
  let settleId = undefined;
154214
154378
  let id = undefined;
154215
154379
  let lowercaseId = undefined;
154380
+ const contract = ('contract_code' in market);
154381
+ const spot = !contract;
154382
+ let swap = false;
154383
+ let future = false;
154384
+ let linear = undefined;
154385
+ let inverse = undefined;
154386
+ // check if parsed market is contract
154216
154387
  if (contract) {
154217
154388
  id = this.safeString(market, 'contract_code');
154218
154389
  lowercaseId = id.toLowerCase();
154390
+ const delivery_date = this.safeString(market, 'delivery_date');
154391
+ const business_type = this.safeString(market, 'business_type');
154392
+ future = delivery_date !== undefined;
154393
+ swap = !future;
154394
+ linear = business_type !== undefined;
154395
+ inverse = !linear;
154219
154396
  if (swap) {
154397
+ type = 'swap';
154220
154398
  const parts = id.split('-');
154221
154399
  baseId = this.safeStringLower(market, 'symbol');
154222
154400
  quoteId = this.safeStringLower(parts, 1);
154223
154401
  settleId = inverse ? baseId : quoteId;
154224
154402
  }
154225
154403
  else if (future) {
154404
+ type = 'future';
154226
154405
  baseId = this.safeStringLower(market, 'symbol');
154227
154406
  if (inverse) {
154228
154407
  quoteId = 'USD';
@@ -154237,6 +154416,7 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154237
154416
  }
154238
154417
  }
154239
154418
  else {
154419
+ type = 'spot';
154240
154420
  baseId = this.safeString(market, 'base-currency');
154241
154421
  quoteId = this.safeString(market, 'quote-currency');
154242
154422
  id = baseId + quoteId;
@@ -154371,6 +154551,45 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154371
154551
  }
154372
154552
  return result;
154373
154553
  }
154554
+ tryGetSymbolFromFutureMarkets(symbolOrMarketId) {
154555
+ if (symbolOrMarketId in this.markets) {
154556
+ return symbolOrMarketId;
154557
+ }
154558
+ // only on "future" market type (inverse & linear), market-id differs between "fetchMarkets" and "fetchTicker"
154559
+ // so we have to create a mapping
154560
+ // - market-id from fetchMarkts: `BTC-USDT-240419` (linear future) or `BTC240412` (inverse future)
154561
+ // - market-id from fetchTciker[s]: `BTC-USDT-CW` (linear future) or `BTC_CW` (inverse future)
154562
+ if (!('futureMarketIdsForSymbols' in this.options)) {
154563
+ this.options['futureMarketIdsForSymbols'] = {};
154564
+ }
154565
+ const futureMarketIdsForSymbols = this.safeDict(this.options, 'futureMarketIdsForSymbols', {});
154566
+ if (symbolOrMarketId in futureMarketIdsForSymbols) {
154567
+ return futureMarketIdsForSymbols[symbolOrMarketId];
154568
+ }
154569
+ const futureMarkets = this.filterBy(this.markets, 'future', true);
154570
+ const futuresCharsMaps = {
154571
+ 'this_week': 'CW',
154572
+ 'next_week': 'NW',
154573
+ 'quarter': 'CQ',
154574
+ 'next_quarter': 'NQ',
154575
+ };
154576
+ for (let i = 0; i < futureMarkets.length; i++) {
154577
+ const market = futureMarkets[i];
154578
+ const info = this.safeValue(market, 'info', {});
154579
+ const contractType = this.safeString(info, 'contract_type');
154580
+ const contractSuffix = futuresCharsMaps[contractType];
154581
+ // see comment on formats a bit above
154582
+ const constructedId = market['linear'] ? market['base'] + '-' + market['quote'] + '-' + contractSuffix : market['base'] + '_' + contractSuffix;
154583
+ if (constructedId === symbolOrMarketId) {
154584
+ const symbol = market['symbol'];
154585
+ this.options['futureMarketIdsForSymbols'][symbolOrMarketId] = symbol;
154586
+ return symbol;
154587
+ }
154588
+ }
154589
+ // if not found, just save it to avoid unnecessary future iterations
154590
+ this.options['futureMarketIdsForSymbols'][symbolOrMarketId] = symbolOrMarketId;
154591
+ return symbolOrMarketId;
154592
+ }
154374
154593
  parseTicker(ticker, market = undefined) {
154375
154594
  //
154376
154595
  // fetchTicker
@@ -154418,7 +154637,8 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154418
154637
  // }
154419
154638
  //
154420
154639
  const marketId = this.safeString2(ticker, 'symbol', 'contract_code');
154421
- const symbol = this.safeSymbol(marketId, market);
154640
+ let symbol = this.safeSymbol(marketId, market);
154641
+ symbol = this.tryGetSymbolFromFutureMarkets(symbol);
154422
154642
  const timestamp = this.safeInteger2(ticker, 'ts', 'quoteTime');
154423
154643
  let bid = undefined;
154424
154644
  let bidVolume = undefined;
@@ -154561,7 +154781,7 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154561
154781
  * @see https://huobiapi.github.io/docs/usdt_swap/v1/en/#general-get-a-batch-of-market-data-overview
154562
154782
  * @see https://huobiapi.github.io/docs/dm/v1/en/#get-a-batch-of-market-data-overview
154563
154783
  * @see https://huobiapi.github.io/docs/coin_margined_swap/v1/en/#get-a-batch-of-market-data-overview-v2
154564
- * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
154784
+ * @param {string[]} [symbols] unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
154565
154785
  * @param {object} [params] extra parameters specific to the exchange API endpoint
154566
154786
  * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
154567
154787
  */
@@ -154572,22 +154792,30 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154572
154792
  if (first !== undefined) {
154573
154793
  market = this.market(first);
154574
154794
  }
154795
+ const isSubTypeRequested = ('subType' in params) || ('business_type' in params);
154575
154796
  let type = undefined;
154576
154797
  let subType = undefined;
154577
154798
  [type, params] = this.handleMarketTypeAndParams('fetchTickers', market, params);
154578
154799
  [subType, params] = this.handleSubTypeAndParams('fetchTickers', market, params);
154579
154800
  const request = {};
154801
+ const isSpot = (type === 'spot');
154580
154802
  const future = (type === 'future');
154581
154803
  const swap = (type === 'swap');
154582
154804
  const linear = (subType === 'linear');
154583
154805
  const inverse = (subType === 'inverse');
154584
- params = this.omit(params, ['type', 'subType']);
154585
154806
  let response = undefined;
154586
- if (future || swap) {
154807
+ if (!isSpot || isSubTypeRequested) {
154587
154808
  if (linear) {
154809
+ // independently of type, supports calling all linear symbols i.e. fetchTickers(undefined, {subType:'linear'})
154588
154810
  if (future) {
154589
154811
  request['business_type'] = 'futures';
154590
154812
  }
154813
+ else if (swap) {
154814
+ request['business_type'] = 'swap';
154815
+ }
154816
+ else {
154817
+ request['business_type'] = 'all';
154818
+ }
154591
154819
  response = await this.contractPublicGetLinearSwapExMarketDetailBatchMerged(this.extend(request, params));
154592
154820
  }
154593
154821
  else if (inverse) {
@@ -154597,6 +154825,12 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154597
154825
  else if (swap) {
154598
154826
  response = await this.contractPublicGetSwapExMarketDetailBatchMerged(this.extend(request, params));
154599
154827
  }
154828
+ else {
154829
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' fetchTickers() you have to set params["type"] to either "swap" or "future" for inverse contracts');
154830
+ }
154831
+ }
154832
+ else {
154833
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' fetchTickers() you have to set params["subType"] to either "linear" or "inverse" for contracts');
154600
154834
  }
154601
154835
  }
154602
154836
  else {
@@ -154652,42 +154886,9 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154652
154886
  // "ts":1637504679376
154653
154887
  // }
154654
154888
  //
154655
- const tickers = this.safeValue2(response, 'data', 'ticks', []);
154656
- const timestamp = this.safeInteger(response, 'ts');
154657
- const result = {};
154658
- for (let i = 0; i < tickers.length; i++) {
154659
- const ticker = this.parseTicker(tickers[i]);
154660
- // the market ids for linear futures are non-standard and differ from all the other endpoints
154661
- // we are doing a linear-matching here
154662
- if (future && linear) {
154663
- for (let j = 0; j < this.symbols.length; j++) {
154664
- const symbolInner = this.symbols[j];
154665
- const marketInner = this.market(symbolInner);
154666
- const contractType = this.safeString(marketInner['info'], 'contract_type');
154667
- if ((contractType === 'this_week') && (ticker['symbol'] === (marketInner['baseId'] + '-' + marketInner['quoteId'] + '-CW'))) {
154668
- ticker['symbol'] = marketInner['symbol'];
154669
- break;
154670
- }
154671
- else if ((contractType === 'next_week') && (ticker['symbol'] === (marketInner['baseId'] + '-' + marketInner['quoteId'] + '-NW'))) {
154672
- ticker['symbol'] = marketInner['symbol'];
154673
- break;
154674
- }
154675
- else if ((contractType === 'this_quarter') && (ticker['symbol'] === (marketInner['baseId'] + '-' + marketInner['quoteId'] + '-CQ'))) {
154676
- ticker['symbol'] = marketInner['symbol'];
154677
- break;
154678
- }
154679
- else if ((contractType === 'next_quarter') && (ticker['symbol'] === (marketInner['baseId'] + '-' + marketInner['quoteId'] + '-NQ'))) {
154680
- ticker['symbol'] = marketInner['symbol'];
154681
- break;
154682
- }
154683
- }
154684
- }
154685
- const symbol = ticker['symbol'];
154686
- ticker['timestamp'] = timestamp;
154687
- ticker['datetime'] = this.iso8601(timestamp);
154688
- result[symbol] = ticker;
154689
- }
154690
- return this.filterByArrayTickers(result, 'symbol', symbols);
154889
+ const rawTickers = this.safeList2(response, 'data', 'ticks', []);
154890
+ const tickers = this.parseTickers(rawTickers, symbols, params);
154891
+ return this.filterByArrayTickers(tickers, 'symbol', symbols);
154691
154892
  }
154692
154893
  async fetchLastPrices(symbols = undefined, params = {}) {
154693
154894
  /**
@@ -154697,7 +154898,7 @@ class htx extends _abstract_htx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
154697
154898
  * @see https://www.htx.com/en-us/opend/newApiPages/?id=8cb81024-77b5-11ed-9966-0242ac110003 linear swap & linear future
154698
154899
  * @see https://www.htx.com/en-us/opend/newApiPages/?id=28c2e8fc-77ae-11ed-9966-0242ac110003 inverse future
154699
154900
  * @see https://www.htx.com/en-us/opend/newApiPages/?id=5d517ef5-77b6-11ed-9966-0242ac110003 inverse swap
154700
- * @param {string[]|undefined} symbols unified symbols of the markets to fetch the last prices
154901
+ * @param {string[]} [symbols] unified symbols of the markets to fetch the last prices
154701
154902
  * @param {object} [params] extra parameters specific to the exchange API endpoint
154702
154903
  * @returns {object} a dictionary of lastprices structures
154703
154904
  */
@@ -206973,6 +207174,8 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
206973
207174
  'fetchCanceledOrders': true,
206974
207175
  'fetchClosedOrder': undefined,
206975
207176
  'fetchClosedOrders': true,
207177
+ 'fetchConvertCurrencies': true,
207178
+ 'fetchConvertQuote': true,
206976
207179
  'fetchCrossBorrowRate': true,
206977
207180
  'fetchCrossBorrowRates': true,
206978
207181
  'fetchCurrencies': true,
@@ -208028,7 +208231,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
208028
208231
  return super.handleMarketTypeAndParams(methodName, market, params);
208029
208232
  }
208030
208233
  convertToInstrumentType(type) {
208031
- const exchangeTypes = this.safeValue(this.options, 'exchangeType', {});
208234
+ const exchangeTypes = this.safeDict(this.options, 'exchangeType', {});
208032
208235
  return this.safeString(exchangeTypes, type, type);
208033
208236
  }
208034
208237
  createExpiredOptionMarket(symbol) {
@@ -209832,7 +210035,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
209832
210035
  const side = this.safeString(rawOrder, 'side');
209833
210036
  const amount = this.safeValue(rawOrder, 'amount');
209834
210037
  const price = this.safeValue(rawOrder, 'price');
209835
- const orderParams = this.safeValue(rawOrder, 'params', {});
210038
+ const orderParams = this.safeDict(rawOrder, 'params', {});
209836
210039
  const extendedParams = this.extend(orderParams, params); // the request does not accept extra params since it's a list, so we're extending each order with the common params
209837
210040
  const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, extendedParams);
209838
210041
  ordersRequests.push(orderRequest);
@@ -210021,8 +210224,8 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
210021
210224
  // "msg": ""
210022
210225
  // }
210023
210226
  //
210024
- const data = this.safeValue(response, 'data', []);
210025
- const first = this.safeValue(data, 0);
210227
+ const data = this.safeList(response, 'data', []);
210228
+ const first = this.safeDict(data, 0, {});
210026
210229
  const order = this.parseOrder(first, market);
210027
210230
  order['type'] = type;
210028
210231
  order['side'] = side;
@@ -211221,7 +211424,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
211221
211424
  if (paginate) {
211222
211425
  return await this.fetchPaginatedCallDynamic('fetchLedger', code, since, limit, params);
211223
211426
  }
211224
- const options = this.safeValue(this.options, 'fetchLedger', {});
211427
+ const options = this.safeDict(this.options, 'fetchLedger', {});
211225
211428
  let method = this.safeString(options, 'method');
211226
211429
  method = this.safeString(params, 'method', method);
211227
211430
  params = this.omit(params, 'method');
@@ -211550,7 +211753,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
211550
211753
  // ]
211551
211754
  // }
211552
211755
  //
211553
- const data = this.safeValue(response, 'data', []);
211756
+ const data = this.safeList(response, 'data', []);
211554
211757
  const filtered = this.filterBy(data, 'selected', true);
211555
211758
  const parsed = this.parseDepositAddresses(filtered, [currency['code']], false);
211556
211759
  return this.indexBy(parsed, 'network');
@@ -211624,7 +211827,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
211624
211827
  };
211625
211828
  let network = this.safeString(params, 'network'); // this line allows the user to specify either ERC20 or ETH
211626
211829
  if (network !== undefined) {
211627
- const networks = this.safeValue(this.options, 'networks', {});
211830
+ const networks = this.safeDict(this.options, 'networks', {});
211628
211831
  network = this.safeString(networks, network.toUpperCase(), network); // handle ETH>ERC20 alias
211629
211832
  request['chain'] = currency['id'] + '-' + network;
211630
211833
  params = this.omit(params, 'network');
@@ -211633,7 +211836,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
211633
211836
  if (fee === undefined) {
211634
211837
  const currencies = await this.fetchCurrencies();
211635
211838
  this.currencies = this.deepExtend(this.currencies, currencies);
211636
- const targetNetwork = this.safeValue(currency['networks'], this.networkIdToCode(network), {});
211839
+ const targetNetwork = this.safeDict(currency['networks'], this.networkIdToCode(network), {});
211637
211840
  fee = this.safeString(targetNetwork, 'fee');
211638
211841
  if (fee === undefined) {
211639
211842
  throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' withdraw() requires a "fee" string parameter, network transaction fee must be ≥ 0. Withdrawals to OKCoin or OKX are fee-free, please set "0". Withdrawing to external digital asset address requires network transaction fee.');
@@ -211655,7 +211858,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
211655
211858
  // ]
211656
211859
  // }
211657
211860
  //
211658
- const data = this.safeValue(response, 'data', []);
211861
+ const data = this.safeList(response, 'data', []);
211659
211862
  const transaction = this.safeDict(data, 0);
211660
211863
  return this.parseTransaction(transaction, currency);
211661
211864
  }
@@ -211880,7 +212083,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
211880
212083
  // "msg": ''
211881
212084
  // }
211882
212085
  //
211883
- const data = this.safeValue(response, 'data');
212086
+ const data = this.safeList(response, 'data', []);
211884
212087
  const withdrawal = this.safeDict(data, 0, {});
211885
212088
  return this.parseTransaction(withdrawal);
211886
212089
  }
@@ -212167,8 +212370,8 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
212167
212370
  // ]
212168
212371
  // }
212169
212372
  //
212170
- const data = this.safeValue(response, 'data', []);
212171
- const position = this.safeValue(data, 0);
212373
+ const data = this.safeList(response, 'data', []);
212374
+ const position = this.safeDict(data, 0);
212172
212375
  if (position === undefined) {
212173
212376
  return undefined;
212174
212377
  }
@@ -212204,7 +212407,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
212204
212407
  request['instId'] = marketIds.join(',');
212205
212408
  }
212206
212409
  }
212207
- const fetchPositionsOptions = this.safeValue(this.options, 'fetchPositions', {});
212410
+ const fetchPositionsOptions = this.safeDict(this.options, 'fetchPositions', {});
212208
212411
  const method = this.safeString(fetchPositionsOptions, 'method', 'privateGetAccountPositions');
212209
212412
  let response = undefined;
212210
212413
  if (method === 'privateGetAccountPositionsHistory') {
@@ -212259,7 +212462,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
212259
212462
  // ]
212260
212463
  // }
212261
212464
  //
212262
- const positions = this.safeValue(response, 'data', []);
212465
+ const positions = this.safeList(response, 'data', []);
212263
212466
  const result = [];
212264
212467
  for (let i = 0; i < positions.length; i++) {
212265
212468
  result.push(this.parsePosition(positions[i]));
@@ -212467,7 +212670,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
212467
212670
  */
212468
212671
  await this.loadMarkets();
212469
212672
  const currency = this.currency(code);
212470
- const accountsByType = this.safeValue(this.options, 'accountsByType', {});
212673
+ const accountsByType = this.safeDict(this.options, 'accountsByType', {});
212471
212674
  const fromId = this.safeString(accountsByType, fromAccount, fromAccount);
212472
212675
  const toId = this.safeString(accountsByType, toAccount, toAccount);
212473
212676
  const request = {
@@ -212509,7 +212712,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
212509
212712
  // ]
212510
212713
  // }
212511
212714
  //
212512
- const data = this.safeValue(response, 'data', []);
212715
+ const data = this.safeList(response, 'data', []);
212513
212716
  const rawTransfer = this.safeDict(data, 0, {});
212514
212717
  return this.parseTransfer(rawTransfer, currency);
212515
212718
  }
@@ -212572,7 +212775,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
212572
212775
  let amount = this.safeNumber(transfer, 'amt');
212573
212776
  const fromAccountId = this.safeString(transfer, 'from');
212574
212777
  const toAccountId = this.safeString(transfer, 'to');
212575
- const accountsById = this.safeValue(this.options, 'accountsById', {});
212778
+ const accountsById = this.safeDict(this.options, 'accountsById', {});
212576
212779
  const timestamp = this.safeInteger(transfer, 'ts');
212577
212780
  const balanceChange = this.safeString(transfer, 'sz');
212578
212781
  if (balanceChange !== undefined) {
@@ -212623,7 +212826,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
212623
212826
  // "msg": ""
212624
212827
  // }
212625
212828
  //
212626
- const data = this.safeValue(response, 'data', []);
212829
+ const data = this.safeList(response, 'data', []);
212627
212830
  const transfer = this.safeDict(data, 0);
212628
212831
  return this.parseTransfer(transfer);
212629
212832
  }
@@ -212829,8 +213032,8 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
212829
213032
  // "msg": ""
212830
213033
  // }
212831
213034
  //
212832
- const data = this.safeValue(response, 'data', []);
212833
- const entry = this.safeValue(data, 0, {});
213035
+ const data = this.safeList(response, 'data', []);
213036
+ const entry = this.safeDict(data, 0, {});
212834
213037
  return this.parseFundingRate(entry, market);
212835
213038
  }
212836
213039
  async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
@@ -212970,7 +213173,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
212970
213173
  // "type": "8"
212971
213174
  // }
212972
213175
  //
212973
- const data = this.safeValue(response, 'data', []);
213176
+ const data = this.safeList(response, 'data', []);
212974
213177
  const result = [];
212975
213178
  for (let i = 0; i < data.length; i++) {
212976
213179
  const entry = data[i];
@@ -213162,7 +213365,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
213162
213365
  // ],
213163
213366
  // }
213164
213367
  //
213165
- const data = this.safeValue(response, 'data', []);
213368
+ const data = this.safeList(response, 'data', []);
213166
213369
  const rates = [];
213167
213370
  for (let i = 0; i < data.length; i++) {
213168
213371
  rates.push(this.parseBorrowRate(data[i]));
@@ -213198,8 +213401,8 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
213198
213401
  // "msg": ""
213199
213402
  // }
213200
213403
  //
213201
- const data = this.safeValue(response, 'data');
213202
- const rate = this.safeValue(data, 0);
213404
+ const data = this.safeList(response, 'data', []);
213405
+ const rate = this.safeDict(data, 0, {});
213203
213406
  return this.parseBorrowRate(rate);
213204
213407
  }
213205
213408
  parseBorrowRate(info, currency = undefined) {
@@ -213303,7 +213506,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
213303
213506
  // "msg": ""
213304
213507
  // }
213305
213508
  //
213306
- const data = this.safeValue(response, 'data');
213509
+ const data = this.safeList(response, 'data', []);
213307
213510
  return this.parseBorrowRateHistories(data, codes, since, limit);
213308
213511
  }
213309
213512
  async fetchBorrowRateHistory(code, since = undefined, limit = undefined, params = {}) {
@@ -213347,7 +213550,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
213347
213550
  // "msg": ""
213348
213551
  // }
213349
213552
  //
213350
- const data = this.safeValue(response, 'data');
213553
+ const data = this.safeList(response, 'data', []);
213351
213554
  return this.parseBorrowRateHistory(data, code, since, limit);
213352
213555
  }
213353
213556
  async modifyMarginHelper(symbol, amount, type, params = {}) {
@@ -213539,7 +213742,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
213539
213742
  // ]
213540
213743
  // }
213541
213744
  //
213542
- const data = this.safeValue(response, 'data');
213745
+ const data = this.safeList(response, 'data', []);
213543
213746
  return this.parseMarketLeverageTiers(data, market);
213544
213747
  }
213545
213748
  parseMarketLeverageTiers(info, market = undefined) {
@@ -213641,7 +213844,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
213641
213844
  // "msg": ""
213642
213845
  // }
213643
213846
  //
213644
- const data = this.safeValue(response, 'data');
213847
+ const data = this.safeList(response, 'data', []);
213645
213848
  const interest = this.parseBorrowInterests(data);
213646
213849
  return this.filterByCurrencySinceLimit(interest, code, since, limit);
213647
213850
  }
@@ -213697,8 +213900,8 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
213697
213900
  // "msg": ""
213698
213901
  // }
213699
213902
  //
213700
- const data = this.safeValue(response, 'data', []);
213701
- const loan = this.safeValue(data, 0);
213903
+ const data = this.safeList(response, 'data', []);
213904
+ const loan = this.safeDict(data, 0, {});
213702
213905
  return this.parseMarginLoan(loan, currency);
213703
213906
  }
213704
213907
  async repayCrossMargin(code, amount, params = {}) {
@@ -213742,8 +213945,8 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
213742
213945
  // "msg": ""
213743
213946
  // }
213744
213947
  //
213745
- const data = this.safeValue(response, 'data', []);
213746
- const loan = this.safeValue(data, 0);
213948
+ const data = this.safeList(response, 'data', []);
213949
+ const loan = this.safeDict(data, 0, {});
213747
213950
  return this.parseMarginLoan(loan, currency);
213748
213951
  }
213749
213952
  parseMarginLoan(info, currency = undefined) {
@@ -213825,8 +214028,8 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
213825
214028
  * @param {int} [params.until] The time in ms of the latest record to retrieve as a unix timestamp
213826
214029
  * @returns An array of [open interest structures]{@link https://docs.ccxt.com/#/?id=open-interest-structure}
213827
214030
  */
213828
- const options = this.safeValue(this.options, 'fetchOpenInterestHistory', {});
213829
- const timeframes = this.safeValue(options, 'timeframes', {});
214031
+ const options = this.safeDict(this.options, 'fetchOpenInterestHistory', {});
214032
+ const timeframes = this.safeDict(options, 'timeframes', {});
213830
214033
  timeframe = this.safeString(timeframes, timeframe, timeframe);
213831
214034
  if (timeframe !== '5m' && timeframe !== '1H' && timeframe !== '1D') {
213832
214035
  throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest(this.id + ' fetchOpenInterestHistory cannot only use the 5m, 1h, and 1d timeframe');
@@ -214116,7 +214319,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
214116
214319
  // "msg": ""
214117
214320
  // }
214118
214321
  //
214119
- const data = this.safeValue(response, 'data', []);
214322
+ const data = this.safeList(response, 'data', []);
214120
214323
  const settlements = this.parseSettlements(data, market);
214121
214324
  const sorted = this.sortBy(settlements, 'timestamp');
214122
214325
  return this.filterBySymbolSinceLimit(sorted, market['symbol'], since, limit);
@@ -214155,7 +214358,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
214155
214358
  for (let i = 0; i < settlements.length; i++) {
214156
214359
  const entry = settlements[i];
214157
214360
  const timestamp = this.safeInteger(entry, 'ts');
214158
- const details = this.safeValue(entry, 'details', []);
214361
+ const details = this.safeList(entry, 'details', []);
214159
214362
  for (let j = 0; j < details.length; j++) {
214160
214363
  const settlement = this.parseSettlement(details[j], market);
214161
214364
  result.push(this.extend(settlement, {
@@ -214201,7 +214404,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
214201
214404
  // "msg": ""
214202
214405
  // }
214203
214406
  //
214204
- const underlyings = this.safeValue(response, 'data', []);
214407
+ const underlyings = this.safeList(response, 'data', []);
214205
214408
  return underlyings[0];
214206
214409
  }
214207
214410
  async fetchGreeks(symbol, params = {}) {
@@ -214253,7 +214456,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
214253
214456
  // "msg": ""
214254
214457
  // }
214255
214458
  //
214256
- const data = this.safeValue(response, 'data', []);
214459
+ const data = this.safeList(response, 'data', []);
214257
214460
  for (let i = 0; i < data.length; i++) {
214258
214461
  const entry = data[i];
214259
214462
  const entryMarketId = this.safeString(entry, 'instId');
@@ -214376,7 +214579,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
214376
214579
  // "outTime": "1701877077102579"
214377
214580
  // }
214378
214581
  //
214379
- const data = this.safeValue(response, 'data');
214582
+ const data = this.safeList(response, 'data', []);
214380
214583
  const order = this.safeDict(data, 0);
214381
214584
  return this.parseOrder(order, market);
214382
214585
  }
@@ -214517,6 +214720,157 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
214517
214720
  'quoteVolume': undefined,
214518
214721
  };
214519
214722
  }
214723
+ async fetchConvertQuote(fromCode, toCode, amount = undefined, params = {}) {
214724
+ /**
214725
+ * @method
214726
+ * @name okx#fetchConvertQuote
214727
+ * @description fetch a quote for converting from one currency to another
214728
+ * @see https://www.okx.com/docs-v5/en/#funding-account-rest-api-estimate-quote
214729
+ * @param {string} fromCode the currency that you want to sell and convert from
214730
+ * @param {string} toCode the currency that you want to buy and convert into
214731
+ * @param {float} [amount] how much you want to trade in units of the from currency
214732
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
214733
+ * @returns {object} a [conversion structure]{@link https://docs.ccxt.com/#/?id=conversion-structure}
214734
+ */
214735
+ await this.loadMarkets();
214736
+ const request = {
214737
+ 'baseCcy': fromCode.toUpperCase(),
214738
+ 'quoteCcy': toCode.toUpperCase(),
214739
+ 'rfqSzCcy': fromCode.toUpperCase(),
214740
+ 'rfqSz': this.numberToString(amount),
214741
+ 'side': 'sell',
214742
+ };
214743
+ const response = await this.privatePostAssetConvertEstimateQuote(this.extend(request, params));
214744
+ //
214745
+ // {
214746
+ // "code": "0",
214747
+ // "data": [
214748
+ // {
214749
+ // "baseCcy": "ETH",
214750
+ // "baseSz": "0.01023052",
214751
+ // "clQReqId": "",
214752
+ // "cnvtPx": "2932.40104429",
214753
+ // "origRfqSz": "30",
214754
+ // "quoteCcy": "USDT",
214755
+ // "quoteId": "quoterETH-USDT16461885104612381",
214756
+ // "quoteSz": "30",
214757
+ // "quoteTime": "1646188510461",
214758
+ // "rfqSz": "30",
214759
+ // "rfqSzCcy": "USDT",
214760
+ // "side": "buy",
214761
+ // "ttlMs": "10000"
214762
+ // }
214763
+ // ],
214764
+ // "msg": ""
214765
+ // }
214766
+ //
214767
+ const data = this.safeList(response, 'data', []);
214768
+ const result = this.safeDict(data, 0, {});
214769
+ const fromCurrencyId = this.safeString(result, 'baseCcy', fromCode);
214770
+ const fromCurrency = this.currency(fromCurrencyId);
214771
+ const toCurrencyId = this.safeString(result, 'quoteCcy', toCode);
214772
+ const toCurrency = this.currency(toCurrencyId);
214773
+ return this.parseConversion(result, fromCurrency, toCurrency);
214774
+ }
214775
+ parseConversion(conversion, fromCurrency = undefined, toCurrency = undefined) {
214776
+ //
214777
+ // fetchConvertQuote
214778
+ //
214779
+ // {
214780
+ // "baseCcy": "ETH",
214781
+ // "baseSz": "0.01023052",
214782
+ // "clQReqId": "",
214783
+ // "cnvtPx": "2932.40104429",
214784
+ // "origRfqSz": "30",
214785
+ // "quoteCcy": "USDT",
214786
+ // "quoteId": "quoterETH-USDT16461885104612381",
214787
+ // "quoteSz": "30",
214788
+ // "quoteTime": "1646188510461",
214789
+ // "rfqSz": "30",
214790
+ // "rfqSzCcy": "USDT",
214791
+ // "side": "buy",
214792
+ // "ttlMs": "10000"
214793
+ // }
214794
+ //
214795
+ const timestamp = this.safeInteger(conversion, 'quoteTime');
214796
+ const fromCoin = this.safeString(conversion, 'baseCcy');
214797
+ const fromCode = this.safeCurrencyCode(fromCoin, fromCurrency);
214798
+ const to = this.safeString(conversion, 'quoteCcy');
214799
+ const toCode = this.safeCurrencyCode(to, toCurrency);
214800
+ return {
214801
+ 'info': conversion,
214802
+ 'timestamp': timestamp,
214803
+ 'datetime': this.iso8601(timestamp),
214804
+ 'id': this.safeString(conversion, 'clQReqId'),
214805
+ 'fromCurrency': fromCode,
214806
+ 'fromAmount': this.safeNumber(conversion, 'baseSz'),
214807
+ 'toCurrency': toCode,
214808
+ 'toAmount': this.safeNumber(conversion, 'quoteSz'),
214809
+ 'price': this.safeNumber(conversion, 'cnvtPx'),
214810
+ 'fee': undefined,
214811
+ };
214812
+ }
214813
+ async fetchConvertCurrencies(params = {}) {
214814
+ /**
214815
+ * @method
214816
+ * @name okx#fetchConvertCurrencies
214817
+ * @description fetches all available currencies that can be converted
214818
+ * @see https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-convert-currencies
214819
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
214820
+ * @returns {object} an associative dictionary of currencies
214821
+ */
214822
+ await this.loadMarkets();
214823
+ const response = await this.privateGetAssetConvertCurrencies(params);
214824
+ //
214825
+ // {
214826
+ // "code": "0",
214827
+ // "data": [
214828
+ // {
214829
+ // "ccy": "BTC",
214830
+ // "max": "",
214831
+ // "min": ""
214832
+ // },
214833
+ // ],
214834
+ // "msg": ""
214835
+ // }
214836
+ //
214837
+ const result = {};
214838
+ const data = this.safeList(response, 'data', []);
214839
+ for (let i = 0; i < data.length; i++) {
214840
+ const entry = data[i];
214841
+ const id = this.safeString(entry, 'ccy');
214842
+ const code = this.safeCurrencyCode(id);
214843
+ result[code] = {
214844
+ 'info': entry,
214845
+ 'id': id,
214846
+ 'code': code,
214847
+ 'networks': undefined,
214848
+ 'type': undefined,
214849
+ 'name': undefined,
214850
+ 'active': undefined,
214851
+ 'deposit': undefined,
214852
+ 'withdraw': undefined,
214853
+ 'fee': undefined,
214854
+ 'precision': undefined,
214855
+ 'limits': {
214856
+ 'amount': {
214857
+ 'min': this.safeNumber(entry, 'min'),
214858
+ 'max': this.safeNumber(entry, 'max'),
214859
+ },
214860
+ 'withdraw': {
214861
+ 'min': undefined,
214862
+ 'max': undefined,
214863
+ },
214864
+ 'deposit': {
214865
+ 'min': undefined,
214866
+ 'max': undefined,
214867
+ },
214868
+ },
214869
+ 'created': undefined,
214870
+ };
214871
+ }
214872
+ return result;
214873
+ }
214520
214874
  handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
214521
214875
  if (!response) {
214522
214876
  return undefined; // fallback to default error handler
@@ -214544,7 +214898,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
214544
214898
  const code = this.safeString(response, 'code');
214545
214899
  if ((code !== '0') && (code !== '2')) { // 2 means that bulk operation partially succeeded
214546
214900
  const feedback = this.id + ' ' + body;
214547
- const data = this.safeValue(response, 'data', []);
214901
+ const data = this.safeList(response, 'data', []);
214548
214902
  for (let i = 0; i < data.length; i++) {
214549
214903
  const error = data[i];
214550
214904
  const errorCode = this.safeString(error, 'sCode');
@@ -248168,6 +248522,9 @@ class coinbase extends _coinbase_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] *
248168
248522
  const messageHash = channel + '::' + wsMarketId;
248169
248523
  newTickers.push(result);
248170
248524
  client.resolve(result, messageHash);
248525
+ if (messageHash.endsWith('USD')) {
248526
+ client.resolve(result, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
248527
+ }
248171
248528
  }
248172
248529
  }
248173
248530
  const messageHashes = this.findMessageHashes(client, 'ticker_batch::');
@@ -248179,6 +248536,9 @@ class coinbase extends _coinbase_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] *
248179
248536
  const tickers = this.filterByArray(newTickers, 'symbol', symbols);
248180
248537
  if (!this.isEmpty(tickers)) {
248181
248538
  client.resolve(tickers, messageHash);
248539
+ if (messageHash.endsWith('USD')) {
248540
+ client.resolve(tickers, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
248541
+ }
248182
248542
  }
248183
248543
  }
248184
248544
  return message;
@@ -248328,6 +248688,9 @@ class coinbase extends _coinbase_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] *
248328
248688
  }
248329
248689
  }
248330
248690
  client.resolve(tradesArray, messageHash);
248691
+ if (marketId.endsWith('USD')) {
248692
+ client.resolve(tradesArray, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
248693
+ }
248331
248694
  return message;
248332
248695
  }
248333
248696
  handleOrder(client, message) {
@@ -248383,6 +248746,9 @@ class coinbase extends _coinbase_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] *
248383
248746
  const marketId = marketIds[i];
248384
248747
  const messageHash = 'user::' + marketId;
248385
248748
  client.resolve(this.orders, messageHash);
248749
+ if (messageHash.endsWith('USD')) {
248750
+ client.resolve(this.orders, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
248751
+ }
248386
248752
  }
248387
248753
  client.resolve(this.orders, 'user');
248388
248754
  return message;
@@ -248495,6 +248861,9 @@ class coinbase extends _coinbase_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] *
248495
248861
  orderbook['datetime'] = undefined;
248496
248862
  orderbook['symbol'] = symbol;
248497
248863
  client.resolve(orderbook, messageHash);
248864
+ if (messageHash.endsWith('USD')) {
248865
+ client.resolve(orderbook, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
248866
+ }
248498
248867
  }
248499
248868
  else if (type === 'update') {
248500
248869
  const orderbook = this.orderbooks[symbol];
@@ -248503,6 +248872,9 @@ class coinbase extends _coinbase_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] *
248503
248872
  orderbook['timestamp'] = this.parse8601(datetime);
248504
248873
  orderbook['symbol'] = symbol;
248505
248874
  client.resolve(orderbook, messageHash);
248875
+ if (messageHash.endsWith('USD')) {
248876
+ client.resolve(orderbook, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
248877
+ }
248506
248878
  }
248507
248879
  }
248508
248880
  return message;
@@ -264020,10 +264392,12 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
264020
264392
  'watchMyTrades': true,
264021
264393
  'watchOHLCV': true,
264022
264394
  'watchOrderBook': true,
264395
+ 'watchOrderBookForSymbols': true,
264023
264396
  'watchOrders': true,
264024
264397
  'watchTicker': true,
264025
- 'watchTickers': false,
264398
+ 'watchTickers': true,
264026
264399
  'watchTrades': true,
264400
+ 'watchTradesForSymbols': true,
264027
264401
  'createOrderWs': true,
264028
264402
  'editOrderWs': true,
264029
264403
  'cancelOrderWs': true,
@@ -264314,10 +264688,9 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
264314
264688
  // ]
264315
264689
  //
264316
264690
  const wsName = message[3];
264317
- const name = 'ticker';
264318
- const messageHash = name + ':' + wsName;
264319
264691
  const market = this.safeValue(this.options['marketsByWsName'], wsName);
264320
264692
  const symbol = market['symbol'];
264693
+ const messageHash = this.getMessageHash('ticker', undefined, symbol);
264321
264694
  const ticker = message[1];
264322
264695
  const vwap = this.safeString(ticker['p'], 0);
264323
264696
  let quoteVolume = undefined;
@@ -264348,9 +264721,6 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
264348
264721
  'quoteVolume': quoteVolume,
264349
264722
  'info': ticker,
264350
264723
  });
264351
- // todo add support for multiple tickers (may be tricky)
264352
- // kraken confirms multi-pair subscriptions separately one by one
264353
- // trigger correct watchTickers calls upon receiving any of symbols
264354
264724
  this.tickers[symbol] = result;
264355
264725
  client.resolve(result, messageHash);
264356
264726
  }
@@ -264368,9 +264738,9 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
264368
264738
  //
264369
264739
  const wsName = this.safeString(message, 3);
264370
264740
  const name = this.safeString(message, 2);
264371
- const messageHash = name + ':' + wsName;
264372
264741
  const market = this.safeValue(this.options['marketsByWsName'], wsName);
264373
264742
  const symbol = market['symbol'];
264743
+ const messageHash = this.getMessageHash(name, undefined, symbol);
264374
264744
  let stored = this.safeValue(this.trades, symbol);
264375
264745
  if (stored === undefined) {
264376
264746
  const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
@@ -264471,25 +264841,61 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
264471
264841
  * @param {object} [params] extra parameters specific to the exchange API endpoint
264472
264842
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
264473
264843
  */
264474
- return await this.watchPublic('ticker', symbol, params);
264844
+ await this.loadMarkets();
264845
+ symbol = this.symbol(symbol);
264846
+ const tickers = await this.watchTickers([symbol], params);
264847
+ return tickers[symbol];
264848
+ }
264849
+ async watchTickers(symbols = undefined, params = {}) {
264850
+ /**
264851
+ * @method
264852
+ * @name kraken#watchTickers
264853
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
264854
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
264855
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
264856
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
264857
+ */
264858
+ await this.loadMarkets();
264859
+ symbols = this.marketSymbols(symbols, undefined, false);
264860
+ const ticker = await this.watchMultiHelper('ticker', 'ticker', symbols, undefined, params);
264861
+ if (this.newUpdates) {
264862
+ const result = {};
264863
+ result[ticker['symbol']] = ticker;
264864
+ return result;
264865
+ }
264866
+ return this.filterByArray(this.tickers, 'symbol', symbols);
264475
264867
  }
264476
264868
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
264477
264869
  /**
264478
264870
  * @method
264479
264871
  * @name kraken#watchTrades
264480
264872
  * @description get the list of most recent trades for a particular symbol
264873
+ * @see https://docs.kraken.com/websockets/#message-trade
264481
264874
  * @param {string} symbol unified symbol of the market to fetch trades for
264482
264875
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
264483
264876
  * @param {int} [limit] the maximum amount of trades to fetch
264484
264877
  * @param {object} [params] extra parameters specific to the exchange API endpoint
264485
264878
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
264486
264879
  */
264487
- await this.loadMarkets();
264488
- symbol = this.symbol(symbol);
264489
- const name = 'trade';
264490
- const trades = await this.watchPublic(name, symbol, params);
264880
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
264881
+ }
264882
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
264883
+ /**
264884
+ * @method
264885
+ * @name kraken#watchTradesForSymbols
264886
+ * @see https://docs.kraken.com/websockets/#message-trade
264887
+ * @description get the list of most recent trades for a list of symbols
264888
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
264889
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
264890
+ * @param {int} [limit] the maximum amount of trades to fetch
264891
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
264892
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
264893
+ */
264894
+ const trades = await this.watchMultiHelper('trade', 'trade', symbols, undefined, params);
264491
264895
  if (this.newUpdates) {
264492
- limit = trades.getLimit(symbol, limit);
264896
+ const first = this.safeList(trades, 0);
264897
+ const tradeSymbol = this.safeString(first, 'symbol');
264898
+ limit = trades.getLimit(tradeSymbol, limit);
264493
264899
  }
264494
264900
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
264495
264901
  }
@@ -264498,15 +264904,28 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
264498
264904
  * @method
264499
264905
  * @name kraken#watchOrderBook
264500
264906
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
264907
+ * @see https://docs.kraken.com/websockets/#message-book
264501
264908
  * @param {string} symbol unified symbol of the market to fetch the order book for
264502
264909
  * @param {int} [limit] the maximum amount of order book entries to return
264503
264910
  * @param {object} [params] extra parameters specific to the exchange API endpoint
264504
264911
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
264505
264912
  */
264506
- const name = 'book';
264913
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
264914
+ }
264915
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
264916
+ /**
264917
+ * @method
264918
+ * @name kraken#watchOrderBookForSymbols
264919
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
264920
+ * @see https://docs.kraken.com/websockets/#message-book
264921
+ * @param {string[]} symbols unified array of symbols
264922
+ * @param {int} [limit] the maximum amount of order book entries to return
264923
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
264924
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
264925
+ */
264507
264926
  const request = {};
264508
264927
  if (limit !== undefined) {
264509
- if ((limit === 10) || (limit === 25) || (limit === 100) || (limit === 500) || (limit === 1000)) {
264928
+ if (this.inArray(limit, [10, 25, 100, 500, 1000])) {
264510
264929
  request['subscription'] = {
264511
264930
  'depth': limit, // default 10, valid options 10, 25, 100, 500, 1000
264512
264931
  };
@@ -264515,7 +264934,7 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
264515
264934
  throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' watchOrderBook accepts limit values of 10, 25, 100, 500 and 1000 only');
264516
264935
  }
264517
264936
  }
264518
- const orderbook = await this.watchPublic(name, symbol, this.extend(request, params));
264937
+ const orderbook = await this.watchMultiHelper('orderbook', 'book', symbols, { 'limit': limit }, this.extend(request, params));
264519
264938
  return orderbook.limit();
264520
264939
  }
264521
264940
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
@@ -264644,7 +265063,7 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
264644
265063
  const market = this.safeValue(this.options['marketsByWsName'], wsName);
264645
265064
  const symbol = market['symbol'];
264646
265065
  let timestamp = undefined;
264647
- const messageHash = 'book:' + wsName;
265066
+ const messageHash = this.getMessageHash('orderbook', undefined, symbol);
264648
265067
  // if this is a snapshot
264649
265068
  if ('as' in message[1]) {
264650
265069
  // todo get depth from marketsByWsName
@@ -264725,6 +265144,7 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
264725
265144
  if (localChecksum !== c) {
264726
265145
  const error = new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.InvalidNonce(this.id + ' invalid checksum');
264727
265146
  client.reject(error, messageHash);
265147
+ return;
264728
265148
  }
264729
265149
  }
264730
265150
  orderbook['symbol'] = symbol;
@@ -265252,6 +265672,48 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
265252
265672
  'trades': trades,
265253
265673
  });
265254
265674
  }
265675
+ async watchMultiHelper(unifiedName, channelName, symbols = undefined, subscriptionArgs = undefined, params = {}) {
265676
+ await this.loadMarkets();
265677
+ // symbols are required
265678
+ symbols = this.marketSymbols(symbols, undefined, false, true, false);
265679
+ const messageHashes = [];
265680
+ for (let i = 0; i < symbols.length; i++) {
265681
+ messageHashes.push(this.getMessageHash(unifiedName, undefined, this.symbol(symbols[i])));
265682
+ }
265683
+ // for WS subscriptions, we can't use .marketIds (symbols), instead a custom is field needed
265684
+ const markets = this.marketsForSymbols(symbols);
265685
+ const wsMarketIds = [];
265686
+ for (let i = 0; i < markets.length; i++) {
265687
+ const wsMarketId = this.safeString(markets[i]['info'], 'wsname');
265688
+ wsMarketIds.push(wsMarketId);
265689
+ }
265690
+ const request = {
265691
+ 'event': 'subscribe',
265692
+ 'reqid': this.requestId(),
265693
+ 'pair': wsMarketIds,
265694
+ 'subscription': {
265695
+ 'name': channelName,
265696
+ },
265697
+ };
265698
+ const url = this.urls['api']['ws']['public'];
265699
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscriptionArgs);
265700
+ }
265701
+ getMessageHash(unifiedElementName, subChannelName = undefined, symbol = undefined) {
265702
+ // unifiedElementName can be : orderbook, trade, ticker, bidask ...
265703
+ // subChannelName only applies to channel that needs specific variation (i.e. depth_50, depth_100..) to be selected
265704
+ const withSymbol = symbol !== undefined;
265705
+ let messageHash = unifiedElementName;
265706
+ if (!withSymbol) {
265707
+ messageHash += 's';
265708
+ }
265709
+ else {
265710
+ messageHash += '@' + symbol;
265711
+ }
265712
+ if (subChannelName !== undefined) {
265713
+ messageHash += '#' + subChannelName;
265714
+ }
265715
+ return messageHash;
265716
+ }
265255
265717
  handleSubscriptionStatus(client, message) {
265256
265718
  //
265257
265719
  // public
@@ -265398,9 +265860,12 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
265398
265860
  'fetchTradesWs': false,
265399
265861
  'watchOHLCV': false,
265400
265862
  'watchOrderBook': true,
265863
+ 'watchOrderBookForSymbols': true,
265401
265864
  'watchTicker': true,
265402
265865
  'watchTickers': true,
265866
+ 'watchBidsAsks': true,
265403
265867
  'watchTrades': true,
265868
+ 'watchTradesForSymbols': true,
265404
265869
  'watchBalance': true,
265405
265870
  // 'watchStatus': true, // https://docs.futures.kraken.com/#websocket-api-public-feeds-heartbeat
265406
265871
  'watchOrders': true,
@@ -265421,12 +265886,6 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
265421
265886
  'OHLCVLimit': 1000,
265422
265887
  'connectionLimit': 100,
265423
265888
  'requestLimit': 100,
265424
- 'watchTicker': {
265425
- 'method': 'ticker', // or ticker_lite
265426
- },
265427
- 'watchTickers': {
265428
- 'method': 'ticker', // or ticker_lite
265429
- },
265430
265889
  'fetchBalance': {
265431
265890
  'type': undefined,
265432
265891
  },
@@ -265464,6 +265923,20 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
265464
265923
  }
265465
265924
  return future;
265466
265925
  }
265926
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
265927
+ /**
265928
+ * @method
265929
+ * @name krakenfutures#watchOrderBookForSymbols
265930
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
265931
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-challenge
265932
+ * @param {string[]} symbols unified array of symbols
265933
+ * @param {int} [limit] the maximum amount of order book entries to return
265934
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
265935
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
265936
+ */
265937
+ const orderbook = await this.watchMultiHelper('orderbook', 'book', symbols, { 'limit': limit }, params);
265938
+ return orderbook.limit();
265939
+ }
265467
265940
  async subscribePublic(name, symbols, params = {}) {
265468
265941
  /**
265469
265942
  * @ignore
@@ -265531,34 +266004,49 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
265531
266004
  * @param {object} [params] extra parameters specific to the exchange API endpoint
265532
266005
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
265533
266006
  */
265534
- const options = this.safeValue(this.options, 'watchTicker');
265535
- const method = this.safeString(options, 'method', 'ticker'); // or ticker_lite
265536
- const name = this.safeString(params, 'method', method);
265537
- params = this.omit(params, ['method']);
265538
- return await this.subscribePublic(name, [symbol], params);
266007
+ await this.loadMarkets();
266008
+ symbol = this.symbol(symbol);
266009
+ const tickers = await this.watchTickers([symbol], params);
266010
+ return tickers[symbol];
265539
266011
  }
265540
266012
  async watchTickers(symbols = undefined, params = {}) {
265541
266013
  /**
265542
266014
  * @method
265543
- * @name krakenfutures#watchTicker
266015
+ * @name krakenfutures#watchTickers
265544
266016
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
265545
- * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-ticker-lite
266017
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-ticker
265546
266018
  * @param {string} symbol unified symbol of the market to fetch the ticker for
265547
266019
  * @param {object} [params] extra parameters specific to the exchange API endpoint
265548
266020
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
265549
266021
  */
265550
- const method = this.safeString(this.options, 'watchTickerMethod', 'ticker'); // or ticker_lite
265551
- const name = this.safeString2(params, 'method', 'watchTickerMethod', method);
265552
- params = this.omit(params, ['watchTickerMethod', 'method']);
266022
+ await this.loadMarkets();
265553
266023
  symbols = this.marketSymbols(symbols, undefined, false);
265554
- const ticker = await this.subscribePublic(name, symbols, params);
266024
+ const ticker = await this.watchMultiHelper('ticker', 'ticker', symbols, undefined, params);
265555
266025
  if (this.newUpdates) {
265556
- const tickers = {};
265557
- tickers[ticker['symbol']] = ticker;
265558
- return tickers;
266026
+ const result = {};
266027
+ result[ticker['symbol']] = ticker;
266028
+ return result;
265559
266029
  }
265560
266030
  return this.filterByArray(this.tickers, 'symbol', symbols);
265561
266031
  }
266032
+ async watchBidsAsks(symbols = undefined, params = {}) {
266033
+ /**
266034
+ * @method
266035
+ * @name krakenfutures#watchBidsAsks
266036
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-ticker-lite
266037
+ * @description watches best bid & ask for symbols
266038
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
266039
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
266040
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
266041
+ */
266042
+ const ticker = await this.watchMultiHelper('bidask', 'ticker_lite', symbols, undefined, params);
266043
+ if (this.newUpdates) {
266044
+ const result = {};
266045
+ result[ticker['symbol']] = ticker;
266046
+ return result;
266047
+ }
266048
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
266049
+ }
265562
266050
  async watchTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
265563
266051
  /**
265564
266052
  * @method
@@ -265571,11 +266059,25 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
265571
266059
  * @param {object} [params] extra parameters specific to the exchange API endpoint
265572
266060
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
265573
266061
  */
265574
- await this.loadMarkets();
265575
- const name = 'trade';
265576
- const trades = await this.subscribePublic(name, [symbol], params);
266062
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
266063
+ }
266064
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
266065
+ /**
266066
+ * @method
266067
+ * @name krakenfutures#watchTradesForSymbols
266068
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-trade
266069
+ * @description get the list of most recent trades for a list of symbols
266070
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
266071
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
266072
+ * @param {int} [limit] the maximum amount of trades to fetch
266073
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
266074
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
266075
+ */
266076
+ const trades = await this.watchMultiHelper('trade', 'trade', symbols, undefined, params);
265577
266077
  if (this.newUpdates) {
265578
- limit = trades.getLimit(symbol, limit);
266078
+ const first = this.safeList(trades, 0);
266079
+ const tradeSymbol = this.safeString(first, 'symbol');
266080
+ limit = trades.getLimit(tradeSymbol, limit);
265579
266081
  }
265580
266082
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
265581
266083
  }
@@ -265590,8 +266092,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
265590
266092
  * @param {object} [params] extra parameters specific to the exchange API endpoint
265591
266093
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
265592
266094
  */
265593
- const orderbook = await this.subscribePublic('book', [symbol], params);
265594
- return orderbook.limit();
266095
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
265595
266096
  }
265596
266097
  async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
265597
266098
  /**
@@ -265839,7 +266340,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
265839
266340
  if (marketId !== undefined) {
265840
266341
  const market = this.market(marketId);
265841
266342
  const symbol = market['symbol'];
265842
- const messageHash = 'trade:' + symbol;
266343
+ const messageHash = this.getMessageHash('trade', undefined, symbol);
265843
266344
  if (this.safeList(this.trades, symbol) === undefined) {
265844
266345
  const tradesLimit = this.safeInteger(this.options, 'tradesLimit', 1000);
265845
266346
  this.trades[symbol] = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCache */ .ZL(tradesLimit);
@@ -265861,7 +266362,6 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
265861
266362
  }
265862
266363
  client.resolve(tradesArray, messageHash);
265863
266364
  }
265864
- return message;
265865
266365
  }
265866
266366
  parseWsTrade(trade, market = undefined) {
265867
266367
  //
@@ -266287,7 +266787,16 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
266287
266787
  // "volumeQuote": 19628180
266288
266788
  // }
266289
266789
  //
266290
- // ticker_lite
266790
+ const marketId = this.safeString(message, 'product_id');
266791
+ if (marketId !== undefined) {
266792
+ const ticker = this.parseWsTicker(message);
266793
+ const symbol = ticker['symbol'];
266794
+ this.tickers[symbol] = ticker;
266795
+ const messageHash = this.getMessageHash('ticker', undefined, symbol);
266796
+ client.resolve(ticker, messageHash);
266797
+ }
266798
+ }
266799
+ handleBidAsk(client, message) {
266291
266800
  //
266292
266801
  // {
266293
266802
  // "feed": "ticker_lite",
@@ -266305,16 +266814,13 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
266305
266814
  // }
266306
266815
  //
266307
266816
  const marketId = this.safeString(message, 'product_id');
266308
- const feed = this.safeString(message, 'feed');
266309
266817
  if (marketId !== undefined) {
266310
266818
  const ticker = this.parseWsTicker(message);
266311
266819
  const symbol = ticker['symbol'];
266312
- this.tickers[symbol] = ticker;
266313
- const messageHash = feed + ':' + symbol;
266820
+ this.bidsasks[symbol] = ticker;
266821
+ const messageHash = this.getMessageHash('bidask', undefined, symbol);
266314
266822
  client.resolve(ticker, messageHash);
266315
266823
  }
266316
- client.resolve(this.tickers, feed);
266317
- return message;
266318
266824
  }
266319
266825
  parseWsTicker(ticker, market = undefined) {
266320
266826
  //
@@ -266426,14 +266932,14 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
266426
266932
  const marketId = this.safeString(message, 'product_id');
266427
266933
  const market = this.safeMarket(marketId);
266428
266934
  const symbol = market['symbol'];
266429
- const messageHash = 'book:' + symbol;
266430
- const subscription = this.safeValue(client.subscriptions, messageHash, {});
266935
+ const messageHash = this.getMessageHash('orderbook', undefined, symbol);
266936
+ const subscription = this.safeDict(client.subscriptions, messageHash, {});
266431
266937
  const limit = this.safeInteger(subscription, 'limit');
266432
266938
  const timestamp = this.safeInteger(message, 'timestamp');
266433
266939
  this.orderbooks[symbol] = this.orderBook({}, limit);
266434
266940
  const orderbook = this.orderbooks[symbol];
266435
- const bids = this.safeValue(message, 'bids');
266436
- const asks = this.safeValue(message, 'asks');
266941
+ const bids = this.safeList(message, 'bids');
266942
+ const asks = this.safeList(message, 'asks');
266437
266943
  for (let i = 0; i < bids.length; i++) {
266438
266944
  const bid = bids[i];
266439
266945
  const price = this.safeNumber(bid, 'price');
@@ -266468,7 +266974,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
266468
266974
  const marketId = this.safeString(message, 'product_id');
266469
266975
  const market = this.safeMarket(marketId);
266470
266976
  const symbol = market['symbol'];
266471
- const messageHash = 'book:' + symbol;
266977
+ const messageHash = this.getMessageHash('orderbook', undefined, symbol);
266472
266978
  const orderbook = this.orderbooks[symbol];
266473
266979
  const side = this.safeString(message, 'side');
266474
266980
  const price = this.safeNumber(message, 'price');
@@ -266795,6 +267301,39 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
266795
267301
  },
266796
267302
  });
266797
267303
  }
267304
+ async watchMultiHelper(unifiedName, channelName, symbols = undefined, subscriptionArgs = undefined, params = {}) {
267305
+ await this.loadMarkets();
267306
+ // symbols are required
267307
+ symbols = this.marketSymbols(symbols, undefined, false, true, false);
267308
+ const messageHashes = [];
267309
+ for (let i = 0; i < symbols.length; i++) {
267310
+ messageHashes.push(this.getMessageHash(unifiedName, undefined, this.symbol(symbols[i])));
267311
+ }
267312
+ const marketIds = this.marketIds(symbols);
267313
+ const request = {
267314
+ 'event': 'subscribe',
267315
+ 'feed': channelName,
267316
+ 'product_ids': marketIds,
267317
+ };
267318
+ const url = this.urls['api']['ws'];
267319
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscriptionArgs);
267320
+ }
267321
+ getMessageHash(unifiedElementName, subChannelName = undefined, symbol = undefined) {
267322
+ // unifiedElementName can be : orderbook, trade, ticker, bidask ...
267323
+ // subChannelName only applies to channel that needs specific variation (i.e. depth_50, depth_100..) to be selected
267324
+ const withSymbol = symbol !== undefined;
267325
+ let messageHash = unifiedElementName;
267326
+ if (!withSymbol) {
267327
+ messageHash += 's';
267328
+ }
267329
+ else {
267330
+ messageHash += ':' + symbol;
267331
+ }
267332
+ if (subChannelName !== undefined) {
267333
+ messageHash += '#' + subChannelName;
267334
+ }
267335
+ return messageHash;
267336
+ }
266798
267337
  handleErrorMessage(client, message) {
266799
267338
  //
266800
267339
  // {
@@ -266825,10 +267364,10 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
266825
267364
  const feed = this.safeString(message, 'feed');
266826
267365
  const methods = {
266827
267366
  'ticker': this.handleTicker,
267367
+ 'ticker_lite': this.handleBidAsk,
266828
267368
  'trade': this.handleTrade,
266829
267369
  'trade_snapshot': this.handleTrade,
266830
267370
  // 'heartbeat': this.handleStatus,
266831
- 'ticker_lite': this.handleTicker,
266832
267371
  'book': this.handleOrderBook,
266833
267372
  'book_snapshot': this.handleOrderBookSnapshot,
266834
267373
  'open_orders_verbose': this.handleOrder,
@@ -267065,22 +267604,46 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
267065
267604
  /**
267066
267605
  * @method
267067
267606
  * @name kucoin#watchTickers
267607
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/ticker
267068
267608
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
267069
267609
  * @param {string[]} symbols unified symbol of the market to fetch the ticker for
267070
267610
  * @param {object} [params] extra parameters specific to the exchange API endpoint
267611
+ * @param {string} [params.method] either '/market/snapshot' or '/market/ticker' default is '/market/ticker'
267071
267612
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
267072
267613
  */
267073
267614
  await this.loadMarkets();
267074
267615
  symbols = this.marketSymbols(symbols);
267075
- let messageHash = 'tickers';
267616
+ const messageHash = 'tickers';
267617
+ let method = undefined;
267618
+ [method, params] = this.handleOptionAndParams(params, 'watchTickers', 'method', '/market/ticker');
267619
+ const messageHashes = [];
267620
+ const topics = [];
267076
267621
  if (symbols !== undefined) {
267077
- messageHash = 'tickers::' + symbols.join(',');
267622
+ for (let i = 0; i < symbols.length; i++) {
267623
+ const symbol = symbols[i];
267624
+ messageHashes.push('ticker:' + symbol);
267625
+ const market = this.market(symbol);
267626
+ topics.push(method + ':' + market['id']);
267627
+ }
267078
267628
  }
267079
267629
  const url = await this.negotiate(false);
267080
- const topic = '/market/ticker:all';
267081
- const tickers = await this.subscribe(url, messageHash, topic, params);
267082
- if (this.newUpdates) {
267083
- return tickers;
267630
+ let tickers = undefined;
267631
+ if (symbols === undefined) {
267632
+ const allTopic = method + ':all';
267633
+ tickers = await this.subscribe(url, messageHash, allTopic, params);
267634
+ if (this.newUpdates) {
267635
+ return tickers;
267636
+ }
267637
+ }
267638
+ else {
267639
+ const marketIds = this.marketIds(symbols);
267640
+ const symbolsTopic = method + ':' + marketIds.join(',');
267641
+ tickers = await this.subscribeMultiple(url, messageHashes, symbolsTopic, topics, params);
267642
+ if (this.newUpdates) {
267643
+ const newDict = {};
267644
+ newDict[tickers['symbol']] = tickers;
267645
+ return newDict;
267646
+ }
267084
267647
  }
267085
267648
  return this.filterByArray(this.tickers, 'symbol', symbols);
267086
267649
  }
@@ -267164,19 +267727,6 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
267164
267727
  const allTickers = {};
267165
267728
  allTickers[symbol] = ticker;
267166
267729
  client.resolve(allTickers, 'tickers');
267167
- const messageHashes = this.findMessageHashes(client, 'tickers::');
267168
- for (let i = 0; i < messageHashes.length; i++) {
267169
- const currentMessageHash = messageHashes[i];
267170
- const parts = currentMessageHash.split('::');
267171
- const symbolsString = parts[1];
267172
- const symbols = symbolsString.split(',');
267173
- const tickers = this.filterByArray(this.tickers, 'symbol', symbols);
267174
- const tickersSymbols = Object.keys(tickers);
267175
- const numTickers = tickersSymbols.length;
267176
- if (numTickers > 0) {
267177
- client.resolve(tickers, currentMessageHash);
267178
- }
267179
- }
267180
267730
  }
267181
267731
  async watchBidsAsks(symbols = undefined, params = {}) {
267182
267732
  /**
@@ -312452,6 +313002,8 @@ class woo extends _abstract_woo_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
312452
313002
  'fetchCanceledOrders': false,
312453
313003
  'fetchClosedOrder': false,
312454
313004
  'fetchClosedOrders': true,
313005
+ 'fetchConvertCurrencies': true,
313006
+ 'fetchConvertQuote': true,
312455
313007
  'fetchCurrencies': true,
312456
313008
  'fetchDepositAddress': true,
312457
313009
  'fetchDeposits': true,
@@ -315380,6 +315932,143 @@ class woo extends _abstract_woo_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
315380
315932
  'takeProfitPrice': undefined,
315381
315933
  });
315382
315934
  }
315935
+ async fetchConvertQuote(fromCode, toCode, amount = undefined, params = {}) {
315936
+ /**
315937
+ * @method
315938
+ * @name woo#fetchConvertQuote
315939
+ * @description fetch a quote for converting from one currency to another
315940
+ * @see https://docs.woo.org/#get-quote-rfq
315941
+ * @param {string} fromCode the currency that you want to sell and convert from
315942
+ * @param {string} toCode the currency that you want to buy and convert into
315943
+ * @param {float} [amount] how much you want to trade in units of the from currency
315944
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
315945
+ * @returns {object} a [conversion structure]{@link https://docs.ccxt.com/#/?id=conversion-structure}
315946
+ */
315947
+ await this.loadMarkets();
315948
+ const request = {
315949
+ 'sellToken': fromCode.toUpperCase(),
315950
+ 'buyToken': toCode.toUpperCase(),
315951
+ 'sellQuantity': this.numberToString(amount),
315952
+ };
315953
+ const response = await this.v3PrivateGetConvertRfq(this.extend(request, params));
315954
+ //
315955
+ // {
315956
+ // "success": true,
315957
+ // "data": {
315958
+ // "quoteId": 123123123,
315959
+ // "counterPartyId": "",
315960
+ // "sellToken": "ETH",
315961
+ // "sellQuantity": "0.0445",
315962
+ // "buyToken": "USDT",
315963
+ // "buyQuantity": "33.45",
315964
+ // "buyPrice": "6.77",
315965
+ // "expireTimestamp": 1659084466000,
315966
+ // "message": 1659084466000
315967
+ // }
315968
+ // }
315969
+ //
315970
+ const data = this.safeDict(response, 'data', {});
315971
+ const fromCurrencyId = this.safeString(data, 'sellToken', fromCode);
315972
+ const fromCurrency = this.currency(fromCurrencyId);
315973
+ const toCurrencyId = this.safeString(data, 'buyToken', toCode);
315974
+ const toCurrency = this.currency(toCurrencyId);
315975
+ return this.parseConversion(data, fromCurrency, toCurrency);
315976
+ }
315977
+ parseConversion(conversion, fromCurrency = undefined, toCurrency = undefined) {
315978
+ //
315979
+ // fetchConvertQuote
315980
+ //
315981
+ // {
315982
+ // "quoteId": 123123123,
315983
+ // "counterPartyId": "",
315984
+ // "sellToken": "ETH",
315985
+ // "sellQuantity": "0.0445",
315986
+ // "buyToken": "USDT",
315987
+ // "buyQuantity": "33.45",
315988
+ // "buyPrice": "6.77",
315989
+ // "expireTimestamp": 1659084466000,
315990
+ // "message": 1659084466000
315991
+ // }
315992
+ //
315993
+ const timestamp = this.safeInteger(conversion, 'expireTimestamp');
315994
+ const fromCoin = this.safeString(conversion, 'sellToken');
315995
+ const fromCode = this.safeCurrencyCode(fromCoin, fromCurrency);
315996
+ const to = this.safeString(conversion, 'buyToken');
315997
+ const toCode = this.safeCurrencyCode(to, toCurrency);
315998
+ return {
315999
+ 'info': conversion,
316000
+ 'timestamp': timestamp,
316001
+ 'datetime': this.iso8601(timestamp),
316002
+ 'id': this.safeString(conversion, 'quoteId'),
316003
+ 'fromCurrency': fromCode,
316004
+ 'fromAmount': this.safeNumber(conversion, 'sellQuantity'),
316005
+ 'toCurrency': toCode,
316006
+ 'toAmount': this.safeNumber(conversion, 'buyQuantity'),
316007
+ 'price': this.safeNumber(conversion, 'buyPrice'),
316008
+ 'fee': undefined,
316009
+ };
316010
+ }
316011
+ async fetchConvertCurrencies(params = {}) {
316012
+ /**
316013
+ * @method
316014
+ * @name woo#fetchConvertCurrencies
316015
+ * @description fetches all available currencies that can be converted
316016
+ * @see https://docs.woo.org/#get-quote-asset-info
316017
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
316018
+ * @returns {object} an associative dictionary of currencies
316019
+ */
316020
+ await this.loadMarkets();
316021
+ const response = await this.v3PrivateGetConvertAssetInfo(params);
316022
+ //
316023
+ // {
316024
+ // "success": true,
316025
+ // "rows": [
316026
+ // {
316027
+ // "token": "BTC",
316028
+ // "tick": 0.0001,
316029
+ // "createdTime": "1575014248.99", // Unix epoch time in seconds
316030
+ // "updatedTime": "1575014248.99" // Unix epoch time in seconds
316031
+ // },
316032
+ // ]
316033
+ // }
316034
+ //
316035
+ const result = {};
316036
+ const data = this.safeList(response, 'rows', []);
316037
+ for (let i = 0; i < data.length; i++) {
316038
+ const entry = data[i];
316039
+ const id = this.safeString(entry, 'token');
316040
+ const code = this.safeCurrencyCode(id);
316041
+ result[code] = {
316042
+ 'info': entry,
316043
+ 'id': id,
316044
+ 'code': code,
316045
+ 'networks': undefined,
316046
+ 'type': undefined,
316047
+ 'name': undefined,
316048
+ 'active': undefined,
316049
+ 'deposit': undefined,
316050
+ 'withdraw': undefined,
316051
+ 'fee': undefined,
316052
+ 'precision': this.safeNumber(entry, 'tick'),
316053
+ 'limits': {
316054
+ 'amount': {
316055
+ 'min': undefined,
316056
+ 'max': undefined,
316057
+ },
316058
+ 'withdraw': {
316059
+ 'min': undefined,
316060
+ 'max': undefined,
316061
+ },
316062
+ 'deposit': {
316063
+ 'min': undefined,
316064
+ 'max': undefined,
316065
+ },
316066
+ },
316067
+ 'created': this.safeTimestamp(entry, 'createdTime'),
316068
+ };
316069
+ }
316070
+ return result;
316071
+ }
315383
316072
  defaultNetworkCodeForCurrency(code) {
315384
316073
  const currencyItem = this.currency(code);
315385
316074
  const networks = currencyItem['networks'];
@@ -325553,7 +326242,7 @@ SOFTWARE.
325553
326242
 
325554
326243
  //-----------------------------------------------------------------------------
325555
326244
  // this is updated by vss.js when building
325556
- const version = '4.2.93';
326245
+ const version = '4.2.95';
325557
326246
  _src_base_Exchange_js__WEBPACK_IMPORTED_MODULE_0__/* .Exchange */ .e.ccxtVersion = version;
325558
326247
  //-----------------------------------------------------------------------------
325559
326248