ccxt 4.3.10 → 4.3.12

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 (84) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/ccxt.js +1 -1
  3. package/dist/cjs/src/base/Exchange.js +15 -0
  4. package/dist/cjs/src/bigone.js +22 -22
  5. package/dist/cjs/src/binance.js +5 -5
  6. package/dist/cjs/src/bingx.js +2 -2
  7. package/dist/cjs/src/bitget.js +7 -4
  8. package/dist/cjs/src/bitmart.js +3 -8
  9. package/dist/cjs/src/bitmex.js +2 -2
  10. package/dist/cjs/src/blofin.js +2 -0
  11. package/dist/cjs/src/bybit.js +81 -71
  12. package/dist/cjs/src/coinbase.js +8 -8
  13. package/dist/cjs/src/coinbaseinternational.js +2 -2
  14. package/dist/cjs/src/coinex.js +513 -449
  15. package/dist/cjs/src/coinlist.js +12 -12
  16. package/dist/cjs/src/coinmetro.js +2 -2
  17. package/dist/cjs/src/cryptocom.js +16 -16
  18. package/dist/cjs/src/gate.js +2 -2
  19. package/dist/cjs/src/hitbtc.js +3 -3
  20. package/dist/cjs/src/htx.js +3 -7
  21. package/dist/cjs/src/indodax.js +2 -2
  22. package/dist/cjs/src/kraken.js +3 -1
  23. package/dist/cjs/src/kucoin.js +4 -4
  24. package/dist/cjs/src/kucoinfutures.js +6 -6
  25. package/dist/cjs/src/mexc.js +5 -5
  26. package/dist/cjs/src/okx.js +6 -6
  27. package/dist/cjs/src/poloniexfutures.js +4 -4
  28. package/dist/cjs/src/pro/bitget.js +140 -89
  29. package/dist/cjs/src/pro/bybit.js +196 -11
  30. package/dist/cjs/src/pro/coinbase.js +107 -29
  31. package/dist/cjs/src/pro/mexc.js +21 -1
  32. package/dist/cjs/src/probit.js +2 -2
  33. package/dist/cjs/src/whitebit.js +76 -1
  34. package/dist/cjs/src/woo.js +2 -2
  35. package/js/ccxt.d.ts +1 -1
  36. package/js/ccxt.js +1 -1
  37. package/js/src/abstract/blofin.d.ts +2 -0
  38. package/js/src/base/Exchange.d.ts +10 -6
  39. package/js/src/base/Exchange.js +15 -0
  40. package/js/src/base/types.d.ts +17 -2
  41. package/js/src/bigone.js +22 -22
  42. package/js/src/binance.d.ts +2 -9
  43. package/js/src/binance.js +5 -5
  44. package/js/src/bingx.js +2 -2
  45. package/js/src/bitget.d.ts +4 -31
  46. package/js/src/bitget.js +7 -4
  47. package/js/src/bitmart.d.ts +4 -24
  48. package/js/src/bitmart.js +3 -8
  49. package/js/src/bitmex.js +2 -2
  50. package/js/src/blofin.js +2 -0
  51. package/js/src/bybit.d.ts +7 -9
  52. package/js/src/bybit.js +81 -71
  53. package/js/src/coinbase.js +8 -8
  54. package/js/src/coinbaseinternational.js +2 -2
  55. package/js/src/coinex.d.ts +4 -24
  56. package/js/src/coinex.js +513 -449
  57. package/js/src/coinlist.js +12 -12
  58. package/js/src/coinmetro.js +2 -2
  59. package/js/src/cryptocom.js +16 -16
  60. package/js/src/digifinex.d.ts +3 -10
  61. package/js/src/gate.js +2 -2
  62. package/js/src/hitbtc.js +3 -3
  63. package/js/src/htx.d.ts +3 -13
  64. package/js/src/htx.js +3 -7
  65. package/js/src/indodax.js +2 -2
  66. package/js/src/kraken.js +3 -1
  67. package/js/src/kucoin.js +4 -4
  68. package/js/src/kucoinfutures.js +6 -6
  69. package/js/src/mexc.js +5 -5
  70. package/js/src/okx.d.ts +3 -10
  71. package/js/src/okx.js +6 -6
  72. package/js/src/poloniexfutures.js +4 -4
  73. package/js/src/pro/bitget.js +140 -89
  74. package/js/src/pro/bybit.d.ts +5 -1
  75. package/js/src/pro/bybit.js +196 -11
  76. package/js/src/pro/coinbase.d.ts +4 -0
  77. package/js/src/pro/coinbase.js +107 -29
  78. package/js/src/pro/mexc.js +21 -1
  79. package/js/src/probit.js +2 -2
  80. package/js/src/whitebit.d.ts +1 -0
  81. package/js/src/whitebit.js +76 -1
  82. package/js/src/woo.js +2 -2
  83. package/package.json +6 -5
  84. package/dist/cjs/src/flowbtc.js +0 -35
