ccxt 4.4.82 → 4.4.86

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 (145) hide show
  1. package/README.md +6 -9
  2. package/dist/ccxt.browser.min.js +7 -7
  3. package/dist/cjs/ccxt.js +6 -17
  4. package/dist/cjs/src/abstract/bittrade.js +9 -0
  5. package/dist/cjs/src/apex.js +2 -1
  6. package/dist/cjs/src/ascendex.js +189 -155
  7. package/dist/cjs/src/base/Exchange.js +15 -2
  8. package/dist/cjs/src/bequant.js +1 -1
  9. package/dist/cjs/src/bitget.js +6 -7
  10. package/dist/cjs/src/bitmart.js +1 -1
  11. package/dist/cjs/src/bitrue.js +14 -35
  12. package/dist/cjs/src/bitso.js +33 -0
  13. package/dist/cjs/src/bitstamp.js +33 -0
  14. package/dist/cjs/src/bittrade.js +2049 -0
  15. package/dist/cjs/src/blofin.js +154 -13
  16. package/dist/cjs/src/btcbox.js +25 -5
  17. package/dist/cjs/src/bybit.js +16 -40
  18. package/dist/cjs/src/cex.js +2 -4
  19. package/dist/cjs/src/coinbase.js +58 -46
  20. package/dist/cjs/src/coinbaseexchange.js +142 -32
  21. package/dist/cjs/src/coincatch.js +14 -67
  22. package/dist/cjs/src/coinex.js +29 -32
  23. package/dist/cjs/src/coinlist.js +16 -15
  24. package/dist/cjs/src/coinmetro.js +22 -11
  25. package/dist/cjs/src/coinone.js +8 -10
  26. package/dist/cjs/src/coinsph.js +126 -1
  27. package/dist/cjs/src/cryptocom.js +111 -1
  28. package/dist/cjs/src/cryptomus.js +43 -89
  29. package/dist/cjs/src/delta.js +76 -36
  30. package/dist/cjs/src/deribit.js +4 -5
  31. package/dist/cjs/src/derive.js +46 -10
  32. package/dist/cjs/src/ellipx.js +175 -79
  33. package/dist/cjs/src/gate.js +1 -1
  34. package/dist/cjs/src/gemini.js +3 -5
  35. package/dist/cjs/src/hitbtc.js +56 -69
  36. package/dist/cjs/src/hollaex.js +107 -49
  37. package/dist/cjs/src/htx.js +20 -44
  38. package/dist/cjs/src/hyperliquid.js +6 -6
  39. package/dist/cjs/src/kraken.js +29 -24
  40. package/dist/cjs/src/kucoinfutures.js +6 -0
  41. package/dist/cjs/src/lbank.js +1 -1
  42. package/dist/cjs/src/mexc.js +2 -2
  43. package/dist/cjs/src/ndax.js +25 -24
  44. package/dist/cjs/src/okcoin.js +12 -31
  45. package/dist/cjs/src/okx.js +9 -0
  46. package/dist/cjs/src/onetrading.js +9 -6
  47. package/dist/cjs/src/oxfun.js +42 -114
  48. package/dist/cjs/src/paradex.js +124 -4
  49. package/dist/cjs/src/pro/binance.js +32 -33
  50. package/dist/cjs/src/pro/bithumb.js +5 -3
  51. package/dist/cjs/src/pro/bittrade.js +605 -0
  52. package/dist/cjs/src/pro/kraken.js +289 -79
  53. package/dist/cjs/src/pro/luno.js +6 -5
  54. package/dist/cjs/src/pro/mexc.js +304 -7
  55. package/dist/cjs/src/pro/poloniex.js +6 -2
  56. package/examples/js/cli.js +127 -13
  57. package/js/ccxt.d.ts +8 -20
  58. package/js/ccxt.js +6 -14
  59. package/js/src/abstract/blofin.d.ts +8 -0
  60. package/js/src/abstract/btcbox.d.ts +1 -0
  61. package/js/src/abstract/myokx.d.ts +2 -0
  62. package/js/src/abstract/okx.d.ts +2 -0
  63. package/js/src/apex.js +2 -1
  64. package/js/src/ascendex.d.ts +2 -0
  65. package/js/src/ascendex.js +189 -155
  66. package/js/src/base/Exchange.d.ts +15 -1
  67. package/js/src/base/Exchange.js +15 -2
  68. package/js/src/base/types.d.ts +3 -0
  69. package/js/src/bequant.js +1 -1
  70. package/js/src/bitget.js +6 -7
  71. package/js/src/bitmart.js +1 -1
  72. package/js/src/bitrue.js +14 -35
  73. package/js/src/bitso.js +33 -0
  74. package/js/src/bitstamp.js +33 -0
  75. package/js/src/{huobijp.d.ts → bittrade.d.ts} +29 -29
  76. package/js/src/{huobijp.js → bittrade.js} +35 -35
  77. package/js/src/blofin.d.ts +42 -2
  78. package/js/src/blofin.js +154 -13
  79. package/js/src/btcbox.js +25 -5
  80. package/js/src/bybit.js +16 -40
  81. package/js/src/cex.js +2 -4
  82. package/js/src/coinbase.js +58 -46
  83. package/js/src/coinbaseexchange.js +142 -32
  84. package/js/src/coincatch.js +14 -67
  85. package/js/src/coinex.js +28 -29
  86. package/js/src/coinlist.js +16 -15
  87. package/js/src/coinmetro.js +22 -11
  88. package/js/src/coinone.js +8 -10
  89. package/js/src/coinsph.d.ts +10 -1
  90. package/js/src/coinsph.js +126 -1
  91. package/js/src/cryptocom.d.ts +10 -1
  92. package/js/src/cryptocom.js +111 -1
  93. package/js/src/cryptomus.js +43 -89
  94. package/js/src/delta.js +76 -36
  95. package/js/src/deribit.js +4 -5
  96. package/js/src/derive.js +46 -10
  97. package/js/src/ellipx.d.ts +2 -3
  98. package/js/src/ellipx.js +175 -80
  99. package/js/src/gate.js +1 -1
  100. package/js/src/gemini.js +3 -5
  101. package/js/src/hitbtc.js +56 -69
  102. package/js/src/hollaex.js +107 -49
  103. package/js/src/htx.js +20 -44
  104. package/js/src/hyperliquid.js +6 -6
  105. package/js/src/kraken.js +29 -24
  106. package/js/src/kucoinfutures.d.ts +1 -0
  107. package/js/src/kucoinfutures.js +6 -0
  108. package/js/src/lbank.js +1 -1
  109. package/js/src/mexc.js +2 -2
  110. package/js/src/ndax.js +25 -24
  111. package/js/src/okcoin.js +12 -31
  112. package/js/src/okx.js +9 -0
  113. package/js/src/onetrading.js +9 -6
  114. package/js/src/oxfun.js +42 -114
  115. package/js/src/paradex.d.ts +12 -1
  116. package/js/src/paradex.js +124 -4
  117. package/js/src/pro/binance.d.ts +26 -26
  118. package/js/src/pro/binance.js +32 -33
  119. package/js/src/pro/bithumb.js +5 -3
  120. package/js/src/pro/{huobijp.d.ts → bittrade.d.ts} +6 -6
  121. package/js/src/pro/{huobijp.js → bittrade.js} +7 -7
  122. package/js/src/pro/kraken.d.ts +7 -6
  123. package/js/src/pro/kraken.js +290 -80
  124. package/js/src/pro/luno.js +6 -5
  125. package/js/src/pro/mexc.d.ts +58 -0
  126. package/js/src/pro/mexc.js +304 -7
  127. package/js/src/pro/poloniex.d.ts +1 -1
  128. package/js/src/pro/poloniex.js +6 -2
  129. package/package.json +1 -1
  130. package/js/src/abstract/bl3p.d.ts +0 -22
  131. package/js/src/abstract/huobijp.js +0 -11
  132. package/js/src/abstract/idex.d.ts +0 -29
  133. package/js/src/abstract/idex.js +0 -11
  134. package/js/src/abstract/kuna.d.ts +0 -185
  135. package/js/src/abstract/kuna.js +0 -11
  136. package/js/src/bl3p.d.ts +0 -116
  137. package/js/src/bl3p.js +0 -552
  138. package/js/src/idex.d.ts +0 -312
  139. package/js/src/idex.js +0 -1961
  140. package/js/src/kuna.d.ts +0 -335
  141. package/js/src/kuna.js +0 -2006
  142. package/js/src/pro/idex.d.ts +0 -81
  143. package/js/src/pro/idex.js +0 -720
  144. /package/js/src/abstract/{huobijp.d.ts → bittrade.d.ts} +0 -0
  145. /package/js/src/abstract/{bl3p.js → bittrade.js} +0 -0
