@pear-protocol/symmio-client 0.3.13 → 0.3.15

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.
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { createContext, useContext, useMemo, useCallback, useRef, useEffect } from 'react';
2
+ import { createContext, useContext, useMemo, useCallback, useState, useRef, useEffect } from 'react';
3
3
  import { createSymmSDK, isAuthExpiredError, isNetworkError, isInsufficientMarginError, isRateLimitedError, isTimeoutError } from '@pear-protocol/symm-core';
4
4
  import { create } from 'zustand';
5
5
  import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
@@ -238,14 +238,20 @@ var BinanceWsManager = class {
238
238
  }
239
239
  }
240
240
  ensureConnected() {
241
- if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) {
242
- return;
241
+ if (this.ws) {
242
+ const state = this.ws.readyState;
243
+ if (state === WebSocket.OPEN || state === WebSocket.CONNECTING || state === WebSocket.CLOSING) {
244
+ return;
245
+ }
243
246
  }
244
247
  this.clearReconnectTimer();
245
248
  this.connect();
246
249
  }
247
250
  connect() {
248
251
  if (typeof WebSocket === "undefined") return;
252
+ if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
253
+ return;
254
+ }
249
255
  this.intentionalClose = false;
250
256
  this.ws = new WebSocket(BINANCE_WS_URL);
251
257
  this.ws.onopen = () => {
@@ -269,9 +275,17 @@ var BinanceWsManager = class {
269
275
  }
270
276
  };
271
277
  this.ws.onclose = () => {
278
+ const wasIntentional = this.intentionalClose;
279
+ this.intentionalClose = false;
272
280
  this.ws = null;
273
281
  this.clearStaleCheckTimer();
274
- if (this.intentionalClose) return;
282
+ if (this.streams.size === 0) {
283
+ return;
284
+ }
285
+ if (wasIntentional) {
286
+ this.connect();
287
+ return;
288
+ }
275
289
  this.scheduleReconnect();
276
290
  };
277
291
  this.ws.onerror = () => {
@@ -347,9 +361,6 @@ var BinanceWsManager = class {
347
361
  if (this.streams.size > 0 || !this.ws) return;
348
362
  this.intentionalClose = true;
349
363
  this.ws.close();
350
- this.ws = null;
351
- this.intentionalClose = false;
352
- this.clearStaleCheckTimer();
353
364
  }, IDLE_CLOSE_DELAY_MS);
354
365
  }
355
366
  startStaleCheck() {
@@ -377,12 +388,15 @@ var BinanceWsManager = class {
377
388
  this.staleCheckTimer = null;
378
389
  }
379
390
  };
380
- var _instance = null;
391
+ var BINANCE_WS_SINGLETON_KEY = "__pearBinanceWsManager__";
381
392
  function getBinanceWsManager() {
382
- if (!_instance) {
383
- _instance = new BinanceWsManager();
393
+ const g = globalThis;
394
+ let manager = g[BINANCE_WS_SINGLETON_KEY];
395
+ if (!manager) {
396
+ manager = new BinanceWsManager();
397
+ g[BINANCE_WS_SINGLETON_KEY] = manager;
384
398
  }
385
- return _instance;
399
+ return manager;
386
400
  }
387
401
 
388
402
  // src/react/stores/use-binance-mark-price-store.ts
@@ -576,7 +590,7 @@ var symmKeys = {
576
590
  signature: (address, chainId) => ["symm", "signature", address, chainId],
577
591
  auth: (accountAddress, chainId, signerAddress) => ["symm", "auth", accountAddress, chainId, signerAddress],
578
592
  approval: (owner, spender, chainId, token) => ["symm", "approval", owner, spender, chainId, token],
579
- balances: (address, chainId) => ["symm", "balances", address, chainId],
593
+ balances: (address, chainId, multiAccountAddress) => multiAccountAddress === void 0 ? ["symm", "balances", address, chainId] : ["symm", "balances", address, chainId, multiAccountAddress],
580
594
  positions: (params) => ["symm", "positions", params],
581
595
  openOrders: (params) => ["symm", "openOrders", params],
582
596
  tradeHistory: (params) => ["symm", "tradeHistory", params],
@@ -25633,6 +25647,616 @@ function useSymmAccountData(params) {
25633
25647
  enabled: internalEnabled && (params.query?.enabled ?? true)
25634
25648
  });
25635
25649
  }
