ccxt 4.1.39 → 4.1.41

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.
package/dist/cjs/ccxt.js CHANGED
@@ -180,7 +180,7 @@ var woo$1 = require('./src/pro/woo.js');
180
180
 
181
181
  //-----------------------------------------------------------------------------
182
182
  // this is updated by vss.js when building
183
- const version = '4.1.39';
183
+ const version = '4.1.41';
184
184
  Exchange["default"].ccxtVersion = version;
185
185
  const exchanges = {
186
186
  'ace': ace,
@@ -1450,6 +1450,17 @@ class Exchange {
1450
1450
  const convertedNumber = parseFloat(stringifiedNumber);
1451
1451
  return parseInt(convertedNumber);
1452
1452
  }
1453
+ parseToNumeric(number) {
1454
+ const stringVersion = this.numberToString(number); // this will convert 1.0 and 1 to "1" and 1.1 to "1.1"
1455
+ // keep this in mind:
1456
+ // in JS: 1 == 1.0 is true
1457
+ // in Python: 1 == 1.0 is true
1458
+ // in PHP 1 == 1.0 is false
1459
+ if (stringVersion.indexOf('.') > 0) {
1460
+ return parseFloat(stringVersion);
1461
+ }
1462
+ return parseInt(stringVersion);
1463
+ }
1453
1464
  afterConstruct() {
1454
1465
  this.createNetworksByIdObject();
1455
1466
  }
@@ -4431,7 +4442,13 @@ class Exchange {
4431
4442
  }
4432
4443
  params[cursorSent] = cursorValue;
4433
4444
  }
4434
- const response = await this[method](symbol, since, maxEntriesPerRequest, params);
4445
+ let response = undefined;
4446
+ if (method === 'fetchAccounts') {
4447
+ response = await this[method](params);
4448
+ }
4449
+ else {
4450
+ response = await this[method](symbol, since, maxEntriesPerRequest, params);
4451
+ }
4435
4452
  errors = 0;
4436
4453
  const responseLength = response.length;
4437
4454
  if (this.verbose) {
@@ -30,6 +30,7 @@ class bingx extends bingx$1 {
30
30
  'cancelOrder': true,
31
31
  'cancelOrders': true,
32
32
  'createOrder': true,
33
+ 'createOrders': true,
33
34
  'fetchBalance': true,
34
35
  'fetchClosedOrders': true,
35
36
  'fetchCurrencies': true,
@@ -1588,31 +1589,22 @@ class bingx extends bingx$1 {
1588
1589
  'takeProfitPrice': undefined,
1589
1590
  });
1590
1591
  }
1591
- async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1592
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
1592
1593
  /**
1593
1594
  * @method
1594
- * @name bingx#createOrder
1595
- * @description create a trade order
1596
- * @see https://bingx-api.github.io/docs/#/spot/trade-api.html#Create%20an%20Order
1597
- * @see https://bingx-api.github.io/docs/#/swapV2/trade-api.html#Trade%20order
1595
+ * @ignore
1596
+ * @name bingx#createOrderRequest
1597
+ * @description helper function to build request
1598
1598
  * @param {string} symbol unified symbol of the market to create an order in
1599
1599
  * @param {string} type 'market' or 'limit'
1600
1600
  * @param {string} side 'buy' or 'sell'
1601
- * @param {float} amount how much of currency you want to trade in units of base currency
1601
+ * @param {float} amount how much you want to trade in units of the base currency
1602
1602
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1603
1603
  * @param {object} [params] extra parameters specific to the bingx api endpoint
1604
- * @param {bool} [params.postOnly] true to place a post only order
1605
- * @param {string} [params.timeInForce] spot supports 'PO' and 'IOC', swap supports 'PO', 'GTC', 'IOC' and 'FOK'
1606
- * @param {bool} [params.reduceOnly] *swap only* true or false whether the order is reduce only
1607
- * @param {float} [params.triggerPrice] *swap only* triggerPrice at which the attached take profit / stop loss order will be triggered
1608
- * @param {float} [params.stopLossPrice] *swap only* stop loss trigger price
1609
- * @param {float} [params.takeProfitPrice] *swap only* take profit trigger price
1610
- * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1604
+ * @returns {object} request to be sent to the exchange
1611
1605
  */
