ccxt 4.3.4 → 4.3.6

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 (71) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/ccxt.js +1 -1
  3. package/dist/cjs/src/base/Exchange.js +299 -6
  4. package/dist/cjs/src/binance.js +24 -17
  5. package/dist/cjs/src/bingx.js +45 -0
  6. package/dist/cjs/src/bitmex.js +24 -0
  7. package/dist/cjs/src/bybit.js +86 -0
  8. package/dist/cjs/src/coinbase.js +5 -4
  9. package/dist/cjs/src/coinex.js +30 -32
  10. package/dist/cjs/src/cryptocom.js +32 -0
  11. package/dist/cjs/src/htx.js +28 -0
  12. package/dist/cjs/src/hyperliquid.js +40 -0
  13. package/dist/cjs/src/kraken.js +30 -0
  14. package/dist/cjs/src/krakenfutures.js +28 -0
  15. package/dist/cjs/src/kucoin.js +53 -3
  16. package/dist/cjs/src/kucoinfutures.js +2 -2
  17. package/dist/cjs/src/okx.js +113 -0
  18. package/dist/cjs/src/pro/binance.js +439 -75
  19. package/dist/cjs/src/pro/bitget.js +1 -1
  20. package/dist/cjs/src/pro/woo.js +0 -1
  21. package/dist/cjs/src/whitebit.js +174 -2
  22. package/dist/cjs/src/woo.js +29 -0
  23. package/js/ccxt.d.ts +1 -1
  24. package/js/ccxt.js +1 -1
  25. package/js/src/abstract/binance.d.ts +1 -0
  26. package/js/src/abstract/binancecoinm.d.ts +1 -0
  27. package/js/src/abstract/binanceus.d.ts +1 -0
  28. package/js/src/abstract/binanceusdm.d.ts +1 -0
  29. package/js/src/abstract/bingx.d.ts +1 -0
  30. package/js/src/abstract/whitebit.d.ts +21 -0
  31. package/js/src/abstract/woo.d.ts +1 -0
  32. package/js/src/base/Exchange.d.ts +52 -3
  33. package/js/src/base/Exchange.js +299 -6
  34. package/js/src/binance.d.ts +4 -0
  35. package/js/src/binance.js +24 -17
  36. package/js/src/bingx.d.ts +1 -0
  37. package/js/src/bingx.js +45 -0
  38. package/js/src/bitmex.d.ts +1 -0
  39. package/js/src/bitmex.js +24 -0
  40. package/js/src/bybit.d.ts +2 -1
  41. package/js/src/bybit.js +86 -0
  42. package/js/src/coinbase.js +5 -4
  43. package/js/src/coinex.js +30 -32
  44. package/js/src/cryptocom.d.ts +2 -1
  45. package/js/src/cryptocom.js +32 -0
  46. package/js/src/htx.d.ts +1 -0
  47. package/js/src/htx.js +28 -0
  48. package/js/src/hyperliquid.d.ts +1 -0
  49. package/js/src/hyperliquid.js +40 -0
  50. package/js/src/kraken.d.ts +1 -0
  51. package/js/src/kraken.js +30 -0
  52. package/js/src/krakenfutures.d.ts +1 -0
  53. package/js/src/krakenfutures.js +28 -0
  54. package/js/src/kucoin.d.ts +1 -0
  55. package/js/src/kucoin.js +53 -3
  56. package/js/src/kucoinfutures.js +2 -2
  57. package/js/src/okx.d.ts +3 -1
  58. package/js/src/okx.js +113 -0
  59. package/js/src/pro/binance.d.ts +9 -1
  60. package/js/src/pro/binance.js +439 -75
  61. package/js/src/pro/bitget.d.ts +1 -1
  62. package/js/src/pro/bitget.js +1 -1
  63. package/js/src/pro/cex.d.ts +1 -1
  64. package/js/src/pro/lbank.d.ts +1 -1
  65. package/js/src/pro/woo.js +0 -1
  66. package/js/src/static_dependencies/jsencrypt/lib/jsbn/jsbn.d.ts +1 -1
  67. package/js/src/whitebit.d.ts +3 -0
  68. package/js/src/whitebit.js +174 -2
  69. package/js/src/woo.d.ts +2 -1
  70. package/js/src/woo.js +29 -0
  71. package/package.json +1 -1
@@ -43,9 +43,14 @@ export default class binance extends binanceRest {
43
43
  'fetchMarketsWs': false,
44
44
  'fetchMyTradesWs': true,
45
45
  'fetchOHLCVWs': true,
46
+ 'fetchOrderBookWs': true,
46
47
  'fetchOpenOrdersWs': true,
47
48
  'fetchOrderWs': true,
48
49
  'fetchOrdersWs': true,
50
+ 'fetchPositionWs': true,
51
+ 'fetchPositionForSymbolWs': true,
52
+ 'fetchPositionsWs': true,
53
+ 'fetchTickerWs': true,
49
54
  'fetchTradesWs': true,
50
55
  'fetchTradingFeesWs': false,
51
56
  'fetchWithdrawalsWs': false,
@@ -57,7 +62,10 @@ export default class binance extends binanceRest {
57
62
  'margin': 'wss://testnet.binance.vision/ws',
58
63
  'future': 'wss://fstream.binancefuture.com/ws',
59
64
  'delivery': 'wss://dstream.binancefuture.com/ws',
60
- 'ws': 'wss://testnet.binance.vision/ws-api/v3',
65
+ 'ws-api': {
66
+ 'spot': 'wss://testnet.binance.vision/ws-api/v3',
67
+ 'future': 'wss://testnet.binancefuture.com/ws-fapi/v1',
68
+ },
61
69
  },
62
70
  },
63
71
  'api': {
@@ -66,7 +74,10 @@ export default class binance extends binanceRest {
66
74
  'margin': 'wss://stream.binance.com:9443/ws',
67
75
  'future': 'wss://fstream.binance.com/ws',
68
76
  'delivery': 'wss://dstream.binance.com/ws',
69
- 'ws': 'wss://ws-api.binance.com:443/ws-api/v3',
77
+ 'ws-api': {
78
+ 'spot': 'wss://ws-api.binance.com:443/ws-api/v3',
79
+ 'future': 'wss://ws-fapi.binance.com/ws-fapi/v1',
80
+ },
70
81
  'papi': 'wss://fstream.binance.com/pm/ws',
71
82
  },
72
83
  },
