ccxt 4.2.93 → 4.2.94

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.
@@ -28,9 +28,12 @@ export default class krakenfutures extends krakenfuturesRest {
28
28
  'fetchTradesWs': false,
29
29
  'watchOHLCV': false,
30
30
  'watchOrderBook': true,
31
+ 'watchOrderBookForSymbols': true,
31
32
  'watchTicker': true,
32
33
  'watchTickers': true,
34
+ 'watchBidsAsks': true,
33
35
  'watchTrades': true,
36
+ 'watchTradesForSymbols': true,
34
37
  'watchBalance': true,
35
38
  // 'watchStatus': true, // https://docs.futures.kraken.com/#websocket-api-public-feeds-heartbeat
36
39
  'watchOrders': true,
@@ -51,12 +54,6 @@ export default class krakenfutures extends krakenfuturesRest {
51
54
  'OHLCVLimit': 1000,
52
55
  'connectionLimit': 100,
53
56
  'requestLimit': 100,
54
- 'watchTicker': {
55
- 'method': 'ticker', // or ticker_lite
56
- },
57
- 'watchTickers': {
58
- 'method': 'ticker', // or ticker_lite
59
- },
60
57
  'fetchBalance': {
61
58
  'type': undefined,
62
59
  },
@@ -94,6 +91,20 @@ export default class krakenfutures extends krakenfuturesRest {
94
91
  }
95
92
  return future;
96
93
  }
94
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
95
+ /**
96
+ * @method
97
+ * @name krakenfutures#watchOrderBookForSymbols
98
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
99
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-challenge
100
+ * @param {string[]} symbols unified array of symbols
101
+ * @param {int} [limit] the maximum amount of order book entries to return
102
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
103
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
104
+ */
105
+ const orderbook = await this.watchMultiHelper('orderbook', 'book', symbols, { 'limit': limit }, params);
106
+ return orderbook.limit();
107
+ }
97
108
  async subscribePublic(name, symbols, params = {}) {
98
109
  /**
99
110
  * @ignore
@@ -161,34 +172,49 @@ export default class krakenfutures extends krakenfuturesRest {
161
172
  * @param {object} [params] extra parameters specific to the exchange API endpoint
162
173
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
163
174
  */
164
- const options = this.safeValue(this.options, 'watchTicker');
165
- const method = this.safeString(options, 'method', 'ticker'); // or ticker_lite
166
- const name = this.safeString(params, 'method', method);
167
- params = this.omit(params, ['method']);
168
- return await this.subscribePublic(name, [symbol], params);
175
+ await this.loadMarkets();
176
+ symbol = this.symbol(symbol);
177
+ const tickers = await this.watchTickers([symbol], params);
178
+ return tickers[symbol];
169
179
  }
170
180
  async watchTickers(symbols = undefined, params = {}) {
171
181
  /**
172
182
  * @method
173
- * @name krakenfutures#watchTicker
183
+ * @name krakenfutures#watchTickers
174
184
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
175
- * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-ticker-lite
185
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-ticker
176
186
  * @param {string} symbol unified symbol of the market to fetch the ticker for
177
187
  * @param {object} [params] extra parameters specific to the exchange API endpoint
178
188
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
179
189
  */
180
- const method = this.safeString(this.options, 'watchTickerMethod', 'ticker'); // or ticker_lite
181
- const name = this.safeString2(params, 'method', 'watchTickerMethod', method);
182
- params = this.omit(params, ['watchTickerMethod', 'method']);
190
+ await this.loadMarkets();
183
191
  symbols = this.marketSymbols(symbols, undefined, false);
184
- const ticker = await this.subscribePublic(name, symbols, params);
192
+ const ticker = await this.watchMultiHelper('ticker', 'ticker', symbols, undefined, params);
185
193
  if (this.newUpdates) {
186
- const tickers = {};
187
- tickers[ticker['symbol']] = ticker;
188
- return tickers;
194
+ const result = {};
195
+ result[ticker['symbol']] = ticker;
196
+ return result;
189
197
  }
190
198
  return this.filterByArray(this.tickers, 'symbol', symbols);
191
199
  }
