@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.d.mts
CHANGED
|
@@ -8552,12 +8552,16 @@ declare function useSymmBalances(params: {
|
|
|
8552
8552
|
}): _tanstack_react_query.UseQueryResult<node_modules__pear_protocol_symm_core_dist_types.BalanceInfoResponse, Error>;
|
|
8553
8553
|
|
|
8554
8554
|
type SymmTradeAuthParams = {
|
|
8555
|
+
accountAddress?: Address;
|
|
8555
8556
|
address?: Address;
|
|
8556
8557
|
chainId?: number;
|
|
8557
8558
|
};
|
|
8558
8559
|
|
|
8559
8560
|
type OpenBasketMutationRequest = WithOptionalAuthToken<OpenBasketPositionRequest>;
|
|
8560
|
-
type ClosePositionMutationRequest = WithOptionalAuthToken<ClosePositionRequest
|
|
8561
|
+
type ClosePositionMutationRequest = WithOptionalAuthToken<ClosePositionRequest> & {
|
|
8562
|
+
accountAddress?: Address;
|
|
8563
|
+
chainId?: number;
|
|
8564
|
+
};
|
|
8561
8565
|
type CloseAllPositionsMutationRequest = WithOptionalAuthToken<Parameters<NonNullable<ReturnType<typeof useSymmContext>['symmCoreClient']>['positions']['closeAll']>[0]>;
|
|
8562
8566
|
type UpdatePositionMutationRequest = WithOptionalAuthToken<UpdatePositionRequest>;
|
|
8563
8567
|
/**
|
|
@@ -8575,9 +8579,7 @@ declare function useSymmClosePositionMutation(paramsOrOptions?: SymmTradeAuthPar
|
|
|
8575
8579
|
mutation?: SymmMutationConfig<unknown, Error, ClosePositionMutationRequest>;
|
|
8576
8580
|
}, maybeOptions?: {
|
|
8577
8581
|
mutation?: SymmMutationConfig<unknown, Error, ClosePositionMutationRequest>;
|
|
8578
|
-
}): _tanstack_react_query.UseMutationResult<_pear_protocol_symm_core.ClosePositionResponse | _pear_protocol_symm_core.CloseCommandResult, Error,
|
|
8579
|
-
authToken?: string | undefined;
|
|
8580
|
-
}, unknown>;
|
|
8582
|
+
}): _tanstack_react_query.UseMutationResult<_pear_protocol_symm_core.ClosePositionResponse | _pear_protocol_symm_core.CloseCommandResult, Error, ClosePositionMutationRequest, unknown>;
|
|
8581
8583
|
/**
|
|
8582
8584
|
* Use case: Close all open positions for the provided request scope.
|
|
8583
8585
|
*/
|
package/dist/react/index.d.ts
CHANGED
|
@@ -8552,12 +8552,16 @@ declare function useSymmBalances(params: {
|
|
|
8552
8552
|
}): _tanstack_react_query.UseQueryResult<node_modules__pear_protocol_symm_core_dist_types.BalanceInfoResponse, Error>;
|
|
8553
8553
|
|
|
8554
8554
|
type SymmTradeAuthParams = {
|
|
8555
|
+
accountAddress?: Address;
|
|
8555
8556
|
address?: Address;
|
|
8556
8557
|
chainId?: number;
|
|
8557
8558
|
};
|
|
8558
8559
|
|
|
8559
8560
|
type OpenBasketMutationRequest = WithOptionalAuthToken<OpenBasketPositionRequest>;
|
|
8560
|
-
type ClosePositionMutationRequest = WithOptionalAuthToken<ClosePositionRequest
|
|
8561
|
+
type ClosePositionMutationRequest = WithOptionalAuthToken<ClosePositionRequest> & {
|
|
8562
|
+
accountAddress?: Address;
|
|
8563
|
+
chainId?: number;
|
|
8564
|
+
};
|
|
8561
8565
|
type CloseAllPositionsMutationRequest = WithOptionalAuthToken<Parameters<NonNullable<ReturnType<typeof useSymmContext>['symmCoreClient']>['positions']['closeAll']>[0]>;
|
|
8562
8566
|
type UpdatePositionMutationRequest = WithOptionalAuthToken<UpdatePositionRequest>;
|
|
8563
8567
|
/**
|
|
@@ -8575,9 +8579,7 @@ declare function useSymmClosePositionMutation(paramsOrOptions?: SymmTradeAuthPar
|
|
|
8575
8579
|
mutation?: SymmMutationConfig<unknown, Error, ClosePositionMutationRequest>;
|
|
8576
8580
|
}, maybeOptions?: {
|
|
8577
8581
|
mutation?: SymmMutationConfig<unknown, Error, ClosePositionMutationRequest>;
|
|
8578
|
-
}): _tanstack_react_query.UseMutationResult<_pear_protocol_symm_core.ClosePositionResponse | _pear_protocol_symm_core.CloseCommandResult, Error,
|
|
8579
|
-
authToken?: string | undefined;
|
|
8580
|
-
}, unknown>;
|
|
8582
|
+
}): _tanstack_react_query.UseMutationResult<_pear_protocol_symm_core.ClosePositionResponse | _pear_protocol_symm_core.CloseCommandResult, Error, ClosePositionMutationRequest, unknown>;
|
|
8581
8583
|
/**
|
|
8582
8584
|
* Use case: Close all open positions for the provided request scope.
|
|
8583
8585
|
*/
|
package/dist/react/index.js
CHANGED
|
@@ -72,6 +72,9 @@ function toBinanceSymbol(symmSymbol) {
|
|
|
72
72
|
// src/utils/binance-ws.ts
|
|
73
73
|
var BINANCE_WS_URL = "wss://fstream.binance.com/market/ws";
|
|
74
74
|
var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
|
|
75
|
+
var IDLE_CLOSE_DELAY_MS = 3e4;
|
|
76
|
+
var STALE_CONNECTION_MS = 3e4;
|
|
77
|
+
var STALE_CHECK_INTERVAL_MS = 1e4;
|
|
75
78
|
var STABLE_QUOTES = ["USDT0", "USDT", "USDC", "USDE", "USDH", "USD"];
|
|
76
79
|
function normalizeBaseSymbol(symbol) {
|
|
77
80
|
const normalized = symbol.toUpperCase().trim();
|
|
@@ -121,8 +124,11 @@ var BinanceWsManager = class {
|
|
|
121
124
|
streams = /* @__PURE__ */ new Map();
|
|
122
125
|
reconnectAttempt = 0;
|
|
123
126
|
reconnectTimer = null;
|
|
127
|
+
idleCloseTimer = null;
|
|
128
|
+
staleCheckTimer = null;
|
|
124
129
|
intentionalClose = false;
|
|
125
|
-
pendingSubscribes =
|
|
130
|
+
pendingSubscribes = /* @__PURE__ */ new Set();
|
|
131
|
+
lastMessageAt = 0;
|
|
126
132
|
idCounter = 0;
|
|
127
133
|
/**
|
|
128
134
|
* Subscribe to a kline stream. Returns an unsubscribe function.
|
|
@@ -195,10 +201,10 @@ var BinanceWsManager = class {
|
|
|
195
201
|
*/
|
|
196
202
|
destroy() {
|
|
197
203
|
this.intentionalClose = true;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
204
|
+
this.clearReconnectTimer();
|
|
205
|
+
this.clearIdleCloseTimer();
|
|
206
|
+
this.clearStaleCheckTimer();
|
|
207
|
+
this.pendingSubscribes.clear();
|
|
202
208
|
if (this.ws) {
|
|
203
209
|
this.ws.close();
|
|
204
210
|
this.ws = null;
|
|
@@ -218,6 +224,7 @@ var BinanceWsManager = class {
|
|
|
218
224
|
}
|
|
219
225
|
sub.callbacks.set(id, cb);
|
|
220
226
|
if (isNew) {
|
|
227
|
+
this.clearIdleCloseTimer();
|
|
221
228
|
this.ensureConnected();
|
|
222
229
|
this.sendSubscribe([streamName]);
|
|
223
230
|
}
|
|
@@ -229,18 +236,14 @@ var BinanceWsManager = class {
|
|
|
229
236
|
if (sub.callbacks.size === 0) {
|
|
230
237
|
this.streams.delete(streamName);
|
|
231
238
|
this.sendUnsubscribe([streamName]);
|
|
232
|
-
|
|
233
|
-
this.intentionalClose = true;
|
|
234
|
-
this.ws.close();
|
|
235
|
-
this.ws = null;
|
|
236
|
-
this.intentionalClose = false;
|
|
237
|
-
}
|
|
239
|
+
this.scheduleIdleClose();
|
|
238
240
|
}
|
|
239
241
|
}
|
|
240
242
|
ensureConnected() {
|
|
241
243
|
if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) {
|
|
242
244
|
return;
|
|
243
245
|
}
|
|
246
|
+
this.clearReconnectTimer();
|
|
244
247
|
this.connect();
|
|
245
248
|
}
|
|
246
249
|
connect() {
|
|
@@ -249,23 +252,27 @@ var BinanceWsManager = class {
|
|
|
249
252
|
this.ws = new WebSocket(BINANCE_WS_URL);
|
|
250
253
|
this.ws.onopen = () => {
|
|
251
254
|
this.reconnectAttempt = 0;
|
|
252
|
-
|
|
255
|
+
this.lastMessageAt = Date.now();
|
|
256
|
+
this.startStaleCheck();
|
|
257
|
+
const activeStreams = Array.from(
|
|
258
|
+
/* @__PURE__ */ new Set([...this.streams.keys(), ...this.pendingSubscribes])
|
|
259
|
+
);
|
|
260
|
+
this.pendingSubscribes.clear();
|
|
253
261
|
if (activeStreams.length > 0) {
|
|
254
262
|
this.sendSubscribe(activeStreams);
|
|
255
263
|
}
|
|
256
|
-
if (this.pendingSubscribes.length > 0) {
|
|
257
|
-
this.sendSubscribe(this.pendingSubscribes);
|
|
258
|
-
this.pendingSubscribes = [];
|
|
259
|
-
}
|
|
260
264
|
};
|
|
261
265
|
this.ws.onmessage = (event) => {
|
|
262
266
|
try {
|
|
263
267
|
const data = JSON.parse(event.data);
|
|
268
|
+
this.lastMessageAt = Date.now();
|
|
264
269
|
this.handleMessage(data);
|
|
265
270
|
} catch {
|
|
266
271
|
}
|
|
267
272
|
};
|
|
268
273
|
this.ws.onclose = () => {
|
|
274
|
+
this.ws = null;
|
|
275
|
+
this.clearStaleCheckTimer();
|
|
269
276
|
if (this.intentionalClose) return;
|
|
270
277
|
this.scheduleReconnect();
|
|
271
278
|
};
|
|
@@ -299,25 +306,27 @@ var BinanceWsManager = class {
|
|
|
299
306
|
}
|
|
300
307
|
sendSubscribe(streams) {
|
|
301
308
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
302
|
-
this.pendingSubscribes.
|
|
309
|
+
streams.forEach((stream) => this.pendingSubscribes.add(stream));
|
|
303
310
|
return;
|
|
304
311
|
}
|
|
312
|
+
const params = Array.from(new Set(streams));
|
|
313
|
+
if (params.length === 0) return;
|
|
305
314
|
this.ws.send(JSON.stringify({
|
|
306
315
|
method: "SUBSCRIBE",
|
|
307
|
-
params
|
|
316
|
+
params,
|
|
308
317
|
id: Date.now()
|
|
309
318
|
}));
|
|
310
319
|
}
|
|
311
320
|
sendUnsubscribe(streams) {
|
|
312
321
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
313
|
-
|
|
314
|
-
(s) => !streams.includes(s)
|
|
315
|
-
);
|
|
322
|
+
streams.forEach((stream) => this.pendingSubscribes.delete(stream));
|
|
316
323
|
return;
|
|
317
324
|
}
|
|
325
|
+
const params = Array.from(new Set(streams));
|
|
326
|
+
if (params.length === 0) return;
|
|
318
327
|
this.ws.send(JSON.stringify({
|
|
319
328
|
method: "UNSUBSCRIBE",
|
|
320
|
-
params
|
|
329
|
+
params,
|
|
321
330
|
id: Date.now()
|
|
322
331
|
}));
|
|
323
332
|
}
|
|
@@ -331,6 +340,44 @@ var BinanceWsManager = class {
|
|
|
331
340
|
this.connect();
|
|
332
341
|
}, delay);
|
|
333
342
|
}
|
|
343
|
+
scheduleIdleClose() {
|
|
344
|
+
if (this.streams.size > 0 || this.idleCloseTimer) return;
|
|
345
|
+
this.clearReconnectTimer();
|
|
346
|
+
if (!this.ws) return;
|
|
347
|
+
this.idleCloseTimer = setTimeout(() => {
|
|
348
|
+
this.idleCloseTimer = null;
|
|
349
|
+
if (this.streams.size > 0 || !this.ws) return;
|
|
350
|
+
this.intentionalClose = true;
|
|
351
|
+
this.ws.close();
|
|
352
|
+
this.ws = null;
|
|
353
|
+
this.intentionalClose = false;
|
|
354
|
+
this.clearStaleCheckTimer();
|
|
355
|
+
}, IDLE_CLOSE_DELAY_MS);
|
|
356
|
+
}
|
|
357
|
+
startStaleCheck() {
|
|
358
|
+
this.clearStaleCheckTimer();
|
|
359
|
+
this.staleCheckTimer = setInterval(() => {
|
|
360
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
|
361
|
+
if (this.streams.size === 0) return;
|
|
362
|
+
if (Date.now() - this.lastMessageAt < STALE_CONNECTION_MS) return;
|
|
363
|
+
this.ws.close();
|
|
364
|
+
}, STALE_CHECK_INTERVAL_MS);
|
|
365
|
+
}
|
|
366
|
+
clearReconnectTimer() {
|
|
367
|
+
if (!this.reconnectTimer) return;
|
|
368
|
+
clearTimeout(this.reconnectTimer);
|
|
369
|
+
this.reconnectTimer = null;
|
|
370
|
+
}
|
|
371
|
+
clearIdleCloseTimer() {
|
|
372
|
+
if (!this.idleCloseTimer) return;
|
|
373
|
+
clearTimeout(this.idleCloseTimer);
|
|
374
|
+
this.idleCloseTimer = null;
|
|
375
|
+
}
|
|
376
|
+
clearStaleCheckTimer() {
|
|
377
|
+
if (!this.staleCheckTimer) return;
|
|
378
|
+
clearInterval(this.staleCheckTimer);
|
|
379
|
+
this.staleCheckTimer = null;
|
|
380
|
+
}
|
|
334
381
|
};
|
|
335
382
|
var _instance = null;
|
|
336
383
|
function getBinanceWsManager() {
|
|
@@ -361,6 +408,28 @@ function getNextRefCount(binanceSymbol) {
|
|
|
361
408
|
function getPrevRefCount(binanceSymbol) {
|
|
362
409
|
return Math.max(0, (refCounts.get(binanceSymbol) ?? 0) - 1);
|
|
363
410
|
}
|
|
411
|
+
function addMappedSymbol(binanceSymbol, symmSymbol) {
|
|
412
|
+
const symbols = streamSymbols.get(binanceSymbol) ?? /* @__PURE__ */ new Map();
|
|
413
|
+
symbols.set(symmSymbol, (symbols.get(symmSymbol) ?? 0) + 1);
|
|
414
|
+
streamSymbols.set(binanceSymbol, symbols);
|
|
415
|
+
}
|
|
416
|
+
function removeMappedSymbol(binanceSymbol, symmSymbol) {
|
|
417
|
+
const symbols = streamSymbols.get(binanceSymbol);
|
|
418
|
+
if (!symbols) return false;
|
|
419
|
+
const currentCount = symbols.get(symmSymbol) ?? 0;
|
|
420
|
+
if (currentCount <= 0) return false;
|
|
421
|
+
if (currentCount === 1) {
|
|
422
|
+
symbols.delete(symmSymbol);
|
|
423
|
+
} else {
|
|
424
|
+
symbols.set(symmSymbol, currentCount - 1);
|
|
425
|
+
}
|
|
426
|
+
if (symbols.size === 0) {
|
|
427
|
+
streamSymbols.delete(binanceSymbol);
|
|
428
|
+
} else {
|
|
429
|
+
streamSymbols.set(binanceSymbol, symbols);
|
|
430
|
+
}
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
364
433
|
var useBinanceMarkPriceStore = zustand.create((set) => ({
|
|
365
434
|
markPrices: {},
|
|
366
435
|
fundingRates: {},
|
|
@@ -369,9 +438,7 @@ var useBinanceMarkPriceStore = zustand.create((set) => ({
|
|
|
369
438
|
const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
|
|
370
439
|
const nextRefCount = getNextRefCount(binanceSymbol);
|
|
371
440
|
refCounts.set(binanceSymbol, nextRefCount);
|
|
372
|
-
|
|
373
|
-
symbols.add(symmSymbol);
|
|
374
|
-
streamSymbols.set(binanceSymbol, symbols);
|
|
441
|
+
addMappedSymbol(binanceSymbol, symmSymbol);
|
|
375
442
|
if (allMarkPricesRefCount === 0) {
|
|
376
443
|
const wsManager = getBinanceWsManager();
|
|
377
444
|
allMarkPricesUnsubscribe = wsManager.subscribeAllMarkPrices((entries) => {
|
|
@@ -386,7 +453,7 @@ var useBinanceMarkPriceStore = zustand.create((set) => ({
|
|
|
386
453
|
nextMarkPrices ??= { ...state.markPrices };
|
|
387
454
|
nextFundingRates ??= { ...state.fundingRates };
|
|
388
455
|
nextFundingTimes ??= { ...state.nextFundingTimes };
|
|
389
|
-
mappedSymbols.forEach((mappedSymbol) => {
|
|
456
|
+
mappedSymbols.forEach((_count, mappedSymbol) => {
|
|
390
457
|
nextMarkPrices[mappedSymbol] = entry.markPrice;
|
|
391
458
|
nextFundingRates[mappedSymbol] = entry.fundingRate;
|
|
392
459
|
nextFundingTimes[mappedSymbol] = entry.nextFundingTime;
|
|
@@ -407,14 +474,9 @@ var useBinanceMarkPriceStore = zustand.create((set) => ({
|
|
|
407
474
|
},
|
|
408
475
|
unsubscribeSymbol: (symmSymbol, rawBinanceSymbol) => {
|
|
409
476
|
const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
|
|
410
|
-
const
|
|
411
|
-
if (
|
|
412
|
-
|
|
413
|
-
if (symbols.size === 0) {
|
|
414
|
-
streamSymbols.delete(binanceSymbol);
|
|
415
|
-
} else {
|
|
416
|
-
streamSymbols.set(binanceSymbol, symbols);
|
|
417
|
-
}
|
|
477
|
+
const removedSubscription = removeMappedSymbol(binanceSymbol, symmSymbol);
|
|
478
|
+
if (!removedSubscription) {
|
|
479
|
+
return;
|
|
418
480
|
}
|
|
419
481
|
const nextRefCount = getPrevRefCount(binanceSymbol);
|
|
420
482
|
if (nextRefCount === 0) {
|
|
@@ -428,6 +490,10 @@ var useBinanceMarkPriceStore = zustand.create((set) => ({
|
|
|
428
490
|
allMarkPricesUnsubscribe = null;
|
|
429
491
|
}
|
|
430
492
|
set((state) => {
|
|
493
|
+
const hasMappedSymbol = Boolean(streamSymbols.get(binanceSymbol)?.has(symmSymbol));
|
|
494
|
+
if (hasMappedSymbol) {
|
|
495
|
+
return state;
|
|
496
|
+
}
|
|
431
497
|
if (state.markPrices[symmSymbol] == null && state.fundingRates[symmSymbol] == null && state.nextFundingTimes[symmSymbol] == null) {
|
|
432
498
|
return state;
|
|
433
499
|
}
|
|
@@ -545,8 +611,33 @@ var useSymmWsStore = zustand.create((set) => ({
|
|
|
545
611
|
}));
|
|
546
612
|
|
|
547
613
|
// src/react/hooks/use-symm-ws.ts
|
|
548
|
-
|
|
549
|
-
|
|
614
|
+
var wsOwnerCounts = /* @__PURE__ */ new WeakMap();
|
|
615
|
+
var wsConnectPromises = /* @__PURE__ */ new WeakMap();
|
|
616
|
+
function addWsOwner(ws) {
|
|
617
|
+
wsOwnerCounts.set(ws, (wsOwnerCounts.get(ws) ?? 0) + 1);
|
|
618
|
+
}
|
|
619
|
+
function removeWsOwner(ws) {
|
|
620
|
+
const nextCount = Math.max(0, (wsOwnerCounts.get(ws) ?? 0) - 1);
|
|
621
|
+
if (nextCount === 0) {
|
|
622
|
+
wsOwnerCounts.delete(ws);
|
|
623
|
+
} else {
|
|
624
|
+
wsOwnerCounts.set(ws, nextCount);
|
|
625
|
+
}
|
|
626
|
+
return nextCount;
|
|
627
|
+
}
|
|
628
|
+
function connectShared(ws) {
|
|
629
|
+
if (ws.isConnected()) {
|
|
630
|
+
return Promise.resolve();
|
|
631
|
+
}
|
|
632
|
+
const existing = wsConnectPromises.get(ws);
|
|
633
|
+
if (existing) {
|
|
634
|
+
return existing;
|
|
635
|
+
}
|
|
636
|
+
const promise = ws.connect().finally(() => {
|
|
637
|
+
wsConnectPromises.delete(ws);
|
|
638
|
+
});
|
|
639
|
+
wsConnectPromises.set(ws, promise);
|
|
640
|
+
return promise;
|
|
550
641
|
}
|
|
551
642
|
function useSymmWs(params = {}) {
|
|
552
643
|
const ctx = react.useContext(SymmContext);
|
|
@@ -563,114 +654,76 @@ function useSymmWs(params = {}) {
|
|
|
563
654
|
}
|
|
564
655
|
const ws = symmCoreClient.ws;
|
|
565
656
|
const addr = accountAddress;
|
|
566
|
-
const unsubscribers = [];
|
|
567
657
|
let cancelled = false;
|
|
568
|
-
|
|
569
|
-
|
|
658
|
+
addWsOwner(ws);
|
|
659
|
+
const removeOnConnect = ws.onConnect(() => setConnected(true));
|
|
660
|
+
const removeOnDisconnect = ws.onDisconnect(() => setConnected(false));
|
|
661
|
+
const subscriptions = [];
|
|
662
|
+
const addSubscription = (channel, handler) => {
|
|
663
|
+
ws.subscribe(channel, addr, chainId, handler);
|
|
664
|
+
subscriptions.push({ channel, handler });
|
|
665
|
+
};
|
|
666
|
+
addSubscription("positions", () => {
|
|
667
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.positionsRoot });
|
|
570
668
|
});
|
|
571
|
-
|
|
572
|
-
|
|
669
|
+
addSubscription("open-orders", () => {
|
|
670
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
573
671
|
});
|
|
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
|
-
})
|
|
614
|
-
);
|
|
615
|
-
if (accountSummaryUnsub) unsubscribers.push(accountSummaryUnsub);
|
|
616
|
-
const notificationsUnsub = asUnsubscribeFn(
|
|
617
|
-
ws.subscribeToNotifications(addr, chainId, () => {
|
|
618
|
-
queryClient.invalidateQueries({
|
|
619
|
-
queryKey: symmKeys.notifications({ accountAddress, chainId })
|
|
620
|
-
});
|
|
621
|
-
queryClient.invalidateQueries({
|
|
622
|
-
queryKey: symmKeys.unreadCount({ accountAddress, chainId })
|
|
623
|
-
});
|
|
624
|
-
})
|
|
625
|
-
);
|
|
626
|
-
if (notificationsUnsub) unsubscribers.push(notificationsUnsub);
|
|
627
|
-
const tpslUnsub = asUnsubscribeFn(
|
|
628
|
-
ws.subscribeToTpsl(addr, chainId, () => {
|
|
629
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.tpslOrdersRoot });
|
|
630
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
631
|
-
})
|
|
632
|
-
);
|
|
633
|
-
if (tpslUnsub) unsubscribers.push(tpslUnsub);
|
|
634
|
-
const twapUnsub = asUnsubscribeFn(
|
|
635
|
-
ws.subscribeToTwapOrders(addr, chainId, () => {
|
|
636
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.twapOrdersRoot });
|
|
637
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
638
|
-
})
|
|
639
|
-
);
|
|
640
|
-
if (twapUnsub) unsubscribers.push(twapUnsub);
|
|
641
|
-
const triggerOrdersUnsub = asUnsubscribeFn(
|
|
642
|
-
ws.subscribeToTriggerOrders(addr, chainId, () => {
|
|
643
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.triggerOrdersRoot });
|
|
644
|
-
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
645
|
-
})
|
|
646
|
-
);
|
|
647
|
-
if (triggerOrdersUnsub) unsubscribers.push(triggerOrdersUnsub);
|
|
648
|
-
const executionsUnsub = asUnsubscribeFn(
|
|
649
|
-
ws.subscribeToExecutions(addr, chainId, () => {
|
|
650
|
-
queryClient.invalidateQueries({
|
|
651
|
-
queryKey: symmKeys.positionsRoot
|
|
652
|
-
});
|
|
653
|
-
queryClient.invalidateQueries({
|
|
654
|
-
queryKey: symmKeys.portfolioRoot
|
|
655
|
-
});
|
|
656
|
-
})
|
|
657
|
-
);
|
|
658
|
-
if (executionsUnsub) unsubscribers.push(executionsUnsub);
|
|
659
|
-
void ws.connect().then(() => {
|
|
660
|
-
if (cancelled) {
|
|
661
|
-
return;
|
|
672
|
+
addSubscription("trades", () => {
|
|
673
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.tradeHistoryRoot });
|
|
674
|
+
});
|
|
675
|
+
addSubscription("account-summary", () => {
|
|
676
|
+
queryClient.invalidateQueries({
|
|
677
|
+
queryKey: symmKeys.balances(accountAddress, chainId)
|
|
678
|
+
});
|
|
679
|
+
queryClient.invalidateQueries({
|
|
680
|
+
queryKey: symmKeys.accountSummary(accountAddress, chainId)
|
|
681
|
+
});
|
|
682
|
+
});
|
|
683
|
+
addSubscription("notifications", () => {
|
|
684
|
+
queryClient.invalidateQueries({
|
|
685
|
+
queryKey: symmKeys.notifications({ accountAddress, chainId })
|
|
686
|
+
});
|
|
687
|
+
queryClient.invalidateQueries({
|
|
688
|
+
queryKey: symmKeys.unreadCount({ accountAddress, chainId })
|
|
689
|
+
});
|
|
690
|
+
});
|
|
691
|
+
addSubscription("tpsl", () => {
|
|
692
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.tpslOrdersRoot });
|
|
693
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
694
|
+
});
|
|
695
|
+
addSubscription("twap-orders", () => {
|
|
696
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.twapOrdersRoot });
|
|
697
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
698
|
+
});
|
|
699
|
+
addSubscription("trigger-orders", () => {
|
|
700
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.triggerOrdersRoot });
|
|
701
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.openOrdersRoot });
|
|
702
|
+
});
|
|
703
|
+
addSubscription("executions", () => {
|
|
704
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.positionsRoot });
|
|
705
|
+
queryClient.invalidateQueries({ queryKey: symmKeys.portfolioRoot });
|
|
706
|
+
});
|
|
707
|
+
void connectShared(ws).then(() => {
|
|
708
|
+
if (cancelled) return;
|
|
709
|
+
if (ws.isConnected()) {
|
|
710
|
+
setConnected(true);
|
|
662
711
|
}
|
|
663
712
|
}).catch(() => {
|
|
664
|
-
if (cancelled)
|
|
665
|
-
return;
|
|
666
|
-
}
|
|
713
|
+
if (cancelled) return;
|
|
667
714
|
setConnected(false);
|
|
668
715
|
});
|
|
669
716
|
return () => {
|
|
670
717
|
cancelled = true;
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
718
|
+
removeOnConnect();
|
|
719
|
+
removeOnDisconnect();
|
|
720
|
+
subscriptions.forEach(({ channel, handler }) => {
|
|
721
|
+
ws.unsubscribe(channel, addr, chainId, handler);
|
|
722
|
+
});
|
|
723
|
+
if (removeWsOwner(ws) === 0) {
|
|
724
|
+
ws.disconnect();
|
|
725
|
+
setConnected(false);
|
|
726
|
+
}
|
|
674
727
|
};
|
|
675
728
|
}, [symmCoreClient, accountAddress, chainId, queryClient, setConnected]);
|
|
676
729
|
return { isConnected };
|
|
@@ -833,28 +886,54 @@ async function login(chainId, params) {
|
|
|
833
886
|
var TOKEN_STORAGE_PREFIX = "symm_access_token";
|
|
834
887
|
var TOKEN_STORAGE_VERSION = 1;
|
|
835
888
|
function cacheKey(address, chainId) {
|
|
836
|
-
return `${address}:${chainId}`;
|
|
889
|
+
return `${address.toLowerCase()}:${chainId}`;
|
|
837
890
|
}
|
|
838
891
|
function storageKey(address, chainId) {
|
|
839
892
|
return `${TOKEN_STORAGE_PREFIX}:${TOKEN_STORAGE_VERSION}:${cacheKey(address, chainId)}`;
|
|
840
893
|
}
|
|
894
|
+
function findStorageKey(address, chainId) {
|
|
895
|
+
const canonicalKey = storageKey(address, chainId);
|
|
896
|
+
if (typeof window === "undefined") return canonicalKey;
|
|
897
|
+
if (window.localStorage.getItem(canonicalKey) != null) {
|
|
898
|
+
return canonicalKey;
|
|
899
|
+
}
|
|
900
|
+
const normalizedKey = canonicalKey.toLowerCase();
|
|
901
|
+
for (let index = 0; index < window.localStorage.length; index += 1) {
|
|
902
|
+
const key = window.localStorage.key(index);
|
|
903
|
+
if (key?.toLowerCase() === normalizedKey) {
|
|
904
|
+
return key;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
return canonicalKey;
|
|
908
|
+
}
|
|
909
|
+
function removeStoredTokenKeys(address, chainId) {
|
|
910
|
+
if (typeof window === "undefined") return;
|
|
911
|
+
const normalizedKey = storageKey(address, chainId).toLowerCase();
|
|
912
|
+
for (let index = window.localStorage.length - 1; index >= 0; index -= 1) {
|
|
913
|
+
const key = window.localStorage.key(index);
|
|
914
|
+
if (key?.toLowerCase() === normalizedKey) {
|
|
915
|
+
window.localStorage.removeItem(key);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
841
919
|
function getCachedTokenEntry(address, chainId) {
|
|
842
920
|
if (typeof window === "undefined") return null;
|
|
921
|
+
const key = findStorageKey(address, chainId);
|
|
843
922
|
try {
|
|
844
|
-
const raw = window.localStorage.getItem(
|
|
923
|
+
const raw = window.localStorage.getItem(key);
|
|
845
924
|
if (!raw) return null;
|
|
846
925
|
const parsed = JSON.parse(raw);
|
|
847
926
|
if (!parsed || typeof parsed.token !== "string" || typeof parsed.expiresAt !== "number") {
|
|
848
|
-
window.localStorage.removeItem(
|
|
927
|
+
window.localStorage.removeItem(key);
|
|
849
928
|
return null;
|
|
850
929
|
}
|
|
851
930
|
if (Date.now() >= parsed.expiresAt) {
|
|
852
|
-
window.localStorage.removeItem(
|
|
931
|
+
window.localStorage.removeItem(key);
|
|
853
932
|
return null;
|
|
854
933
|
}
|
|
855
934
|
return parsed;
|
|
856
935
|
} catch {
|
|
857
|
-
window.localStorage.removeItem(
|
|
936
|
+
window.localStorage.removeItem(key);
|
|
858
937
|
return null;
|
|
859
938
|
}
|
|
860
939
|
}
|
|
@@ -869,9 +948,7 @@ function writeStoredToken(address, chainId, cached) {
|
|
|
869
948
|
}
|
|
870
949
|
}
|
|
871
950
|
function clearCachedToken(address, chainId) {
|
|
872
|
-
|
|
873
|
-
window.localStorage.removeItem(storageKey(address, chainId));
|
|
874
|
-
}
|
|
951
|
+
removeStoredTokenKeys(address, chainId);
|
|
875
952
|
}
|
|
876
953
|
async function fetchAccessTokenEntry(walletClient, signerAddress, accountAddress, chainId, domain) {
|
|
877
954
|
const resolvedDomain = domain ?? (typeof window !== "undefined" ? window.location.hostname : "localhost");
|
|
@@ -905,7 +982,7 @@ async function fetchAccessTokenEntry(walletClient, signerAddress, accountAddress
|
|
|
905
982
|
return cachedToken;
|
|
906
983
|
}
|
|
907
984
|
function authStoreKey(accountAddress, chainId, signerAddress) {
|
|
908
|
-
return `${accountAddress}:${chainId}:${signerAddress ?? ""}`;
|
|
985
|
+
return `${accountAddress.toLowerCase()}:${chainId}:${signerAddress?.toLowerCase() ?? ""}`;
|
|
909
986
|
}
|
|
910
987
|
function getEntryFromSnapshot(state, accountAddress, chainId, signerAddress) {
|
|
911
988
|
const signerScoped = state.entries[authStoreKey(accountAddress, chainId, signerAddress)];
|
|
@@ -2346,14 +2423,15 @@ function splitTradeHookArgs(paramsOrOptions, options) {
|
|
|
2346
2423
|
function useResolveTradeAuthToken(params = {}) {
|
|
2347
2424
|
const context = useSymmContext();
|
|
2348
2425
|
const address = params.address ?? context.address;
|
|
2426
|
+
const defaultAccountAddress = params.accountAddress ?? address;
|
|
2349
2427
|
const chainId = params.chainId ?? context.chainId;
|
|
2350
2428
|
return react.useCallback(
|
|
2351
|
-
async (providedAuthToken,
|
|
2429
|
+
async (providedAuthToken, requestAccountAddress, overrideChainId) => {
|
|
2352
2430
|
const resolvedChainId = overrideChainId ?? chainId;
|
|
2353
2431
|
if (providedAuthToken) {
|
|
2354
2432
|
return providedAuthToken;
|
|
2355
2433
|
}
|
|
2356
|
-
const resolvedAccountAddress =
|
|
2434
|
+
const resolvedAccountAddress = requestAccountAddress ?? defaultAccountAddress;
|
|
2357
2435
|
if (!resolvedAccountAddress) {
|
|
2358
2436
|
return null;
|
|
2359
2437
|
}
|
|
@@ -2367,7 +2445,7 @@ function useResolveTradeAuthToken(params = {}) {
|
|
|
2367
2445
|
}
|
|
2368
2446
|
return null;
|
|
2369
2447
|
},
|
|
2370
|
-
[address, chainId]
|
|
2448
|
+
[address, defaultAccountAddress, chainId]
|
|
2371
2449
|
);
|
|
2372
2450
|
}
|
|
2373
2451
|
|
|
@@ -25616,7 +25694,8 @@ function useSymmClosePositionMutation(paramsOrOptions, maybeOptions) {
|
|
|
25616
25694
|
const typedRequest = request;
|
|
25617
25695
|
const authToken = await resolveAuthToken(
|
|
25618
25696
|
typedRequest.authToken,
|
|
25619
|
-
typedRequest.accountAddress
|
|
25697
|
+
typedRequest.accountAddress,
|
|
25698
|
+
typedRequest.chainId
|
|
25620
25699
|
);
|
|
25621
25700
|
if (!authToken) {
|
|
25622
25701
|
throw new Error("auth token is required to close a position");
|