25650
+
25651
+ // src/utils/account-pnl.ts
25652
+ function toNumber(value) {
25653
+ if (value === null || value === void 0 || value === "") {
25654
+ return 0;
25655
+ }
25656
+ const parsed = Number(value);
25657
+ return Number.isFinite(parsed) ? parsed : 0;
25658
+ }
25659
+ function readOpenedPrice(leg) {
25660
+ return toNumber(leg.openedPrice ?? leg.opened_price);
25661
+ }
25662
+ function readCurrentPrice(leg) {
25663
+ const parsed = Number(leg.currentPrice ?? leg.current_price);
25664
+ return Number.isFinite(parsed) ? parsed : void 0;
25665
+ }
25666
+ function readMarkPrice(leg, markPrices) {
25667
+ const symbol = leg.symbol?.trim().toUpperCase();
25668
+ if (symbol) {
25669
+ const markPrice = Number(markPrices[symbol]);
25670
+ if (Number.isFinite(markPrice)) {
25671
+ return markPrice;
25672
+ }
25673
+ }
25674
+ return readCurrentPrice(leg);
25675
+ }
25676
+ function getSymbol(leg) {
25677
+ return leg.symbol?.trim().toUpperCase() || void 0;
25678
+ }
25679
+ function computeLegUpnl(leg, side, markPrices) {
25680
+ const markPrice = readMarkPrice(leg, markPrices);
25681
+ if (markPrice === void 0) {
25682
+ return { upnl: 0, missingSymbol: getSymbol(leg) };
25683
+ }
25684
+ const quantity = toNumber(leg.quantity);
25685
+ const openedPrice = readOpenedPrice(leg);
25686
+ const direction = side === "short" ? -1 : 1;
25687
+ return {
25688
+ upnl: quantity * (markPrice - openedPrice) * direction
25689
+ };
25690
+ }
25691
+ function computeSymmPositionUpnl(position, markPrices = {}) {
25692
+ const missingSymbols = /* @__PURE__ */ new Set();
25693
+ let upnl = 0;
25694
+ let legsCount = 0;
25695
+ for (const leg of position.longAssets ?? []) {
25696
+ legsCount += 1;
25697
+ const result = computeLegUpnl(leg, "long", markPrices);
25698
+ upnl += result.upnl;
25699
+ if (result.missingSymbol) missingSymbols.add(result.missingSymbol);
25700
+ }
25701
+ for (const leg of position.shortAssets ?? []) {
25702
+ legsCount += 1;
25703
+ const result = computeLegUpnl(leg, "short", markPrices);
25704
+ upnl += result.upnl;
25705
+ if (result.missingSymbol) missingSymbols.add(result.missingSymbol);
25706
+ }
25707
+ if (legsCount === 0) {
25708
+ return {
25709
+ upnl: toNumber(position.unrealizedPnl ?? position.unrealized_pnl),
25710
+ missingSymbols: [],
25711
+ positionsCount: 1,
25712
+ legsCount,
25713
+ usedFallbackPositions: 1
25714
+ };
25715
+ }
25716
+ return {
25717
+ upnl,
25718
+ missingSymbols: Array.from(missingSymbols),
25719
+ positionsCount: 1,
25720
+ legsCount,
25721
+ usedFallbackPositions: 0
25722
+ };
25723
+ }
25724
+ function computeSymmPositionsUpnl(positions = [], markPrices = {}) {
25725
+ const missingSymbols = /* @__PURE__ */ new Set();
25726
+ let upnl = 0;
25727
+ let legsCount = 0;
25728
+ let usedFallbackPositions = 0;
25729
+ for (const position of positions) {
25730
+ const result = computeSymmPositionUpnl(position, markPrices);
25731
+ upnl += result.upnl;
25732
+ legsCount += result.legsCount;
25733
+ usedFallbackPositions += result.usedFallbackPositions;
25734
+ result.missingSymbols.forEach((symbol) => missingSymbols.add(symbol));
25735
+ }
25736
+ return {
25737
+ upnl,
25738
+ missingSymbols: Array.from(missingSymbols),
25739
+ positionsCount: positions.length,
25740
+ legsCount,
25741
+ usedFallbackPositions
25742
+ };
25743
+ }
25744
+ function readMessageNumber(message, keys) {
25745
+ for (const key of keys) {
25746
+ if (key in message) {
25747
+ return toNumber(message[key]);
25748
+ }
25749
+ }
25750
+ return 0;
25751
+ }
25752
+ function normalizeSymmUpnlWebSocketMessage(raw) {
25753
+ if (typeof raw !== "object" || raw === null) {
25754
+ return void 0;
25755
+ }
25756
+ const message = raw;
25757
+ const timestamp = readMessageNumber(message, ["timestamp"]);
25758
+ return {
25759
+ upnl: readMessageNumber(message, ["upnl"]),
25760
+ timestamp: timestamp || void 0,
25761
+ availableBalance: readMessageNumber(message, [
25762
+ "availableBalance",
25763
+ "available_balance"
25764
+ ]),
25765
+ allocatedBalance: readMessageNumber(message, [
25766
+ "allocatedBalance",
25767
+ "allocated_balance"
25768
+ ]),
25769
+ cva: readMessageNumber(message, ["cva"]),
25770
+ lf: readMessageNumber(message, ["lf"]),
25771
+ partyAmm: readMessageNumber(message, ["partyAmm", "party_a_mm", "mm"]),
25772
+ pendingPartyAmm: readMessageNumber(message, [
25773
+ "pendingPartyAmm",
25774
+ "pending_party_a_mm",
25775
+ "pending_mm"
25776
+ ]),
25777
+ pendingCva: readMessageNumber(message, ["pendingCva", "pending_cva"]),
25778
+ pendingLf: readMessageNumber(message, ["pendingLf", "pending_lf"]),
25779
+ raw
25780
+ };
25781
+ }
25782
+ function useSymmPositions(params) {
25783
+ const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
25784
+ const { accountAddress, address } = params;
25785
+ const resolvedAddress = accountAddress ? void 0 : address;
25786
+ const chainId = params.chainId ?? ctxChainId;
25787
+ const internalEnabled = !!symmCoreClient && !!(accountAddress || resolvedAddress);
25788
+ const enabled = internalEnabled && (params.query?.enabled ?? true);
25789
+ return useQuery({
25790
+ ...params.query,
25791
+ queryKey: symmKeys.positions({
25792
+ accountAddress,
25793
+ address: resolvedAddress,
25794
+ chainId
25795
+ }),
25796
+ queryFn: () => symmCoreClient.positions.getOpen({
25797
+ accountAddress,
25798
+ address: resolvedAddress,
25799
+ chainId
25800
+ }),
25801
+ enabled
25802
+ });
25803
+ }
25804
+
25805
+ // src/react/hooks/use-symm-account-current-pnl.ts
25806
+ function readPositions(response) {
25807
+ if (typeof response !== "object" || response === null) {
25808
+ return [];
25809
+ }
25810
+ const data = response.data;
25811
+ if (typeof data !== "object" || data === null) {
25812
+ return [];
25813
+ }
25814
+ const positions = data.positions;
25815
+ return Array.isArray(positions) ? positions : [];
25816
+ }
25817
+ function useSymmAccountCurrentPnl(params) {
25818
+ const { accountAddress, address, positions, query } = params;
25819
+ const liveMarkPrices = useBinanceMarkPriceStore((state) => state.markPrices);
25820
+ const positionsQuery = useSymmPositions({
25821
+ accountAddress,
25822
+ address,
25823
+ chainId: params.chainId,
25824
+ query: {
25825
+ ...query,
25826
+ enabled: positions === void 0 && (query?.enabled ?? true)
25827
+ }
25828
+ });
25829
+ const resolvedPositions = positions ?? readPositions(positionsQuery.data);
25830
+ const pnl = useMemo(
25831
+ () => computeSymmPositionsUpnl(resolvedPositions, liveMarkPrices),
25832
+ [liveMarkPrices, resolvedPositions]
25833
+ );
25834
+ return {
25835
+ ...pnl,
25836
+ value: pnl.upnl,
25837
+ positions: resolvedPositions,
25838
+ positionsQuery
25839
+ };
25840
+ }
25841
+
25842
+ // src/utils/account-overview.ts
25843
+ var BALANCE_INFO_KEYS = [
25844
+ "allocatedBalance",
25845
+ "allocated_balance",
25846
+ "cva",
25847
+ "lf",
25848
+ "partyAmm",
25849
+ "partyAMM",
25850
+ "party_a_mm",
25851
+ "mm",
25852
+ "lockedPartyAMM",
25853
+ "upnl"
25854
+ ];
25855
+ function isRecord(value) {
25856
+ return typeof value === "object" && value !== null;
25857
+ }
25858
+ function hasBalanceInfoShape(value) {
25859
+ return isRecord(value) && BALANCE_INFO_KEYS.some((key) => key in value);
25860
+ }
25861
+ function readValue(source, keys) {
25862
+ for (const key of keys) {
25863
+ if (key in source) {
25864
+ return source[key];
25865
+ }
25866
+ }
25867
+ return void 0;
25868
+ }
25869
+ function toNumber2(value) {
25870
+ if (value === null || value === void 0 || value === "") {
25871
+ return 0;
25872
+ }
25873
+ if (typeof value === "bigint") {
25874
+ return Number(value);
25875
+ }
25876
+ const parsed = Number(value);
25877
+ return Number.isFinite(parsed) ? parsed : 0;
25878
+ }
25879
+ function toDisplayString(value) {
25880
+ if (Object.is(value, -0) || Math.abs(value) < Number.EPSILON) {
25881
+ return "0";
25882
+ }
25883
+ return String(value);
25884
+ }
25885
+ function readNumber(source, keys) {
25886
+ return toNumber2(readValue(source, keys));
25887
+ }
25888
+ function readTimestamp(source) {
25889
+ const timestamp = readValue(source, ["timestamp"]);
25890
+ if (timestamp === void 0 || timestamp === null) {
25891
+ return void 0;
25892
+ }
25893
+ const parsed = Number(timestamp);
25894
+ return Number.isFinite(parsed) ? parsed : void 0;
25895
+ }
25896
+ function getSymmAccountData(response) {
25897
+ if (!isRecord(response)) {
25898
+ return void 0;
25899
+ }
25900
+ const data = response.data;
25901
+ if (isRecord(data)) {
25902
+ return data;
25903
+ }
25904
+ if ("equity" in response || "maintenanceMargin" in response || "availableForOrder" in response || "totalLocked" in response) {
25905
+ return response;
25906
+ }
25907
+ return void 0;
25908
+ }
25909
+ function getBalanceInfoContainer(response) {
25910
+ if (!isRecord(response)) {
25911
+ return void 0;
25912
+ }
25913
+ if (hasBalanceInfoShape(response)) {
25914
+ return response;
25915
+ }
25916
+ const data = response.data;
25917
+ if (isRecord(data)) {
25918
+ return data;
25919
+ }
25920
+ return response;
25921
+ }
25922
+ function getSymmAccountBalanceInfo(response, accountAddress) {
25923
+ const container = getBalanceInfoContainer(response);
25924
+ if (!container) {
25925
+ return void 0;
25926
+ }
25927
+ if (hasBalanceInfoShape(container)) {
25928
+ return container;
25929
+ }
25930
+ if (accountAddress) {
25931
+ const normalizedAddress = accountAddress.toLowerCase();
25932
+ const direct = container[accountAddress] ?? container[normalizedAddress];
25933
+ if (isRecord(direct) && hasBalanceInfoShape(direct)) {
25934
+ return direct;
25935
+ }
25936
+ const matchingEntry = Object.entries(container).find(
25937
+ ([key]) => key.toLowerCase() === normalizedAddress
25938
+ );
25939
+ if (isRecord(matchingEntry?.[1]) && hasBalanceInfoShape(matchingEntry[1])) {
25940
+ return matchingEntry[1];
25941
+ }
25942
+ }
25943
+ const values = Object.values(container);
25944
+ if (values.length === 1 && isRecord(values[0]) && hasBalanceInfoShape(values[0])) {
25945
+ return values[0];
25946
+ }
25947
+ return void 0;
25948
+ }
25949
+ function computeSymmAccountOverview({
25950
+ balanceInfo,
25951
+ upnl: upnlOverride,
25952
+ netDeposited
25953
+ }) {
25954
+ const allocatedBalance = readNumber(balanceInfo, [
25955
+ "allocatedBalance",
25956
+ "allocated_balance"
25957
+ ]);
25958
+ const cva = readNumber(balanceInfo, ["cva", "lockedCVA", "locked_cva"]);
25959
+ const lf = readNumber(balanceInfo, ["lf", "lockedLF", "locked_lf"]);
25960
+ const partyAmm = readNumber(balanceInfo, [
25961
+ "partyAmm",
25962
+ "partyAMM",
25963
+ "party_a_mm",
25964
+ "mm",
25965
+ "lockedPartyAMM",
25966
+ "locked_party_a_mm"
25967
+ ]);
25968
+ const pendingCva = readNumber(balanceInfo, [
25969
+ "pendingCva",
25970
+ "pending_cva",
25971
+ "pendingLockedCVA",
25972
+ "pending_locked_cva"
25973
+ ]);
25974
+ const pendingLf = readNumber(balanceInfo, [
25975
+ "pendingLf",
25976
+ "pending_lf",
25977
+ "pendingLockedLF",
25978
+ "pending_locked_lf"
25979
+ ]);
25980
+ const pendingPartyAmm = readNumber(balanceInfo, [
25981
+ "pendingPartyAmm",
25982
+ "pendingPartyAMM",
25983
+ "pending_party_a_mm",
25984
+ "pendingMm",
25985
+ "pending_mm",
25986
+ "pendingLockedPartyAMM",
25987
+ "pending_locked_party_a_mm"
25988
+ ]);
25989
+ const upnl = upnlOverride === void 0 ? readNumber(balanceInfo, ["upnl"]) : toNumber2(upnlOverride);
25990
+ const computedTotalLocked = cva + lf + partyAmm;
25991
+ const totalLocked = readValue(
25992
+ balanceInfo,
25993
+ ["totalLocked", "total_locked"]
25994
+ ) === void 0 ? computedTotalLocked : readNumber(balanceInfo, ["totalLocked", "total_locked"]);
25995
+ const totalPendingLocked = readValue(balanceInfo, [
25996
+ "totalPendingLocked",
25997
+ "total_pending_locked"
25998
+ ]) === void 0 ? pendingCva + pendingLf + pendingPartyAmm : readNumber(balanceInfo, ["totalPendingLocked", "total_pending_locked"]);
25999
+ const maintenanceMargin = cva + lf;
26000
+ const equity = allocatedBalance + upnl;
26001
+ const availableForOrder = upnl >= 0 ? allocatedBalance + upnl - totalLocked - totalPendingLocked : allocatedBalance - cva - lf - totalPendingLocked - Math.max(Math.abs(upnl), partyAmm);
26002
+ const availableBalance = readNumber(balanceInfo, [
26003
+ "availableBalance",
26004
+ "available_balance"
26005
+ ]);
26006
+ const notional = readNumber(balanceInfo, ["notional"]);
26007
+ return {
26008
+ allocatedBalance: toDisplayString(allocatedBalance),
26009
+ upnl: toDisplayString(upnl),
26010
+ equity: toDisplayString(equity),
26011
+ totalAccountValue: toDisplayString(equity),
26012
+ maintenanceMargin: toDisplayString(maintenanceMargin),
26013
+ totalLocked: toDisplayString(totalLocked),
26014
+ marginUsed: toDisplayString(computedTotalLocked),
26015
+ totalPendingLocked: toDisplayString(totalPendingLocked),
26016
+ availableForOrder: toDisplayString(availableForOrder),
26017
+ availableMargin: toDisplayString(availableForOrder),
26018
+ availableBalance: toDisplayString(availableBalance),
26019
+ netDeposited: toDisplayString(toNumber2(netDeposited)),
26020
+ notional: toDisplayString(notional),
26021
+ timestamp: readTimestamp(balanceInfo)
26022
+ };
26023
+ }
26024
+ function computeSymmAccountOverviewFromData({
26025
+ accountData,
26026
+ upnl,
26027
+ netDeposited
26028
+ }) {
26029
+ const equity = readNumber(accountData, ["equity"]);
26030
+ const maintenanceMargin = readNumber(accountData, [
26031
+ "maintenanceMargin",
26032
+ "maintenance_margin"
26033
+ ]);
26034
+ const availableForOrder = readNumber(accountData, [
26035
+ "availableForOrder",
26036
+ "available_for_order"
26037
+ ]);
26038
+ const totalLocked = readNumber(accountData, ["totalLocked", "total_locked"]);
26039
+ return {
26040
+ allocatedBalance: "0",
26041
+ upnl: toDisplayString(toNumber2(upnl)),
26042
+ equity: toDisplayString(equity),
26043
+ totalAccountValue: toDisplayString(equity),
26044
+ maintenanceMargin: toDisplayString(maintenanceMargin),
26045
+ accountHealthData: accountData.accountHealthData,
26046
+ totalLocked: toDisplayString(totalLocked),
26047
+ marginUsed: toDisplayString(totalLocked),
26048
+ totalPendingLocked: "0",
26049
+ availableForOrder: toDisplayString(availableForOrder),
26050
+ availableMargin: toDisplayString(availableForOrder),
26051
+ availableBalance: toDisplayString(availableForOrder),
26052
+ netDeposited: toDisplayString(toNumber2(netDeposited)),
26053
+ notional: "0"
26054
+ };
26055
+ }
26056
+ function computeSymmNetDeposited(totals, decimals = 6) {
26057
+ if (!totals) {
26058
+ return "0";
26059
+ }
26060
+ const deposit2 = parseRawCollateralUnits(totals.deposit);
26061
+ const withdraw2 = parseRawCollateralUnits(totals.withdraw);
26062
+ const value = deposit2 - withdraw2;
26063
+ const negative = value < 0n;
26064
+ const absolute = negative ? -value : value;
26065
+ const scale = 10n ** BigInt(decimals);
26066
+ const whole = absolute / scale;
26067
+ const fraction = absolute % scale;
26068
+ const fractionText = fraction.toString().padStart(decimals, "0").replace(/0+$/, "");
26069
+ const amount = fractionText ? `${whole}.${fractionText}` : whole.toString();
26070
+ return negative ? `-${amount}` : amount;
26071
+ }
26072
+ function parseRawCollateralUnits(value) {
26073
+ if (value === null || value === void 0 || value === "") {
26074
+ return 0n;
26075
+ }
26076
+ if (typeof value === "bigint") {
26077
+ return value;
26078
+ }
26079
+ if (typeof value === "number") {
26080
+ if (!Number.isSafeInteger(value)) {
26081
+ throw new Error("Raw collateral unit numbers must be safe integers");
26082
+ }
26083
+ return BigInt(value);
26084
+ }
26085
+ if (!/^-?\d+$/.test(value)) {
26086
+ throw new Error("Raw collateral unit strings must be base-10 integers");
26087
+ }
26088
+ return BigInt(value);
26089
+ }
26090
+
26091
+ // src/react/hooks/use-symm-account-overview.ts
26092
+ function useSymmAccountOverview(params) {
26093
+ const {
26094
+ userAddress,
26095
+ accountAddress,
26096
+ upnl,
26097
+ netDeposited,
26098
+ positions,
26099
+ currentPnlQuery
26100
+ } = params;
26101
+ const address = accountAddress ?? userAddress;
26102
+ const shouldUseLocalPnl = upnl === void 0;
26103
+ const currentPnl = useSymmAccountCurrentPnl({
26104
+ accountAddress: address,
26105
+ positions,
26106
+ chainId: params.chainId,
26107
+ query: {
26108
+ ...currentPnlQuery,
26109
+ enabled: shouldUseLocalPnl && (currentPnlQuery?.enabled ?? true)
26110
+ }
26111
+ });
26112
+ const resolvedUpnl = shouldUseLocalPnl ? currentPnl.value : upnl;
26113
+ const upnlReady = !shouldUseLocalPnl || positions !== void 0 || currentPnl.positionsQuery.isSuccess;
26114
+ const query = useSymmAccountData({
26115
+ address,
26116
+ upnl: upnlReady ? String(resolvedUpnl ?? 0) : void 0,
26117
+ chainId: params.chainId,
26118
+ query: {
26119
+ ...params.query,
26120
+ enabled: upnlReady && (params.query?.enabled ?? true)
26121
+ }
26122
+ });
26123
+ const data = useMemo(() => {
26124
+ if (query.data === void 0) {
26125
+ return void 0;
26126
+ }
26127
+ const accountData = getSymmAccountData(query.data);
26128
+ return {
26129
+ response: query.data,
26130
+ accountData,
26131
+ coreAccountData: accountData,
26132
+ currentPnl,
26133
+ overview: accountData ? computeSymmAccountOverviewFromData({
26134
+ accountData,
26135
+ upnl: resolvedUpnl,
26136
+ netDeposited
26137
+ }) : void 0
26138
+ };
26139
+ }, [currentPnl, netDeposited, query.data, resolvedUpnl]);
26140
+ return { ...query, data };
26141
+ }
26142
+ function parseMessageData(data) {
26143
+ if (typeof data !== "string") {
26144
+ return data;
26145
+ }
26146
+ try {
26147
+ return JSON.parse(data);
26148
+ } catch {
26149
+ return void 0;
26150
+ }
26151
+ }
26152
+ function toBalanceInfo(message) {
26153
+ return {
26154
+ allocatedBalance: message.allocatedBalance,
26155
+ cva: message.cva,
26156
+ lf: message.lf,
26157
+ partyAmm: message.partyAmm,
26158
+ pendingCva: message.pendingCva,
26159
+ pendingLf: message.pendingLf,
26160
+ pendingPartyAmm: message.pendingPartyAmm,
26161
+ upnl: message.upnl,
26162
+ availableBalance: message.availableBalance,
26163
+ timestamp: message.timestamp
26164
+ };
26165
+ }
26166
+ function useSymmUpnlWebSocket(params) {
26167
+ const {
26168
+ url,
26169
+ accountAddress,
26170
+ enabled = true,
26171
+ reconnectAttempts = 2,
26172
+ reconnectDelayMs = 1e3,
26173
+ webSocketFactory
26174
+ } = params;
26175
+ const [data, setData] = useState();
26176
+ const [status, setStatus] = useState("idle");
26177
+ const [error, setError] = useState();
26178
+ const socketRef = useRef(null);
26179
+ const sendAccountAddress = useCallback(() => {
26180
+ if (!accountAddress || socketRef.current?.readyState !== 1) {
26181
+ return;
26182
+ }
26183
+ socketRef.current.send(accountAddress);
26184
+ }, [accountAddress]);
26185
+ useEffect(() => {
26186
+ if (!enabled || !url || !accountAddress) {
26187
+ setStatus("idle");
26188
+ setData(void 0);
26189
+ setError(void 0);
26190
+ return;
26191
+ }
26192
+ const createSocket = webSocketFactory ?? ((wsUrl) => new WebSocket(wsUrl));
26193
+ let closedByHook = false;
26194
+ let reconnectCount = 0;
26195
+ let reconnectTimer;
26196
+ const connect = () => {
26197
+ setStatus("connecting");
26198
+ const socket = createSocket(url);
26199
+ socketRef.current = socket;
26200
+ socket.onopen = () => {
26201
+ reconnectCount = 0;
26202
+ setStatus("open");
26203
+ setError(void 0);
26204
+ socket.send(accountAddress);
26205
+ };
26206
+ socket.onmessage = (event) => {
26207
+ const parsed = parseMessageData(event.data);
26208
+ const nextMessage = normalizeSymmUpnlWebSocketMessage(parsed);
26209
+ if (nextMessage) {
26210
+ setData(nextMessage);
26211
+ }
26212
+ };
26213
+ socket.onerror = (event) => {
26214
+ setError(event);
26215
+ setStatus("error");
26216
+ };
26217
+ socket.onclose = () => {
26218
+ if (closedByHook) {
26219
+ setStatus("closed");
26220
+ return;
26221
+ }
26222
+ if (reconnectCount < reconnectAttempts) {
26223
+ reconnectCount += 1;
26224
+ reconnectTimer = setTimeout(connect, reconnectDelayMs);
26225
+ return;
26226
+ }
26227
+ setStatus("closed");
26228
+ };
26229
+ };
26230
+ connect();
26231
+ return () => {
26232
+ closedByHook = true;
26233
+ if (reconnectTimer) {
26234
+ clearTimeout(reconnectTimer);
26235
+ }
26236
+ socketRef.current?.close();
26237
+ socketRef.current = null;
26238
+ };
26239
+ }, [
26240
+ accountAddress,
26241
+ enabled,
26242
+ reconnectAttempts,
26243
+ reconnectDelayMs,
26244
+ url,
26245
+ webSocketFactory
26246
+ ]);
26247
+ const balanceInfo = useMemo(
26248
+ () => data ? toBalanceInfo(data) : void 0,
26249
+ [data]
26250
+ );
26251
+ return {
26252
+ data,
26253
+ upnl: data?.upnl,
26254
+ balanceInfo,
26255
+ status,
26256
+ error,
26257
+ sendAccountAddress
26258
+ };
26259
+ }
25636
26260
  function useSymmBalances(params) {
25637
26261
  const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
25638
26262
  const { userAddress, multiAccountAddress } = params;
@@ -25640,7 +26264,7 @@ function useSymmBalances(params) {
25640
26264
  const internalEnabled = !!symmCoreClient && !!userAddress;
25641
26265
  return useQuery({
25642
26266
  ...params.query,
25643
- queryKey: symmKeys.balances(userAddress, chainId),
26267
+ queryKey: symmKeys.balances(userAddress, chainId, multiAccountAddress),
25644
26268
  queryFn: () => symmCoreClient.accounts.getBalanceInfo({
25645
26269
  userAddress,
25646
26270
  chainId,
@@ -25779,28 +26403,6 @@ function useSymmUpdatePositionMutation(paramsOrOptions, maybeOptions) {
25779
26403
  }
25780
26404
  });
25781
26405
  }
25782
- function useSymmPositions(params) {
25783
- const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
25784
- const { accountAddress, address } = params;
25785
- const resolvedAddress = accountAddress ? void 0 : address;
25786
- const chainId = params.chainId ?? ctxChainId;
25787
- const internalEnabled = !!symmCoreClient && !!(accountAddress || resolvedAddress);
25788
- const enabled = internalEnabled && (params.query?.enabled ?? true);
25789
- return useQuery({
25790
- ...params.query,
25791
- queryKey: symmKeys.positions({
25792
- accountAddress,
25793
- address: resolvedAddress,
25794
- chainId
25795
- }),
25796
- queryFn: () => symmCoreClient.positions.getOpen({
25797
- accountAddress,
25798
- address: resolvedAddress,
25799
- chainId
25800
- }),
25801
- enabled
25802
- });
25803
- }
25804
26406
  function useSymmOpenOrders(params) {
25805
26407
  const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
25806
26408
  const { accountAddress, address } = params;
@@ -27221,6 +27823,6 @@ function getSymmErrorMessage(error) {
27221
27823
  return "An unexpected error occurred.";
27222
27824
  }
27223
27825
 
27224
- export { SymmProvider, getSymmErrorMessage, symmKeys, useBinanceMarkPriceStore, useSymmAccountData, useSymmAccountSummary, useSymmAccountsApi, useSymmAccountsLength, useSymmAccountsQuery, useSymmAccountsWithPositions, useSymmAllocateCollateralMutation, useSymmApprovalQuery, useSymmApproveMutation, useSymmAuth, useSymmAvailableMargin, useSymmBalances, useSymmCancelClose, useSymmCancelOpenMutation, useSymmCancelTpslMutation, useSymmCancelTwapOrderMutation, useSymmChartCandles, useSymmChartSelection, useSymmClearTriggerConfigMutation, useSymmCloseAllPositionsMutation, useSymmCloseOrder, useSymmClosePositionMutation, useSymmContext, useSymmCoreClient, useSymmCreateAccountMutation, useSymmDeallocateCollateralMutation, useSymmDelegateAccessMutation, useSymmDelegation, useSymmDepositAndAllocateMutation, useSymmDepositMutation, useSymmEditAccountNameMutation, useSymmFunding, useSymmFundingHistory, useSymmFundingPayments, useSymmHedgerMarketById, useSymmHedgerMarketBySymbol, useSymmHedgerMarkets, useSymmInstantTradeEnsureReadyMutation, useSymmInstantTradeExecuteMutation, useSymmInternalTransferCollateralMutation, useSymmLockedParams, useSymmMarkReadNotificationMutation, useSymmMarkets, useSymmNotificationsQuery, useSymmOpenBasketMutation, useSymmOpenOrders, useSymmPendingIds, useSymmPendingInstantOpens, useSymmPerformanceOverlays, useSymmPortfolio, useSymmPositions, useSymmProposeRevokeDelegationMutation, useSymmRevokeDelegationMutation, useSymmSetTpslMutation, useSymmSetTriggerConfigMutation, useSymmSignTermsMutation, useSymmSignatureQuery, useSymmTokenMarkPrice, useSymmTokenSelectionMarkets, useSymmTokenSelectionMetadata, useSymmTpslOrders, useSymmTradeHistory, useSymmTriggerConfigQuery, useSymmTriggerOrders, useSymmTwapOrder, useSymmTwapOrdersQuery, useSymmUnreadCountQuery, useSymmUpdatePositionMutation, useSymmWithdraw, useSymmWsStore };
27826
+ export { SymmProvider, computeSymmAccountOverview, computeSymmAccountOverviewFromData, computeSymmNetDeposited, computeSymmPositionUpnl, computeSymmPositionsUpnl, getSymmAccountBalanceInfo, getSymmAccountData, getSymmErrorMessage, normalizeSymmUpnlWebSocketMessage, symmKeys, useBinanceMarkPriceStore, useSymmAccountCurrentPnl, useSymmAccountData, useSymmAccountOverview, useSymmAccountSummary, useSymmAccountsApi, useSymmAccountsLength, useSymmAccountsQuery, useSymmAccountsWithPositions, useSymmAllocateCollateralMutation, useSymmApprovalQuery, useSymmApproveMutation, useSymmAuth, useSymmAvailableMargin, useSymmBalances, useSymmCancelClose, useSymmCancelOpenMutation, useSymmCancelTpslMutation, useSymmCancelTwapOrderMutation, useSymmChartCandles, useSymmChartSelection, useSymmClearTriggerConfigMutation, useSymmCloseAllPositionsMutation, useSymmCloseOrder, useSymmClosePositionMutation, useSymmContext, useSymmCoreClient, useSymmCreateAccountMutation, useSymmDeallocateCollateralMutation, useSymmDelegateAccessMutation, useSymmDelegation, useSymmDepositAndAllocateMutation, useSymmDepositMutation, useSymmEditAccountNameMutation, useSymmFunding, useSymmFundingHistory, useSymmFundingPayments, useSymmHedgerMarketById, useSymmHedgerMarketBySymbol, useSymmHedgerMarkets, useSymmInstantTradeEnsureReadyMutation, useSymmInstantTradeExecuteMutation, useSymmInternalTransferCollateralMutation, useSymmLockedParams, useSymmMarkReadNotificationMutation, useSymmMarkets, useSymmNotificationsQuery, useSymmOpenBasketMutation, useSymmOpenOrders, useSymmPendingIds, useSymmPendingInstantOpens, useSymmPerformanceOverlays, useSymmPortfolio, useSymmPositions, useSymmProposeRevokeDelegationMutation, useSymmRevokeDelegationMutation, useSymmSetTpslMutation, useSymmSetTriggerConfigMutation, useSymmSignTermsMutation, useSymmSignatureQuery, useSymmTokenMarkPrice, useSymmTokenSelectionMarkets, useSymmTokenSelectionMetadata, useSymmTpslOrders, useSymmTradeHistory, useSymmTriggerConfigQuery, useSymmTriggerOrders, useSymmTwapOrder, useSymmTwapOrdersQuery, useSymmUnreadCountQuery, useSymmUpdatePositionMutation, useSymmUpnlWebSocket, useSymmWithdraw, useSymmWsStore };
27225
27827
  //# sourceMappingURL=index.mjs.map
27226
27828
  //# sourceMappingURL=index.mjs.map