@@ -278,6 +289,79 @@ export default class binance extends binanceRest {
278
289
  const orderbook = await this.watchMultiple(url, messageHashes, message, messageHashes, subscription);
279
290
  return orderbook.limit();
280
291
  }
292
+ async fetchOrderBookWs(symbol, limit = undefined, params = {}) {
293
+ /**
294
+ * @method
295
+ * @name binance#fetchOrderBookWs
296
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
297
+ * @see https://binance-docs.github.io/apidocs/futures/en/#order-book-2
298
+ * @param {string} symbol unified symbol of the market to fetch the order book for
299
+ * @param {int} [limit] the maximum amount of order book entries to return
300
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
301
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
302
+ */
303
+ await this.loadMarkets();
304
+ const market = this.market(symbol);
305
+ const payload = {
306
+ 'symbol': market['id'],
307
+ };
308
+ if (limit !== undefined) {
309
+ payload['limit'] = limit;
310
+ }
311
+ const marketType = this.getMarketType('fetchOrderBookWs', market, params);
312
+ if (marketType !== 'future') {
313
+ throw new BadRequest(this.id + ' fetchOrderBookWs only supports swap markets');
314
+ }
315
+ const url = this.urls['api']['ws']['ws-api'][marketType];
316
+ const requestId = this.requestId(url);
317
+ const messageHash = requestId.toString();
318
+ let returnRateLimits = false;
319
+ [returnRateLimits, params] = this.handleOptionAndParams(params, 'createOrderWs', 'returnRateLimits', false);
320
+ payload['returnRateLimits'] = returnRateLimits;
321
+ params = this.omit(params, 'test');
322
+ const message = {
323
+ 'id': messageHash,
324
+ 'method': 'depth',
325
+ 'params': this.signParams(this.extend(payload, params)),
326
+ };
327
+ const subscription = {
328
+ 'method': this.handleFetchOrderBook,
329
+ };
330
+ const orderbook = await this.watch(url, messageHash, message, messageHash, subscription);
331
+ orderbook['symbol'] = market['symbol'];
332
+ return orderbook;
333
+ }
334
+ handleFetchOrderBook(client, message) {
335
+ //
336
+ // {
337
+ // "id":"51e2affb-0aba-4821-ba75-f2625006eb43",
338
+ // "status":200,
339
+ // "result":{
340
+ // "lastUpdateId":1027024,
341
+ // "E":1589436922972,
342
+ // "T":1589436922959,
343
+ // "bids":[
344
+ // [
345
+ // "4.00000000",
346
+ // "431.00000000"
347
+ // ]
348
+ // ],
349
+ // "asks":[
350
+ // [
351
+ // "4.00000200",
352
+ // "12.00000000"
353
+ // ]
354
+ // ]
355
+ // }
356
+ // }
357
+ //
358
+ const messageHash = this.safeString(message, 'id');
359
+ const result = this.safeDict(message, 'result');
360
+ const timestamp = this.safeInteger(result, 'T');
361
+ const orderbook = this.parseOrderBook(result, undefined, timestamp);
362
+ orderbook['nonce'] = this.safeInteger2(result, 'lastUpdateId', 'u');
363
+ client.resolve(orderbook, messageHash);
364
+ }
281
365
  async fetchOrderBookSnapshot(client, message, subscription) {
282
366
  const name = this.safeString(subscription, 'name');
283
367
  const symbol = this.safeString(subscription, 'symbol');
@@ -859,6 +943,47 @@ export default class binance extends binanceRest {
859
943
  stored.append(parsed);
860
944
  client.resolve(stored, messageHash);
861
945
  }
946
+ async fetchTickerWs(symbol, params = {}) {
947
+ /**
948
+ * @method
949
+ * @name binance#fetchTickerWs
950
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
951
+ * @see https://binance-docs.github.io/apidocs/voptions/en/#24hr-ticker-price-change-statistics
952
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
953
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
954
+ * @param {string} [params.method] method to use can be ticker.price or ticker.book
955
+ * @param {boolean} [params.returnRateLimits] return the rate limits for the exchange
956
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
957
+ */
958
+ await this.loadMarkets();
959
+ const market = this.market(symbol);
960
+ const payload = {
961
+ 'symbol': market['id'],
962
+ };
963
+ const type = this.getMarketType('fetchTickerWs', market, params);
964
+ if (type !== 'future') {
965
+ throw new BadRequest(this.id + ' fetchTickerWs only supports swap markets');
966
+ }
967
+ const url = this.urls['api']['ws']['ws-api'][type];
968
+ const requestId = this.requestId(url);
969
+ const messageHash = requestId.toString();
970
+ const subscription = {
971
+ 'method': this.handleTickerWs,
972
+ };
973
+ let returnRateLimits = false;
974
+ [returnRateLimits, params] = this.handleOptionAndParams(params, 'fetchTickerWs', 'returnRateLimits', false);
975
+ payload['returnRateLimits'] = returnRateLimits;
976
+ params = this.omit(params, 'test');
977
+ let method = undefined;
978
+ [method, params] = this.handleOptionAndParams(params, 'fetchTickerWs', 'method', 'ticker.book');
979
+ const message = {
980
+ 'id': messageHash,
981
+ 'method': method,
982
+ 'params': this.signParams(this.extend(payload, params)),
983
+ };
984
+ const ticker = await this.watch(url, messageHash, message, messageHash, subscription);
985
+ return ticker;
986
+ }
862
987
  async fetchOHLCVWs(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
863
988
  /**
864
989
  * @method
@@ -877,8 +1002,12 @@ export default class binance extends binanceRest {
877
1002
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
878
1003
  */
879
1004
  await this.loadMarkets();
880
- this.checkIsSpot('fetchOHLCVWs', symbol, params);
881
- const url = this.urls['api']['ws']['ws'];
1005
+ const market = this.market(symbol);
1006
+ const marketType = this.getMarketType('fetchOHLCVWs', market, params);
1007
+ if (marketType !== 'spot' && marketType !== 'future') {
1008
+ throw new BadRequest(this.id + ' fetchOHLCVWs only supports spot or swap markets');
1009
+ }
1010
+ const url = this.urls['api']['ws']['ws-api'][marketType];
882
1011
  const requestId = this.requestId(url);
883
1012
  const messageHash = requestId.toString();
884
1013
  let returnRateLimits = false;
@@ -1115,6 +1244,22 @@ export default class binance extends binanceRest {
1115
1244
  // "v": "2109995.32000000",
1116
1245
  // "q": "2019254.05788000"
1117
1246
  // }
1247
+ // fetchTickerWs
1248
+ // {
1249
+ // "symbol":"BTCUSDT",
1250
+ // "price":"72606.70",
1251
+ // "time":1712526204284
1252
+ // }
1253
+ // fetchTickerWs - ticker.book
1254
+ // {
1255
+ // "lastUpdateId":1027024,
1256
+ // "symbol":"BTCUSDT",
1257
+ // "bidPrice":"4.00000000",
1258
+ // "bidQty":"431.00000000",
1259
+ // "askPrice":"4.00000200",
1260
+ // "askQty":"9.00000000",
1261
+ // "time":1589437530011,
1262
+ // }
1118
1263
  //
1119
1264
  let event = this.safeString(message, 'e', 'bookTicker');
1120
1265
  if (event === '24hrTicker') {
@@ -1123,26 +1268,26 @@ export default class binance extends binanceRest {
1123
1268
  let timestamp = undefined;
1124
1269
  if (event === 'bookTicker') {
1125
1270
  // take the event timestamp, if available, for spot tickers it is not
1126
- timestamp = this.safeInteger(message, 'E');
1271
+ timestamp = this.safeInteger2(message, 'E', 'time');
1127
1272
  }
1128
1273
  else {
1129
1274
  // take the timestamp of the closing price for candlestick streams
1130
- timestamp = this.safeInteger2(message, 'C', 'E');
1275
+ timestamp = this.safeIntegerN(message, ['C', 'E', 'time']);
1131
1276
  }
1132
- const marketId = this.safeString(message, 's');
1277
+ const marketId = this.safeString2(message, 's', 'symbol');
1133
1278
  const symbol = this.safeSymbol(marketId, undefined, undefined, marketType);
1134
1279
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
1135
- const last = this.safeString(message, 'c');
1280
+ const last = this.safeString2(message, 'c', 'price');
1136
1281
  return this.safeTicker({
1137
1282
  'symbol': symbol,
1138
1283
  'timestamp': timestamp,
1139
1284
  'datetime': this.iso8601(timestamp),
1140
1285
  'high': this.safeString(message, 'h'),
1141
1286
  'low': this.safeString(message, 'l'),
1142
- 'bid': this.safeString(message, 'b'),
1143
- 'bidVolume': this.safeString(message, 'B'),
1144
- 'ask': this.safeString(message, 'a'),
1145
- 'askVolume': this.safeString(message, 'A'),
1287
+ 'bid': this.safeString2(message, 'b', 'bidPrice'),
1288
+ 'bidVolume': this.safeString2(message, 'B', 'bidQty'),
1289
+ 'ask': this.safeString2(message, 'a', 'askPrice'),
1290
+ 'askVolume': this.safeString2(message, 'A', 'askQty'),
1146
1291
  'vwap': this.safeString(message, 'w'),
1147
1292
  'open': this.safeString(message, 'o'),
1148
1293
  'close': last,
@@ -1156,6 +1301,38 @@ export default class binance extends binanceRest {
1156
1301
  'info': message,
1157
1302
  }, market);
1158
1303
  }
1304
+ handleTickerWs(client, message) {
1305
+ //
1306
+ // ticker.price
1307
+ // {
1308
+ // "id":"1",
1309
+ // "status":200,
1310
+ // "result":{
1311
+ // "symbol":"BTCUSDT",
1312
+ // "price":"73178.50",
1313
+ // "time":1712527052374
1314
+ // }
1315
+ // }
1316
+ // ticker.book
1317
+ // {
1318
+ // "id":"9d32157c-a556-4d27-9866-66760a174b57",
1319
+ // "status":200,
1320
+ // "result":{
1321
+ // "lastUpdateId":1027024,
1322
+ // "symbol":"BTCUSDT",
1323
+ // "bidPrice":"4.00000000",
1324
+ // "bidQty":"431.00000000",
1325
+ // "askPrice":"4.00000200",
1326
+ // "askQty":"9.00000000",
1327
+ // "time":1589437530011 // Transaction time
1328
+ // }
1329
+ // }
1330
+ //
1331
+ const messageHash = this.safeString(message, 'id');
1332
+ const result = this.safeValue(message, 'result', {});
1333
+ const ticker = this.parseWsTicker(result, 'future');
1334
+ client.resolve(ticker, messageHash);
1335
+ }
1159
1336
  handleBidsAsks(client, message) {
1160
1337
  //
1161
1338
  // arrives one symbol dict or array of symbol dicts
@@ -1462,33 +1639,52 @@ export default class binance extends binanceRest {
1462
1639
  * @name binance#fetchBalanceWs
1463
1640
  * @description fetch balance and get the amount of funds available for trading or funds locked in orders
1464
1641
  * @see https://binance-docs.github.io/apidocs/websocket_api/en/#account-information-user_data
1642
+ * @see https://binance-docs.github.io/apidocs/futures/en/#account-information-user_data
1643
+ * @see https://binance-docs.github.io/apidocs/futures/en/#futures-account-balance-user_data
1465
1644
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1466
1645
  * @param {string|undefined} [params.type] 'future', 'delivery', 'savings', 'funding', or 'spot'
1467
1646
  * @param {string|undefined} [params.marginMode] 'cross' or 'isolated', for margin trading, uses this.options.defaultMarginMode if not passed, defaults to undefined/None/null
1468
1647
  * @param {string[]|undefined} [params.symbols] unified market symbols, only used in isolated margin mode
1648
+ * @param {string|undefined} [params.method] method to use. Can be account.balance or account.status
1469
1649
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1470
1650
  */
1471
1651
  await this.loadMarkets();
1472
- const url = this.urls['api']['ws']['ws'];
1652
+ const type = this.getMarketType('fetchBalanceWs', undefined, params);
1653
+ if (type !== 'spot' && type !== 'future') {
1654
+ throw new BadRequest(this.id + ' fetchBalanceWs only supports spot or swap markets');
1655
+ }
1656
+ const url = this.urls['api']['ws']['ws-api'][type];
1473
1657
  const requestId = this.requestId(url);
1474
1658
  const messageHash = requestId.toString();
1475
1659
  let returnRateLimits = false;
1476
- [returnRateLimits, params] = this.handleOptionAndParams(params, 'createOrderWs', 'returnRateLimits', false);
1660
+ [returnRateLimits, params] = this.handleOptionAndParams(params, 'fetchBalanceWs', 'returnRateLimits', false);
1477
1661
  const payload = {
1478
1662
  'returnRateLimits': returnRateLimits,
1479
1663
  };
1664
+ let method = undefined;
1665
+ [method, params] = this.handleOptionAndParams(params, 'fetchBalanceWs', 'method', 'account.status');
1480
1666
  const message = {
1481
1667
  'id': messageHash,
1482
- 'method': 'account.status',
1668
+ 'method': method,
1483
1669
  'params': this.signParams(this.extend(payload, params)),
1484
1670
  };
1485
1671
  const subscription = {
1486
- 'method': this.handleBalanceWs,
1672
+ 'method': (method === 'account.status') ? this.handleAccountStatusWs : this.handleBalanceWs,
1487
1673
  };
1488
1674
  return await this.watch(url, messageHash, message, messageHash, subscription);
1489
1675
  }
1490
1676
  handleBalanceWs(client, message) {
1491
1677
  //
1678
+ //
1679
+ const messageHash = this.safeString(message, 'id');
1680
+ const result = this.safeDict(message, 'result', {});
1681
+ const rawBalance = this.safeList(result, 0, []);
1682
+ const parsedBalances = this.parseBalanceCustom(rawBalance);
1683
+ client.resolve(parsedBalances, messageHash);
1684
+ }
1685
+ handleAccountStatusWs(client, message) {
1686
+ //
1687
+ // spot
1492
1688
  // {
1493
1689
  // "id": "605a6d20-6588-4cb9-afa0-b0ab087507ba",
1494
1690
  // "status": 200,
@@ -1531,12 +1727,105 @@ export default class binance extends binanceRest {
1531
1727
  // ]
1532
1728
  // }
1533
1729
  // }
1730
+ // swap
1534
1731
  //
1535
1732
  const messageHash = this.safeString(message, 'id');
1536
- const result = this.safeValue(message, 'result', {});
1537
- const parsedBalances = this.parseBalance(result);
1733
+ const result = this.safeDict(message, 'result', {});
1734
+ const parsedBalances = this.parseBalanceCustom(result);
1538
1735
  client.resolve(parsedBalances, messageHash);
1539
1736
  }
1737
+ async fetchPositionWs(symbol, params = {}) {
1738
+ /**
1739
+ * @method
1740
+ * @name binance#fetchPositionWs
1741
+ * @see https://binance-docs.github.io/apidocs/futures/en/#position-information-user_data
1742
+ * @description fetch data on an open position
1743
+ * @param {string} symbol unified market symbol of the market the position is held in
1744
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1745
+ * @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
1746
+ */
1747
+ return await this.fetchPositionsWs([symbol], params);
1748
+ }
1749
+ async fetchPositionsWs(symbols = undefined, params = {}) {
1750
+ /**
1751
+ * @method
1752
+ * @name binance#fetchPositionsWs
1753
+ * @description fetch all open positions
1754
+ * @see https://binance-docs.github.io/apidocs/futures/en/#position-information-user_data
1755
+ * @param {string[]} [symbols] list of unified market symbols
1756
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1757
+ * @param {boolean} [params.returnRateLimits] set to true to return rate limit informations, defaults to false.
1758
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
1759
+ */
1760
+ await this.loadMarkets();
1761
+ symbols = this.marketSymbols(symbols, 'swap', true, true, true);
1762
+ const url = this.urls['api']['ws']['ws-api']['future'];
1763
+ const requestId = this.requestId(url);
1764
+ const messageHash = requestId.toString();
1765
+ const payload = {};
1766
+ if (symbols !== undefined) {
1767
+ const symbolsLength = symbols.length;
1768
+ if (symbolsLength === 1) {
1769
+ payload['symbol'] = this.marketId(symbols[0]);
1770
+ }
1771
+ }
1772
+ let returnRateLimits = false;
1773
+ [returnRateLimits, params] = this.handleOptionAndParams(params, 'fetchPositionsWs', 'returnRateLimits', false);
1774
+ payload['returnRateLimits'] = returnRateLimits;
1775
+ const message = {
1776
+ 'id': messageHash,
1777
+ 'method': 'account.position',
1778
+ 'params': this.signParams(this.extend(payload, params)),
1779
+ };
1780
+ const subscription = {
1781
+ 'method': this.handlePositionsWs,
1782
+ };
1783
+ const result = await this.watch(url, messageHash, message, messageHash, subscription);
1784
+ return this.filterByArrayPositions(result, 'symbol', symbols, false);
1785
+ }
1786
+ handlePositionsWs(client, message) {
1787
+ //
1788
+ // {
1789
+ // id: '1',
1790
+ // status: 200,
1791
+ // result: [
1792
+ // {
1793
+ // symbol: 'BTCUSDT',
1794
+ // positionAmt: '-0.014',
1795
+ // entryPrice: '42901.1',
1796
+ // breakEvenPrice: '30138.83333142',
1797
+ // markPrice: '71055.98470333',
1798
+ // unRealizedProfit: '-394.16838584',
1799
+ // liquidationPrice: '137032.02272908',
1800
+ // leverage: '123',
1801
+ // maxNotionalValue: '50000',
1802
+ // marginType: 'cross',
1803
+ // isolatedMargin: '0.00000000',
1804
+ // isAutoAddMargin: 'false',
1805
+ // positionSide: 'BOTH',
1806
+ // notional: '-994.78378584',
1807
+ // isolatedWallet: '0',
1808
+ // updateTime: 1708906343111,
1809
+ // isolated: false,
1810
+ // adlQuantile: 2
1811
+ // },
1812
+ // ...
1813
+ // ]
1814
+ // }
1815
+ //
1816
+ //
1817
+ const messageHash = this.safeString(message, 'id');
1818
+ const result = this.safeList(message, 'result', []);
1819
+ const positions = [];
1820
+ for (let i = 0; i < result.length; i++) {
1821
+ const parsed = this.parsePositionRisk(result[i]);
1822
+ const entryPrice = this.safeString(parsed, 'entryPrice');
1823
+ if ((entryPrice !== '0') && (entryPrice !== '0.0') && (entryPrice !== '0.00000000')) {
1824
+ positions.push(parsed);
1825
+ }
1826
+ }
1827
+ client.resolve(positions, messageHash);
1828
+ }
1540
1829
  async watchBalance(params = {}) {
1541
1830
  /**
1542
1831
  * @method
@@ -1568,7 +1857,7 @@ export default class binance extends binanceRest {
1568
1857
  const client = this.client(url);
1569
1858
  this.setBalanceCache(client, type, isPortfolioMargin);
1570
1859
  this.setPositionsCache(client, type, undefined, isPortfolioMargin);
1571
- const options = this.safeValue(this.options, 'watchBalance');
1860
+ const options = this.safeDict(this.options, 'watchBalance');
1572
1861
  const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
1573
1862
  const awaitBalanceSnapshot = this.safeBool(options, 'awaitBalanceSnapshot', true);
1574
1863
  if (fetchBalanceSnapshot && awaitBalanceSnapshot) {
@@ -1636,7 +1925,7 @@ export default class binance extends binanceRest {
1636
1925
  // }
1637
1926
  // }
1638
1927
  //
1639
- const wallet = this.safeValue(this.options, 'wallet', 'wb'); // cw for cross wallet
1928
+ const wallet = this.safeString(this.options, 'wallet', 'wb'); // cw for cross wallet
1640
1929
  // each account is connected to a different endpoint
1641
1930
  // and has exactly one subscriptionhash which is the account type
1642
1931
  const subscriptions = Object.keys(client.subscriptions);
@@ -1665,8 +1954,8 @@ export default class binance extends binanceRest {
1665
1954
  this.balance[accountType][code] = account;
1666
1955
  }
1667
1956
  else {
1668
- message = this.safeValue(message, 'a', message);
1669
- const B = this.safeValue(message, 'B');
1957
+ message = this.safeDict(message, 'a', message);
1958
+ const B = this.safeList(message, 'B');
1670
1959
  for (let i = 0; i < B.length; i++) {
1671
1960
  const entry = B[i];
1672
1961
  const currencyId = this.safeString(entry, 'a');
@@ -1684,32 +1973,25 @@ export default class binance extends binanceRest {
1684
1973
  this.balance[accountType] = this.safeBalance(this.balance[accountType]);
1685
1974
  client.resolve(this.balance[accountType], messageHash);
1686
1975
  }
1687
- checkIsSpot(method, symbol, params = {}) {
1688
- /**
1689
- * @method
1690
- * @ignore
1691
- * @description checks if symbols is a spot market if not throws an error
1692
- * @param {string} method name of the method to be checked
1693
- * @param {string} symbol symbol or marketId of the market to be checked
1694
- */
1695
- if (symbol === undefined) {
1696
- const type = this.safeString(params, 'type', 'spot');
1697
- const defaultType = this.safeString(this.options, 'defaultType', type);
1698
- if (defaultType === 'spot') {
1699
- return;
1700
- }
1701
- throw new BadRequest(this.id + ' ' + method + ' only supports spot markets');
1976
+ getMarketType(method, market, params = {}) {
1977
+ let type = undefined;
1978
+ [type, params] = this.handleMarketTypeAndParams(method, market, params);
1979
+ let subType = undefined;
1980
+ [subType, params] = this.handleSubTypeAndParams(method, market, params);
1981
+ if (this.isLinear(type, subType)) {
1982
+ type = 'future';
1702
1983
  }
1703
- const market = this.market(symbol);
1704
- if (!market['spot']) {
1705
- throw new BadRequest(this.id + ' ' + method + ' only supports spot markets');
1984
+ else if (this.isInverse(type, subType)) {
1985
+ type = 'delivery';
1706
1986
  }
1987
+ return type;
1707
1988
  }
1708
1989
  async createOrderWs(symbol, type, side, amount, price = undefined, params = {}) {
1709
1990
  /**
1710
1991
  * @method
1711
1992
  * @name binance#createOrderWs
1712
1993
  * @see https://binance-docs.github.io/apidocs/websocket_api/en/#place-new-order-trade
1994
+ * @see https://binance-docs.github.io/apidocs/futures/en/#new-order-trade-2
1713
1995
  * @description create a trade order
1714
1996
  * @param {string} symbol unified symbol of the market to create an order in
1715
1997
  * @param {string} type 'market' or 'limit'
@@ -1718,14 +2000,19 @@ export default class binance extends binanceRest {
1718
2000
  * @param {float|undefined} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1719
2001
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1720
2002
  * @param {boolean} params.test test order, default false
2003
+ * @param {boolean} params.returnRateLimits set to true to return rate limit information, default false
1721
2004
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1722
2005
  */
1723
2006
  await this.loadMarkets();
1724
- this.checkIsSpot('createOrderWs', symbol, params);
1725
- const url = this.urls['api']['ws']['ws'];
2007
+ const market = this.market(symbol);
2008
+ const marketType = this.getMarketType('createOrderWs', market, params);
2009
+ if (marketType !== 'spot' && marketType !== 'future') {
2010
+ throw new BadRequest(this.id + ' createOrderWs only supports spot or swap markets');
2011
+ }
2012
+ const url = this.urls['api']['ws']['ws-api'][marketType];
1726
2013
  const requestId = this.requestId(url);
1727
2014
  const messageHash = requestId.toString();
1728
- const sor = this.safeValue2(params, 'sor', 'SOR', false);
2015
+ const sor = this.safeBool2(params, 'sor', 'SOR', false);
1729
2016
  params = this.omit(params, 'sor', 'SOR');
1730
2017
  const payload = this.createOrderRequest(symbol, type, side, amount, price, params);
1731
2018
  let returnRateLimits = false;
@@ -1800,7 +2087,7 @@ export default class binance extends binanceRest {
1800
2087
  // }
1801
2088
  //
1802
2089
  const messageHash = this.safeString(message, 'id');
1803
- const result = this.safeValue(message, 'result', {});
2090
+ const result = this.safeDict(message, 'result', {});
1804
2091
  const order = this.parseOrder(result);
1805
2092
  client.resolve(order, messageHash);
1806
2093
  }
@@ -1843,7 +2130,7 @@ export default class binance extends binanceRest {
1843
2130
  // }
1844
2131
  //
1845
2132
  const messageHash = this.safeString(message, 'id');
1846
- const result = this.safeValue(message, 'result', []);
2133
+ const result = this.safeList(message, 'result', []);
1847
2134
  const orders = this.parseOrders(result);
1848
2135
  client.resolve(orders, messageHash);
1849
2136
  }
@@ -1853,6 +2140,7 @@ export default class binance extends binanceRest {
1853
2140
  * @name binance#editOrderWs
1854
2141
  * @description edit a trade order
1855
2142
  * @see https://binance-docs.github.io/apidocs/websocket_api/en/#cancel-and-replace-order-trade
2143
+ * @see https://binance-docs.github.io/apidocs/futures/en/#modify-order-trade-2
1856
2144
  * @param {string} id order id
1857
2145
  * @param {string} symbol unified symbol of the market to create an order in
1858
2146
  * @param {string} type 'market' or 'limit'
@@ -1863,17 +2151,27 @@ export default class binance extends binanceRest {
1863
2151
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1864
2152
  */
1865
2153
  await this.loadMarkets();
1866
- this.checkIsSpot('editOrderWs', symbol, params);
1867
- const url = this.urls['api']['ws']['ws'];
2154
+ const market = this.market(symbol);
2155
+ const marketType = this.getMarketType('editOrderWs', market, params);
2156
+ if (marketType !== 'spot' && marketType !== 'future') {
2157
+ throw new BadRequest(this.id + ' editOrderWs only supports spot or swap markets');
2158
+ }
2159
+ const url = this.urls['api']['ws']['ws-api'][marketType];
1868
2160
  const requestId = this.requestId(url);
1869
2161
  const messageHash = requestId.toString();
1870
- const payload = this.editSpotOrderRequest(id, symbol, type, side, amount, price, params);
2162
+ let payload = undefined;
2163
+ if (marketType === 'spot') {
2164
+ payload = this.editSpotOrderRequest(id, symbol, type, side, amount, price, params);
2165
+ }
2166
+ else if (marketType === 'future') {
2167
+ payload = this.editContractOrderRequest(id, symbol, type, side, amount, price, params);
2168
+ }
1871
2169
  let returnRateLimits = false;
1872
2170
  [returnRateLimits, params] = this.handleOptionAndParams(params, 'editOrderWs', 'returnRateLimits', false);
1873
2171
  payload['returnRateLimits'] = returnRateLimits;
1874
2172
  const message = {
1875
2173
  'id': messageHash,
1876
- 'method': 'order.cancelReplace',
2174
+ 'method': (marketType === 'future') ? 'order.modify' : 'order.cancelReplace',
1877
2175
  'params': this.signParams(this.extend(payload, params)),
1878
2176
  };
1879
2177
  const subscription = {
@@ -1883,6 +2181,7 @@ export default class binance extends binanceRest {
1883
2181
  }
1884
2182
  handleEditOrderWs(client, message) {
1885
2183
  //
2184
+ // spot
1886
2185
  // {
1887
2186
  // "id": 1,
1888
2187
  // "status": 200,
@@ -1947,11 +2246,48 @@ export default class binance extends binanceRest {
1947
2246
  // }
1948
2247
  // ]
1949
2248
  // }
2249
+ // swap
2250
+ // {
2251
+ // "id":"1",
2252
+ // "status":200,
2253
+ // "result":{
2254
+ // "orderId":667061487,
2255
+ // "symbol":"LTCUSDT",
2256
+ // "status":"NEW",
2257
+ // "clientOrderId":"x-xcKtGhcu91a74c818749ee42c0f70",
2258
+ // "price":"82.00",
2259
+ // "avgPrice":"0.00",
2260
+ // "origQty":"1.000",
2261
+ // "executedQty":"0.000",
2262
+ // "cumQty":"0.000",
2263
+ // "cumQuote":"0.00000",
2264
+ // "timeInForce":"GTC",
2265
+ // "type":"LIMIT",
2266
+ // "reduceOnly":false,
2267
+ // "closePosition":false,
2268
+ // "side":"BUY",
2269
+ // "positionSide":"BOTH",
2270
+ // "stopPrice":"0.00",
2271
+ // "workingType":"CONTRACT_PRICE",
2272
+ // "priceProtect":false,
2273
+ // "origType":"LIMIT",
2274
+ // "priceMatch":"NONE",
2275
+ // "selfTradePreventionMode":"NONE",
2276
+ // "goodTillDate":0,
2277
+ // "updateTime":1712918927511
2278
+ // }
2279
+ // }
1950
2280
  //
1951
2281
  const messageHash = this.safeString(message, 'id');
1952
- const result = this.safeValue(message, 'result', {});
1953
- const rawOrder = this.safeValue(result, 'newOrderResponse', {});
1954
- const order = this.parseOrder(rawOrder);
2282
+ const result = this.safeDict(message, 'result', {});
2283
+ const newSpotOrder = this.safeDict(result, 'newOrderResponse');
2284
+ let order = undefined;
2285
+ if (newSpotOrder !== undefined) {
2286
+ order = this.parseOrder(newSpotOrder);
2287
+ }
2288
+ else {
2289
+ order = this.parseOrder(result);
2290
+ }
1955
2291
  client.resolve(order, messageHash);
1956
2292
  }
1957
2293
  async cancelOrderWs(id, symbol = undefined, params = {}) {
@@ -1959,6 +2295,7 @@ export default class binance extends binanceRest {
1959
2295
  * @method
1960
2296
  * @name binance#cancelOrderWs
1961
2297
  * @see https://binance-docs.github.io/apidocs/websocket_api/en/#cancel-order-trade
2298
+ * @see https://binance-docs.github.io/apidocs/futures/en/#cancel-order-trade-2
1962
2299
  * @description cancel multiple orders
1963
2300
  * @param {string} id order id
1964
2301
  * @param {string} symbol unified market symbol, default is undefined
@@ -1970,8 +2307,9 @@ export default class binance extends binanceRest {
1970
2307
  if (symbol === undefined) {
1971
2308
  throw new BadRequest(this.id + ' cancelOrderWs requires a symbol');
1972
2309
  }
1973
- this.checkIsSpot('cancelOrderWs', symbol, params);
1974
- const url = this.urls['api']['ws']['ws'];
2310
+ const market = this.market(symbol);
2311
+ const type = this.getMarketType('cancelOrderWs', market, params);
2312
+ const url = this.urls['api']['ws']['ws-api'][type];
1975
2313
  const requestId = this.requestId(url);
1976
2314
  const messageHash = requestId.toString();
1977
2315
  let returnRateLimits = false;
@@ -1980,7 +2318,7 @@ export default class binance extends binanceRest {
1980
2318
  'symbol': this.marketId(symbol),
1981
2319
  'returnRateLimits': returnRateLimits,
1982
2320
  };
1983
- const clientOrderId = this.safeValue2(params, 'origClientOrderId', 'clientOrderId');
2321
+ const clientOrderId = this.safeString2(params, 'origClientOrderId', 'clientOrderId');
1984
2322
  if (clientOrderId !== undefined) {
1985
2323
  payload['origClientOrderId'] = clientOrderId;
1986
2324
  }
@@ -2009,7 +2347,12 @@ export default class binance extends binanceRest {
2009
2347
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2010
2348
  */
2011
2349
  await this.loadMarkets();
2012
- const url = this.urls['api']['ws']['ws'];
2350
+ const market = this.market(symbol);
2351
+ const type = this.getMarketType('cancelAllOrdersWs', market, params);
2352
+ if (type !== 'spot' && type !== 'future') {
2353
+ throw new BadRequest(this.id + ' cancelAllOrdersWs only supports spot or swap markets');
2354
+ }
2355
+ const url = this.urls['api']['ws']['ws-api'][type];
2013
2356
  const requestId = this.requestId(url);
2014
2357
  const messageHash = requestId.toString();
2015
2358
  let returnRateLimits = false;
@@ -2033,6 +2376,7 @@ export default class binance extends binanceRest {
2033
2376
  * @method
2034
2377
  * @name binance#fetchOrderWs
2035
2378
  * @see https://binance-docs.github.io/apidocs/websocket_api/en/#query-order-user_data
2379
+ * @see https://binance-docs.github.io/apidocs/futures/en/#query-order-user_data-2
2036
2380
  * @description fetches information on an order made by the user
2037
2381
  * @param {string} symbol unified symbol of the market the order was made in
2038
2382
  * @param {object} params extra parameters specific to the exchange API endpoint
@@ -2042,8 +2386,12 @@ export default class binance extends binanceRest {
2042
2386
  if (symbol === undefined) {
2043
2387
  throw new BadRequest(this.id + ' cancelOrderWs requires a symbol');
2044
2388
  }
2045
- this.checkIsSpot('fetchOrderWs', symbol, params);
2046
- const url = this.urls['api']['ws']['ws'];
2389
+ const market = this.market(symbol);
2390
+ const type = this.getMarketType('fetchOrderWs', market, params);
2391
+ if (type !== 'spot' && type !== 'future') {
2392
+ throw new BadRequest(this.id + ' fetchOrderWs only supports spot or swap markets');
2393
+ }
2394
+ const url = this.urls['api']['ws']['ws-api'][type];
2047
2395
  const requestId = this.requestId(url);
2048
2396
  const messageHash = requestId.toString();
2049
2397
  let returnRateLimits = false;
@@ -2052,7 +2400,7 @@ export default class binance extends binanceRest {
2052
2400
  'symbol': this.marketId(symbol),
2053
2401
  'returnRateLimits': returnRateLimits,
2054
2402
  };
2055
- const clientOrderId = this.safeValue2(params, 'origClientOrderId', 'clientOrderId');
2403
+ const clientOrderId = this.safeString2(params, 'origClientOrderId', 'clientOrderId');
2056
2404
  if (clientOrderId !== undefined) {
2057
2405
  payload['origClientOrderId'] = clientOrderId;
2058
2406
  }
@@ -2089,8 +2437,12 @@ export default class binance extends binanceRest {
2089
2437
  if (symbol === undefined) {
2090
2438
  throw new BadRequest(this.id + ' fetchOrdersWs requires a symbol');
2091
2439
  }
2092
- this.checkIsSpot('fetchOrdersWs', symbol, params);
2093
- const url = this.urls['api']['ws']['ws'];
2440
+ const market = this.market(symbol);
2441
+ const type = this.getMarketType('fetchOrdersWs', market, params);
2442
+ if (type !== 'spot') {
2443
+ throw new BadRequest(this.id + ' fetchOrdersWs only supports spot markets');
2444
+ }
2445
+ const url = this.urls['api']['ws']['ws-api'][type];
2094
2446
  const requestId = this.requestId(url);
2095
2447
  const messageHash = requestId.toString();
2096
2448
  let returnRateLimits = false;
@@ -2145,8 +2497,12 @@ export default class binance extends binanceRest {
2145
2497
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2146
2498
  */
2147
2499
  await this.loadMarkets();
2148
- this.checkIsSpot('fetchOpenOrdersWs', symbol);
2149
- const url = this.urls['api']['ws']['ws'];
2500
+ const market = this.market(symbol);
2501
+ const type = this.getMarketType('fetchOpenOrdersWs', market, params);
2502
+ if (type !== 'spot' && type !== 'future') {
2503
+ throw new BadRequest(this.id + ' fetchOpenOrdersWs only supports spot or swap markets');
2504
+ }
2505
+ const url = this.urls['api']['ws']['ws-api'][type];
2150
2506
  const requestId = this.requestId(url);
2151
2507
  const messageHash = requestId.toString();
2152
2508
  let returnRateLimits = false;
@@ -2362,7 +2718,7 @@ export default class binance extends binanceRest {
2362
2718
  'type': type,
2363
2719
  'timeInForce': timeInForce,
2364
2720
  'postOnly': undefined,
2365
- 'reduceOnly': this.safeValue(order, 'R'),
2721
+ 'reduceOnly': this.safeBool(order, 'R'),
2366
2722
  'side': side,
2367
2723
  'price': price,
2368
2724
  'stopPrice': stopPrice,
@@ -2461,7 +2817,7 @@ export default class binance extends binanceRest {
2461
2817
  //
2462
2818
  const e = this.safeString(message, 'e');
2463
2819
  if (e === 'ORDER_TRADE_UPDATE') {
2464
- message = this.safeValue(message, 'o', message);
2820
+ message = this.safeDict(message, 'o', message);
2465
2821
  }
2466
2822
  this.handleMyTrade(client, message);
2467
2823
  this.handleOrder(client, message);
@@ -2610,8 +2966,8 @@ export default class binance extends binanceRest {
2610
2966
  this.positions[accountType] = new ArrayCacheBySymbolBySide();
2611
2967
  }
2612
2968
  const cache = this.positions[accountType];
2613
- const data = this.safeValue(message, 'a', {});
2614
- const rawPositions = this.safeValue(data, 'P', []);
2969
+ const data = this.safeDict(message, 'a', {});
2970
+ const rawPositions = this.safeList(data, 'P', []);
2615
2971
  const newPositions = [];
2616
2972
  for (let i = 0; i < rawPositions.length; i++) {
2617
2973
  const rawPosition = rawPositions[i];
@@ -2708,8 +3064,12 @@ export default class binance extends binanceRest {
2708
3064
  if (symbol === undefined) {
2709
3065
  throw new BadRequest(this.id + ' fetchMyTradesWs requires a symbol');
2710
3066
  }
2711
- this.checkIsSpot('fetchMyTradesWs', symbol, params);
2712
- const url = this.urls['api']['ws']['ws'];
3067
+ const market = this.market(symbol);
3068
+ const type = this.getMarketType('fetchMyTradesWs', market, params);
3069
+ if (type !== 'spot' && type !== 'future') {
3070
+ throw new BadRequest(this.id + ' fetchMyTradesWs does not support ' + type + ' markets');
3071
+ }
3072
+ const url = this.urls['api']['ws']['ws-api'][type];
2713
3073
  const requestId = this.requestId(url);
2714
3074
  const messageHash = requestId.toString();
2715
3075
  let returnRateLimits = false;
@@ -2758,8 +3118,12 @@ export default class binance extends binanceRest {
2758
3118
  if (symbol === undefined) {
2759
3119
  throw new BadRequest(this.id + ' fetchTradesWs () requires a symbol argument');
2760
3120
  }
2761
- this.checkIsSpot('fetchTradesWs', symbol, params);
2762
- const url = this.urls['api']['ws']['ws'];
3121
+ const market = this.market(symbol);
3122
+ const type = this.getMarketType('fetchTradesWs', market, params);
3123
+ if (type !== 'spot' && type !== 'future') {
3124
+ throw new BadRequest(this.id + ' fetchTradesWs does not support ' + type + ' markets');
3125
+ }
3126
+ const url = this.urls['api']['ws']['ws-api'][type];
2763
3127
  const requestId = this.requestId(url);
2764
3128
  const messageHash = requestId.toString();
2765
3129
  let returnRateLimits = false;
@@ -2829,7 +3193,7 @@ export default class binance extends binanceRest {
2829
3193
  // }
2830
3194
  //
2831
3195
  const messageHash = this.safeString(message, 'id');
2832
- const result = this.safeValue(message, 'result', []);
3196
+ const result = this.safeList(message, 'result', []);
2833
3197
  const trades = this.parseTrades(result);
2834
3198
  client.resolve(trades, messageHash);
2835
3199
  }
@@ -2894,7 +3258,7 @@ export default class binance extends binanceRest {
2894
3258
  if (executionType === 'TRADE') {
2895
3259
  const trade = this.parseWsTrade(message);
2896
3260
  const orderId = this.safeString(trade, 'order');
2897
- let tradeFee = this.safeValue(trade, 'fee', {});
3261
+ let tradeFee = this.safeDict(trade, 'fee', {});
2898
3262
  tradeFee = this.extend({}, tradeFee);
2899
3263
  const symbol = this.safeString(trade, 'symbol');
2900
3264
  if (orderId !== undefined && tradeFee !== undefined && symbol !== undefined) {
@@ -2938,7 +3302,7 @@ export default class binance extends binanceRest {
2938
3302
  order['fee'] = tradeFee;
2939
3303
  }
2940
3304
  // save this trade in the order
2941
- const orderTrades = this.safeValue(order, 'trades', []);
3305
+ const orderTrades = this.safeList(order, 'trades', []);
2942
3306
  orderTrades.push(trade);
2943
3307
  order['trades'] = orderTrades;
2944
3308
  // don't append twice cause it breaks newUpdates mode
@@ -3008,7 +3372,7 @@ export default class binance extends binanceRest {
3008
3372
  //
3009
3373
  const id = this.safeString(message, 'id');
3010
3374
  let rejected = false;
3011
- const error = this.safeValue(message, 'error', {});
3375
+ const error = this.safeDict(message, 'error', {});
3012
3376
  const code = this.safeInteger(error, 'code');
3013
3377
  const msg = this.safeString(error, 'msg');
3014
3378
  try {