ccxt 4.5.48 → 4.5.49

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 (43) hide show
  1. package/README.md +6 -5
  2. package/dist/ccxt.browser.min.js +10 -10
  3. package/dist/cjs/ccxt.js +6 -1
  4. package/dist/cjs/src/abstract/weex.js +11 -0
  5. package/dist/cjs/src/btcbox.js +1 -1
  6. package/dist/cjs/src/bullish.js +2 -1
  7. package/dist/cjs/src/kraken.js +1 -0
  8. package/dist/cjs/src/krakenfutures.js +10 -1
  9. package/dist/cjs/src/kucoin.js +5 -1
  10. package/dist/cjs/src/lighter.js +6 -3
  11. package/dist/cjs/src/mexc.js +7 -12
  12. package/dist/cjs/src/paradex.js +5 -2
  13. package/dist/cjs/src/pro/binance.js +1 -1
  14. package/dist/cjs/src/pro/cex.js +1 -1
  15. package/dist/cjs/src/pro/coinbase.js +1 -1
  16. package/dist/cjs/src/pro/lighter.js +338 -18
  17. package/dist/cjs/src/pro/weex.js +1906 -0
  18. package/dist/cjs/src/weex.js +3823 -0
  19. package/js/ccxt.d.ts +8 -2
  20. package/js/ccxt.js +6 -2
  21. package/js/src/abstract/weex.d.ts +83 -0
  22. package/js/src/abstract/weex.js +11 -0
  23. package/js/src/btcbox.js +1 -1
  24. package/js/src/bullish.js +2 -1
  25. package/js/src/kraken.js +1 -0
  26. package/js/src/krakenfutures.js +10 -1
  27. package/js/src/kucoin.d.ts +4 -0
  28. package/js/src/kucoin.js +5 -1
  29. package/js/src/lighter.d.ts +1 -0
  30. package/js/src/lighter.js +6 -3
  31. package/js/src/mexc.d.ts +2 -0
  32. package/js/src/mexc.js +7 -12
  33. package/js/src/paradex.js +5 -2
  34. package/js/src/pro/binance.js +1 -1
  35. package/js/src/pro/cex.js +1 -1
  36. package/js/src/pro/coinbase.js +1 -1
  37. package/js/src/pro/lighter.d.ts +37 -2
  38. package/js/src/pro/lighter.js +338 -18
  39. package/js/src/pro/weex.d.ts +330 -0
  40. package/js/src/pro/weex.js +1905 -0
  41. package/js/src/weex.d.ts +675 -0
  42. package/js/src/weex.js +3822 -0
  43. package/package.json +1 -1
