ccxt 4.3.7 → 4.3.9

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 (44) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/ccxt.js +1 -1
  3. package/dist/cjs/src/base/Exchange.js +13 -3
  4. package/dist/cjs/src/binance.js +1 -1
  5. package/dist/cjs/src/bingx.js +22 -12
  6. package/dist/cjs/src/bitget.js +1 -1
  7. package/dist/cjs/src/coinex.js +629 -433
  8. package/dist/cjs/src/coinmetro.js +31 -31
  9. package/dist/cjs/src/okx.js +59 -2
  10. package/dist/cjs/src/woo.js +1 -1
  11. package/js/ccxt.d.ts +1 -1
  12. package/js/ccxt.js +1 -1
  13. package/js/src/abstract/bingx.d.ts +1 -1
  14. package/js/src/abstract/coinmetro.d.ts +1 -0
  15. package/js/src/base/Exchange.d.ts +19 -19
  16. package/js/src/base/Exchange.js +13 -3
  17. package/js/src/base/functions/generic.d.ts +20 -19
  18. package/js/src/binance.js +1 -1
  19. package/js/src/bingx.d.ts +2 -2
  20. package/js/src/bingx.js +22 -12
  21. package/js/src/bitget.js +1 -1
  22. package/js/src/bybit.d.ts +1 -1
  23. package/js/src/coinbase.d.ts +1 -1
  24. package/js/src/coinbaseinternational.d.ts +1 -1
  25. package/js/src/coinex.js +629 -433
  26. package/js/src/coinmetro.d.ts +1 -1
  27. package/js/src/coinmetro.js +31 -31
  28. package/js/src/gemini.d.ts +1 -1
  29. package/js/src/hollaex.d.ts +1 -1
  30. package/js/src/htx.d.ts +2 -2
  31. package/js/src/idex.d.ts +1 -1
  32. package/js/src/kucoin.d.ts +1 -1
  33. package/js/src/mexc.d.ts +1 -1
  34. package/js/src/okcoin.d.ts +1 -1
  35. package/js/src/okx.d.ts +5 -1
  36. package/js/src/okx.js +59 -2
  37. package/js/src/paymium.d.ts +1 -1
  38. package/js/src/pro/luno.d.ts +2 -2
  39. package/js/src/probit.d.ts +1 -1
  40. package/js/src/upbit.d.ts +1 -1
  41. package/js/src/whitebit.d.ts +1 -1
  42. package/js/src/woo.js +1 -1
  43. package/js/src/zonda.d.ts +1 -1
  44. package/package.json +7 -7
@@ -1529,190 +1529,144 @@ class coinex extends coinex$1 {
1529
1529
  }
1530
1530
  async fetchMarginBalance(params = {}) {
1531
1531
  await this.loadMarkets();
1532
- const symbol = this.safeString(params, 'symbol');
1533
- let marketId = this.safeString(params, 'market');
1534
- let market = undefined;
1535
- if (symbol !== undefined) {
1536
- market = this.market(symbol);
1537
- marketId = market['id'];
1538
- }
1539
- else if (marketId === undefined) {
1540
- throw new errors.ArgumentsRequired(this.id + ' fetchMarginBalance() fetching a margin account requires a market parameter or a symbol parameter');
1541
- }
1542
- params = this.omit(params, ['symbol', 'market']);
1543
- const request = {
1544
- 'market': marketId,
1545
- };
1546
- const response = await this.v1PrivateGetMarginAccount(this.extend(request, params));
1532
+ const response = await this.v2PrivateGetAssetsMarginBalance(params);
1547
1533
  //
1548
- // {
1549
- // "code": 0,
1550
- // "data": {
1551
- // "account_id": 126,
1552
- // "leverage": 3,
1553
- // "market_type": "AAVEUSDT",
1554
- // "sell_asset_type": "AAVE",
1555
- // "buy_asset_type": "USDT",
1556
- // "balance": {
1557
- // "sell_type": "0.3", // borrowed
1558
- // "buy_type": "30"
1559
- // },
1560
- // "frozen": {
1561
- // "sell_type": "0",
1562
- // "buy_type": "0"
1563
- // },
1564
- // "loan": {
1565
- // "sell_type": "0.3", // loan
1566
- // "buy_type": "0"
1567
- // },
1568
- // "interest": {
1569
- // "sell_type": "0.0000125",
1570
- // "buy_type": "0"
1571
- // },
1572
- // "can_transfer": {
1573
- // "sell_type": "0.02500646",
1574
- // "buy_type": "4.28635738"
1575
- // },
1576
- // "warn_rate": "",
1577
- // "liquidation_price": ""
1578
- // },
1579
- // "message": "Success"
1580
- // }
1534
+ // {
1535
+ // "data": [
1536
+ // {
1537
+ // "margin_account": "BTCUSDT",
1538
+ // "base_ccy": "BTC",
1539
+ // "quote_ccy": "USDT",
1540
+ // "available": {
1541
+ // "base_ccy": "0.00000026",
1542
+ // "quote_ccy": "0"
1543
+ // },
1544
+ // "frozen": {
1545
+ // "base_ccy": "0",
1546
+ // "quote_ccy": "0"
1547
+ // },
1548
+ // "repaid": {
1549
+ // "base_ccy": "0",
1550
+ // "quote_ccy": "0"
1551
+ // },
1552
+ // "interest": {
1553
+ // "base_ccy": "0",
1554
+ // "quote_ccy": "0"
1555
+ // },
1556
+ // "rik_rate": "",
1557
+ // "liq_price": ""
1558
+ // },
1559
+ // ],
1560
+ // "code": 0,
1561
+ // "message": "OK"
1562
+ // }
1581
1563
  //
1582
1564
  const result = { 'info': response };
1583
- const data = this.safeValue(response, 'data', {});
1584
- const free = this.safeValue(data, 'can_transfer', {});
1585
- const total = this.safeValue(data, 'balance', {});
1586
- const loan = this.safeValue(data, 'loan', {});
1587
- const interest = this.safeValue(data, 'interest', {});
1588
- //
1589
- const sellAccount = this.account();
1590
- const sellCurrencyId = this.safeString(data, 'sell_asset_type');
1591
- const sellCurrencyCode = this.safeCurrencyCode(sellCurrencyId);
1592
- sellAccount['free'] = this.safeString(free, 'sell_type');
1593
- sellAccount['total'] = this.safeString(total, 'sell_type');
1594
- const sellDebt = this.safeString(loan, 'sell_type');
1595
- const sellInterest = this.safeString(interest, 'sell_type');
1596
- sellAccount['debt'] = Precise["default"].stringAdd(sellDebt, sellInterest);
1597
- result[sellCurrencyCode] = sellAccount;
1598
- //
1599
- const buyAccount = this.account();
1600
- const buyCurrencyId = this.safeString(data, 'buy_asset_type');
1601
- const buyCurrencyCode = this.safeCurrencyCode(buyCurrencyId);
1602
- buyAccount['free'] = this.safeString(free, 'buy_type');
1603
- buyAccount['total'] = this.safeString(total, 'buy_type');
1604
- const buyDebt = this.safeString(loan, 'buy_type');
1605
- const buyInterest = this.safeString(interest, 'buy_type');
1606
- buyAccount['debt'] = Precise["default"].stringAdd(buyDebt, buyInterest);
1607
- result[buyCurrencyCode] = buyAccount;
1608
- //
1565
+ const balances = this.safeList(response, 'data', []);
1566
+ for (let i = 0; i < balances.length; i++) {
1567
+ const entry = balances[i];
1568
+ const free = this.safeDict(entry, 'available', {});
1569
+ const used = this.safeDict(entry, 'frozen', {});
1570
+ const loan = this.safeDict(entry, 'repaid', {});
1571
+ const interest = this.safeDict(entry, 'interest', {});
1572
+ const baseAccount = this.account();
1573
+ const baseCurrencyId = this.safeString(entry, 'base_ccy');
1574
+ const baseCurrencyCode = this.safeCurrencyCode(baseCurrencyId);
1575
+ baseAccount['free'] = this.safeString(free, 'base_ccy');
1576
+ baseAccount['used'] = this.safeString(used, 'base_ccy');
1577
+ const baseDebt = this.safeString(loan, 'base_ccy');
1578
+ const baseInterest = this.safeString(interest, 'base_ccy');
1579
+ baseAccount['debt'] = Precise["default"].stringAdd(baseDebt, baseInterest);
1580
+ result[baseCurrencyCode] = baseAccount;
1581
+ }
1609
1582
  return this.safeBalance(result);
1610
1583
  }