1612
- await this.loadMarkets();
1613
1606
  const market = this.market(symbol);
1614
1607
  let postOnly = undefined;
1615
- let response = undefined;
1616
1608
  let marketType = undefined;
1617
1609
  [marketType, params] = this.handleMarketTypeAndParams('createOrder', market, params);
1618
1610
  type = type.toUpperCase();
@@ -1642,20 +1634,19 @@ class bingx extends bingx$1 {
1642
1634
  const amountString = this.numberToString(amount);
1643
1635
  const priceString = this.numberToString(price);
1644
1636
  const cost = this.parseNumber(Precise["default"].stringMul(amountString, priceString));
1645
- request['quoteOrderQty'] = this.priceToPrecision(symbol, cost);
1637
+ request['quoteOrderQty'] = this.parseToNumeric(this.priceToPrecision(symbol, cost));
1646
1638
  }
1647
1639
  }
1648
1640
  else {
1649
- request['quoteOrderQty'] = this.priceToPrecision(symbol, amount);
1641
+ request['quoteOrderQty'] = this.parseToNumeric(this.priceToPrecision(symbol, amount));
1650
1642
  }
1651
1643
  }
1652
1644
  else {
1653
- request['quantity'] = this.amountToPrecision(symbol, amount);
1645
+ request['quantity'] = this.parseToNumeric(this.amountToPrecision(symbol, amount));
1654
1646
  }
1655
1647
  if (!isMarketOrder) {
1656
- request['price'] = this.priceToPrecision(symbol, price);
1648
+ request['price'] = this.parseToNumeric(this.priceToPrecision(symbol, price));
1657
1649
  }
1658
- response = await this.spotV1PrivatePostTradeOrder(this.extend(request, params));
1659
1650
  }