@@ -691,55 +691,70 @@ class bitget extends bitget$1 {
691
691
  // "side": "buy",
692
692
  // "tradeId": "1116461060594286593"
693
693
  // }
694
+ // swap private
694
695
  //
695
- // order with trade in it
696
- // {
697
- // accBaseVolume: '0.1',
698
- // baseVolume: '0.1',
699
- // cTime: '1709221342922',
700
- // clientOid: '1147122943507734528',
701
- // enterPointSource: 'API',
702
- // feeDetail: [Array],
703
- // fillFee: '-0.0049578',
704
- // fillFeeCoin: 'USDT',
705
- // fillNotionalUsd: '8.263',
706
- // fillPrice: '82.63',
707
- // fillTime: '1709221342986',
708
- // force: 'gtc',
709
- // instId: 'LTCUSDT',
710
- // leverage: '10',
711
- // marginCoin: 'USDT',
712
- // marginMode: 'crossed',
713
- // notionalUsd: '8.268',
714
- // orderId: '1147122943499345921',
715
- // orderType: 'market',
716
- // pnl: '0',
717
- // posMode: 'hedge_mode',
718
- // posSide: 'short',
719
- // price: '0',
720
- // priceAvg: '82.63',
721
- // reduceOnly: 'no',
722
- // side: 'sell',
723
- // size: '0.1',
724
- // status: 'filled',
725
- // tradeId: '1147122943772479563',
726
- // tradeScope: 'T',
727
- // tradeSide: 'open',
728
- // uTime: '1709221342986'
729
- // }
696
+ // {
697
+ // "orderId": "1169142761031114781",
698
+ // "tradeId": "1169142761312637004",
699
+ // "symbol": "LTCUSDT",
700
+ // "orderType": "market",
701
+ // "side": "buy",
702
+ // "price": "80.87",
703
+ // "baseVolume": "0.1",
704
+ // "quoteVolume": "8.087",
705
+ // "profit": "0",
706
+ // "tradeSide": "open",
707
+ // "posMode": "hedge_mode",
708
+ // "tradeScope": "taker",
709
+ // "feeDetail": [
710
+ // {
711
+ // "feeCoin": "USDT",
712
+ // "deduction": "no",
713
+ // "totalDeductionFee": "0",
714
+ // "totalFee": "-0.0048522"
715
+ // }
716
+ // ],
717
+ // "cTime": "1714471276596",
718
+ // "uTime": "1714471276596"
719
+ // }
720
+ // spot private
721
+ // {
722
+ // "orderId": "1169142457356959747",
723
+ // "tradeId": "1169142457636958209",
724
+ // "symbol": "LTCUSDT",
725
+ // "orderType": "market",
726
+ // "side": "buy",
727
+ // "priceAvg": "81.069",
728
+ // "size": "0.074",
729
+ // "amount": "5.999106",
730
+ // "tradeScope": "taker",
731
+ // "feeDetail": [
732
+ // {
733
+ // "feeCoin": "LTC",
734
+ // "deduction": "no",
735
+ // "totalDeductionFee": "0",
736
+ // "totalFee": "0.000074"
737
+ // }
738
+ // ],
739
+ // "cTime": "1714471204194",
740
+ // "uTime": "1714471204194"
741
+ // }
730
742
  //
731
- const instId = this.safeString(trade, 'instId');
743
+ const instId = this.safeString2(trade, 'symbol', 'instId');
744
+ const posMode = this.safeString(trade, 'posMode');
745
+ const defaultType = (posMode !== undefined) ? 'contract' : 'spot';
732
746
  if (market === undefined) {
733
- market = this.safeMarket(instId, undefined, undefined, 'contract');
747
+ market = this.safeMarket(instId, undefined, undefined, defaultType);
734
748
  }
735
749
  const timestamp = this.safeIntegerN(trade, ['uTime', 'cTime', 'ts']);
736
- const feeCost = this.safeString(trade, 'fillFee');
750
+ const feeDetail = this.safeList(trade, 'feeDetail', []);
751
+ const first = this.safeDict(feeDetail, 0);
737
752
  let fee = undefined;
738
- if (feeCost !== undefined) {
739
- const feeCurrencyId = this.safeString(trade, 'fillFeeCoin');
753
+ if (first !== undefined) {
754
+ const feeCurrencyId = this.safeString(first, 'feeCoin');
740
755
  const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId);
741
756
  fee = {
742
- 'cost': Precise["default"].stringAbs(feeCost),
757
+ 'cost': Precise["default"].stringAbs(this.safeString(first, 'totalFee')),
743
758
  'currency': feeCurrencyCode,
744
759
  };
745
760
  }
@@ -750,12 +765,12 @@ class bitget extends bitget$1 {
750
765
  'timestamp': timestamp,
751
766
  'datetime': this.iso8601(timestamp),
752
767
  'symbol': market['symbol'],
753
- 'type': undefined,
768
+ 'type': this.safeString(trade, 'orderType'),
754
769
  'side': this.safeString(trade, 'side'),
755
- 'takerOrMaker': undefined,
770
+ 'takerOrMaker': this.safeString(trade, 'tradeScope'),
756
771
  'price': this.safeString2(trade, 'priceAvg', 'price'),
757
- 'amount': this.safeString(trade, 'size'),
758
- 'cost': this.safeString(trade, 'fillNotionalUsd'),
772
+ 'amount': this.safeString2(trade, 'size', 'baseVolume'),
773
+ 'cost': this.safeString2(trade, 'amount', 'quoteVolume'),
759
774
  'fee': fee,
760
775
  }, market);