200
+ async watchBidsAsks(symbols = undefined, params = {}) {
201
+ /**
202
+ * @method
203
+ * @name krakenfutures#watchBidsAsks
204
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-ticker-lite
205
+ * @description watches best bid & ask for symbols
206
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
207
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
208
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
209
+ */
210
+ const ticker = await this.watchMultiHelper('bidask', 'ticker_lite', symbols, undefined, params);
211
+ if (this.newUpdates) {
212
+ const result = {};
213
+ result[ticker['symbol']] = ticker;
214
+ return result;
215
+ }
216
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
217
+ }
192
218
  async watchTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
193
219
  /**
194
220
  * @method
@@ -201,11 +227,25 @@ export default class krakenfutures extends krakenfuturesRest {
201
227
  * @param {object} [params] extra parameters specific to the exchange API endpoint
202
228
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
203
229
  */
204
- await this.loadMarkets();
205
- const name = 'trade';
206
- const trades = await this.subscribePublic(name, [symbol], params);
230
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
231
+ }
232
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
233
+ /**
234
+ * @method
235
+ * @name krakenfutures#watchTradesForSymbols
236
+ * @see https://docs.futures.kraken.com/#websocket-api-public-feeds-trade
237
+ * @description get the list of most recent trades for a list of symbols
238
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
239
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
240
+ * @param {int} [limit] the maximum amount of trades to fetch
241
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
242
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
243
+ */
244
+ const trades = await this.watchMultiHelper('trade', 'trade', symbols, undefined, params);
207
245
  if (this.newUpdates) {
208
- limit = trades.getLimit(symbol, limit);
246
+ const first = this.safeList(trades, 0);
247
+ const tradeSymbol = this.safeString(first, 'symbol');
248
+ limit = trades.getLimit(tradeSymbol, limit);
209
249
  }
210
250
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
211
251
  }
@@ -220,8 +260,7 @@ export default class krakenfutures extends krakenfuturesRest {
220
260
  * @param {object} [params] extra parameters specific to the exchange API endpoint
221
261
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
222
262
  */
223
- const orderbook = await this.subscribePublic('book', [symbol], params);
224
- return orderbook.limit();
263
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
225
264
  }
226
265
  async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