1660
1651
  else {
1661
1652
  [postOnly, params] = this.handlePostOnly(isMarketOrder, timeInForce === 'PostOnly', params);
@@ -1669,7 +1660,7 @@ class bingx extends bingx$1 {
1669
1660
  request['timeInForce'] = 'FOK';
1670
1661
  }
1671
1662
  if ((type === 'LIMIT') || (type === 'TRIGGER_LIMIT') || (type === 'STOP') || (type === 'TAKE_PROFIT')) {
1672
- request['price'] = this.priceToPrecision(symbol, price);
1663
+ request['price'] = this.parseToNumeric(this.priceToPrecision(symbol, price));
1673
1664
  }
1674
1665
  const triggerPrice = this.safeNumber2(params, 'stopPrice', 'triggerPrice');
1675
1666
  const stopLossPrice = this.safeNumber(params, 'stopLossPrice');
@@ -1677,8 +1668,9 @@ class bingx extends bingx$1 {
1677
1668
  const isTriggerOrder = triggerPrice !== undefined;
1678
1669
  const isStopLossPriceOrder = stopLossPrice !== undefined;
1679
1670
  const isTakeProfitPriceOrder = takeProfitPrice !== undefined;
1671
+ let reduceOnly = this.safeValue(params, 'reduceOnly', false);
1680
1672
  if (isTriggerOrder) {
1681
- request['stopPrice'] = this.priceToPrecision(symbol, triggerPrice);
1673
+ request['stopPrice'] = this.parseToNumeric(this.priceToPrecision(symbol, triggerPrice));
1682
1674
  if (isMarketOrder || (type === 'TRIGGER_MARKET')) {
1683
1675
  request['type'] = 'TRIGGER_MARKET';
1684
1676
  }
@@ -1688,8 +1680,9 @@ class bingx extends bingx$1 {
1688
1680
  }
1689
1681
  else if (isStopLossPriceOrder || isTakeProfitPriceOrder) {
1690
1682
  // This can be used to set the stop loss and take profit, but the position needs to be opened first
1683
+ reduceOnly = true;
1691
1684
  if (isStopLossPriceOrder) {
1692
- request['stopPrice'] = this.priceToPrecision(symbol, stopLossPrice);
1685
+ request['stopPrice'] = this.parseToNumeric(this.priceToPrecision(symbol, stopLossPrice));
1693
1686
  if (isMarketOrder || (type === 'STOP_MARKET')) {
1694
1687
  request['type'] = 'STOP_MARKET';
1695
1688
  }
@@ -1698,7 +1691,7 @@ class bingx extends bingx$1 {
1698
1691
  }
1699
1692
  }
1700
1693
  else if (isTakeProfitPriceOrder) {
1701
- request['stopPrice'] = this.priceToPrecision(symbol, takeProfitPrice);
1694
+ request['stopPrice'] = this.parseToNumeric(this.priceToPrecision(symbol, takeProfitPrice));
1702
1695
  if (isMarketOrder || (type === 'TAKE_PROFIT_MARKET')) {
1703
1696
  request['type'] = 'TAKE_PROFIT_MARKET';
1704
1697
  }
@@ -1707,7 +1700,6 @@ class bingx extends bingx$1 {
1707
1700
  }
1708
1701
  }
1709
1702
  }
1710
- const reduceOnly = this.safeValue(params, 'reduceOnly', false);
1711
1703
  let positionSide = undefined;
1712
1704
  if (reduceOnly) {
1713
1705
  positionSide = (side === 'buy') ? 'SHORT' : 'LONG';
@@ -1716,9 +1708,41 @@ class bingx extends bingx$1 {
1716
1708
  positionSide = (side === 'buy') ? 'LONG' : 'SHORT';
1717
1709
  }
1718
1710
  request['positionSide'] = positionSide;
1719
- request['quantity'] = this.amountToPrecision(symbol, amount);
1711
+ request['quantity'] = this.parseToNumeric(this.amountToPrecision(symbol, amount));
1720
1712
  params = this.omit(params, ['reduceOnly', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice']);
1721
- response = await this.swapV2PrivatePostTradeOrder(this.extend(request, params));
1713
+ }
1714
+ return this.extend(request, params);
1715
+ }
1716
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1717
+ /**
1718
+ * @method
1719
+ * @name bingx#createOrder
1720
+ * @description create a trade order
1721
+ * @see https://bingx-api.github.io/docs/#/spot/trade-api.html#Create%20an%20Order
1722
+ * @see https://bingx-api.github.io/docs/#/swapV2/trade-api.html#Trade%20order
1723
+ * @param {string} symbol unified symbol of the market to create an order in
1724
+ * @param {string} type 'market' or 'limit'
1725
+ * @param {string} side 'buy' or 'sell'
1726
+ * @param {float} amount how much you want to trade in units of the base currency
1727
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1728
+ * @param {object} [params] extra parameters specific to the bingx api endpoint
1729
+ * @param {bool} [params.postOnly] true to place a post only order
1730
+ * @param {string} [params.timeInForce] spot supports 'PO' and 'IOC', swap supports 'PO', 'GTC', 'IOC' and 'FOK'
1731
+ * @param {bool} [params.reduceOnly] *swap only* true or false whether the order is reduce only
1732
+ * @param {float} [params.triggerPrice] *swap only* triggerPrice at which the attached take profit / stop loss order will be triggered
1733
+ * @param {float} [params.stopLossPrice] *swap only* stop loss trigger price
1734
+ * @param {float} [params.takeProfitPrice] *swap only* take profit trigger price
1735
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1736
+ */
1737
+ await this.loadMarkets();
1738
+ const market = this.market(symbol);
1739
+ const request = this.createOrderRequest(symbol, type, side, amount, price, params);
1740
+ let response = undefined;
1741
+ if (market['swap']) {
1742
+ response = await this.swapV2PrivatePostTradeOrder(request);
1743
+ }
1744
+ else {
1745
+ response = await this.spotV1PrivatePostTradeOrder(request);
1722
1746
  }
1723
1747
  //
1724
1748
  // spot
@@ -1762,6 +1786,99 @@ class bingx extends bingx$1 {
1762
1786
  const order = this.safeValue(data, 'order', data);
1763
1787
  return this.parseOrder(order, market);
1764
1788
  }
1789
+ async createOrders(orders, params = {}) {
1790
+ /**
1791
+ * @method
1792
+ * @name bingx#createOrders
1793
+ * @description create a list of trade orders
1794
+ * @see https://bingx-api.github.io/docs/#/spot/trade-api.html#Batch%20Placing%20Orders
1795
+ * @see https://bingx-api.github.io/docs/#/swapV2/trade-api.html#Bulk%20order
1796
+ * @param {array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
1797
+ * @param {object} [params] extra parameters specific to the bingx api endpoint
1798
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1799
+ */
1800
+ await this.loadMarkets();
1801
+ const ordersRequests = [];
1802
+ let symbol = undefined;
1803
+ for (let i = 0; i < orders.length; i++) {
1804
+ const rawOrder = orders[i];
1805
+ const marketId = this.safeString(rawOrder, 'symbol');
1806
+ if (symbol === undefined) {
1807
+ symbol = marketId;
1808
+ }
1809
+ else {
1810
+ if (symbol !== marketId) {
1811
+ throw new errors.BadRequest(this.id + ' createOrders() requires all orders to have the same symbol');
1812
+ }
1813
+ }
1814
+ const type = this.safeString(rawOrder, 'type');
1815
+ const side = this.safeString(rawOrder, 'side');
1816
+ const amount = this.safeNumber(rawOrder, 'amount');
1817
+ const price = this.safeNumber(rawOrder, 'price');
1818
+ const orderParams = this.safeValue(rawOrder, 'params', {});
1819
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
1820
+ ordersRequests.push(orderRequest);
1821
+ }
1822
+ const market = this.market(symbol);
1823
+ const request = {};
1824
+ let response = undefined;
1825
+ if (market['swap']) {
1826
+ request['batchOrders'] = this.json(ordersRequests);
1827
+ response = await this.swapV2PrivatePostTradeBatchOrders(request);
1828
+ }
1829
+ else {
1830
+ request['data'] = this.json(ordersRequests);
1831
+ response = await this.spotV1PrivatePostTradeBatchOrders(request);
1832
+ }
1833
+ //
1834
+ // spot
1835
+ //
1836
+ // {
1837
+ // "code": 0,
1838
+ // "msg": "",
1839
+ // "debugMsg": "",
1840
+ // "data": {
1841
+ // "orders": [
1842
+ // {
1843
+ // "symbol": "BTC-USDT",
1844
+ // "orderId": 1720661389564968960,
1845
+ // "transactTime": 1699072618272,
1846
+ // "price": "25000",
1847
+ // "origQty": "0.0002",
1848
+ // "executedQty": "0",
1849
+ // "cummulativeQuoteQty": "0",
1850
+ // "status": "PENDING",
1851
+ // "type": "LIMIT",
1852
+ // "side": "BUY"
1853
+ // },
1854
+ // ]
1855
+ // }
1856
+ // }
1857
+ //
1858
+ // swap
1859
+ //
1860
+ // {
1861
+ // "code": 0,
1862
+ // "msg": "",
1863
+ // "data": {
1864
+ // "orders": [
1865
+ // {
1866
+ // "symbol": "BTC-USDT",
1867
+ // "orderId": 1720657081994006528,
1868
+ // "side": "BUY",
1869
+ // "positionSide": "LONG",
1870
+ // "type": "LIMIT",
1871
+ // "clientOrderID": "",
1872
+ // "workingType": ""
1873
+ // },
1874
+ // ]
1875
+ // }
1876
+ // }
1877
+ //
1878
+ const data = this.safeValue(response, 'data', {});
1879
+ const result = this.safeValue(data, 'orders', []);
1880
+ return this.parseOrders(result, market);
1881
+ }
1765
1882
  parseOrderSide(side) {
1766
1883
  const sides = {
1767
1884
  'BUY': 'buy',
@@ -1774,7 +1891,7 @@ class bingx extends bingx$1 {
1774
1891
  parseOrder(order, market = undefined) {
1775
1892
  //
1776
1893
  // spot
1777
- // createOrder, cancelOrder
1894
+ // createOrder, createOrders, cancelOrder
1778
1895
  //
1779
1896
  // {
1780
1897
  // "symbol": "XRP-USDT",
@@ -1827,7 +1944,7 @@ class bingx extends bingx$1 {
1827
1944
  //
1828
1945
  //
1829
1946
  // swap
1830
- // createOrder
1947
+ // createOrder, createOrders
1831
1948
  //
1832
1949
  // {
1833
1950
  // "symbol": "BTC-USDT",
@@ -508,6 +508,7 @@ class bittrex extends bittrex$1 {
508
508
  'max': undefined,
509
509
  },
510
510
  },
511
+ 'networks': {},
511
512
  };
512
513
  }
513
514
  return result;
@@ -319,6 +319,7 @@ class coinbase extends coinbase$1 {
319
319
  * @name coinbase#fetchAccounts
320
320
  * @description fetch all the accounts associated with a profile
321
321
  * @param {object} [params] extra parameters specific to the coinbase api endpoint
322
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
322
323
  * @returns {object} a dictionary of [account structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#account-structure} indexed by the account type
323
324
  */
324
325
  const method = this.safeString(this.options, 'fetchAccounts', 'fetchAccountsV3');
@@ -329,6 +330,11 @@ class coinbase extends coinbase$1 {
329
330
  }
330
331
  async fetchAccountsV2(params = {}) {
331
332
  await this.loadMarkets();
333
+ let paginate = false;
334
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchAccounts', 'paginate');
335
+ if (paginate) {
336
+ return await this.fetchPaginatedCallCursor('fetchAccounts', undefined, undefined, undefined, params, 'next_starting_after', 'starting_after', undefined, 100);
337
+ }
332
338
  const request = {
333
339
  'limit': 100,
334
340
  };
@@ -378,10 +384,24 @@ class coinbase extends coinbase$1 {
378
384
  // }
379
385
  //
380
386
  const data = this.safeValue(response, 'data', []);
387
+ const pagination = this.safeValue(response, 'pagination', {});
388
+ const cursor = this.safeString(pagination, 'next_starting_after');
389
+ const accounts = this.safeValue(response, 'data', []);
390
+ const lastIndex = accounts.length - 1;
391
+ const last = this.safeValue(accounts, lastIndex);
392
+ if ((cursor !== undefined) && (cursor !== '')) {
393
+ last['next_starting_after'] = cursor;
394
+ accounts[lastIndex] = last;
395
+ }
381
396
  return this.parseAccounts(data, params);
382
397
  }
383
398
  async fetchAccountsV3(params = {}) {
384
399
  await this.loadMarkets();
400
+ let paginate = false;
401
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchAccounts', 'paginate');
402
+ if (paginate) {
403
+ return await this.fetchPaginatedCallCursor('fetchAccounts', undefined, undefined, undefined, params, 'cursor', 'cursor', undefined, 100);
404
+ }
385
405
  const request = {
386
406
  'limit': 100,
387
407
  };
@@ -416,8 +436,15 @@ class coinbase extends coinbase$1 {
416
436
  // "size": 9
417
437
  // }
418
438
  //
419
- const data = this.safeValue(response, 'accounts', []);
420
- return this.parseAccounts(data, params);
439
+ const accounts = this.safeValue(response, 'accounts', []);
440
+ const lastIndex = accounts.length - 1;
441
+ const last = this.safeValue(accounts, lastIndex);
442
+ const cursor = this.safeString(response, 'cursor');
443
+ if ((cursor !== undefined) && (cursor !== '')) {
444
+ last['cursor'] = cursor;
445
+ accounts[lastIndex] = last;
446
+ }
447
+ return this.parseAccounts(accounts, params);
421
448
  }
422
449
  parseAccount(account) {
423
450
  //
@@ -567,9 +567,12 @@ class okx extends okx$1 {
567
567
  '51028': errors.ContractUnavailable,
568
568
  '51029': errors.ContractUnavailable,
569
569
  '51030': errors.ContractUnavailable,
570
+ '51031': errors.InvalidOrder,
570
571
  '51046': errors.InvalidOrder,
571
572
  '51047': errors.InvalidOrder,
572
- '51031': errors.InvalidOrder,
573
+ '51072': errors.InvalidOrder,
574
+ '51073': errors.InvalidOrder,
575
+ '51074': errors.InvalidOrder,
573
576
  '51100': errors.InvalidOrder,
574
577
  '51101': errors.InvalidOrder,
575
578
  '51102': errors.InvalidOrder,
@@ -614,6 +617,7 @@ class okx extends okx$1 {
614
617
  '51163': errors.InvalidOrder,
615
618
  '51166': errors.InvalidOrder,
616
619
  '51174': errors.InvalidOrder,
620
+ '51185': errors.InvalidOrder,
617
621
  '51201': errors.InvalidOrder,
618
622
  '51202': errors.InvalidOrder,
619
623
  '51203': errors.InvalidOrder,
@@ -761,6 +765,8 @@ class okx extends okx$1 {
761
765
  '59200': errors.InsufficientFunds,
762
766
  '59201': errors.InsufficientFunds,
763
767
  '59216': errors.BadRequest,
768
+ '59260': errors.PermissionDenied,
769
+ '59262': errors.PermissionDenied,
764
770
  '59300': errors.ExchangeError,
765
771
  '59301': errors.ExchangeError,
766
772
  '59313': errors.ExchangeError,
@@ -774,6 +780,8 @@ class okx extends okx$1 {
774
780
  '59506': errors.ExchangeError,
775
781
  '59507': errors.ExchangeError,
776
782
  '59508': errors.AccountSuspended,
783
+ '59642': errors.BadRequest,
784
+ '59643': errors.ExchangeError,
777
785
  // WebSocket error Codes from 60000-63999
778
786
  '60001': errors.AuthenticationError,
779
787
  '60002': errors.AuthenticationError,
@@ -1234,10 +1234,11 @@ class binance extends binance$1 {
1234
1234
  }
1235
1235
  async authenticate(params = {}) {
1236
1236
  const time = this.milliseconds();
1237
- let type = this.safeString2(this.options, 'defaultType', 'authenticate', 'spot');
1238
- type = this.safeString(params, 'type', type);
1237
+ let query = undefined;
1238
+ let type = undefined;
1239
+ [type, query] = this.handleMarketTypeAndParams('authenticate', undefined, params);
1239
1240
  let subType = undefined;
1240
- [subType, params] = this.handleSubTypeAndParams('authenticate', undefined, params);
1241
+ [subType, query] = this.handleSubTypeAndParams('authenticate', undefined, query);
1241
1242
  if (this.isLinear(type, subType)) {
1242
1243
  type = 'future';
1243
1244
  }
@@ -1245,11 +1246,11 @@ class binance extends binance$1 {
1245
1246
  type = 'delivery';
1246
1247
  }
1247
1248
  let marginMode = undefined;
1248
- [marginMode, params] = this.handleMarginModeAndParams('authenticate', params);
1249
+ [marginMode, query] = this.handleMarginModeAndParams('authenticate', query);
1249
1250
  const isIsolatedMargin = (marginMode === 'isolated');
1250
1251
  const isCrossMargin = (marginMode === 'cross') || (marginMode === undefined);
1251
- const symbol = this.safeString(params, 'symbol');
1252
- params = this.omit(params, 'symbol');
1252
+ const symbol = this.safeString(query, 'symbol');
1253
+ query = this.omit(query, 'symbol');
1253
1254
  const options = this.safeValue(this.options, type, {});
1254
1255
  const lastAuthenticatedTime = this.safeInteger(options, 'lastAuthenticatedTime', 0);
1255
1256
  const listenKeyRefreshRate = this.safeInteger(this.options, 'listenKeyRefreshRate', 1200000);
@@ -1271,9 +1272,9 @@ class binance extends binance$1 {
1271
1272
  throw new errors.ArgumentsRequired(this.id + ' authenticate() requires a symbol argument for isolated margin mode');
1272
1273
  }
1273
1274
  const marketId = this.marketId(symbol);
1274
- params = this.extend(params, { 'symbol': marketId });
1275
+ query = this.extend(query, { 'symbol': marketId });
1275
1276
  }
1276
- const response = await this[method](params);
1277
+ const response = await this[method](query);
1277
1278
  this.options[type] = this.extend(options, {
1278
1279
  'listenKey': this.safeString(response, 'listenKey'),
1279
1280
  'lastAuthenticatedTime': time,
@@ -1285,8 +1286,8 @@ class binance extends binance$1 {
1285
1286
  // https://binance-docs.github.io/apidocs/spot/en/#listen-key-spot
1286
1287
  let type = this.safeString2(this.options, 'defaultType', 'authenticate', 'spot');
1287
1288
  type = this.safeString(params, 'type', type);
1288
- let subType = undefined;
1289
- [subType, params] = this.handleSubTypeAndParams('keepAliveListenKey', undefined, params);
1289
+ const subTypeInfo = this.handleSubTypeAndParams('keepAliveListenKey', undefined, params);
1290
+ const subType = subTypeInfo[0];
1290
1291
  if (this.isLinear(type, subType)) {
1291
1292
  type = 'future';
1292
1293
  }
@@ -2063,7 +2064,7 @@ class binance extends binance$1 {
2063
2064
  market = this.market(symbol);
2064
2065
  symbol = market['symbol'];
2065
2066
  messageHash += ':' + symbol;
2066
- params = this.extend(params, { 'symbol': symbol }); // needed inside authenticate for isolated margin
2067
+ params = this.extend(params, { 'type': market['type'], 'symbol': symbol }); // needed inside authenticate for isolated margin
2067
2068
  }
2068
2069
  await this.authenticate(params);
2069
2070
  let type = undefined;
@@ -2076,7 +2077,11 @@ class binance extends binance$1 {
2076
2077
  else if (this.isInverse(type, subType)) {
2077
2078
  type = 'delivery';
2078
2079
  }
2079
- const url = this.urls['api']['ws'][type] + '/' + this.options[type]['listenKey'];
2080
+ let urlType = type;
2081
+ if (type === 'margin') {
2082
+ urlType = 'spot'; // spot-margin shares the same stream as regular spot
2083
+ }
2084
+ const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2080
2085
  const client = this.client(url);
2081
2086
  this.setBalanceCache(client, type);
2082
2087
  const message = undefined;
@@ -2416,10 +2421,15 @@ class binance extends binance$1 {
2416
2421
  * @returns {object[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#trade-structure
2417
2422
  */
2418
2423
  await this.loadMarkets();
2419
- const defaultType = this.safeString2(this.options, 'watchMyTrades', 'defaultType', 'spot');
2420
- let type = this.safeString(params, 'type', defaultType);
2424
+ let type = undefined;
2425
+ let market = undefined;
2426
+ if (symbol !== undefined) {
2427
+ market = this.market(symbol);
2428
+ symbol = market['symbol'];
2429
+ }
2430
+ [type, params] = this.handleMarketTypeAndParams('watchMyTrades', market, params);
2421
2431
  let subType = undefined;
2422
- [subType, params] = this.handleSubTypeAndParams('watchMyTrades', undefined, params);
2432
+ [subType, params] = this.handleSubTypeAndParams('watchMyTrades', market, params);
2423
2433
  if (this.isLinear(type, subType)) {
2424
2434
  type = 'future';
2425
2435
  }
@@ -2430,10 +2440,14 @@ class binance extends binance$1 {
2430
2440
  if (symbol !== undefined) {
2431
2441
  symbol = this.symbol(symbol);
2432
2442
  messageHash += ':' + symbol;
2433
- params = this.extend(params, { 'symbol': symbol });
2443
+ params = this.extend(params, { 'type': market['type'], 'symbol': symbol });
2434
2444
  }
2435
2445
  await this.authenticate(params);
2436
- const url = this.urls['api']['ws'][type] + '/' + this.options[type]['listenKey'];
2446
+ let urlType = type; // we don't change type because the listening key is different
2447
+ if (type === 'margin') {
2448
+ urlType = 'spot'; // spot-margin shares the same stream as regular spot
2449
+ }
2450
+ const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2437
2451
  const client = this.client(url);
2438
2452
  this.setBalanceCache(client, type);
2439
2453
  const message = undefined;
@@ -1405,13 +1405,13 @@ class huobi extends huobi$1 {
1405
1405
  // }
1406
1406
  //
1407
1407
  const channel = this.safeString(message, 'ch');
1408
- const timestamp = this.safeInteger(message, 'ts');
1408
+ const data = this.safeValue(message, 'data', []);
1409
+ const timestamp = this.safeInteger(data, 'changeTime', this.safeInteger(message, 'ts'));
1409
1410
  this.balance['timestamp'] = timestamp;
1410
1411
  this.balance['datetime'] = this.iso8601(timestamp);
1411
- this.balance['info'] = this.safeValue(message, 'data');
1412
+ this.balance['info'] = data;
1412
1413
  if (channel !== undefined) {
1413
1414
  // spot balance
1414
- const data = this.safeValue(message, 'data', {});
1415
1415
  const currencyId = this.safeString(data, 'currency');
1416
1416
  const code = this.safeCurrencyCode(currencyId);
1417
1417
  const account = this.account();
@@ -1423,7 +1423,6 @@ class huobi extends huobi$1 {
1423
1423
  }
1424
1424
  else {
1425
1425
  // contract balance
1426
- const data = this.safeValue(message, 'data', []);
1427
1426
  const dataLength = data.length;
1428
1427
  if (dataLength === 0) {
1429
1428
  return;
package/js/ccxt.d.ts CHANGED
@@ -4,7 +4,7 @@ import * as functions from './src/base/functions.js';
4
4
  import * as errors from './src/base/errors.js';
5
5
  import { Market, Trade, Fee, Ticker, OrderBook, Order, Transaction, Tickers, Currency, Balance, DepositAddress, WithdrawalResponse, DepositAddressResponse, OHLCV, Balances, PartialBalances, Dictionary, MinMax, Position, FundingRateHistory, Liquidation, FundingHistory } from './src/base/types.js';
6
6
  import { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, NoChange } from './src/base/errors.js';
7
- declare const version = "4.1.38";
7
+ declare const version = "4.1.40";
8
8
  import ace from './src/ace.js';
9
9
  import alpaca from './src/alpaca.js';
10
10
  import ascendex from './src/ascendex.js';
package/js/ccxt.js CHANGED
@@ -38,7 +38,7 @@ import * as errors from './src/base/errors.js';
38
38
  import { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, NoChange } from './src/base/errors.js';
39
39
  //-----------------------------------------------------------------------------
40
40
  // this is updated by vss.js when building
41
- const version = '4.1.39';
41
+ const version = '4.1.41';
42
42
  Exchange.ccxtVersion = version;
43
43
  //-----------------------------------------------------------------------------
44
44
  import ace from './src/ace.js';
@@ -576,6 +576,7 @@ export default class Exchange {
576
576
  createDepositAddress(code: string, params?: {}): Promise<DepositAddressResponse>;
577
577
  setLeverage(leverage: any, symbol?: string, params?: {}): Promise<any>;
578
578
  parseToInt(number: any): number;
579
+ parseToNumeric(number: any): number;
579
580
  afterConstruct(): void;
580
581
  createNetworksByIdObject(): void;
581
582
  getDefaultOptions(): {
@@ -1446,6 +1446,17 @@ export default class Exchange {
1446
1446
  const convertedNumber = parseFloat(stringifiedNumber);
1447
1447
  return parseInt(convertedNumber);
1448
1448
  }
1449
+ parseToNumeric(number) {
1450
+ const stringVersion = this.numberToString(number); // this will convert 1.0 and 1 to "1" and 1.1 to "1.1"
1451
+ // keep this in mind:
1452
+ // in JS: 1 == 1.0 is true
1453
+ // in Python: 1 == 1.0 is true
1454
+ // in PHP 1 == 1.0 is false
1455
+ if (stringVersion.indexOf('.') > 0) {
1456
+ return parseFloat(stringVersion);
1457
+ }
1458
+ return parseInt(stringVersion);
1459
+ }
1449
1460
  afterConstruct() {
1450
1461
  this.createNetworksByIdObject();
1451
1462
  }
@@ -4427,7 +4438,13 @@ export default class Exchange {
4427
4438
  }
4428
4439
  params[cursorSent] = cursorValue;
4429
4440
  }
4430
- const response = await this[method](symbol, since, maxEntriesPerRequest, params);
4441
+ let response = undefined;
4442
+ if (method === 'fetchAccounts') {
4443
+ response = await this[method](params);
4444
+ }
4445
+ else {
4446
+ response = await this[method](symbol, since, maxEntriesPerRequest, params);
4447
+ }
4431
4448
  errors = 0;
4432
4449
  const responseLength = response.length;
4433
4450
  if (this.verbose) {