ccxt 4.1.40 → 4.1.43

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
@@ -58,6 +58,7 @@ var coinbasepro = require('./src/coinbasepro.js');
58
58
  var coincheck = require('./src/coincheck.js');
59
59
  var coinex = require('./src/coinex.js');
60
60
  var coinfalcon = require('./src/coinfalcon.js');
61
+ var coinlist = require('./src/coinlist.js');
61
62
  var coinmate = require('./src/coinmate.js');
62
63
  var coinone = require('./src/coinone.js');
63
64
  var coinsph = require('./src/coinsph.js');
@@ -180,7 +181,7 @@ var woo$1 = require('./src/pro/woo.js');
180
181
 
181
182
  //-----------------------------------------------------------------------------
182
183
  // this is updated by vss.js when building
183
- const version = '4.1.40';
184
+ const version = '4.1.43';
184
185
  Exchange["default"].ccxtVersion = version;
185
186
  const exchanges = {
186
187
  'ace': ace,
@@ -229,6 +230,7 @@ const exchanges = {
229
230
  'coincheck': coincheck,
230
231
  'coinex': coinex,
231
232
  'coinfalcon': coinfalcon,
233
+ 'coinlist': coinlist,
232
234
  'coinmate': coinmate,
233
235
  'coinone': coinone,
234
236
  'coinsph': coinsph,
@@ -438,6 +440,7 @@ exports.coinbasepro = coinbasepro;
438
440
  exports.coincheck = coincheck;
439
441
  exports.coinex = coinex;
440
442
  exports.coinfalcon = coinfalcon;
443
+ exports.coinlist = coinlist;
441
444
  exports.coinmate = coinmate;
442
445
  exports.coinone = coinone;
443
446
  exports.coinsph = coinsph;
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ var Exchange$1 = require('../base/Exchange.js');
4
+
5
+ // -------------------------------------------------------------------------------
6
+ class Exchange extends Exchange$1["default"] {
7
+ }
8
+
9
+ module.exports = Exchange;
@@ -35,6 +35,7 @@ class ascendex extends ascendex$1 {
35
35
  'cancelAllOrders': true,
36
36
  'cancelOrder': true,
37
37
  'createOrder': true,
38
+ 'createOrders': true,
38
39
  'createPostOnlyOrder': true,
39
40
  'createReduceOnlyOrder': true,
40
41
  'createStopLimitOrder': true,
@@ -1460,30 +1461,33 @@ class ascendex extends ascendex$1 {
1460
1461
  }
1461
1462
  return result;
1462
1463
  }
1463
- async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1464
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
1464
1465
  /**
1465
1466
  * @method
1466
- * @name ascendex#createOrder
1467
- * @description Create an order on the exchange
1468
- * @param {string} symbol Unified CCXT market symbol
1469
- * @param {string} type "limit" or "market"
1470
- * @param {string} side "buy" or "sell"
1471
- * @param {float} amount the amount of currency to trade
1472
- * @param {float} [price] *ignored in "market" orders* the price at which the order is to be fullfilled at in units of the quote currency
1473
- * @param {object} [params] Extra parameters specific to the exchange API endpoint
1467
+ * @ignore
1468
+ * @name ascendex#createOrderRequest
1469
+ * @description helper function to build request
1470
+ * @param {string} symbol unified symbol of the market to create an order in
1471
+ * @param {string} type 'market' or 'limit'
1472
+ * @param {string} side 'buy' or 'sell'
1473
+ * @param {float} amount how much you want to trade in units of the base currency
1474
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1475
+ * @param {object} [params] extra parameters specific to the ascendex api endpoint
1474
1476
  * @param {string} [params.timeInForce] "GTC", "IOC", "FOK", or "PO"
1475
1477
  * @param {bool} [params.postOnly] true or false
1476
- * @param {float} [params.stopPrice] The price at which a trigger order is triggered at
1477
- * @returns [An order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1478
+ * @param {float} [params.stopPrice] the price at which a trigger order is triggered at
1479
+ * @returns {object} request to be sent to the exchange
1478
1480
  */
1479
- await this.loadMarkets();
1480
- await this.loadAccounts();
1481
1481
  const market = this.market(symbol);
1482
+ let marginMode = undefined;
1482
1483
  let marketType = undefined;
1483
- [marketType, params] = this.handleMarketTypeAndParams('createOrder', market, params);
1484
- const options = this.safeValue(this.options, 'createOrder', {});
1484
+ [marginMode, params] = this.handleMarginModeAndParams('createOrderRequest', params);
1485
+ [marketType, params] = this.handleMarketTypeAndParams('createOrderRequest', market, params);
1485
1486
  const accountsByType = this.safeValue(this.options, 'accountsByType', {});
1486
- const accountCategory = this.safeString(accountsByType, marketType, 'cash');
1487
+ let accountCategory = this.safeString(accountsByType, marketType, 'cash');
1488
+ if (marginMode !== undefined) {
1489
+ accountCategory = 'margin';
1490
+ }
1487
1491
  const account = this.safeValue(this.accounts, 0, {});
1488
1492
  const accountGroup = this.safeValue(account, 'id');
1489
1493
  const clientOrderId = this.safeString2(params, 'clientOrderId', 'id');
@@ -1504,13 +1508,6 @@ class ascendex extends ascendex$1 {
1504
1508
  const postOnly = this.isPostOnly(isMarketOrder, false, params);
1505
1509
  const reduceOnly = this.safeValue(params, 'reduceOnly', false);
1506
1510
  const stopPrice = this.safeValue2(params, 'triggerPrice', 'stopPrice');
1507
- params = this.omit(params, ['timeInForce', 'postOnly', 'reduceOnly', 'stopPrice', 'triggerPrice']);
1508
- if (reduceOnly) {
1509
- if (marketType !== 'swap') {
1510
- throw new errors.InvalidOrder(this.id + ' createOrder() does not support reduceOnly for ' + marketType + ' orders, reduceOnly orders are supported for perpetuals only');
1511
- }
1512
- request['execInst'] = 'ReduceOnly';
1513
- }
1514
1511
  if (isLimitOrder) {
1515
1512
  request['orderPrice'] = this.priceToPrecision(symbol, price);
1516
1513
  }
@@ -1535,21 +1532,56 @@ class ascendex extends ascendex$1 {
1535
1532
  if (clientOrderId !== undefined) {
1536
1533
  request['id'] = clientOrderId;
1537
1534
  }
1538
- const defaultMethod = this.safeString(options, 'method', 'v1PrivateAccountCategoryPostOrder');
1539
- const method = this.getSupportedMapping(marketType, {
1540
- 'spot': defaultMethod,
1541
- 'margin': defaultMethod,
1542
- 'swap': 'v2PrivateAccountGroupPostFuturesOrder',
1543
- });
1544
- if (method === 'v1PrivateAccountCategoryPostOrder') {
1535
+ if (market['spot']) {
1545
1536
  if (accountCategory !== undefined) {
1546
1537
  request['category'] = accountCategory;
1547
1538
  }
1548
1539
  }
1549
1540
  else {
1550
1541
  request['account-category'] = accountCategory;
1542
+ if (reduceOnly) {
1543
+ request['execInst'] = 'ReduceOnly';
1544
+ }
1545
+ if (postOnly) {
1546
+ request['execInst'] = 'Post';
1547
+ }
1548
+ }
1549
+ params = this.omit(params, ['reduceOnly', 'triggerPrice']);
1550
+ return this.extend(request, params);
1551
+ }
1552
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1553
+ /**
1554
+ * @method
1555
+ * @name ascendex#createOrder
1556
+ * @description create a trade order on the exchange
1557
+ * @see https://ascendex.github.io/ascendex-pro-api/#place-order
1558
+ * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#new-order
1559
+ * @param {string} symbol unified CCXT market symbol
1560
+ * @param {string} type "limit" or "market"
1561
+ * @param {string} side "buy" or "sell"
1562
+ * @param {float} amount the amount of currency to trade
1563
+ * @param {float} [price] *ignored in "market" orders* the price at which the order is to be fullfilled at in units of the quote currency
1564
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1565
+ * @param {string} [params.timeInForce] "GTC", "IOC", "FOK", or "PO"
1566
+ * @param {bool} [params.postOnly] true or false
1567
+ * @param {float} [params.stopPrice] the price at which a trigger order is triggered at
1568
+ * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice that the attached take profit order will be triggered (perpetual swap markets only)
1569
+ * @param {float} [params.takeProfit.triggerPrice] *swap only* take profit trigger price
1570
+ * @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice that the attached stop loss order will be triggered (perpetual swap markets only)
1571
+ * @param {float} [params.stopLoss.triggerPrice] *swap only* stop loss trigger price
1572
+ * @returns [An order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1573
+ */
1574
+ await this.loadMarkets();
1575
+ await this.loadAccounts();
1576
+ const market = this.market(symbol);
1577
+ const request = this.createOrderRequest(symbol, type, side, amount, price, params);
1578
+ let response = undefined;
1579
+ if (market['swap']) {
1580
+ response = await this.v2PrivateAccountGroupPostFuturesOrder(request);
1581
+ }
1582
+ else {
1583
+ response = await this.v1PrivateAccountCategoryPostOrder(request);
1551
1584
  }
1552
- const response = await this[method](this.extend(request, params));
1553
1585
  //
1554
1586
  // spot
1555
1587
  //
@@ -1570,7 +1602,6 @@ class ascendex extends ascendex$1 {
1570
1602
  // }
1571
1603
  // }
1572
1604
  //
1573
- //
1574
1605
  // swap
1575
1606
  //
1576
1607
  // {
@@ -1618,6 +1649,105 @@ class ascendex extends ascendex$1 {
1618
1649
  const order = this.safeValue2(data, 'order', 'info', {});
1619
1650
  return this.parseOrder(order, market);
1620
1651
  }
1652
+ async createOrders(orders, params = {}) {
1653
+ /**
1654
+ * @method
1655
+ * @name ascendex#createOrders
1656
+ * @description create a list of trade orders
1657
+ * @see https://ascendex.github.io/ascendex-pro-api/#place-batch-orders
1658
+ * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#place-batch-orders
1659
+ * @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
1660
+ * @param {object} [params] extra parameters specific to the ascendex api endpoint
1661
+ * @param {string} [params.timeInForce] "GTC", "IOC", "FOK", or "PO"
1662
+ * @param {bool} [params.postOnly] true or false
1663
+ * @param {float} [params.stopPrice] the price at which a trigger order is triggered at
1664
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1665
+ */
1666
+ await this.loadMarkets();
1667
+ await this.loadAccounts();
1668
+ const ordersRequests = [];
1669
+ let symbol = undefined;
1670
+ let marginMode = undefined;
1671
+ for (let i = 0; i < orders.length; i++) {
1672
+ const rawOrder = orders[i];
1673
+ const marketId = this.safeString(rawOrder, 'symbol');
1674
+ if (symbol === undefined) {
1675
+ symbol = marketId;
1676
+ }
1677
+ else {
1678
+ if (symbol !== marketId) {
1679
+ throw new errors.BadRequest(this.id + ' createOrders() requires all orders to have the same symbol');
1680
+ }
1681
+ }
1682
+ const type = this.safeString(rawOrder, 'type');
1683
+ const side = this.safeString(rawOrder, 'side');
1684
+ const amount = this.safeValue(rawOrder, 'amount');
1685
+ const price = this.safeValue(rawOrder, 'price');
1686
+ const orderParams = this.safeValue(rawOrder, 'params', {});
1687
+ const marginResult = this.handleMarginModeAndParams('createOrders', orderParams);
1688
+ const currentMarginMode = marginResult[0];
1689
+ if (currentMarginMode !== undefined) {
1690
+ if (marginMode === undefined) {
1691
+ marginMode = currentMarginMode;
1692
+ }
1693
+ else {
1694
+ if (marginMode !== currentMarginMode) {
1695
+ throw new errors.BadRequest(this.id + ' createOrders() requires all orders to have the same margin mode (isolated or cross)');
1696
+ }
1697
+ }
1698
+ }
1699
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
1700
+ ordersRequests.push(orderRequest);
1701
+ }
1702
+ const market = this.market(symbol);
1703
+ const accountsByType = this.safeValue(this.options, 'accountsByType', {});
1704
+ let accountCategory = this.safeString(accountsByType, market['type'], 'cash');
1705
+ if (marginMode !== undefined) {
1706
+ accountCategory = 'margin';
1707
+ }
1708
+ const account = this.safeValue(this.accounts, 0, {});
1709
+ const accountGroup = this.safeValue(account, 'id');
1710
+ const request = {};
1711
+ let response = undefined;
1712
+ if (market['swap']) {
1713
+ throw new errors.NotSupported(this.id + ' createOrders() is not currently supported for swap markets on ascendex');
1714
+ // request['account-group'] = accountGroup;
1715
+ // request['category'] = accountCategory;
1716
+ // request['orders'] = ordersRequests;
1717
+ // response = await this.v2PrivateAccountGroupPostFuturesOrderBatch (request);
1718
+ }
1719
+ else {
1720
+ request['account-group'] = accountGroup;
1721
+ request['account-category'] = accountCategory;
1722
+ request['orders'] = ordersRequests;
1723
+ response = await this.v1PrivateAccountCategoryPostOrderBatch(request);
1724
+ }
1725
+ //
1726
+ // spot
1727
+ //
1728
+ // {
1729
+ // "code": 0,
1730
+ // "data": {
1731
+ // "accountId": "cshdAKBO43TKIh2kJtq7FVVb42KIePyS",
1732
+ // "ac": "CASH",
1733
+ // "action": "batch-place-order",
1734
+ // "status": "Ack",
1735
+ // "info": [
1736
+ // {
1737
+ // "symbol": "BTC/USDT",
1738
+ // "orderType": "Limit",
1739
+ // "timestamp": 1699326589344,
1740
+ // "id": "",
1741
+ // "orderId": "a18ba7c1f6efU0711043490p3HvjjN5x"
1742
+ // }
1743
+ // ]
1744
+ // }
1745
+ // }
1746
+ //
1747
+ const data = this.safeValue(response, 'data', {});
1748
+ const info = this.safeValue(data, 'info', []);
1749
+ return this.parseOrders(info, market);
1750
+ }
1621
1751
  async fetchOrder(id, symbol = undefined, params = {}) {
1622
1752
  /**
1623
1753
  * @method
@@ -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;