ccxt 4.2.21 β†’ 4.2.22

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 (56) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.js +352 -42
  3. package/dist/ccxt.browser.min.js +3 -3
  4. package/dist/cjs/ccxt.js +1 -1
  5. package/dist/cjs/src/bigone.js +1 -0
  6. package/dist/cjs/src/binance.js +14 -3
  7. package/dist/cjs/src/bitget.js +11 -1
  8. package/dist/cjs/src/bitrue.js +1 -0
  9. package/dist/cjs/src/bybit.js +57 -9
  10. package/dist/cjs/src/coinbasepro.js +1 -0
  11. package/dist/cjs/src/coinex.js +37 -12
  12. package/dist/cjs/src/deribit.js +164 -0
  13. package/dist/cjs/src/okcoin.js +3 -0
  14. package/dist/cjs/src/phemex.js +5 -2
  15. package/dist/cjs/src/poloniex.js +1 -0
  16. package/dist/cjs/src/pro/bequant.js +6 -1
  17. package/dist/cjs/src/pro/binance.js +7 -4
  18. package/dist/cjs/src/pro/binancecoinm.js +6 -1
  19. package/dist/cjs/src/pro/binanceus.js +6 -1
  20. package/dist/cjs/src/pro/bitcoincom.js +6 -1
  21. package/dist/cjs/src/pro/bitget.js +1 -1
  22. package/dist/cjs/src/pro/bitrue.js +6 -1
  23. package/dist/cjs/src/pro/okx.js +13 -3
  24. package/dist/cjs/src/woo.js +1 -1
  25. package/js/ccxt.d.ts +1 -1
  26. package/js/ccxt.js +1 -1
  27. package/js/src/abstract/binance.d.ts +3 -0
  28. package/js/src/abstract/binancecoinm.d.ts +3 -0
  29. package/js/src/abstract/binanceus.d.ts +4 -0
  30. package/js/src/abstract/binanceusdm.d.ts +3 -0
  31. package/js/src/bigone.js +1 -0
  32. package/js/src/binance.js +14 -3
  33. package/js/src/bitget.js +11 -1
  34. package/js/src/bitrue.js +1 -0
  35. package/js/src/bybit.d.ts +2 -1
  36. package/js/src/bybit.js +57 -9
  37. package/js/src/coinbasepro.js +1 -0
  38. package/js/src/coinex.d.ts +1 -0
  39. package/js/src/coinex.js +37 -12
  40. package/js/src/deribit.d.ts +6 -1
  41. package/js/src/deribit.js +164 -0
  42. package/js/src/okcoin.js +3 -0
  43. package/js/src/phemex.js +5 -2
  44. package/js/src/poloniex.js +1 -0
  45. package/js/src/pro/bequant.js +6 -1
  46. package/js/src/pro/binance.js +7 -4
  47. package/js/src/pro/binancecoinm.js +6 -1
  48. package/js/src/pro/binanceus.js +6 -1
  49. package/js/src/pro/bitcoincom.js +6 -1
  50. package/js/src/pro/bitget.js +1 -1
  51. package/js/src/pro/bitrue.js +6 -1
  52. package/js/src/pro/okx.js +13 -3
  53. package/js/src/woo.js +1 -1
  54. package/jsdoc2md.js +38 -16
  55. package/package.json +4 -1
  56. package/skip-tests.json +4 -0
package/js/src/deribit.js CHANGED
@@ -405,6 +405,170 @@ export default class deribit extends Exchange {
405
405
  },
406
406
  });
407
407
  }