@@ -23,14 +23,14 @@ export default class lighter extends lighterRest {
23
23
  'watchTrades': true,
24
24
  'watchTradesForSymbols': false,
25
25
  'watchOrderBookForSymbols': false,
26
- 'watchBalance': false,
26
+ 'watchBalance': true,
27
27
  'watchLiquidations': true,
28
28
  'watchLiquidationsForSymbols': false,
29
29
  'watchMyLiquidations': false,
30
30
  'watchMyLiquidationsForSymbols': false,
31
31
  'watchOHLCV': false,
32
32
  'watchOHLCVForSymbols': false,
33
- 'watchOrders': false,
33
+ 'watchOrders': true,
34
34
  'watchMyTrades': true,
35
35
  'watchPositions': false,
36
36
  'watchFundingRate': false,
@@ -42,6 +42,7 @@ export default class lighter extends lighterRest {
42
42
  'unWatchMyTrades': true,
43
43
  'unWatchMarkPrice': true,
44
44
  'unWatchMarkPrices': true,
45
+ 'unWatchOrders': true,
45
46
  },
46
47
  'urls': {
47
48
  'api': {
@@ -89,7 +90,7 @@ export default class lighter extends lighterRest {
89
90
  };
90
91
  return await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscription);
91
92
  }
92
- async unsubscribePublic(messageHash, params = {}) {
93
+ async unsubscribe(messageHash, params = {}) {
93
94
  const url = this.urls['api']['ws'];
94
95
  const request = {
95
96
  'type': 'unsubscribe',
@@ -100,6 +101,10 @@ export default class lighter extends lighterRest {
100
101
  };
101
102
  return await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
102
103
  }
104
+ async subscribePrivate(messageHash, params = {}) {
105
+ params['auth'] = this.createAuth(params);
106
+ return await this.subscribePublic(messageHash, params);
107
+ }
103
108
  handleDelta(bookside, delta) {
104
109
  const price = this.safeFloat(delta, 'price');
105
110
  const amount = this.safeFloat(delta, 'size');
@@ -205,7 +210,7 @@ export default class lighter extends lighterRest {
205
210
  'channel': 'order_book/' + market['id'],
206
211
  };
207
212
  const messageHash = this.getMessageHash('unsubscribe', symbol);
208
- return await this.unsubscribePublic(messageHash, this.extend(request, params));
213
+ return await this.unsubscribe(messageHash, this.extend(request, params));
209
214
  }
210
215
  handleTicker(client, message) {
211
216
  //
@@ -316,7 +321,7 @@ export default class lighter extends lighterRest {
316
321
  'channel': 'market_stats/' + market['id'],
317
322
  };
318
323
  const messageHash = this.getMessageHash('unsubscribe', symbol);
319
- return await this.unsubscribePublic(messageHash, this.extend(request, params));
324
+ return await this.unsubscribe(messageHash, this.extend(request, params));
320
325
  }
321
326
  /**
322
327
  * @method
@@ -371,7 +376,7 @@ export default class lighter extends lighterRest {
371
376
  'channel': 'market_stats/all',
372
377
  };
373
378
  const messageHash = this.getMessageHash('unsubscribe');
374
- return await this.unsubscribePublic(messageHash, this.extend(request, params));
379
+ return await this.unsubscribe(messageHash, this.extend(request, params));
375
380
  }
376
381
  /**
377
382
  * @method
@@ -455,10 +460,7 @@ export default class lighter extends lighterRest {
455
460
  const priceString = this.safeString(trade, 'price');
456
461
  const amountString = this.safeString(trade, 'size');
457
462
  const isMakerAsk = this.safeBool(trade, 'is_maker_ask');
458
- const side = (isMakerAsk === true) ? 'sell' : 'buy';
459
- const makerFeeRate = this.safeString(market, 'maker_fee');
460
- const maker = Precise.stringDiv(makerFeeRate, '100');
461
- const feeAmount = Precise.stringMul(maker, makerFeeRate);
463
+ const side = isMakerAsk ? 'buy' : 'sell';
462
464
  return this.safeTrade({
463
465
  'info': trade,
464
466
  'id': tradeId,
@@ -468,14 +470,11 @@ export default class lighter extends lighterRest {
468
470
  'symbol': this.safeSymbol(undefined, market),
469
471
  'type': undefined,
470
472
  'side': side,
471
- 'takerOrMaker': 'maker',
473
+ 'takerOrMaker': 'taker',
472
474
  'price': priceString,
473
475
  'amount': amountString,
474
476
  'cost': this.safeString(trade, 'usd_amount'),
475
- 'fee': {
476
- 'cost': feeAmount,
477
- 'currency': 'USDC',
478
- },
477
+ 'fee': undefined,
479
478
  }, market);
480
479
  }
481
480
  handleTrades(client, message) {
@@ -578,7 +577,83 @@ export default class lighter extends lighterRest {
578
577
  'channel': 'trade/' + market['id'],
579
578
  };
580
579
  const messageHash = this.getMessageHash('unsubscribe', symbol);
581
- return await this.unsubscribePublic(messageHash, this.extend(request, params));
580
+ return await this.unsubscribe(messageHash, this.extend(request, params));
581
+ }
582
+ parseWsOrderTrade(trade, market = undefined) {
583
+ //
584
+ // {
585
+ // "trade_id": 526801155,
586
+ // "tx_hash": "1998d9df580acb7540aa141cc369d6ef926d003b3062196d2007bca15f978ab208e0caae4ac5872b",
587
+ // "type": "trade",
588
+ // "market_id": 0,
589
+ // "size": "0.0346",
590
+ // "price": "3028.85",
591
+ // "usd_amount": "104.798210",
592
+ // "ask_id": 281475673670566,
593
+ // "bid_id": 562949291740362,
594
+ // "ask_client_id": 76303170,
595
+ // "bid_client_id": 27601,
596
+ // "ask_account_id": 99349,
597
+ // "bid_account_id": 243008,
598
+ // "is_maker_ask": false,
599
+ // "block_height": 102322769,
600
+ // "timestamp": 1763623734215,
601
+ // "taker_position_size_before": "0.0346",
602
+ // "taker_entry_quote_before": "104.359926",
603
+ // "taker_initial_margin_fraction_before": 500,
604
+ // "taker_position_sign_changed": true,
605
+ // "maker_fee": 20,
606
+ // "maker_position_size_before": "2.1277",
607
+ // "maker_entry_quote_before": "6444.179555",
608
+ // "maker_initial_margin_fraction_before": 200
609
+ // }
610
+ //
611
+ const timestamp = this.safeInteger(trade, 'timestamp');
612
+ const tradeId = this.safeString(trade, 'trade_id');
613
+ const priceString = this.safeString(trade, 'price');
614
+ const amountString = this.safeString(trade, 'size');
615
+ const costString = this.safeString(trade, 'usd_amount');
616
+ const isMakerAsk = this.safeBool(trade, 'is_maker_ask');
617
+ const side = isMakerAsk ? 'buy' : 'sell';
618
+ const accountIndex = this.safeInteger(trade, 'accountIndex');
619
+ let order = undefined;
620
+ let takerOrMaker = undefined;
621
+ if (accountIndex !== undefined) {
622
+ if (this.safeInteger(trade, 'bid_account_id') === accountIndex) {
623
+ order = this.safeString(trade, 'bid_id');
624
+ takerOrMaker = isMakerAsk ? 'taker' : 'maker';
625
+ }
626
+ else if (this.safeInteger(trade, 'ask_account_id') === accountIndex) {
627
+ order = this.safeString(trade, 'ask_id');
628
+ takerOrMaker = isMakerAsk ? 'maker' : 'taker';
629
+ }
630
+ }
631
+ let fee = undefined;
632
+ if (takerOrMaker !== undefined) {
633
+ const feeRateRaw = (takerOrMaker === 'maker') ? this.safeString(trade, 'maker_fee') : this.safeString(trade, 'taker_fee');
634
+ const feeRate = (feeRateRaw !== undefined) ? Precise.stringDiv(feeRateRaw, '1000000') : '0';
635
+ const feeAmount = Precise.stringMul(costString, feeRate);
636
+ fee = {
637
+ 'cost': feeAmount,
638
+ 'currency': 'USDC',
639
+ 'rate': feeRate,
640
+ };
641
+ }
642
+ return this.safeTrade({
643
+ 'info': trade,
644
+ 'id': tradeId,
645
+ 'order': order,
646
+ 'timestamp': timestamp,
647
+ 'datetime': this.iso8601(timestamp),
648
+ 'symbol': this.safeSymbol(undefined, market),
649
+ 'type': undefined,
650
+ 'side': side,
651
+ 'takerOrMaker': takerOrMaker,
652
+ 'price': priceString,
653
+ 'amount': amountString,
654
+ 'cost': costString,
655
+ 'fee': fee,
656
+ }, market);
582
657
  }
583
658
  handleMyTrades(client, message) {
584
659
  //
@@ -615,6 +690,9 @@ export default class lighter extends lighterRest {
615
690
  // "type": "update/account_all_trades"
616
691
  // }
617
692
  //
693
+ const channel = this.safeString(message, 'channel', '');
694
+ const parts = channel.split(':');
695
+ const accountIndex = parts[1];
618
696
  const data = this.safeDict(message, 'trades', {});
619
697
  const marketIds = Object.keys(data);
620
698
  const idsLength = marketIds.length;
@@ -634,7 +712,9 @@ export default class lighter extends lighterRest {
634
712
  const tradesLength = trades.length;
635
713
  for (let j = 0; j < tradesLength; j++) {
636
714
  const jReversed = tradesLength - 1 - j;
637
- const trade = this.parseWsTrade(trades[jReversed], market);
715
+ const tradeRaw = trades[jReversed];
716
+ tradeRaw['accountIndex'] = accountIndex;
717
+ const trade = this.parseWsOrderTrade(tradeRaw, market);
638
718
  stored.append(trade);
639
719
  const symbol = trade['symbol'];
640
720
  if (symbol !== undefined) {
@@ -698,7 +778,7 @@ export default class lighter extends lighterRest {
698
778
  const request = {
699
779
  'channel': 'account_all_trades/' + accountIndex,
700
780
  };
701
- return await this.unsubscribePublic(messageHash, this.extend(request, params));
781
+ return await this.unsubscribe(messageHash, this.extend(request, params));
702
782
  }
703
783
  parseWsLiquidation(liquidation, market = undefined) {
704
784
  //
@@ -828,6 +908,230 @@ export default class lighter extends lighterRest {
828
908
  const messageHash = this.getMessageHash('liquidations', symbol);
829
909
  return await this.subscribePublic(messageHash, this.extend(request, params));
830
910
  }
911
+ /**
912
+ * @method
913
+ * @name lighter#watchBalance
914
+ * @description watch balance and get the amount of funds available for trading or funds locked in orders
915
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#account-all-assets
916
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
917
+ * @param {string} [params.type] 'spot' or 'swap', default is 'swap'
918
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
919
+ */
920
+ async watchBalance(params = {}) {
921
+ await this.loadMarkets();
922
+ const defaultType = this.safeString2(this.options, 'watchBalance', 'defaultType', 'spot');
923
+ let type = undefined;
924
+ [type, params] = this.handleParamString(params, 'type', defaultType);
925
+ let accountIndex = undefined;
926
+ [accountIndex, params] = await this.handleAccountIndex(params, 'watchBalance', 'accountIndex', 'account_index');
927
+ const messageHash = this.getMessageHash('balances', undefined, type);
928
+ const request = {};
929
+ if (type === 'spot') {
930
+ request['channel'] = 'account_all_assets/' + this.numberToString(accountIndex);
931
+ return await this.subscribePrivate(messageHash, this.extend(request, params));
932
+ }
933
+ else {
934
+ request['channel'] = 'user_stats/' + this.numberToString(accountIndex);
935
+ return await this.subscribePublic(messageHash, this.extend(request, params));
936
+ }
937
+ }
938
+ handleBalance(client, message) {
939
+ //
940
+ // spot balance
941
+ // {
942
+ // "assets": {
943
+ // "1": {
944
+ // "symbol": "ETH",
945
+ // "asset_id": 1,
946
+ // "balance": "7.1072",
947
+ // "locked_balance": "0.0000"
948
+ // },
949
+ // "3": {
950
+ // "symbol": "USDC",
951
+ // "asset_id": 3,
952
+ // "balance": "6343.581906",
953
+ // "locked_balance": "297.000000"
954
+ // }
955
+ // },
956
+ // "channel": "account_all_assets:1234",
957
+ // "timestamp": 1773158679717,
958
+ // "type": "update/account_all_assets"
959
+ // }
960
+ //
961
+ // swap balance
962
+ // {
963
+ // "channel": "user_stats:10",
964
+ // "stats": {
965
+ // "collateral": "5000.00",
966
+ // "portfolio_value": "15000.00",
967
+ // "leverage": "3.0",
968
+ // "available_balance": "2000.00",
969
+ // "margin_usage": "0.80",
970
+ // "buying_power": "4000.00",
971
+ // "account_trading_mode": 1,
972
+ // "cross_stats":{
973
+ // "collateral":"0.000000",
974
+ // "portfolio_value":"0.000000",
975
+ // "leverage":"0.00",
976
+ // "available_balance":"0.000000",
977
+ // "margin_usage":"0.00",
978
+ // "buying_power":"0"
979
+ // },
980
+ // "total_stats":{
981
+ // "collateral":"0.000000",
982
+ // "portfolio_value":"0.000000",
983
+ // "leverage":"0.00",
984
+ // "available_balance":"0.000000",
985
+ // "margin_usage":"0.00",
986
+ // "buying_power":"0"
987
+ // }
988
+ // },
989
+ // "timestamp": 1773158679717,
990
+ // "type": "update/user_stats"
991
+ // }
992
+ //
993
+ const channel = this.safeString(message, 'channel', '');
994
+ let type = 'spot';
995
+ if (channel.indexOf('user_stats:') >= 0) {
996
+ type = 'swap';
997
+ }
998
+ const balance = this.safeDict(this.balance, type, {});
999
+ if (type === 'spot') {
1000
+ const assets = this.safeDict(message, 'assets', {});
1001
+ const assetIds = Object.keys(assets);
1002
+ for (let i = 0; i < assetIds.length; i++) {
1003
+ const assetId = assetIds[i];
1004
+ const asset = assets[assetId];
1005
+ const codeId = this.safeString(asset, 'symbol');
1006
+ const code = this.safeCurrencyCode(codeId);
1007
+ const account = this.account();
1008
+ account['used'] = this.safeString(asset, 'locked_balance');
1009
+ account['total'] = this.safeString(asset, 'balance');
1010
+ balance[code] = account;
1011
+ }
1012
+ }
1013
+ else {
1014
+ const stats = this.safeDict(message, 'stats', {});
1015
+ const account = this.account();
1016
+ account['free'] = this.safeString(stats, 'available_balance');
1017
+ account['total'] = this.safeString(stats, 'collateral');
1018
+ account['info'] = stats;
1019
+ balance['USDC'] = account;
1020
+ }
1021
+ const timestamp = this.safeInteger(message, 'timestamp');
1022
+ balance['timestamp'] = timestamp;
1023
+ balance['datetime'] = this.iso8601(timestamp);
1024
+ this.balance[type] = this.safeBalance(balance);
1025
+ const messageHash = this.getMessageHash('balances', undefined, type);
1026
+ client.resolve(this.balance[type], messageHash);
1027
+ return true;
1028
+ }
1029
+ /**
1030
+ * @name lighter#watchOrders
1031
+ * @description watches information on multiple orders made by the user
1032
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#account-all-orders
1033
+ * @param {string} symbol unified market symbol of the market orders were made in
1034
+ * @param {int} [since] the earliest time in ms to fetch orders for
1035
+ * @param {int} [limit] the maximum number of order structures to retrieve
1036
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1037
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
1038
+ */
1039
+ async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1040
+ await this.loadMarkets();
1041
+ let accountIndex = undefined;
1042
+ [accountIndex, params] = await this.handleAccountIndex(params, 'watchOrders', 'accountIndex', 'account_index');
1043
+ let messageHash = undefined;
1044
+ const request = {};
1045
+ if (symbol !== undefined) {
1046
+ const market = this.market(symbol);
1047
+ messageHash = this.getMessageHash('orders', market['symbol']);
1048
+ request['channel'] = 'account_orders/' + market['id'] + '/' + this.numberToString(accountIndex);
1049
+ }
1050
+ else {
1051
+ messageHash = this.getMessageHash('orders');
1052
+ request['channel'] = 'account_all_orders/' + this.numberToString(accountIndex);
1053
+ }
1054
+ const orders = await this.subscribePrivate(messageHash, this.extend(request, params));
1055
+ if (this.newUpdates) {
1056
+ limit = orders.getLimit(symbol, limit);
1057
+ }
1058
+ return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
1059
+ }
1060
+ /**
1061
+ * @method
1062
+ * @name lighter#unWatchOrders
1063
+ * @description unWatches information on multiple orders made by the user
1064
+ * @see https://apidocs.lighter.xyz/docs/websocket-reference#account-all-orders
1065
+ * @param {string} symbol unified market symbol of the market orders were made in
1066
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1067
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
1068
+ */
1069
+ async unWatchOrders(symbol = undefined, params = {}) {
1070
+ await this.loadMarkets();
1071
+ let accountIndex = undefined;
1072
+ [accountIndex, params] = await this.handleAccountIndex(params, 'watchOrders', 'accountIndex', 'account_index');
1073
+ let messageHash = undefined;
1074
+ const request = {};
1075
+ if (symbol !== undefined) {
1076
+ const market = this.market(symbol);
1077
+ messageHash = this.getMessageHash('orders', market['symbol']);
1078
+ request['channel'] = 'account_orders/' + market['id'] + '/' + this.numberToString(accountIndex);
1079
+ }
1080
+ else {
1081
+ messageHash = this.getMessageHash('orders');
1082
+ request['channel'] = 'account_all_orders/' + this.numberToString(accountIndex);
1083
+ }
1084
+ return await this.unsubscribe(messageHash, this.extend(request, params));
1085
+ }
1086
+ handleOrders(client, message) {
1087
+ //
1088
+ // {
1089
+ // "account": {ACCOUNT_INDEX},
1090
+ // "channel": "account_orders:{MARKET_INDEX}",
1091
+ // "nonce": INTEGER,
1092
+ // "orders": {
1093
+ // "{MARKET_INDEX}": [Order] // the only present market index will be the one provided
1094
+ // },
1095
+ // "type": "update/account_orders"
1096
+ // }
1097
+ //
1098
+ // {
1099
+ // "channel": "account_all_orders:{ACCOUNT_ID}",
1100
+ // "orders": {
1101
+ // "{MARKET_INDEX}": [Order]
1102
+ // },
1103
+ // "type": "update/account_all_orders"
1104
+ // }
1105
+ //
1106
+ const data = this.safeDict(message, 'orders', {});
1107
+ const marketIds = Object.keys(data);
1108
+ const idsLength = marketIds.length;
1109
+ if (idsLength === 0) {
1110
+ return false; // nothing to process
1111
+ }
1112
+ if (this.orders === undefined) {
1113
+ const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
1114
+ this.orders = new ArrayCache(limit);
1115
+ }
1116
+ const stored = this.orders;
1117
+ const messageHash = this.getMessageHash('orders');
1118
+ for (let i = 0; i < marketIds.length; i++) {
1119
+ const marketId = marketIds[i];
1120
+ const market = this.safeMarket(marketId);
1121
+ const orders = this.safeList(data, marketId, []);
1122
+ for (let j = 0; j < orders.length; j++) {
1123
+ const order = this.parseOrder(orders[j], market);
1124
+ stored.append(order);
1125
+ const symbol = order['symbol'];
1126
+ if (symbol !== undefined) {
1127
+ const symbolSpecificMessageHash = this.getMessageHash('orders', symbol);
1128
+ client.resolve(stored, symbolSpecificMessageHash);
1129
+ }
1130
+ }
1131
+ }
1132
+ client.resolve(stored, messageHash);
1133
+ return true;
1134
+ }
831
1135
  handleErrorMessage(client, message) {
832
1136
  //
833
1137
  // {
@@ -878,6 +1182,22 @@ export default class lighter extends lighterRest {
878
1182
  this.handleMyTrades(client, message);
879
1183
  return;
880
1184
  }
1185
+ if (channel.indexOf('account_all_assets:') >= 0) {
1186
+ this.handleBalance(client, message);
1187
+ return;
1188
+ }
1189
+ if (channel.indexOf('user_stats:') >= 0) {
1190
+ this.handleBalance(client, message);
1191
+ return;
1192
+ }
1193
+ if (channel.indexOf('account_orders:') >= 0) {
1194
+ this.handleOrders(client, message);
1195
+ return;
1196
+ }
1197
+ if (channel.indexOf('account_all_orders:') >= 0) {
1198
+ this.handleOrders(client, message);
1199
+ return;
1200
+ }
881
1201
  if (channel === '') {
882
1202
  this.handleSubscriptionStatus(client, message);
883
1203
  }