@pear-protocol/symmio-client 0.2.28 → 0.2.30

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.
@@ -8706,8 +8706,6 @@ interface SymmTokenSelectionMarket extends MarketItem {
8706
8706
  priceChange24hPercent: number | null;
8707
8707
  }
8708
8708
  interface UseSymmTokenSelectionMarketsReturn {
8709
- query: ReturnType<typeof useSymmHedgerMarkets>;
8710
- priceQuery: ReturnType<typeof useQuery>;
8711
8709
  markets: SymmTokenSelectionMarket[];
8712
8710
  marketsBySymbol: Map<string, SymmTokenSelectionMarket>;
8713
8711
  marketsById: Map<number, SymmTokenSelectionMarket>;
@@ -8875,6 +8873,8 @@ interface SymmTokenMetadata {
8875
8873
  priceChange24hPercent: number;
8876
8874
  netFunding: number;
8877
8875
  markPrice: number;
8876
+ fundingRate: number;
8877
+ nextFundingTime: number;
8878
8878
  }
8879
8879
  interface UseSymmTokenSelectionMetadataReturn {
8880
8880
  query: ReturnType<typeof useQuery>;
@@ -9099,8 +9099,12 @@ type SymmWsState = {
9099
9099
  declare const useSymmWsStore: zustand.UseBoundStore<zustand.StoreApi<SymmWsState>>;
9100
9100
 
9101
9101
  type MarkPrices = Record<string, number>;
9102
+ type FundingRates = Record<string, number>;
9103
+ type NextFundingTimes = Record<string, number>;
9102
9104
  type BinanceMarkPriceState = {
9103
9105
  markPrices: MarkPrices;
9106
+ fundingRates: FundingRates;
9107
+ nextFundingTimes: NextFundingTimes;
9104
9108
  subscribeSymbol: (symmSymbol: string, binanceSymbol: string) => void;
9105
9109
  unsubscribeSymbol: (symmSymbol: string, binanceSymbol: string) => void;
9106
9110
  };
@@ -8706,8 +8706,6 @@ interface SymmTokenSelectionMarket extends MarketItem {
8706
8706
  priceChange24hPercent: number | null;
8707
8707
  }
8708
8708
  interface UseSymmTokenSelectionMarketsReturn {
8709
- query: ReturnType<typeof useSymmHedgerMarkets>;
8710
- priceQuery: ReturnType<typeof useQuery>;
8711
8709
  markets: SymmTokenSelectionMarket[];
8712
8710
  marketsBySymbol: Map<string, SymmTokenSelectionMarket>;
8713
8711
  marketsById: Map<number, SymmTokenSelectionMarket>;
@@ -8875,6 +8873,8 @@ interface SymmTokenMetadata {
8875
8873
  priceChange24hPercent: number;
8876
8874
  netFunding: number;
8877
8875
  markPrice: number;
8876
+ fundingRate: number;
8877
+ nextFundingTime: number;
8878
8878
  }
8879
8879
  interface UseSymmTokenSelectionMetadataReturn {
8880
8880
  query: ReturnType<typeof useQuery>;
@@ -9099,8 +9099,12 @@ type SymmWsState = {
9099
9099
  declare const useSymmWsStore: zustand.UseBoundStore<zustand.StoreApi<SymmWsState>>;
9100
9100
 
9101
9101
  type MarkPrices = Record<string, number>;
9102
+ type FundingRates = Record<string, number>;
9103
+ type NextFundingTimes = Record<string, number>;
9102
9104
  type BinanceMarkPriceState = {
9103
9105
  markPrices: MarkPrices;
9106
+ fundingRates: FundingRates;
9107
+ nextFundingTimes: NextFundingTimes;
9104
9108
  subscribeSymbol: (symmSymbol: string, binanceSymbol: string) => void;
9105
9109
  unsubscribeSymbol: (symmSymbol: string, binanceSymbol: string) => void;
9106
9110
  };
@@ -71,7 +71,7 @@ function toBinanceSymbol(symmSymbol) {
71
71
  }
72
72
 
73
73
  // src/utils/binance-ws.ts
74
- var BINANCE_WS_URL = "wss://fstream.binance.com/ws";
74
+ var BINANCE_WS_URL = "wss://fstream.binance.com/market/ws";
75
75
  var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
76
76
  var STABLE_QUOTES = ["USDT0", "USDT", "USDC", "USDE", "USDH", "USD"];
77
77
  function normalizeBaseSymbol(symbol) {
@@ -101,6 +101,22 @@ function extractTickers(payload) {
101
101
  }
102
102
  return [];
103
103
  }
104
+ function extractWsPayload(payload) {
105
+ if (payload && typeof payload === "object" && "data" in payload) {
106
+ return payload.data ?? payload;
107
+ }
108
+ return payload;
109
+ }
110
+ function isKlinePayload(payload) {
111
+ return Boolean(
112
+ payload && typeof payload === "object" && payload.e === "kline" && typeof payload.s === "string" && payload.k && typeof payload.k.i === "string"
113
+ );
114
+ }
115
+ function isMarkPricePayload(payload) {
116
+ return Boolean(
117
+ payload && typeof payload === "object" && payload.e === "markPriceUpdate" && typeof payload.s === "string"
118
+ );
119
+ }
104
120
  var BinanceWsManager = class {
105
121
  ws = null;
106
122
  streams = /* @__PURE__ */ new Map();
@@ -145,7 +161,9 @@ var BinanceWsManager = class {
145
161
  symbol: normalizeBaseSymbol(raw.s),
146
162
  markPrice: parseFloat(raw.p),
147
163
  indexPrice: parseFloat(raw.i),
148
- time: raw.E
164
+ time: raw.E,
165
+ fundingRate: parseFloat(raw.r ?? "0"),
166
+ nextFundingTime: Number(raw.T ?? 0)
149
167
  });
150
168
  };
151
169
  this.addStreamCallback(streamName, id, wrappedCb);
@@ -164,7 +182,9 @@ var BinanceWsManager = class {
164
182
  symbol: normalizeBaseSymbol(entry.s),
165
183
  markPrice: parseFloat(entry.p),
166
184
  indexPrice: parseFloat(entry.i),
167
- time: entry.E
185
+ time: entry.E,
186
+ fundingRate: parseFloat(entry.r ?? "0"),
187
+ nextFundingTime: Number(entry.T ?? 0)
168
188
  }))
169
189
  );
170
190
  };
@@ -254,17 +274,18 @@ var BinanceWsManager = class {
254
274
  };
255
275
  }
