ccxt 4.5.49 → 4.5.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/js/src/okx.js CHANGED
@@ -207,6 +207,7 @@ export default class okx extends Exchange {
207
207
  'market/option/instrument-family-trades': 1,
208
208
  'market/platform-24-volume': 10,
209
209
  'market/call-auction-detail': 1,
210
+ 'market/call-auction-details': 1,
210
211
  'market/books-sbe': 10,
211
212
  'market/block-tickers': 1,
212
213
  'market/block-ticker': 1,
@@ -247,6 +248,9 @@ export default class okx extends Exchange {
247
248
  'public/premium-history': 1,
248
249
  'public/economic-calendar': 50,
249
250
  'public/market-data-history': 4,
251
+ 'public/event-contract/events': 1,
252
+ 'public/event-contract/markets': 1,
253
+ 'public/event-contract/series': 1,
250
254
  'public/vip-interest-rate-loan-quota': 10,
251
255
  // rubik
252
256
  'rubik/stat/trading-data/support-coin': 4,
@@ -255,6 +259,7 @@ export default class okx extends Exchange {
255
259
  'rubik/stat/taker-volume-contract': 4,
256
260
  'rubik/stat/margin/loan-ratio': 4,
257
261
  'rubik/stat/contracts/long-short-account-ratio-contract-top-trader': 4,
262
+ 'rubik/stat/contracts/long-short-position-ratio-contract-top-trader': 4,
258
263
  'rubik/stat/contracts/long-short-account-ratio-contract': 4,
259
264
  'rubik/stat/contracts/long-short-account-ratio': 4,
260
265
  'rubik/stat/contracts/open-interest-volume': 4,
@@ -296,6 +301,7 @@ export default class okx extends Exchange {
296
301
  'copytrading/public-copy-traders': 4,
297
302
  'support/announcements': 4,
298
303
  'support/announcements-types': 20,
304
+ 'support/announcement-types': 20,
299
305
  },
300
306
  'post': {
301
307
  'tradingBot/grid/min-investment': 1, // public
@@ -362,6 +368,7 @@ export default class okx extends Exchange {
362
368
  'account/bills-archive': 4,
363
369
  'account/bills-history-archive': 2,
364
370
  'account/config': 4,
371
+ 'account/subtypes': 4,
365
372
  'account/max-size': 1,
366
373
  'account/max-avail-size': 1,
367
374
  'account/leverage-info': 1,
@@ -421,6 +428,11 @@ export default class okx extends Exchange {
421
428
  'tradingBot/recurring/orders-algo-history': 1,
422
429
  'tradingBot/recurring/orders-algo-details': 1,
423
430
  'tradingBot/recurring/sub-orders': 1,
431
+ 'tradingBot/dca/ongoing-list': 1,
432
+ 'tradingBot/dca/history-list': 1,
433
+ 'tradingBot/dca/orders': 1,
434
+ 'tradingBot/dca/position-details': 1,
435
+ 'tradingBot/dca/cycle-list': 1,
424
436
  // earn
425
437
  'finance/savings/balance': 5 / 3,
426
438
  'finance/savings/lending-history': 5 / 3,
@@ -470,6 +482,9 @@ export default class okx extends Exchange {
470
482
  'broker/nd/rebate-per-orders': 300,
471
483
  'finance/sfp/dcd/order': 2,
472
484
  'finance/sfp/dcd/orders': 2,
485
+ 'finance/sfp/dcd/currency-pair': 2,
486
+ 'finance/sfp/dcd/order-status': 2,
487
+ 'finance/sfp/dcd/order-history': 2,
473
488
  // affiliate
474
489
  'affiliate/invitee/detail': 1,
475
490
  'users/partner/if-rebate': 1,
@@ -540,6 +555,7 @@ export default class okx extends Exchange {
540
555
  'account/position-builder': 10,
541
556
  'account/position-builder-graph': 50,
542
557
  'account/set-riskOffset-type': 2,
558
+ 'account/set-riskOffset-amt': 2,
543
559
  'account/activate-option': 4,
544
560
  'account/set-auto-loan': 4,
545
561
  'account/account-level-switch-preset': 4,
@@ -566,6 +582,7 @@ export default class okx extends Exchange {
566
582
  'users/subaccount/set-transfer-out': 10,
567
583
  // grid trading
568
584
  'tradingBot/grid/order-algo': 1,
585
+ 'tradingBot/grid/copy-order-algo': 1,
569
586
  'tradingBot/grid/amend-algo-basic-param': 1,
570
587
  'tradingBot/grid/amend-order-algo': 1,
571
588
  'tradingBot/grid/stop-order-algo': 1,
@@ -589,6 +606,20 @@ export default class okx extends Exchange {
589
606
  'tradingBot/recurring/order-algo': 1,
590
607
  'tradingBot/recurring/amend-order-algo': 1,
591
608
  'tradingBot/recurring/stop-order-algo': 1,
609
+ 'tradingBot/dca/create': 1,
610
+ 'tradingBot/dca/amend-order-algo': 1,
611
+ 'tradingBot/dca/stop': 1,
612
+ 'tradingBot/dca/orders/manual-buy': 1,
613
+ 'tradingBot/dca/settings/reinvestment': 1,
614
+ 'tradingBot/dca/settings/take-profit': 1,
615
+ 'tradingBot/dca/margin/add': 1,
616
+ 'tradingBot/dca/margin/reduce': 1,
617
+ 'tradingBot/recurring/add-investment': 1,
618
+ 'tradingBot/recurring/amend-price-range': 1,
619
+ 'tradingBot/recurring/amend-recurring-amount': 1,
620
+ 'tradingBot/recurring/amend-recurring-time': 1,
621
+ 'tradingBot/recurring/pause': 1,
622
+ 'tradingBot/recurring/restart': 1,
592
623
  // earn
593
624
  'finance/savings/purchase-redempt': 5 / 3,
594
625
  'finance/savings/set-lending-rate': 5 / 3,
@@ -627,6 +658,9 @@ export default class okx extends Exchange {
627
658
  'broker/nd/rebate-per-orders': 36000,
628
659
  'finance/sfp/dcd/quote': 10,
629
660
  'finance/sfp/dcd/order': 10,
661
+ 'finance/sfp/dcd/trade': 10,
662
+ 'finance/sfp/dcd/redeem-quote': 10,
663
+ 'finance/sfp/dcd/redeem': 10,
630
664
  'broker/nd/report-subaccount-ip': 0.25,
631
665
  'broker/dma/subaccount/apikey': 1 / 4,
632
666
  'broker/dma/trades': 36000,
@@ -5780,6 +5814,16 @@ export default class okx extends Exchange {
5780
5814
  }
5781
5815
  const currencyId = this.safeString(transaction, 'ccy');
5782
5816
  const code = this.safeCurrencyCode(currencyId);
5817
+ let network = undefined;
5818
+ const chain = this.safeString(transaction, 'chain');
5819
+ if (chain !== undefined) {
5820
+ const chainParts = chain.split('-');
5821
+ const networkParts = this.arraySlice(chainParts, 1);
5822
+ const networkId = networkParts.join('-');
5823
+ if (networkId !== undefined) {
5824
+ network = this.networkIdToCode(networkId, code);
5825
+ }
5826
+ }
5783
5827
  const amount = this.safeNumber(transaction, 'amt');
5784
5828
  const status = this.parseTransactionStatus(this.safeString(transaction, 'state'));
5785
5829
  const txid = this.safeString(transaction, 'txId');
@@ -5797,7 +5841,7 @@ export default class okx extends Exchange {
5797
5841
  'id': id,
5798
5842
  'currency': code,
5799
5843
  'amount': amount,
5800
- 'network': undefined,
5844
+ 'network': network,
5801
5845
  'addressFrom': addressFrom,
5802
5846
  'addressTo': addressTo,
5803
5847
  'address': address,
@@ -6614,6 +6658,7 @@ export default class okx extends Exchange {
6614
6658
  parseFundingInterval(interval) {
6615
6659
  const intervals = {
6616
6660
  '3600000': '1h',
6661
+ '7200000': '2h',
6617
6662
  '14400000': '4h',
6618
6663
  '28800000': '8h',
6619
6664
  '57600000': '16h',
@@ -1,6 +1,6 @@
1
1
  import hyperliquidRest from '../hyperliquid.js';
2
2
  import Client from '../base/ws/Client.js';
3
- import { Int, Str, Market, OrderBook, Trade, OHLCV, Order, Dict, Strings, Ticker, Tickers, type Num, OrderType, OrderSide, type OrderRequest, Bool } from '../base/types.js';
3
+ import { Int, Str, Market, OrderBook, Trade, OHLCV, Order, Dict, Strings, Ticker, Tickers, type Num, OrderType, OrderSide, type OrderRequest, Bool, Balances, Position } from '../base/types.js';
4
4
  export default class hyperliquid extends hyperliquidRest {
5
5
  describe(): any;
6
6
  /**
@@ -214,6 +214,51 @@ export default class hyperliquid extends hyperliquidRest {
214
214
  unWatchOHLCV(symbol: string, timeframe?: string, params?: {}): Promise<any>;
215
215
  handleOHLCV(client: Client, message: any): void;
216
216
  handleWsPost(client: Client, message: Dict): void;
217
+ /**
218
+ * @method
219
+ * @name hyperliquid#watchBalance
220
+ * @description watch balance and get the amount of funds available for trading or funds locked in orders
221
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
222
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
223
+ * @param {string} [params.dex] for for hip3 tokens subscription, eg: 'xyz' or 'flx'
224
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
225
+ */
226
+ watchBalance(params?: {}): Promise<Balances>;
227
+ /**
228
+ * @method
229
+ * @name hyperliquid#unWatchBalance
230
+ * @description unWatches balance
231
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
232
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
233
+ * @returns {object} status of the unwatch request
234
+ */
235
+ unWatchBalance(params?: {}): Promise<any>;
236
+ handleBalance(client: Client, message: any): void;
237
+ parseWsBalance(balance: any, accountType?: any): void;
238
+ /**
239
+ * @method
240
+ * @name hyperliquid#watchPositions
241
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
242
+ * @description watch all open positions
243
+ * @param {string[]} [symbols] list of unified market symbols
244
+ * @param {int} [since] the earliest time in ms to fetch positions for
245
+ * @param {int} [limit] the maximum number of positions to retrieve
246
+ * @param {object} params extra parameters specific to the exchange API endpoint
247
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
248
+ */
249
+ watchPositions(symbols?: Strings, since?: Int, limit?: Int, params?: {}): Promise<Position[]>;
250
+ setPositionsCache(client: Client, symbols?: Strings): void;
251
+ handlePositions(client: any, message: any): void;
252
+ /**
253
+ * @method
254
+ * @name hyperliquid#unWatchPositions
255
+ * @description unWatches all open positions
256
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
257
+ * @param {string[]} [symbols] list of unified market symbols
258
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
259
+ * @returns {object} status of the unwatch request
260
+ */
261
+ unWatchPositions(symbols?: Strings, params?: {}): Promise<any>;
217
262
  /**
218
263
  * @method
219
264
  * @name hyperliquid#watchOrders
@@ -246,6 +291,8 @@ export default class hyperliquid extends hyperliquidRest {
246
291
  handleOHLCVUnsubscription(client: Client, subscription: Dict): void;
247
292
  handleOrderUnsubscription(client: Client, subscription: Dict): void;
248
293
  handleMyTradesUnsubscription(client: Client, subscription: Dict): void;
294
+ handlePositionsUnsubscription(client: Client, subscription: Dict): void;
295
+ handleSpotBalanceUnsubscription(client: Client, subscription: Dict): void;
249
296
  handleSubscriptionResponse(client: Client, message: any): void;
250
297
  handleMessage(client: Client, message: any): void;
251
298
  ping(client: Client): {
@@ -7,7 +7,7 @@
7
7
  // ---------------------------------------------------------------------------
8
8
  import hyperliquidRest from '../hyperliquid.js';
9
9
  import { NotSupported } from '../base/errors.js';
10
- import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById } from '../base/ws/Cache.js';
10
+ import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js';
11
11
  // ---------------------------------------------------------------------------
12
12
  export default class hyperliquid extends hyperliquidRest {
13
13
  describe() {
@@ -19,7 +19,7 @@ export default class hyperliquid extends hyperliquidRest {
19
19
  'createOrderWs': true,
20
20
  'createOrdersWs': true,
21
21
  'editOrderWs': true,
22
- 'watchBalance': false,
22
+ 'watchBalance': true,
23
23
  'watchMyTrades': true,
24
24
  'watchOHLCV': true,
25
25
  'watchOrderBook': true,
@@ -29,6 +29,9 @@ export default class hyperliquid extends hyperliquidRest {
29
29
  'watchTrades': true,
30
30
  'watchTradesForSymbols': false,
31
31
  'watchPosition': false,
32
+ 'unWatchBalance': true,
33
+ 'watchPositions': true,
34
+ 'unWatchPositions': true,
32
35
  'unWatchOrderBook': true,
33
36
  'unWatchTickers': true,
34
37
  'unWatchTrades': true,
@@ -912,6 +915,334 @@ export default class hyperliquid extends hyperliquidRest {
912
915
  const payload = this.safeDict(response, 'payload');
913
916
  client.resolve(payload, id);
914
917
  }
918
+ /**
919
+ * @method
920
+ * @name hyperliquid#watchBalance
921
+ * @description watch balance and get the amount of funds available for trading or funds locked in orders
922
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
923
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
924
+ * @param {string} [params.dex] for for hip3 tokens subscription, eg: 'xyz' or 'flx'
925
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
926
+ */
927
+ async watchBalance(params = {}) {
928
+ await this.loadMarkets();
929
+ let userAddress = undefined;
930
+ [userAddress, params] = this.handlePublicAddress('watchBalance', params);
931
+ let type = undefined;
932
+ [type, params] = this.handleMarketTypeAndParams('watchBalance', undefined, params);
933
+ let isUnifiedEnabled = undefined;
934
+ [isUnifiedEnabled, params] = await this.isUnifiedEnabled('watchBalance', userAddress, false, params);
935
+ const dex = this.safeString(params, 'dex');
936
+ const isSpot = ((type === 'spot') || isUnifiedEnabled) && (dex === undefined);
937
+ const topic = (isSpot) ? 'spotState' : 'clearinghouseState';
938
+ const messageHash = topic + '::balance';
939
+ const url = this.urls['api']['ws']['public'];
940
+ const subscription = {
941
+ 'type': topic,
942
+ 'user': userAddress,
943
+ };
944
+ if (isSpot) {
945
+ if (isUnifiedEnabled) {
946
+ subscription['isPortfolioMargin'] = true;
947
+ }
948
+ }
949
+ else {
950
+ if (dex !== undefined) {
951
+ subscription['dex'] = dex;
952
+ }
953
+ }
954
+ const request = {
955
+ 'method': 'subscribe',
956
+ 'subscription': subscription,
957
+ };
958
+ const message = this.extend(request, params);
959
+ return await this.watch(url, messageHash, message, topic);
960
+ }
961
+ /**
962
+ * @method
963
+ * @name hyperliquid#unWatchBalance
964
+ * @description unWatches balance
965
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
966
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
967
+ * @returns {object} status of the unwatch request
968
+ */
969
+ async unWatchBalance(params = {}) {
970
+ await this.loadMarkets();
971
+ const url = this.urls['api']['ws']['public'];
972
+ let userAddress = undefined;
973
+ [userAddress, params] = this.handlePublicAddress('unWatchBalance', params);
974
+ let type = undefined;
975
+ [type, params] = this.handleMarketTypeAndParams('unWatchBalance', undefined, params);
976
+ let isUnifiedEnabled = undefined;
977
+ [isUnifiedEnabled, params] = await this.isUnifiedEnabled('unWatchBalance', userAddress, false, params);
978
+ const dex = this.safeString(params, 'dex');
979
+ const isSpot = ((type === 'spot') || isUnifiedEnabled) && (dex === undefined);
980
+ const topic = (isSpot) ? 'spotState' : 'clearinghouseState';
981
+ const messageHash = 'unsubscribe' + ':' + topic;
982
+ const request = {
983
+ 'method': 'unsubscribe',
984
+ 'subscription': {
985
+ 'type': topic,
986
+ 'user': userAddress,
987
+ },
988
+ };
989
+ const message = this.extend(request, params);
990
+ return await this.watch(url, messageHash, message, messageHash);
991
+ }
992
+ handleBalance(client, message) {
993
+ //
994
+ // spot
995
+ // {
996
+ // "channel": "spotState",
997
+ // "data": {
998
+ // "user": "0xeeeeexxxxeeeee",
999
+ // "spotState": {
1000
+ // "balances": [
1001
+ // {
1002
+ // "coin": "USDH",
1003
+ // "token": 360,
1004
+ // "total": "0.0",
1005
+ // "hold": "0.0",
1006
+ // "entryNtl": "0.0"
1007
+ // }
1008
+ // ],
1009
+ // "tokenToAvailableAfterMaintenance": [
1010
+ // [
1011
+ // 0,
1012
+ // "56.1"
1013
+ // ]
1014
+ // ]
1015
+ // }
1016
+ // }
1017
+ // }
1018
+ // swap
1019
+ // {
1020
+ // "channel": "clearinghouseState",
1021
+ // "data": {
1022
+ // "dex": "",
1023
+ // "user": "0xeeeeexxxxeeeee",
1024
+ // "clearinghouseState": {
1025
+ // "marginSummary": {
1026
+ // "accountValue": "0.0",
1027
+ // "totalNtlPos": "0.0",
1028
+ // "totalRawUsd": "0.0",
1029
+ // "totalMarginUsed": "0.0"
1030
+ // },
1031
+ // "crossMarginSummary": {
1032
+ // "accountValue": "0.0",
1033
+ // "totalNtlPos": "0.0",
1034
+ // "totalRawUsd": "0.0",
1035
+ // "totalMarginUsed": "0.0"
1036
+ // },
1037
+ // "crossMaintenanceMarginUsed": "0.0",
1038
+ // "withdrawable": "0.0",
1039
+ // "assetPositions": [],
1040
+ // "time": 1776000003409
1041
+ // }
1042
+ // }
1043
+ // }
1044
+ //
1045
+ if (this.balance === undefined) {
1046
+ this.balance = {};
1047
+ }
1048
+ const topic = this.safeValue(message, 'channel');
1049
+ const messageHash = topic + '::balance';
1050
+ let info = undefined;
1051
+ let rawBalances = [];
1052
+ let account = undefined;
1053
+ let timestamp = undefined;
1054
+ const data = this.safeValue(message, 'data', []);
1055
+ if (topic === 'spotState') {
1056
+ const spotState = this.safeDict(data, 'spotState');
1057
+ rawBalances = this.safeList(spotState, 'balances');
1058
+ account = 'spot';
1059
+ info = rawBalances;
1060
+ }
1061
+ if (topic === 'clearinghouseState') {
1062
+ account = 'swap';
1063
+ const clearinghouseState = this.safeDict(data, 'clearinghouseState');
1064
+ rawBalances.push(clearinghouseState);
1065
+ info = clearinghouseState;
1066
+ timestamp = this.safeInteger(clearinghouseState, 'time');
1067
+ this.handlePositions(client, message);
1068
+ }
1069
+ for (let i = 0; i < rawBalances.length; i++) {
1070
+ this.parseWsBalance(rawBalances[i], account);
1071
+ }
1072
+ if (this.safeValue(this.balance, account) === undefined) {
1073
+ this.balance[account] = {};
1074
+ }
1075
+ this.balance[account]['info'] = info;
1076
+ this.balance[account]['timestamp'] = timestamp;
1077
+ this.balance[account]['datetime'] = this.iso8601(timestamp);
1078
+ this.balance[account] = this.safeBalance(this.balance[account]);
1079
+ client.resolve(this.balance[account], messageHash);
1080
+ }
1081
+ parseWsBalance(balance, accountType = undefined) {
1082
+ //
1083
+ // spot
1084
+ // {
1085
+ // "coin": "USDH",
1086
+ // "token": 360,
1087
+ // "total": "0.0",
1088
+ // "hold": "0.0",
1089
+ // "entryNtl": "0.0"
1090
+ // }
1091
+ // swap
1092
+ // {
1093
+ // "marginSummary": {
1094
+ // "accountValue": "0.0",
1095
+ // "totalNtlPos": "0.0",
1096
+ // "totalRawUsd": "0.0",
1097
+ // "totalMarginUsed": "0.0"
1098
+ // },
1099
+ // "crossMarginSummary": {
1100
+ // "accountValue": "0.0",
1101
+ // "totalNtlPos": "0.0",
1102
+ // "totalRawUsd": "0.0",
1103
+ // "totalMarginUsed": "0.0"
1104
+ // },
1105
+ // "crossMaintenanceMarginUsed": "0.0",
1106
+ // "withdrawable": "0.0",
1107
+ // "assetPositions": [],
1108
+ // "time": 1776000003409
1109
+ // }
1110
+ //
1111
+ const account = this.account();
1112
+ const currencyId = this.safeString(balance, 'coin');
1113
+ let code = undefined;
1114
+ if (currencyId === undefined) {
1115
+ code = 'USDC';
1116
+ const marginSummary = this.safeDict(balance, 'marginSummary', {});
1117
+ account['free'] = this.safeString(balance, 'withdrawable');
1118
+ account['used'] = this.safeString(marginSummary, 'totalMarginUsed');
1119
+ account['total'] = this.safeString(marginSummary, 'accountValue');
1120
+ }
1121
+ else {
1122
+ code = this.safeCurrencyCode(currencyId);
1123
+ account['used'] = this.safeString(balance, 'hold');
1124
+ account['total'] = this.safeString(balance, 'total');
1125
+ }
1126
+ if (accountType !== undefined) {
1127
+ if (this.safeValue(this.balance, accountType) === undefined) {
1128
+ this.balance[accountType] = {};
1129
+ }
1130
+ this.balance[accountType][code] = account;
1131
+ }
1132
+ else {
1133
+ this.balance[code] = account;
1134
+ }
1135
+ }
1136
+ /**
1137
+ * @method
1138
+ * @name hyperliquid#watchPositions
1139
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
1140
+ * @description watch all open positions
1141
+ * @param {string[]} [symbols] list of unified market symbols
1142
+ * @param {int} [since] the earliest time in ms to fetch positions for
1143
+ * @param {int} [limit] the maximum number of positions to retrieve
1144
+ * @param {object} params extra parameters specific to the exchange API endpoint
1145
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
1146
+ */
1147
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
1148
+ await this.loadMarkets();
1149
+ let userAddress = undefined;
1150
+ [userAddress, params] = this.handlePublicAddress('watchPositions', params);
1151
+ const topic = 'clearinghouseState';
1152
+ let messageHash = topic + '::positions';
1153
+ if (!this.isEmpty(symbols)) {
1154
+ symbols = this.marketSymbols(symbols);
1155
+ messageHash += '::' + symbols.join(',');
1156
+ }
1157
+ const url = this.urls['api']['ws']['public'];
1158
+ const subscription = {
1159
+ 'type': topic,
1160
+ 'user': userAddress,
1161
+ };
1162
+ const dexName = this.getDexFromSymbols('watchPositions', symbols);
1163
+ if (dexName !== undefined) {
1164
+ subscription['dex'] = dexName;
1165
+ }
1166
+ const request = {
1167
+ 'method': 'subscribe',
1168
+ 'subscription': subscription,
1169
+ };
1170
+ const message = this.extend(request, params);
1171
+ const client = this.client(url);
1172
+ this.setPositionsCache(client, symbols);
1173
+ const cache = this.positions;
1174
+ const newPositions = await this.watch(url, messageHash, message, topic);
1175
+ if (this.newUpdates) {
1176
+ return newPositions;
1177
+ }
1178
+ return this.filterBySymbolsSinceLimit(cache, symbols, since, limit, true);
1179
+ }
1180
+ setPositionsCache(client, symbols = undefined) {
1181
+ if (this.positions !== undefined) {
1182
+ return;
1183
+ }
1184
+ this.positions = new ArrayCacheBySymbolBySide();
1185
+ }
1186
+ handlePositions(client, message) {
1187
+ if (this.positions === undefined) {
1188
+ this.positions = new ArrayCacheBySymbolBySide();
1189
+ }
1190
+ const cache = this.positions;
1191
+ const data = this.safeDict(message, 'data', {});
1192
+ const clearinghouseState = this.safeDict(data, 'clearinghouseState', {});
1193
+ const newPositions = [];
1194
+ const rawPositions = this.safeList(clearinghouseState, 'assetPositions', []);
1195
+ for (let i = 0; i < rawPositions.length; i++) {
1196
+ const rawPosition = rawPositions[i];
1197
+ const position = this.parsePosition(rawPosition);
1198
+ newPositions.push(position);
1199
+ cache.append(position);
1200
+ }
1201
+ const baseMessageHash = 'clearinghouseState::positions';
1202
+ const messageHashes = this.findMessageHashes(client, baseMessageHash);
1203
+ for (let i = 0; i < messageHashes.length; i++) {
1204
+ const messageHash = messageHashes[i];
1205
+ const parts = messageHash.split('::');
1206
+ const symbolsString = this.safeString(parts, 2);
1207
+ if (symbolsString === undefined) {
1208
+ continue;
1209
+ }
1210
+ const symbols = symbolsString.split(',');
1211
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
1212
+ if (!this.isEmpty(positions)) {
1213
+ client.resolve(positions, messageHash);
1214
+ }
1215
+ }
1216
+ client.resolve(newPositions, baseMessageHash);
1217
+ }
1218
+ /**
1219
+ * @method
1220
+ * @name hyperliquid#unWatchPositions
1221
+ * @description unWatches all open positions
1222
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
1223
+ * @param {string[]} [symbols] list of unified market symbols
1224
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1225
+ * @returns {object} status of the unwatch request
1226
+ */
1227
+ async unWatchPositions(symbols = undefined, params = {}) {
1228
+ await this.loadMarkets();
1229
+ if (!this.isEmpty(symbols)) {
1230
+ throw new NotSupported(this.id + ' unWatchPositions() does not support a symbol parameter, you must unwatch all orders');
1231
+ }
1232
+ const messageHash = 'unsubscribe:clearinghouseState';
1233
+ const url = this.urls['api']['ws']['public'];
1234
+ let userAddress = undefined;
1235
+ [userAddress, params] = this.handlePublicAddress('unWatchPositions', params);
1236
+ const request = {
1237
+ 'method': 'unsubscribe',
1238
+ 'subscription': {
1239
+ 'type': 'clearinghouseState',
1240
+ 'user': userAddress,
1241
+ },
1242
+ };
1243
+ const message = this.extend(request, params);
1244
+ return await this.watch(url, messageHash, message, messageHash);
1245
+ }
915
1246
  /**
916
1247
  * @method
917
1248
  * @name hyperliquid#watchOrders
@@ -1166,6 +1497,27 @@ export default class hyperliquid extends hyperliquidRest {
1166
1497
  };
1167
1498
  this.cleanCache(topicStructure);
1168
1499
  }
1500
+ handlePositionsUnsubscription(client, subscription) {
1501
+ const subHash = 'clearinghouseState';
1502
+ const unSubHash = 'unsubscribe:' + subHash;
1503
+ this.cleanUnsubscription(client, subHash, unSubHash, true);
1504
+ const topicStructure = {
1505
+ 'topic': 'positions',
1506
+ };
1507
+ this.cleanCache(topicStructure);
1508
+ // clean swap balance if it existed
1509
+ if ('swap' in this.balance) {
1510
+ delete this.balance['swap'];
1511
+ }
1512
+ }
1513
+ handleSpotBalanceUnsubscription(client, subscription) {
1514
+ const subHash = 'spotState';
1515
+ const unSubHash = 'unsubscribe:' + subHash;
1516
+ this.cleanUnsubscription(client, subHash, unSubHash, true);
1517
+ if ('spot' in this.balance) {
1518
+ delete this.balance['spot'];
1519
+ }
1520
+ }
1169
1521
  handleSubscriptionResponse(client, message) {
1170
1522
  // {
1171
1523
  // "channel":"subscriptionResponse",
@@ -1214,6 +1566,12 @@ export default class hyperliquid extends hyperliquidRest {
1214
1566
  else if (type === 'userFills') {
1215
1567
  this.handleMyTradesUnsubscription(client, subscription);
1216
1568
  }
1569
+ else if (type === 'clearinghoustState') {
1570
+ this.handlePositionsUnsubscription(client, subscription);
1571
+ }
1572
+ else if (type === 'spotState') {
1573
+ this.handleSpotBalanceUnsubscription(client, subscription);
1574
+ }
1217
1575
  }
1218
1576
  }
1219
1577
  handleMessage(client, message) {
@@ -1246,6 +1604,8 @@ export default class hyperliquid extends hyperliquidRest {
1246
1604
  'allMids': this.handleWsTickers,
1247
1605
  'post': this.handleWsPost,
1248
1606
  'subscriptionResponse': this.handleSubscriptionResponse,
1607
+ 'clearinghouseState': this.handleBalance,
1608
+ 'spotState': this.handleBalance,
1249
1609
  };
1250
1610
  const exacMethod = this.safeValue(methods, topic);
1251
1611
  if (exacMethod !== undefined) {
@@ -102,6 +102,7 @@ export default class lighter extends lighterRest {
102
102
  return await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
103
103
  }
104
104
  async subscribePrivate(messageHash, params = {}) {
105
+ await this.preLoadLighterLibrary();
105
106
  params['auth'] = this.createAuth(params);
106
107
  return await this.subscribePublic(messageHash, params);
107
108
  }
package/js/src/weex.js CHANGED
@@ -200,7 +200,7 @@ export default class weex extends Exchange {
200
200
  'doc': [
201
201
  'https://www.weex.com/api-doc',
202
202
  ],
203
- 'referral': 'https://weex.com/register?vipCode=4lvdl',
203
+ 'referral': 'https://www.weex.com/register?vipCode=qfyh',
204
204
  },
205
205
  'api': {
206
206
  'public': {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccxt",
3
- "version": "4.5.49",
3
+ "version": "4.5.50",
4
4
  "description": "A cryptocurrency trading API with more than 100 exchanges in JavaScript / TypeScript / Python / C# / PHP / Go",
5
5
  "unpkg": "dist/ccxt.browser.min.js",
6
6
  "type": "module",