227
266
  /**
@@ -469,7 +508,7 @@ export default class krakenfutures extends krakenfuturesRest {
469
508
  if (marketId !== undefined) {
470
509
  const market = this.market(marketId);
471
510
  const symbol = market['symbol'];
472
- const messageHash = 'trade:' + symbol;
511
+ const messageHash = this.getMessageHash('trade', undefined, symbol);
473
512
  if (this.safeList(this.trades, symbol) === undefined) {
474
513
  const tradesLimit = this.safeInteger(this.options, 'tradesLimit', 1000);
475
514
  this.trades[symbol] = new ArrayCache(tradesLimit);
@@ -491,7 +530,6 @@ export default class krakenfutures extends krakenfuturesRest {
491
530
  }
492
531
  client.resolve(tradesArray, messageHash);
493
532
  }
494
- return message;
495
533
  }
496
534
  parseWsTrade(trade, market = undefined) {
497
535
  //
@@ -917,7 +955,16 @@ export default class krakenfutures extends krakenfuturesRest {
917
955
  // "volumeQuote": 19628180
918
956
  // }
919
957
  //
920
- // ticker_lite
958
+ const marketId = this.safeString(message, 'product_id');
959
+ if (marketId !== undefined) {
960
+ const ticker = this.parseWsTicker(message);
961
+ const symbol = ticker['symbol'];
962
+ this.tickers[symbol] = ticker;
963
+ const messageHash = this.getMessageHash('ticker', undefined, symbol);
964
+ client.resolve(ticker, messageHash);
965
+ }
966
+ }
967
+ handleBidAsk(client, message) {
921
968
  //
922
969
  // {
923
970
  // "feed": "ticker_lite",
@@ -935,16 +982,13 @@ export default class krakenfutures extends krakenfuturesRest {
935
982
  // }
936
983
  //
937
984
  const marketId = this.safeString(message, 'product_id');
938
- const feed = this.safeString(message, 'feed');
939
985
  if (marketId !== undefined) {
940
986
  const ticker = this.parseWsTicker(message);
941
987
  const symbol = ticker['symbol'];
942
- this.tickers[symbol] = ticker;
943
- const messageHash = feed + ':' + symbol;
988
+ this.bidsasks[symbol] = ticker;
989
+ const messageHash = this.getMessageHash('bidask', undefined, symbol);
944
990
  client.resolve(ticker, messageHash);
945
991
  }
946
- client.resolve(this.tickers, feed);
947
- return message;
948
992
  }
949
993
  parseWsTicker(ticker, market = undefined) {
950
994
  //
@@ -1056,14 +1100,14 @@ export default class krakenfutures extends krakenfuturesRest {
1056
1100
  const marketId = this.safeString(message, 'product_id');
1057
1101
  const market = this.safeMarket(marketId);
1058
1102
  const symbol = market['symbol'];
1059
- const messageHash = 'book:' + symbol;
1060
- const subscription = this.safeValue(client.subscriptions, messageHash, {});
1103
+ const messageHash = this.getMessageHash('orderbook', undefined, symbol);
1104
+ const subscription = this.safeDict(client.subscriptions, messageHash, {});
1061
1105
  const limit = this.safeInteger(subscription, 'limit');
1062
1106
  const timestamp = this.safeInteger(message, 'timestamp');
1063
1107
  this.orderbooks[symbol] = this.orderBook({}, limit);
1064
1108
  const orderbook = this.orderbooks[symbol];
1065
- const bids = this.safeValue(message, 'bids');
1066
- const asks = this.safeValue(message, 'asks');
1109
+ const bids = this.safeList(message, 'bids');
1110
+ const asks = this.safeList(message, 'asks');
1067
1111
  for (let i = 0; i < bids.length; i++) {
1068
1112
  const bid = bids[i];
1069
1113
  const price = this.safeNumber(bid, 'price');
@@ -1098,7 +1142,7 @@ export default class krakenfutures extends krakenfuturesRest {
1098
1142
  const marketId = this.safeString(message, 'product_id');
1099
1143
  const market = this.safeMarket(marketId);
1100
1144
  const symbol = market['symbol'];
1101
- const messageHash = 'book:' + symbol;
1145
+ const messageHash = this.getMessageHash('orderbook', undefined, symbol);
1102
1146
  const orderbook = this.orderbooks[symbol];
1103
1147
  const side = this.safeString(message, 'side');
1104
1148
  const price = this.safeNumber(message, 'price');
@@ -1425,6 +1469,39 @@ export default class krakenfutures extends krakenfuturesRest {
1425
1469
  },
1426
1470
  });
1427
1471
  }
1472
+ async watchMultiHelper(unifiedName, channelName, symbols = undefined, subscriptionArgs = undefined, params = {}) {
1473
+ await this.loadMarkets();
1474
+ // symbols are required
1475
+ symbols = this.marketSymbols(symbols, undefined, false, true, false);
1476
+ const messageHashes = [];
1477
+ for (let i = 0; i < symbols.length; i++) {
1478
+ messageHashes.push(this.getMessageHash(unifiedName, undefined, this.symbol(symbols[i])));
1479
+ }
1480
+ const marketIds = this.marketIds(symbols);
1481
+ const request = {
1482
+ 'event': 'subscribe',
1483
+ 'feed': channelName,
1484
+ 'product_ids': marketIds,
1485
+ };
1486
+ const url = this.urls['api']['ws'];
1487
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscriptionArgs);
1488
+ }
1489
+ getMessageHash(unifiedElementName, subChannelName = undefined, symbol = undefined) {
1490
+ // unifiedElementName can be : orderbook, trade, ticker, bidask ...
1491
+ // subChannelName only applies to channel that needs specific variation (i.e. depth_50, depth_100..) to be selected
1492
+ const withSymbol = symbol !== undefined;
1493
+ let messageHash = unifiedElementName;
1494
+ if (!withSymbol) {
1495
+ messageHash += 's';
1496
+ }
1497
+ else {
1498
+ messageHash += ':' + symbol;
1499
+ }
1500
+ if (subChannelName !== undefined) {
1501
+ messageHash += '#' + subChannelName;
1502
+ }
1503
+ return messageHash;
1504
+ }
1428
1505
  handleErrorMessage(client, message) {
1429
1506
  //
1430
1507
  // {
@@ -1455,10 +1532,10 @@ export default class krakenfutures extends krakenfuturesRest {
1455
1532
  const feed = this.safeString(message, 'feed');
1456
1533
  const methods = {
1457
1534
  'ticker': this.handleTicker,
1535
+ 'ticker_lite': this.handleBidAsk,
1458
1536
  'trade': this.handleTrade,
1459
1537
  'trade_snapshot': this.handleTrade,
1460
1538
  // 'heartbeat': this.handleStatus,
1461
- 'ticker_lite': this.handleTicker,
1462
1539
  'book': this.handleOrderBook,
1463
1540
  'book_snapshot': this.handleOrderBookSnapshot,
1464
1541
  'open_orders_verbose': this.handleOrder,
@@ -176,22 +176,46 @@ export default class kucoin extends kucoinRest {
176
176
  /**
177
177
  * @method
178
178
  * @name kucoin#watchTickers
179
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/ticker
179
180
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
180
181
  * @param {string[]} symbols unified symbol of the market to fetch the ticker for
181
182
  * @param {object} [params] extra parameters specific to the exchange API endpoint
183
+ * @param {string} [params.method] either '/market/snapshot' or '/market/ticker' default is '/market/ticker'
182
184
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
183
185
  */