@@ -31,6 +31,12 @@ class mexc extends mexc$1 {
31
31
  'watchBidsAsks': true,
32
32
  'watchTrades': true,
33
33
  'watchTradesForSymbols': false,
34
+ 'unWatchTicker': true,
35
+ 'unWatchTickers': true,
36
+ 'unWatchBidsAsks': true,
37
+ 'unWatchOHLCV': true,
38
+ 'unWatchOrderBook': true,
39
+ 'unWatchTrades': true,
34
40
  },
35
41
  'urls': {
36
42
  'api': {
@@ -488,12 +494,15 @@ class mexc extends mexc$1 {
488
494
  }, market);
489
495
  }
490
496
  async watchSpotPublic(channel, messageHash, params = {}) {
497
+ const unsubscribed = this.safeBool(params, 'unsubscribed', false);
498
+ params = this.omit(params, ['unsubscribed']);
491
499
  const url = this.urls['api']['ws']['spot'];
500
+ const method = (unsubscribed) ? 'UNSUBSCRIPTION' : 'SUBSCRIPTION';
492
501
  const request = {
493
- 'method': 'SUBSCRIPTION',
502
+ 'method': method,
494
503
  'params': [channel],
495
504
  };
496
- return await this.watch(url, messageHash, this.extend(request, params), channel);
505
+ return await this.watch(url, messageHash, this.extend(request, params), messageHash);
497
506
  }