256
276
  handleMessage(data) {
257
- if (Array.isArray(data)) {
258
- this.dispatchToStream("!markPrice@arr@1s", data);
277
+ const payload = extractWsPayload(data);
278
+ if (Array.isArray(payload)) {
279
+ this.dispatchToStream("!markPrice@arr@1s", payload);
259
280
  return;
260
281
  }
261
- if (data.e === "kline") {
262
- const k = data.k;
263
- const streamName = `${data.s.toLowerCase()}@kline_${k.i}`;
264
- this.dispatchToStream(streamName, data);
265
- } else if (data.e === "markPriceUpdate") {
266
- const streamName = `${data.s.toLowerCase()}@markPrice@1s`;
267
- this.dispatchToStream(streamName, data);
282
+ if (isKlinePayload(payload)) {
283
+ const k = payload.k;
284
+ const streamName = `${payload.s.toLowerCase()}@kline_${k.i}`;
285
+ this.dispatchToStream(streamName, payload);
286
+ } else if (isMarkPricePayload(payload)) {
287
+ const streamName = `${payload.s.toLowerCase()}@markPrice@1s`;
288
+ this.dispatchToStream(streamName, payload);
268
289
  }
269
290
  }
270
291
  dispatchToStream(streamName, data) {
@@ -343,6 +364,8 @@ function getPrevRefCount(binanceSymbol) {
343
364
  }
344
365
  var useBinanceMarkPriceStore = zustand.create((set) => ({
345
366
  markPrices: {},
367
+ fundingRates: {},
368
+ nextFundingTimes: {},
346
369
  subscribeSymbol: (symmSymbol, rawBinanceSymbol) => {
347
370
  const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
348
371
  const nextRefCount = getNextRefCount(binanceSymbol);
@@ -355,16 +378,29 @@ var useBinanceMarkPriceStore = zustand.create((set) => ({
355
378
  allMarkPricesUnsubscribe = wsManager.subscribeAllMarkPrices((entries) => {
356
379
  set((state) => {
357
380
  let nextMarkPrices = null;
381
+ let nextFundingRates = null;
382
+ let nextFundingTimes = null;
358
383
  entries.forEach((entry) => {
359
384
  const canonicalSymbol = normalizeBinanceSymbol(entry.symbol);
360
385
  const mappedSymbols = streamSymbols.get(canonicalSymbol);
361
386
  if (!mappedSymbols || mappedSymbols.size === 0) return;
362
387
  nextMarkPrices ??= { ...state.markPrices };
388
+ nextFundingRates ??= { ...state.fundingRates };
389
+ nextFundingTimes ??= { ...state.nextFundingTimes };
363
390
  mappedSymbols.forEach((mappedSymbol) => {
364
391
  nextMarkPrices[mappedSymbol] = entry.markPrice;
392
+ nextFundingRates[mappedSymbol] = entry.fundingRate;
393
+ nextFundingTimes[mappedSymbol] = entry.nextFundingTime;
365
394
  });
366
395
  });
367
- return nextMarkPrices ? { markPrices: nextMarkPrices } : state;
396
+ if (!nextMarkPrices || !nextFundingRates || !nextFundingTimes) {
397
+ return state;
398
+ }
399
+ return {
400
+ markPrices: nextMarkPrices,
401
+ fundingRates: nextFundingRates,
402
+ nextFundingTimes
403
+ };
368
404
  });
369
405
  });
370
406
  }
@@ -393,10 +429,20 @@ var useBinanceMarkPriceStore = zustand.create((set) => ({
393
429
  allMarkPricesUnsubscribe = null;
394
430
  }
395
431
  set((state) => {
396
- if (state.markPrices[symmSymbol] == null) return state;
432
+ if (state.markPrices[symmSymbol] == null && state.fundingRates[symmSymbol] == null && state.nextFundingTimes[symmSymbol] == null) {
433
+ return state;
434
+ }
397
435
  const nextMarkPrices = { ...state.markPrices };
436
+ const nextFundingRates = { ...state.fundingRates };
437
+ const nextFundingTimes = { ...state.nextFundingTimes };
398
438
  delete nextMarkPrices[symmSymbol];
399
- return { markPrices: nextMarkPrices };
439
+ delete nextFundingRates[symmSymbol];
440
+ delete nextFundingTimes[symmSymbol];
441
+ return {
442
+ markPrices: nextMarkPrices,
443
+ fundingRates: nextFundingRates,
444
+ nextFundingTimes
445
+ };
400
446
  });
401
447
  }
402
448
  }));
@@ -25437,7 +25483,7 @@ function useSymmHedgerMarkets(params) {
25437
25483
 
25438
25484
  // src/utils/binance-api.ts
25439
25485
  var BINANCE_FAPI_BASE = "https://fapi.binance.com";
25440
- async function fetchMarkPriceKlines(symbol, interval, startTime, endTime, limit = 1500) {
25486
+ async function fetchKlines(symbol, interval, startTime, endTime, limit = 1500) {
25441
25487
  const params = new URLSearchParams({
25442
25488
  symbol,
25443
25489
  interval,
@@ -25445,9 +25491,9 @@ async function fetchMarkPriceKlines(symbol, interval, startTime, endTime, limit
25445
25491
  endTime: String(endTime),
25446
25492
  limit: String(Math.min(limit, 1500))
25447
25493
  });
25448
- const response = await fetch(`${BINANCE_FAPI_BASE}/fapi/v1/markPriceKlines?${params}`);
25494
+ const response = await fetch(`${BINANCE_FAPI_BASE}/fapi/v1/klines?${params}`);
25449
25495
  if (!response.ok) {
25450
- throw new Error(`Binance markPriceKlines failed: ${response.status}`);
25496
+ throw new Error(`Binance klines failed: ${response.status}`);
25451
25497
  }
25452
25498
  const data = await response.json();
25453
25499
  return data.map((k) => ({
@@ -25467,7 +25513,7 @@ async function fetch24hrTicker(symbol) {
25467
25513
  const data = await response.json();
25468
25514
  return {
25469
25515
  lastPrice: parseFloat(data.lastPrice),
25470
- prevClosePrice: parseFloat(data.prevClosePrice),
25516
+ openPrice: parseFloat(data.openPrice),
25471
25517
  priceChangePercent: parseFloat(data.priceChangePercent)
25472
25518
  };
25473
25519
  }
@@ -25481,7 +25527,7 @@ async function fetch24hrTickers() {
25481
25527
  for (const item of data) {
25482
25528
  result[item.symbol] = {
25483
25529
  lastPrice: parseFloat(item.lastPrice),
25484
- prevClosePrice: parseFloat(item.prevClosePrice),
25530
+ openPrice: parseFloat(item.openPrice),
25485
25531
  priceChangePercent: parseFloat(item.priceChangePercent)
25486
25532
  };
25487
25533
  }
@@ -25517,7 +25563,7 @@ function useSymmTokenSelectionMarkets(params) {
25517
25563
  return;
25518
25564
  }
25519
25565
  const ticker = allTickers[binanceSymbol];
25520
- tickerSnapshots[symbol] = ticker ? { prevClosePrice: ticker.prevClosePrice } : null;
25566
+ tickerSnapshots[symbol] = ticker ? { openPrice: ticker.openPrice } : null;
25521
25567
  });
25522
25568
  return { tickerSnapshots };
25523
25569
  },
@@ -25530,7 +25576,7 @@ function useSymmTokenSelectionMarkets(params) {
25530
25576
  return baseMarkets.map((market) => {
25531
25577
  const symbol = market.symbol ?? "";
25532
25578
  const markPrice = symbol ? liveMarkPrices[symbol] ?? null : null;
25533
- const prevDayPrice = symbol ? snapshots[symbol]?.prevClosePrice ?? null : null;
25579
+ const prevDayPrice = symbol ? snapshots[symbol]?.openPrice ?? null : null;
25534
25580
  const priceChange24h = markPrice != null && prevDayPrice != null ? markPrice - prevDayPrice : null;
25535
25581
  const priceChange24hPercent = markPrice != null && prevDayPrice != null && prevDayPrice !== 0 ? (markPrice - prevDayPrice) / prevDayPrice * 100 : null;
25536
25582
  return {
@@ -25545,7 +25591,9 @@ function useSymmTokenSelectionMarkets(params) {
25545
25591
  }, [baseMarkets, liveMarkPrices, priceQuery.data]);
25546
25592
  const marketsBySymbol = react.useMemo(
25547
25593
  () => new Map(
25548
- markets.filter((m) => !!m.symbol).map((m) => [m.symbol, m])
25594
+ markets.filter(
25595
+ (m) => !!m.symbol
25596
+ ).map((m) => [m.symbol, m])
25549
25597
  ),
25550
25598
  [markets]
25551
25599
  );
@@ -25553,64 +25601,7 @@ function useSymmTokenSelectionMarkets(params) {
25553
25601
  () => new Map(markets.map((market) => [market.id, market])),
25554
25602
  [markets]
25555
25603
  );
25556
- react.useEffect(() => {
25557
- console.debug("[useSymmTokenSelectionMarkets] data flow", {
25558
- params,
25559
- query: {
25560
- status: query.status,
25561
- fetchStatus: query.fetchStatus,
25562
- isLoading: query.isLoading,
25563
- isSuccess: query.isSuccess,
25564
- isError: query.isError,
25565
- error: query.error
25566
- },
25567
- priceQuery: {
25568
- status: priceQuery.status,
25569
- fetchStatus: priceQuery.fetchStatus,
25570
- isLoading: priceQuery.isLoading,
25571
- isSuccess: priceQuery.isSuccess,
25572
- isError: priceQuery.isError,
25573
- error: priceQuery.error
25574
- },
25575
- marketSymbols,
25576
- symbolsKey,
25577
- liveMarkPrices,
25578
- tickerSnapshots: priceQuery.data?.tickerSnapshots ?? {},
25579
- result: {
25580
- marketCount: markets.length,
25581
- markets: markets.map((market) => ({
25582
- id: market.id,
25583
- symbol: market.symbol,
25584
- markPrice: market.markPrice,
25585
- prevDayPrice: market.prevDayPrice,
25586
- priceChange24h: market.priceChange24h,
25587
- priceChange24hPercent: market.priceChange24hPercent
25588
- }))
25589
- }
25590
- });
25591
- }, [
25592
- liveMarkPrices,
25593
- marketSymbols,
25594
- markets,
25595
- params,
25596
- priceQuery.data,
25597
- priceQuery.error,
25598
- priceQuery.fetchStatus,
25599
- priceQuery.isError,
25600
- priceQuery.isLoading,
25601
- priceQuery.isSuccess,
25602
- priceQuery.status,
25603
- query.error,
25604
- query.fetchStatus,
25605
- query.isError,
25606
- query.isLoading,
25607
- query.isSuccess,
25608
- query.status,
25609
- symbolsKey
25610
- ]);
25611
25604
  return {
25612
- query,
25613
- priceQuery,
25614
25605
  markets,
25615
25606
  marketsBySymbol,
25616
25607
  marketsById,
@@ -26148,10 +26139,10 @@ async function fetchTickerSnapshot(symbol) {
26148
26139
  const ticker = await fetch24hrTicker(resolution.binanceSymbol);
26149
26140
  if (!ticker) return null;
26150
26141
  return {
26151
- prevClosePrice: ticker.prevClosePrice
26142
+ openPrice: ticker.openPrice
26152
26143
  };
26153
26144
  }
26154
- function toSymmTokenMetadata(currentPrice, prevDayPrice) {
26145
+ function toSymmTokenMetadata(currentPrice, prevDayPrice, fundingRate, nextFundingTime) {
26155
26146
  const priceChange24h = currentPrice - prevDayPrice;
26156
26147
  const priceChange24hPercent = prevDayPrice !== 0 ? (currentPrice - prevDayPrice) / prevDayPrice * 100 : 0;
26157
26148
  return {
@@ -26159,9 +26150,10 @@ function toSymmTokenMetadata(currentPrice, prevDayPrice) {
26159
26150
  prevDayPrice,
26160
26151
  priceChange24h,
26161
26152
  priceChange24hPercent,
26162
- netFunding: 0,
26163
- // SYMM funding integration deferred
26164
- markPrice: currentPrice
26153
+ netFunding: fundingRate,
26154
+ markPrice: currentPrice,
26155
+ fundingRate,
26156
+ nextFundingTime
26165
26157
  };
26166
26158
  }
26167
26159
  function useSymmTokenSelectionMetadata(selection, options = {}) {
@@ -26175,6 +26167,12 @@ function useSymmTokenSelectionMetadata(selection, options = {}) {
26175
26167
  const unavailableReason = isUnsupported ? `Binance market data is unavailable for ${unsupportedSymbols.join(", ")}.` : null;
26176
26168
  const symbolsKey = [...selectedSymbols].sort().join(",");
26177
26169
  const liveMarkPrices = useBinanceMarkPriceStore((state) => state.markPrices);
26170
+ const liveFundingRates = useBinanceMarkPriceStore(
26171
+ (state) => state.fundingRates
26172
+ );
26173
+ const liveNextFundingTimes = useBinanceMarkPriceStore(
26174
+ (state) => state.nextFundingTimes
26175
+ );
26178
26176
  const query = reactQuery.useQuery({
26179
26177
  queryKey: ["symm", "chart-metadata", symbolsKey],
26180
26178
  queryFn: async () => {
@@ -26207,13 +26205,27 @@ function useSymmTokenSelectionMetadata(selection, options = {}) {
26207
26205
  const isLoading = query.isLoading;
26208
26206
  for (const token of longTokens) {
26209
26207
  const currentPrice = liveMarkPrices[token.symbol];
26208
+ const fundingRate = liveFundingRates[token.symbol];
26209
+ const nextFundingTime = liveNextFundingTimes[token.symbol];
26210
26210
  const ticker = tickerSnapshots[token.symbol];
26211
- longMeta[token.symbol] = currentPrice != null && ticker ? toSymmTokenMetadata(currentPrice, ticker.prevClosePrice) : null;
26211
+ longMeta[token.symbol] = currentPrice != null && ticker ? toSymmTokenMetadata(
26212
+ currentPrice,
26213
+ ticker.openPrice,
26214
+ fundingRate ?? 0,
26215
+ nextFundingTime ?? 0
26216
+ ) : null;
26212
26217
  }
26213
26218
  for (const token of shortTokens) {
26214
26219
  const currentPrice = liveMarkPrices[token.symbol];
26220
+ const fundingRate = liveFundingRates[token.symbol];
26221
+ const nextFundingTime = liveNextFundingTimes[token.symbol];
26215
26222
  const ticker = tickerSnapshots[token.symbol];
26216
- shortMeta[token.symbol] = currentPrice != null && ticker ? toSymmTokenMetadata(currentPrice, ticker.prevClosePrice) : null;
26223
+ shortMeta[token.symbol] = currentPrice != null && ticker ? toSymmTokenMetadata(
26224
+ currentPrice,
26225
+ ticker.openPrice,
26226
+ fundingRate ?? 0,
26227
+ nextFundingTime ?? 0
26228
+ ) : null;
26217
26229
  }
26218
26230
  const allLongReady = longTokens.every(
26219
26231
  (t) => longMeta[t.symbol]?.currentPrice != null
@@ -26251,60 +26263,17 @@ function useSymmTokenSelectionMetadata(selection, options = {}) {
26251
26263
  }, [
26252
26264
  isUnsupported,
26253
26265
  longTokens,
26266
+ query,
26254
26267
  query.data,
26255
26268
  query.isLoading,
26256
26269
  shortTokens,
26257
26270
  unavailableReason,
26258
26271
  unsupportedSymbols,
26259
26272
  selectedSymbols.length,
26273
+ liveFundingRates,
26274
+ liveNextFundingTimes,
26260
26275
  liveMarkPrices
26261
26276
  ]);
26262
- react.useEffect(() => {
26263
- console.debug("[useSymmTokenSelectionMetadata] data flow", {
26264
- selection,
26265
- options,
26266
- query: {
26267
- status: query.status,
26268
- fetchStatus: query.fetchStatus,
26269
- isLoading: query.isLoading,
26270
- isSuccess: query.isSuccess,
26271
- isError: query.isError,
26272
- error: query.error
26273
- },
26274
- selectedSymbols,
26275
- unsupportedSymbols,
26276
- unavailableReason,
26277
- liveMarkPrices,
26278
- tickerSnapshots: query.data?.tickerSnapshots ?? {},
26279
- result: {
26280
- isLoading: result.isLoading,
26281
- isPriceDataReady: result.isPriceDataReady,
26282
- isUnsupported: result.isUnsupported,
26283
- longTokensMetadata: result.longTokensMetadata,
26284
- shortTokensMetadata: result.shortTokensMetadata,
26285
- weightedRatio: result.weightedRatio,
26286
- weightedRatio24h: result.weightedRatio24h,
26287
- priceRatio: result.priceRatio,
26288
- priceRatio24h: result.priceRatio24h,
26289
- sumNetFunding: result.sumNetFunding
26290
- }
26291
- });
26292
- }, [
26293
- liveMarkPrices,
26294
- options,
26295
- query.data,
26296
- query.error,
26297
- query.fetchStatus,
26298
- query.isError,
26299
- query.isLoading,
26300
- query.isSuccess,
26301
- query.status,
26302
- result,
26303
- selectedSymbols,
26304
- selection,
26305
- unavailableReason,
26306
- unsupportedSymbols
26307
- ]);
26308
26277
  return result;
26309
26278
  }
26310
26279
 
@@ -26334,10 +26303,13 @@ function toBinanceInterval(interval) {
26334
26303
  }
26335
26304
 
26336
26305
  // src/react/hooks/use-symm-chart-candles.ts
26306
+ function areIntervalsEqual(currentInterval, nextInterval) {
26307
+ return currentInterval === toBinanceInterval(nextInterval);
26308
+ }
26337
26309
  async function fetchSymbolKlines(symbol, interval, start, end) {
26338
26310
  const binanceSymbol = toBinanceSymbol(symbol);
26339
26311
  if (!binanceSymbol) return [];
26340
- const klines = await fetchMarkPriceKlines(
26312
+ const klines = await fetchKlines(
26341
26313
  binanceSymbol,
26342
26314
  toBinanceInterval(interval),
26343
26315
  start,
@@ -26498,6 +26470,15 @@ function useSymmChartCandles(selection) {
26498
26470
  wsUnsubsRef.current.push(unsub);
26499
26471
  }
26500
26472
  }, [emitRealtimeBar, isUnsupported, selectedSymbols]);
26473
+ const setRealtimeInterval = react.useCallback((interval) => {
26474
+ if (areIntervalsEqual(activeIntervalRef.current, interval)) {
26475
+ return;
26476
+ }
26477
+ activeIntervalRef.current = toBinanceInterval(interval);
26478
+ if (listenersRef.current.size > 0) {
26479
+ setupWsSubscriptions();
26480
+ }
26481
+ }, [setupWsSubscriptions]);
26501
26482
  react.useEffect(() => {
26502
26483
  if (listenersRef.current.size > 0) {
26503
26484
  setupWsSubscriptions();
@@ -26509,6 +26490,7 @@ function useSymmChartCandles(selection) {
26509
26490
  }, [setupWsSubscriptions]);
26510
26491
  const fetchBasketCandles = react.useCallback(
26511
26492
  async (start, end, interval) => {
26493
+ setRealtimeInterval(interval);
26512
26494
  const longSymbol = longTokens[0]?.symbol;
26513
26495
  const shortSymbol = shortTokens[0]?.symbol;
26514
26496
  if (isUnsupported) {
@@ -26534,18 +26516,20 @@ function useSymmChartCandles(selection) {
26534
26516
  Object.fromEntries(entries)
26535
26517
  );
26536
26518
  },
26537
- [isUnsupported, longTokens, shortTokens]
26519
+ [isUnsupported, longTokens, setRealtimeInterval, shortTokens]
26538
26520
  );
26539
26521
  const fetchPerformanceCandles = react.useCallback(
26540
26522
  async (start, end, interval, symbol) => {
26523
+ setRealtimeInterval(interval);
26541
26524
  const parts = symbol.split(" ");
26542
26525
  const assetSymbol = parts.length >= 2 ? parts.slice(1).join(" ") : symbol;
26543
26526
  return fetchSymbolKlines(assetSymbol, interval, start, end);
26544
26527
  },
26545
- []
26528
+ [setRealtimeInterval]
26546
26529
  );
26547
26530
  const fetchOverallPerformanceCandles = react.useCallback(
26548
26531
  async (start, end, interval) => {
26532
+ setRealtimeInterval(interval);
26549
26533
  const longSymbol = longTokens[0]?.symbol;
26550
26534
  const shortSymbol = shortTokens[0]?.symbol;
26551
26535
  if (isUnsupported) return [];
@@ -26602,7 +26586,7 @@ function useSymmChartCandles(selection) {
26602
26586
  }
26603
26587
  return result;
26604
26588
  },
26605
- [isUnsupported, longTokens, shortTokens]
26589
+ [isUnsupported, longTokens, setRealtimeInterval, shortTokens]
26606
26590
  );
26607
26591
  const addRealtimeListener = react.useCallback((cb) => {
26608
26592
  const id = Math.random().toString(36).slice(2);