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
package/js/src/okx.js CHANGED
@@ -63,6 +63,8 @@ export default class okx extends Exchange {
63
63
  'fetchCanceledOrders': true,
64
64
  'fetchClosedOrder': undefined,
65
65
  'fetchClosedOrders': true,
66
+ 'fetchConvertCurrencies': true,
67
+ 'fetchConvertQuote': true,
66
68
  'fetchCrossBorrowRate': true,
67
69
  'fetchCrossBorrowRates': true,
68
70
  'fetchCurrencies': true,
@@ -1118,7 +1120,7 @@ export default class okx extends Exchange {
1118
1120
  return super.handleMarketTypeAndParams(methodName, market, params);
1119
1121
  }
1120
1122
  convertToInstrumentType(type) {
1121
- const exchangeTypes = this.safeValue(this.options, 'exchangeType', {});
1123
+ const exchangeTypes = this.safeDict(this.options, 'exchangeType', {});
1122
1124
  return this.safeString(exchangeTypes, type, type);
1123
1125
  }
1124
1126
  createExpiredOptionMarket(symbol) {
@@ -2922,7 +2924,7 @@ export default class okx extends Exchange {
2922
2924
  const side = this.safeString(rawOrder, 'side');
2923
2925
  const amount = this.safeValue(rawOrder, 'amount');
2924
2926
  const price = this.safeValue(rawOrder, 'price');
2925
- const orderParams = this.safeValue(rawOrder, 'params', {});
2927
+ const orderParams = this.safeDict(rawOrder, 'params', {});
2926
2928
  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
2927
2929
  const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, extendedParams);
2928
2930
  ordersRequests.push(orderRequest);
@@ -3111,8 +3113,8 @@ export default class okx extends Exchange {
3111
3113
  // "msg": ""
3112
3114
  // }
3113
3115
  //
3114
- const data = this.safeValue(response, 'data', []);
3115
- const first = this.safeValue(data, 0);
3116
+ const data = this.safeList(response, 'data', []);
3117
+ const first = this.safeDict(data, 0, {});
3116
3118
  const order = this.parseOrder(first, market);
3117
3119
  order['type'] = type;
3118
3120
  order['side'] = side;
@@ -4311,7 +4313,7 @@ export default class okx extends Exchange {
4311
4313
  if (paginate) {
4312
4314
  return await this.fetchPaginatedCallDynamic('fetchLedger', code, since, limit, params);
4313
4315
  }
4314
- const options = this.safeValue(this.options, 'fetchLedger', {});
4316
+ const options = this.safeDict(this.options, 'fetchLedger', {});
4315
4317
  let method = this.safeString(options, 'method');
4316
4318
  method = this.safeString(params, 'method', method);
4317
4319
  params = this.omit(params, 'method');
@@ -4640,7 +4642,7 @@ export default class okx extends Exchange {
4640
4642
  // ]
4641
4643
  // }
4642
4644
  //
4643
- const data = this.safeValue(response, 'data', []);
4645
+ const data = this.safeList(response, 'data', []);
4644
4646
  const filtered = this.filterBy(data, 'selected', true);
4645
4647
  const parsed = this.parseDepositAddresses(filtered, [currency['code']], false);
4646
4648
  return this.indexBy(parsed, 'network');
@@ -4714,7 +4716,7 @@ export default class okx extends Exchange {
4714
4716
  };
4715
4717
  let network = this.safeString(params, 'network'); // this line allows the user to specify either ERC20 or ETH
4716
4718
  if (network !== undefined) {
4717
- const networks = this.safeValue(this.options, 'networks', {});
4719
+ const networks = this.safeDict(this.options, 'networks', {});
4718
4720
  network = this.safeString(networks, network.toUpperCase(), network); // handle ETH>ERC20 alias
4719
4721
  request['chain'] = currency['id'] + '-' + network;
4720
4722
  params = this.omit(params, 'network');
@@ -4723,7 +4725,7 @@ export default class okx extends Exchange {
4723
4725
  if (fee === undefined) {
4724
4726
  const currencies = await this.fetchCurrencies();
4725
4727
  this.currencies = this.deepExtend(this.currencies, currencies);
4726
- const targetNetwork = this.safeValue(currency['networks'], this.networkIdToCode(network), {});
4728
+ const targetNetwork = this.safeDict(currency['networks'], this.networkIdToCode(network), {});
4727
4729
  fee = this.safeString(targetNetwork, 'fee');
4728
4730
  if (fee === undefined) {
4729
4731
  throw new 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.');
@@ -4745,7 +4747,7 @@ export default class okx extends Exchange {
4745
4747
  // ]
4746
4748
  // }
4747
4749
  //
4748
- const data = this.safeValue(response, 'data', []);
4750
+ const data = this.safeList(response, 'data', []);
4749
4751
  const transaction = this.safeDict(data, 0);
4750
4752
  return this.parseTransaction(transaction, currency);
4751
4753
  }
@@ -4970,7 +4972,7 @@ export default class okx extends Exchange {
4970
4972
  // "msg": ''
4971
4973
  // }
4972
4974
  //
4973
- const data = this.safeValue(response, 'data');
4975
+ const data = this.safeList(response, 'data', []);
4974
4976
  const withdrawal = this.safeDict(data, 0, {});
4975
4977
  return this.parseTransaction(withdrawal);
4976
4978
  }
@@ -5257,8 +5259,8 @@ export default class okx extends Exchange {
5257
5259
  // ]
5258
5260
  // }
5259
5261
  //
5260
- const data = this.safeValue(response, 'data', []);
5261
- const position = this.safeValue(data, 0);
5262
+ const data = this.safeList(response, 'data', []);
5263
+ const position = this.safeDict(data, 0);
5262
5264
  if (position === undefined) {
5263
5265
  return undefined;
5264
5266
  }
@@ -5294,7 +5296,7 @@ export default class okx extends Exchange {
5294
5296
  request['instId'] = marketIds.join(',');
5295
5297
  }
5296
5298
  }
5297
- const fetchPositionsOptions = this.safeValue(this.options, 'fetchPositions', {});
5299
+ const fetchPositionsOptions = this.safeDict(this.options, 'fetchPositions', {});
5298
5300
  const method = this.safeString(fetchPositionsOptions, 'method', 'privateGetAccountPositions');
5299
5301
  let response = undefined;
5300
5302
  if (method === 'privateGetAccountPositionsHistory') {
@@ -5349,7 +5351,7 @@ export default class okx extends Exchange {
5349
5351
  // ]
5350
5352
  // }
5351
5353
  //
5352
- const positions = this.safeValue(response, 'data', []);
5354
+ const positions = this.safeList(response, 'data', []);
5353
5355
  const result = [];
5354
5356
  for (let i = 0; i < positions.length; i++) {
5355
5357
  result.push(this.parsePosition(positions[i]));
@@ -5557,7 +5559,7 @@ export default class okx extends Exchange {
5557
5559
  */
5558
5560
  await this.loadMarkets();
5559
5561
  const currency = this.currency(code);
5560
- const accountsByType = this.safeValue(this.options, 'accountsByType', {});
5562
+ const accountsByType = this.safeDict(this.options, 'accountsByType', {});
5561
5563
  const fromId = this.safeString(accountsByType, fromAccount, fromAccount);
5562
5564
  const toId = this.safeString(accountsByType, toAccount, toAccount);
5563
5565
  const request = {
@@ -5599,7 +5601,7 @@ export default class okx extends Exchange {
5599
5601
  // ]
5600
5602
  // }
5601
5603
  //
5602
- const data = this.safeValue(response, 'data', []);
5604
+ const data = this.safeList(response, 'data', []);
5603
5605
  const rawTransfer = this.safeDict(data, 0, {});
5604
5606
  return this.parseTransfer(rawTransfer, currency);
5605
5607
  }
@@ -5662,7 +5664,7 @@ export default class okx extends Exchange {
5662
5664
  let amount = this.safeNumber(transfer, 'amt');
5663
5665
  const fromAccountId = this.safeString(transfer, 'from');
5664
5666
  const toAccountId = this.safeString(transfer, 'to');
5665
- const accountsById = this.safeValue(this.options, 'accountsById', {});
5667
+ const accountsById = this.safeDict(this.options, 'accountsById', {});
5666
5668
  const timestamp = this.safeInteger(transfer, 'ts');
5667
5669
  const balanceChange = this.safeString(transfer, 'sz');
5668
5670
  if (balanceChange !== undefined) {
@@ -5713,7 +5715,7 @@ export default class okx extends Exchange {
5713
5715
  // "msg": ""
5714
5716
  // }
5715
5717
  //
5716
- const data = this.safeValue(response, 'data', []);
5718
+ const data = this.safeList(response, 'data', []);
5717
5719
  const transfer = this.safeDict(data, 0);
5718
5720
  return this.parseTransfer(transfer);
5719
5721
  }
@@ -5919,8 +5921,8 @@ export default class okx extends Exchange {
5919
5921
  // "msg": ""
5920
5922
  // }
5921
5923
  //
5922
- const data = this.safeValue(response, 'data', []);
5923
- const entry = this.safeValue(data, 0, {});
5924
+ const data = this.safeList(response, 'data', []);
5925
+ const entry = this.safeDict(data, 0, {});
5924
5926
  return this.parseFundingRate(entry, market);
5925
5927
  }
5926
5928
  async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
@@ -6060,7 +6062,7 @@ export default class okx extends Exchange {
6060
6062
  // "type": "8"
6061
6063
  // }
6062
6064
  //
6063
- const data = this.safeValue(response, 'data', []);
6065
+ const data = this.safeList(response, 'data', []);
6064
6066
  const result = [];
6065
6067
  for (let i = 0; i < data.length; i++) {
6066
6068
  const entry = data[i];
@@ -6252,7 +6254,7 @@ export default class okx extends Exchange {
6252
6254
  // ],
6253
6255
  // }
6254
6256
  //
6255
- const data = this.safeValue(response, 'data', []);
6257
+ const data = this.safeList(response, 'data', []);
6256
6258
  const rates = [];
6257
6259
  for (let i = 0; i < data.length; i++) {
6258
6260
  rates.push(this.parseBorrowRate(data[i]));
@@ -6288,8 +6290,8 @@ export default class okx extends Exchange {
6288
6290
  // "msg": ""
6289
6291
  // }
6290
6292
  //
6291
- const data = this.safeValue(response, 'data');
6292
- const rate = this.safeValue(data, 0);
6293
+ const data = this.safeList(response, 'data', []);
6294
+ const rate = this.safeDict(data, 0, {});
6293
6295
  return this.parseBorrowRate(rate);
6294
6296
  }
6295
6297
  parseBorrowRate(info, currency = undefined) {
@@ -6393,7 +6395,7 @@ export default class okx extends Exchange {
6393
6395
  // "msg": ""
6394
6396
  // }
6395
6397
  //
6396
- const data = this.safeValue(response, 'data');
6398
+ const data = this.safeList(response, 'data', []);
6397
6399
  return this.parseBorrowRateHistories(data, codes, since, limit);
6398
6400
  }
6399
6401
  async fetchBorrowRateHistory(code, since = undefined, limit = undefined, params = {}) {
@@ -6437,7 +6439,7 @@ export default class okx extends Exchange {
6437
6439
  // "msg": ""
6438
6440
  // }
6439
6441
  //
6440
- const data = this.safeValue(response, 'data');
6442
+ const data = this.safeList(response, 'data', []);
6441
6443
  return this.parseBorrowRateHistory(data, code, since, limit);
6442
6444
  }
6443
6445
  async modifyMarginHelper(symbol, amount, type, params = {}) {
@@ -6629,7 +6631,7 @@ export default class okx extends Exchange {
6629
6631
  // ]
6630
6632
  // }
6631
6633
  //
6632
- const data = this.safeValue(response, 'data');
6634
+ const data = this.safeList(response, 'data', []);
6633
6635
  return this.parseMarketLeverageTiers(data, market);
6634
6636
  }
6635
6637
  parseMarketLeverageTiers(info, market = undefined) {
@@ -6731,7 +6733,7 @@ export default class okx extends Exchange {
6731
6733
  // "msg": ""
6732
6734
  // }
6733
6735
  //
6734
- const data = this.safeValue(response, 'data');
6736
+ const data = this.safeList(response, 'data', []);
6735
6737
  const interest = this.parseBorrowInterests(data);
6736
6738
  return this.filterByCurrencySinceLimit(interest, code, since, limit);
6737
6739
  }
@@ -6787,8 +6789,8 @@ export default class okx extends Exchange {
6787
6789
  // "msg": ""
6788
6790
  // }
6789
6791
  //
6790
- const data = this.safeValue(response, 'data', []);
6791
- const loan = this.safeValue(data, 0);
6792
+ const data = this.safeList(response, 'data', []);
6793
+ const loan = this.safeDict(data, 0, {});
6792
6794
  return this.parseMarginLoan(loan, currency);
6793
6795
  }
6794
6796
  async repayCrossMargin(code, amount, params = {}) {
@@ -6832,8 +6834,8 @@ export default class okx extends Exchange {
6832
6834
  // "msg": ""
6833
6835
  // }
6834
6836
  //
6835
- const data = this.safeValue(response, 'data', []);
6836
- const loan = this.safeValue(data, 0);
6837
+ const data = this.safeList(response, 'data', []);
6838
+ const loan = this.safeDict(data, 0, {});
6837
6839
  return this.parseMarginLoan(loan, currency);
6838
6840
  }
6839
6841
  parseMarginLoan(info, currency = undefined) {
@@ -6915,8 +6917,8 @@ export default class okx extends Exchange {
6915
6917
  * @param {int} [params.until] The time in ms of the latest record to retrieve as a unix timestamp
6916
6918
  * @returns An array of [open interest structures]{@link https://docs.ccxt.com/#/?id=open-interest-structure}
6917
6919
  */
6918
- const options = this.safeValue(this.options, 'fetchOpenInterestHistory', {});
6919
- const timeframes = this.safeValue(options, 'timeframes', {});
6920
+ const options = this.safeDict(this.options, 'fetchOpenInterestHistory', {});
6921
+ const timeframes = this.safeDict(options, 'timeframes', {});
6920
6922
  timeframe = this.safeString(timeframes, timeframe, timeframe);
6921
6923
  if (timeframe !== '5m' && timeframe !== '1H' && timeframe !== '1D') {
6922
6924
  throw new BadRequest(this.id + ' fetchOpenInterestHistory cannot only use the 5m, 1h, and 1d timeframe');
@@ -7206,7 +7208,7 @@ export default class okx extends Exchange {
7206
7208
  // "msg": ""
7207
7209
  // }
7208
7210
  //
7209
- const data = this.safeValue(response, 'data', []);
7211
+ const data = this.safeList(response, 'data', []);
7210
7212
  const settlements = this.parseSettlements(data, market);
7211
7213
  const sorted = this.sortBy(settlements, 'timestamp');
7212
7214
  return this.filterBySymbolSinceLimit(sorted, market['symbol'], since, limit);
@@ -7245,7 +7247,7 @@ export default class okx extends Exchange {
7245
7247
  for (let i = 0; i < settlements.length; i++) {
7246
7248
  const entry = settlements[i];
7247
7249
  const timestamp = this.safeInteger(entry, 'ts');
7248
- const details = this.safeValue(entry, 'details', []);
7250
+ const details = this.safeList(entry, 'details', []);
7249
7251
  for (let j = 0; j < details.length; j++) {
7250
7252
  const settlement = this.parseSettlement(details[j], market);
7251
7253
  result.push(this.extend(settlement, {
@@ -7291,7 +7293,7 @@ export default class okx extends Exchange {
7291
7293
  // "msg": ""
7292
7294
  // }
7293
7295
  //
7294
- const underlyings = this.safeValue(response, 'data', []);
7296
+ const underlyings = this.safeList(response, 'data', []);
7295
7297
  return underlyings[0];
7296
7298
  }
7297
7299
  async fetchGreeks(symbol, params = {}) {
@@ -7343,7 +7345,7 @@ export default class okx extends Exchange {
7343
7345
  // "msg": ""
7344
7346
  // }
7345
7347
  //
7346
- const data = this.safeValue(response, 'data', []);
7348
+ const data = this.safeList(response, 'data', []);
7347
7349
  for (let i = 0; i < data.length; i++) {
7348
7350
  const entry = data[i];
7349
7351
  const entryMarketId = this.safeString(entry, 'instId');
@@ -7466,7 +7468,7 @@ export default class okx extends Exchange {
7466
7468
  // "outTime": "1701877077102579"
7467
7469
  // }
7468
7470
  //
7469
- const data = this.safeValue(response, 'data');
7471
+ const data = this.safeList(response, 'data', []);
7470
7472
  const order = this.safeDict(data, 0);
7471
7473
  return this.parseOrder(order, market);
7472
7474
  }
@@ -7607,6 +7609,157 @@ export default class okx extends Exchange {
7607
7609
  'quoteVolume': undefined,
7608
7610
  };
7609
7611
  }
7612
+ async fetchConvertQuote(fromCode, toCode, amount = undefined, params = {}) {
7613
+ /**
7614
+ * @method
7615
+ * @name okx#fetchConvertQuote
7616
+ * @description fetch a quote for converting from one currency to another
7617
+ * @see https://www.okx.com/docs-v5/en/#funding-account-rest-api-estimate-quote
7618
+ * @param {string} fromCode the currency that you want to sell and convert from
7619
+ * @param {string} toCode the currency that you want to buy and convert into
7620
+ * @param {float} [amount] how much you want to trade in units of the from currency
7621
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
7622
+ * @returns {object} a [conversion structure]{@link https://docs.ccxt.com/#/?id=conversion-structure}
7623
+ */
7624
+ await this.loadMarkets();
7625
+ const request = {
7626
+ 'baseCcy': fromCode.toUpperCase(),
7627
+ 'quoteCcy': toCode.toUpperCase(),
7628
+ 'rfqSzCcy': fromCode.toUpperCase(),
7629
+ 'rfqSz': this.numberToString(amount),
7630
+ 'side': 'sell',
7631
+ };
7632
+ const response = await this.privatePostAssetConvertEstimateQuote(this.extend(request, params));
7633
+ //
7634
+ // {
7635
+ // "code": "0",
7636
+ // "data": [
7637
+ // {
7638
+ // "baseCcy": "ETH",
7639
+ // "baseSz": "0.01023052",
7640
+ // "clQReqId": "",
7641
+ // "cnvtPx": "2932.40104429",
7642
+ // "origRfqSz": "30",
7643
+ // "quoteCcy": "USDT",
7644
+ // "quoteId": "quoterETH-USDT16461885104612381",
7645
+ // "quoteSz": "30",
7646
+ // "quoteTime": "1646188510461",
7647
+ // "rfqSz": "30",
7648
+ // "rfqSzCcy": "USDT",
7649
+ // "side": "buy",
7650
+ // "ttlMs": "10000"
7651
+ // }
7652
+ // ],
7653
+ // "msg": ""
7654
+ // }
7655
+ //
7656
+ const data = this.safeList(response, 'data', []);
7657
+ const result = this.safeDict(data, 0, {});
7658
+ const fromCurrencyId = this.safeString(result, 'baseCcy', fromCode);
7659
+ const fromCurrency = this.currency(fromCurrencyId);
7660
+ const toCurrencyId = this.safeString(result, 'quoteCcy', toCode);
7661
+ const toCurrency = this.currency(toCurrencyId);
7662
+ return this.parseConversion(result, fromCurrency, toCurrency);
7663
+ }
7664
+ parseConversion(conversion, fromCurrency = undefined, toCurrency = undefined) {
7665
+ //
7666
+ // fetchConvertQuote
7667
+ //
7668
+ // {
7669
+ // "baseCcy": "ETH",
7670
+ // "baseSz": "0.01023052",
7671
+ // "clQReqId": "",
7672
+ // "cnvtPx": "2932.40104429",
7673
+ // "origRfqSz": "30",
7674
+ // "quoteCcy": "USDT",
7675
+ // "quoteId": "quoterETH-USDT16461885104612381",
7676
+ // "quoteSz": "30",
7677
+ // "quoteTime": "1646188510461",
7678
+ // "rfqSz": "30",
7679
+ // "rfqSzCcy": "USDT",
7680
+ // "side": "buy",
7681
+ // "ttlMs": "10000"
7682
+ // }
7683
+ //
7684
+ const timestamp = this.safeInteger(conversion, 'quoteTime');
7685
+ const fromCoin = this.safeString(conversion, 'baseCcy');
7686
+ const fromCode = this.safeCurrencyCode(fromCoin, fromCurrency);
7687
+ const to = this.safeString(conversion, 'quoteCcy');
7688
+ const toCode = this.safeCurrencyCode(to, toCurrency);
7689
+ return {
7690
+ 'info': conversion,
7691
+ 'timestamp': timestamp,
7692
+ 'datetime': this.iso8601(timestamp),
7693
+ 'id': this.safeString(conversion, 'clQReqId'),
7694
+ 'fromCurrency': fromCode,
7695
+ 'fromAmount': this.safeNumber(conversion, 'baseSz'),
7696
+ 'toCurrency': toCode,
7697
+ 'toAmount': this.safeNumber(conversion, 'quoteSz'),
7698
+ 'price': this.safeNumber(conversion, 'cnvtPx'),
7699
+ 'fee': undefined,
7700
+ };
7701
+ }
7702
+ async fetchConvertCurrencies(params = {}) {
7703
+ /**
7704
+ * @method
7705
+ * @name okx#fetchConvertCurrencies
7706
+ * @description fetches all available currencies that can be converted
7707
+ * @see https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-convert-currencies
7708
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
7709
+ * @returns {object} an associative dictionary of currencies
7710
+ */
7711
+ await this.loadMarkets();
7712
+ const response = await this.privateGetAssetConvertCurrencies(params);
7713
+ //
7714
+ // {
7715
+ // "code": "0",
7716
+ // "data": [
7717
+ // {
7718
+ // "ccy": "BTC",
7719
+ // "max": "",
7720
+ // "min": ""
7721
+ // },
7722
+ // ],
7723
+ // "msg": ""
7724
+ // }
7725
+ //
7726
+ const result = {};
7727
+ const data = this.safeList(response, 'data', []);
7728
+ for (let i = 0; i < data.length; i++) {
7729
+ const entry = data[i];
7730
+ const id = this.safeString(entry, 'ccy');
7731
+ const code = this.safeCurrencyCode(id);
7732
+ result[code] = {
7733
+ 'info': entry,
7734
+ 'id': id,
7735
+ 'code': code,
7736
+ 'networks': undefined,
7737
+ 'type': undefined,
7738
+ 'name': undefined,
7739
+ 'active': undefined,
7740
+ 'deposit': undefined,
7741
+ 'withdraw': undefined,
7742
+ 'fee': undefined,
7743
+ 'precision': undefined,
7744
+ 'limits': {
7745
+ 'amount': {
7746
+ 'min': this.safeNumber(entry, 'min'),
7747
+ 'max': this.safeNumber(entry, 'max'),
7748
+ },
7749
+ 'withdraw': {
7750
+ 'min': undefined,
7751
+ 'max': undefined,
7752
+ },
7753
+ 'deposit': {
7754
+ 'min': undefined,
7755
+ 'max': undefined,
7756
+ },
7757
+ },
7758
+ 'created': undefined,
7759
+ };
7760
+ }
7761
+ return result;
7762
+ }
7610
7763
  handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
7611
7764
  if (!response) {
7612
7765
  return undefined; // fallback to default error handler
@@ -7634,7 +7787,7 @@ export default class okx extends Exchange {
7634
7787
  const code = this.safeString(response, 'code');
7635
7788
  if ((code !== '0') && (code !== '2')) { // 2 means that bulk operation partially succeeded
7636
7789
  const feedback = this.id + ' ' + body;
7637
- const data = this.safeValue(response, 'data', []);
7790
+ const data = this.safeList(response, 'data', []);
7638
7791
  for (let i = 0; i < data.length; i++) {
7639
7792
  const error = data[i];
7640
7793
  const errorCode = this.safeString(error, 'sCode');
@@ -189,6 +189,9 @@ export default class coinbase extends coinbaseRest {
189
189
  const messageHash = channel + '::' + wsMarketId;
190
190
  newTickers.push(result);
191
191
  client.resolve(result, messageHash);
192
+ if (messageHash.endsWith('USD')) {
193
+ client.resolve(result, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
194
+ }
192
195
  }
193
196
  }
194
197
  const messageHashes = this.findMessageHashes(client, 'ticker_batch::');
@@ -200,6 +203,9 @@ export default class coinbase extends coinbaseRest {
200
203
  const tickers = this.filterByArray(newTickers, 'symbol', symbols);
201
204
  if (!this.isEmpty(tickers)) {
202
205
  client.resolve(tickers, messageHash);
206
+ if (messageHash.endsWith('USD')) {
207
+ client.resolve(tickers, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
208
+ }
203
209
  }
204
210
  }
205
211
  return message;
@@ -349,6 +355,9 @@ export default class coinbase extends coinbaseRest {
349
355
  }
350
356
  }
351
357
  client.resolve(tradesArray, messageHash);
358
+ if (marketId.endsWith('USD')) {
359
+ client.resolve(tradesArray, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
360
+ }
352
361
  return message;
353
362
  }
354
363
  handleOrder(client, message) {
@@ -404,6 +413,9 @@ export default class coinbase extends coinbaseRest {
404
413
  const marketId = marketIds[i];
405
414
  const messageHash = 'user::' + marketId;
406
415
  client.resolve(this.orders, messageHash);
416
+ if (messageHash.endsWith('USD')) {
417
+ client.resolve(this.orders, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
418
+ }
407
419
  }
408
420
  client.resolve(this.orders, 'user');
409
421
  return message;
@@ -516,6 +528,9 @@ export default class coinbase extends coinbaseRest {
516
528
  orderbook['datetime'] = undefined;
517
529
  orderbook['symbol'] = symbol;
518
530
  client.resolve(orderbook, messageHash);
531
+ if (messageHash.endsWith('USD')) {
532
+ client.resolve(orderbook, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
533
+ }
519
534
  }
520
535
  else if (type === 'update') {
521
536
  const orderbook = this.orderbooks[symbol];
@@ -524,6 +539,9 @@ export default class coinbase extends coinbaseRest {
524
539
  orderbook['timestamp'] = this.parse8601(datetime);
525
540
  orderbook['symbol'] = symbol;
526
541
  client.resolve(orderbook, messageHash);
542
+ if (messageHash.endsWith('USD')) {
543
+ client.resolve(orderbook, messageHash + 'C'); // sometimes we subscribe to BTC/USDC and coinbase returns BTC/USD
544
+ }
527
545
  }
528
546
  }
529
547
  return message;
@@ -1,5 +1,5 @@
1
1
  import krakenRest from '../kraken.js';
2
- import type { Int, OrderSide, OrderType, Str, OrderBook, Order, Trade, Ticker, OHLCV, Num } from '../base/types.js';
2
+ import type { Int, Strings, OrderSide, OrderType, Str, OrderBook, Order, Trade, Ticker, Tickers, OHLCV, Num } from '../base/types.js';
3
3
  import Client from '../base/ws/Client.js';
4
4
  export default class kraken extends krakenRest {
5
5
  describe(): any;
@@ -17,8 +17,11 @@ export default class kraken extends krakenRest {
17
17
  requestId(): any;
18
18
  watchPublic(name: any, symbol: any, params?: {}): Promise<any>;
19
19
  watchTicker(symbol: string, params?: {}): Promise<Ticker>;
20
+ watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
20
21
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
22
+ watchTradesForSymbols(symbols: string[], since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
21
23
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
24
+ watchOrderBookForSymbols(symbols: string[], limit?: Int, params?: {}): Promise<OrderBook>;
22
25
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
23
26
  loadMarkets(reload?: boolean, params?: {}): Promise<import("../base/types.js").Dictionary<import("../base/types.js").MarketInterface>>;
24
27
  watchHeartbeat(params?: {}): Promise<any>;
@@ -49,6 +52,8 @@ export default class kraken extends krakenRest {
49
52
  watchOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
50
53
  handleOrders(client: Client, message: any, subscription?: any): void;
51
54
  parseWsOrder(order: any, market?: any): Order;
55
+ watchMultiHelper(unifiedName: string, channelName: string, symbols?: Strings, subscriptionArgs?: any, params?: {}): Promise<any>;
56
+ getMessageHash(unifiedElementName: string, subChannelName?: Str, symbol?: Str): string;
52
57
  handleSubscriptionStatus(client: Client, message: any): void;
53
58
  handleErrorMessage(client: Client, message: any): boolean;
54
59
  handleMessage(client: Client, message: any): void;