@pear-protocol/symmio-client 0.3.11 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/index.d.mts +6 -4
- package/dist/react/index.d.ts +6 -4
- package/dist/react/index.js +227 -148
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +227 -148
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/provider.js +188 -135
- package/dist/react/provider.js.map +1 -1
- package/dist/react/provider.mjs +188 -135
- package/dist/react/provider.mjs.map +1 -1
- package/package.json +2 -2
package/dist/react/index.mjs
CHANGED
|
@@ -70,6 +70,9 @@ function toBinanceSymbol(symmSymbol) {
|
|
|
70
70
|
// src/utils/binance-ws.ts
|
|
71
71
|
var BINANCE_WS_URL = "wss://fstream.binance.com/market/ws";
|
|
72
72
|
var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
|
|
73
|
+
var IDLE_CLOSE_DELAY_MS = 3e4;
|
|
74
|
+
var STALE_CONNECTION_MS = 3e4;
|
|
75
|
+
var STALE_CHECK_INTERVAL_MS = 1e4;
|
|
73
76
|
var STABLE_QUOTES = ["USDT0", "USDT", "USDC", "USDE", "USDH", "USD"];
|
|
74
77
|
function normalizeBaseSymbol(symbol) {
|
|
75
78
|
const normalized = symbol.toUpperCase().trim();
|
|
@@ -119,8 +122,11 @@ var BinanceWsManager = class {
|
|
|
119
122
|
streams = /* @__PURE__ */ new Map();
|
|
120
123
|
reconnectAttempt = 0;
|
|
121
124
|
reconnectTimer = null;
|
|
125
|
+
idleCloseTimer = null;
|
|
126
|
+
staleCheckTimer = null;
|
|
122
127
|
intentionalClose = false;
|
|
123
|
-
pendingSubscribes =
|
|
128
|
+
pendingSubscribes = /* @__PURE__ */ new Set();
|
|
129
|
+
lastMessageAt = 0;
|
|
124
130
|
idCounter = 0;
|
|
125
131
|
/**
|
|
126
132
|
* Subscribe to a kline stream. Returns an unsubscribe function.
|
|
@@ -193,10 +199,10 @@ var BinanceWsManager = class {
|
|
|
193
199
|
*/
|
|
194
200
|
destroy() {
|
|
195
201
|
this.intentionalClose = true;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
202
|
+
this.clearReconnectTimer();
|
|
203
|
+
this.clearIdleCloseTimer();
|
|
204
|
+
this.clearStaleCheckTimer();
|
|
205
|
+
this.pendingSubscribes.clear();
|
|
200
206
|
if (this.ws) {
|
|
201
207
|
this.ws.close();
|
|
202
208
|
this.ws = null;
|
|
@@ -216,6 +222,7 @@ var BinanceWsManager = class {
|
|
|
216
222
|
}
|
|
217
223
|
sub.callbacks.set(id, cb);
|
|
218
224
|
if (isNew) {
|
|
225
|
+
this.clearIdleCloseTimer();
|
|
219
226
|
this.ensureConnected();
|
|
220
227
|
this.sendSubscribe([streamName]);
|
|
221
228
|
}
|
|
@@ -227,18 +234,14 @@ var BinanceWsManager = class {
|
|
|
227
234
|
if (sub.callbacks.size === 0) {
|
|
228
235
|
this.streams.delete(streamName);
|
|
229
236
|
this.sendUnsubscribe([streamName]);
|
|
230
|
-
|
|
231
|
-
this.intentionalClose = true;
|
|
232
|
-
this.ws.close();
|
|
233
|
-
this.ws = null;
|
|
234
|
-
this.intentionalClose = false;
|
|
235
|
-
}
|
|
237
|
+
this.scheduleIdleClose();
|
|
236
238
|
}
|
|
237
239
|
}
|
|
238
240
|
ensureConnected() {
|
|
239
241
|
if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) {
|
|
240
242
|
return;
|
|
241
243
|
}
|
|
244
|
+
this.clearReconnectTimer();
|
|
242
245
|
this.connect();
|
|
243
246
|
}
|
|
244
247
|
connect() {
|
|
@@ -247,23 +250,27 @@ var BinanceWsManager = class {
|
|
|
247
250
|
this.ws = new WebSocket(BINANCE_WS_URL);
|
|
248
251
|
this.ws.onopen = () => {
|
|
249
252
|
this.reconnectAttempt = 0;
|
|
250
|
-
|
|
253
|
+
this.lastMessageAt = Date.now();
|
|
254
|
+
this.startStaleCheck();
|
|
255
|
+
const activeStreams = Array.from(
|
|
256
|
+
/* @__PURE__ */ new Set([...this.streams.keys(), ...this.pendingSubscribes])
|
|
257
|
+
);
|
|
258
|
+
this.pendingSubscribes.clear();
|
|
251
259
|
if (activeStreams.length > 0) {
|
|
252
260
|
this.sendSubscribe(activeStreams);
|
|
253
261
|
}
|
|
254
|
-
if (this.pendingSubscribes.length > 0) {
|
|
255
|
-
this.sendSubscribe(this.pendingSubscribes);
|
|
256
|
-
this.pendingSubscribes = [];
|
|
257
|
-
}
|
|
258
262
|
};
|
|
259
263
|
this.ws.onmessage = (event) => {
|
|
260
264
|
try {
|
|
261
265
|
const data = JSON.parse(event.data);
|
|
266
|
+
this.lastMessageAt = Date.now();
|
|
262
267
|
this.handleMessage(data);
|
|
263
268
|
} catch {
|
|
264
269
|
}
|
|
265
270
|
};
|
|
266
271
|
this.ws.onclose = () => {
|
|
272
|
+
this.ws = null;
|
|
273
|
+
this.clearStaleCheckTimer();
|
|
267
274
|
if (this.intentionalClose) return;
|
|
268
275
|
this.scheduleReconnect();
|
|
269
276
|
};
|
|
@@ -297,25 +304,27 @@ var BinanceWsManager = class {
|
|
|
297
304
|
}
|
|
298
305
|
sendSubscribe(streams) {
|
|
299
306
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
300
|
-
this.pendingSubscribes.
|
|
307
|
+
streams.forEach((stream) => this.pendingSubscribes.add(stream));
|
|
301
308
|
return;
|
|
302
309
|
}
|
|
310
|
+
const params = Array.from(new Set(streams));
|
|
311
|
+
if (params.length === 0) return;
|
|
303
312
|
this.ws.send(JSON.stringify({
|
|
304
313
|
method: "SUBSCRIBE",
|
|
305
|
-
params
|
|
314
|
+
params,
|
|
306
315
|
id: Date.now()
|
|
307
316
|
}));
|
|
308
317
|
}
|
|
309
318
|
sendUnsubscribe(streams) {
|
|
310
319
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
311
|
-
|
|
312
|
-
(s) => !streams.includes(s)
|
|
313
|
-
);
|
|
320
|
+
streams.forEach((stream) => this.pendingSubscribes.delete(stream));
|
|
314
321
|
return;
|
|
315
322
|
}
|
|
323
|
+
const params = Array.from(new Set(streams));
|
|
324
|
+
if (params.length === 0) return;
|
|
316
325
|
this.ws.send(JSON.stringify({
|
|
317
326
|
method: "UNSUBSCRIBE",
|
|
318
|
-
params
|
|
327
|
+
params,
|
|
319
328
|
id: Date.now()
|
|
320
329
|
}));
|
|
321
330
|
}
|
|
@@ -329,6 +338,44 @@ var BinanceWsManager = class {
|
|
|
329
338
|
this.connect();
|
|
330
339
|
}, delay);
|
|
331
340
|
}
|
|
341
|
+
scheduleIdleClose() {
|
|
342
|
+
if (this.streams.size > 0 || this.idleCloseTimer) return;
|
|
343
|
+
this.clearReconnectTimer();
|
|
344
|
+
if (!this.ws) return;
|
|
345
|
+
this.idleCloseTimer = setTimeout(() => {
|
|
346
|
+
this.idleCloseTimer = null;
|
|
347
|
+
if (this.streams.size > 0 || !this.ws) return;
|
|
348
|
+
this.intentionalClose = true;
|
|
349
|
+
this.ws.close();
|
|
350
|
+
this.ws = null;
|
|
351
|
+
this.intentionalClose = false;
|
|
352
|
+
this.clearStaleCheckTimer();
|
|
353
|
+
}, IDLE_CLOSE_DELAY_MS);
|
|
354
|
+
}
|
|
355
|
+
startStaleCheck() {
|
|
356
|
+
this.clearStaleCheckTimer();
|
|
357
|
+
this.staleCheckTimer = setInterval(() => {
|
|
358
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
|
359
|
+
if (this.streams.size === 0) return;
|
|
360
|
+
if (Date.now() - this.lastMessageAt < STALE_CONNECTION_MS) return;
|
|
361
|
+
this.ws.close();
|
|
362
|
+
}, STALE_CHECK_INTERVAL_MS);
|
|
363
|
+
}
|
|
364
|
+
clearReconnectTimer() {
|
|
365
|
+
if (!this.reconnectTimer) return;
|
|
366
|
+
clearTimeout(this.reconnectTimer);
|
|
367
|
+
this.reconnectTimer = null;
|
|
368
|
+
}
|
|
369
|
+
clearIdleCloseTimer() {
|
|
370
|
+
if (!this.idleCloseTimer) return;
|
|
371
|
+
clearTimeout(this.idleCloseTimer);
|
|
372
|
+
this.idleCloseTimer = null;
|
|
373
|
+
}
|
|
374
|
+
clearStaleCheckTimer() {
|
|
375
|
+
if (!this.staleCheckTimer) return;
|
|
376
|
+
clearInterval(this.staleCheckTimer);
|
|
377
|
+
this.staleCheckTimer = null;
|
|
378
|
+
}
|
|
332
379
|
};
|
|
333
380
|
var _instance = null;
|
|
334
381
|
function getBinanceWsManager() {
|
|
@@ -359,6 +406,28 @@ function getNextRefCount(binanceSymbol) {
|
|
|
359
406
|
function getPrevRefCount(binanceSymbol) {
|
|
360
407
|
return Math.max(0, (refCounts.get(binanceSymbol) ?? 0) - 1);
|
|
361
408
|
}
|
|
409
|
+
function addMappedSymbol(binanceSymbol, symmSymbol) {
|
|
410
|
+
const symbols = streamSymbols.get(binanceSymbol) ?? /* @__PURE__ */ new Map();
|
|
411
|
+
symbols.set(symmSymbol, (symbols.get(symmSymbol) ?? 0) + 1);
|
|
412
|
+
streamSymbols.set(binanceSymbol, symbols);
|
|
413
|
+
}
|
|
414
|
+
function removeMappedSymbol(binanceSymbol, symmSymbol) {
|
|
415
|
+
const symbols = streamSymbols.get(binanceSymbol);
|
|
416
|
+
if (!symbols) return false;
|
|
417
|
+
const currentCount = symbols.get(symmSymbol) ?? 0;
|
|
418
|
+
if (currentCount <= 0) return false;
|
|
419
|
+
if (currentCount === 1) {
|
|
420
|
+
symbols.delete(symmSymbol);
|
|
421
|
+
} else {
|
|
422
|
+
symbols.set(symmSymbol, currentCount - 1);
|
|
423
|
+
}
|
|
424
|
+
if (symbols.size === 0) {
|
|
425
|
+
streamSymbols.delete(binanceSymbol);
|
|
426
|
+
} else {
|
|
427
|
+
streamSymbols.set(binanceSymbol, symbols);
|
|
428
|
+
}
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
362
431
|
var useBinanceMarkPriceStore = create((set) => ({
|
|
363
432
|
markPrices: {},
|
|
364
433
|
fundingRates: {},
|
|
@@ -367,9 +436,7 @@ var useBinanceMarkPriceStore = create((set) => ({
|
|
|
367
436
|
const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
|
|
368
437
|
const nextRefCount = getNextRefCount(binanceSymbol);
|
|
369
438
|
refCounts.set(binanceSymbol, nextRefCount);
|
|
370
|
-
|
|
371
|
-
symbols.add(symmSymbol);
|
|
372
|
-
streamSymbols.set(binanceSymbol, symbols);
|
|
439
|
+
addMappedSymbol(binanceSymbol, symmSymbol);
|
|
373
440
|
if (allMarkPricesRefCount === 0) {
|
|
374
441
|
const wsManager = getBinanceWsManager();
|
|
375
442
|
allMarkPricesUnsubscribe = wsManager.subscribeAllMarkPrices((entries) => {
|
|
@@ -384,7 +451,7 @@ var useBinanceMarkPriceStore = create((set) => ({
|
|
|
384
451
|
nextMarkPrices ??= { ...state.markPrices };
|
|
385
452
|
nextFundingRates ??= { ...state.fundingRates };
|
|
386
453
|
nextFundingTimes ??= { ...state.nextFundingTimes };
|
|
387
|
-
mappedSymbols.forEach((mappedSymbol) => {
|
|
454
|
+
mappedSymbols.forEach((_count, mappedSymbol) => {
|
|
388
455
|
nextMarkPrices[mappedSymbol] = entry.markPrice;
|
|
389
456
|
nextFundingRates[mappedSymbol] = entry.fundingRate;
|
|
390
457
|
nextFundingTimes[mappedSymbol] = entry.nextFundingTime;
|
|
@@ -405,14 +472,9 @@ var useBinanceMarkPriceStore = create((set) => ({
|
|
|
405
472
|
},
|
|
406
473
|
unsubscribeSymbol: (symmSymbol, rawBinanceSymbol) => {
|
|
407
474
|
const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
|
|
408
|
-
const
|
|
409
|
-
if (
|
|
410
|
-
|
|
411
|
-
if (symbols.size === 0) {
|
|
412
|
-
streamSymbols.delete(binanceSymbol);
|
|
413
|
-
} else {
|
|
414
|
-
streamSymbols.set(binanceSymbol, symbols);
|
|
415
|
-
}
|
|
475
|
+
const removedSubscription = removeMappedSymbol(binanceSymbol, symmSymbol);
|
|
476
|
+
if (!removedSubscription) {
|
|
477
|
+
return;
|
|
416
478
|
}
|
|
417
479
|
const nextRefCount = getPrevRefCount(binanceSymbol);
|
|
418
480
|
if (nextRefCount === 0) {
|
|
@@ -426,6 +488,10 @@ var useBinanceMarkPriceStore = create((set) => ({
|
|
|
426
488
|
allMarkPricesUnsubscribe = null;
|
|
427
489
|
}
|
|
428
490
|
set((state) => {
|
|
491
|
+
const hasMappedSymbol = Boolean(streamSymbols.get(binanceSymbol)?.has(symmSymbol));
|
|
492
|
+
if (hasMappedSymbol) {
|
|
493
|
+
return state;
|
|
494
|
+
}
|
|
429
495
|
if (state.markPrices[symmSymbol] == null && state.fundingRates[symmSymbol] == null && state.nextFundingTimes[symmSymbol] == null) {
|
|
430
496
|
return state;
|
|
431
497
|
}
|
|
@@ -543,8 +609,33 @@ var useSymmWsStore = create((set) => ({
|
|
|
543
609
|
}));
|
|
544
610
|
|
|
545
611
|
// src/react/hooks/use-symm-ws.ts
|
|
546
|
-
|
|
547
|
-
|
|
612
|
+
var wsOwnerCounts = /* @__PURE__ */ new WeakMap();
|
|
613
|
+
var wsConnectPromises = /* @__PURE__ */ new WeakMap();
|
|
614
|
+
function addWsOwner(ws) {
|
|
615
|
+
wsOwnerCounts.set(ws, (wsOwnerCounts.get(ws) ?? 0) + 1);
|
|
616
|
+
}
|
|
617
|
+
function removeWsOwner(ws) {
|
|
618
|
+
const nextCount = Math.max(0, (wsOwnerCounts.get(ws) ?? 0) - 1);
|
|
619
|
+
if (nextCount === 0) {
|
|
620
|
+
wsOwnerCounts.delete(ws);
|
|
621
|
+
} else {
|
|
622
|
+
wsOwnerCounts.set(ws, nextCount);
|
|
623
|
+
}
|
|
624
|
+
return nextCount;
|
|
625
|
+
}
|
|
626
|
+
function connectShared(ws) {
|
|
627
|
+
if (ws.isConnected()) {
|
|
628
|
+
return Promise.resolve();
|
|
629
|
+
}
|
|
630
|
+
const existing = wsConnectPromises.get(ws);
|
|
631
|
+
if (existing) {
|
|
632
|
+
return existing;
|
|
633
|
+
}
|
|
634
|
+
const promise = ws.connect().finally(() => {
|
|
635
|
+
wsConnectPromises.delete(ws);
|
|
636
|
+
});
|
|
637
|
+
wsConnectPromises.set(ws, promise);
|
|
638
|
+
return promise;
|
|
548
639
|
}
|
|
549
640
|
function useSymmWs(params = {}) {
|
|
550
641
|
const ctx = useContext(SymmContext);
|
|
@@ -561,114 +652,76 @@ function useSymmWs(params = {}) {
|
|
|
561
652
|
}
|
|
562
653
|
const ws = symmCoreClient.ws;
|
|
563
654
|
const addr = accountAddress;
|
|
564
|
-
const unsubscribers = [];
|
|
565
655
|
let cancelled = false;
|
|
566
|
-
|
|
567
|
-
|
|
656
|
+
addWsOwner(ws);
|
|
657
|
+
const removeOnConnect = ws.onConnect(() => setConnected(true));
|
|
658
|
+
const removeOnDisconnect = ws.onDisconnect(() => setConnected(false));
|
|
659
|
+
const subscriptions = [];
|
|
660
|
+
const addSubscription = (channel, handler) => {
|
|
661
|
+
ws.subscribe(channel, addr, chainId, handler);
|
|
662
|
+
subscriptions.push({ channel, handler });
|
|
663
|
+
};
|
|
664
|
+
addSubscription("positions", () => {
|
|
665
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.positionsRoot });
|
|
568
666
|
});
|
|
569
|
-
|
|
570
|
-
|
|
667
|
+
addSubscription("open-orders", () => {
|
|
668
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
571
669
|
});
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
})
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
})
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
})
|
|
612
|
-
);
|
|
613
|
-
if (accountSummaryUnsub) unsubscribers.push(accountSummaryUnsub);
|
|
614
|
-
const notificationsUnsub = asUnsubscribeFn(
|
|
615
|
-
ws.subscribeToNotifications(addr, chainId, () => {
|
|
616
|
-
queryClient.invalidateQueries({
|
|
617
|
-
queryKey: symmKeys.notifications({ accountAddress, chainId })
|
|
618
|
-
});
|
|
619
|
-
queryClient.invalidateQueries({
|
|
620
|
-
queryKey: symmKeys.unreadCount({ accountAddress, chainId })
|
|
621
|
-
});
|
|
622
|
-
})
|
|
623
|
-
);
|
|
624
|
-
if (notificationsUnsub) unsubscribers.push(notificationsUnsub);
|
|
625
|
-
const tpslUnsub = asUnsubscribeFn(
|
|
626
|
-
ws.subscribeToTpsl(addr, chainId, () => {
|
|
627
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.tpslOrdersRoot });
|
|
628
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
629
|
-
})
|
|
630
|
-
);
|
|
631
|
-
if (tpslUnsub) unsubscribers.push(tpslUnsub);
|
|
632
|
-
const twapUnsub = asUnsubscribeFn(
|
|
633
|
-
ws.subscribeToTwapOrders(addr, chainId, () => {
|
|
634
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.twapOrdersRoot });
|
|
635
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
636
|
-
})
|
|
637
|
-
);
|
|
638
|
-
if (twapUnsub) unsubscribers.push(twapUnsub);
|
|
639
|
-
const triggerOrdersUnsub = asUnsubscribeFn(
|
|
640
|
-
ws.subscribeToTriggerOrders(addr, chainId, () => {
|
|
641
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.triggerOrdersRoot });
|
|
642
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
643
|
-
})
|
|
644
|
-
);
|
|
645
|
-
if (triggerOrdersUnsub) unsubscribers.push(triggerOrdersUnsub);
|
|
646
|
-
const executionsUnsub = asUnsubscribeFn(
|
|
647
|
-
ws.subscribeToExecutions(addr, chainId, () => {
|
|
648
|
-
queryClient.invalidateQueries({
|
|
649
|
-
queryKey: symmKeys.positionsRoot
|
|
650
|
-
});
|
|
651
|
-
queryClient.invalidateQueries({
|
|
652
|
-
queryKey: symmKeys.portfolioRoot
|
|
653
|
-
});
|
|
654
|
-
})
|
|
655
|
-
);
|
|
656
|
-
if (executionsUnsub) unsubscribers.push(executionsUnsub);
|
|
657
|
-
void ws.connect().then(() => {
|
|
658
|
-
if (cancelled) {
|
|
659
|
-
return;
|
|
670
|
+
addSubscription("trades", () => {
|
|
671
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.tradeHistoryRoot });
|
|
672
|
+
});
|
|
673
|
+
addSubscription("account-summary", () => {
|
|
674
|
+
queryClient.invalidateQueries({
|
|
675
|
+
queryKey: symmKeys.balances(accountAddress, chainId)
|
|
676
|
+
});
|
|
677
|
+
queryClient.invalidateQueries({
|
|
678
|
+
queryKey: symmKeys.accountSummary(accountAddress, chainId)
|
|
679
|
+
});
|
|
680
|
+
});
|
|
681
|
+
addSubscription("notifications", () => {
|
|
682
|
+
queryClient.invalidateQueries({
|
|
683
|
+
queryKey: symmKeys.notifications({ accountAddress, chainId })
|
|
684
|
+
});
|
|
685
|
+
queryClient.invalidateQueries({
|
|
686
|
+
queryKey: symmKeys.unreadCount({ accountAddress, chainId })
|
|
687
|
+
});
|
|
688
|
+
});
|
|
689
|
+
addSubscription("tpsl", () => {
|
|
690
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.tpslOrdersRoot });
|
|
691
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
692
|
+
});
|
|
693
|
+
addSubscription("twap-orders", () => {
|
|
694
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.twapOrdersRoot });
|
|
695
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
696
|
+
});
|
|
697
|
+
addSubscription("trigger-orders", () => {
|
|
698
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.triggerOrdersRoot });
|
|
699
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
700
|
+
});
|
|
701
|
+
addSubscription("executions", () => {
|
|
702
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.positionsRoot });
|
|
703
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.portfolioRoot });
|
|
704
|
+
});
|
|
705
|
+
void connectShared(ws).then(() => {
|
|
706
|
+
if (cancelled) return;
|
|
707
|
+
if (ws.isConnected()) {
|
|
708
|
+
setConnected(true);
|
|
660
709
|
}
|
|
661
710
|
}).catch(() => {
|
|
662
|
-
if (cancelled)
|
|
663
|
-
return;
|
|
664
|
-
}
|
|
711
|
+
if (cancelled) return;
|
|
665
712
|
setConnected(false);
|
|
666
713
|
});
|
|
667
714
|
return () => {
|
|
668
715
|
cancelled = true;
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
716
|
+
removeOnConnect();
|
|
717
|
+
removeOnDisconnect();
|
|
718
|
+
subscriptions.forEach(({ channel, handler }) => {
|
|
719
|
+
ws.unsubscribe(channel, addr, chainId, handler);
|
|
720
|
+
});
|
|
721
|
+
if (removeWsOwner(ws) === 0) {
|
|
722
|
+
ws.disconnect();
|
|
723
|
+
setConnected(false);
|
|
724
|
+
}
|
|
672
725
|
};
|
|
673
726
|
}, [symmCoreClient, accountAddress, chainId, queryClient, setConnected]);
|
|
674
727
|
return { isConnected };
|
|
@@ -831,28 +884,54 @@ async function login(chainId, params) {
|
|
|
831
884
|
var TOKEN_STORAGE_PREFIX = "symm_access_token";
|
|
832
885
|
var TOKEN_STORAGE_VERSION = 1;
|
|
833
886
|
function cacheKey(address, chainId) {
|
|
834
|
-
return `${address}:${chainId}`;
|
|
887
|
+
return `${address.toLowerCase()}:${chainId}`;
|
|
835
888
|
}
|
|
836
889
|
function storageKey(address, chainId) {
|
|
837
890
|
return `${TOKEN_STORAGE_PREFIX}:${TOKEN_STORAGE_VERSION}:${cacheKey(address, chainId)}`;
|
|
838
891
|
}
|
|
892
|
+
function findStorageKey(address, chainId) {
|
|
893
|
+
const canonicalKey = storageKey(address, chainId);
|
|
894
|
+
if (typeof window === "undefined") return canonicalKey;
|
|
895
|
+
if (window.localStorage.getItem(canonicalKey) != null) {
|
|
896
|
+
return canonicalKey;
|
|
897
|
+
}
|
|
898
|
+
const normalizedKey = canonicalKey.toLowerCase();
|
|
899
|
+
for (let index = 0; index < window.localStorage.length; index += 1) {
|
|
900
|
+
const key = window.localStorage.key(index);
|
|
901
|
+
if (key?.toLowerCase() === normalizedKey) {
|
|
902
|
+
return key;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
return canonicalKey;
|
|
906
|
+
}
|
|
907
|
+
function removeStoredTokenKeys(address, chainId) {
|
|
908
|
+
if (typeof window === "undefined") return;
|
|
909
|
+
const normalizedKey = storageKey(address, chainId).toLowerCase();
|
|
910
|
+
for (let index = window.localStorage.length - 1; index >= 0; index -= 1) {
|
|
911
|
+
const key = window.localStorage.key(index);
|
|
912
|
+
if (key?.toLowerCase() === normalizedKey) {
|
|
913
|
+
window.localStorage.removeItem(key);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
839
917
|
function getCachedTokenEntry(address, chainId) {
|
|
840
918
|
if (typeof window === "undefined") return null;
|
|
919
|
+
const key = findStorageKey(address, chainId);
|
|
841
920
|
try {
|
|
842
|
-
const raw = window.localStorage.getItem(
|
|
921
|
+
const raw = window.localStorage.getItem(key);
|
|
843
922
|
if (!raw) return null;
|
|
844
923
|
const parsed = JSON.parse(raw);
|
|
845
924
|
if (!parsed || typeof parsed.token !== "string" || typeof parsed.expiresAt !== "number") {
|
|
846
|
-
window.localStorage.removeItem(
|
|
925
|
+
window.localStorage.removeItem(key);
|
|
847
926
|
return null;
|
|
848
927
|
}
|
|
849
928
|
if (Date.now() >= parsed.expiresAt) {
|
|
850
|
-
window.localStorage.removeItem(
|
|
929
|
+
window.localStorage.removeItem(key);
|
|
851
930
|
return null;
|
|
852
931
|
}
|
|
853
932
|
return parsed;
|
|
854
933
|
} catch {
|
|
855
|
-
window.localStorage.removeItem(
|
|
934
|
+
window.localStorage.removeItem(key);
|
|
856
935
|
return null;
|
|
857
936
|
}
|
|
858
937
|
}
|
|
@@ -867,9 +946,7 @@ function writeStoredToken(address, chainId, cached) {
|
|
|
867
946
|
}
|
|
868
947
|
}
|
|
869
948
|
function clearCachedToken(address, chainId) {
|
|
870
|
-
|
|
871
|
-
window.localStorage.removeItem(storageKey(address, chainId));
|
|
872
|
-
}
|
|
949
|
+
removeStoredTokenKeys(address, chainId);
|
|
873
950
|
}
|
|
874
951
|
async function fetchAccessTokenEntry(walletClient, signerAddress, accountAddress, chainId, domain) {
|
|
875
952
|
const resolvedDomain = domain ?? (typeof window !== "undefined" ? window.location.hostname : "localhost");
|
|
@@ -903,7 +980,7 @@ async function fetchAccessTokenEntry(walletClient, signerAddress, accountAddress
|
|
|
903
980
|
return cachedToken;
|
|
904
981
|
}
|
|
905
982
|
function authStoreKey(accountAddress, chainId, signerAddress) {
|
|
906
|
-
return `${accountAddress}:${chainId}:${signerAddress ?? ""}`;
|
|
983
|
+
return `${accountAddress.toLowerCase()}:${chainId}:${signerAddress?.toLowerCase() ?? ""}`;
|
|
907
984
|
}
|
|
908
985
|
function getEntryFromSnapshot(state, accountAddress, chainId, signerAddress) {
|
|
909
986
|
const signerScoped = state.entries[authStoreKey(accountAddress, chainId, signerAddress)];
|
|
@@ -2344,14 +2421,15 @@ function splitTradeHookArgs(paramsOrOptions, options) {
|
|
|
2344
2421
|
function useResolveTradeAuthToken(params = {}) {
|
|
2345
2422
|
const context = useSymmContext();
|
|
2346
2423
|
const address = params.address ?? context.address;
|
|
2424
|
+
const defaultAccountAddress = params.accountAddress ?? address;
|
|
2347
2425
|
const chainId = params.chainId ?? context.chainId;
|
|
2348
2426
|
return useCallback(
|
|
2349
|
-
async (providedAuthToken,
|
|
2427
|
+
async (providedAuthToken, requestAccountAddress, overrideChainId) => {
|
|
2350
2428
|
const resolvedChainId = overrideChainId ?? chainId;
|
|
2351
2429
|
if (providedAuthToken) {
|
|
2352
2430
|
return providedAuthToken;
|
|
2353
2431
|
}
|
|
2354
|
-
const resolvedAccountAddress =
|
|
2432
|
+
const resolvedAccountAddress = requestAccountAddress ?? defaultAccountAddress;
|
|
2355
2433
|
if (!resolvedAccountAddress) {
|
|
2356
2434
|
return null;
|
|
2357
2435
|
}
|
|
@@ -2365,7 +2443,7 @@ function useResolveTradeAuthToken(params = {}) {
|
|
|
2365
2443
|
}
|
|
2366
2444
|
return null;
|
|
2367
2445
|
},
|
|
2368
|
-
[address, chainId]
|
|
2446
|
+
[address, defaultAccountAddress, chainId]
|
|
2369
2447
|
);
|
|
2370
2448
|
}
|
|
2371
2449
|
|
|
@@ -25614,7 +25692,8 @@ function useSymmClosePositionMutation(paramsOrOptions, maybeOptions) {
|
|
|
25614
25692
|
const typedRequest = request;
|
|
25615
25693
|
const authToken = await resolveAuthToken(
|
|
25616
25694
|
typedRequest.authToken,
|
|
25617
|
-
typedRequest.accountAddress
|
|
25695
|
+
typedRequest.accountAddress,
|
|
25696
|
+
typedRequest.chainId
|
|
25618
25697
|
);
|
|
25619
25698
|
if (!authToken) {
|
|
25620
25699
|
throw new Error("auth token is required to close a position");
|