@pear-protocol/symmio-client 0.3.12 → 0.3.14
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/index.d.mts +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.js +207 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +205 -1
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +232 -2
- package/dist/react/index.d.ts +232 -2
- package/dist/react/index.js +430 -137
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +427 -138
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/provider.js +189 -136
- package/dist/react/provider.js.map +1 -1
- package/dist/react/provider.mjs +189 -136
- 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
|
}
|
|
@@ -510,7 +576,7 @@ var symmKeys = {
|
|
|
510
576
|
signature: (address, chainId) => ["symm", "signature", address, chainId],
|
|
511
577
|
auth: (accountAddress, chainId, signerAddress) => ["symm", "auth", accountAddress, chainId, signerAddress],
|
|
512
578
|
approval: (owner, spender, chainId, token) => ["symm", "approval", owner, spender, chainId, token],
|
|
513
|
-
balances: (address, chainId) => ["symm", "balances", address, chainId],
|
|
579
|
+
balances: (address, chainId, multiAccountAddress) => multiAccountAddress === void 0 ? ["symm", "balances", address, chainId] : ["symm", "balances", address, chainId, multiAccountAddress],
|
|
514
580
|
positions: (params) => ["symm", "positions", params],
|
|
515
581
|
openOrders: (params) => ["symm", "openOrders", params],
|
|
516
582
|
tradeHistory: (params) => ["symm", "tradeHistory", params],
|
|
@@ -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 };
|
|
@@ -25587,7 +25640,7 @@ function useSymmBalances(params) {
|
|
|
25587
25640
|
const internalEnabled = !!symmCoreClient && !!userAddress;
|
|
25588
25641
|
return useQuery({
|
|
25589
25642
|
...params.query,
|
|
25590
|
-
queryKey: symmKeys.balances(userAddress, chainId),
|
|
25643
|
+
queryKey: symmKeys.balances(userAddress, chainId, multiAccountAddress),
|
|
25591
25644
|
queryFn: () => symmCoreClient.accounts.getBalanceInfo({
|
|
25592
25645
|
userAddress,
|
|
25593
25646
|
chainId,
|
|
@@ -25596,6 +25649,242 @@ function useSymmBalances(params) {
|
|
|
25596
25649
|
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25597
25650
|
});
|
|
25598
25651
|
}
|
|
25652
|
+
|
|
25653
|
+
// src/utils/account-overview.ts
|
|
25654
|
+
var BALANCE_INFO_KEYS = [
|
|
25655
|
+
"allocatedBalance",
|
|
25656
|
+
"allocated_balance",
|
|
25657
|
+
"cva",
|
|
25658
|
+
"lf",
|
|
25659
|
+
"partyAmm",
|
|
25660
|
+
"partyAMM",
|
|
25661
|
+
"party_a_mm",
|
|
25662
|
+
"mm",
|
|
25663
|
+
"lockedPartyAMM",
|
|
25664
|
+
"upnl"
|
|
25665
|
+
];
|
|
25666
|
+
function isRecord(value) {
|
|
25667
|
+
return typeof value === "object" && value !== null;
|
|
25668
|
+
}
|
|
25669
|
+
function hasBalanceInfoShape(value) {
|
|
25670
|
+
return isRecord(value) && BALANCE_INFO_KEYS.some((key) => key in value);
|
|
25671
|
+
}
|
|
25672
|
+
function readValue(source, keys) {
|
|
25673
|
+
for (const key of keys) {
|
|
25674
|
+
if (key in source) {
|
|
25675
|
+
return source[key];
|
|
25676
|
+
}
|
|
25677
|
+
}
|
|
25678
|
+
return void 0;
|
|
25679
|
+
}
|
|
25680
|
+
function toNumber(value) {
|
|
25681
|
+
if (value === null || value === void 0 || value === "") {
|
|
25682
|
+
return 0;
|
|
25683
|
+
}
|
|
25684
|
+
if (typeof value === "bigint") {
|
|
25685
|
+
return Number(value);
|
|
25686
|
+
}
|
|
25687
|
+
const parsed = Number(value);
|
|
25688
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
25689
|
+
}
|
|
25690
|
+
function toDisplayString(value) {
|
|
25691
|
+
if (Object.is(value, -0) || Math.abs(value) < Number.EPSILON) {
|
|
25692
|
+
return "0";
|
|
25693
|
+
}
|
|
25694
|
+
return String(value);
|
|
25695
|
+
}
|
|
25696
|
+
function readNumber(source, keys) {
|
|
25697
|
+
return toNumber(readValue(source, keys));
|
|
25698
|
+
}
|
|
25699
|
+
function readTimestamp(source) {
|
|
25700
|
+
const timestamp = readValue(source, ["timestamp"]);
|
|
25701
|
+
if (timestamp === void 0 || timestamp === null) {
|
|
25702
|
+
return void 0;
|
|
25703
|
+
}
|
|
25704
|
+
const parsed = Number(timestamp);
|
|
25705
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
25706
|
+
}
|
|
25707
|
+
function getBalanceInfoContainer(response) {
|
|
25708
|
+
if (!isRecord(response)) {
|
|
25709
|
+
return void 0;
|
|
25710
|
+
}
|
|
25711
|
+
if (hasBalanceInfoShape(response)) {
|
|
25712
|
+
return response;
|
|
25713
|
+
}
|
|
25714
|
+
const data = response.data;
|
|
25715
|
+
if (isRecord(data)) {
|
|
25716
|
+
return data;
|
|
25717
|
+
}
|
|
25718
|
+
return response;
|
|
25719
|
+
}
|
|
25720
|
+
function getSymmAccountBalanceInfo(response, accountAddress) {
|
|
25721
|
+
const container = getBalanceInfoContainer(response);
|
|
25722
|
+
if (!container) {
|
|
25723
|
+
return void 0;
|
|
25724
|
+
}
|
|
25725
|
+
if (hasBalanceInfoShape(container)) {
|
|
25726
|
+
return container;
|
|
25727
|
+
}
|
|
25728
|
+
if (accountAddress) {
|
|
25729
|
+
const normalizedAddress = accountAddress.toLowerCase();
|
|
25730
|
+
const direct = container[accountAddress] ?? container[normalizedAddress];
|
|
25731
|
+
if (isRecord(direct) && hasBalanceInfoShape(direct)) {
|
|
25732
|
+
return direct;
|
|
25733
|
+
}
|
|
25734
|
+
const matchingEntry = Object.entries(container).find(
|
|
25735
|
+
([key]) => key.toLowerCase() === normalizedAddress
|
|
25736
|
+
);
|
|
25737
|
+
if (isRecord(matchingEntry?.[1]) && hasBalanceInfoShape(matchingEntry[1])) {
|
|
25738
|
+
return matchingEntry[1];
|
|
25739
|
+
}
|
|
25740
|
+
}
|
|
25741
|
+
const values = Object.values(container);
|
|
25742
|
+
if (values.length === 1 && isRecord(values[0]) && hasBalanceInfoShape(values[0])) {
|
|
25743
|
+
return values[0];
|
|
25744
|
+
}
|
|
25745
|
+
return void 0;
|
|
25746
|
+
}
|
|
25747
|
+
function computeSymmAccountOverview({
|
|
25748
|
+
balanceInfo,
|
|
25749
|
+
upnl: upnlOverride,
|
|
25750
|
+
netDeposited
|
|
25751
|
+
}) {
|
|
25752
|
+
const allocatedBalance = readNumber(balanceInfo, [
|
|
25753
|
+
"allocatedBalance",
|
|
25754
|
+
"allocated_balance"
|
|
25755
|
+
]);
|
|
25756
|
+
const cva = readNumber(balanceInfo, ["cva", "lockedCVA", "locked_cva"]);
|
|
25757
|
+
const lf = readNumber(balanceInfo, ["lf", "lockedLF", "locked_lf"]);
|
|
25758
|
+
const partyAmm = readNumber(balanceInfo, [
|
|
25759
|
+
"partyAmm",
|
|
25760
|
+
"partyAMM",
|
|
25761
|
+
"party_a_mm",
|
|
25762
|
+
"mm",
|
|
25763
|
+
"lockedPartyAMM",
|
|
25764
|
+
"locked_party_a_mm"
|
|
25765
|
+
]);
|
|
25766
|
+
const pendingCva = readNumber(balanceInfo, [
|
|
25767
|
+
"pendingCva",
|
|
25768
|
+
"pending_cva",
|
|
25769
|
+
"pendingLockedCVA",
|
|
25770
|
+
"pending_locked_cva"
|
|
25771
|
+
]);
|
|
25772
|
+
const pendingLf = readNumber(balanceInfo, [
|
|
25773
|
+
"pendingLf",
|
|
25774
|
+
"pending_lf",
|
|
25775
|
+
"pendingLockedLF",
|
|
25776
|
+
"pending_locked_lf"
|
|
25777
|
+
]);
|
|
25778
|
+
const pendingPartyAmm = readNumber(balanceInfo, [
|
|
25779
|
+
"pendingPartyAmm",
|
|
25780
|
+
"pendingPartyAMM",
|
|
25781
|
+
"pending_party_a_mm",
|
|
25782
|
+
"pendingMm",
|
|
25783
|
+
"pending_mm",
|
|
25784
|
+
"pendingLockedPartyAMM",
|
|
25785
|
+
"pending_locked_party_a_mm"
|
|
25786
|
+
]);
|
|
25787
|
+
const upnl = upnlOverride === void 0 ? readNumber(balanceInfo, ["upnl"]) : toNumber(upnlOverride);
|
|
25788
|
+
const computedTotalLocked = cva + lf + partyAmm;
|
|
25789
|
+
const totalLocked = readValue(
|
|
25790
|
+
balanceInfo,
|
|
25791
|
+
["totalLocked", "total_locked"]
|
|
25792
|
+
) === void 0 ? computedTotalLocked : readNumber(balanceInfo, ["totalLocked", "total_locked"]);
|
|
25793
|
+
const totalPendingLocked = readValue(balanceInfo, [
|
|
25794
|
+
"totalPendingLocked",
|
|
25795
|
+
"total_pending_locked"
|
|
25796
|
+
]) === void 0 ? pendingCva + pendingLf + pendingPartyAmm : readNumber(balanceInfo, ["totalPendingLocked", "total_pending_locked"]);
|
|
25797
|
+
const maintenanceMargin = cva + lf;
|
|
25798
|
+
const equity = allocatedBalance + upnl;
|
|
25799
|
+
const availableForOrder = upnl >= 0 ? allocatedBalance + upnl - totalLocked - totalPendingLocked : allocatedBalance - cva - lf - totalPendingLocked - Math.max(Math.abs(upnl), partyAmm);
|
|
25800
|
+
const availableBalance = readNumber(balanceInfo, [
|
|
25801
|
+
"availableBalance",
|
|
25802
|
+
"available_balance"
|
|
25803
|
+
]);
|
|
25804
|
+
const notional = readNumber(balanceInfo, ["notional"]);
|
|
25805
|
+
return {
|
|
25806
|
+
allocatedBalance: toDisplayString(allocatedBalance),
|
|
25807
|
+
upnl: toDisplayString(upnl),
|
|
25808
|
+
equity: toDisplayString(equity),
|
|
25809
|
+
totalAccountValue: toDisplayString(equity),
|
|
25810
|
+
maintenanceMargin: toDisplayString(maintenanceMargin),
|
|
25811
|
+
totalLocked: toDisplayString(totalLocked),
|
|
25812
|
+
marginUsed: toDisplayString(computedTotalLocked),
|
|
25813
|
+
totalPendingLocked: toDisplayString(totalPendingLocked),
|
|
25814
|
+
availableForOrder: toDisplayString(availableForOrder),
|
|
25815
|
+
availableMargin: toDisplayString(availableForOrder),
|
|
25816
|
+
availableBalance: toDisplayString(availableBalance),
|
|
25817
|
+
netDeposited: toDisplayString(toNumber(netDeposited)),
|
|
25818
|
+
notional: toDisplayString(notional),
|
|
25819
|
+
timestamp: readTimestamp(balanceInfo)
|
|
25820
|
+
};
|
|
25821
|
+
}
|
|
25822
|
+
function computeSymmNetDeposited(totals, decimals = 6) {
|
|
25823
|
+
if (!totals) {
|
|
25824
|
+
return "0";
|
|
25825
|
+
}
|
|
25826
|
+
const deposit2 = parseRawCollateralUnits(totals.deposit);
|
|
25827
|
+
const withdraw2 = parseRawCollateralUnits(totals.withdraw);
|
|
25828
|
+
const value = deposit2 - withdraw2;
|
|
25829
|
+
const negative = value < 0n;
|
|
25830
|
+
const absolute = negative ? -value : value;
|
|
25831
|
+
const scale = 10n ** BigInt(decimals);
|
|
25832
|
+
const whole = absolute / scale;
|
|
25833
|
+
const fraction = absolute % scale;
|
|
25834
|
+
const fractionText = fraction.toString().padStart(decimals, "0").replace(/0+$/, "");
|
|
25835
|
+
const amount = fractionText ? `${whole}.${fractionText}` : whole.toString();
|
|
25836
|
+
return negative ? `-${amount}` : amount;
|
|
25837
|
+
}
|
|
25838
|
+
function parseRawCollateralUnits(value) {
|
|
25839
|
+
if (value === null || value === void 0 || value === "") {
|
|
25840
|
+
return 0n;
|
|
25841
|
+
}
|
|
25842
|
+
if (typeof value === "bigint") {
|
|
25843
|
+
return value;
|
|
25844
|
+
}
|
|
25845
|
+
if (typeof value === "number") {
|
|
25846
|
+
if (!Number.isSafeInteger(value)) {
|
|
25847
|
+
throw new Error("Raw collateral unit numbers must be safe integers");
|
|
25848
|
+
}
|
|
25849
|
+
return BigInt(value);
|
|
25850
|
+
}
|
|
25851
|
+
if (!/^-?\d+$/.test(value)) {
|
|
25852
|
+
throw new Error("Raw collateral unit strings must be base-10 integers");
|
|
25853
|
+
}
|
|
25854
|
+
return BigInt(value);
|
|
25855
|
+
}
|
|
25856
|
+
|
|
25857
|
+
// src/react/hooks/use-symm-account-overview.ts
|
|
25858
|
+
function useSymmAccountOverview(params) {
|
|
25859
|
+
const {
|
|
25860
|
+
userAddress,
|
|
25861
|
+
accountAddress,
|
|
25862
|
+
multiAccountAddress,
|
|
25863
|
+
upnl,
|
|
25864
|
+
netDeposited
|
|
25865
|
+
} = params;
|
|
25866
|
+
const query = useSymmBalances({
|
|
25867
|
+
userAddress,
|
|
25868
|
+
multiAccountAddress,
|
|
25869
|
+
chainId: params.chainId,
|
|
25870
|
+
query: params.query
|
|
25871
|
+
});
|
|
25872
|
+
const data = useMemo(() => {
|
|
25873
|
+
if (query.data === void 0) {
|
|
25874
|
+
return void 0;
|
|
25875
|
+
}
|
|
25876
|
+
const balanceInfo = getSymmAccountBalanceInfo(
|
|
25877
|
+
query.data,
|
|
25878
|
+
accountAddress ?? userAddress
|
|
25879
|
+
);
|
|
25880
|
+
return {
|
|
25881
|
+
response: query.data,
|
|
25882
|
+
balanceInfo,
|
|
25883
|
+
overview: balanceInfo ? computeSymmAccountOverview({ balanceInfo, upnl, netDeposited }) : void 0
|
|
25884
|
+
};
|
|
25885
|
+
}, [accountAddress, netDeposited, query.data, upnl, userAddress]);
|
|
25886
|
+
return { ...query, data };
|
|
25887
|
+
}
|
|
25599
25888
|
function useSymmOpenBasketMutation(options) {
|
|
25600
25889
|
const { symmCoreClient } = useSymmContext();
|
|
25601
25890
|
const queryClient = useQueryClient();
|
|
@@ -27168,6 +27457,6 @@ function getSymmErrorMessage(error) {
|
|
|
27168
27457
|
return "An unexpected error occurred.";
|
|
27169
27458
|
}
|
|
27170
27459
|
|
|
27171
|
-
export { SymmProvider, getSymmErrorMessage, symmKeys, useBinanceMarkPriceStore, useSymmAccountData, useSymmAccountSummary, useSymmAccountsApi, useSymmAccountsLength, useSymmAccountsQuery, useSymmAccountsWithPositions, useSymmAllocateCollateralMutation, useSymmApprovalQuery, useSymmApproveMutation, useSymmAuth, useSymmAvailableMargin, useSymmBalances, useSymmCancelClose, useSymmCancelOpenMutation, useSymmCancelTpslMutation, useSymmCancelTwapOrderMutation, useSymmChartCandles, useSymmChartSelection, useSymmClearTriggerConfigMutation, useSymmCloseAllPositionsMutation, useSymmCloseOrder, useSymmClosePositionMutation, useSymmContext, useSymmCoreClient, useSymmCreateAccountMutation, useSymmDeallocateCollateralMutation, useSymmDelegateAccessMutation, useSymmDelegation, useSymmDepositAndAllocateMutation, useSymmDepositMutation, useSymmEditAccountNameMutation, useSymmFunding, useSymmFundingHistory, useSymmFundingPayments, useSymmHedgerMarketById, useSymmHedgerMarketBySymbol, useSymmHedgerMarkets, useSymmInstantTradeEnsureReadyMutation, useSymmInstantTradeExecuteMutation, useSymmInternalTransferCollateralMutation, useSymmLockedParams, useSymmMarkReadNotificationMutation, useSymmMarkets, useSymmNotificationsQuery, useSymmOpenBasketMutation, useSymmOpenOrders, useSymmPendingIds, useSymmPendingInstantOpens, useSymmPerformanceOverlays, useSymmPortfolio, useSymmPositions, useSymmProposeRevokeDelegationMutation, useSymmRevokeDelegationMutation, useSymmSetTpslMutation, useSymmSetTriggerConfigMutation, useSymmSignTermsMutation, useSymmSignatureQuery, useSymmTokenMarkPrice, useSymmTokenSelectionMarkets, useSymmTokenSelectionMetadata, useSymmTpslOrders, useSymmTradeHistory, useSymmTriggerConfigQuery, useSymmTriggerOrders, useSymmTwapOrder, useSymmTwapOrdersQuery, useSymmUnreadCountQuery, useSymmUpdatePositionMutation, useSymmWithdraw, useSymmWsStore };
|
|
27460
|
+
export { SymmProvider, computeSymmAccountOverview, computeSymmNetDeposited, getSymmAccountBalanceInfo, getSymmErrorMessage, symmKeys, useBinanceMarkPriceStore, useSymmAccountData, useSymmAccountOverview, useSymmAccountSummary, useSymmAccountsApi, useSymmAccountsLength, useSymmAccountsQuery, useSymmAccountsWithPositions, useSymmAllocateCollateralMutation, useSymmApprovalQuery, useSymmApproveMutation, useSymmAuth, useSymmAvailableMargin, useSymmBalances, useSymmCancelClose, useSymmCancelOpenMutation, useSymmCancelTpslMutation, useSymmCancelTwapOrderMutation, useSymmChartCandles, useSymmChartSelection, useSymmClearTriggerConfigMutation, useSymmCloseAllPositionsMutation, useSymmCloseOrder, useSymmClosePositionMutation, useSymmContext, useSymmCoreClient, useSymmCreateAccountMutation, useSymmDeallocateCollateralMutation, useSymmDelegateAccessMutation, useSymmDelegation, useSymmDepositAndAllocateMutation, useSymmDepositMutation, useSymmEditAccountNameMutation, useSymmFunding, useSymmFundingHistory, useSymmFundingPayments, useSymmHedgerMarketById, useSymmHedgerMarketBySymbol, useSymmHedgerMarkets, useSymmInstantTradeEnsureReadyMutation, useSymmInstantTradeExecuteMutation, useSymmInternalTransferCollateralMutation, useSymmLockedParams, useSymmMarkReadNotificationMutation, useSymmMarkets, useSymmNotificationsQuery, useSymmOpenBasketMutation, useSymmOpenOrders, useSymmPendingIds, useSymmPendingInstantOpens, useSymmPerformanceOverlays, useSymmPortfolio, useSymmPositions, useSymmProposeRevokeDelegationMutation, useSymmRevokeDelegationMutation, useSymmSetTpslMutation, useSymmSetTriggerConfigMutation, useSymmSignTermsMutation, useSymmSignatureQuery, useSymmTokenMarkPrice, useSymmTokenSelectionMarkets, useSymmTokenSelectionMetadata, useSymmTpslOrders, useSymmTradeHistory, useSymmTriggerConfigQuery, useSymmTriggerOrders, useSymmTwapOrder, useSymmTwapOrdersQuery, useSymmUnreadCountQuery, useSymmUpdatePositionMutation, useSymmWithdraw, useSymmWsStore };
|
|
27172
27461
|
//# sourceMappingURL=index.mjs.map
|
|
27173
27462
|
//# sourceMappingURL=index.mjs.map
|