498
507
  async watchSpotPrivate(channel, messageHash, params = {}) {
499
508
  this.checkRequiredCredentials();
@@ -785,11 +794,8 @@ class mexc extends mexc$1 {
785
794
  const messageHash = 'orderbook:' + symbol;
786
795
  const subscription = this.safeValue(client.subscriptions, messageHash);
787
796
  const limit = this.safeInteger(subscription, 'limit');
788
- if (subscription === true) {
789
- // we set client.subscriptions[messageHash] to 1
790
- // once we have received the first delta and initialized the orderbook
791
- client.subscriptions[messageHash] = 1;
792
- this.orderbooks[symbol] = this.countedOrderBook({});
797
+ if (!(symbol in this.orderbooks)) {
798
+ this.orderbooks[symbol] = this.orderBook();
793
799
  }
794
800
  const storedOrderBook = this.orderbooks[symbol];
795
801
  const nonce = this.safeInteger(storedOrderBook, 'nonce');
@@ -1412,6 +1418,297 @@ class mexc extends mexc$1 {
1412
1418
  this.balance[type] = this.safeBalance(this.balance[type]);
1413
1419
  client.resolve(this.balance[type], messageHash);
1414
1420
  }
1421
+ /**
1422
+ * @method
1423
+ * @name mexc#unWatchTicker
1424
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
1425
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
1426
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1427
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1428
+ */
1429
+ async unWatchTicker(symbol, params = {}) {
1430
+ await this.loadMarkets();
1431
+ const market = this.market(symbol);
1432
+ const messageHash = 'unsubscribe:ticker:' + market['symbol'];
1433
+ let url = undefined;
1434
+ let channel = undefined;
1435
+ if (market['spot']) {
1436
+ let miniTicker = false;
1437
+ [miniTicker, params] = this.handleOptionAndParams(params, 'watchTicker', 'miniTicker');
1438
+ if (miniTicker) {
1439
+ channel = 'spot@public.miniTicker.v3.api@' + market['id'] + '@UTC+8';
1440
+ }
1441
+ else {
1442
+ channel = 'spot@public.bookTicker.v3.api@' + market['id'];
1443
+ }
1444
+ url = this.urls['api']['ws']['spot'];
1445
+ params['unsubscribed'] = true;
1446
+ this.watchSpotPublic(channel, messageHash, params);
1447
+ }
1448
+ else {
1449
+ channel = 'unsub.ticker';
1450
+ const requestParams = {
1451
+ 'symbol': market['id'],
1452
+ };
1453
+ url = this.urls['api']['ws']['swap'];
1454
+ this.watchSwapPublic(channel, messageHash, requestParams, params);
1455
+ }
1456
+ const client = this.client(url);
1457
+ this.handleUnsubscriptions(client, [messageHash]);
1458
+ return undefined;
1459
+ }
1460
+ /**
1461
+ * @method
1462
+ * @name mexc#unWatchTickers
1463
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
1464
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
1465
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1466
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1467
+ */
1468
+ async unWatchTickers(symbols = undefined, params = {}) {
1469
+ await this.loadMarkets();
1470
+ symbols = this.marketSymbols(symbols, undefined);
1471
+ const messageHashes = [];
1472
+ const firstSymbol = this.safeString(symbols, 0);
1473
+ let market = undefined;
1474
+ if (firstSymbol !== undefined) {
1475
+ market = this.market(firstSymbol);
1476
+ }
1477
+ let type = undefined;
1478
+ [type, params] = this.handleMarketTypeAndParams('watchTickers', market, params);
1479
+ const isSpot = (type === 'spot');
1480
+ const url = (isSpot) ? this.urls['api']['ws']['spot'] : this.urls['api']['ws']['swap'];
1481
+ const request = {};
1482
+ if (isSpot) {
1483
+ let miniTicker = false;
1484
+ [miniTicker, params] = this.handleOptionAndParams(params, 'watchTickers', 'miniTicker');
1485
+ const topics = [];
1486
+ if (!miniTicker) {
1487
+ if (symbols === undefined) {
1488
+ throw new errors.ArgumentsRequired(this.id + ' watchTickers required symbols argument for the bookTicker channel');
1489
+ }
1490
+ const marketIds = this.marketIds(symbols);
1491
+ for (let i = 0; i < marketIds.length; i++) {
1492
+ const marketId = marketIds[i];
1493
+ messageHashes.push('unsubscribe:ticker:' + symbols[i]);
1494
+ const channel = 'spot@public.bookTicker.v3.api@' + marketId;
1495
+ topics.push(channel);
1496
+ }
1497
+ }
1498
+ else {
1499
+ topics.push('spot@public.miniTickers.v3.api@UTC+8');
1500
+ if (symbols === undefined) {
1501
+ messageHashes.push('unsubscribe:spot:ticker');
1502
+ }
1503
+ else {
1504
+ for (let i = 0; i < symbols.length; i++) {
1505
+ messageHashes.push('unsubscribe:ticker:' + symbols[i]);
1506
+ }
1507
+ }
1508
+ }
1509
+ request['method'] = 'UNSUBSCRIPTION';
1510
+ request['params'] = topics;
1511
+ }
1512
+ else {
1513
+ request['method'] = 'unsub.tickers';
1514
+ request['params'] = {};
1515
+ messageHashes.push('unsubscribe:ticker');
1516
+ }
1517
+ const client = this.client(url);
1518
+ this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes);
1519
+ this.handleUnsubscriptions(client, messageHashes);
1520
+ return undefined;
1521
+ }
1522
+ /**
1523
+ * @method
1524
+ * @name mexc#unWatchBidsAsks
1525
+ * @description unWatches best bid & ask for symbols
1526
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
1527
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1528
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1529
+ */
1530
+ async unWatchBidsAsks(symbols = undefined, params = {}) {
1531
+ await this.loadMarkets();
1532
+ symbols = this.marketSymbols(symbols, undefined, true, false, true);
1533
+ let marketType = undefined;
1534
+ if (symbols === undefined) {
1535
+ throw new errors.ArgumentsRequired(this.id + ' watchBidsAsks required symbols argument');
1536
+ }
1537
+ const markets = this.marketsForSymbols(symbols);
1538
+ [marketType, params] = this.handleMarketTypeAndParams('watchBidsAsks', markets[0], params);
1539
+ const isSpot = marketType === 'spot';
1540
+ if (!isSpot) {
1541
+ throw new errors.NotSupported(this.id + ' watchBidsAsks only support spot market');
1542
+ }
1543
+ const messageHashes = [];
1544
+ const topics = [];
1545
+ for (let i = 0; i < symbols.length; i++) {
1546
+ if (isSpot) {
1547
+ const market = this.market(symbols[i]);
1548
+ topics.push('spot@public.bookTicker.v3.api@' + market['id']);
1549
+ }
1550
+ messageHashes.push('unsubscribe:bidask:' + symbols[i]);
1551
+ }
1552
+ const url = this.urls['api']['ws']['spot'];
1553
+ const request = {
1554
+ 'method': 'UNSUBSCRIPTION',
1555
+ 'params': topics,
1556
+ };
1557
+ const client = this.client(url);
1558
+ this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes);
1559
+ this.handleUnsubscriptions(client, messageHashes);
1560
+ return undefined;
1561
+ }
1562
+ /**
1563
+ * @method
1564
+ * @name mexc#unWatchOHLCV
1565
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1566
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1567
+ * @param {string} timeframe the length of time each candle represents
1568
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1569
+ * @param {object} [params.timezone] if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1570
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1571
+ */
1572
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
1573
+ await this.loadMarkets();
1574
+ const market = this.market(symbol);
1575
+ symbol = market['symbol'];
1576
+ const timeframes = this.safeValue(this.options, 'timeframes', {});
1577
+ const timeframeId = this.safeString(timeframes, timeframe);
1578
+ const messageHash = 'unsubscribe:candles:' + symbol + ':' + timeframe;
1579
+ let url = undefined;
1580
+ if (market['spot']) {
1581
+ url = this.urls['api']['ws']['spot'];
1582
+ const channel = 'spot@public.kline.v3.api@' + market['id'] + '@' + timeframeId;
1583
+ params['unsubscribed'] = true;
1584
+ this.watchSpotPublic(channel, messageHash, params);
1585
+ }
1586
+ else {
1587
+ url = this.urls['api']['ws']['swap'];
1588
+ const channel = 'unsub.kline';
1589
+ const requestParams = {
1590
+ 'symbol': market['id'],
1591
+ 'interval': timeframeId,
1592
+ };
1593
+ this.watchSwapPublic(channel, messageHash, requestParams, params);
1594
+ }
1595
+ const client = this.client(url);
1596
+ this.handleUnsubscriptions(client, [messageHash]);
1597
+ return undefined;
1598
+ }
1599
+ /**
1600
+ * @method
1601
+ * @name mexc#unWatchOrderBook
1602
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
1603
+ * @param {string} symbol unified array of symbols
1604
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1605
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
1606
+ */
1607
+ async unWatchOrderBook(symbol, params = {}) {
1608
+ await this.loadMarkets();
1609
+ const market = this.market(symbol);
1610
+ symbol = market['symbol'];
1611
+ const messageHash = 'unsubscribe:orderbook:' + symbol;
1612
+ let url = undefined;
1613
+ if (market['spot']) {
1614
+ url = this.urls['api']['ws']['spot'];
1615
+ const channel = 'spot@public.increase.depth.v3.api@' + market['id'];
1616
+ params['unsubscribed'] = true;
1617
+ this.watchSpotPublic(channel, messageHash, params);
1618
+ }
1619
+ else {
1620
+ url = this.urls['api']['ws']['swap'];
1621
+ const channel = 'unsub.depth';
1622
+ const requestParams = {
1623
+ 'symbol': market['id'],
1624
+ };
1625
+ this.watchSwapPublic(channel, messageHash, requestParams, params);
1626
+ }
1627
+ const client = this.client(url);
1628
+ this.handleUnsubscriptions(client, [messageHash]);
1629
+ return undefined;
1630
+ }
1631
+ /**
1632
+ * @method
1633
+ * @name mexc#unWatchTrades
1634
+ * @description unsubscribes from the trades channel
1635
+ * @param {string} symbol unified symbol of the market to fetch trades for
1636
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1637
+ * @param {string} [params.name] the name of the method to call, 'trade' or 'aggTrade', default is 'trade'
1638
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
1639
+ */
1640
+ async unWatchTrades(symbol, params = {}) {
1641
+ await this.loadMarkets();
1642
+ const market = this.market(symbol);
1643
+ symbol = market['symbol'];
1644
+ const messageHash = 'unsubscribe:trades:' + symbol;
1645
+ let url = undefined;
1646
+ if (market['spot']) {
1647
+ url = this.urls['api']['ws']['spot'];
1648
+ const channel = 'spot@public.deals.v3.api@' + market['id'];
1649
+ params['unsubscribed'] = true;
1650
+ this.watchSpotPublic(channel, messageHash, params);
1651
+ }
1652
+ else {
1653
+ url = this.urls['api']['ws']['swap'];
1654
+ const channel = 'unsub.deal';
1655
+ const requestParams = {
1656
+ 'symbol': market['id'],
1657
+ };
1658
+ this.watchSwapPublic(channel, messageHash, requestParams, params);
1659
+ }
1660
+ const client = this.client(url);
1661
+ this.handleUnsubscriptions(client, [messageHash]);
1662
+ return undefined;
1663
+ }
1664
+ handleUnsubscriptions(client, messageHashes) {
1665
+ for (let i = 0; i < messageHashes.length; i++) {
1666
+ const messageHash = messageHashes[i];
1667
+ const subMessageHash = messageHash.replace('unsubscribe:', '');
1668
+ this.cleanUnsubscription(client, subMessageHash, messageHash);
1669
+ if (messageHash.indexOf('ticker') >= 0) {
1670
+ const symbol = messageHash.replace('unsubscribe:ticker:', '');
1671
+ if (symbol.indexOf('unsubscribe') >= 0) {
1672
+ // unWatchTickers
1673
+ const symbols = Object.keys(this.tickers);
1674
+ for (let j = 0; j < symbols.length; j++) {
1675
+ delete this.tickers[symbols[j]];
1676
+ }
1677
+ }
1678
+ else if (symbol in this.tickers) {
1679
+ delete this.tickers[symbol];
1680
+ }
1681
+ }
1682
+ else if (messageHash.indexOf('bidask') >= 0) {
1683
+ const symbol = messageHash.replace('unsubscribe:bidask:', '');
1684
+ if (symbol in this.bidsasks) {
1685
+ delete this.bidsasks[symbol];
1686
+ }
1687
+ }
1688
+ else if (messageHash.indexOf('candles') >= 0) {
1689
+ const splitHashes = messageHash.split(':');
1690
+ let symbol = this.safeString(splitHashes, 2);
1691
+ if (splitHashes.length > 4) {
1692
+ symbol += ':' + this.safeString(splitHashes, 3);
1693
+ }
1694
+ if (symbol in this.ohlcvs) {
1695
+ delete this.ohlcvs[symbol];
1696
+ }
1697
+ }
1698
+ else if (messageHash.indexOf('orderbook') >= 0) {
1699
+ const symbol = messageHash.replace('unsubscribe:orderbook:', '');
1700
+ if (symbol in this.orderbooks) {
1701
+ delete this.orderbooks[symbol];
1702
+ }
1703
+ }
1704
+ else if (messageHash.indexOf('trades') >= 0) {
1705
+ const symbol = messageHash.replace('unsubscribe:trades:', '');
1706
+ if (symbol in this.trades) {
1707
+ delete this.trades[symbol];
1708
+ }
1709
+ }
1710
+ }
1711
+ }
1415
1712
  async authenticate(subscriptionHash, params = {}) {
1416
1713
  // we only need one listenKey since ccxt shares connections
1417
1714
  let listenKey = this.safeString(this.options, 'listenKey');
@@ -249,7 +249,9 @@ class poloniex extends poloniex$1 {
249
249
  request['price'] = this.priceToPrecision(symbol, price);
250
250
  }
251
251
  }
