@pear-protocol/symmio-client 0.3.14 → 0.3.16

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';
@@ -73,6 +73,7 @@ var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
73
73
  var IDLE_CLOSE_DELAY_MS = 3e4;
74
74
  var STALE_CONNECTION_MS = 3e4;
75
75
  var STALE_CHECK_INTERVAL_MS = 1e4;
76
+ var RECONNECT_RESET_MS = 6e4;
76
77
  var STABLE_QUOTES = ["USDT0", "USDT", "USDC", "USDE", "USDH", "USD"];
77
78
  function normalizeBaseSymbol(symbol) {
78
79
  const normalized = symbol.toUpperCase().trim();
@@ -124,6 +125,7 @@ var BinanceWsManager = class {
124
125
  reconnectTimer = null;
125
126
  idleCloseTimer = null;
126
127
  staleCheckTimer = null;
128
+ reconnectResetTimer = null;
127
129
  intentionalClose = false;
128
130
  pendingSubscribes = /* @__PURE__ */ new Set();
129
131
  lastMessageAt = 0;
@@ -162,6 +164,7 @@ var BinanceWsManager = class {
162
164
  const wrappedCb = (raw) => {
163
165
  cb({
164
166
  symbol: normalizeBaseSymbol(raw.s),
167
+ binanceSymbol: raw.s,
165
168
  markPrice: parseFloat(raw.p),
166
169
  indexPrice: parseFloat(raw.i),
167
170
  time: raw.E,
@@ -183,6 +186,7 @@ var BinanceWsManager = class {
183
186
  cb(
184
187
  extractTickers(raw).map((entry) => ({
185
188
  symbol: normalizeBaseSymbol(entry.s),
189
+ binanceSymbol: entry.s,
186
190
  markPrice: parseFloat(entry.p),
187
191
  indexPrice: parseFloat(entry.i),
188
192
  time: entry.E,
@@ -202,6 +206,7 @@ var BinanceWsManager = class {
202
206
  this.clearReconnectTimer();
203
207
  this.clearIdleCloseTimer();
204
208
  this.clearStaleCheckTimer();
209
+ this.clearReconnectResetTimer();
205
210
  this.pendingSubscribes.clear();
206
211
  if (this.ws) {
207
212
  this.ws.close();
@@ -238,20 +243,26 @@ var BinanceWsManager = class {
238
243
  }
239
244
  }
240
245
  ensureConnected() {
241
- if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) {
242
- return;
246
+ if (this.ws) {
247
+ const state = this.ws.readyState;
248
+ if (state === WebSocket.OPEN || state === WebSocket.CONNECTING || state === WebSocket.CLOSING) {
249
+ return;
250
+ }
243
251
  }
244
252
  this.clearReconnectTimer();
245
253
  this.connect();
246
254
  }
247
255
  connect() {
248
256
  if (typeof WebSocket === "undefined") return;
257
+ if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
258
+ return;
259
+ }
249
260
  this.intentionalClose = false;
250
261
  this.ws = new WebSocket(BINANCE_WS_URL);
251
262
  this.ws.onopen = () => {
252
- this.reconnectAttempt = 0;
253
263
  this.lastMessageAt = Date.now();
254
264
  this.startStaleCheck();
265
+ this.scheduleReconnectReset();
255
266
  const activeStreams = Array.from(
256
267
  /* @__PURE__ */ new Set([...this.streams.keys(), ...this.pendingSubscribes])
257
268
  );
@@ -264,14 +275,24 @@ var BinanceWsManager = class {
264
275
  try {
265
276
  const data = JSON.parse(event.data);
266
277
  this.lastMessageAt = Date.now();
278
+ this.resetReconnectAttempt();
267
279
  this.handleMessage(data);
268
280
  } catch {
269
281
  }
270
282
  };
271
283
  this.ws.onclose = () => {
284
+ const wasIntentional = this.intentionalClose;
285
+ this.intentionalClose = false;
272
286
  this.ws = null;
273
287
  this.clearStaleCheckTimer();
274
- if (this.intentionalClose) return;
288
+ this.clearReconnectResetTimer();
289
+ if (this.streams.size === 0) {
290
+ return;
291
+ }
292
+ if (wasIntentional) {
293
+ this.connect();
294
+ return;
295
+ }
275
296
  this.scheduleReconnect();
276
297
  };
277
298
  this.ws.onerror = () => {
@@ -347,9 +368,6 @@ var BinanceWsManager = class {
347
368
  if (this.streams.size > 0 || !this.ws) return;
348
369
  this.intentionalClose = true;
349
370
  this.ws.close();
350
- this.ws = null;
351
- this.intentionalClose = false;
352
- this.clearStaleCheckTimer();
353
371
  }, IDLE_CLOSE_DELAY_MS);
354
372
  }
355
373
  startStaleCheck() {
@@ -361,6 +379,17 @@ var BinanceWsManager = class {
361
379
  this.ws.close();
362
380
  }, STALE_CHECK_INTERVAL_MS);
363
381
  }
382
+ scheduleReconnectReset() {
383
+ this.clearReconnectResetTimer();
384
+ this.reconnectResetTimer = setTimeout(() => {
385
+ this.reconnectResetTimer = null;
386
+ this.resetReconnectAttempt();
387
+ }, RECONNECT_RESET_MS);
388
+ }
389
+ resetReconnectAttempt() {
390
+ this.reconnectAttempt = 0;
391
+ this.clearReconnectResetTimer();
392
+ }
364
393
  clearReconnectTimer() {
365
394
  if (!this.reconnectTimer) return;
366
395
  clearTimeout(this.reconnectTimer);
@@ -376,13 +405,21 @@ var BinanceWsManager = class {
376
405
  clearInterval(this.staleCheckTimer);
377
406
  this.staleCheckTimer = null;
378
407
  }
408
+ clearReconnectResetTimer() {
409
+ if (!this.reconnectResetTimer) return;
410
+ clearTimeout(this.reconnectResetTimer);
411
+ this.reconnectResetTimer = null;
412
+ }
379
413
  };
380
- var _instance = null;
414
+ var BINANCE_WS_SINGLETON_KEY = "__pearBinanceWsManager__";
381
415
  function getBinanceWsManager() {
382
- if (!_instance) {
383
- _instance = new BinanceWsManager();
416
+ const g = globalThis;
417
+ let manager = g[BINANCE_WS_SINGLETON_KEY];
418
+ if (!manager) {
419
+ manager = new BinanceWsManager();
420
+ g[BINANCE_WS_SINGLETON_KEY] = manager;
384
421
  }
385
- return _instance;
422
+ return manager;
386
423
  }
387
424
 
388
425
  // src/react/stores/use-binance-mark-price-store.ts
@@ -390,15 +427,8 @@ var refCounts = /* @__PURE__ */ new Map();
390
427
  var streamSymbols = /* @__PURE__ */ new Map();
391
428
  var allMarkPricesRefCount = 0;
392
429
  var allMarkPricesUnsubscribe = null;
393
- var STABLE_QUOTES2 = ["USDT0", "USDT", "USDC", "USDE", "USDH", "USD"];
394
- function normalizeBinanceSymbol(symbol) {
395
- const normalized = symbol.toUpperCase().trim();
396
- for (const quote of STABLE_QUOTES2) {
397
- if (normalized.endsWith(quote) && normalized.length > quote.length) {
398
- return normalized.slice(0, -quote.length);
399
- }
400
- }
401
- return normalized;
430
+ function normalizeBinanceSymbolKey(symbol) {
431
+ return symbol.toUpperCase().trim();
402
432
  }
403
433
  function getNextRefCount(binanceSymbol) {
404
434
  return (refCounts.get(binanceSymbol) ?? 0) + 1;
@@ -433,7 +463,7 @@ var useBinanceMarkPriceStore = create((set) => ({
433
463
  fundingRates: {},
434
464
  nextFundingTimes: {},
435
465
  subscribeSymbol: (symmSymbol, rawBinanceSymbol) => {
436
- const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
466
+ const binanceSymbol = normalizeBinanceSymbolKey(rawBinanceSymbol);
437
467
  const nextRefCount = getNextRefCount(binanceSymbol);
438
468
  refCounts.set(binanceSymbol, nextRefCount);
439
469
  addMappedSymbol(binanceSymbol, symmSymbol);
@@ -445,8 +475,10 @@ var useBinanceMarkPriceStore = create((set) => ({
445
475
  let nextFundingRates = null;
446
476
  let nextFundingTimes = null;
447
477
  entries.forEach((entry) => {
448
- const canonicalSymbol = normalizeBinanceSymbol(entry.symbol);
449
- const mappedSymbols = streamSymbols.get(canonicalSymbol);
478
+ const binanceSymbolKey = normalizeBinanceSymbolKey(
479
+ entry.binanceSymbol ?? entry.symbol
480
+ );
481
+ const mappedSymbols = streamSymbols.get(binanceSymbolKey);
450
482
  if (!mappedSymbols || mappedSymbols.size === 0) return;
451
483
  nextMarkPrices ??= { ...state.markPrices };
452
484
  nextFundingRates ??= { ...state.fundingRates };
@@ -471,7 +503,7 @@ var useBinanceMarkPriceStore = create((set) => ({
471
503
  allMarkPricesRefCount += 1;
472
504
  },
473
505
  unsubscribeSymbol: (symmSymbol, rawBinanceSymbol) => {
474
- const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
506
+ const binanceSymbol = normalizeBinanceSymbolKey(rawBinanceSymbol);
475
507
  const removedSubscription = removeMappedSymbol(binanceSymbol, symmSymbol);
476
508
  if (!removedSubscription) {
477
509
  return;
@@ -511,6 +543,7 @@ var useBinanceMarkPriceStore = create((set) => ({
511
543
  }));
512
544
 
513
545
  // src/react/hooks/use-binance-ws.ts
546
+ var BOOTSTRAP_RETRY_DELAYS_MS = [1e3, 2e3, 5e3];
514
547
  function useBinanceWs(params) {
515
548
  const { symmCoreClient, chainId } = params;
516
549
  const subscribeSymbol = useBinanceMarkPriceStore((state) => state.subscribeSymbol);
@@ -521,7 +554,8 @@ function useBinanceWs(params) {
521
554
  }
522
555
  let cancelled = false;
523
556
  let subscribedPairs = [];
524
- const run = async () => {
557
+ let retryTimer = null;
558
+ const run = async (attempt = 0) => {
525
559
  try {
526
560
  const result = await symmCoreClient.markets.listSymmHedger({ chainId });
527
561
  if (cancelled) {
@@ -541,11 +575,22 @@ function useBinanceWs(params) {
541
575
  subscribeSymbol(symbol, binanceSymbol);
542
576
  });
543
577
  } catch {
578
+ const delay = BOOTSTRAP_RETRY_DELAYS_MS[attempt];
579
+ if (cancelled || delay == null) {
580
+ return;
581
+ }
582
+ retryTimer = setTimeout(() => {
583
+ retryTimer = null;
584
+ void run(attempt + 1);
585
+ }, delay);
544
586
  }
545
587
  };
546
588
  void run();
547
589
  return () => {
548
590
  cancelled = true;
591
+ if (retryTimer) {
592
+ clearTimeout(retryTimer);
593
+ }
549
594
  subscribedPairs.forEach(([symbol, binanceSymbol]) => {
550
595
  unsubscribeSymbol(symbol, binanceSymbol);
551
596
  });
@@ -25633,21 +25678,196 @@ function useSymmAccountData(params) {
25633
25678
  enabled: internalEnabled && (params.query?.enabled ?? true)
25634
25679
  });
25635
25680
  }
25636
- function useSymmBalances(params) {
25681
+
25682
+ // src/utils/account-pnl.ts
25683
+ function toNumber(value) {
25684
+ if (value === null || value === void 0 || value === "") {
25685
+ return 0;
25686
+ }
25687
+ const parsed = Number(value);
25688
+ return Number.isFinite(parsed) ? parsed : 0;
25689
+ }
25690
+ function readOpenedPrice(leg) {
25691
+ return toNumber(leg.openedPrice ?? leg.opened_price);
25692
+ }
25693
+ function readCurrentPrice(leg) {
25694
+ const parsed = Number(leg.currentPrice ?? leg.current_price);
25695
+ return Number.isFinite(parsed) ? parsed : void 0;
25696
+ }
25697
+ function readMarkPrice(leg, markPrices) {
25698
+ const symbol = leg.symbol?.trim().toUpperCase();
25699
+ if (symbol) {
25700
+ const markPrice = Number(markPrices[symbol]);
25701
+ if (Number.isFinite(markPrice)) {
25702
+ return markPrice;
25703
+ }
25704
+ }
25705
+ return readCurrentPrice(leg);
25706
+ }
25707
+ function getSymbol(leg) {
25708
+ return leg.symbol?.trim().toUpperCase() || void 0;
25709
+ }
25710
+ function computeLegUpnl(leg, side, markPrices) {
25711
+ const markPrice = readMarkPrice(leg, markPrices);
25712
+ if (markPrice === void 0) {
25713
+ return { upnl: 0, missingSymbol: getSymbol(leg) };
25714
+ }
25715
+ const quantity = toNumber(leg.quantity);
25716
+ const openedPrice = readOpenedPrice(leg);
25717
+ const direction = side === "short" ? -1 : 1;
25718
+ return {
25719
+ upnl: quantity * (markPrice - openedPrice) * direction
25720
+ };
25721
+ }
25722
+ function computeSymmPositionUpnl(position, markPrices = {}) {
25723
+ const missingSymbols = /* @__PURE__ */ new Set();
25724
+ let upnl = 0;
25725
+ let legsCount = 0;
25726
+ for (const leg of position.longAssets ?? []) {
25727
+ legsCount += 1;
25728
+ const result = computeLegUpnl(leg, "long", markPrices);
25729
+ upnl += result.upnl;
25730
+ if (result.missingSymbol) missingSymbols.add(result.missingSymbol);
25731
+ }
25732
+ for (const leg of position.shortAssets ?? []) {
25733
+ legsCount += 1;
25734
+ const result = computeLegUpnl(leg, "short", markPrices);
25735
+ upnl += result.upnl;
25736
+ if (result.missingSymbol) missingSymbols.add(result.missingSymbol);
25737
+ }
25738
+ if (legsCount === 0) {
25739
+ return {
25740
+ upnl: toNumber(position.unrealizedPnl ?? position.unrealized_pnl),
25741
+ missingSymbols: [],
25742
+ positionsCount: 1,
25743
+ legsCount,
25744
+ usedFallbackPositions: 1
25745
+ };
25746
+ }
25747
+ return {
25748
+ upnl,
25749
+ missingSymbols: Array.from(missingSymbols),
25750
+ positionsCount: 1,
25751
+ legsCount,
25752
+ usedFallbackPositions: 0
25753
+ };
25754
+ }
25755
+ function computeSymmPositionsUpnl(positions = [], markPrices = {}) {
25756
+ const missingSymbols = /* @__PURE__ */ new Set();
25757
+ let upnl = 0;
25758
+ let legsCount = 0;
25759
+ let usedFallbackPositions = 0;
25760
+ for (const position of positions) {
25761
+ const result = computeSymmPositionUpnl(position, markPrices);
25762
+ upnl += result.upnl;
25763
+ legsCount += result.legsCount;
25764
+ usedFallbackPositions += result.usedFallbackPositions;
25765
+ result.missingSymbols.forEach((symbol) => missingSymbols.add(symbol));
25766
+ }
25767
+ return {
25768
+ upnl,
25769
+ missingSymbols: Array.from(missingSymbols),
25770
+ positionsCount: positions.length,
25771
+ legsCount,
25772
+ usedFallbackPositions
25773
+ };
25774
+ }
25775
+ function readMessageNumber(message, keys) {
25776
+ for (const key of keys) {
25777
+ if (key in message) {
25778
+ return toNumber(message[key]);
25779
+ }
25780
+ }
25781
+ return 0;
25782
+ }
25783
+ function normalizeSymmUpnlWebSocketMessage(raw) {
25784
+ if (typeof raw !== "object" || raw === null) {
25785
+ return void 0;
25786
+ }
25787
+ const message = raw;
25788
+ const timestamp = readMessageNumber(message, ["timestamp"]);
25789
+ return {
25790
+ upnl: readMessageNumber(message, ["upnl"]),
25791
+ timestamp: timestamp || void 0,
25792
+ availableBalance: readMessageNumber(message, [
25793
+ "availableBalance",
25794
+ "available_balance"
25795
+ ]),
25796
+ allocatedBalance: readMessageNumber(message, [
25797
+ "allocatedBalance",
25798
+ "allocated_balance"
25799
+ ]),
25800
+ cva: readMessageNumber(message, ["cva"]),
25801
+ lf: readMessageNumber(message, ["lf"]),
25802
+ partyAmm: readMessageNumber(message, ["partyAmm", "party_a_mm", "mm"]),
25803
+ pendingPartyAmm: readMessageNumber(message, [
25804
+ "pendingPartyAmm",
25805
+ "pending_party_a_mm",
25806
+ "pending_mm"
25807
+ ]),
25808
+ pendingCva: readMessageNumber(message, ["pendingCva", "pending_cva"]),
25809
+ pendingLf: readMessageNumber(message, ["pendingLf", "pending_lf"]),
25810
+ raw
25811
+ };
25812
+ }
25813
+ function useSymmPositions(params) {
25637
25814
  const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
25638
- const { userAddress, multiAccountAddress } = params;
25815
+ const { accountAddress, address } = params;
25816
+ const resolvedAddress = accountAddress ? void 0 : address;
25639
25817
  const chainId = params.chainId ?? ctxChainId;
25640
- const internalEnabled = !!symmCoreClient && !!userAddress;
25818
+ const internalEnabled = !!symmCoreClient && !!(accountAddress || resolvedAddress);
25819
+ const enabled = internalEnabled && (params.query?.enabled ?? true);
25641
25820
  return useQuery({
25642
25821
  ...params.query,
25643
- queryKey: symmKeys.balances(userAddress, chainId, multiAccountAddress),
25644
- queryFn: () => symmCoreClient.accounts.getBalanceInfo({
25645
- userAddress,
25646
- chainId,
25647
- multiAccountAddress
25822
+ queryKey: symmKeys.positions({
25823
+ accountAddress,
25824
+ address: resolvedAddress,
25825
+ chainId
25648
25826
  }),
25649
- enabled: internalEnabled && (params.query?.enabled ?? true)
25827
+ queryFn: () => symmCoreClient.positions.getOpen({
25828
+ accountAddress,
25829
+ address: resolvedAddress,
25830
+ chainId
25831
+ }),
25832
+ enabled
25833
+ });
25834
+ }
25835
+
25836
+ // src/react/hooks/use-symm-account-current-pnl.ts
25837
+ function readPositions(response) {
25838
+ if (typeof response !== "object" || response === null) {
25839
+ return [];
25840
+ }
25841
+ const data = response.data;
25842
+ if (typeof data !== "object" || data === null) {
25843
+ return [];
25844
+ }
25845
+ const positions = data.positions;
25846
+ return Array.isArray(positions) ? positions : [];
25847
+ }
25848
+ function useSymmAccountCurrentPnl(params) {
25849
+ const { accountAddress, address, positions, query } = params;
25850
+ const liveMarkPrices = useBinanceMarkPriceStore((state) => state.markPrices);
25851
+ const positionsQuery = useSymmPositions({
25852
+ accountAddress,
25853
+ address,
25854
+ chainId: params.chainId,
25855
+ query: {
25856
+ ...query,
25857
+ enabled: positions === void 0 && (query?.enabled ?? true)
25858
+ }
25650
25859
  });
25860
+ const resolvedPositions = positions ?? readPositions(positionsQuery.data);
25861
+ const pnl = useMemo(
25862
+ () => computeSymmPositionsUpnl(resolvedPositions, liveMarkPrices),
25863
+ [liveMarkPrices, resolvedPositions]
25864
+ );
25865
+ return {
25866
+ ...pnl,
25867
+ value: pnl.upnl,
25868
+ positions: resolvedPositions,
25869
+ positionsQuery
25870
+ };
25651
25871
  }
25652
25872
 
25653
25873
  // src/utils/account-overview.ts
@@ -25677,7 +25897,7 @@ function readValue(source, keys) {
25677
25897
  }
25678
25898
  return void 0;
25679
25899
  }
25680
- function toNumber(value) {
25900
+ function toNumber2(value) {
25681
25901
  if (value === null || value === void 0 || value === "") {
25682
25902
  return 0;
25683
25903
  }
@@ -25694,7 +25914,7 @@ function toDisplayString(value) {
25694
25914
  return String(value);
25695
25915
  }
25696
25916
  function readNumber(source, keys) {
25697
- return toNumber(readValue(source, keys));
25917
+ return toNumber2(readValue(source, keys));
25698
25918
  }
25699
25919
  function readTimestamp(source) {
25700
25920
  const timestamp = readValue(source, ["timestamp"]);
@@ -25704,6 +25924,28 @@ function readTimestamp(source) {
25704
25924
  const parsed = Number(timestamp);
25705
25925
  return Number.isFinite(parsed) ? parsed : void 0;
25706
25926
  }
25927
+ function hasAccountDataShape(value) {
25928
+ return isRecord(value) && ("equity" in value || "maintenanceMargin" in value || "availableForOrder" in value || "totalLocked" in value);
25929
+ }
25930
+ function getSymmAccountData(response) {
25931
+ if (!isRecord(response)) {
25932
+ return void 0;
25933
+ }
25934
+ const data = response.data;
25935
+ if (isRecord(data)) {
25936
+ if (hasAccountDataShape(data.accountData)) {
25937
+ return data.accountData;
25938
+ }
25939
+ if (hasAccountDataShape(data)) {
25940
+ return data;
25941
+ }
25942
+ return void 0;
25943
+ }
25944
+ if (hasAccountDataShape(response)) {
25945
+ return response;
25946
+ }
25947
+ return void 0;
25948
+ }
25707
25949
  function getBalanceInfoContainer(response) {
25708
25950
  if (!isRecord(response)) {
25709
25951
  return void 0;
@@ -25784,7 +26026,7 @@ function computeSymmAccountOverview({
25784
26026
  "pendingLockedPartyAMM",
25785
26027
  "pending_locked_party_a_mm"
25786
26028
  ]);
25787
- const upnl = upnlOverride === void 0 ? readNumber(balanceInfo, ["upnl"]) : toNumber(upnlOverride);
26029
+ const upnl = upnlOverride === void 0 ? readNumber(balanceInfo, ["upnl"]) : toNumber2(upnlOverride);
25788
26030
  const computedTotalLocked = cva + lf + partyAmm;
25789
26031
  const totalLocked = readValue(
25790
26032
  balanceInfo,
@@ -25814,11 +26056,43 @@ function computeSymmAccountOverview({
25814
26056
  availableForOrder: toDisplayString(availableForOrder),
25815
26057
  availableMargin: toDisplayString(availableForOrder),
25816
26058
  availableBalance: toDisplayString(availableBalance),
25817
- netDeposited: toDisplayString(toNumber(netDeposited)),
26059
+ netDeposited: toDisplayString(toNumber2(netDeposited)),
25818
26060
  notional: toDisplayString(notional),
25819
26061
  timestamp: readTimestamp(balanceInfo)
25820
26062
  };
25821
26063
  }
26064
+ function computeSymmAccountOverviewFromData({
26065
+ accountData,
26066
+ upnl,
26067
+ netDeposited
26068
+ }) {
26069
+ const equity = readNumber(accountData, ["equity"]);
26070
+ const maintenanceMargin = readNumber(accountData, [
26071
+ "maintenanceMargin",
26072
+ "maintenance_margin"
26073
+ ]);
26074
+ const availableForOrder = readNumber(accountData, [
26075
+ "availableForOrder",
26076
+ "available_for_order"
26077
+ ]);
26078
+ const totalLocked = readNumber(accountData, ["totalLocked", "total_locked"]);
26079
+ return {
26080
+ allocatedBalance: "0",
26081
+ upnl: toDisplayString(toNumber2(upnl)),
26082
+ equity: toDisplayString(equity),
26083
+ totalAccountValue: toDisplayString(equity),
26084
+ maintenanceMargin: toDisplayString(maintenanceMargin),
26085
+ accountHealthData: accountData.accountHealthData,
26086
+ totalLocked: toDisplayString(totalLocked),
26087
+ marginUsed: toDisplayString(totalLocked),
26088
+ totalPendingLocked: "0",
26089
+ availableForOrder: toDisplayString(availableForOrder),
26090
+ availableMargin: toDisplayString(availableForOrder),
26091
+ availableBalance: toDisplayString(availableForOrder),
26092
+ netDeposited: toDisplayString(toNumber2(netDeposited)),
26093
+ notional: "0"
26094
+ };
26095
+ }
25822
26096
  function computeSymmNetDeposited(totals, decimals = 6) {
25823
26097
  if (!totals) {
25824
26098
  return "0";
@@ -25859,32 +26133,186 @@ function useSymmAccountOverview(params) {
25859
26133
  const {
25860
26134
  userAddress,
25861
26135
  accountAddress,
25862
- multiAccountAddress,
25863
26136
  upnl,
25864
- netDeposited
26137
+ netDeposited,
26138
+ positions,
26139
+ currentPnlQuery
25865
26140
  } = params;
25866
- const query = useSymmBalances({
25867
- userAddress,
25868
- multiAccountAddress,
26141
+ const address = accountAddress ?? userAddress;
26142
+ const shouldUseLocalPnl = upnl === void 0;
26143
+ const currentPnl = useSymmAccountCurrentPnl({
26144
+ accountAddress: address,
26145
+ positions,
25869
26146
  chainId: params.chainId,
25870
- query: params.query
26147
+ query: {
26148
+ ...currentPnlQuery,
26149
+ enabled: shouldUseLocalPnl && (currentPnlQuery?.enabled ?? true)
26150
+ }
26151
+ });
26152
+ const resolvedUpnl = shouldUseLocalPnl ? currentPnl.value : upnl;
26153
+ const upnlReady = !shouldUseLocalPnl || positions !== void 0 || currentPnl.positionsQuery.isSuccess;
26154
+ const query = useSymmAccountData({
26155
+ address,
26156
+ upnl: upnlReady ? String(resolvedUpnl ?? 0) : void 0,
26157
+ chainId: params.chainId,
26158
+ query: {
26159
+ ...params.query,
26160
+ enabled: upnlReady && (params.query?.enabled ?? true)
26161
+ }
25871
26162
  });
25872
26163
  const data = useMemo(() => {
25873
26164
  if (query.data === void 0) {
25874
26165
  return void 0;
25875
26166
  }
25876
- const balanceInfo = getSymmAccountBalanceInfo(
25877
- query.data,
25878
- accountAddress ?? userAddress
25879
- );
26167
+ const accountData = getSymmAccountData(query.data);
25880
26168
  return {
25881
26169
  response: query.data,
25882
- balanceInfo,
25883
- overview: balanceInfo ? computeSymmAccountOverview({ balanceInfo, upnl, netDeposited }) : void 0
26170
+ accountData,
26171
+ coreAccountData: accountData,
26172
+ currentPnl,
26173
+ overview: accountData ? computeSymmAccountOverviewFromData({
26174
+ accountData,
26175
+ upnl: resolvedUpnl,
26176
+ netDeposited
26177
+ }) : void 0
25884
26178
  };
25885
- }, [accountAddress, netDeposited, query.data, upnl, userAddress]);
26179
+ }, [currentPnl, netDeposited, query.data, resolvedUpnl]);
25886
26180
  return { ...query, data };
25887
26181
  }
26182
+ function parseMessageData(data) {
26183
+ if (typeof data !== "string") {
26184
+ return data;
26185
+ }
26186
+ try {
26187
+ return JSON.parse(data);
26188
+ } catch {
26189
+ return void 0;
26190
+ }
26191
+ }
26192
+ function toBalanceInfo(message) {
26193
+ return {
26194
+ allocatedBalance: message.allocatedBalance,
26195
+ cva: message.cva,
26196
+ lf: message.lf,
26197
+ partyAmm: message.partyAmm,
26198
+ pendingCva: message.pendingCva,
26199
+ pendingLf: message.pendingLf,
26200
+ pendingPartyAmm: message.pendingPartyAmm,
26201
+ upnl: message.upnl,
26202
+ availableBalance: message.availableBalance,
26203
+ timestamp: message.timestamp
26204
+ };
26205
+ }
26206
+ function useSymmUpnlWebSocket(params) {
26207
+ const {
26208
+ url,
26209
+ accountAddress,
26210
+ enabled = true,
26211
+ reconnectAttempts = 2,
26212
+ reconnectDelayMs = 1e3,
26213
+ webSocketFactory
26214
+ } = params;
26215
+ const [data, setData] = useState();
26216
+ const [status, setStatus] = useState("idle");
26217
+ const [error, setError] = useState();
26218
+ const socketRef = useRef(null);
26219
+ const sendAccountAddress = useCallback(() => {
26220
+ if (!accountAddress || socketRef.current?.readyState !== 1) {
26221
+ return;
26222
+ }
26223
+ socketRef.current.send(accountAddress);
26224
+ }, [accountAddress]);
26225
+ useEffect(() => {
26226
+ if (!enabled || !url || !accountAddress) {
26227
+ setStatus("idle");
26228
+ setData(void 0);
26229
+ setError(void 0);
26230
+ return;
26231
+ }
26232
+ const createSocket = webSocketFactory ?? ((wsUrl) => new WebSocket(wsUrl));
26233
+ let closedByHook = false;
26234
+ let reconnectCount = 0;
26235
+ let reconnectTimer;
26236
+ const connect = () => {
26237
+ setStatus("connecting");
26238
+ const socket = createSocket(url);
26239
+ socketRef.current = socket;
26240
+ socket.onopen = () => {
26241
+ reconnectCount = 0;
26242
+ setStatus("open");
26243
+ setError(void 0);
26244
+ socket.send(accountAddress);
26245
+ };
26246
+ socket.onmessage = (event) => {
26247
+ const parsed = parseMessageData(event.data);
26248
+ const nextMessage = normalizeSymmUpnlWebSocketMessage(parsed);
26249
+ if (nextMessage) {
26250
+ setData(nextMessage);
26251
+ }
26252
+ };
26253
+ socket.onerror = (event) => {
26254
+ setError(event);
26255
+ setStatus("error");
26256
+ };
26257
+ socket.onclose = () => {
26258
+ if (closedByHook) {
26259
+ setStatus("closed");
26260
+ return;
26261
+ }
26262
+ if (reconnectCount < reconnectAttempts) {
26263
+ reconnectCount += 1;
26264
+ reconnectTimer = setTimeout(connect, reconnectDelayMs);
26265
+ return;
26266
+ }
26267
+ setStatus("closed");
26268
+ };
26269
+ };
26270
+ connect();
26271
+ return () => {
26272
+ closedByHook = true;
26273
+ if (reconnectTimer) {
26274
+ clearTimeout(reconnectTimer);
26275
+ }
26276
+ socketRef.current?.close();
26277
+ socketRef.current = null;
26278
+ };
26279
+ }, [
26280
+ accountAddress,
26281
+ enabled,
26282
+ reconnectAttempts,
26283
+ reconnectDelayMs,
26284
+ url,
26285
+ webSocketFactory
26286
+ ]);
26287
+ const balanceInfo = useMemo(
26288
+ () => data ? toBalanceInfo(data) : void 0,
26289
+ [data]
26290
+ );
26291
+ return {
26292
+ data,
26293
+ upnl: data?.upnl,
26294
+ balanceInfo,
26295
+ status,
26296
+ error,
26297
+ sendAccountAddress
26298
+ };
26299
+ }
26300
+ function useSymmBalances(params) {
26301
+ const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
26302
+ const { userAddress, multiAccountAddress } = params;
26303
+ const chainId = params.chainId ?? ctxChainId;
26304
+ const internalEnabled = !!symmCoreClient && !!userAddress;
26305
+ return useQuery({
26306
+ ...params.query,
26307
+ queryKey: symmKeys.balances(userAddress, chainId, multiAccountAddress),
26308
+ queryFn: () => symmCoreClient.accounts.getBalanceInfo({
26309
+ userAddress,
26310
+ chainId,
26311
+ multiAccountAddress
26312
+ }),
26313
+ enabled: internalEnabled && (params.query?.enabled ?? true)
26314
+ });
26315
+ }
25888
26316
  function useSymmOpenBasketMutation(options) {
25889
26317
  const { symmCoreClient } = useSymmContext();
25890
26318
  const queryClient = useQueryClient();
@@ -26015,28 +26443,6 @@ function useSymmUpdatePositionMutation(paramsOrOptions, maybeOptions) {
26015
26443
  }
26016
26444
  });
26017
26445
  }
26018
- function useSymmPositions(params) {
26019
- const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
26020
- const { accountAddress, address } = params;
26021
- const resolvedAddress = accountAddress ? void 0 : address;
26022
- const chainId = params.chainId ?? ctxChainId;
26023
- const internalEnabled = !!symmCoreClient && !!(accountAddress || resolvedAddress);
26024
- const enabled = internalEnabled && (params.query?.enabled ?? true);
26025
- return useQuery({
26026
- ...params.query,
26027
- queryKey: symmKeys.positions({
26028
- accountAddress,
26029
- address: resolvedAddress,
26030
- chainId
26031
- }),
26032
- queryFn: () => symmCoreClient.positions.getOpen({
26033
- accountAddress,
26034
- address: resolvedAddress,
26035
- chainId
26036
- }),
26037
- enabled
26038
- });
26039
- }
26040
26446
  function useSymmOpenOrders(params) {
26041
26447
  const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
26042
26448
  const { accountAddress, address } = params;
@@ -27457,6 +27863,6 @@ function getSymmErrorMessage(error) {
27457
27863
  return "An unexpected error occurred.";
27458
27864
  }
27459
27865
 
27460
- export { SymmProvider, computeSymmAccountOverview, computeSymmNetDeposited, getSymmAccountBalanceInfo, getSymmErrorMessage, symmKeys, useBinanceMarkPriceStore, 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, useSymmWithdraw, useSymmWsStore };
27866
+ 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 };
27461
27867
  //# sourceMappingURL=index.mjs.map
27462
27868
  //# sourceMappingURL=index.mjs.map