@pear-protocol/symmio-client 0.3.15 → 0.3.17

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.
@@ -75,6 +75,7 @@ var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
75
75
  var IDLE_CLOSE_DELAY_MS = 3e4;
76
76
  var STALE_CONNECTION_MS = 3e4;
77
77
  var STALE_CHECK_INTERVAL_MS = 1e4;
78
+ var RECONNECT_RESET_MS = 6e4;
78
79
  var STABLE_QUOTES = ["USDT0", "USDT", "USDC", "USDE", "USDH", "USD"];
79
80
  function normalizeBaseSymbol(symbol) {
80
81
  const normalized = symbol.toUpperCase().trim();
@@ -126,6 +127,7 @@ var BinanceWsManager = class {
126
127
  reconnectTimer = null;
127
128
  idleCloseTimer = null;
128
129
  staleCheckTimer = null;
130
+ reconnectResetTimer = null;
129
131
  intentionalClose = false;
130
132
  pendingSubscribes = /* @__PURE__ */ new Set();
131
133
  lastMessageAt = 0;
@@ -164,6 +166,7 @@ var BinanceWsManager = class {
164
166
  const wrappedCb = (raw) => {
165
167
  cb({
166
168
  symbol: normalizeBaseSymbol(raw.s),
169
+ binanceSymbol: raw.s,
167
170
  markPrice: parseFloat(raw.p),
168
171
  indexPrice: parseFloat(raw.i),
169
172
  time: raw.E,
@@ -185,6 +188,7 @@ var BinanceWsManager = class {
185
188
  cb(
186
189
  extractTickers(raw).map((entry) => ({
187
190
  symbol: normalizeBaseSymbol(entry.s),
191
+ binanceSymbol: entry.s,
188
192
  markPrice: parseFloat(entry.p),
189
193
  indexPrice: parseFloat(entry.i),
190
194
  time: entry.E,
@@ -204,6 +208,7 @@ var BinanceWsManager = class {
204
208
  this.clearReconnectTimer();
205
209
  this.clearIdleCloseTimer();
206
210
  this.clearStaleCheckTimer();
211
+ this.clearReconnectResetTimer();
207
212
  this.pendingSubscribes.clear();
208
213
  if (this.ws) {
209
214
  this.ws.close();
@@ -257,9 +262,9 @@ var BinanceWsManager = class {
257
262
  this.intentionalClose = false;
258
263
  this.ws = new WebSocket(BINANCE_WS_URL);
259
264
  this.ws.onopen = () => {
260
- this.reconnectAttempt = 0;
261
265
  this.lastMessageAt = Date.now();
262
266
  this.startStaleCheck();
267
+ this.scheduleReconnectReset();
263
268
  const activeStreams = Array.from(
264
269
  /* @__PURE__ */ new Set([...this.streams.keys(), ...this.pendingSubscribes])
265
270
  );
@@ -272,6 +277,7 @@ var BinanceWsManager = class {
272
277
  try {
273
278
  const data = JSON.parse(event.data);
274
279
  this.lastMessageAt = Date.now();
280
+ this.resetReconnectAttempt();
275
281
  this.handleMessage(data);
276
282
  } catch {
277
283
  }
@@ -281,6 +287,7 @@ var BinanceWsManager = class {
281
287
  this.intentionalClose = false;
282
288
  this.ws = null;
283
289
  this.clearStaleCheckTimer();
290
+ this.clearReconnectResetTimer();
284
291
  if (this.streams.size === 0) {
285
292
  return;
286
293
  }
@@ -374,6 +381,17 @@ var BinanceWsManager = class {
374
381
  this.ws.close();
375
382
  }, STALE_CHECK_INTERVAL_MS);
376
383
  }
384
+ scheduleReconnectReset() {
385
+ this.clearReconnectResetTimer();
386
+ this.reconnectResetTimer = setTimeout(() => {
387
+ this.reconnectResetTimer = null;
388
+ this.resetReconnectAttempt();
389
+ }, RECONNECT_RESET_MS);
390
+ }
391
+ resetReconnectAttempt() {
392
+ this.reconnectAttempt = 0;
393
+ this.clearReconnectResetTimer();
394
+ }
377
395
  clearReconnectTimer() {
378
396
  if (!this.reconnectTimer) return;
379
397
  clearTimeout(this.reconnectTimer);
@@ -389,6 +407,11 @@ var BinanceWsManager = class {
389
407
  clearInterval(this.staleCheckTimer);
390
408
  this.staleCheckTimer = null;
391
409
  }
410
+ clearReconnectResetTimer() {
411
+ if (!this.reconnectResetTimer) return;
412
+ clearTimeout(this.reconnectResetTimer);
413
+ this.reconnectResetTimer = null;
414
+ }
392
415
  };
393
416
  var BINANCE_WS_SINGLETON_KEY = "__pearBinanceWsManager__";
394
417
  function getBinanceWsManager() {
@@ -406,15 +429,8 @@ var refCounts = /* @__PURE__ */ new Map();
406
429
  var streamSymbols = /* @__PURE__ */ new Map();
407
430
  var allMarkPricesRefCount = 0;
408
431
  var allMarkPricesUnsubscribe = null;
409
- var STABLE_QUOTES2 = ["USDT0", "USDT", "USDC", "USDE", "USDH", "USD"];
410
- function normalizeBinanceSymbol(symbol) {
411
- const normalized = symbol.toUpperCase().trim();
412
- for (const quote of STABLE_QUOTES2) {
413
- if (normalized.endsWith(quote) && normalized.length > quote.length) {
414
- return normalized.slice(0, -quote.length);
415
- }
416
- }
417
- return normalized;
432
+ function normalizeBinanceSymbolKey(symbol) {
433
+ return symbol.toUpperCase().trim();
418
434
  }
419
435
  function getNextRefCount(binanceSymbol) {
420
436
  return (refCounts.get(binanceSymbol) ?? 0) + 1;
@@ -449,7 +465,7 @@ var useBinanceMarkPriceStore = zustand.create((set) => ({
449
465
  fundingRates: {},
450
466
  nextFundingTimes: {},
451
467
  subscribeSymbol: (symmSymbol, rawBinanceSymbol) => {
452
- const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
468
+ const binanceSymbol = normalizeBinanceSymbolKey(rawBinanceSymbol);
453
469
  const nextRefCount = getNextRefCount(binanceSymbol);
454
470
  refCounts.set(binanceSymbol, nextRefCount);
455
471
  addMappedSymbol(binanceSymbol, symmSymbol);
@@ -461,8 +477,10 @@ var useBinanceMarkPriceStore = zustand.create((set) => ({
461
477
  let nextFundingRates = null;
462
478
  let nextFundingTimes = null;
463
479
  entries.forEach((entry) => {
464
- const canonicalSymbol = normalizeBinanceSymbol(entry.symbol);
465
- const mappedSymbols = streamSymbols.get(canonicalSymbol);
480
+ const binanceSymbolKey = normalizeBinanceSymbolKey(
481
+ entry.binanceSymbol ?? entry.symbol
482
+ );
483
+ const mappedSymbols = streamSymbols.get(binanceSymbolKey);
466
484
  if (!mappedSymbols || mappedSymbols.size === 0) return;
467
485
  nextMarkPrices ??= { ...state.markPrices };
468
486
  nextFundingRates ??= { ...state.fundingRates };
@@ -487,7 +505,7 @@ var useBinanceMarkPriceStore = zustand.create((set) => ({
487
505
  allMarkPricesRefCount += 1;
488
506
  },
489
507
  unsubscribeSymbol: (symmSymbol, rawBinanceSymbol) => {
490
- const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
508
+ const binanceSymbol = normalizeBinanceSymbolKey(rawBinanceSymbol);
491
509
  const removedSubscription = removeMappedSymbol(binanceSymbol, symmSymbol);
492
510
  if (!removedSubscription) {
493
511
  return;
@@ -527,6 +545,7 @@ var useBinanceMarkPriceStore = zustand.create((set) => ({
527
545
  }));
528
546
 
529
547
  // src/react/hooks/use-binance-ws.ts
548
+ var BOOTSTRAP_RETRY_DELAYS_MS = [1e3, 2e3, 5e3];
530
549
  function useBinanceWs(params) {
531
550
  const { symmCoreClient, chainId } = params;
532
551
  const subscribeSymbol = useBinanceMarkPriceStore((state) => state.subscribeSymbol);
@@ -537,7 +556,8 @@ function useBinanceWs(params) {
537
556
  }
538
557
  let cancelled = false;
539
558
  let subscribedPairs = [];
540
- const run = async () => {
559
+ let retryTimer = null;
560
+ const run = async (attempt = 0) => {
541
561
  try {
542
562
  const result = await symmCoreClient.markets.listSymmHedger({ chainId });
543
563
  if (cancelled) {
@@ -557,11 +577,22 @@ function useBinanceWs(params) {
557
577
  subscribeSymbol(symbol, binanceSymbol);
558
578
  });
559
579
  } catch {
580
+ const delay = BOOTSTRAP_RETRY_DELAYS_MS[attempt];
581
+ if (cancelled || delay == null) {
582
+ return;
583
+ }
584
+ retryTimer = setTimeout(() => {
585
+ retryTimer = null;
586
+ void run(attempt + 1);
587
+ }, delay);
560
588
  }
561
589
  };
562
590
  void run();
563
591
  return () => {
564
592
  cancelled = true;
593
+ if (retryTimer) {
594
+ clearTimeout(retryTimer);
595
+ }
565
596
  subscribedPairs.forEach(([symbol, binanceSymbol]) => {
566
597
  unsubscribeSymbol(symbol, binanceSymbol);
567
598
  });
@@ -602,6 +633,7 @@ var symmKeys = {
602
633
  triggerOrders: (params) => ["symm", "triggerOrders", params],
603
634
  triggerConfig: (orderId) => ["symm", "triggerConfig", orderId],
604
635
  markets: (chainId, search, pageSize) => ["symm", "markets", chainId, search, pageSize],
636
+ marketPositioning: (chainId, market) => ["symm", "marketPositioning", chainId, market],
605
637
  hedgerMarketById: (id, chainId) => ["symm", "hedgerMarketById", id, chainId],
606
638
  hedgerMarketBySymbol: (symbol, chainId) => ["symm", "hedgerMarketBySymbol", symbol, chainId],
607
639
  lockedParams: (marketName, leverage, chainId) => ["symm", "lockedParams", marketName, leverage, chainId],
@@ -1674,6 +1706,7 @@ var SymmioSDKError = class extends Error {
1674
1706
  this.code = code;
1675
1707
  this.name = "SymmioSDKError";
1676
1708
  }
1709
+ code;
1677
1710
  };
1678
1711
  function validateAddress(address, name) {
1679
1712
  if (!viem.isAddress(address)) {
@@ -25895,15 +25928,24 @@ function readTimestamp(source) {
25895
25928
  const parsed = Number(timestamp);
25896
25929
  return Number.isFinite(parsed) ? parsed : void 0;
25897
25930
  }
25931
+ function hasAccountDataShape(value) {
25932
+ return isRecord(value) && ("equity" in value || "maintenanceMargin" in value || "availableForOrder" in value || "totalLocked" in value);
25933
+ }
25898
25934
  function getSymmAccountData(response) {
25899
25935
  if (!isRecord(response)) {
25900
25936
  return void 0;
25901
25937
  }
25902
25938
  const data = response.data;
25903
25939
  if (isRecord(data)) {
25904
- return data;
25940
+ if (hasAccountDataShape(data.accountData)) {
25941
+ return data.accountData;
25942
+ }
25943
+ if (hasAccountDataShape(data)) {
25944
+ return data;
25945
+ }
25946
+ return void 0;
25905
25947
  }
25906
- if ("equity" in response || "maintenanceMargin" in response || "availableForOrder" in response || "totalLocked" in response) {
25948
+ if (hasAccountDataShape(response)) {
25907
25949
  return response;
25908
25950
  }
25909
25951
  return void 0;
@@ -26119,7 +26161,7 @@ function useSymmAccountOverview(params) {
26119
26161
  chainId: params.chainId,
26120
26162
  query: {
26121
26163
  ...params.query,
26122
- enabled: upnlReady && (params.query?.enabled ?? true)
26164
+ enabled: params.query?.enabled ?? true
26123
26165
  }
26124
26166
  });
26125
26167
  const data = react.useMemo(() => {
@@ -26641,6 +26683,34 @@ function useSymmMarkets(params) {
26641
26683
  enabled: internalEnabled && (params?.query?.enabled ?? true)
26642
26684
  });
26643
26685
  }
26686
+ function normalizeMarket(market) {
26687
+ if (Array.isArray(market)) {
26688
+ const markets = market.map((marketName2) => marketName2.trim()).filter((marketName2) => marketName2.length > 0);
26689
+ return markets.length > 0 ? markets : void 0;
26690
+ }
26691
+ const marketName = market?.trim();
26692
+ return marketName ? marketName : void 0;
26693
+ }
26694
+ function hasMarket(market) {
26695
+ return Array.isArray(market) ? market.length > 0 : market !== void 0;
26696
+ }
26697
+ function useSymmMarketPositioning(params) {
26698
+ const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
26699
+ const chainId = params?.chainId ?? ctxChainId;
26700
+ const market = normalizeMarket(params?.market);
26701
+ const internalEnabled = !!symmCoreClient && hasMarket(market);
26702
+ return reactQuery.useQuery({
26703
+ ...params?.query,
26704
+ queryKey: symmKeys.marketPositioning(chainId, market),
26705
+ queryFn: () => {
26706
+ if (!hasMarket(market)) {
26707
+ throw new Error("Market is required to fetch positioning");
26708
+ }
26709
+ return symmCoreClient.markets.getPositioning({ chainId, market });
26710
+ },
26711
+ enabled: internalEnabled && (params?.query?.enabled ?? true)
26712
+ });
26713
+ }
26644
26714
  function useSymmHedgerMarketById(params) {
26645
26715
  const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
26646
26716
  const { id } = params;
@@ -26746,7 +26816,9 @@ async function fetch24hrTicker(symbol) {
26746
26816
  return {
26747
26817
  lastPrice: parseFloat(data.lastPrice),
26748
26818
  openPrice: parseFloat(data.openPrice),
26749
- priceChangePercent: parseFloat(data.priceChangePercent)
26819
+ priceChangePercent: parseFloat(data.priceChangePercent),
26820
+ volume: parseFloat(data.volume),
26821
+ quoteVolume: parseFloat(data.quoteVolume)
26750
26822
  };
26751
26823
  }
26752
26824
  async function fetch24hrTickers() {
@@ -26760,7 +26832,9 @@ async function fetch24hrTickers() {
26760
26832
  result[item.symbol] = {
26761
26833
  lastPrice: parseFloat(item.lastPrice),
26762
26834
  openPrice: parseFloat(item.openPrice),
26763
- priceChangePercent: parseFloat(item.priceChangePercent)
26835
+ priceChangePercent: parseFloat(item.priceChangePercent),
26836
+ volume: parseFloat(item.volume),
26837
+ quoteVolume: parseFloat(item.quoteVolume)
26764
26838
  };
26765
26839
  }
26766
26840
  return result;
@@ -26796,7 +26870,11 @@ function useSymmTokenSelectionMarkets(params) {
26796
26870
  return;
26797
26871
  }
26798
26872
  const ticker = allTickers[binanceSymbol];
26799
- tickerSnapshots[symbol] = ticker ? { openPrice: ticker.openPrice } : null;
26873
+ tickerSnapshots[symbol] = ticker ? {
26874
+ openPrice: ticker.openPrice,
26875
+ volume: ticker.volume,
26876
+ quoteVolume: ticker.quoteVolume
26877
+ } : null;
26800
26878
  });
26801
26879
  return { tickerSnapshots };
26802
26880
  },
@@ -26806,21 +26884,30 @@ function useSymmTokenSelectionMarkets(params) {
26806
26884
  });
26807
26885
  const markets = react.useMemo(() => {
26808
26886
  const snapshots = priceQuery.data?.tickerSnapshots ?? {};
26809
- return baseMarkets.map((market) => {
26887
+ return baseMarkets.map((market, index) => {
26810
26888
  const symbol = market.symbol ?? "";
26811
26889
  const markPrice = symbol ? liveMarkPrices[symbol] ?? null : null;
26812
- const prevDayPrice = symbol ? snapshots[symbol]?.openPrice ?? null : null;
26890
+ const ticker = symbol ? snapshots[symbol] ?? null : null;
26891
+ const prevDayPrice = ticker?.openPrice ?? null;
26813
26892
  const priceChange24h = markPrice != null && prevDayPrice != null ? markPrice - prevDayPrice : null;
26814
26893
  const priceChange24hPercent = markPrice != null && prevDayPrice != null && prevDayPrice !== 0 ? (markPrice - prevDayPrice) / prevDayPrice * 100 : null;
26815
26894
  return {
26816
- ...market,
26817
- collateralToken: "USDC",
26818
- markPrice,
26819
- prevDayPrice,
26820
- priceChange24h,
26821
- priceChange24hPercent
26895
+ market: {
26896
+ ...market,
26897
+ collateralToken: "USDC",
26898
+ markPrice,
26899
+ prevDayPrice,
26900
+ priceChange24h,
26901
+ priceChange24hPercent,
26902
+ volume24h: ticker?.volume ?? null,
26903
+ quoteVolume24h: ticker?.quoteVolume ?? null
26904
+ },
26905
+ index
26822
26906
  };
26823
- });
26907
+ }).sort((a, b) => {
26908
+ const volumeDelta = (b.market.quoteVolume24h ?? 0) - (a.market.quoteVolume24h ?? 0);
26909
+ return volumeDelta === 0 ? a.index - b.index : volumeDelta;
26910
+ }).map(({ market }) => market);
26824
26911
  }, [baseMarkets, liveMarkPrices, priceQuery.data]);
26825
26912
  const marketsBySymbol = react.useMemo(
26826
26913
  () => new Map(
@@ -27881,6 +27968,7 @@ exports.useSymmInstantTradeExecuteMutation = useSymmInstantTradeExecuteMutation;
27881
27968
  exports.useSymmInternalTransferCollateralMutation = useSymmInternalTransferCollateralMutation;
27882
27969
  exports.useSymmLockedParams = useSymmLockedParams;
27883
27970
  exports.useSymmMarkReadNotificationMutation = useSymmMarkReadNotificationMutation;
27971
+ exports.useSymmMarketPositioning = useSymmMarketPositioning;
27884
27972
  exports.useSymmMarkets = useSymmMarkets;
27885
27973
  exports.useSymmNotificationsQuery = useSymmNotificationsQuery;
27886
27974
  exports.useSymmOpenBasketMutation = useSymmOpenBasketMutation;