252
- return await this.tradeRequest('createOrder', this.extend(request, params));
252
+ const orders = await this.tradeRequest('createOrder', this.extend(request, params));
253
+ const order = this.safeDict(orders, 0);
254
+ return order;
253
255
  }
254
256
  /**
255
257
  * @method
@@ -268,7 +270,9 @@ class poloniex extends poloniex$1 {
268
270
  const clientOrderIds = this.safeValue(params, 'clientOrderId', []);
269
271
  params['clientOrderIds'] = this.arrayConcat(clientOrderIds, [clientOrderId]);
270
272
  }
271
- return await this.cancelOrdersWs([id], symbol, params);
273
+ const orders = await this.cancelOrdersWs([id], symbol, params);
274
+ const order = this.safeDict(orders, 0);
275
+ return order;
272
276
  }
273
277
  /**
274
278
  * @method
@@ -15,6 +15,21 @@ const { ExchangeError , NetworkError} = ccxt
15
15
  function jsonStringify (obj, indent = undefined) {
16
16
  return JSON.stringify (obj, function(k, v) { return v === undefined ? null : v; }, indent);
17
17
  }
18
+
19
+
20
+ function countAllParams(fn) {
21
+ const fnStr = fn.toString()
22
+ .replace(/\/\/.*$/mg, '')
23
+ .replace(/\/\*[\s\S]*?\*\//mg, '')
24
+ .replace(/\s+/g, '');
25
+
26
+ const match = fnStr.match(/^[^(]*\(([^)]*)\)/);
27
+ if (!match) return 0;
28
+
29
+ const params = match[1].split(',').filter(p => p);
30
+ return params.length;
31
+ }
32
+
18
33
  //-----------------------------------------------------------------------------
19
34
 
20
35
  let [processPath, , exchangeId, methodName, ... params] = process.argv.filter (x => !x.startsWith ('--'))
@@ -45,19 +60,63 @@ let [processPath, , exchangeId, methodName, ... params] = process.argv.filter (x
45
60
  , noKeys = process.argv.includes ('--no-keys')
46
61
 
47
62
  let foundDescription = undefined;
63
+ const nameIndex = process.argv.indexOf ('--name')
64
+ if (nameIndex >= 0) {
65
+ foundDescription = process.argv[nameIndex + 1];
66
+ // search that string in `params` and remove it
67
+ const index = params.indexOf (foundDescription)
68
+ if (index >= 0) {
69
+ params.splice (index, 1);
70
+ }
71
+ }
72
+
73
+ let lastParamObject
74
+ let symbol
48
75
  for (let i = 0; i < process.argv.length; i++) {
49
- if (process.argv[i] === '--name') {
50
- foundDescription = process.argv[i + 1];
51
- // search that string in `params` and remove it
52
- for (let j = 0; j < params.length; j++) {
53
- if (params[j] === foundDescription) {
54
- params.splice(j, 1);
55
- break;
76
+ if (process.argv[i] === '--param') {
77
+ const nextParam = process.argv[i + 1]
78
+ if (nextParam) {
79
+ const paramIndex = params.indexOf (nextParam)
80
+ if (paramIndex >= 0) {
81
+ if (nextParam.indexOf('=') >= 0) {
82
+ const parsed = nextParam.split('=')
83
+ if (parsed.length === 2) {
84
+ if (!lastParamObject) {
85
+ lastParamObject = {}
86
+ }
87
+ const key = parsed[0];
88
+ const value = parsed[1];
89
+ if (key === 'symbol') {
90
+ symbol = value
91
+ }
92
+ lastParamObject[key] = value
93
+ params.splice(paramIndex, 1)
94
+ } else {
95
+ throw new Error ('Invalid usage of --param. Please provide a key=value pair after --param.')
96
+ }
97
+ } else {
98
+ if (!lastParamObject) {
99
+ lastParamObject = {}
100
+ }
101
+ lastParamObject[nextParam] = true
102
+ }
103
+ } else {
104
+ throw new Error (`Unexpected error by parsing parameters: ${nextParam} is not found in params array.`)
56
105
  }
106
+ } else {
107
+ throw new Error ('Invalid usage of --param. Please provide a value after --param.')
57
108
  }
58
- break;
59
109
  }
60
110
  }
111
+
112
+ let lastParam = params[params.length - 1]
113
+ // exclude parasitic single quotes. Can happen on some shell processors
114
+ if (lastParam?.includes('{') && lastParam?.includes('}')) {
115
+ if (lastParam.startsWith('\'{') && lastParam.endsWith('}\'')) {
116
+ lastParam = params[params.length - 1] = lastParam.substring(1, lastParam.length - 1)
117
+ }
118
+ }
119
+
61
120
  //-----------------------------------------------------------------------------
62
121
  if (!raw) {
63
122
  log ((new Date ()).toISOString())
@@ -213,6 +272,7 @@ function printUsage () {
213
272
  log ('node', process.argv[1], 'okcoin fetchOHLCV BTC/USD 15m')
214
273
  log ('node', process.argv[1], 'bitfinex fetchBalance')
215
274
  log ('node', process.argv[1], 'kraken fetchOrderBook ETH/BTC')
275
+ log ('node', process.argv[1], 'binanceusdm fetchTrades BTC/USDC undefined undefined --param until=1746988377067')
216
276
  printSupportedExchanges ()
217
277
  log ('Supported options:')
218
278
  log ('--verbose Print verbose output')
@@ -224,6 +284,8 @@ function printUsage () {
224
284
  log ('--no-table Do not print the fetch response as a table')
225
285
  log ('--table Print the fetch response as a table')
226
286
  log ('--iso8601 Print timestamps as ISO8601 datetimes')
287
+ log ('--param key=value Set a custom key=value pair for the last method\'s argument. Can be repeated multiple times')
288
+ log (' NOTE: don\'t forget to fill up missed arguments with "undefined" before last options parameter')
227
289
  log ('--cors use CORS proxy for debugging')
228
290
  log ('--sign-in Call signIn() if any')
229
291
  log ('--sandbox Use the exchange sandbox if available, same as --testnet')
@@ -306,10 +368,16 @@ async function run () {
306
368
 
307
369
  let args = params
308
370
  .map (s => s.match (/^[0-9]{4}[-][0-9]{2}[-][0-9]{2}[T\s]?[0-9]{2}[:][0-9]{2}[:][0-9]{2}/g) ? exchange.parse8601 (s) : s)
309
- .map (s => (() => {
310
- if (s.match ( /^\d+$/g)) return s < Number.MAX_SAFE_INTEGER ? Number (s) : s
311
- try {return eval ('(() => (' + s + ')) ()') } catch (e) { return s }
312
- }) ())
371
+ .map (s => {
372
+ return (() => {
373
+ if (s.match(/^\d+$/g)) return s < Number.MAX_SAFE_INTEGER ? Number(s) : s
374
+ try {
375
+ return eval('(() => (' + s + ')) ()')
376
+ } catch (e) {
377
+ return s
378
+ }
379
+ })();
380
+ })
313
381
 
314
382
  const www = Array.isArray (exchange.urls.www) ? exchange.urls.www[0] : exchange.urls.www
315
383
 
@@ -337,6 +405,34 @@ async function run () {
337
405
  }
338
406
  }
339
407
  }
408
+ if (symbol && lastParamObject) {
409
+ let marketId
410
+ try {
411
+ marketId = exchange.marketId(symbol)
412
+ } catch (e) {
413
+ // noop possible loaded from cache
414
+ }
415
+ if (!marketId) {
416
+ try {
417
+ await exchange.loadMarkets();
418
+ marketId = exchange.marketId(symbol)
419
+ } catch (e) {
420
+ // noop
421
+ }
422
+ }
423
+ if (marketId) {
424
+ lastParamObject.symbol = marketId
425
+ }
426
+ }
427
+
428
+ if (typeof lastParamObject === 'object') {
429
+ const lastArgument = args[args.length - 1];
430
+ if (lastParam && typeof lastArgument === 'object') {
431
+ args[args.length - 1] = Object.assign (lastArgument, lastParamObject)
432
+ } else {
433
+ args.push (lastParamObject)
434
+ }
435
+ }
340
436
 
341
437
  if (signIn && exchange.has.signIn) {
342
438
  await exchange.signIn ()
@@ -363,7 +459,10 @@ async function run () {
363
459
 
364
460
  if (typeof exchange[methodName] === 'function') {
365
461
 
366
- if (!raw) log (exchange.id + '.' + methodName, '(' + args.join (', ') + ')')
462
+ if (!raw || details) {
463
+ const methodArgsPrint = JSON.stringify(args);
464
+ log(exchange.id + '.' + methodName, '(' + methodArgsPrint.substring(1, methodArgsPrint.length - 1) + ')')
465
+ }
367
466
 
368
467
  let start = exchange.milliseconds ()
369
468
  let end = exchange.milliseconds ()
@@ -377,6 +476,21 @@ async function run () {
377
476
 
378
477
  while (true) {
379
478
  try {
479
+ const fn = exchange[methodName]
480
+ const fnParams = countAllParams(fn)
481
+ const argsContainsParams = args.find( arg=> arg && typeof arg === 'object' && !Array.isArray(arg) && Object.keys(arg).length > 0)
482
+ if (argsContainsParams && fnParams !== args.length) {
483
+ // populate the missing params with undefined
484
+ const missingParams = fnParams - args.length
485
+ const paramsObj = args[args.length - 1]
486
+ args.pop()
487
+ const newArgsArray = args;
488
+ for (let i = 0; i < missingParams; i++) {
489
+ newArgsArray.push(undefined)
490
+ }
491
+ newArgsArray.push(paramsObj)
492
+ args = newArgsArray
493
+ }
380
494
  const result = await exchange[methodName] (... args)
381
495
  end = exchange.milliseconds ()
382
496
  if (!isWsMethod && !raw) {