184
186
  await this.loadMarkets();
185
187
  symbols = this.marketSymbols(symbols);
186
- let messageHash = 'tickers';
188
+ const messageHash = 'tickers';
189
+ let method = undefined;
190
+ [method, params] = this.handleOptionAndParams(params, 'watchTickers', 'method', '/market/ticker');
191
+ const messageHashes = [];
192
+ const topics = [];
187
193
  if (symbols !== undefined) {
188
- messageHash = 'tickers::' + symbols.join(',');
194
+ for (let i = 0; i < symbols.length; i++) {
195
+ const symbol = symbols[i];
196
+ messageHashes.push('ticker:' + symbol);
197
+ const market = this.market(symbol);
198
+ topics.push(method + ':' + market['id']);
199
+ }
189
200
  }
190
201
  const url = await this.negotiate(false);
191
- const topic = '/market/ticker:all';
192
- const tickers = await this.subscribe(url, messageHash, topic, params);
193
- if (this.newUpdates) {
194
- return tickers;
202
+ let tickers = undefined;
203
+ if (symbols === undefined) {
204
+ const allTopic = method + ':all';
205
+ tickers = await this.subscribe(url, messageHash, allTopic, params);
206
+ if (this.newUpdates) {
207
+ return tickers;
208
+ }
209
+ }
210
+ else {
211
+ const marketIds = this.marketIds(symbols);
212
+ const symbolsTopic = method + ':' + marketIds.join(',');
213
+ tickers = await this.subscribeMultiple(url, messageHashes, symbolsTopic, topics, params);
214
+ if (this.newUpdates) {
215
+ const newDict = {};
216
+ newDict[tickers['symbol']] = tickers;
217
+ return newDict;
218
+ }
195
219
  }
196
220
  return this.filterByArray(this.tickers, 'symbol', symbols);
197
221
  }
@@ -275,19 +299,6 @@ export default class kucoin extends kucoinRest {
275
299
  const allTickers = {};
276
300
  allTickers[symbol] = ticker;
277
301
  client.resolve(allTickers, 'tickers');
278
- const messageHashes = this.findMessageHashes(client, 'tickers::');
279
- for (let i = 0; i < messageHashes.length; i++) {
280
- const currentMessageHash = messageHashes[i];
281
- const parts = currentMessageHash.split('::');
282
- const symbolsString = parts[1];
283
- const symbols = symbolsString.split(',');
284
- const tickers = this.filterByArray(this.tickers, 'symbol', symbols);
285
- const tickersSymbols = Object.keys(tickers);
286
- const numTickers = tickersSymbols.length;
287
- if (numTickers > 0) {
288
- client.resolve(tickers, currentMessageHash);
289
- }
290
- }
291
302
  }