408
+ convertExpireDate(date) {
409
+ // parse YYMMDD to timestamp
410
+ const year = date.slice(0, 2);
411
+ const month = date.slice(2, 4);
412
+ const day = date.slice(4, 6);
413
+ const reconstructedDate = '20' + year + '-' + month + '-' + day + 'T00:00:00Z';
414
+ return reconstructedDate;
415
+ }
416
+ convertMarketIdExpireDate(date) {
417
+ // parse 19JAN24 to 240119
418
+ const monthMappping = {
419
+ 'JAN': '01',
420
+ 'FEB': '02',
421
+ 'MAR': '03',
422
+ 'APR': '04',
423
+ 'MAY': '05',
424
+ 'JUN': '06',
425
+ 'JUL': '07',
426
+ 'AUG': '08',
427
+ 'SEP': '09',
428
+ 'OCT': '10',
429
+ 'NOV': '11',
430
+ 'DEC': '12',
431
+ };
432
+ const year = date.slice(0, 2);
433
+ const monthName = date.slice(2, 5);
434
+ const month = this.safeString(monthMappping, monthName);
435
+ const day = date.slice(5, 7);
436
+ const reconstructedDate = day + month + year;
437
+ return reconstructedDate;
438
+ }
439
+ convertExpireDateToMarketIdDate(date) {
440
+ // parse 240119 to 19JAN24
441
+ const year = date.slice(0, 2);
442
+ const monthRaw = date.slice(2, 4);
443
+ let month = undefined;
444
+ const day = date.slice(4, 6);
445
+ if (monthRaw === '01') {
446
+ month = 'JAN';
447
+ }
448
+ else if (monthRaw === '02') {
449
+ month = 'FEB';
450
+ }
451
+ else if (monthRaw === '03') {
452
+ month = 'MAR';
453
+ }
454
+ else if (monthRaw === '04') {
455
+ month = 'APR';
456
+ }
457
+ else if (monthRaw === '05') {
458
+ month = 'MAY';
459
+ }
460
+ else if (monthRaw === '06') {
461
+ month = 'JUN';
462
+ }
463
+ else if (monthRaw === '07') {
464
+ month = 'JUL';
465
+ }
466
+ else if (monthRaw === '08') {
467
+ month = 'AUG';
468
+ }
469
+ else if (monthRaw === '09') {
470
+ month = 'SEP';
471
+ }
472
+ else if (monthRaw === '10') {
473
+ month = 'OCT';
474
+ }
475
+ else if (monthRaw === '11') {
476
+ month = 'NOV';
477
+ }
478
+ else if (monthRaw === '12') {
479
+ month = 'DEC';
480
+ }
481
+ const reconstructedDate = day + month + year;
482
+ return reconstructedDate;
483
+ }
484
+ createExpiredOptionMarket(symbol) {
485
+ // support expired option contracts
486
+ let quote = 'USD';
487
+ let settle = undefined;
488
+ const optionParts = symbol.split('-');
489
+ const symbolBase = symbol.split('/');
490
+ let base = undefined;
491
+ let expiry = undefined;
492
+ if (symbol.indexOf('/') > -1) {
493
+ base = this.safeString(symbolBase, 0);
494
+ expiry = this.safeString(optionParts, 1);
495
+ if (symbol.indexOf('USDC') > -1) {
496
+ base = base + '_USDC';
497
+ }
498
+ }
499
+ else {
500
+ base = this.safeString(optionParts, 0);
501
+ expiry = this.convertMarketIdExpireDate(this.safeString(optionParts, 1));
502
+ }
503
+ if (symbol.indexOf('USDC') > -1) {
504
+ quote = 'USDC';
505
+ settle = 'USDC';
506
+ }
507
+ else {
508
+ settle = base;
509
+ }
510
+ let splitBase = base;
511
+ if (base.indexOf('_') > -1) {
512
+ const splitSymbol = base.split('_');
513
+ splitBase = this.safeString(splitSymbol, 0);
514
+ }
515
+ const strike = this.safeString(optionParts, 2);
516
+ const optionType = this.safeString(optionParts, 3);
517
+ const datetime = this.convertExpireDate(expiry);
518
+ const timestamp = this.parse8601(datetime);
519
+ return {
520
+ 'id': base + '-' + this.convertExpireDateToMarketIdDate(expiry) + '-' + strike + '-' + optionType,
521
+ 'symbol': splitBase + '/' + quote + ':' + settle + '-' + expiry + '-' + strike + '-' + optionType,
522
+ 'base': base,
523
+ 'quote': quote,
524
+ 'settle': settle,
525
+ 'baseId': base,
526
+ 'quoteId': quote,
527
+ 'settleId': settle,
528
+ 'active': false,
529
+ 'type': 'option',
530
+ 'linear': undefined,
531
+ 'inverse': undefined,
532
+ 'spot': false,
533
+ 'swap': false,
534
+ 'future': false,
535
+ 'option': true,
536
+ 'margin': false,
537
+ 'contract': true,
538
+ 'contractSize': undefined,
539
+ 'expiry': timestamp,
540
+ 'expiryDatetime': datetime,
541
+ 'optionType': (optionType === 'C') ? 'call' : 'put',
542
+ 'strike': this.parseNumber(strike),
543
+ 'precision': {
544
+ 'amount': undefined,
545
+ 'price': undefined,
546
+ },
547
+ 'limits': {
548
+ 'amount': {
549
+ 'min': undefined,
550
+ 'max': undefined,
551
+ },
552
+ 'price': {
553
+ 'min': undefined,
554
+ 'max': undefined,
555
+ },
556
+ 'cost': {
557
+ 'min': undefined,
558
+ 'max': undefined,
559
+ },
560
+ },
561
+ 'info': undefined,
562
+ };
563
+ }
564
+ safeMarket(marketId = undefined, market = undefined, delimiter = undefined, marketType = undefined) {
565
+ const isOption = (marketId !== undefined) && ((marketId.endsWith('-C')) || (marketId.endsWith('-P')));
566
+ if (isOption && !(marketId in this.markets_by_id)) {
567
+ // handle expired option contracts
568
+ return this.createExpiredOptionMarket(marketId);
569
+ }
570
+ return super.safeMarket(marketId, market, delimiter, marketType);
571
+ }
408
572
  async fetchTime(params = {}) {
409
573
  /**
410
574
  * @method
package/js/src/okcoin.js CHANGED
@@ -49,6 +49,9 @@ export default class okcoin extends Exchange {
49
49
  'fetchCurrencies': true,
50
50
  'fetchDepositAddress': true,
51
51
  'fetchDeposits': true,
52
+ 'fetchFundingHistory': false,
53
+ 'fetchFundingRate': false,
54
+ 'fetchFundingRateHistory': false,
52
55
  'fetchLedger': true,
53
56
  'fetchMarkets': true,
54
57
  'fetchMyTrades': true,
package/js/src/phemex.js CHANGED
@@ -1918,16 +1918,19 @@ export default class phemex extends Exchange {
1918
1918
  * @method
1919
1919
  * @name phemex#fetchBalance
1920
1920
  * @description query for balance and get the amount of funds available for trading or funds locked in orders
1921
+ * @see https://phemex-docs.github.io/#query-wallets
1921
1922
  * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
1923
+ * @see https://phemex-docs.github.io/#query-trading-account-and-positions
1922
1924
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1923
1925
  * @param {string} [params.type] spot or swap
1926
+ * @param {string} [params.code] *swap only* currency code of the balance to query (USD, USDT, etc), default is USDT
1924
1927
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1925
1928
  */
1926
1929
  await this.loadMarkets();
1927
1930
  let type = undefined;
1928
1931
  [type, params] = this.handleMarketTypeAndParams('fetchBalance', undefined, params);
1929
1932
  const code = this.safeString(params, 'code');
1930
- params = this.omit(params, ['type', 'code']);
1933
+ params = this.omit(params, ['code']);
1931
1934
  let response = undefined;
1932
1935
  const request = {};
1933
1936
  if ((type !== 'spot') && (type !== 'swap')) {
@@ -1935,7 +1938,7 @@ export default class phemex extends Exchange {
1935
1938
  }
1936
1939
  if (type === 'swap') {
1937
1940
  let settle = undefined;
1938
- [settle, params] = this.handleOptionAndParams(params, 'fetchBalance', 'settle');
1941
+ [settle, params] = this.handleOptionAndParams(params, 'fetchBalance', 'settle', 'USDT');
1939
1942
  if (code !== undefined || settle !== undefined) {
1940
1943
  let coin = undefined;
1941
1944
  if (code !== undefined) {
@@ -58,6 +58,7 @@ export default class poloniex extends Exchange {
58
58
  'fetchOrder': true,
59
59
  'fetchOrderBook': true,
60
60
  'fetchOrderBooks': false,
61
+ 'fetchFundingRate': false,
61
62
  'fetchOrderTrades': true,
62
63
  'fetchPosition': false,
63
64
  'fetchPositionMode': false,
@@ -6,10 +6,15 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import hitbtc from './hitbtc.js';
9
+ import bequantRest from '../bequant.js';
9
10
  // ---------------------------------------------------------------------------
10
11
  export default class bequant extends hitbtc {
11
12
  describe() {
12
- return this.deepExtend(super.describe(), {
13
+ // eslint-disable-next-line new-cap
14
+ const restInstance = new bequantRest();
15
+ const restDescribe = restInstance.describe();
16
+ const extended = this.deepExtend(super.describe(), restDescribe);
17
+ return this.deepExtend(extended, {
13
18
  'id': 'bequant',
14
19
  'name': 'Bequant',
15
20
  'countries': ['MT'],
@@ -47,7 +47,7 @@ export default class binance extends binanceRest {
47
47
  'ws': {
48
48
  'spot': 'wss://testnet.binance.vision/ws',
49
49
  'margin': 'wss://testnet.binance.vision/ws',
50
- 'future': 'wss://stream.binancefuture.com/ws',
50
+ 'future': 'wss://fstream.binancefuture.com/ws',
51
51
  'delivery': 'wss://dstream.binancefuture.com/ws',
52
52
  'ws': 'wss://testnet.binance.vision/ws-api/v3',
53
53
  },
@@ -1980,12 +1980,13 @@ export default class binance extends binanceRest {
1980
1980
  /**
1981
1981
  * @method
1982
1982
  * @name binance#watchOrders
1983
- * @see https://binance-docs.github.io/apidocs/spot/en/#payload-order-update
1984
1983
  * @description watches information on multiple orders made by the user
1985
- * @param {string} symbol unified market symbol of the market orders were made in
1984
+ * @see https://binance-docs.github.io/apidocs/spot/en/#payload-order-update
1985
+ * @param {string} symbol unified market symbol of the market the orders were made in
1986
1986
  * @param {int} [since] the earliest time in ms to fetch orders for
1987
1987
  * @param {int} [limit] the maximum number of order structures to retrieve
1988
1988
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1989
+ * @param {string|undefined} [params.marginMode] 'cross' or 'isolated', for spot margin
1989
1990
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1990
1991
  */
1991
1992
  await this.loadMarkets();
@@ -2008,8 +2009,10 @@ export default class binance extends binanceRest {
2008
2009
  }
2009
2010
  params = this.extend(params, { 'type': type, 'symbol': symbol }); // needed inside authenticate for isolated margin
2010
2011
  await this.authenticate(params);
2012
+ let marginMode = undefined;
2013
+ [marginMode, params] = this.handleMarginModeAndParams('watchOrders', params);
2011
2014
  let urlType = type;
2012
- if (type === 'margin') {
2015
+ if ((type === 'margin') || ((type === 'spot') && (marginMode !== undefined))) {
2013
2016
  urlType = 'spot'; // spot-margin shares the same stream as regular spot
2014
2017
  }
2015
2018
  const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
@@ -6,10 +6,15 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import binance from './binance.js';
9
+ import binancecoinmRest from '../binancecoinm.js';
9
10
  // ---------------------------------------------------------------------------
10
11
  export default class binancecoinm extends binance {
11
12
  describe() {
12
- return this.deepExtend(super.describe(), {
13
+ // eslint-disable-next-line new-cap
14
+ const restInstance = new binancecoinmRest();
15
+ const restDescribe = restInstance.describe();
16
+ const extended = this.deepExtend(super.describe(), restDescribe);
17
+ return this.deepExtend(extended, {
13
18
  'id': 'binancecoinm',
14
19
  'name': 'Binance COIN-M',
15
20
  'urls': {
@@ -6,10 +6,15 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import binance from './binance.js';
9
+ import binanceusRest from '../binanceus.js';
9
10
  // ---------------------------------------------------------------------------
10
11
  export default class binanceus extends binance {
11
12
  describe() {
12
- return this.deepExtend(super.describe(), {
13
+ // eslint-disable-next-line new-cap
14
+ const restInstance = new binanceusRest();
15
+ const restDescribe = restInstance.describe();
16
+ const extended = this.deepExtend(super.describe(), restDescribe);
17
+ return this.deepExtend(extended, {
13
18
  'id': 'binanceus',
14
19
  'name': 'Binance US',
15
20
  'countries': ['US'],
@@ -6,10 +6,15 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import hitbtc from './hitbtc.js';
9
+ import bequantRest from '../bequant.js';
9
10
  // ---------------------------------------------------------------------------
10
11
  export default class bitcoincom extends hitbtc {
11
12
  describe() {
12
- return this.deepExtend(super.describe(), {
13
+ // eslint-disable-next-line new-cap
14
+ const restInstance = new bequantRest();
15
+ const restDescribe = restInstance.describe();
16
+ const extended = this.deepExtend(super.describe(), restDescribe);
17
+ return this.deepExtend(extended, {
13
18
  'id': 'bitcoincom',
14
19
  'name': 'bitcoin.com',
15
20
  'countries': ['KN'],
@@ -1248,7 +1248,7 @@ export default class bitget extends bitgetRest {
1248
1248
  'price': this.safeString(order, 'price'),
1249
1249
  'stopPrice': triggerPrice,
1250
1250
  'triggerPrice': triggerPrice,
1251
- 'amount': this.safeString2(order, 'size', 'baseSize'),
1251
+ 'amount': this.safeString(order, 'baseVolume'),
1252
1252
  'cost': this.safeStringN(order, ['notional', 'notionalUsd', 'quoteSize']),
1253
1253
  'average': this.omitZero(this.safeString2(order, 'priceAvg', 'fillPrice')),
1254
1254
  'filled': this.safeString2(order, 'accBaseVolume', 'baseVolume'),
@@ -349,7 +349,12 @@ export default class bitrue extends bitrueRest {
349
349
  const symbol = market['symbol'];
350
350
  const timestamp = this.safeInteger(message, 'ts');
351
351
  const tick = this.safeValue(message, 'tick', {});
352
- const orderbook = this.parseOrderBook(tick, symbol, timestamp, 'buys', 'asks');
352
+ let orderbook = this.safeValue(this.orderbooks, symbol);
353
+ if (orderbook === undefined) {
354
+ orderbook = this.orderBook();
355
+ }
356
+ const snapshot = this.parseOrderBook(tick, symbol, timestamp, 'buys', 'asks');
357
+ orderbook.reset(snapshot);
353
358
  this.orderbooks[symbol] = orderbook;
354
359
  const messageHash = 'orderbook:' + symbol;
355
360
  client.resolve(orderbook, messageHash);
package/js/src/pro/okx.js CHANGED
@@ -1014,17 +1014,20 @@ export default class okx extends okxRest {
1014
1014
  /**
1015
1015
  * @method
1016
1016
  * @name okx#watchOrders
1017
- * @see https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-order-channel
1018
1017
  * @description watches information on multiple orders made by the user
1019
- * @param {string} [symbol] unified market symbol of the market orders were made in
1018
+ * @see https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-order-channel
1019
+ * @param {string} [symbol] unified market symbol of the market the orders were made in
1020
1020
  * @param {int} [since] the earliest time in ms to fetch orders for
1021
1021
  * @param {int} [limit] the maximum number of order structures to retrieve
1022
1022
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1023
1023
  * @param {bool} [params.stop] true if fetching trigger or conditional orders
1024
+ * @param {string} [params.type] 'spot', 'swap', 'future', 'option', 'ANY', 'SPOT', 'MARGIN', 'SWAP', 'FUTURES' or 'OPTION'
1025
+ * @param {string} [params.marginMode] 'cross' or 'isolated', for automatically setting the type to spot margin
1024
1026
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1025
1027
  */
1026
1028
  let type = undefined;
1027
1029
  // By default, receive order updates from any instrument type
1030
+ [type, params] = this.handleOptionAndParams(params, 'watchOrders', 'defaultType');
1028
1031
  [type, params] = this.handleOptionAndParams(params, 'watchOrders', 'type', 'ANY');
1029
1032
  const isStop = this.safeValue2(params, 'stop', 'trigger', false);
1030
1033
  params = this.omit(params, ['stop', 'trigger']);
@@ -1039,7 +1042,14 @@ export default class okx extends okxRest {
1039
1042
  if (type === 'future') {
1040
1043
  type = 'futures';
1041
1044
  }
1042
- const uppercaseType = type.toUpperCase();
1045
+ let uppercaseType = type.toUpperCase();
1046
+ let marginMode = undefined;
1047
+ [marginMode, params] = this.handleMarginModeAndParams('watchOrders', params);
1048
+ if (uppercaseType === 'SPOT') {
1049
+ if (marginMode !== undefined) {
1050
+ uppercaseType = 'MARGIN';
1051
+ }
1052
+ }
1043
1053
  const request = {
1044
1054
  'instType': uppercaseType,
1045
1055
  };
package/js/src/woo.js CHANGED
@@ -61,7 +61,7 @@ export default class woo extends Exchange {
61
61
  'fetchClosedOrder': false,
62
62
  'fetchClosedOrders': false,
63
63
  'fetchCurrencies': true,
64
- 'fetchDepositAddress': false,
64
+ 'fetchDepositAddress': true,
65
65
  'fetchDeposits': true,
66
66
  'fetchDepositsWithdrawals': true,
67
67
  'fetchFundingHistory': true,
package/jsdoc2md.js CHANGED
@@ -29,9 +29,12 @@ const findByExtensionSync = (dir, ext) => {
29
29
  // Get all files to read js docs
30
30
  const inputFiles = findByExtensionSync('js/src', 'js')
31
31
  const proInputFiles = findByExtensionSync('js/src/pro', 'js');
32
- const partials = './wiki/partials/'
33
- const partial = fs.readdirSync (partials).map (file => partials + file)
34
- const outputFile = './wiki/spec.md'
32
+ const basePartials = './wiki/basePartials/'
33
+ const basePartial = fs.readdirSync (basePartials).map (file => basePartials + file)
34
+ const exchangePartials = './wiki/exchangePartials/'
35
+ const exchangePartial = fs.readdirSync (exchangePartials).map (file => exchangePartials + file)
36
+ const outputFolder = './wiki/'
37
+ const outputFile = './wiki/baseSpec.md'
35
38
  const helper = './wiki/helpers.cjs'
36
39
 
37
40
  console.log ('πŸ“° loading js docs...')
@@ -54,6 +57,7 @@ proTemplateData.forEach((proData) => {
54
57
  console.log ('πŸ“° rendering docs for each exchange...')
55
58
  const template = fs.readFileSync ('./wiki/spec.hbs', 'utf8')
56
59
 
60
+ const outputByExchange = await Promise.all (templateData.map (data => jsdoc2md.render ({ template, data, partial: exchangePartial, helper })))
57
61
  // Group docs by method
58
62
  const groupedByMethod = templateData.reduce((acc, arr) => {
59
63
  arr.filter(obj => obj.kind === 'function' && !obj.ignore).forEach(obj => {
@@ -79,21 +83,39 @@ const groupedByMethod = templateData.reduce((acc, arr) => {
79
83
 
80
84
  const templateDataGroupedByMethod = Object.values(groupedByMethod).sort((a, b) =>a[0].name < b[0].name ? -1 : 1)
81
85
 
82
- const outputs = await Promise.all (templateDataGroupedByMethod.map (data => jsdoc2md.render ({ template, data, partial, helper})))
86
+
87
+ const baseOutput = await Promise.all (templateDataGroupedByMethod.map (data => jsdoc2md.render ({ template, data, partial: basePartial, helper})))
83
88
 
84
89
  console.log ('πŸ“° creating index of exchange functions')
85
- const functions = Object.keys(groupedByMethod).sort ()
86
- const alphabet = Array.from ( Array (26)).map((e, i) => String.fromCharCode(i + 97));
87
-
88
- const index = {}
89
- let i = -1
90
- for (const char of alphabet) {
91
- do {
92
- index[char] = functions[++i]
93
- } while (char > functions[i])
94
- }
95
-
96
- fs.writeFileSync (outputFile, outputs.join ('\n---\n'))
90
+ const exchangeLinks = []
91
+ outputByExchange.forEach ((output, i) => {
92
+ const name = templateData[i][0].id
93
+ const fileName = 'exchanges/' + name + '.md'
94
+ fs.writeFileSync (outputFolder + fileName, output)
95
+ exchangeLinks.push (`\t- [${name}](${fileName})`)
96
+ })
97
+
98
+
99
+ fs.writeFileSync (outputFile, baseOutput.join ('\n---\n'))
100
+
101
+ const sidebar =
102
+ `
103
+ - [Install](Install.md)
104
+ - [Examples](Examples.md)
105
+ - [Manual](Manual.md)
106
+ - [CCXT Pro](ccxt.pro.manual.md)
107
+ - [Contributing](CONTRIBUTING.md)
108
+ - [Supported Exchanges](Exchange-Markets.md)
109
+ - [Exchanges By Country](Exchange-Markets-By-Country.md)
110
+ - [API Spec By Method](baseSpec.md)
111
+ - API Spec by Exchange
112
+ ${exchangeLinks.join('\n')}
113
+ - [Changelog](CHANGELOG.md)
114
+ - [Awesome](Awesome.md)
115
+ `
116
+ fs.writeFileSync('./wiki/_sidebar.md', sidebar);
117
+
97
118
  console.log ('πŸ“° finished rendering docs! πŸ™Œ πŸ˜Άβ€πŸŒ«')
98
119
 
99
120
  })()
121
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccxt",
3
- "version": "4.2.21",
3
+ "version": "4.2.22",
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",
@@ -22,6 +22,9 @@
22
22
  },
23
23
  "readme": "README.md",
24
24
  "scripts": {
25
+ "instrument": "nyc instrument js/ jsInstrumented/",
26
+ "nyc-coverage": "nyc --reporter=html --reporter=lcov --exclude='js/src/pro/**' --exclude='js/src/base/**' --exclude='js/src/test/**' --exclude='js/src/abstract/**' --exclude='js/src/static_dependencies' node jsInstrumented/src/test/test.js --requestTests --responseTests",
27
+ "coverage-js": "npm run instrument && npm run nyc-coverage && rm -rf jsInstrumented",
25
28
  "docker": "docker-compose run --rm ccxt",
26
29
  "fixTSBug": "node build/fixTSBug",
27
30
  "build-docs": "node jsdoc2md.js && node examples2md.js",
package/skip-tests.json CHANGED
@@ -1433,6 +1433,10 @@
1433
1433
  },
1434
1434
  "watchOrderBook": {
1435
1435
  "nonce": "missing https://app.travis-ci.com/github/ccxt/ccxt/builds/267900037#L6909"
1436
+ },
1437
+ "watchTickers": {
1438
+ "quoteVolume": "same",
1439
+ "baseVolume": "same"
1436
1440
  }
1437
1441
  }
1438
1442
  },