761
776
  }
@@ -1161,9 +1176,6 @@ class bitget extends bitget$1 {
1161
1176
  const marketSymbols = {};
1162
1177
  for (let i = 0; i < data.length; i++) {
1163
1178
  const order = data[i];
1164
- if ('tradeId' in order) {
1165
- this.handleMyTrades(client, order);
1166
- }
1167
1179
  const marketId = this.safeString(order, 'instId');
1168
1180
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
1169
1181
  const parsed = this.parseWsOrder(order, market);
@@ -1363,8 +1375,6 @@ class bitget extends bitget$1 {
1363
1375
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1364
1376
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1365
1377
  */
1366
- // only contracts stream provides the trade info consistently in between order updates
1367
- // the spot stream only provides on limit orders updates so we can't support it for spot
1368
1378
  await this.loadMarkets();
1369
1379
  let market = undefined;
1370
1380
  let messageHash = 'myTrades';
@@ -1373,17 +1383,12 @@ class bitget extends bitget$1 {
1373
1383
  symbol = market['symbol'];
1374
1384
  messageHash = messageHash + ':' + symbol;
1375
1385
  }
1376
- let type = undefined;
1377
- [type, params] = this.handleMarketTypeAndParams('watchMyTrades', market, params);
1378
- if (type === 'spot') {
1379
- throw new errors.NotSupported(this.id + ' watchMyTrades is not supported for ' + type + ' markets.');
1380
- }
1381
1386
  let instType = undefined;
1382
1387
  [instType, params] = this.getInstType(market, params);
1383
- const subscriptionHash = 'order:trades';
1388
+ const subscriptionHash = 'fill:' + instType;
1384
1389
  const args = {
1385
1390
  'instType': instType,
1386
- 'channel': 'orders',
1391
+ 'channel': 'fill',
1387
1392
  'instId': 'default',
1388
1393
  };
1389
1394
  const trades = await this.watchPrivate(messageHash, subscriptionHash, args, params);
@@ -1394,34 +1399,74 @@ class bitget extends bitget$1 {
1394
1399
  }
1395
1400
  handleMyTrades(client, message) {
1396
1401
  //
1397
- // order and trade mixin (contract)
1398
- //
1402
+ // spot
1403
+ // {
1404
+ // "action": "snapshot",
1405
+ // "arg": {
1406
+ // "instType": "SPOT",
1407
+ // "channel": "fill",
1408
+ // "instId": "default"
1409
+ // },
1410
+ // "data": [
1411
+ // {
1412
+ // "orderId": "1169142457356959747",
1413
+ // "tradeId": "1169142457636958209",
1414
+ // "symbol": "LTCUSDT",
1415
+ // "orderType": "market",
1416
+ // "side": "buy",
1417
+ // "priceAvg": "81.069",
1418
+ // "size": "0.074",
1419
+ // "amount": "5.999106",
1420
+ // "tradeScope": "taker",
1421
+ // "feeDetail": [
1422
+ // {
1423
+ // "feeCoin": "LTC",
1424
+ // "deduction": "no",
1425
+ // "totalDeductionFee": "0",
1426
+ // "totalFee": "0.000074"
1427
+ // }
1428
+ // ],
1429
+ // "cTime": "1714471204194",
1430
+ // "uTime": "1714471204194"
1431
+ // }
1432
+ // ],
1433
+ // "ts": 1714471204270
1434
+ // }
1435
+ // swap
1399
1436
  // {
1400
- // "accBaseVolume": "0",
1401
- // "cTime": "1701920553759",
1402
- // "clientOid": "1116501214318198793",
1403
- // "enterPointSource": "WEB",
1404
- // "feeDetail": [{
1405
- // "feeCoin": "USDT",
1406
- // "fee": "-0.162003"
1407
- // }],
1408
- // "force": "gtc",
1409
- // "instId": "BTCUSDT",
1410
- // "leverage": "20",
1411
- // "marginCoin": "USDT",
1412
- // "marginMode": "isolated",
1413
- // "notionalUsd": "105",
1414
- // "orderId": "1116501214293032964",
1415
- // "orderType": "limit",
1416
- // "posMode": "hedge_mode",
1417
- // "posSide": "long",
1418
- // "price": "35000",
1419
- // "reduceOnly": "no",
1420
- // "side": "buy",
1421
- // "size": "0.003",
1422
- // "status": "canceled",
1423
- // "tradeSide": "open",
1424
- // "uTime": "1701920595866"
1437
+ // "action": "snapshot",
1438
+ // "arg": {
1439
+ // "instType": "USDT-FUTURES",
1440
+ // "channel": "fill",
1441
+ // "instId": "default"
1442
+ // },
1443
+ // "data": [
1444
+ // {
1445
+ // "orderId": "1169142761031114781",
1446
+ // "tradeId": "1169142761312637004",
1447
+ // "symbol": "LTCUSDT",
1448
+ // "orderType": "market",
1449
+ // "side": "buy",
1450
+ // "price": "80.87",
1451
+ // "baseVolume": "0.1",
1452
+ // "quoteVolume": "8.087",
1453
+ // "profit": "0",
1454
+ // "tradeSide": "open",
1455
+ // "posMode": "hedge_mode",
1456
+ // "tradeScope": "taker",
1457
+ // "feeDetail": [
1458
+ // {
1459
+ // "feeCoin": "USDT",
1460
+ // "deduction": "no",
1461
+ // "totalDeductionFee": "0",
1462
+ // "totalFee": "-0.0048522"
1463
+ // }
1464
+ // ],
1465
+ // "cTime": "1714471276596",
1466
+ // "uTime": "1714471276596"
1467
+ // }
1468
+ // ],
1469
+ // "ts": 1714471276629
1425
1470
  // }
1426
1471
  //
1427
1472
  if (this.myTrades === undefined) {
@@ -1429,13 +1474,18 @@ class bitget extends bitget$1 {
1429
1474
  this.myTrades = new Cache.ArrayCache(limit);
1430
1475
  }
1431
1476
  const stored = this.myTrades;
1432
- const parsed = this.parseWsTrade(message);
1433
- stored.append(parsed);
1434
- const symbol = parsed['symbol'];
1477
+ const data = this.safeList(message, 'data', []);
1478
+ const length = data.length;
1435
1479
  const messageHash = 'myTrades';
1480
+ for (let i = 0; i < length; i++) {
1481
+ const trade = data[i];
1482
+ const parsed = this.parseWsTrade(trade);
1483
+ stored.append(parsed);
1484
+ const symbol = parsed['symbol'];
1485
+ const symbolSpecificMessageHash = 'myTrades:' + symbol;
1486
+ client.resolve(stored, symbolSpecificMessageHash);
1487
+ }
1436
1488
  client.resolve(stored, messageHash);
1437
- const symbolSpecificMessageHash = 'myTrades:' + symbol;
1438
- client.resolve(stored, symbolSpecificMessageHash);
1439
1489
  }
1440
1490
  async watchBalance(params = {}) {
1441
1491
  /**
@@ -1718,6 +1768,7 @@ class bitget extends bitget$1 {
1718
1768
  const methods = {
1719
1769
  'ticker': this.handleTicker,
1720
1770
  'trade': this.handleTrades,
1771
+ 'fill': this.handleMyTrades,
1721
1772
  'orders': this.handleOrder,
1722
1773
  'ordersAlgo': this.handleOrder,
1723
1774
  'account': this.handleBalance,
@@ -50,6 +50,7 @@ class bybit extends bybit$1 {
50
50
  },
51
51
  'contract': 'wss://stream.{hostname}/v5/private',
52
52
  'usdc': 'wss://stream.{hostname}/trade/option/usdc/private/v1',
53
+ 'trade': 'wss://stream-testnet.bybit.com/v5/trade',
53
54
  },
54
55
  },
55
56
  },
@@ -68,6 +69,7 @@ class bybit extends bybit$1 {
68
69
  },
69
70
  'contract': 'wss://stream-testnet.{hostname}/v5/private',
70
71
  'usdc': 'wss://stream-testnet.{hostname}/trade/option/usdc/private/v1',
72
+ 'trade': 'wss://stream-testnet.bybit.com/v5/trade',
71
73
  },
72
74
  },
73
75
  },
@@ -169,6 +171,133 @@ class bybit extends bybit$1 {
169
171
  params = this.omit(params, ['type', 'subType', 'settle', 'defaultSettle', 'unifiedMargin']);
170
172
  return params;
171
173
  }
174
+ async createOrderWs(symbol, type, side, amount, price = undefined, params = {}) {
175
+ /**
176
+ * @method
177
+ * @name bybit#createOrderWs
178
+ * @description create a trade order
179
+ * @see https://bybit-exchange.github.io/docs/v5/order/create-order
180
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/trade/guideline#createamendcancel-order
181
+ * @param {string} symbol unified symbol of the market to create an order in
182
+ * @param {string} type 'market' or 'limit'
183
+ * @param {string} side 'buy' or 'sell'
184
+ * @param {float} amount how much of currency you want to trade in units of base currency
185
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
186
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
187
+ * @param {string} [params.timeInForce] "GTC", "IOC", "FOK"
188
+ * @param {bool} [params.postOnly] true or false whether the order is post-only
189
+ * @param {bool} [params.reduceOnly] true or false whether the order is reduce-only
190
+ * @param {string} [params.positionIdx] *contracts only* 0 for one-way mode, 1 buy side of hedged mode, 2 sell side of hedged mode
191
+ * @param {boolean} [params.isLeverage] *unified spot only* false then spot trading true then margin trading
192
+ * @param {string} [params.tpslMode] *contract only* 'full' or 'partial'
193
+ * @param {string} [params.mmp] *option only* market maker protection
194
+ * @param {string} [params.triggerDirection] *contract only* the direction for trigger orders, 'above' or 'below'
195
+ * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
196
+ * @param {float} [params.stopLossPrice] The price at which a stop loss order is triggered at
197
+ * @param {float} [params.takeProfitPrice] The price at which a take profit order is triggered at
198
+ * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered
199
+ * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
200
+ * @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered
201
+ * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
202
+ * @param {string} [params.trailingAmount] the quote amount to trail away from the current market price
203
+ * @param {string} [params.trailingTriggerPrice] the price to trigger a trailing order, default uses the price argument
204
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
205
+ */
206
+ await this.loadMarkets();
207
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params, true);
208
+ const url = this.urls['api']['ws']['private']['trade'];
209
+ await this.authenticate(url);
210
+ const requestId = this.requestId().toString();
211
+ const request = {
212
+ 'op': 'order.create',
213
+ 'reqId': requestId,
214
+ 'args': [
215
+ orderRequest,
216
+ ],
217
+ 'header': {
218
+ 'X-BAPI-TIMESTAMP': this.milliseconds().toString(),
219
+ 'X-BAPI-RECV-WINDOW': this.options['recvWindow'].toString(),
220
+ },
221
+ };
222
+ return await this.watch(url, requestId, request, requestId, true);
223
+ }
224
+ async editOrderWs(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
225
+ /**
226
+ * @method
227
+ * @name bybit#editOrderWs
228
+ * @description edit a trade order
229
+ * @see https://bybit-exchange.github.io/docs/v5/order/amend-order
230
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/trade/guideline#createamendcancel-order
231
+ * @param {string} id cancel order id
232
+ * @param {string} symbol unified symbol of the market to create an order in
233
+ * @param {string} type 'market' or 'limit'
234
+ * @param {string} side 'buy' or 'sell'
235
+ * @param {float} amount how much of currency you want to trade in units of base currency
236
+ * @param {float} price the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
237
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
238
+ * @param {float} [params.triggerPrice] The price that a trigger order is triggered at
239
+ * @param {float} [params.stopLossPrice] The price that a stop loss order is triggered at
240
+ * @param {float} [params.takeProfitPrice] The price that a take profit order is triggered at
241
+ * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice that the attached take profit order will be triggered
242
+ * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
243
+ * @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice that the attached stop loss order will be triggered
244
+ * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
245
+ * @param {string} [params.triggerBy] 'IndexPrice', 'MarkPrice' or 'LastPrice', default is 'LastPrice', required if no initial value for triggerPrice
246
+ * @param {string} [params.slTriggerBy] 'IndexPrice', 'MarkPrice' or 'LastPrice', default is 'LastPrice', required if no initial value for stopLoss
247
+ * @param {string} [params.tpTriggerby] 'IndexPrice', 'MarkPrice' or 'LastPrice', default is 'LastPrice', required if no initial value for takeProfit
248
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
249
+ */
250
+ await this.loadMarkets();
251
+ const orderRequest = this.editOrderRequest(id, symbol, type, side, amount, price, params);
252
+ const url = this.urls['api']['ws']['private']['trade'];
253
+ await this.authenticate(url);
254
+ const requestId = this.requestId().toString();
255
+ const request = {
256
+ 'op': 'order.amend',
257
+ 'reqId': requestId,
258
+ 'args': [
259
+ orderRequest,
260
+ ],
261
+ 'header': {
262
+ 'X-BAPI-TIMESTAMP': this.milliseconds().toString(),
263
+ 'X-BAPI-RECV-WINDOW': this.options['recvWindow'].toString(),
264
+ },
265
+ };
266
+ return await this.watch(url, requestId, request, requestId, true);
267
+ }
268
+ async cancelOrderWs(id, symbol = undefined, params = {}) {
269
+ /**
270
+ * @method
271
+ * @name bybit#cancelOrderWs
272
+ * @description cancels an open order
273
+ * @see https://bybit-exchange.github.io/docs/v5/order/cancel-order
274
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/trade/guideline#createamendcancel-order
275
+ * @param {string} id order id
276
+ * @param {string} symbol unified symbol of the market the order was made in
277
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
278
+ * @param {boolean} [params.stop] *spot only* whether the order is a stop order
279
+ * @param {string} [params.orderFilter] *spot only* 'Order' or 'StopOrder' or 'tpslOrder'
280
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
281
+ */
282
+ await this.loadMarkets();
283
+ const orderRequest = this.cancelOrderRequest(id, symbol, params);
284
+ const url = this.urls['api']['ws']['private']['trade'];
285
+ await this.authenticate(url);
286
+ const requestId = this.requestId().toString();
287
+ delete orderRequest['orderFilter'];
288
+ const request = {
289
+ 'op': 'order.cancel',
290
+ 'reqId': requestId,
291
+ 'args': [
292
+ orderRequest,
293
+ ],
294
+ 'header': {
295
+ 'X-BAPI-TIMESTAMP': this.milliseconds().toString(),
296
+ 'X-BAPI-RECV-WINDOW': this.options['recvWindow'].toString(),
297
+ },
298
+ };
299
+ return await this.watch(url, requestId, request, requestId, true);
300
+ }
172
301
  async watchTicker(symbol, params = {}) {
173
302
  /**
174
303
  * @method
@@ -1101,6 +1230,32 @@ class bybit extends bybit$1 {
1101
1230
  }
1102
1231
  return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
1103
1232
  }
1233
+ handleOrderWs(client, message) {
1234
+ //
1235
+ // {
1236
+ // "reqId":"1",
1237
+ // "retCode":0,
1238
+ // "retMsg":"OK",
1239
+ // "op":"order.create",
1240
+ // "data":{
1241
+ // "orderId":"1673523595617593600",
1242
+ // "orderLinkId":"1673523595617593601"
1243
+ // },
1244
+ // "header":{
1245
+ // "X-Bapi-Limit":"20",
1246
+ // "X-Bapi-Limit-Status":"19",
1247
+ // "X-Bapi-Limit-Reset-Timestamp":"1714235558880",
1248
+ // "Traceid":"584a06d373f2fdcb3a4dfdd81d27df11",
1249
+ // "Timenow":"1714235558881"
1250
+ // },
1251
+ // "connId":"cojidqec0hv9fgvhtbt0-40e"
1252
+ // }
1253
+ //
1254
+ const messageHash = this.safeString(message, 'reqId');
1255
+ const data = this.safeDict(message, 'data');
1256
+ const order = this.parseOrder(data);
1257
+ client.resolve(order, messageHash);
1258
+ }
1104
1259
  handleOrder(client, message) {
1105
1260
  //
1106
1261
  // spot
@@ -1708,11 +1863,32 @@ class bybit extends bybit$1 {
1708
1863
  //
1709
1864
  // { code: '-10009', desc: "Invalid period!" }
1710
1865
  //
1711
- const code = this.safeString2(message, 'code', 'ret_code');
1866
+ // {
1867
+ // "reqId":"1",
1868
+ // "retCode":170131,
1869
+ // "retMsg":"Insufficient balance.",
1870
+ // "op":"order.create",
1871
+ // "data":{
1872
+ //
1873
+ // },
1874
+ // "header":{
1875
+ // "X-Bapi-Limit":"20",
1876
+ // "X-Bapi-Limit-Status":"19",
1877
+ // "X-Bapi-Limit-Reset-Timestamp":"1714236608944",
1878
+ // "Traceid":"3d7168a137bf32a947b7e5e6a575ac7f",
1879
+ // "Timenow":"1714236608946"
1880
+ // },
1881
+ // "connId":"cojifin88smerbj9t560-406"
1882
+ // }
1883
+ //
1884
+ const code = this.safeStringN(message, ['code', 'ret_code', 'retCode']);
1712
1885
  try {
1713
- if (code !== undefined) {
1886
+ if (code !== undefined && code !== '0') {
1714
1887
  const feedback = this.id + ' ' + this.json(message);
1715
1888
  this.throwExactlyMatchedException(this.exceptions['exact'], code, feedback);
1889
+ const msg = this.safeString2(message, 'retMsg', 'ret_msg');
1890
+ this.throwBroadlyMatchedException(this.exceptions['broad'], msg, feedback);
1891
+ throw new errors.ExchangeError(feedback);
1716
1892
  }
1717
1893
  const success = this.safeValue(message, 'success');
1718
1894
  if (success !== undefined && !success) {
@@ -1737,7 +1913,8 @@ class bybit extends bybit$1 {
1737
1913
  }
1738
1914
  }
1739
1915
  else {
1740
- client.reject(error);
1916
+ const messageHash = this.safeString(message, 'reqId');
1917
+ client.reject(error, messageHash);
1741
1918
  }
1742
1919
  return true;
1743
1920
  }
@@ -1759,17 +1936,12 @@ class bybit extends bybit$1 {
1759
1936
  return;
1760
1937
  }
1761
1938
  // pong
1762
- const op = this.safeString(message, 'op');
1763
- if (op === 'pong') {
1764
- this.handlePong(client, message);
1765
- return;
1766
- }
1767
1939
  const event = this.safeString(message, 'event');
1768
1940
  if (event === 'sub') {
1769
1941
  this.handleSubscriptionStatus(client, message);
1770
1942
  return;
1771
1943
  }
1772
- const topic = this.safeString(message, 'topic', '');
1944
+ const topic = this.safeString2(message, 'topic', 'op');
1773
1945
  const methods = {
1774
1946
  'orderbook': this.handleOrderBook,
1775
1947
  'kline': this.handleOHLCV,
@@ -1785,6 +1957,11 @@ class bybit extends bybit$1 {
1785
1957
  'ticketInfo': this.handleMyTrades,
1786
1958
  'user.openapi.perp.trade': this.handleMyTrades,
1787
1959
  'position': this.handlePositions,
1960
+ 'pong': this.handlePong,
1961
+ 'order.create': this.handleOrderWs,
1962
+ 'order.amend': this.handleOrderWs,
1963
+ 'order.cancel': this.handleOrderWs,
1964
+ 'auth': this.handleAuthenticate,
1788
1965
  };
1789
1966
  const exacMethod = this.safeValue(methods, topic);
1790
1967
  if (exacMethod !== undefined) {
@@ -1802,7 +1979,7 @@ class bybit extends bybit$1 {
1802
1979
  }
1803
1980
  // unified auth acknowledgement
1804
1981
  const type = this.safeString(message, 'type');
1805
- if ((op === 'auth') || (type === 'AUTH_RESP')) {
1982
+ if (type === 'AUTH_RESP') {
1806
1983
  this.handleAuthenticate(client, message);
1807
1984
  }
1808
1985
  }
@@ -1835,9 +2012,17 @@ class bybit extends bybit$1 {
1835
2012
  // "conn_id": "ce3dpomvha7dha97tvp0-2xh"
1836
2013
  // }
1837
2014
  //
2015
+ // {
2016
+ // "retCode":0,
2017
+ // "retMsg":"OK",
2018
+ // "op":"auth",
2019
+ // "connId":"cojifin88smerbj9t560-404"
2020
+ // }
2021
+ //
1838
2022
  const success = this.safeValue(message, 'success');
2023
+ const code = this.safeInteger(message, 'retCode');
1839
2024
  const messageHash = 'authenticated';
1840
- if (success) {
2025
+ if (success || code === 0) {
1841
2026
  const future = this.safeValue(client.futures, messageHash);
1842
2027
  future.resolve(true);
1843
2028
  }