292
303
  async watchBidsAsks(symbols = undefined, params = {}) {
293
304
  /**
package/js/src/woo.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import Exchange from './abstract/woo.js';
2
- import type { TransferEntry, Balances, Currency, FundingRateHistory, Int, Market, Num, OHLCV, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, Transaction, Leverage, Account, Currencies, TradingFees } from './base/types.js';
2
+ import type { TransferEntry, Balances, Currency, FundingRateHistory, Int, Market, Num, OHLCV, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, Transaction, Leverage, Account, Currencies, TradingFees, Conversion } from './base/types.js';
3
3
  /**
4
4
  * @class woo
5
5
  * @augments Exchange
@@ -174,6 +174,9 @@ export default class woo extends Exchange {
174
174
  fetchPosition(symbol?: Str, params?: {}): Promise<import("./base/types.js").Position>;
175
175
  fetchPositions(symbols?: Strings, params?: {}): Promise<import("./base/types.js").Position[]>;
176
176
  parsePosition(position: any, market?: Market): import("./base/types.js").Position;
177
+ fetchConvertQuote(fromCode: string, toCode: string, amount?: Num, params?: {}): Promise<Conversion>;
178
+ parseConversion(conversion: any, fromCurrency?: Currency, toCurrency?: Currency): Conversion;
179
+ fetchConvertCurrencies(params?: {}): Promise<Currencies>;
177
180
  defaultNetworkCodeForCurrency(code: any): any;
178
181
  setSandboxMode(enable: boolean): void;
179
182
  }
package/js/src/woo.js CHANGED
@@ -60,6 +60,8 @@ export default class woo extends Exchange {
60
60
  'fetchCanceledOrders': false,
61
61
  'fetchClosedOrder': false,
62
62
  'fetchClosedOrders': true,
63
+ 'fetchConvertCurrencies': true,
64
+ 'fetchConvertQuote': true,
63
65
  'fetchCurrencies': true,
64
66
  'fetchDepositAddress': true,
65
67
  'fetchDeposits': true,
@@ -2988,6 +2990,143 @@ export default class woo extends Exchange {
2988
2990
  'takeProfitPrice': undefined,
2989
2991
  });
2990
2992
  }
2993
+ async fetchConvertQuote(fromCode, toCode, amount = undefined, params = {}) {
2994
+ /**
2995
+ * @method
2996
+ * @name woo#fetchConvertQuote
2997
+ * @description fetch a quote for converting from one currency to another
2998
+ * @see https://docs.woo.org/#get-quote-rfq
2999
+ * @param {string} fromCode the currency that you want to sell and convert from
3000
+ * @param {string} toCode the currency that you want to buy and convert into
3001
+ * @param {float} [amount] how much you want to trade in units of the from currency
3002
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3003
+ * @returns {object} a [conversion structure]{@link https://docs.ccxt.com/#/?id=conversion-structure}
3004
+ */
3005
+ await this.loadMarkets();
3006
+ const request = {
3007
+ 'sellToken': fromCode.toUpperCase(),
3008
+ 'buyToken': toCode.toUpperCase(),
3009
+ 'sellQuantity': this.numberToString(amount),
3010
+ };
3011
+ const response = await this.v3PrivateGetConvertRfq(this.extend(request, params));
3012
+ //
3013
+ // {
3014
+ // "success": true,
3015
+ // "data": {
3016
+ // "quoteId": 123123123,
3017
+ // "counterPartyId": "",
3018
+ // "sellToken": "ETH",
3019
+ // "sellQuantity": "0.0445",
3020
+ // "buyToken": "USDT",
3021
+ // "buyQuantity": "33.45",
3022
+ // "buyPrice": "6.77",
3023
+ // "expireTimestamp": 1659084466000,
3024
+ // "message": 1659084466000
3025
+ // }
3026
+ // }
3027
+ //
3028
+ const data = this.safeDict(response, 'data', {});
3029
+ const fromCurrencyId = this.safeString(data, 'sellToken', fromCode);
3030
+ const fromCurrency = this.currency(fromCurrencyId);
3031
+ const toCurrencyId = this.safeString(data, 'buyToken', toCode);
3032
+ const toCurrency = this.currency(toCurrencyId);
3033
+ return this.parseConversion(data, fromCurrency, toCurrency);
3034
+ }
3035
+ parseConversion(conversion, fromCurrency = undefined, toCurrency = undefined) {
3036
+ //
3037
+ // fetchConvertQuote
3038
+ //
3039
+ // {
3040
+ // "quoteId": 123123123,
3041
+ // "counterPartyId": "",
3042
+ // "sellToken": "ETH",
3043
+ // "sellQuantity": "0.0445",
3044
+ // "buyToken": "USDT",
3045
+ // "buyQuantity": "33.45",
3046
+ // "buyPrice": "6.77",
3047
+ // "expireTimestamp": 1659084466000,
3048
+ // "message": 1659084466000
3049
+ // }
3050
+ //
3051
+ const timestamp = this.safeInteger(conversion, 'expireTimestamp');
3052
+ const fromCoin = this.safeString(conversion, 'sellToken');
3053
+ const fromCode = this.safeCurrencyCode(fromCoin, fromCurrency);
3054
+ const to = this.safeString(conversion, 'buyToken');
3055
+ const toCode = this.safeCurrencyCode(to, toCurrency);
3056
+ return {
3057
+ 'info': conversion,
3058
+ 'timestamp': timestamp,
3059
+ 'datetime': this.iso8601(timestamp),
3060
+ 'id': this.safeString(conversion, 'quoteId'),
3061
+ 'fromCurrency': fromCode,
3062
+ 'fromAmount': this.safeNumber(conversion, 'sellQuantity'),
3063
+ 'toCurrency': toCode,
3064
+ 'toAmount': this.safeNumber(conversion, 'buyQuantity'),
3065
+ 'price': this.safeNumber(conversion, 'buyPrice'),
3066
+ 'fee': undefined,
3067
+ };
3068
+ }
3069
+ async fetchConvertCurrencies(params = {}) {
3070
+ /**
3071
+ * @method
3072
+ * @name woo#fetchConvertCurrencies
3073
+ * @description fetches all available currencies that can be converted
3074
+ * @see https://docs.woo.org/#get-quote-asset-info
3075
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3076
+ * @returns {object} an associative dictionary of currencies
3077
+ */
3078
+ await this.loadMarkets();
3079
+ const response = await this.v3PrivateGetConvertAssetInfo(params);
3080
+ //
3081
+ // {
3082
+ // "success": true,
3083
+ // "rows": [
3084
+ // {
3085
+ // "token": "BTC",
3086
+ // "tick": 0.0001,
3087
+ // "createdTime": "1575014248.99", // Unix epoch time in seconds
3088
+ // "updatedTime": "1575014248.99" // Unix epoch time in seconds
3089
+ // },
3090
+ // ]
3091
+ // }
3092
+ //
3093
+ const result = {};
3094
+ const data = this.safeList(response, 'rows', []);
3095
+ for (let i = 0; i < data.length; i++) {
3096
+ const entry = data[i];
3097
+ const id = this.safeString(entry, 'token');
3098
+ const code = this.safeCurrencyCode(id);
3099
+ result[code] = {
3100
+ 'info': entry,
3101
+ 'id': id,
3102
+ 'code': code,
3103
+ 'networks': undefined,
3104
+ 'type': undefined,
3105
+ 'name': undefined,
3106
+ 'active': undefined,
3107
+ 'deposit': undefined,
3108
+ 'withdraw': undefined,
3109
+ 'fee': undefined,
3110
+ 'precision': this.safeNumber(entry, 'tick'),
3111
+ 'limits': {
3112
+ 'amount': {
3113
+ 'min': undefined,
3114
+ 'max': undefined,
3115
+ },
3116
+ 'withdraw': {
3117
+ 'min': undefined,
3118
+ 'max': undefined,
3119
+ },
3120
+ 'deposit': {
3121
+ 'min': undefined,
3122
+ 'max': undefined,
3123
+ },
3124
+ },
3125
+ 'created': this.safeTimestamp(entry, 'createdTime'),
3126
+ };
3127
+ }
3128
+ return result;
3129
+ }
2991
3130
  defaultNetworkCodeForCurrency(code) {
2992
3131
  const currencyItem = this.currency(code);
2993
3132
  const networks = currencyItem['networks'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccxt",
3
- "version": "4.2.93",
3
+ "version": "4.2.94",
4
4
  "description": "A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges",
5
5
  "unpkg": "dist/ccxt.browser.js",
6
6
  "type": "module",
package/skip-tests.json CHANGED
@@ -1318,6 +1318,10 @@
1318
1318
  },
1319
1319
  "watchTrades": {
1320
1320
  "timestamp": "timestamp reversed: https://app.travis-ci.com/github/ccxt/ccxt/builds/269484317#L3681"
1321
+ },
1322
+ "watchBidsAsks": {
1323
+ "bidVolume": "https://app.travis-ci.com/github/ccxt/ccxt/builds/269878519#L3759",
1324
+ "askVolume": "same"
1321
1325
  }
1322
1326
  },
1323
1327
  "timeout": 120000