1611
1584
  async fetchSpotBalance(params = {}) {
1612
1585
  await this.loadMarkets();
1613
- const response = await this.v1PrivateGetBalanceInfo(params);
1586
+ const response = await this.v2PrivateGetAssetsSpotBalance(params);
1614
1587
  //
1615
1588
  // {
1616
- // "code": 0,
1617
- // "data": {
1618
- // "BCH": { # BCH account
1619
- // "available": "13.60109", # Available BCH
1620
- // "frozen": "0.00000" # Frozen BCH
1621
- // },
1622
- // "BTC": { # BTC account
1623
- // "available": "32590.16", # Available BTC
1624
- // "frozen": "7000.00" # Frozen BTC
1625
- // },
1626
- // "ETH": { # ETH account
1627
- // "available": "5.06000", # Available ETH
1628
- // "frozen": "0.00000" # Frozen ETH
1629
- // }
1630
- // },
1631
- // "message": "Ok"
1589
+ // "code": 0,
1590
+ // "data": [
1591
+ // {
1592
+ // "available": "0.00000046",
1593
+ // "ccy": "USDT",
1594
+ // "frozen": "0"
1595
+ // }
1596
+ // ],
1597
+ // "message": "OK"
1632
1598
  // }
1633
1599
  //
1634
1600
  const result = { 'info': response };
1635
- const balances = this.safeValue(response, 'data', {});
1636
- const currencyIds = Object.keys(balances);
1637
- for (let i = 0; i < currencyIds.length; i++) {
1638
- const currencyId = currencyIds[i];
1601
+ const balances = this.safeList(response, 'data', []);
1602
+ for (let i = 0; i < balances.length; i++) {
1603
+ const entry = balances[i];
1604
+ const currencyId = this.safeString(entry, 'ccy');
1639
1605
  const code = this.safeCurrencyCode(currencyId);
1640
- const balance = this.safeValue(balances, currencyId, {});
1641
1606
  const account = this.account();
1642
- account['free'] = this.safeString(balance, 'available');
1643
- account['used'] = this.safeString(balance, 'frozen');
1607
+ account['free'] = this.safeString(entry, 'available');
1608
+ account['used'] = this.safeString(entry, 'frozen');
1644
1609
  result[code] = account;
1645
1610
  }
1646
1611
  return this.safeBalance(result);
1647
1612
  }
1648
1613
  async fetchSwapBalance(params = {}) {
1649
1614
  await this.loadMarkets();
1650
- const response = await this.v1PerpetualPrivateGetAssetQuery(params);
1615
+ const response = await this.v2PrivateGetAssetsFuturesBalance(params);
1651
1616
  //
1652
1617
  // {
1653
1618
  // "code": 0,
1654
- // "data": {
1655
- // "USDT": {
1656
- // "available": "37.24817690383456000000",
1657
- // "balance_total": "37.24817690383456000000",
1658
- // "frozen": "0.00000000000000000000",
1659
- // "margin": "0.00000000000000000000",
1660
- // "profit_unreal": "0.00000000000000000000",
1661
- // "transfer": "37.24817690383456000000"
1619
+ // "data": [
1620
+ // {
1621
+ // "available": "0.00000046",
1622
+ // "ccy": "USDT",
1623
+ // "frozen": "0",
1624
+ // "margin": "0",
1625
+ // "transferrable": "0.00000046",
1626
+ // "unrealized_pnl": "0"
1662
1627
  // }
1663
- // },
1628
+ // ],
1664
1629
  // "message": "OK"
1665
1630
  // }
1666
1631
  //
1667
1632
  const result = { 'info': response };
1668
- const balances = this.safeValue(response, 'data', {});
1669
- const currencyIds = Object.keys(balances);
1670
- for (let i = 0; i < currencyIds.length; i++) {
1671
- const currencyId = currencyIds[i];
1633
+ const balances = this.safeList(response, 'data', []);
1634
+ for (let i = 0; i < balances.length; i++) {
1635
+ const entry = balances[i];
1636
+ const currencyId = this.safeString(entry, 'ccy');
1672
1637
  const code = this.safeCurrencyCode(currencyId);
1673
- const balance = this.safeValue(balances, currencyId, {});
1674
1638
  const account = this.account();
1675
- account['free'] = this.safeString(balance, 'available');
1676
- account['used'] = this.safeString(balance, 'frozen');
1677
- account['total'] = this.safeString(balance, 'balance_total');
1639
+ account['free'] = this.safeString(entry, 'available');
1640
+ account['used'] = this.safeString(entry, 'frozen');
1678
1641
  result[code] = account;
1679
1642
  }
1680
1643
  return this.safeBalance(result);
1681
1644
  }
1682
1645
  async fetchFinancialBalance(params = {}) {
1683
1646
  await this.loadMarkets();
1684
- const response = await this.v1PrivateGetAccountInvestmentBalance(params);
1647
+ const response = await this.v2PrivateGetAssetsFinancialBalance(params);
1685
1648
  //
1686
1649
  // {
1687
- // "code": 0,
1688
- // "data": [
1689
- // {
1690
- // "asset": "CET",
1691
- // "available": "0",
1692
- // "frozen": "0",
1693
- // "lock": "0",
1694
- // },
1695
- // {
1696
- // "asset": "USDT",
1697
- // "available": "999900",
1698
- // "frozen": "0",
1699
- // "lock": "0"
1700
- // }
1701
- // ],
1702
- // "message": "Success"
1703
- // }
1650
+ // "code": 0,
1651
+ // "data": [
1652
+ // {
1653
+ // "available": "0.00000046",
1654
+ // "ccy": "USDT",
1655
+ // "frozen": "0"
1656
+ // }
1657
+ // ],
1658
+ // "message": "OK"
1659
+ // }
1704
1660
  //
1705
1661
  const result = { 'info': response };
1706
- const balances = this.safeValue(response, 'data', {});
1662
+ const balances = this.safeList(response, 'data', []);
1707
1663
  for (let i = 0; i < balances.length; i++) {
1708
- const balance = balances[i];
1709
- const currencyId = this.safeString(balance, 'asset');
1664
+ const entry = balances[i];
1665
+ const currencyId = this.safeString(entry, 'ccy');
1710
1666
  const code = this.safeCurrencyCode(currencyId);
1711
1667
  const account = this.account();
1712
- account['free'] = this.safeString(balance, 'available');
1713
- const frozen = this.safeString(balance, 'frozen');
1714
- const locked = this.safeString(balance, 'lock');
1715
- account['used'] = Precise["default"].stringAdd(frozen, locked);
1668
+ account['free'] = this.safeString(entry, 'available');
1669
+ account['used'] = this.safeString(entry, 'frozen');
1716
1670
  result[code] = account;
1717
1671
  }
1718
1672
  return this.safeBalance(result);
@@ -1722,10 +1676,10 @@ class coinex extends coinex$1 {
1722
1676
  * @method
1723
1677
  * @name coinex#fetchBalance
1724
1678
  * @description query for balance and get the amount of funds available for trading or funds locked in orders
1725
- * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account001_account_info // spot
1726
- * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account004_investment_balance // financial
1727
- * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account006_margin_account // margin
1728
- * @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http016_asset_query // swap
1679
+ * @see https://docs.coinex.com/api/v2/assets/balance/http/get-spot-balance // spot
1680
+ * @see https://docs.coinex.com/api/v2/assets/balance/http/get-futures-balance // swap
1681
+ * @see https://docs.coinex.com/api/v2/assets/balance/http/get-marigin-balance // margin
1682
+ * @see https://docs.coinex.com/api/v2/assets/balance/http/get-financial-balance // financial
1729
1683
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1730
1684
  * @param {string} [params.type] 'margin', 'swap', 'financial', or 'spot'
1731
1685
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
@@ -1786,7 +1740,7 @@ class coinex extends coinex$1 {
1786
1740
  // "client_id": "",
1787
1741
  // }
1788
1742
  //
1789
- // Spot and Margin createOrder, createOrders, cancelOrder, cancelOrders, fetchOrder
1743
+ // Spot and Margin cancelOrder, cancelOrders, fetchOrder
1790
1744
  //
1791
1745
  // {
1792
1746
  // "amount":"1.5",
@@ -1814,7 +1768,7 @@ class coinex extends coinex$1 {
1814
1768
  // "client_id": "",
1815
1769
  // }
1816
1770
  //
1817
- // Swap createOrder, cancelOrder, fetchOrder
1771
+ // Swap cancelOrder, fetchOrder
1818
1772
  //
1819
1773
  // {
1820
1774
  // "amount": "0.0005",
@@ -1851,10 +1805,6 @@ class coinex extends coinex$1 {
1851
1805
  // "user_id": 3620173
1852
1806
  // }
1853
1807
  //
1854
- // Stop order createOrder
1855
- //
1856
- // {"status":"success"}
1857
- //
1858
1808
  // Swap Stop cancelOrder, fetchOrder
1859
1809
  //
1860
1810
  // {
@@ -2027,25 +1977,128 @@ class coinex extends coinex$1 {
2027
1977
  // "user_id": 3620173
2028
1978
  // }
2029
1979
  //
1980
+ // Spot and Margin createOrder, createOrders v2
1981
+ //
1982
+ // {
1983
+ // "amount": "0.0001",
1984
+ // "base_fee": "0",
1985
+ // "ccy": "BTC",
1986
+ // "client_id": "x-167673045-a0a3c6461459a801",
1987
+ // "created_at": 1714114386250,
1988
+ // "discount_fee": "0",
1989
+ // "filled_amount": "0",
1990
+ // "filled_value": "0",
1991
+ // "last_fill_amount": "0",
1992
+ // "last_fill_price": "0",
1993
+ // "maker_fee_rate": "0.002",
1994
+ // "market": "BTCUSDT",
1995
+ // "market_type": "SPOT",
1996
+ // "order_id": 117178743547,
1997
+ // "price": "61000",
1998
+ // "quote_fee": "0",
1999
+ // "side": "buy",
2000
+ // "taker_fee_rate": "0.002",
2001
+ // "type": "limit",
2002
+ // "unfilled_amount": "0.0001",
2003
+ // "updated_at": 1714114386250
2004
+ // }
2005
+ //
2006
+ // Spot, Margin and Swap trigger createOrder, createOrders v2
2007
+ //
2008
+ // {
2009
+ // "stop_id": 117180138153
2010
+ // }
2011
+ //
2012
+ // Swap createOrder, createOrders v2
2013
+ //
2014
+ // {
2015
+ // "amount": "0.0001",
2016
+ // "client_id": "x-167673045-1471b81d747080a0",
2017
+ // "created_at": 1714116769986,
2018
+ // "fee": "0",
2019
+ // "fee_ccy": "USDT",
2020
+ // "filled_amount": "0",
2021
+ // "filled_value": "0",
2022
+ // "last_filled_amount": "0",
2023
+ // "last_filled_price": "0",
2024
+ // "maker_fee_rate": "0.0003",
2025
+ // "market": "BTCUSDT",
2026
+ // "market_type": "FUTURES",
2027
+ // "order_id": 136913377780,
2028
+ // "price": "61000.42",
2029
+ // "realized_pnl": "0",
2030
+ // "side": "buy",
2031
+ // "taker_fee_rate": "0.0005",
2032
+ // "type": "limit",
2033
+ // "unfilled_amount": "0.0001",
2034
+ // "updated_at": 1714116769986
2035
+ // }
2036
+ //
2037
+ // Swap stopLossPrice and takeProfitPrice createOrder v2
2038
+ //
2039
+ // {
2040
+ // "adl_level": 1,
2041
+ // "ath_margin_size": "2.14586666",
2042
+ // "ath_position_amount": "0.0001",
2043
+ // "avg_entry_price": "64376",
2044
+ // "bkr_price": "0",
2045
+ // "close_avbl": "0.0001",
2046
+ // "cml_position_value": "6.4376",
2047
+ // "created_at": 1714119054558,
2048
+ // "leverage": "3",
2049
+ // "liq_price": "0",
2050
+ // "maintenance_margin_rate": "0.005",
2051
+ // "maintenance_margin_value": "0.03218632",
2052
+ // "margin_avbl": "2.14586666",
2053
+ // "margin_mode": "cross",
2054
+ // "market": "BTCUSDT",
2055
+ // "market_type": "FUTURES",
2056
+ // "max_position_value": "6.4376",
2057
+ // "open_interest": "0.0001",
2058
+ // "position_id": 303884204,
2059
+ // "position_margin_rate": "3.10624785634397912265",
2060
+ // "realized_pnl": "-0.0032188",
2061
+ // "settle_price": "64376",
2062
+ // "settle_value": "6.4376",
2063
+ // "side": "long",
2064
+ // "stop_loss_price": "62000",
2065
+ // "stop_loss_type": "latest_price",
2066
+ // "take_profit_price": "0",
2067
+ // "take_profit_type": "",
2068
+ // "unrealized_pnl": "0",
2069
+ // "updated_at": 1714119054559
2070
+ // }
2071
+ //
2030
2072
  const rawStatus = this.safeString(order, 'status');
2031
- const timestamp = this.safeTimestamp(order, 'create_time');
2073
+ let timestamp = this.safeTimestamp(order, 'create_time');
2074
+ if (timestamp === undefined) {
2075
+ timestamp = this.safeInteger(order, 'created_at');
2076
+ }
2077
+ let update = this.safeTimestamp(order, 'update_time');
2078
+ if (update === undefined) {
2079
+ update = this.safeInteger(order, 'updated_at');
2080
+ }
2032
2081
  const marketId = this.safeString(order, 'market');
2033
2082
  const defaultType = this.safeString(this.options, 'defaultType');
2034
2083
  const orderType = ('source' in order) ? 'swap' : defaultType;
2035
2084
  market = this.safeMarket(marketId, market, undefined, orderType);
2036
- const feeCurrencyId = this.safeString(order, 'fee_asset');
2085
+ const feeCurrencyId = this.safeString2(order, 'fee_asset', 'fee_ccy');
2037
2086
  let feeCurrency = this.safeCurrencyCode(feeCurrencyId);
2038
2087
  if (feeCurrency === undefined) {
2039
2088
  feeCurrency = market['quote'];
2040
2089
  }
2041
- const rawSide = this.safeInteger(order, 'side');
2090
+ const rawIntegerSide = this.safeInteger(order, 'side');
2091
+ const rawStringSide = this.safeString(order, 'side');
2042
2092
  let side = undefined;
2043
- if (rawSide === 1) {
2093
+ if (rawIntegerSide === 1) {
2044
2094
  side = 'sell';
2045
2095
  }
2046
- else if (rawSide === 2) {
2096
+ else if (rawIntegerSide === 2) {
2047
2097
  side = 'buy';
2048
2098
  }
2099
+ else if ((rawStringSide === 'buy') || (rawStringSide === 'sell')) {
2100
+ side = rawStringSide;
2101
+ }
2049
2102
  else {
2050
2103
  side = this.safeString(order, 'type');
2051
2104
  }
@@ -2053,12 +2106,19 @@ class coinex extends coinex$1 {
2053
2106
  let type = undefined;
2054
2107
  if (rawType === undefined) {
2055
2108
  const typeInteger = this.safeInteger(order, 'type');
2109
+ const typeString = this.safeString(order, 'type');
2056
2110
  if (typeInteger === 1) {
2057
2111
  type = 'limit';
2058
2112
  }
2059
2113
  else if (typeInteger === 2) {
2060
2114
  type = 'market';
2061
2115
  }
2116
+ else if ((typeString === 'limit') || (typeString === 'market')) {
2117
+ type = typeString;
2118
+ }
2119
+ else if (typeString === 'maker_only') {
2120
+ type = 'limit';
2121
+ }
2062
2122
  }
2063
2123
  else {
2064
2124
  type = rawType;
@@ -2068,11 +2128,11 @@ class coinex extends coinex$1 {
2068
2128
  clientOrderId = undefined;
2069
2129
  }
2070
2130
  return this.safeOrder({
2071
- 'id': this.safeString2(order, 'id', 'order_id'),
2131
+ 'id': this.safeStringN(order, ['id', 'order_id', 'stop_id']),
2072
2132
  'clientOrderId': clientOrderId,
2073
2133
  'datetime': this.iso8601(timestamp),
2074
2134
  'timestamp': timestamp,
2075
- 'lastTradeTimestamp': this.safeTimestamp(order, 'update_time'),
2135
+ 'lastTradeTimestamp': update,
2076
2136
  'status': this.parseOrderStatus(rawStatus),
2077
2137
  'symbol': market['symbol'],
2078
2138
  'type': type,
@@ -2085,15 +2145,15 @@ class coinex extends coinex$1 {
2085
2145
  'triggerPrice': this.safeString(order, 'stop_price'),
2086
2146
  'takeProfitPrice': this.safeNumber(order, 'take_profit_price'),
2087
2147
  'stopLossPrice': this.safeNumber(order, 'stop_loss_price'),
2088
- 'cost': this.safeString(order, 'deal_money'),
2089
- 'average': this.safeString(order, 'avg_price'),
2148
+ 'cost': this.safeString2(order, 'deal_money', 'filled_value'),
2149
+ 'average': this.safeString2(order, 'avg_price', 'avg_entry_price'),
2090
2150
  'amount': this.safeString(order, 'amount'),
2091
- 'filled': this.safeString(order, 'deal_amount'),
2092
- 'remaining': this.safeString(order, 'left'),
2151
+ 'filled': this.safeString2(order, 'deal_amount', 'filled_amount'),
2152
+ 'remaining': this.safeString2(order, 'left', 'unfilled_amount'),
2093
2153
  'trades': undefined,
2094
2154
  'fee': {
2095
2155
  'currency': feeCurrency,
2096
- 'cost': this.safeString(order, 'deal_fee'),
2156
+ 'cost': this.safeStringN(order, ['deal_fee', 'quote_fee', 'fee']),
2097
2157
  },
2098
2158
  'info': order,
2099
2159
  }, market);
@@ -2104,6 +2164,7 @@ class coinex extends coinex$1 {
2104
2164
  * @name coinex#createMarketBuyOrderWithCost
2105
2165
  * @description create a market buy order by providing the symbol and cost
2106
2166
  * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade003_market_order
2167
+ * @see https://docs.coinex.com/api/v2/spot/order/http/put-order
2107
2168
  * @param {string} symbol unified symbol of the market to create an order in
2108
2169
  * @param {float} cost how much you want to trade in units of the quote currency
2109
2170
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -2121,22 +2182,18 @@ class coinex extends coinex$1 {
2121
2182
  const market = this.market(symbol);
2122
2183
  const swap = market['swap'];
2123
2184
  const clientOrderId = this.safeString2(params, 'client_id', 'clientOrderId');
2124
- const stopPrice = this.safeValue2(params, 'stopPrice', 'triggerPrice');
2125
- const stopLossPrice = this.safeValue(params, 'stopLossPrice');
2126
- const takeProfitPrice = this.safeValue(params, 'takeProfitPrice');
2185
+ const stopPrice = this.safeString2(params, 'stopPrice', 'triggerPrice');
2186
+ const stopLossPrice = this.safeString(params, 'stopLossPrice');
2187
+ const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
2127
2188
  const option = this.safeString(params, 'option');
2128
2189
  const isMarketOrder = type === 'market';
2129
- const postOnly = this.isPostOnly(isMarketOrder, option === 'MAKER_ONLY', params);
2130
- const positionId = this.safeInteger2(params, 'position_id', 'positionId'); // Required for closing swap positions
2131
- const timeInForceRaw = this.safeString(params, 'timeInForce'); // Spot: IOC, FOK, PO, GTC, ... NORMAL (default), MAKER_ONLY
2132
- const reduceOnly = this.safeValue(params, 'reduceOnly');
2190
+ const postOnly = this.isPostOnly(isMarketOrder, option === 'maker_only', params);
2191
+ const timeInForceRaw = this.safeStringUpper(params, 'timeInForce');
2192
+ const reduceOnly = this.safeBool(params, 'reduceOnly');
2133
2193
  if (reduceOnly) {
2134
2194
  if (!market['swap']) {
2135
2195
  throw new errors.InvalidOrder(this.id + ' createOrder() does not support reduceOnly for ' + market['type'] + ' orders, reduceOnly orders are supported for swap markets only');
2136
2196
  }
2137
- if (positionId === undefined) {
2138
- throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a position_id/positionId parameter for reduceOnly orders');
2139
- }
2140
2197
  }
2141
2198
  const request = {
2142
2199
  'market': market['id'],
@@ -2149,73 +2206,56 @@ class coinex extends coinex$1 {
2149
2206
  else {
2150
2207
  request['client_id'] = clientOrderId;
2151
2208
  }
2209
+ if ((stopLossPrice === undefined) && (takeProfitPrice === undefined)) {
2210
+ if (!reduceOnly) {
2211
+ request['side'] = side;
2212
+ }
2213
+ let requestType = type;
2214
+ if (postOnly) {
2215
+ requestType = 'maker_only';
2216
+ }
2217
+ else if (timeInForceRaw !== undefined) {
2218
+ if (timeInForceRaw === 'IOC') {
2219
+ requestType = 'ioc';
2220
+ }
2221
+ else if (timeInForceRaw === 'FOK') {
2222
+ requestType = 'fok';
2223
+ }
2224
+ }
2225
+ if (!isMarketOrder) {
2226
+ request['price'] = this.priceToPrecision(symbol, price);
2227
+ }
2228
+ request['type'] = requestType;
2229
+ }
2152
2230
  if (swap) {
2231
+ request['market_type'] = 'FUTURES';
2153
2232
  if (stopLossPrice || takeProfitPrice) {
2154
- request['stop_type'] = this.safeInteger(params, 'stop_type', 1); // 1: triggered by the latest transaction, 2: mark price, 3: index price
2155
- if (positionId === undefined) {
2156
- throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a position_id parameter for stop loss and take profit orders');
2157
- }
2158
- request['position_id'] = positionId;
2159
2233
  if (stopLossPrice) {
2160
2234
  request['stop_loss_price'] = this.priceToPrecision(symbol, stopLossPrice);
2235
+ request['stop_loss_type'] = this.safeString(params, 'stop_type', 'latest_price');
2161
2236
  }
2162
2237
  else if (takeProfitPrice) {
2163
2238
  request['take_profit_price'] = this.priceToPrecision(symbol, takeProfitPrice);
2239
+ request['take_profit_type'] = this.safeString(params, 'stop_type', 'latest_price');
2164
2240
  }
2165
2241
  }
2166
2242
  else {
2167
- const requestSide = (side === 'buy') ? 2 : 1;
2243
+ request['amount'] = this.amountToPrecision(symbol, amount);
2168
2244
  if (stopPrice !== undefined) {
2169
- request['stop_price'] = this.priceToPrecision(symbol, stopPrice);
2170
- request['stop_type'] = this.safeInteger(params, 'stop_type', 1); // 1: triggered by the latest transaction, 2: mark price, 3: index price;
2171
- request['amount'] = this.amountToPrecision(symbol, amount);
2172
- request['side'] = requestSide;
2173
- if (type === 'limit') {
2174
- request['price'] = this.priceToPrecision(symbol, price);
2175
- }
2176
- request['amount'] = this.amountToPrecision(symbol, amount);
2177
- }
2178
- let timeInForce = undefined;
2179
- if ((type !== 'market') || (stopPrice !== undefined)) {
2180
- if (postOnly) {
2181
- request['option'] = 1;
2182
- }
2183
- else if (timeInForceRaw !== undefined) {
2184
- if (timeInForceRaw === 'IOC') {
2185
- timeInForce = 2;
2186
- }
2187
- else if (timeInForceRaw === 'FOK') {
2188
- timeInForce = 3;
2189
- }
2190
- else {
2191
- timeInForce = 1;
2192
- }
2193
- request['effect_type'] = timeInForce; // exchange takes 'IOC' and 'FOK'
2194
- }
2195
- }
2196
- if (type === 'limit' && stopPrice === undefined) {
2197
- if (reduceOnly) {
2198
- request['position_id'] = positionId;
2199
- }
2200
- else {
2201
- request['side'] = requestSide;
2202
- }
2203
- request['price'] = this.priceToPrecision(symbol, price);
2204
- request['amount'] = this.amountToPrecision(symbol, amount);
2205
- }
2206
- else if (type === 'market' && stopPrice === undefined) {
2207
- if (reduceOnly) {
2208
- request['position_id'] = positionId;
2209
- }
2210
- else {
2211
- request['side'] = requestSide;
2212
- request['amount'] = this.amountToPrecision(symbol, amount);
2213
- }
2245
+ request['trigger_price'] = this.priceToPrecision(symbol, stopPrice);
2246
+ request['trigger_price_type'] = this.safeString(params, 'stop_type', 'latest_price');
2214
2247
  }
2215
2248
  }
2216
2249
  }
2217
2250
  else {
2218
- request['type'] = side;
2251
+ let marginMode = undefined;
2252
+ [marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
2253
+ if (marginMode !== undefined) {
2254
+ request['market_type'] = 'MARGIN';
2255
+ }
2256
+ else {
2257
+ request['market_type'] = 'SPOT';
2258
+ }
2219
2259
  if ((type === 'market') && (side === 'buy')) {
2220
2260
  let createMarketBuyOrderRequiresPrice = true;
2221
2261
  [createMarketBuyOrderRequiresPrice, params] = this.handleOptionAndParams(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', true);
@@ -2240,39 +2280,11 @@ class coinex extends coinex$1 {
2240
2280
  else {
2241
2281
  request['amount'] = this.amountToPrecision(symbol, amount);
2242
2282
  }
2243
- if ((type === 'limit') || (type === 'ioc')) {
2244
- request['price'] = this.priceToPrecision(symbol, price);
2245
- }
2246
2283
  if (stopPrice !== undefined) {
2247
- request['stop_price'] = this.priceToPrecision(symbol, stopPrice);
2248
- }
2249
- if ((type !== 'market') || (stopPrice !== undefined)) {
2250
- // following options cannot be applied to vanilla market orders (but can be applied to stop-market orders)
2251
- if ((timeInForceRaw !== undefined) || postOnly) {
2252
- if ((postOnly || (timeInForceRaw !== 'IOC')) && ((type === 'limit') && (stopPrice !== undefined))) {
2253
- throw new errors.InvalidOrder(this.id + ' createOrder() only supports the IOC option for stop-limit orders');
2254
- }
2255
- if (postOnly) {
2256
- request['option'] = 'MAKER_ONLY';
2257
- }
2258
- else {
2259
- if (timeInForceRaw !== undefined) {
2260
- request['option'] = timeInForceRaw; // exchange takes 'IOC' and 'FOK'
2261
- }
2262
- }
2263
- }
2264
- }
2265
- }
2266
- const accountId = this.safeInteger(params, 'account_id');
2267
- let marginMode = undefined;
2268
- [marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
2269
- if (marginMode !== undefined) {
2270
- if (accountId === undefined) {
2271
- throw new errors.BadRequest(this.id + ' createOrder() requires an account_id parameter for margin orders');
2284
+ request['trigger_price'] = this.priceToPrecision(symbol, stopPrice);
2272
2285
  }
2273
- request['account_id'] = accountId;
2274
2286
  }
2275
- params = this.omit(params, ['reduceOnly', 'positionId', 'timeInForce', 'postOnly', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice']);
2287
+ params = this.omit(params, ['reduceOnly', 'timeInForce', 'postOnly', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice']);
2276
2288
  return this.extend(request, params);
2277
2289
  }
2278
2290
  async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
@@ -2280,17 +2292,13 @@ class coinex extends coinex$1 {
2280
2292
  * @method
2281
2293
  * @name coinex#createOrder
2282
2294
  * @description create a trade order
2283
- * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade001_limit_order
2284
- * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade003_market_order
2285
- * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade004_IOC_order
2286
- * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade005_stop_limit_order
2287
- * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade006_stop_market_order
2288
- * @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http017_put_limit
2289
- * @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http018_put_market
2290
- * @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http019_put_limit_stop
2291
- * @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http020_put_market_stop
2292
- * @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http031_market_close
2293
- * @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http030_limit_close
2295
+ * @see https://docs.coinex.com/api/v2/spot/order/http/put-order
2296
+ * @see https://docs.coinex.com/api/v2/spot/order/http/put-stop-order
2297
+ * @see https://docs.coinex.com/api/v2/futures/order/http/put-order
2298
+ * @see https://docs.coinex.com/api/v2/futures/order/http/put-stop-order
2299
+ * @see https://docs.coinex.com/api/v2/futures/position/http/close-position
2300
+ * @see https://docs.coinex.com/api/v2/futures/position/http/set-position-stop-loss
2301
+ * @see https://docs.coinex.com/api/v2/futures/position/http/set-position-take-profit
2294
2302
  * @param {string} symbol unified symbol of the market to create an order in
2295
2303
  * @param {string} type 'market' or 'limit'
2296
2304
  * @param {string} side 'buy' or 'sell'
@@ -2303,15 +2311,14 @@ class coinex extends coinex$1 {
2303
2311
  * @param {string} [params.timeInForce] 'GTC', 'IOC', 'FOK', 'PO'
2304
2312
  * @param {boolean} [params.postOnly] set to true if you wish to make a post only order
2305
2313
  * @param {boolean} [params.reduceOnly] *contract only* indicates if this order is to reduce the size of a position
2306
- * @param {int} [params.position_id] *required for reduce only orders* the position id to reduce
2307
2314
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2308
2315
  */
2309
2316
  await this.loadMarkets();
2310
2317
  const market = this.market(symbol);
2311
- const reduceOnly = this.safeValue(params, 'reduceOnly');
2312
- const triggerPrice = this.safeNumber2(params, 'stopPrice', 'triggerPrice');
2313
- const stopLossTriggerPrice = this.safeNumber(params, 'stopLossPrice');
2314
- const takeProfitTriggerPrice = this.safeNumber(params, 'takeProfitPrice');
2318
+ const reduceOnly = this.safeBool(params, 'reduceOnly');
2319
+ const triggerPrice = this.safeString2(params, 'stopPrice', 'triggerPrice');
2320
+ const stopLossTriggerPrice = this.safeString(params, 'stopLossPrice');
2321
+ const takeProfitTriggerPrice = this.safeString(params, 'takeProfitPrice');
2315
2322
  const isTriggerOrder = triggerPrice !== undefined;
2316
2323
  const isStopLossTriggerOrder = stopLossTriggerPrice !== undefined;
2317
2324
  const isTakeProfitTriggerOrder = takeProfitTriggerPrice !== undefined;
@@ -2320,135 +2327,212 @@ class coinex extends coinex$1 {
2320
2327
  let response = undefined;
2321
2328
  if (market['spot']) {
2322
2329
  if (isTriggerOrder) {
2323
- if (type === 'limit') {
2324
- response = await this.v1PrivatePostOrderStopLimit(request);
2325
- }
2326
- else {
2327
- response = await this.v1PrivatePostOrderStopMarket(request);
2328
- }
2330
+ response = await this.v2PrivatePostSpotStopOrder(request);
2331
+ //
2332
+ // {
2333
+ // "code": 0,
2334
+ // "data": {
2335
+ // "stop_id": 117180138153
2336
+ // },
2337
+ // "message": "OK"
2338
+ // }
2339
+ //
2329
2340
  }
2330
2341
  else {
2331
- if (type === 'limit') {
2332
- response = await this.v1PrivatePostOrderLimit(request);
2333
- }
2334
- else {
2335
- response = await this.v1PrivatePostOrderMarket(request);
2336
- }
2342
+ response = await this.v2PrivatePostSpotOrder(request);
2343
+ //
2344
+ // {
2345
+ // "code": 0,
2346
+ // "data": {
2347
+ // "amount": "0.0001",
2348
+ // "base_fee": "0",
2349
+ // "ccy": "BTC",
2350
+ // "client_id": "x-167673045-a0a3c6461459a801",
2351
+ // "created_at": 1714114386250,
2352
+ // "discount_fee": "0",
2353
+ // "filled_amount": "0",
2354
+ // "filled_value": "0",
2355
+ // "last_fill_amount": "0",
2356
+ // "last_fill_price": "0",
2357
+ // "maker_fee_rate": "0.002",
2358
+ // "market": "BTCUSDT",
2359
+ // "market_type": "SPOT",
2360
+ // "order_id": 117178743547,
2361
+ // "price": "61000",
2362
+ // "quote_fee": "0",
2363
+ // "side": "buy",
2364
+ // "taker_fee_rate": "0.002",
2365
+ // "type": "limit",
2366
+ // "unfilled_amount": "0.0001",
2367
+ // "updated_at": 1714114386250
2368
+ // },
2369
+ // "message": "OK"
2370
+ // }
2371
+ //
2337
2372
  }
2338
2373
  }
2339
2374
  else {
2340
2375
  if (isTriggerOrder) {
2341
- if (type === 'limit') {
2342
- response = await this.v1PerpetualPrivatePostOrderPutStopLimit(request);
2343
- }
2344
- else {
2345
- response = await this.v1PerpetualPrivatePostOrderPutStopMarket(request);
2346
- }
2376
+ response = await this.v2PrivatePostFuturesStopOrder(request);
2377
+ //
2378
+ // {
2379
+ // "code": 0,
2380
+ // "data": {
2381
+ // "stop_id": 136915460994
2382
+ // },
2383
+ // "message": "OK"
2384
+ // }
2385
+ //
2347
2386
  }
2348
2387
  else if (isStopLossOrTakeProfitTrigger) {
2349
2388
  if (isStopLossTriggerOrder) {
2350
- response = await this.v1PerpetualPrivatePostPositionStopLoss(request);
2389
+ response = await this.v2PrivatePostFuturesSetPositionStopLoss(request);
2390
+ //
2391
+ // {
2392
+ // "code": 0,
2393
+ // "data": {
2394
+ // "adl_level": 1,
2395
+ // "ath_margin_size": "2.14586666",
2396
+ // "ath_position_amount": "0.0001",
2397
+ // "avg_entry_price": "64376",
2398
+ // "bkr_price": "0",
2399
+ // "close_avbl": "0.0001",
2400
+ // "cml_position_value": "6.4376",
2401
+ // "created_at": 1714119054558,
2402
+ // "leverage": "3",
2403
+ // "liq_price": "0",
2404
+ // "maintenance_margin_rate": "0.005",
2405
+ // "maintenance_margin_value": "0.03218632",
2406
+ // "margin_avbl": "2.14586666",
2407
+ // "margin_mode": "cross",
2408
+ // "market": "BTCUSDT",
2409
+ // "market_type": "FUTURES",
2410
+ // "max_position_value": "6.4376",
2411
+ // "open_interest": "0.0001",
2412
+ // "position_id": 303884204,
2413
+ // "position_margin_rate": "3.10624785634397912265",
2414
+ // "realized_pnl": "-0.0032188",
2415
+ // "settle_price": "64376",
2416
+ // "settle_value": "6.4376",
2417
+ // "side": "long",
2418
+ // "stop_loss_price": "62000",
2419
+ // "stop_loss_type": "latest_price",
2420
+ // "take_profit_price": "0",
2421
+ // "take_profit_type": "",
2422
+ // "unrealized_pnl": "0",
2423
+ // "updated_at": 1714119054559
2424
+ // },
2425
+ // "message": "OK"
2426
+ // }
2427
+ //
2351
2428
  }
2352
2429
  else if (isTakeProfitTriggerOrder) {
2353
- response = await this.v1PerpetualPrivatePostPositionTakeProfit(request);
2430
+ response = await this.v2PrivatePostFuturesSetPositionTakeProfit(request);
2431
+ //
2432
+ // {
2433
+ // "code": 0,
2434
+ // "data": {
2435
+ // "adl_level": 1,
2436
+ // "ath_margin_size": "2.14586666",
2437
+ // "ath_position_amount": "0.0001",
2438
+ // "avg_entry_price": "64376",
2439
+ // "bkr_price": "0",
2440
+ // "close_avbl": "0.0001",
2441
+ // "cml_position_value": "6.4376",
2442
+ // "created_at": 1714119054558,
2443
+ // "leverage": "3",
2444
+ // "liq_price": "0",
2445
+ // "maintenance_margin_rate": "0.005",
2446
+ // "maintenance_margin_value": "0.03218632",
2447
+ // "margin_avbl": "2.14586666",
2448
+ // "margin_mode": "cross",
2449
+ // "market": "BTCUSDT",
2450
+ // "market_type": "FUTURES",
2451
+ // "max_position_value": "6.4376",
2452
+ // "open_interest": "0.0001",
2453
+ // "position_id": 303884204,
2454
+ // "position_margin_rate": "3.10624785634397912265",
2455
+ // "realized_pnl": "-0.0032188",
2456
+ // "settle_price": "64376",
2457
+ // "settle_value": "6.4376",
2458
+ // "side": "long",
2459
+ // "stop_loss_price": "62000",
2460
+ // "stop_loss_type": "latest_price",
2461
+ // "take_profit_price": "70000",
2462
+ // "take_profit_type": "latest_price",
2463
+ // "unrealized_pnl": "0",
2464
+ // "updated_at": 1714119054559
2465
+ // },
2466
+ // "message": "OK"
2467
+ // }
2468
+ //
2354
2469
  }
2355
2470
  }
2356
2471
  else {
2357
2472
  if (reduceOnly) {
2358
- if (type === 'limit') {
2359
- response = await this.v1PerpetualPrivatePostOrderCloseLimit(request);
2360
- }
2361
- else {
2362
- response = await this.v1PerpetualPrivatePostOrderCloseMarket(request);
2363
- }
2473
+ response = await this.v2PrivatePostFuturesClosePosition(request);
2474
+ //
2475
+ // {
2476
+ // "code": 0,
2477
+ // "data": {
2478
+ // "amount": "0.0001",
2479
+ // "client_id": "x-167673045-4f264600c432ac06",
2480
+ // "created_at": 1714119323764,
2481
+ // "fee": "0.003221",
2482
+ // "fee_ccy": "USDT",
2483
+ // "filled_amount": "0.0001",
2484
+ // "filled_value": "6.442017",
2485
+ // "last_filled_amount": "0.0001",
2486
+ // "last_filled_price": "64420.17",
2487
+ // "maker_fee_rate": "0",
2488
+ // "market": "BTCUSDT",
2489
+ // "market_type": "FUTURES",
2490
+ // "order_id": 136915813578,
2491
+ // "price": "0",
2492
+ // "realized_pnl": "0.004417",
2493
+ // "side": "sell",
2494
+ // "taker_fee_rate": "0.0005",
2495
+ // "type": "market",
2496
+ // "unfilled_amount": "0",
2497
+ // "updated_at": 1714119323764
2498
+ // },
2499
+ // "message": "OK"
2500
+ // }
2501
+ //
2364
2502
  }
2365
2503
  else {
2366
- if (type === 'limit') {
2367
- response = await this.v1PerpetualPrivatePostOrderPutLimit(request);
2368
- }
2369
- else {
2370
- response = await this.v1PerpetualPrivatePostOrderPutMarket(request);
2371
- }
2504
+ response = await this.v2PrivatePostFuturesOrder(request);
2505
+ //
2506
+ // {
2507
+ // "code": 0,
2508
+ // "data": {
2509
+ // "amount": "0.0001",
2510
+ // "client_id": "x-167673045-1471b81d747080a0",
2511
+ // "created_at": 1714116769986,
2512
+ // "fee": "0",
2513
+ // "fee_ccy": "USDT",
2514
+ // "filled_amount": "0",
2515
+ // "filled_value": "0",
2516
+ // "last_filled_amount": "0",
2517
+ // "last_filled_price": "0",
2518
+ // "maker_fee_rate": "0.0003",
2519
+ // "market": "BTCUSDT",
2520
+ // "market_type": "FUTURES",
2521
+ // "order_id": 136913377780,
2522
+ // "price": "61000.42",
2523
+ // "realized_pnl": "0",
2524
+ // "side": "buy",
2525
+ // "taker_fee_rate": "0.0005",
2526
+ // "type": "limit",
2527
+ // "unfilled_amount": "0.0001",
2528
+ // "updated_at": 1714116769986
2529
+ // },
2530
+ // "message": "OK"
2531
+ // }
2532
+ //
2372
2533
  }
2373
2534
  }
2374
2535
  }
2375
- //
2376
- // Spot and Margin
2377
- //
2378
- // {
2379
- // "code": 0,
2380
- // "data": {
2381
- // "amount": "0.0005",
2382
- // "asset_fee": "0",
2383
- // "avg_price": "0.00",
2384
- // "client_id": "",
2385
- // "create_time": 1650951627,
2386
- // "deal_amount": "0",
2387
- // "deal_fee": "0",
2388
- // "deal_money": "0",
2389
- // "fee_asset": null,
2390
- // "fee_discount": "1",
2391
- // "finished_time": null,
2392
- // "id": 74510932594,
2393
- // "left": "0.0005",
2394
- // "maker_fee_rate": "0.002",
2395
- // "market": "BTCUSDT",
2396
- // "money_fee": "0",
2397
- // "order_type": "limit",
2398
- // "price": "30000",
2399
- // "status": "not_deal",
2400
- // "stock_fee": "0",
2401
- // "taker_fee_rate": "0.002",
2402
- // "type": "buy"
2403
- // },
2404
- // "message": "Success"
2405
- // }
2406
- //
2407
- // Swap
2408
- //
2409
- // {
2410
- // "code": 0,
2411
- // "data": {
2412
- // "amount": "0.0005",
2413
- // "client_id": "",
2414
- // "create_time": 1651004578.618224,
2415
- // "deal_asset_fee": "0.00000000000000000000",
2416
- // "deal_fee": "0.00000000000000000000",
2417
- // "deal_profit": "0.00000000000000000000",
2418
- // "deal_stock": "0.00000000000000000000",
2419
- // "effect_type": 1,
2420
- // "fee_asset": "",
2421
- // "fee_discount": "0.00000000000000000000",
2422
- // "last_deal_amount": "0.00000000000000000000",
2423
- // "last_deal_id": 0,
2424
- // "last_deal_price": "0.00000000000000000000",
2425
- // "last_deal_role": 0,
2426
- // "last_deal_time": 0,
2427
- // "last_deal_type": 0,
2428
- // "left": "0.0005",
2429
- // "leverage": "3",
2430
- // "maker_fee": "0.00030",
2431
- // "market": "BTCUSDT",
2432
- // "order_id": 18221659097,
2433
- // "position_id": 0,
2434
- // "position_type": 1,
2435
- // "price": "30000.00",
2436
- // "side": 2,
2437
- // "source": "api.v1",
2438
- // "stop_id": 0,
2439
- // "taker_fee": "0.00050",
2440
- // "target": 0,
2441
- // "type": 1,
2442
- // "update_time": 1651004578.618224,
2443
- // "user_id": 3620173
2444
- // },
2445
- // "message": "OK"
2446
- // }
2447
- //
2448
- // Stop Order
2449
- //
2450
- // {"code":0,"data":{"status":"success"},"message":"OK"}
2451
- //
2452
2536
  const data = this.safeDict(response, 'data', {});
2453
2537
  return this.parseOrder(data, market);
2454
2538
  }
@@ -2457,7 +2541,10 @@ class coinex extends coinex$1 {
2457
2541
  * @method
2458
2542
  * @name coinex#createOrders
2459
2543
  * @description create a list of trade orders (all orders should be of the same symbol)
2460
- * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade002_batch_limit_orders
2544
+ * @see https://docs.coinex.com/api/v2/spot/order/http/put-multi-order
2545
+ * @see https://docs.coinex.com/api/v2/spot/order/http/put-multi-stop-order
2546
+ * @see https://docs.coinex.com/api/v2/futures/order/http/put-multi-order
2547
+ * @see https://docs.coinex.com/api/v2/futures/order/http/put-multi-stop-order
2461
2548
  * @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
2462
2549
  * @param {object} [params] extra parameters specific to the api endpoint
2463
2550
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
@@ -2465,6 +2552,9 @@ class coinex extends coinex$1 {
2465
2552
  await this.loadMarkets();
2466
2553
  const ordersRequests = [];
2467
2554
  let symbol = undefined;
2555
+ let reduceOnly = false;
2556
+ let isTriggerOrder = false;
2557
+ let isStopLossOrTakeProfitTrigger = false;
2468
2558
  for (let i = 0; i < orders.length; i++) {
2469
2559
  const rawOrder = orders[i];
2470
2560
  const marketId = this.safeString(rawOrder, 'symbol');
@@ -2484,56 +2574,148 @@ class coinex extends coinex$1 {
2484
2574
  if (type !== 'limit') {
2485
2575
  throw new errors.NotSupported(this.id + ' createOrders() does not support ' + type + ' orders, only limit orders are accepted');
2486
2576
  }
2577
+ reduceOnly = this.safeValue(orderParams, 'reduceOnly');
2578
+ const triggerPrice = this.safeNumber2(orderParams, 'stopPrice', 'triggerPrice');
2579
+ const stopLossTriggerPrice = this.safeNumber(orderParams, 'stopLossPrice');
2580
+ const takeProfitTriggerPrice = this.safeNumber(orderParams, 'takeProfitPrice');
2581
+ isTriggerOrder = triggerPrice !== undefined;
2582
+ const isStopLossTriggerOrder = stopLossTriggerPrice !== undefined;
2583
+ const isTakeProfitTriggerOrder = takeProfitTriggerPrice !== undefined;
2584
+ isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder || isTakeProfitTriggerOrder;
2487
2585
  const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
2488
2586
  ordersRequests.push(orderRequest);
2489
2587
  }
2490
2588
  const market = this.market(symbol);
2491
- if (!market['spot']) {
2492
- throw new errors.NotSupported(this.id + ' createOrders() does not support ' + market['type'] + ' orders, only spot orders are accepted');
2493
- }
2494
2589
  const request = {
2495
2590
  'market': market['id'],
2496
- 'batch_orders': this.json(ordersRequests),
2591
+ 'orders': ordersRequests,
2497
2592
  };
2498
- const response = await this.v1PrivatePostOrderLimitBatch(request);
2499
- //
2500
- // {
2501
- // "code": 0,
2502
- // "data": [
2503
- // {
2504
- // "code": 0,
2505
- // "data": {
2506
- // "amount": "0.0005",
2507
- // "asset_fee": "0",
2508
- // "avg_price": "0.00",
2509
- // "client_id": "x-167673045-d34bfb41242d8fd1",
2510
- // "create_time": 1701229157,
2511
- // "deal_amount": "0",
2512
- // "deal_fee": "0",
2513
- // "deal_money": "0",
2514
- // "fee_asset": null,
2515
- // "fee_discount": "1",
2516
- // "finished_time": null,
2517
- // "id": 107745856676,
2518
- // "left": "0.0005",
2519
- // "maker_fee_rate": "0.002",
2520
- // "market": "BTCUSDT",
2521
- // "money_fee": "0",
2522
- // "order_type": "limit",
2523
- // "price": "23000",
2524
- // "source_id": "",
2525
- // "status": "not_deal",
2526
- // "stock_fee": "0",
2527
- // "taker_fee_rate": "0.002",
2528
- // "type": "buy"
2529
- // },
2530
- // "message": "OK"
2531
- // },
2532
- // ],
2533
- // "message": "Success"
2534
- // }
2535
- //
2536
- const data = this.safeValue(response, 'data', []);
2593
+ let response = undefined;
2594
+ if (market['spot']) {
2595
+ if (isTriggerOrder) {
2596
+ response = await this.v2PrivatePostSpotBatchStopOrder(request);
2597
+ //
2598
+ // {
2599
+ // "code": 0,
2600
+ // "data": [
2601
+ // {
2602
+ // "code": 0,
2603
+ // "data": {
2604
+ // "stop_id": 117186257510
2605
+ // },
2606
+ // "message": "OK"
2607
+ // },
2608
+ // ],
2609
+ // "message": "OK"
2610
+ // }
2611
+ //
2612
+ }
2613
+ else {
2614
+ response = await this.v2PrivatePostSpotBatchOrder(request);
2615
+ //
2616
+ // {
2617
+ // "code": 0,
2618
+ // "data": [
2619
+ // {
2620
+ // "amount": "0.0001",
2621
+ // "base_fee": "0",
2622
+ // "ccy": "BTC",
2623
+ // "client_id": "x-167673045-f3651372049dab0d",
2624
+ // "created_at": 1714121403450,
2625
+ // "discount_fee": "0",
2626
+ // "filled_amount": "0",
2627
+ // "filled_value": "0",
2628
+ // "last_fill_amount": "0",
2629
+ // "last_fill_price": "0",
2630
+ // "maker_fee_rate": "0.002",
2631
+ // "market": "BTCUSDT",
2632
+ // "market_type": "SPOT",
2633
+ // "order_id": 117185362233,
2634
+ // "price": "61000",
2635
+ // "quote_fee": "0",
2636
+ // "side": "buy",
2637
+ // "taker_fee_rate": "0.002",
2638
+ // "type": "limit",
2639
+ // "unfilled_amount": "0.0001",
2640
+ // "updated_at": 1714121403450
2641
+ // },
2642
+ // {
2643
+ // "code": 3109,
2644
+ // "data": null,
2645
+ // "message": "balance not enough"
2646
+ // }
2647
+ // ],
2648
+ // "message": "OK"
2649
+ // }
2650
+ //
2651
+ }
2652
+ }
2653
+ else {
2654
+ if (isTriggerOrder) {
2655
+ response = await this.v2PrivatePostFuturesBatchStopOrder(request);
2656
+ //
2657
+ // {
2658
+ // "code": 0,
2659
+ // "data": [
2660
+ // {
2661
+ // "code": 0,
2662
+ // "data": {
2663
+ // "stop_id": 136919625994
2664
+ // },
2665
+ // "message": "OK"
2666
+ // },
2667
+ // ],
2668
+ // "message": "OK"
2669
+ // }
2670
+ //
2671
+ }
2672
+ else if (isStopLossOrTakeProfitTrigger) {
2673
+ throw new errors.NotSupported(this.id + ' createOrders() does not support stopLossPrice or takeProfitPrice orders');
2674
+ }
2675
+ else {
2676
+ if (reduceOnly) {
2677
+ throw new errors.NotSupported(this.id + ' createOrders() does not support reduceOnly orders');
2678
+ }
2679
+ else {
2680
+ response = await this.v2PrivatePostFuturesBatchOrder(request);
2681
+ //
2682
+ // {
2683
+ // "code": 0,
2684
+ // "data": [
2685
+ // {
2686
+ // "code": 0,
2687
+ // "data": {
2688
+ // "amount": "0.0001",
2689
+ // "client_id": "x-167673045-2cb7436f3462a654",
2690
+ // "created_at": 1714122832493,
2691
+ // "fee": "0",
2692
+ // "fee_ccy": "USDT",
2693
+ // "filled_amount": "0",
2694
+ // "filled_value": "0",
2695
+ // "last_filled_amount": "0",
2696
+ // "last_filled_price": "0",
2697
+ // "maker_fee_rate": "0.0003",
2698
+ // "market": "BTCUSDT",
2699
+ // "market_type": "FUTURES",
2700
+ // "order_id": 136918835063,
2701
+ // "price": "61000",
2702
+ // "realized_pnl": "0",
2703
+ // "side": "buy",
2704
+ // "taker_fee_rate": "0.0005",
2705
+ // "type": "limit",
2706
+ // "unfilled_amount": "0.0001",
2707
+ // "updated_at": 1714122832493
2708
+ // },
2709
+ // "message": "OK"
2710
+ // },
2711
+ // ],
2712
+ // "message": "OK"
2713
+ // }
2714
+ //
2715
+ }
2716
+ }
2717
+ }
2718
+ const data = this.safeList(response, 'data', []);
2537
2719
  const results = [];
2538
2720
  for (let i = 0; i < data.length; i++) {
2539
2721
  const entry = data[i];
@@ -2547,9 +2729,16 @@ class coinex extends coinex$1 {
2547
2729
  status = 'open';
2548
2730
  }
2549
2731
  }
2550
- const item = this.safeValue(entry, 'data', {});
2551
- item['status'] = status;
2552
- const order = this.parseOrder(item, market);
2732
+ const innerData = this.safeDict(entry, 'data', {});
2733
+ let order = undefined;
2734
+ if (market['spot'] && !isTriggerOrder) {
2735
+ entry['status'] = status;
2736
+ order = this.parseOrder(entry, market);
2737
+ }
2738
+ else {
2739
+ innerData['status'] = status;
2740
+ order = this.parseOrder(innerData, market);
2741
+ }
2553
2742
  results.push(order);
2554
2743
  }
2555
2744
  return results;
@@ -5821,18 +6010,25 @@ class coinex extends coinex$1 {
5821
6010
  this.checkRequiredCredentials();
5822
6011
  query = this.keysort(query);
5823
6012
  const urlencoded = this.rawencode(query);
5824
- const preparedString = method + '/' + version + '/' + path + '?' + urlencoded + nonce + this.secret;
6013
+ let preparedString = method + '/' + version + '/' + path;
6014
+ if (method === 'POST') {
6015
+ body = this.json(query);
6016
+ preparedString += body;
6017
+ }
6018
+ else if (urlencoded) {
6019
+ preparedString += '?' + urlencoded;
6020
+ }
6021
+ preparedString += nonce + this.secret;
5825
6022
  const signature = this.hash(this.encode(preparedString), sha256.sha256);
5826
6023
  headers = {
5827
6024
  'X-COINEX-KEY': this.apiKey,
5828
6025
  'X-COINEX-SIGN': signature,
5829
6026
  'X-COINEX-TIMESTAMP': nonce,
5830
6027
  };
5831
- if ((method === 'GET') || (method === 'DELETE') || (method === 'PUT')) {
5832
- url += '?' + urlencoded;
5833
- }
5834
- else {
5835
- body = this.json(query);
6028
+ if (method !== 'POST') {
6029
+ if (urlencoded) {
6030
+ url += '?' + urlencoded;
6031
+ }
5836
6032
  }
5837
6033
  }
5838
6034
  }