@pear-protocol/symmio-client 0.2.25 → 0.2.26
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 +24 -2
- package/dist/react/index.d.ts +24 -2
- package/dist/react/index.js +919 -812
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +919 -813
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react/index.mjs
CHANGED
|
@@ -25001,634 +25001,128 @@ function useSymmHedgerMarkets(params) {
|
|
|
25001
25001
|
enabled: internalEnabled && consumerEnabled
|
|
25002
25002
|
});
|
|
25003
25003
|
}
|
|
25004
|
-
|
|
25005
|
-
|
|
25006
|
-
|
|
25007
|
-
|
|
25008
|
-
|
|
25009
|
-
|
|
25010
|
-
queryKey: symmKeys.fundingRates(chainId),
|
|
25011
|
-
queryFn: () => symmCoreClient.funding.getRates({ chainId }),
|
|
25012
|
-
enabled: internalEnabled && (params?.query?.enabled ?? true)
|
|
25013
|
-
});
|
|
25014
|
-
}
|
|
25015
|
-
function useSymmFundingHistory(params) {
|
|
25016
|
-
const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
|
|
25017
|
-
const chainId = params.chainId ?? ctxChainId;
|
|
25018
|
-
const {
|
|
25019
|
-
period,
|
|
25020
|
-
longSymbols,
|
|
25021
|
-
shortSymbols,
|
|
25022
|
-
interval,
|
|
25023
|
-
weightMode,
|
|
25024
|
-
includeContributions
|
|
25025
|
-
} = params;
|
|
25026
|
-
const internalEnabled = !!symmCoreClient;
|
|
25027
|
-
const request = {
|
|
25028
|
-
chainId,
|
|
25029
|
-
period,
|
|
25030
|
-
longSymbols,
|
|
25031
|
-
shortSymbols,
|
|
25004
|
+
|
|
25005
|
+
// src/utils/binance-api.ts
|
|
25006
|
+
var BINANCE_FAPI_BASE = "https://fapi.binance.com";
|
|
25007
|
+
async function fetchMarkPriceKlines(symbol, interval, startTime, endTime, limit = 1500) {
|
|
25008
|
+
const params = new URLSearchParams({
|
|
25009
|
+
symbol,
|
|
25032
25010
|
interval,
|
|
25033
|
-
|
|
25034
|
-
|
|
25035
|
-
|
|
25036
|
-
return useQuery({
|
|
25037
|
-
...params.query,
|
|
25038
|
-
queryKey: symmKeys.fundingHistory(request),
|
|
25039
|
-
queryFn: () => symmCoreClient.funding.getHistory(request),
|
|
25040
|
-
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25011
|
+
startTime: String(startTime),
|
|
25012
|
+
endTime: String(endTime),
|
|
25013
|
+
limit: String(Math.min(limit, 1500))
|
|
25041
25014
|
});
|
|
25015
|
+
const response = await fetch(`${BINANCE_FAPI_BASE}/fapi/v1/markPriceKlines?${params}`);
|
|
25016
|
+
if (!response.ok) {
|
|
25017
|
+
throw new Error(`Binance markPriceKlines failed: ${response.status}`);
|
|
25018
|
+
}
|
|
25019
|
+
const data = await response.json();
|
|
25020
|
+
return data.map((k) => ({
|
|
25021
|
+
openTime: Number(k[0]),
|
|
25022
|
+
open: parseFloat(k[1]),
|
|
25023
|
+
high: parseFloat(k[2]),
|
|
25024
|
+
low: parseFloat(k[3]),
|
|
25025
|
+
close: parseFloat(k[4]),
|
|
25026
|
+
volume: parseFloat(k[5]),
|
|
25027
|
+
closeTime: Number(k[6])
|
|
25028
|
+
}));
|
|
25042
25029
|
}
|
|
25043
|
-
function
|
|
25044
|
-
const
|
|
25045
|
-
const
|
|
25046
|
-
|
|
25047
|
-
const
|
|
25048
|
-
|
|
25049
|
-
|
|
25050
|
-
|
|
25051
|
-
|
|
25052
|
-
limit,
|
|
25053
|
-
offset
|
|
25030
|
+
async function fetch24hrTicker(symbol) {
|
|
25031
|
+
const params = new URLSearchParams({ symbol });
|
|
25032
|
+
const response = await fetch(`${BINANCE_FAPI_BASE}/fapi/v1/ticker/24hr?${params}`);
|
|
25033
|
+
if (!response.ok) return null;
|
|
25034
|
+
const data = await response.json();
|
|
25035
|
+
return {
|
|
25036
|
+
lastPrice: parseFloat(data.lastPrice),
|
|
25037
|
+
prevClosePrice: parseFloat(data.prevClosePrice),
|
|
25038
|
+
priceChangePercent: parseFloat(data.priceChangePercent)
|
|
25054
25039
|
};
|
|
25055
|
-
return useQuery({
|
|
25056
|
-
...params.query,
|
|
25057
|
-
queryKey: symmKeys.fundingPayments({
|
|
25058
|
-
address,
|
|
25059
|
-
positionId,
|
|
25060
|
-
chainId,
|
|
25061
|
-
limit,
|
|
25062
|
-
offset
|
|
25063
|
-
}),
|
|
25064
|
-
queryFn: () => symmCoreClient.funding.getPayments(request),
|
|
25065
|
-
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25066
|
-
});
|
|
25067
|
-
}
|
|
25068
|
-
function useSymmPortfolio(params) {
|
|
25069
|
-
const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
|
|
25070
|
-
const { accountAddress, address } = params;
|
|
25071
|
-
const resolvedAddress = accountAddress ? void 0 : address;
|
|
25072
|
-
const chainId = params.chainId ?? ctxChainId;
|
|
25073
|
-
const internalEnabled = !!symmCoreClient && !!(accountAddress || resolvedAddress);
|
|
25074
|
-
return useQuery({
|
|
25075
|
-
...params.query,
|
|
25076
|
-
queryKey: symmKeys.portfolio({
|
|
25077
|
-
accountAddress,
|
|
25078
|
-
address: resolvedAddress,
|
|
25079
|
-
chainId
|
|
25080
|
-
}),
|
|
25081
|
-
queryFn: () => {
|
|
25082
|
-
const request = {
|
|
25083
|
-
accountAddress,
|
|
25084
|
-
address: resolvedAddress,
|
|
25085
|
-
chainId
|
|
25086
|
-
};
|
|
25087
|
-
return symmCoreClient.portfolio.getMetrics(request);
|
|
25088
|
-
},
|
|
25089
|
-
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25090
|
-
});
|
|
25091
25040
|
}
|
|
25092
|
-
|
|
25093
|
-
|
|
25094
|
-
|
|
25041
|
+
|
|
25042
|
+
// src/utils/binance-symbol-map.ts
|
|
25043
|
+
var SYMBOL_OVERRIDES = {
|
|
25044
|
+
// Add overrides here as needed for SYMM markets that don't map 1:1 to Binance
|
|
25045
|
+
// e.g., 'SOME_SYMM_SYMBOL': 'BINANCE_SYMBOL',
|
|
25046
|
+
};
|
|
25047
|
+
var UNSUPPORTED_SYMBOLS = /* @__PURE__ */ new Set([
|
|
25048
|
+
// Add symbols here that have no Binance equivalent
|
|
25049
|
+
]);
|
|
25050
|
+
function resolveBinanceSymbol(symmSymbol) {
|
|
25051
|
+
if (!symmSymbol || !symmSymbol.trim()) {
|
|
25052
|
+
return {
|
|
25053
|
+
symmSymbol,
|
|
25054
|
+
normalizedSymbol: "",
|
|
25055
|
+
binanceSymbol: null,
|
|
25056
|
+
supported: false,
|
|
25057
|
+
reason: "missing_symbol"
|
|
25058
|
+
};
|
|
25059
|
+
}
|
|
25060
|
+
const normalized = symmSymbol.toUpperCase().trim();
|
|
25061
|
+
if (!/^[A-Z0-9]+$/.test(normalized)) {
|
|
25062
|
+
return {
|
|
25063
|
+
symmSymbol,
|
|
25064
|
+
normalizedSymbol: normalized,
|
|
25065
|
+
binanceSymbol: null,
|
|
25066
|
+
supported: false,
|
|
25067
|
+
reason: "invalid_symbol"
|
|
25068
|
+
};
|
|
25069
|
+
}
|
|
25070
|
+
if (UNSUPPORTED_SYMBOLS.has(normalized)) {
|
|
25071
|
+
return {
|
|
25072
|
+
symmSymbol,
|
|
25073
|
+
normalizedSymbol: normalized,
|
|
25074
|
+
binanceSymbol: null,
|
|
25075
|
+
supported: false,
|
|
25076
|
+
reason: "unsupported_symbol"
|
|
25077
|
+
};
|
|
25078
|
+
}
|
|
25079
|
+
const binanceSymbol = SYMBOL_OVERRIDES[normalized] ?? (normalized.endsWith("USDT") ? normalized : `${normalized}USDT`);
|
|
25095
25080
|
return {
|
|
25096
|
-
|
|
25097
|
-
|
|
25098
|
-
|
|
25099
|
-
|
|
25081
|
+
symmSymbol,
|
|
25082
|
+
normalizedSymbol: normalized,
|
|
25083
|
+
binanceSymbol,
|
|
25084
|
+
supported: true,
|
|
25085
|
+
reason: null
|
|
25100
25086
|
};
|
|
25101
25087
|
}
|
|
25102
|
-
function
|
|
25103
|
-
|
|
25104
|
-
const internalEnabled = !!symmCoreClient && !!userAddress;
|
|
25105
|
-
return useQuery({
|
|
25106
|
-
...query,
|
|
25107
|
-
queryKey: symmKeys.notifications(userAddress, chainId),
|
|
25108
|
-
queryFn: () => symmCoreClient.notifications.list({
|
|
25109
|
-
userAddress,
|
|
25110
|
-
chainId
|
|
25111
|
-
}),
|
|
25112
|
-
enabled: internalEnabled && (query?.enabled ?? true)
|
|
25113
|
-
});
|
|
25088
|
+
function getUnsupportedBinanceSymbols(symbols) {
|
|
25089
|
+
return symbols.filter((symbol) => !resolveBinanceSymbol(symbol).supported);
|
|
25114
25090
|
}
|
|
25115
|
-
function
|
|
25116
|
-
|
|
25117
|
-
const internalEnabled = !!symmCoreClient && !!userAddress;
|
|
25118
|
-
return useQuery({
|
|
25119
|
-
...query,
|
|
25120
|
-
queryKey: symmKeys.unreadCount(userAddress, chainId),
|
|
25121
|
-
queryFn: () => symmCoreClient.notifications.getUnreadCount({
|
|
25122
|
-
userAddress,
|
|
25123
|
-
chainId
|
|
25124
|
-
}),
|
|
25125
|
-
enabled: internalEnabled && (query?.enabled ?? true)
|
|
25126
|
-
});
|
|
25091
|
+
function toBinanceSymbol(symmSymbol) {
|
|
25092
|
+
return resolveBinanceSymbol(symmSymbol).binanceSymbol;
|
|
25127
25093
|
}
|
|
25128
|
-
|
|
25129
|
-
|
|
25130
|
-
|
|
25131
|
-
|
|
25132
|
-
|
|
25133
|
-
|
|
25134
|
-
|
|
25135
|
-
|
|
25136
|
-
|
|
25137
|
-
|
|
25138
|
-
|
|
25139
|
-
|
|
25140
|
-
|
|
25141
|
-
|
|
25142
|
-
|
|
25143
|
-
|
|
25144
|
-
|
|
25145
|
-
|
|
25146
|
-
|
|
25147
|
-
|
|
25148
|
-
|
|
25149
|
-
|
|
25150
|
-
|
|
25151
|
-
|
|
25152
|
-
|
|
25153
|
-
|
|
25154
|
-
|
|
25155
|
-
|
|
25156
|
-
|
|
25157
|
-
|
|
25158
|
-
|
|
25159
|
-
|
|
25160
|
-
return useQuery({
|
|
25161
|
-
...params.query,
|
|
25162
|
-
queryKey: symmKeys.pendingIds(accountAddress, chainId),
|
|
25163
|
-
queryFn: () => symmCoreClient.positions.getPendingIds({
|
|
25164
|
-
address: accountAddress,
|
|
25165
|
-
chainId
|
|
25166
|
-
}),
|
|
25167
|
-
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25168
|
-
});
|
|
25169
|
-
}
|
|
25170
|
-
function useSymmPendingInstantOpens(params) {
|
|
25171
|
-
const {
|
|
25172
|
-
symmCoreClient,
|
|
25173
|
-
chainId: ctxChainId
|
|
25174
|
-
} = useSymmContext();
|
|
25175
|
-
const { accountAddress, authToken: providedAuthToken } = params;
|
|
25176
|
-
const chainId = params.chainId ?? ctxChainId;
|
|
25177
|
-
const internalEnabled = !!symmCoreClient && !!accountAddress;
|
|
25178
|
-
return useQuery({
|
|
25179
|
-
...params.query,
|
|
25180
|
-
queryKey: symmKeys.pendingInstantOpens(accountAddress, chainId),
|
|
25181
|
-
queryFn: async () => {
|
|
25182
|
-
const authToken = providedAuthToken ?? useSymmAuthStore.getState().getToken(accountAddress, chainId);
|
|
25183
|
-
if (!authToken) {
|
|
25184
|
-
throw new Error("failed to acquire auth token for pending instant opens");
|
|
25185
|
-
}
|
|
25186
|
-
return symmCoreClient.positions.getPendingInstantOpens({
|
|
25187
|
-
accountAddress,
|
|
25188
|
-
chainId,
|
|
25189
|
-
authToken
|
|
25190
|
-
});
|
|
25191
|
-
},
|
|
25192
|
-
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25193
|
-
});
|
|
25194
|
-
}
|
|
25195
|
-
function useSymmTwapOrder(params) {
|
|
25196
|
-
const { symmCoreClient } = useSymmContext();
|
|
25197
|
-
const { orderId } = params;
|
|
25198
|
-
const internalEnabled = !!symmCoreClient && !!orderId;
|
|
25199
|
-
return useQuery({
|
|
25200
|
-
...params.query,
|
|
25201
|
-
queryKey: symmKeys.twapOrder(orderId),
|
|
25202
|
-
queryFn: () => symmCoreClient.orders.getTwapOrder(orderId),
|
|
25203
|
-
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25204
|
-
});
|
|
25205
|
-
}
|
|
25206
|
-
var useSymmWsStore = create((set) => ({
|
|
25207
|
-
isConnected: false,
|
|
25208
|
-
setConnected: (isConnected) => set({ isConnected })
|
|
25209
|
-
}));
|
|
25210
|
-
|
|
25211
|
-
// src/react/hooks/use-symm-ws.ts
|
|
25212
|
-
function asUnsubscribeFn(value) {
|
|
25213
|
-
return typeof value === "function" ? value : null;
|
|
25214
|
-
}
|
|
25215
|
-
function useSymmWs(params = {}) {
|
|
25216
|
-
const {
|
|
25217
|
-
symmCoreClient: ctxClient,
|
|
25218
|
-
address: ctxAddress,
|
|
25219
|
-
chainId: ctxChainId
|
|
25220
|
-
} = useSymmContext();
|
|
25221
|
-
const queryClient = useQueryClient();
|
|
25222
|
-
const isConnected = useSymmWsStore((state) => state.isConnected);
|
|
25223
|
-
const setConnected = useSymmWsStore((state) => state.setConnected);
|
|
25224
|
-
const symmCoreClient = params.symmCoreClient ?? ctxClient;
|
|
25225
|
-
const accountAddress = params.accountAddress ?? ctxAddress;
|
|
25226
|
-
const chainId = params.chainId ?? ctxChainId;
|
|
25227
|
-
useEffect(() => {
|
|
25228
|
-
if (!symmCoreClient || !accountAddress) {
|
|
25229
|
-
setConnected(false);
|
|
25230
|
-
return;
|
|
25231
|
-
}
|
|
25232
|
-
const ws = symmCoreClient.ws;
|
|
25233
|
-
const addr = accountAddress;
|
|
25234
|
-
const unsubscribers = [];
|
|
25235
|
-
const removeOnConnect = ws.onConnect(() => setConnected(true));
|
|
25236
|
-
const removeOnDisconnect = ws.onDisconnect(() => setConnected(false));
|
|
25237
|
-
unsubscribers.push(removeOnConnect, removeOnDisconnect);
|
|
25238
|
-
const positionsUnsub = asUnsubscribeFn(
|
|
25239
|
-
ws.subscribeToPositions(addr, chainId, () => {
|
|
25240
|
-
queryClient.invalidateQueries({
|
|
25241
|
-
queryKey: ["symm", "positions"]
|
|
25242
|
-
});
|
|
25243
|
-
})
|
|
25244
|
-
);
|
|
25245
|
-
if (positionsUnsub) unsubscribers.push(positionsUnsub);
|
|
25246
|
-
const openOrdersUnsub = asUnsubscribeFn(
|
|
25247
|
-
ws.subscribeToOpenOrders(addr, chainId, () => {
|
|
25248
|
-
queryClient.invalidateQueries({
|
|
25249
|
-
queryKey: ["symm", "openOrders"]
|
|
25250
|
-
});
|
|
25251
|
-
})
|
|
25252
|
-
);
|
|
25253
|
-
if (openOrdersUnsub) unsubscribers.push(openOrdersUnsub);
|
|
25254
|
-
const tradesUnsub = asUnsubscribeFn(
|
|
25255
|
-
ws.subscribeToTrades(addr, chainId, () => {
|
|
25256
|
-
queryClient.invalidateQueries({
|
|
25257
|
-
queryKey: ["symm", "tradeHistory"]
|
|
25258
|
-
});
|
|
25259
|
-
})
|
|
25260
|
-
);
|
|
25261
|
-
if (tradesUnsub) unsubscribers.push(tradesUnsub);
|
|
25262
|
-
const accountSummaryUnsub = asUnsubscribeFn(
|
|
25263
|
-
ws.subscribeToAccountSummary(addr, chainId, () => {
|
|
25264
|
-
queryClient.invalidateQueries({
|
|
25265
|
-
queryKey: symmKeys.balances(accountAddress, chainId)
|
|
25266
|
-
});
|
|
25267
|
-
queryClient.invalidateQueries({
|
|
25268
|
-
queryKey: symmKeys.accountSummary(accountAddress, chainId)
|
|
25269
|
-
});
|
|
25270
|
-
})
|
|
25271
|
-
);
|
|
25272
|
-
if (accountSummaryUnsub) unsubscribers.push(accountSummaryUnsub);
|
|
25273
|
-
const notificationsUnsub = asUnsubscribeFn(
|
|
25274
|
-
ws.subscribeToNotifications(addr, chainId, () => {
|
|
25275
|
-
queryClient.invalidateQueries({
|
|
25276
|
-
queryKey: symmKeys.notifications(accountAddress, chainId)
|
|
25277
|
-
});
|
|
25278
|
-
queryClient.invalidateQueries({
|
|
25279
|
-
queryKey: symmKeys.unreadCount(accountAddress, chainId)
|
|
25280
|
-
});
|
|
25281
|
-
})
|
|
25282
|
-
);
|
|
25283
|
-
if (notificationsUnsub) unsubscribers.push(notificationsUnsub);
|
|
25284
|
-
const tpslUnsub = asUnsubscribeFn(
|
|
25285
|
-
ws.subscribeToTpsl(addr, chainId, () => {
|
|
25286
|
-
queryClient.invalidateQueries({ queryKey: ["symm", "tpslOrders"] });
|
|
25287
|
-
queryClient.invalidateQueries({ queryKey: ["symm", "openOrders"] });
|
|
25288
|
-
})
|
|
25289
|
-
);
|
|
25290
|
-
if (tpslUnsub) unsubscribers.push(tpslUnsub);
|
|
25291
|
-
const twapUnsub = asUnsubscribeFn(
|
|
25292
|
-
ws.subscribeToTwapOrders(addr, chainId, () => {
|
|
25293
|
-
queryClient.invalidateQueries({ queryKey: ["symm", "twapOrders"] });
|
|
25294
|
-
queryClient.invalidateQueries({ queryKey: ["symm", "openOrders"] });
|
|
25295
|
-
})
|
|
25296
|
-
);
|
|
25297
|
-
if (twapUnsub) unsubscribers.push(twapUnsub);
|
|
25298
|
-
const triggerOrdersUnsub = asUnsubscribeFn(
|
|
25299
|
-
ws.subscribeToTriggerOrders(addr, chainId, () => {
|
|
25300
|
-
queryClient.invalidateQueries({ queryKey: ["symm", "triggerOrders"] });
|
|
25301
|
-
queryClient.invalidateQueries({ queryKey: ["symm", "openOrders"] });
|
|
25302
|
-
})
|
|
25303
|
-
);
|
|
25304
|
-
if (triggerOrdersUnsub) unsubscribers.push(triggerOrdersUnsub);
|
|
25305
|
-
const executionsUnsub = asUnsubscribeFn(
|
|
25306
|
-
ws.subscribeToExecutions(addr, chainId, () => {
|
|
25307
|
-
queryClient.invalidateQueries({
|
|
25308
|
-
queryKey: ["symm", "positions"]
|
|
25309
|
-
});
|
|
25310
|
-
queryClient.invalidateQueries({
|
|
25311
|
-
queryKey: ["symm", "portfolio"]
|
|
25312
|
-
});
|
|
25313
|
-
})
|
|
25314
|
-
);
|
|
25315
|
-
if (executionsUnsub) unsubscribers.push(executionsUnsub);
|
|
25316
|
-
return () => {
|
|
25317
|
-
unsubscribers.forEach((unsubscribe) => unsubscribe());
|
|
25318
|
-
};
|
|
25319
|
-
}, [symmCoreClient, accountAddress, chainId, queryClient, setConnected]);
|
|
25320
|
-
return { isConnected };
|
|
25321
|
-
}
|
|
25322
|
-
var STABLE_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USD", "USDT", "USDE", "USDH", "USDT0"]);
|
|
25323
|
-
function useSymmChartSelection(input) {
|
|
25324
|
-
const {
|
|
25325
|
-
longSymbol,
|
|
25326
|
-
shortSymbol,
|
|
25327
|
-
longWeight = 100,
|
|
25328
|
-
shortWeight = 100,
|
|
25329
|
-
longTokens: explicitLongTokens,
|
|
25330
|
-
shortTokens: explicitShortTokens
|
|
25331
|
-
} = input;
|
|
25332
|
-
return useMemo(() => {
|
|
25333
|
-
const longTokens = explicitLongTokens?.length ? explicitLongTokens : longSymbol ? [{ symbol: longSymbol, weight: longWeight }] : [];
|
|
25334
|
-
const shortTokens = explicitShortTokens?.length ? explicitShortTokens : shortSymbol ? [{ symbol: shortSymbol, weight: shortWeight }] : [];
|
|
25335
|
-
const selectedSymbols = [
|
|
25336
|
-
...longTokens.map((t) => t.symbol),
|
|
25337
|
-
...shortTokens.map((t) => t.symbol)
|
|
25338
|
-
];
|
|
25339
|
-
const uniqueSelectedSymbols = Array.from(new Set(selectedSymbols));
|
|
25340
|
-
const longPrimarySymbol = longTokens[0]?.symbol ?? null;
|
|
25341
|
-
const shortPrimarySymbol = shortTokens[0]?.symbol ?? null;
|
|
25342
|
-
const longIsStable = longPrimarySymbol ? STABLE_SYMBOLS.has(longPrimarySymbol.toUpperCase()) : true;
|
|
25343
|
-
const shortIsStable = shortPrimarySymbol ? STABLE_SYMBOLS.has(shortPrimarySymbol.toUpperCase()) : true;
|
|
25344
|
-
let isSingleSided = false;
|
|
25345
|
-
let activeSide = null;
|
|
25346
|
-
let activeTokenSymbol;
|
|
25347
|
-
if (longTokens.length > 0 && !longIsStable && (shortTokens.length === 0 || shortIsStable)) {
|
|
25348
|
-
isSingleSided = true;
|
|
25349
|
-
activeSide = "long";
|
|
25350
|
-
activeTokenSymbol = longPrimarySymbol ?? void 0;
|
|
25351
|
-
} else if (shortTokens.length > 0 && !shortIsStable && (longTokens.length === 0 || longIsStable)) {
|
|
25352
|
-
isSingleSided = true;
|
|
25353
|
-
activeSide = "short";
|
|
25354
|
-
activeTokenSymbol = shortPrimarySymbol ?? void 0;
|
|
25355
|
-
}
|
|
25356
|
-
const longLabel = longTokens.map((token) => token.symbol).join("+") || "USDC";
|
|
25357
|
-
const shortLabel = shortTokens.map((token) => token.symbol).join("+") || "USDC";
|
|
25358
|
-
const pairLabel = `${longLabel}/${shortLabel}`;
|
|
25359
|
-
return {
|
|
25360
|
-
longTokens,
|
|
25361
|
-
shortTokens,
|
|
25362
|
-
isSingleSided,
|
|
25363
|
-
activeSide,
|
|
25364
|
-
activeTokenSymbol,
|
|
25365
|
-
pairLabel,
|
|
25366
|
-
selectedSymbols: uniqueSelectedSymbols
|
|
25367
|
-
};
|
|
25368
|
-
}, [
|
|
25369
|
-
explicitLongTokens,
|
|
25370
|
-
explicitShortTokens,
|
|
25371
|
-
longSymbol,
|
|
25372
|
-
shortSymbol,
|
|
25373
|
-
longWeight,
|
|
25374
|
-
shortWeight
|
|
25375
|
-
]);
|
|
25376
|
-
}
|
|
25377
|
-
|
|
25378
|
-
// src/utils/binance-symbol-map.ts
|
|
25379
|
-
var SYMBOL_OVERRIDES = {
|
|
25380
|
-
// Add overrides here as needed for SYMM markets that don't map 1:1 to Binance
|
|
25381
|
-
// e.g., 'SOME_SYMM_SYMBOL': 'BINANCE_SYMBOL',
|
|
25382
|
-
};
|
|
25383
|
-
var UNSUPPORTED_SYMBOLS = /* @__PURE__ */ new Set([
|
|
25384
|
-
// Add symbols here that have no Binance equivalent
|
|
25385
|
-
]);
|
|
25386
|
-
function resolveBinanceSymbol(symmSymbol) {
|
|
25387
|
-
if (!symmSymbol || !symmSymbol.trim()) {
|
|
25388
|
-
return {
|
|
25389
|
-
symmSymbol,
|
|
25390
|
-
normalizedSymbol: "",
|
|
25391
|
-
binanceSymbol: null,
|
|
25392
|
-
supported: false,
|
|
25393
|
-
reason: "missing_symbol"
|
|
25394
|
-
};
|
|
25395
|
-
}
|
|
25396
|
-
const normalized = symmSymbol.toUpperCase().trim();
|
|
25397
|
-
if (!/^[A-Z0-9]+$/.test(normalized)) {
|
|
25398
|
-
return {
|
|
25399
|
-
symmSymbol,
|
|
25400
|
-
normalizedSymbol: normalized,
|
|
25401
|
-
binanceSymbol: null,
|
|
25402
|
-
supported: false,
|
|
25403
|
-
reason: "invalid_symbol"
|
|
25404
|
-
};
|
|
25405
|
-
}
|
|
25406
|
-
if (UNSUPPORTED_SYMBOLS.has(normalized)) {
|
|
25407
|
-
return {
|
|
25408
|
-
symmSymbol,
|
|
25409
|
-
normalizedSymbol: normalized,
|
|
25410
|
-
binanceSymbol: null,
|
|
25411
|
-
supported: false,
|
|
25412
|
-
reason: "unsupported_symbol"
|
|
25413
|
-
};
|
|
25414
|
-
}
|
|
25415
|
-
const binanceSymbol = SYMBOL_OVERRIDES[normalized] ?? (normalized.endsWith("USDT") ? normalized : `${normalized}USDT`);
|
|
25416
|
-
return {
|
|
25417
|
-
symmSymbol,
|
|
25418
|
-
normalizedSymbol: normalized,
|
|
25419
|
-
binanceSymbol,
|
|
25420
|
-
supported: true,
|
|
25421
|
-
reason: null
|
|
25422
|
-
};
|
|
25423
|
-
}
|
|
25424
|
-
function getUnsupportedBinanceSymbols(symbols) {
|
|
25425
|
-
return symbols.filter((symbol) => !resolveBinanceSymbol(symbol).supported);
|
|
25426
|
-
}
|
|
25427
|
-
function toBinanceSymbol(symmSymbol) {
|
|
25428
|
-
return resolveBinanceSymbol(symmSymbol).binanceSymbol;
|
|
25429
|
-
}
|
|
25430
|
-
|
|
25431
|
-
// src/utils/binance-api.ts
|
|
25432
|
-
var BINANCE_FAPI_BASE = "https://fapi.binance.com";
|
|
25433
|
-
async function fetchMarkPriceKlines(symbol, interval, startTime, endTime, limit = 1500) {
|
|
25434
|
-
const params = new URLSearchParams({
|
|
25435
|
-
symbol,
|
|
25436
|
-
interval,
|
|
25437
|
-
startTime: String(startTime),
|
|
25438
|
-
endTime: String(endTime),
|
|
25439
|
-
limit: String(Math.min(limit, 1500))
|
|
25440
|
-
});
|
|
25441
|
-
const response = await fetch(`${BINANCE_FAPI_BASE}/fapi/v1/markPriceKlines?${params}`);
|
|
25442
|
-
if (!response.ok) {
|
|
25443
|
-
throw new Error(`Binance markPriceKlines failed: ${response.status}`);
|
|
25444
|
-
}
|
|
25445
|
-
const data = await response.json();
|
|
25446
|
-
return data.map((k) => ({
|
|
25447
|
-
openTime: Number(k[0]),
|
|
25448
|
-
open: parseFloat(k[1]),
|
|
25449
|
-
high: parseFloat(k[2]),
|
|
25450
|
-
low: parseFloat(k[3]),
|
|
25451
|
-
close: parseFloat(k[4]),
|
|
25452
|
-
volume: parseFloat(k[5]),
|
|
25453
|
-
closeTime: Number(k[6])
|
|
25454
|
-
}));
|
|
25455
|
-
}
|
|
25456
|
-
async function fetch24hrTicker(symbol) {
|
|
25457
|
-
const params = new URLSearchParams({ symbol });
|
|
25458
|
-
const response = await fetch(`${BINANCE_FAPI_BASE}/fapi/v1/ticker/24hr?${params}`);
|
|
25459
|
-
if (!response.ok) return null;
|
|
25460
|
-
const data = await response.json();
|
|
25461
|
-
return {
|
|
25462
|
-
lastPrice: parseFloat(data.lastPrice),
|
|
25463
|
-
prevClosePrice: parseFloat(data.prevClosePrice),
|
|
25464
|
-
priceChangePercent: parseFloat(data.priceChangePercent)
|
|
25465
|
-
};
|
|
25466
|
-
}
|
|
25467
|
-
|
|
25468
|
-
// src/utils/chart-metrics.ts
|
|
25469
|
-
function getPositiveValue(metadata, field) {
|
|
25470
|
-
const value = metadata?.[field];
|
|
25471
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
25472
|
-
return null;
|
|
25473
|
-
}
|
|
25474
|
-
return value;
|
|
25475
|
-
}
|
|
25476
|
-
function computeWeightedProduct(tokens, metadataMap, field, invert = false) {
|
|
25477
|
-
let product = 1;
|
|
25478
|
-
let hasToken = false;
|
|
25479
|
-
for (const token of tokens) {
|
|
25480
|
-
if (!(token.weight > 0)) {
|
|
25481
|
-
continue;
|
|
25482
|
-
}
|
|
25483
|
-
const price = getPositiveValue(metadataMap[token.symbol], field);
|
|
25484
|
-
if (price === null) {
|
|
25485
|
-
return null;
|
|
25486
|
-
}
|
|
25487
|
-
hasToken = true;
|
|
25488
|
-
const exponent = invert ? -(token.weight / 100) : token.weight / 100;
|
|
25489
|
-
product *= Math.pow(price, exponent);
|
|
25490
|
-
}
|
|
25491
|
-
return hasToken ? product : 1;
|
|
25492
|
-
}
|
|
25493
|
-
function computePriceRatio({
|
|
25494
|
-
longTokens,
|
|
25495
|
-
shortTokens,
|
|
25496
|
-
longTokensMetadata,
|
|
25497
|
-
shortTokensMetadata
|
|
25498
|
-
}) {
|
|
25499
|
-
const firstLong = longTokens[0];
|
|
25500
|
-
const firstShort = shortTokens[0];
|
|
25501
|
-
const longPrice = firstLong ? getPositiveValue(longTokensMetadata[firstLong.symbol], "currentPrice") : null;
|
|
25502
|
-
const shortPrice = firstShort ? getPositiveValue(shortTokensMetadata[firstShort.symbol], "currentPrice") : null;
|
|
25503
|
-
if (longPrice !== null && shortPrice !== null) {
|
|
25504
|
-
return longPrice / shortPrice;
|
|
25505
|
-
}
|
|
25506
|
-
if (longPrice !== null && shortTokens.length === 0) {
|
|
25507
|
-
return longPrice;
|
|
25508
|
-
}
|
|
25509
|
-
if (shortPrice !== null && longTokens.length === 0) {
|
|
25510
|
-
return shortPrice;
|
|
25511
|
-
}
|
|
25512
|
-
return null;
|
|
25513
|
-
}
|
|
25514
|
-
function computePriceRatio24h({
|
|
25515
|
-
longTokens,
|
|
25516
|
-
shortTokens,
|
|
25517
|
-
longTokensMetadata,
|
|
25518
|
-
shortTokensMetadata
|
|
25519
|
-
}) {
|
|
25520
|
-
const firstLong = longTokens[0];
|
|
25521
|
-
const firstShort = shortTokens[0];
|
|
25522
|
-
const longPrice = firstLong ? getPositiveValue(longTokensMetadata[firstLong.symbol], "prevDayPrice") : null;
|
|
25523
|
-
const shortPrice = firstShort ? getPositiveValue(shortTokensMetadata[firstShort.symbol], "prevDayPrice") : null;
|
|
25524
|
-
if (longPrice !== null && shortPrice !== null) {
|
|
25525
|
-
return longPrice / shortPrice;
|
|
25526
|
-
}
|
|
25527
|
-
if (longPrice !== null && shortTokens.length === 0) {
|
|
25528
|
-
return longPrice;
|
|
25529
|
-
}
|
|
25530
|
-
if (shortPrice !== null && longTokens.length === 0) {
|
|
25531
|
-
return shortPrice;
|
|
25532
|
-
}
|
|
25533
|
-
return null;
|
|
25534
|
-
}
|
|
25535
|
-
function computeWeightedRatio({
|
|
25536
|
-
longTokens,
|
|
25537
|
-
shortTokens,
|
|
25538
|
-
longTokensMetadata,
|
|
25539
|
-
shortTokensMetadata
|
|
25540
|
-
}) {
|
|
25541
|
-
const longProduct = computeWeightedProduct(
|
|
25542
|
-
longTokens,
|
|
25543
|
-
longTokensMetadata,
|
|
25544
|
-
"currentPrice"
|
|
25545
|
-
);
|
|
25546
|
-
const shortProduct = computeWeightedProduct(
|
|
25547
|
-
shortTokens,
|
|
25548
|
-
shortTokensMetadata,
|
|
25549
|
-
"currentPrice",
|
|
25550
|
-
true
|
|
25551
|
-
);
|
|
25552
|
-
if (longProduct === null || shortProduct === null) {
|
|
25553
|
-
return null;
|
|
25554
|
-
}
|
|
25555
|
-
return longProduct * shortProduct;
|
|
25556
|
-
}
|
|
25557
|
-
function computeWeightedRatio24h({
|
|
25558
|
-
longTokens,
|
|
25559
|
-
shortTokens,
|
|
25560
|
-
longTokensMetadata,
|
|
25561
|
-
shortTokensMetadata
|
|
25562
|
-
}) {
|
|
25563
|
-
const longProduct = computeWeightedProduct(
|
|
25564
|
-
longTokens,
|
|
25565
|
-
longTokensMetadata,
|
|
25566
|
-
"prevDayPrice"
|
|
25567
|
-
);
|
|
25568
|
-
const shortProduct = computeWeightedProduct(
|
|
25569
|
-
shortTokens,
|
|
25570
|
-
shortTokensMetadata,
|
|
25571
|
-
"prevDayPrice",
|
|
25572
|
-
true
|
|
25573
|
-
);
|
|
25574
|
-
if (longProduct === null || shortProduct === null) {
|
|
25575
|
-
return null;
|
|
25576
|
-
}
|
|
25577
|
-
return longProduct * shortProduct;
|
|
25578
|
-
}
|
|
25579
|
-
function computeNetFundingSum({
|
|
25580
|
-
longTokens,
|
|
25581
|
-
shortTokens,
|
|
25582
|
-
longTokensMetadata,
|
|
25583
|
-
shortTokensMetadata
|
|
25584
|
-
}) {
|
|
25585
|
-
let funding = 0;
|
|
25586
|
-
for (const token of longTokens) {
|
|
25587
|
-
const value = longTokensMetadata[token.symbol]?.netFunding;
|
|
25588
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
25589
|
-
funding += value;
|
|
25590
|
-
}
|
|
25591
|
-
}
|
|
25592
|
-
for (const token of shortTokens) {
|
|
25593
|
-
const value = shortTokensMetadata[token.symbol]?.netFunding;
|
|
25594
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
25595
|
-
funding += value;
|
|
25596
|
-
}
|
|
25597
|
-
}
|
|
25598
|
-
return funding;
|
|
25599
|
-
}
|
|
25600
|
-
|
|
25601
|
-
// src/utils/binance-ws.ts
|
|
25602
|
-
var BINANCE_WS_URL = "wss://fstream.binance.com/ws";
|
|
25603
|
-
var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
|
|
25604
|
-
var BinanceWsManager = class {
|
|
25605
|
-
ws = null;
|
|
25606
|
-
streams = /* @__PURE__ */ new Map();
|
|
25607
|
-
reconnectAttempt = 0;
|
|
25608
|
-
reconnectTimer = null;
|
|
25609
|
-
intentionalClose = false;
|
|
25610
|
-
pendingSubscribes = [];
|
|
25611
|
-
idCounter = 0;
|
|
25612
|
-
/**
|
|
25613
|
-
* Subscribe to a kline stream. Returns an unsubscribe function.
|
|
25614
|
-
*/
|
|
25615
|
-
subscribeKline(symbol, interval, cb) {
|
|
25616
|
-
const streamName = `${symbol.toLowerCase()}@kline_${interval}`;
|
|
25617
|
-
const id = this.generateId();
|
|
25618
|
-
const wrappedCb = (raw) => {
|
|
25619
|
-
const k = raw.k;
|
|
25620
|
-
if (!k) return;
|
|
25621
|
-
cb({
|
|
25622
|
-
symbol: raw.s,
|
|
25623
|
-
interval: k.i,
|
|
25624
|
-
openTime: k.t,
|
|
25625
|
-
closeTime: k.T,
|
|
25626
|
-
open: parseFloat(k.o),
|
|
25627
|
-
high: parseFloat(k.h),
|
|
25628
|
-
low: parseFloat(k.l),
|
|
25629
|
-
close: parseFloat(k.c),
|
|
25630
|
-
volume: parseFloat(k.v),
|
|
25631
|
-
isFinal: k.x
|
|
25094
|
+
|
|
25095
|
+
// src/utils/binance-ws.ts
|
|
25096
|
+
var BINANCE_WS_URL = "wss://fstream.binance.com/ws";
|
|
25097
|
+
var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
|
|
25098
|
+
var BinanceWsManager = class {
|
|
25099
|
+
ws = null;
|
|
25100
|
+
streams = /* @__PURE__ */ new Map();
|
|
25101
|
+
reconnectAttempt = 0;
|
|
25102
|
+
reconnectTimer = null;
|
|
25103
|
+
intentionalClose = false;
|
|
25104
|
+
pendingSubscribes = [];
|
|
25105
|
+
idCounter = 0;
|
|
25106
|
+
/**
|
|
25107
|
+
* Subscribe to a kline stream. Returns an unsubscribe function.
|
|
25108
|
+
*/
|
|
25109
|
+
subscribeKline(symbol, interval, cb) {
|
|
25110
|
+
const streamName = `${symbol.toLowerCase()}@kline_${interval}`;
|
|
25111
|
+
const id = this.generateId();
|
|
25112
|
+
const wrappedCb = (raw) => {
|
|
25113
|
+
const k = raw.k;
|
|
25114
|
+
if (!k) return;
|
|
25115
|
+
cb({
|
|
25116
|
+
symbol: raw.s,
|
|
25117
|
+
interval: k.i,
|
|
25118
|
+
openTime: k.t,
|
|
25119
|
+
closeTime: k.T,
|
|
25120
|
+
open: parseFloat(k.o),
|
|
25121
|
+
high: parseFloat(k.h),
|
|
25122
|
+
low: parseFloat(k.l),
|
|
25123
|
+
close: parseFloat(k.c),
|
|
25124
|
+
volume: parseFloat(k.v),
|
|
25125
|
+
isFinal: k.x
|
|
25632
25126
|
});
|
|
25633
25127
|
};
|
|
25634
25128
|
this.addStreamCallback(streamName, id, wrappedCb);
|
|
@@ -25647,225 +25141,837 @@ var BinanceWsManager = class {
|
|
|
25647
25141
|
indexPrice: parseFloat(raw.i),
|
|
25648
25142
|
time: raw.E
|
|
25649
25143
|
});
|
|
25650
|
-
};
|
|
25651
|
-
this.addStreamCallback(streamName, id, wrappedCb);
|
|
25652
|
-
return () => this.removeStreamCallback(streamName, id);
|
|
25653
|
-
}
|
|
25654
|
-
/**
|
|
25655
|
-
* Destroy the manager and close the connection.
|
|
25656
|
-
*/
|
|
25657
|
-
destroy() {
|
|
25658
|
-
this.intentionalClose = true;
|
|
25659
|
-
if (this.reconnectTimer) {
|
|
25660
|
-
clearTimeout(this.reconnectTimer);
|
|
25661
|
-
this.reconnectTimer = null;
|
|
25662
|
-
}
|
|
25663
|
-
if (this.ws) {
|
|
25664
|
-
this.ws.close();
|
|
25665
|
-
this.ws = null;
|
|
25144
|
+
};
|
|
25145
|
+
this.addStreamCallback(streamName, id, wrappedCb);
|
|
25146
|
+
return () => this.removeStreamCallback(streamName, id);
|
|
25147
|
+
}
|
|
25148
|
+
/**
|
|
25149
|
+
* Destroy the manager and close the connection.
|
|
25150
|
+
*/
|
|
25151
|
+
destroy() {
|
|
25152
|
+
this.intentionalClose = true;
|
|
25153
|
+
if (this.reconnectTimer) {
|
|
25154
|
+
clearTimeout(this.reconnectTimer);
|
|
25155
|
+
this.reconnectTimer = null;
|
|
25156
|
+
}
|
|
25157
|
+
if (this.ws) {
|
|
25158
|
+
this.ws.close();
|
|
25159
|
+
this.ws = null;
|
|
25160
|
+
}
|
|
25161
|
+
this.streams.clear();
|
|
25162
|
+
}
|
|
25163
|
+
// --- Private ---
|
|
25164
|
+
generateId() {
|
|
25165
|
+
return `sub_${++this.idCounter}_${Date.now()}`;
|
|
25166
|
+
}
|
|
25167
|
+
addStreamCallback(streamName, id, cb) {
|
|
25168
|
+
let sub = this.streams.get(streamName);
|
|
25169
|
+
const isNew = !sub;
|
|
25170
|
+
if (!sub) {
|
|
25171
|
+
sub = { callbacks: /* @__PURE__ */ new Map() };
|
|
25172
|
+
this.streams.set(streamName, sub);
|
|
25173
|
+
}
|
|
25174
|
+
sub.callbacks.set(id, cb);
|
|
25175
|
+
if (isNew) {
|
|
25176
|
+
this.ensureConnected();
|
|
25177
|
+
this.sendSubscribe([streamName]);
|
|
25178
|
+
}
|
|
25179
|
+
}
|
|
25180
|
+
removeStreamCallback(streamName, id) {
|
|
25181
|
+
const sub = this.streams.get(streamName);
|
|
25182
|
+
if (!sub) return;
|
|
25183
|
+
sub.callbacks.delete(id);
|
|
25184
|
+
if (sub.callbacks.size === 0) {
|
|
25185
|
+
this.streams.delete(streamName);
|
|
25186
|
+
this.sendUnsubscribe([streamName]);
|
|
25187
|
+
if (this.streams.size === 0 && this.ws) {
|
|
25188
|
+
this.intentionalClose = true;
|
|
25189
|
+
this.ws.close();
|
|
25190
|
+
this.ws = null;
|
|
25191
|
+
this.intentionalClose = false;
|
|
25192
|
+
}
|
|
25193
|
+
}
|
|
25194
|
+
}
|
|
25195
|
+
ensureConnected() {
|
|
25196
|
+
if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) {
|
|
25197
|
+
return;
|
|
25198
|
+
}
|
|
25199
|
+
this.connect();
|
|
25200
|
+
}
|
|
25201
|
+
connect() {
|
|
25202
|
+
if (typeof WebSocket === "undefined") return;
|
|
25203
|
+
this.intentionalClose = false;
|
|
25204
|
+
this.ws = new WebSocket(BINANCE_WS_URL);
|
|
25205
|
+
this.ws.onopen = () => {
|
|
25206
|
+
this.reconnectAttempt = 0;
|
|
25207
|
+
const activeStreams = Array.from(this.streams.keys());
|
|
25208
|
+
if (activeStreams.length > 0) {
|
|
25209
|
+
this.sendSubscribe(activeStreams);
|
|
25210
|
+
}
|
|
25211
|
+
if (this.pendingSubscribes.length > 0) {
|
|
25212
|
+
this.sendSubscribe(this.pendingSubscribes);
|
|
25213
|
+
this.pendingSubscribes = [];
|
|
25214
|
+
}
|
|
25215
|
+
};
|
|
25216
|
+
this.ws.onmessage = (event) => {
|
|
25217
|
+
try {
|
|
25218
|
+
const data = JSON.parse(event.data);
|
|
25219
|
+
this.handleMessage(data);
|
|
25220
|
+
} catch {
|
|
25221
|
+
}
|
|
25222
|
+
};
|
|
25223
|
+
this.ws.onclose = () => {
|
|
25224
|
+
if (this.intentionalClose) return;
|
|
25225
|
+
this.scheduleReconnect();
|
|
25226
|
+
};
|
|
25227
|
+
this.ws.onerror = () => {
|
|
25228
|
+
};
|
|
25229
|
+
}
|
|
25230
|
+
handleMessage(data) {
|
|
25231
|
+
if (data.e === "kline") {
|
|
25232
|
+
const k = data.k;
|
|
25233
|
+
const streamName = `${data.s.toLowerCase()}@kline_${k.i}`;
|
|
25234
|
+
this.dispatchToStream(streamName, data);
|
|
25235
|
+
} else if (data.e === "markPriceUpdate") {
|
|
25236
|
+
const streamName = `${data.s.toLowerCase()}@markPrice@1s`;
|
|
25237
|
+
this.dispatchToStream(streamName, data);
|
|
25238
|
+
}
|
|
25239
|
+
}
|
|
25240
|
+
dispatchToStream(streamName, data) {
|
|
25241
|
+
const sub = this.streams.get(streamName);
|
|
25242
|
+
if (!sub) return;
|
|
25243
|
+
sub.callbacks.forEach((cb) => {
|
|
25244
|
+
try {
|
|
25245
|
+
cb(data);
|
|
25246
|
+
} catch {
|
|
25247
|
+
}
|
|
25248
|
+
});
|
|
25249
|
+
}
|
|
25250
|
+
sendSubscribe(streams) {
|
|
25251
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
25252
|
+
this.pendingSubscribes.push(...streams);
|
|
25253
|
+
return;
|
|
25254
|
+
}
|
|
25255
|
+
this.ws.send(JSON.stringify({
|
|
25256
|
+
method: "SUBSCRIBE",
|
|
25257
|
+
params: streams,
|
|
25258
|
+
id: Date.now()
|
|
25259
|
+
}));
|
|
25260
|
+
}
|
|
25261
|
+
sendUnsubscribe(streams) {
|
|
25262
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
25263
|
+
this.pendingSubscribes = this.pendingSubscribes.filter(
|
|
25264
|
+
(s) => !streams.includes(s)
|
|
25265
|
+
);
|
|
25266
|
+
return;
|
|
25267
|
+
}
|
|
25268
|
+
this.ws.send(JSON.stringify({
|
|
25269
|
+
method: "UNSUBSCRIBE",
|
|
25270
|
+
params: streams,
|
|
25271
|
+
id: Date.now()
|
|
25272
|
+
}));
|
|
25273
|
+
}
|
|
25274
|
+
scheduleReconnect() {
|
|
25275
|
+
if (this.reconnectTimer) return;
|
|
25276
|
+
if (this.streams.size === 0) return;
|
|
25277
|
+
const delay = RECONNECT_DELAYS[Math.min(this.reconnectAttempt, RECONNECT_DELAYS.length - 1)];
|
|
25278
|
+
this.reconnectAttempt++;
|
|
25279
|
+
this.reconnectTimer = setTimeout(() => {
|
|
25280
|
+
this.reconnectTimer = null;
|
|
25281
|
+
this.connect();
|
|
25282
|
+
}, delay);
|
|
25283
|
+
}
|
|
25284
|
+
};
|
|
25285
|
+
var _instance = null;
|
|
25286
|
+
function getBinanceWsManager() {
|
|
25287
|
+
if (!_instance) {
|
|
25288
|
+
_instance = new BinanceWsManager();
|
|
25289
|
+
}
|
|
25290
|
+
return _instance;
|
|
25291
|
+
}
|
|
25292
|
+
|
|
25293
|
+
// src/react/stores/use-binance-mark-price-store.ts
|
|
25294
|
+
var refCounts = /* @__PURE__ */ new Map();
|
|
25295
|
+
var streamUnsubs = /* @__PURE__ */ new Map();
|
|
25296
|
+
var streamSymbols = /* @__PURE__ */ new Map();
|
|
25297
|
+
function normalizeBinanceSymbol(symbol) {
|
|
25298
|
+
return symbol.toUpperCase().trim();
|
|
25299
|
+
}
|
|
25300
|
+
function getNextRefCount(binanceSymbol) {
|
|
25301
|
+
return (refCounts.get(binanceSymbol) ?? 0) + 1;
|
|
25302
|
+
}
|
|
25303
|
+
function getPrevRefCount(binanceSymbol) {
|
|
25304
|
+
return Math.max(0, (refCounts.get(binanceSymbol) ?? 0) - 1);
|
|
25305
|
+
}
|
|
25306
|
+
var useBinanceMarkPriceStore = create((set) => ({
|
|
25307
|
+
markPrices: {},
|
|
25308
|
+
subscribeSymbol: (symmSymbol, rawBinanceSymbol) => {
|
|
25309
|
+
const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
|
|
25310
|
+
const nextRefCount = getNextRefCount(binanceSymbol);
|
|
25311
|
+
refCounts.set(binanceSymbol, nextRefCount);
|
|
25312
|
+
const symbols = streamSymbols.get(binanceSymbol) ?? /* @__PURE__ */ new Set();
|
|
25313
|
+
symbols.add(symmSymbol);
|
|
25314
|
+
streamSymbols.set(binanceSymbol, symbols);
|
|
25315
|
+
if (nextRefCount === 1) {
|
|
25316
|
+
const wsManager = getBinanceWsManager();
|
|
25317
|
+
const unsubscribe = wsManager.subscribeMarkPrice(binanceSymbol, (data) => {
|
|
25318
|
+
const canonicalSymbol = normalizeBinanceSymbol(data.symbol);
|
|
25319
|
+
const mappedSymbols = streamSymbols.get(canonicalSymbol);
|
|
25320
|
+
if (!mappedSymbols || mappedSymbols.size === 0) return;
|
|
25321
|
+
set((state) => {
|
|
25322
|
+
const nextMarkPrices = { ...state.markPrices };
|
|
25323
|
+
mappedSymbols.forEach((mappedSymbol) => {
|
|
25324
|
+
nextMarkPrices[mappedSymbol] = data.markPrice;
|
|
25325
|
+
});
|
|
25326
|
+
return { markPrices: nextMarkPrices };
|
|
25327
|
+
});
|
|
25328
|
+
});
|
|
25329
|
+
streamUnsubs.set(binanceSymbol, unsubscribe);
|
|
25666
25330
|
}
|
|
25667
|
-
|
|
25668
|
-
|
|
25669
|
-
|
|
25670
|
-
|
|
25671
|
-
|
|
25672
|
-
|
|
25673
|
-
|
|
25674
|
-
|
|
25675
|
-
|
|
25676
|
-
|
|
25677
|
-
|
|
25678
|
-
this.streams.set(streamName, sub);
|
|
25331
|
+
},
|
|
25332
|
+
unsubscribeSymbol: (symmSymbol, rawBinanceSymbol) => {
|
|
25333
|
+
const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
|
|
25334
|
+
const symbols = streamSymbols.get(binanceSymbol);
|
|
25335
|
+
if (symbols) {
|
|
25336
|
+
symbols.delete(symmSymbol);
|
|
25337
|
+
if (symbols.size === 0) {
|
|
25338
|
+
streamSymbols.delete(binanceSymbol);
|
|
25339
|
+
} else {
|
|
25340
|
+
streamSymbols.set(binanceSymbol, symbols);
|
|
25341
|
+
}
|
|
25679
25342
|
}
|
|
25680
|
-
|
|
25681
|
-
if (
|
|
25682
|
-
|
|
25683
|
-
|
|
25343
|
+
const nextRefCount = getPrevRefCount(binanceSymbol);
|
|
25344
|
+
if (nextRefCount === 0) {
|
|
25345
|
+
const unsubscribe = streamUnsubs.get(binanceSymbol);
|
|
25346
|
+
if (unsubscribe) unsubscribe();
|
|
25347
|
+
streamUnsubs.delete(binanceSymbol);
|
|
25348
|
+
refCounts.delete(binanceSymbol);
|
|
25349
|
+
} else {
|
|
25350
|
+
refCounts.set(binanceSymbol, nextRefCount);
|
|
25684
25351
|
}
|
|
25352
|
+
set((state) => {
|
|
25353
|
+
if (state.markPrices[symmSymbol] == null) return state;
|
|
25354
|
+
const nextMarkPrices = { ...state.markPrices };
|
|
25355
|
+
delete nextMarkPrices[symmSymbol];
|
|
25356
|
+
return { markPrices: nextMarkPrices };
|
|
25357
|
+
});
|
|
25685
25358
|
}
|
|
25686
|
-
|
|
25687
|
-
|
|
25688
|
-
|
|
25689
|
-
|
|
25690
|
-
|
|
25691
|
-
|
|
25692
|
-
|
|
25693
|
-
|
|
25694
|
-
|
|
25695
|
-
|
|
25696
|
-
|
|
25697
|
-
|
|
25359
|
+
}));
|
|
25360
|
+
|
|
25361
|
+
// src/react/hooks/use-symm-token-selection-markets.ts
|
|
25362
|
+
async function fetchTickerSnapshot(symbol) {
|
|
25363
|
+
const resolution = resolveBinanceSymbol(symbol);
|
|
25364
|
+
if (!resolution.binanceSymbol) return null;
|
|
25365
|
+
const ticker = await fetch24hrTicker(resolution.binanceSymbol);
|
|
25366
|
+
if (!ticker) return null;
|
|
25367
|
+
return {
|
|
25368
|
+
prevClosePrice: ticker.prevClosePrice
|
|
25369
|
+
};
|
|
25370
|
+
}
|
|
25371
|
+
function useSymmTokenSelectionMarkets(params) {
|
|
25372
|
+
const query = useSymmHedgerMarkets(params);
|
|
25373
|
+
const baseMarkets = query.data?.filteredMarkets ?? query.data?.markets ?? [];
|
|
25374
|
+
const marketSymbols = useMemo(
|
|
25375
|
+
() => Array.from(
|
|
25376
|
+
new Set(
|
|
25377
|
+
baseMarkets.map((market) => market.symbol).filter((symbol) => !!symbol)
|
|
25378
|
+
)
|
|
25379
|
+
),
|
|
25380
|
+
[baseMarkets]
|
|
25381
|
+
);
|
|
25382
|
+
const symbolsKey = useMemo(
|
|
25383
|
+
() => [...marketSymbols].sort().join(","),
|
|
25384
|
+
[marketSymbols]
|
|
25385
|
+
);
|
|
25386
|
+
const symbolToBinanceMap = useMemo(
|
|
25387
|
+
() => new Map(
|
|
25388
|
+
marketSymbols.map((symbol) => {
|
|
25389
|
+
const binanceSymbol = resolveBinanceSymbol(symbol).binanceSymbol;
|
|
25390
|
+
if (!binanceSymbol) return null;
|
|
25391
|
+
return [symbol, binanceSymbol];
|
|
25392
|
+
}).filter((entry) => !!entry)
|
|
25393
|
+
),
|
|
25394
|
+
[marketSymbols]
|
|
25395
|
+
);
|
|
25396
|
+
const liveMarkPrices = useBinanceMarkPriceStore((state) => state.markPrices);
|
|
25397
|
+
const subscribeSymbol = useBinanceMarkPriceStore((state) => state.subscribeSymbol);
|
|
25398
|
+
const unsubscribeSymbol = useBinanceMarkPriceStore((state) => state.unsubscribeSymbol);
|
|
25399
|
+
const priceQuery = useQuery({
|
|
25400
|
+
queryKey: ["symm", "token-selection-markets-price", symbolsKey],
|
|
25401
|
+
queryFn: async () => {
|
|
25402
|
+
const tickerSnapshots = {};
|
|
25403
|
+
await Promise.all(
|
|
25404
|
+
marketSymbols.map(async (symbol) => {
|
|
25405
|
+
tickerSnapshots[symbol] = await fetchTickerSnapshot(symbol);
|
|
25406
|
+
})
|
|
25407
|
+
);
|
|
25408
|
+
return { tickerSnapshots };
|
|
25409
|
+
},
|
|
25410
|
+
enabled: query.isSuccess && marketSymbols.length > 0,
|
|
25411
|
+
staleTime: 6e4,
|
|
25412
|
+
gcTime: 5 * 6e4
|
|
25413
|
+
});
|
|
25414
|
+
useEffect(() => {
|
|
25415
|
+
if (!query.isSuccess || symbolToBinanceMap.size === 0) {
|
|
25416
|
+
return;
|
|
25417
|
+
}
|
|
25418
|
+
const symbolEntries = Array.from(symbolToBinanceMap.entries());
|
|
25419
|
+
symbolEntries.forEach(
|
|
25420
|
+
([symbol, binanceSymbol]) => subscribeSymbol(symbol, binanceSymbol)
|
|
25421
|
+
);
|
|
25422
|
+
return () => {
|
|
25423
|
+
symbolEntries.forEach(
|
|
25424
|
+
([symbol, binanceSymbol]) => unsubscribeSymbol(symbol, binanceSymbol)
|
|
25425
|
+
);
|
|
25426
|
+
};
|
|
25427
|
+
}, [query.isSuccess, symbolsKey, symbolToBinanceMap, subscribeSymbol, unsubscribeSymbol]);
|
|
25428
|
+
const markets = useMemo(() => {
|
|
25429
|
+
const snapshots = priceQuery.data?.tickerSnapshots ?? {};
|
|
25430
|
+
return baseMarkets.map((market) => {
|
|
25431
|
+
const symbol = market.symbol ?? "";
|
|
25432
|
+
const markPrice = symbol ? liveMarkPrices[symbol] ?? null : null;
|
|
25433
|
+
const prevDayPrice = symbol ? snapshots[symbol]?.prevClosePrice ?? null : null;
|
|
25434
|
+
const priceChange24h = markPrice != null && prevDayPrice != null ? markPrice - prevDayPrice : null;
|
|
25435
|
+
const priceChange24hPercent = markPrice != null && prevDayPrice != null && prevDayPrice !== 0 ? (markPrice - prevDayPrice) / prevDayPrice * 100 : null;
|
|
25436
|
+
return {
|
|
25437
|
+
...market,
|
|
25438
|
+
collateralToken: "USDC",
|
|
25439
|
+
markPrice,
|
|
25440
|
+
prevDayPrice,
|
|
25441
|
+
priceChange24h,
|
|
25442
|
+
priceChange24hPercent
|
|
25443
|
+
};
|
|
25444
|
+
});
|
|
25445
|
+
}, [baseMarkets, liveMarkPrices, priceQuery.data]);
|
|
25446
|
+
const marketsBySymbol = useMemo(
|
|
25447
|
+
() => new Map(
|
|
25448
|
+
markets.filter((m) => !!m.symbol).map((m) => [m.symbol, m])
|
|
25449
|
+
),
|
|
25450
|
+
[markets]
|
|
25451
|
+
);
|
|
25452
|
+
const marketsById = useMemo(
|
|
25453
|
+
() => new Map(markets.map((market) => [market.id, market])),
|
|
25454
|
+
[markets]
|
|
25455
|
+
);
|
|
25456
|
+
return {
|
|
25457
|
+
query,
|
|
25458
|
+
priceQuery,
|
|
25459
|
+
markets,
|
|
25460
|
+
marketsBySymbol,
|
|
25461
|
+
marketsById,
|
|
25462
|
+
isLoading: query.isLoading || priceQuery.isLoading,
|
|
25463
|
+
isPriceLoading: priceQuery.isLoading
|
|
25464
|
+
};
|
|
25465
|
+
}
|
|
25466
|
+
function useSymmFunding(params) {
|
|
25467
|
+
const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
|
|
25468
|
+
const chainId = params?.chainId ?? ctxChainId;
|
|
25469
|
+
const internalEnabled = !!symmCoreClient;
|
|
25470
|
+
return useQuery({
|
|
25471
|
+
...params?.query,
|
|
25472
|
+
queryKey: symmKeys.fundingRates(chainId),
|
|
25473
|
+
queryFn: () => symmCoreClient.funding.getRates({ chainId }),
|
|
25474
|
+
enabled: internalEnabled && (params?.query?.enabled ?? true)
|
|
25475
|
+
});
|
|
25476
|
+
}
|
|
25477
|
+
function useSymmFundingHistory(params) {
|
|
25478
|
+
const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
|
|
25479
|
+
const chainId = params.chainId ?? ctxChainId;
|
|
25480
|
+
const {
|
|
25481
|
+
period,
|
|
25482
|
+
longSymbols,
|
|
25483
|
+
shortSymbols,
|
|
25484
|
+
interval,
|
|
25485
|
+
weightMode,
|
|
25486
|
+
includeContributions
|
|
25487
|
+
} = params;
|
|
25488
|
+
const internalEnabled = !!symmCoreClient;
|
|
25489
|
+
const request = {
|
|
25490
|
+
chainId,
|
|
25491
|
+
period,
|
|
25492
|
+
longSymbols,
|
|
25493
|
+
shortSymbols,
|
|
25494
|
+
interval,
|
|
25495
|
+
weightMode,
|
|
25496
|
+
includeContributions
|
|
25497
|
+
};
|
|
25498
|
+
return useQuery({
|
|
25499
|
+
...params.query,
|
|
25500
|
+
queryKey: symmKeys.fundingHistory(request),
|
|
25501
|
+
queryFn: () => symmCoreClient.funding.getHistory(request),
|
|
25502
|
+
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25503
|
+
});
|
|
25504
|
+
}
|
|
25505
|
+
function useSymmFundingPayments(params) {
|
|
25506
|
+
const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
|
|
25507
|
+
const { address, positionId, limit, offset } = params;
|
|
25508
|
+
const chainId = params.chainId ?? ctxChainId;
|
|
25509
|
+
const internalEnabled = !!symmCoreClient && !!(address || positionId);
|
|
25510
|
+
const request = {
|
|
25511
|
+
address,
|
|
25512
|
+
positionId,
|
|
25513
|
+
chainId,
|
|
25514
|
+
limit,
|
|
25515
|
+
offset
|
|
25516
|
+
};
|
|
25517
|
+
return useQuery({
|
|
25518
|
+
...params.query,
|
|
25519
|
+
queryKey: symmKeys.fundingPayments({
|
|
25520
|
+
address,
|
|
25521
|
+
positionId,
|
|
25522
|
+
chainId,
|
|
25523
|
+
limit,
|
|
25524
|
+
offset
|
|
25525
|
+
}),
|
|
25526
|
+
queryFn: () => symmCoreClient.funding.getPayments(request),
|
|
25527
|
+
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25528
|
+
});
|
|
25529
|
+
}
|
|
25530
|
+
function useSymmPortfolio(params) {
|
|
25531
|
+
const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
|
|
25532
|
+
const { accountAddress, address } = params;
|
|
25533
|
+
const resolvedAddress = accountAddress ? void 0 : address;
|
|
25534
|
+
const chainId = params.chainId ?? ctxChainId;
|
|
25535
|
+
const internalEnabled = !!symmCoreClient && !!(accountAddress || resolvedAddress);
|
|
25536
|
+
return useQuery({
|
|
25537
|
+
...params.query,
|
|
25538
|
+
queryKey: symmKeys.portfolio({
|
|
25539
|
+
accountAddress,
|
|
25540
|
+
address: resolvedAddress,
|
|
25541
|
+
chainId
|
|
25542
|
+
}),
|
|
25543
|
+
queryFn: () => {
|
|
25544
|
+
const request = {
|
|
25545
|
+
accountAddress,
|
|
25546
|
+
address: resolvedAddress,
|
|
25547
|
+
chainId
|
|
25548
|
+
};
|
|
25549
|
+
return symmCoreClient.portfolio.getMetrics(request);
|
|
25550
|
+
},
|
|
25551
|
+
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25552
|
+
});
|
|
25553
|
+
}
|
|
25554
|
+
function useResolvedNotificationsParams(params) {
|
|
25555
|
+
const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
|
|
25556
|
+
const chainId = params.chainId ?? ctxChainId;
|
|
25557
|
+
return {
|
|
25558
|
+
symmCoreClient,
|
|
25559
|
+
chainId,
|
|
25560
|
+
userAddress: params.userAddress,
|
|
25561
|
+
query: params.query
|
|
25562
|
+
};
|
|
25563
|
+
}
|
|
25564
|
+
function useSymmNotificationsQuery(params) {
|
|
25565
|
+
const { symmCoreClient, chainId, userAddress, query } = useResolvedNotificationsParams(params);
|
|
25566
|
+
const internalEnabled = !!symmCoreClient && !!userAddress;
|
|
25567
|
+
return useQuery({
|
|
25568
|
+
...query,
|
|
25569
|
+
queryKey: symmKeys.notifications(userAddress, chainId),
|
|
25570
|
+
queryFn: () => symmCoreClient.notifications.list({
|
|
25571
|
+
userAddress,
|
|
25572
|
+
chainId
|
|
25573
|
+
}),
|
|
25574
|
+
enabled: internalEnabled && (query?.enabled ?? true)
|
|
25575
|
+
});
|
|
25576
|
+
}
|
|
25577
|
+
function useSymmUnreadCountQuery(params) {
|
|
25578
|
+
const { symmCoreClient, chainId, userAddress, query } = useResolvedNotificationsParams(params);
|
|
25579
|
+
const internalEnabled = !!symmCoreClient && !!userAddress;
|
|
25580
|
+
return useQuery({
|
|
25581
|
+
...query,
|
|
25582
|
+
queryKey: symmKeys.unreadCount(userAddress, chainId),
|
|
25583
|
+
queryFn: () => symmCoreClient.notifications.getUnreadCount({
|
|
25584
|
+
userAddress,
|
|
25585
|
+
chainId
|
|
25586
|
+
}),
|
|
25587
|
+
enabled: internalEnabled && (query?.enabled ?? true)
|
|
25588
|
+
});
|
|
25589
|
+
}
|
|
25590
|
+
function useSymmMarkReadNotificationMutation(params, options) {
|
|
25591
|
+
const { symmCoreClient, chainId, userAddress } = useResolvedNotificationsParams(params);
|
|
25592
|
+
const queryClient = useQueryClient();
|
|
25593
|
+
return useMutation({
|
|
25594
|
+
...withSymmMutationConfig(options?.mutation, {
|
|
25595
|
+
onSuccess: () => {
|
|
25596
|
+
queryClient.invalidateQueries({
|
|
25597
|
+
queryKey: symmKeys.notifications(userAddress, chainId)
|
|
25598
|
+
});
|
|
25599
|
+
queryClient.invalidateQueries({
|
|
25600
|
+
queryKey: symmKeys.unreadCount(userAddress, chainId)
|
|
25601
|
+
});
|
|
25602
|
+
}
|
|
25603
|
+
}),
|
|
25604
|
+
mutationFn: async ({ id, timestamp }) => {
|
|
25605
|
+
if (!symmCoreClient || !userAddress) {
|
|
25606
|
+
throw new Error("symm-core client not available");
|
|
25698
25607
|
}
|
|
25608
|
+
return symmCoreClient.notifications.markRead({
|
|
25609
|
+
id,
|
|
25610
|
+
timestamp,
|
|
25611
|
+
userAddress,
|
|
25612
|
+
chainId
|
|
25613
|
+
});
|
|
25699
25614
|
}
|
|
25700
|
-
}
|
|
25701
|
-
|
|
25702
|
-
|
|
25615
|
+
});
|
|
25616
|
+
}
|
|
25617
|
+
function useSymmPendingIds(params) {
|
|
25618
|
+
const { symmCoreClient, chainId: ctxChainId } = useSymmContext();
|
|
25619
|
+
const { accountAddress } = params;
|
|
25620
|
+
const chainId = params.chainId ?? ctxChainId;
|
|
25621
|
+
const internalEnabled = !!symmCoreClient && !!accountAddress;
|
|
25622
|
+
return useQuery({
|
|
25623
|
+
...params.query,
|
|
25624
|
+
queryKey: symmKeys.pendingIds(accountAddress, chainId),
|
|
25625
|
+
queryFn: () => symmCoreClient.positions.getPendingIds({
|
|
25626
|
+
address: accountAddress,
|
|
25627
|
+
chainId
|
|
25628
|
+
}),
|
|
25629
|
+
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25630
|
+
});
|
|
25631
|
+
}
|
|
25632
|
+
function useSymmPendingInstantOpens(params) {
|
|
25633
|
+
const {
|
|
25634
|
+
symmCoreClient,
|
|
25635
|
+
chainId: ctxChainId
|
|
25636
|
+
} = useSymmContext();
|
|
25637
|
+
const { accountAddress, authToken: providedAuthToken } = params;
|
|
25638
|
+
const chainId = params.chainId ?? ctxChainId;
|
|
25639
|
+
const internalEnabled = !!symmCoreClient && !!accountAddress;
|
|
25640
|
+
return useQuery({
|
|
25641
|
+
...params.query,
|
|
25642
|
+
queryKey: symmKeys.pendingInstantOpens(accountAddress, chainId),
|
|
25643
|
+
queryFn: async () => {
|
|
25644
|
+
const authToken = providedAuthToken ?? useSymmAuthStore.getState().getToken(accountAddress, chainId);
|
|
25645
|
+
if (!authToken) {
|
|
25646
|
+
throw new Error("failed to acquire auth token for pending instant opens");
|
|
25647
|
+
}
|
|
25648
|
+
return symmCoreClient.positions.getPendingInstantOpens({
|
|
25649
|
+
accountAddress,
|
|
25650
|
+
chainId,
|
|
25651
|
+
authToken
|
|
25652
|
+
});
|
|
25653
|
+
},
|
|
25654
|
+
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25655
|
+
});
|
|
25656
|
+
}
|
|
25657
|
+
function useSymmTwapOrder(params) {
|
|
25658
|
+
const { symmCoreClient } = useSymmContext();
|
|
25659
|
+
const { orderId } = params;
|
|
25660
|
+
const internalEnabled = !!symmCoreClient && !!orderId;
|
|
25661
|
+
return useQuery({
|
|
25662
|
+
...params.query,
|
|
25663
|
+
queryKey: symmKeys.twapOrder(orderId),
|
|
25664
|
+
queryFn: () => symmCoreClient.orders.getTwapOrder(orderId),
|
|
25665
|
+
enabled: internalEnabled && (params.query?.enabled ?? true)
|
|
25666
|
+
});
|
|
25667
|
+
}
|
|
25668
|
+
var useSymmWsStore = create((set) => ({
|
|
25669
|
+
isConnected: false,
|
|
25670
|
+
setConnected: (isConnected) => set({ isConnected })
|
|
25671
|
+
}));
|
|
25672
|
+
|
|
25673
|
+
// src/react/hooks/use-symm-ws.ts
|
|
25674
|
+
function asUnsubscribeFn(value) {
|
|
25675
|
+
return typeof value === "function" ? value : null;
|
|
25676
|
+
}
|
|
25677
|
+
function useSymmWs(params = {}) {
|
|
25678
|
+
const {
|
|
25679
|
+
symmCoreClient: ctxClient,
|
|
25680
|
+
address: ctxAddress,
|
|
25681
|
+
chainId: ctxChainId
|
|
25682
|
+
} = useSymmContext();
|
|
25683
|
+
const queryClient = useQueryClient();
|
|
25684
|
+
const isConnected = useSymmWsStore((state) => state.isConnected);
|
|
25685
|
+
const setConnected = useSymmWsStore((state) => state.setConnected);
|
|
25686
|
+
const symmCoreClient = params.symmCoreClient ?? ctxClient;
|
|
25687
|
+
const accountAddress = params.accountAddress ?? ctxAddress;
|
|
25688
|
+
const chainId = params.chainId ?? ctxChainId;
|
|
25689
|
+
useEffect(() => {
|
|
25690
|
+
if (!symmCoreClient || !accountAddress) {
|
|
25691
|
+
setConnected(false);
|
|
25703
25692
|
return;
|
|
25704
25693
|
}
|
|
25705
|
-
|
|
25706
|
-
|
|
25707
|
-
|
|
25708
|
-
|
|
25709
|
-
|
|
25710
|
-
|
|
25711
|
-
|
|
25712
|
-
|
|
25713
|
-
|
|
25714
|
-
|
|
25715
|
-
|
|
25716
|
-
}
|
|
25717
|
-
|
|
25718
|
-
|
|
25719
|
-
|
|
25720
|
-
|
|
25721
|
-
|
|
25722
|
-
|
|
25723
|
-
|
|
25724
|
-
|
|
25725
|
-
|
|
25726
|
-
|
|
25727
|
-
|
|
25728
|
-
|
|
25729
|
-
|
|
25730
|
-
|
|
25731
|
-
|
|
25694
|
+
const ws = symmCoreClient.ws;
|
|
25695
|
+
const addr = accountAddress;
|
|
25696
|
+
const unsubscribers = [];
|
|
25697
|
+
const removeOnConnect = ws.onConnect(() => setConnected(true));
|
|
25698
|
+
const removeOnDisconnect = ws.onDisconnect(() => setConnected(false));
|
|
25699
|
+
unsubscribers.push(removeOnConnect, removeOnDisconnect);
|
|
25700
|
+
const positionsUnsub = asUnsubscribeFn(
|
|
25701
|
+
ws.subscribeToPositions(addr, chainId, () => {
|
|
25702
|
+
queryClient.invalidateQueries({
|
|
25703
|
+
queryKey: ["symm", "positions"]
|
|
25704
|
+
});
|
|
25705
|
+
})
|
|
25706
|
+
);
|
|
25707
|
+
if (positionsUnsub) unsubscribers.push(positionsUnsub);
|
|
25708
|
+
const openOrdersUnsub = asUnsubscribeFn(
|
|
25709
|
+
ws.subscribeToOpenOrders(addr, chainId, () => {
|
|
25710
|
+
queryClient.invalidateQueries({
|
|
25711
|
+
queryKey: ["symm", "openOrders"]
|
|
25712
|
+
});
|
|
25713
|
+
})
|
|
25714
|
+
);
|
|
25715
|
+
if (openOrdersUnsub) unsubscribers.push(openOrdersUnsub);
|
|
25716
|
+
const tradesUnsub = asUnsubscribeFn(
|
|
25717
|
+
ws.subscribeToTrades(addr, chainId, () => {
|
|
25718
|
+
queryClient.invalidateQueries({
|
|
25719
|
+
queryKey: ["symm", "tradeHistory"]
|
|
25720
|
+
});
|
|
25721
|
+
})
|
|
25722
|
+
);
|
|
25723
|
+
if (tradesUnsub) unsubscribers.push(tradesUnsub);
|
|
25724
|
+
const accountSummaryUnsub = asUnsubscribeFn(
|
|
25725
|
+
ws.subscribeToAccountSummary(addr, chainId, () => {
|
|
25726
|
+
queryClient.invalidateQueries({
|
|
25727
|
+
queryKey: symmKeys.balances(accountAddress, chainId)
|
|
25728
|
+
});
|
|
25729
|
+
queryClient.invalidateQueries({
|
|
25730
|
+
queryKey: symmKeys.accountSummary(accountAddress, chainId)
|
|
25731
|
+
});
|
|
25732
|
+
})
|
|
25733
|
+
);
|
|
25734
|
+
if (accountSummaryUnsub) unsubscribers.push(accountSummaryUnsub);
|
|
25735
|
+
const notificationsUnsub = asUnsubscribeFn(
|
|
25736
|
+
ws.subscribeToNotifications(addr, chainId, () => {
|
|
25737
|
+
queryClient.invalidateQueries({
|
|
25738
|
+
queryKey: symmKeys.notifications(accountAddress, chainId)
|
|
25739
|
+
});
|
|
25740
|
+
queryClient.invalidateQueries({
|
|
25741
|
+
queryKey: symmKeys.unreadCount(accountAddress, chainId)
|
|
25742
|
+
});
|
|
25743
|
+
})
|
|
25744
|
+
);
|
|
25745
|
+
if (notificationsUnsub) unsubscribers.push(notificationsUnsub);
|
|
25746
|
+
const tpslUnsub = asUnsubscribeFn(
|
|
25747
|
+
ws.subscribeToTpsl(addr, chainId, () => {
|
|
25748
|
+
queryClient.invalidateQueries({ queryKey: ["symm", "tpslOrders"] });
|
|
25749
|
+
queryClient.invalidateQueries({ queryKey: ["symm", "openOrders"] });
|
|
25750
|
+
})
|
|
25751
|
+
);
|
|
25752
|
+
if (tpslUnsub) unsubscribers.push(tpslUnsub);
|
|
25753
|
+
const twapUnsub = asUnsubscribeFn(
|
|
25754
|
+
ws.subscribeToTwapOrders(addr, chainId, () => {
|
|
25755
|
+
queryClient.invalidateQueries({ queryKey: ["symm", "twapOrders"] });
|
|
25756
|
+
queryClient.invalidateQueries({ queryKey: ["symm", "openOrders"] });
|
|
25757
|
+
})
|
|
25758
|
+
);
|
|
25759
|
+
if (twapUnsub) unsubscribers.push(twapUnsub);
|
|
25760
|
+
const triggerOrdersUnsub = asUnsubscribeFn(
|
|
25761
|
+
ws.subscribeToTriggerOrders(addr, chainId, () => {
|
|
25762
|
+
queryClient.invalidateQueries({ queryKey: ["symm", "triggerOrders"] });
|
|
25763
|
+
queryClient.invalidateQueries({ queryKey: ["symm", "openOrders"] });
|
|
25764
|
+
})
|
|
25765
|
+
);
|
|
25766
|
+
if (triggerOrdersUnsub) unsubscribers.push(triggerOrdersUnsub);
|
|
25767
|
+
const executionsUnsub = asUnsubscribeFn(
|
|
25768
|
+
ws.subscribeToExecutions(addr, chainId, () => {
|
|
25769
|
+
queryClient.invalidateQueries({
|
|
25770
|
+
queryKey: ["symm", "positions"]
|
|
25771
|
+
});
|
|
25772
|
+
queryClient.invalidateQueries({
|
|
25773
|
+
queryKey: ["symm", "portfolio"]
|
|
25774
|
+
});
|
|
25775
|
+
})
|
|
25776
|
+
);
|
|
25777
|
+
if (executionsUnsub) unsubscribers.push(executionsUnsub);
|
|
25778
|
+
return () => {
|
|
25779
|
+
unsubscribers.forEach((unsubscribe) => unsubscribe());
|
|
25732
25780
|
};
|
|
25733
|
-
|
|
25781
|
+
}, [symmCoreClient, accountAddress, chainId, queryClient, setConnected]);
|
|
25782
|
+
return { isConnected };
|
|
25783
|
+
}
|
|
25784
|
+
var STABLE_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USD", "USDT", "USDE", "USDH", "USDT0"]);
|
|
25785
|
+
function useSymmChartSelection(input) {
|
|
25786
|
+
const {
|
|
25787
|
+
longSymbol,
|
|
25788
|
+
shortSymbol,
|
|
25789
|
+
longWeight = 100,
|
|
25790
|
+
shortWeight = 100,
|
|
25791
|
+
longTokens: explicitLongTokens,
|
|
25792
|
+
shortTokens: explicitShortTokens
|
|
25793
|
+
} = input;
|
|
25794
|
+
return useMemo(() => {
|
|
25795
|
+
const longTokens = explicitLongTokens?.length ? explicitLongTokens : longSymbol ? [{ symbol: longSymbol, weight: longWeight }] : [];
|
|
25796
|
+
const shortTokens = explicitShortTokens?.length ? explicitShortTokens : shortSymbol ? [{ symbol: shortSymbol, weight: shortWeight }] : [];
|
|
25797
|
+
const selectedSymbols = [
|
|
25798
|
+
...longTokens.map((t) => t.symbol),
|
|
25799
|
+
...shortTokens.map((t) => t.symbol)
|
|
25800
|
+
];
|
|
25801
|
+
const uniqueSelectedSymbols = Array.from(new Set(selectedSymbols));
|
|
25802
|
+
const longPrimarySymbol = longTokens[0]?.symbol ?? null;
|
|
25803
|
+
const shortPrimarySymbol = shortTokens[0]?.symbol ?? null;
|
|
25804
|
+
const longIsStable = longPrimarySymbol ? STABLE_SYMBOLS.has(longPrimarySymbol.toUpperCase()) : true;
|
|
25805
|
+
const shortIsStable = shortPrimarySymbol ? STABLE_SYMBOLS.has(shortPrimarySymbol.toUpperCase()) : true;
|
|
25806
|
+
let isSingleSided = false;
|
|
25807
|
+
let activeSide = null;
|
|
25808
|
+
let activeTokenSymbol;
|
|
25809
|
+
if (longTokens.length > 0 && !longIsStable && (shortTokens.length === 0 || shortIsStable)) {
|
|
25810
|
+
isSingleSided = true;
|
|
25811
|
+
activeSide = "long";
|
|
25812
|
+
activeTokenSymbol = longPrimarySymbol ?? void 0;
|
|
25813
|
+
} else if (shortTokens.length > 0 && !shortIsStable && (longTokens.length === 0 || longIsStable)) {
|
|
25814
|
+
isSingleSided = true;
|
|
25815
|
+
activeSide = "short";
|
|
25816
|
+
activeTokenSymbol = shortPrimarySymbol ?? void 0;
|
|
25817
|
+
}
|
|
25818
|
+
const longLabel = longTokens.map((token) => token.symbol).join("+") || "USDC";
|
|
25819
|
+
const shortLabel = shortTokens.map((token) => token.symbol).join("+") || "USDC";
|
|
25820
|
+
const pairLabel = `${longLabel}/${shortLabel}`;
|
|
25821
|
+
return {
|
|
25822
|
+
longTokens,
|
|
25823
|
+
shortTokens,
|
|
25824
|
+
isSingleSided,
|
|
25825
|
+
activeSide,
|
|
25826
|
+
activeTokenSymbol,
|
|
25827
|
+
pairLabel,
|
|
25828
|
+
selectedSymbols: uniqueSelectedSymbols
|
|
25734
25829
|
};
|
|
25830
|
+
}, [
|
|
25831
|
+
explicitLongTokens,
|
|
25832
|
+
explicitShortTokens,
|
|
25833
|
+
longSymbol,
|
|
25834
|
+
shortSymbol,
|
|
25835
|
+
longWeight,
|
|
25836
|
+
shortWeight
|
|
25837
|
+
]);
|
|
25838
|
+
}
|
|
25839
|
+
|
|
25840
|
+
// src/utils/chart-metrics.ts
|
|
25841
|
+
function getPositiveValue(metadata, field) {
|
|
25842
|
+
const value = metadata?.[field];
|
|
25843
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
25844
|
+
return null;
|
|
25735
25845
|
}
|
|
25736
|
-
|
|
25737
|
-
|
|
25738
|
-
|
|
25739
|
-
|
|
25740
|
-
|
|
25741
|
-
|
|
25742
|
-
|
|
25743
|
-
|
|
25846
|
+
return value;
|
|
25847
|
+
}
|
|
25848
|
+
function computeWeightedProduct(tokens, metadataMap, field, invert = false) {
|
|
25849
|
+
let product = 1;
|
|
25850
|
+
let hasToken = false;
|
|
25851
|
+
for (const token of tokens) {
|
|
25852
|
+
if (!(token.weight > 0)) {
|
|
25853
|
+
continue;
|
|
25744
25854
|
}
|
|
25745
|
-
|
|
25746
|
-
|
|
25747
|
-
|
|
25748
|
-
if (!sub) return;
|
|
25749
|
-
sub.callbacks.forEach((cb) => {
|
|
25750
|
-
try {
|
|
25751
|
-
cb(data);
|
|
25752
|
-
} catch {
|
|
25753
|
-
}
|
|
25754
|
-
});
|
|
25755
|
-
}
|
|
25756
|
-
sendSubscribe(streams) {
|
|
25757
|
-
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
25758
|
-
this.pendingSubscribes.push(...streams);
|
|
25759
|
-
return;
|
|
25855
|
+
const price = getPositiveValue(metadataMap[token.symbol], field);
|
|
25856
|
+
if (price === null) {
|
|
25857
|
+
return null;
|
|
25760
25858
|
}
|
|
25761
|
-
|
|
25762
|
-
|
|
25763
|
-
|
|
25764
|
-
id: Date.now()
|
|
25765
|
-
}));
|
|
25859
|
+
hasToken = true;
|
|
25860
|
+
const exponent = invert ? -(token.weight / 100) : token.weight / 100;
|
|
25861
|
+
product *= Math.pow(price, exponent);
|
|
25766
25862
|
}
|
|
25767
|
-
|
|
25768
|
-
|
|
25769
|
-
|
|
25770
|
-
|
|
25771
|
-
|
|
25772
|
-
|
|
25773
|
-
|
|
25774
|
-
|
|
25775
|
-
|
|
25776
|
-
|
|
25777
|
-
|
|
25778
|
-
|
|
25863
|
+
return hasToken ? product : 1;
|
|
25864
|
+
}
|
|
25865
|
+
function computePriceRatio({
|
|
25866
|
+
longTokens,
|
|
25867
|
+
shortTokens,
|
|
25868
|
+
longTokensMetadata,
|
|
25869
|
+
shortTokensMetadata
|
|
25870
|
+
}) {
|
|
25871
|
+
const firstLong = longTokens[0];
|
|
25872
|
+
const firstShort = shortTokens[0];
|
|
25873
|
+
const longPrice = firstLong ? getPositiveValue(longTokensMetadata[firstLong.symbol], "currentPrice") : null;
|
|
25874
|
+
const shortPrice = firstShort ? getPositiveValue(shortTokensMetadata[firstShort.symbol], "currentPrice") : null;
|
|
25875
|
+
if (longPrice !== null && shortPrice !== null) {
|
|
25876
|
+
return longPrice / shortPrice;
|
|
25779
25877
|
}
|
|
25780
|
-
|
|
25781
|
-
|
|
25782
|
-
if (this.streams.size === 0) return;
|
|
25783
|
-
const delay = RECONNECT_DELAYS[Math.min(this.reconnectAttempt, RECONNECT_DELAYS.length - 1)];
|
|
25784
|
-
this.reconnectAttempt++;
|
|
25785
|
-
this.reconnectTimer = setTimeout(() => {
|
|
25786
|
-
this.reconnectTimer = null;
|
|
25787
|
-
this.connect();
|
|
25788
|
-
}, delay);
|
|
25878
|
+
if (longPrice !== null && shortTokens.length === 0) {
|
|
25879
|
+
return longPrice;
|
|
25789
25880
|
}
|
|
25790
|
-
|
|
25791
|
-
|
|
25792
|
-
function getBinanceWsManager() {
|
|
25793
|
-
if (!_instance) {
|
|
25794
|
-
_instance = new BinanceWsManager();
|
|
25881
|
+
if (shortPrice !== null && longTokens.length === 0) {
|
|
25882
|
+
return shortPrice;
|
|
25795
25883
|
}
|
|
25796
|
-
return
|
|
25884
|
+
return null;
|
|
25797
25885
|
}
|
|
25798
|
-
|
|
25799
|
-
|
|
25800
|
-
|
|
25801
|
-
|
|
25802
|
-
|
|
25803
|
-
|
|
25804
|
-
|
|
25886
|
+
function computePriceRatio24h({
|
|
25887
|
+
longTokens,
|
|
25888
|
+
shortTokens,
|
|
25889
|
+
longTokensMetadata,
|
|
25890
|
+
shortTokensMetadata
|
|
25891
|
+
}) {
|
|
25892
|
+
const firstLong = longTokens[0];
|
|
25893
|
+
const firstShort = shortTokens[0];
|
|
25894
|
+
const longPrice = firstLong ? getPositiveValue(longTokensMetadata[firstLong.symbol], "prevDayPrice") : null;
|
|
25895
|
+
const shortPrice = firstShort ? getPositiveValue(shortTokensMetadata[firstShort.symbol], "prevDayPrice") : null;
|
|
25896
|
+
if (longPrice !== null && shortPrice !== null) {
|
|
25897
|
+
return longPrice / shortPrice;
|
|
25898
|
+
}
|
|
25899
|
+
if (longPrice !== null && shortTokens.length === 0) {
|
|
25900
|
+
return longPrice;
|
|
25901
|
+
}
|
|
25902
|
+
if (shortPrice !== null && longTokens.length === 0) {
|
|
25903
|
+
return shortPrice;
|
|
25904
|
+
}
|
|
25905
|
+
return null;
|
|
25805
25906
|
}
|
|
25806
|
-
function
|
|
25807
|
-
|
|
25907
|
+
function computeWeightedRatio({
|
|
25908
|
+
longTokens,
|
|
25909
|
+
shortTokens,
|
|
25910
|
+
longTokensMetadata,
|
|
25911
|
+
shortTokensMetadata
|
|
25912
|
+
}) {
|
|
25913
|
+
const longProduct = computeWeightedProduct(
|
|
25914
|
+
longTokens,
|
|
25915
|
+
longTokensMetadata,
|
|
25916
|
+
"currentPrice"
|
|
25917
|
+
);
|
|
25918
|
+
const shortProduct = computeWeightedProduct(
|
|
25919
|
+
shortTokens,
|
|
25920
|
+
shortTokensMetadata,
|
|
25921
|
+
"currentPrice",
|
|
25922
|
+
true
|
|
25923
|
+
);
|
|
25924
|
+
if (longProduct === null || shortProduct === null) {
|
|
25925
|
+
return null;
|
|
25926
|
+
}
|
|
25927
|
+
return longProduct * shortProduct;
|
|
25808
25928
|
}
|
|
25809
|
-
function
|
|
25810
|
-
|
|
25929
|
+
function computeWeightedRatio24h({
|
|
25930
|
+
longTokens,
|
|
25931
|
+
shortTokens,
|
|
25932
|
+
longTokensMetadata,
|
|
25933
|
+
shortTokensMetadata
|
|
25934
|
+
}) {
|
|
25935
|
+
const longProduct = computeWeightedProduct(
|
|
25936
|
+
longTokens,
|
|
25937
|
+
longTokensMetadata,
|
|
25938
|
+
"prevDayPrice"
|
|
25939
|
+
);
|
|
25940
|
+
const shortProduct = computeWeightedProduct(
|
|
25941
|
+
shortTokens,
|
|
25942
|
+
shortTokensMetadata,
|
|
25943
|
+
"prevDayPrice",
|
|
25944
|
+
true
|
|
25945
|
+
);
|
|
25946
|
+
if (longProduct === null || shortProduct === null) {
|
|
25947
|
+
return null;
|
|
25948
|
+
}
|
|
25949
|
+
return longProduct * shortProduct;
|
|
25811
25950
|
}
|
|
25812
|
-
|
|
25813
|
-
|
|
25814
|
-
|
|
25815
|
-
|
|
25816
|
-
|
|
25817
|
-
|
|
25818
|
-
|
|
25819
|
-
|
|
25820
|
-
|
|
25821
|
-
if (
|
|
25822
|
-
|
|
25823
|
-
const unsubscribe = wsManager.subscribeMarkPrice(binanceSymbol, (data) => {
|
|
25824
|
-
const canonicalSymbol = normalizeBinanceSymbol(data.symbol);
|
|
25825
|
-
const mappedSymbols = streamSymbols.get(canonicalSymbol);
|
|
25826
|
-
if (!mappedSymbols || mappedSymbols.size === 0) return;
|
|
25827
|
-
set((state) => {
|
|
25828
|
-
const nextMarkPrices = { ...state.markPrices };
|
|
25829
|
-
mappedSymbols.forEach((mappedSymbol) => {
|
|
25830
|
-
nextMarkPrices[mappedSymbol] = data.markPrice;
|
|
25831
|
-
});
|
|
25832
|
-
return { markPrices: nextMarkPrices };
|
|
25833
|
-
});
|
|
25834
|
-
});
|
|
25835
|
-
streamUnsubs.set(binanceSymbol, unsubscribe);
|
|
25836
|
-
}
|
|
25837
|
-
},
|
|
25838
|
-
unsubscribeSymbol: (symmSymbol, rawBinanceSymbol) => {
|
|
25839
|
-
const binanceSymbol = normalizeBinanceSymbol(rawBinanceSymbol);
|
|
25840
|
-
const symbols = streamSymbols.get(binanceSymbol);
|
|
25841
|
-
if (symbols) {
|
|
25842
|
-
symbols.delete(symmSymbol);
|
|
25843
|
-
if (symbols.size === 0) {
|
|
25844
|
-
streamSymbols.delete(binanceSymbol);
|
|
25845
|
-
} else {
|
|
25846
|
-
streamSymbols.set(binanceSymbol, symbols);
|
|
25847
|
-
}
|
|
25951
|
+
function computeNetFundingSum({
|
|
25952
|
+
longTokens,
|
|
25953
|
+
shortTokens,
|
|
25954
|
+
longTokensMetadata,
|
|
25955
|
+
shortTokensMetadata
|
|
25956
|
+
}) {
|
|
25957
|
+
let funding = 0;
|
|
25958
|
+
for (const token of longTokens) {
|
|
25959
|
+
const value = longTokensMetadata[token.symbol]?.netFunding;
|
|
25960
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
25961
|
+
funding += value;
|
|
25848
25962
|
}
|
|
25849
|
-
|
|
25850
|
-
|
|
25851
|
-
|
|
25852
|
-
|
|
25853
|
-
|
|
25854
|
-
refCounts.delete(binanceSymbol);
|
|
25855
|
-
} else {
|
|
25856
|
-
refCounts.set(binanceSymbol, nextRefCount);
|
|
25963
|
+
}
|
|
25964
|
+
for (const token of shortTokens) {
|
|
25965
|
+
const value = shortTokensMetadata[token.symbol]?.netFunding;
|
|
25966
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
25967
|
+
funding += value;
|
|
25857
25968
|
}
|
|
25858
|
-
set((state) => {
|
|
25859
|
-
if (state.markPrices[symmSymbol] == null) return state;
|
|
25860
|
-
const nextMarkPrices = { ...state.markPrices };
|
|
25861
|
-
delete nextMarkPrices[symmSymbol];
|
|
25862
|
-
return { markPrices: nextMarkPrices };
|
|
25863
|
-
});
|
|
25864
25969
|
}
|
|
25865
|
-
|
|
25970
|
+
return funding;
|
|
25971
|
+
}
|
|
25866
25972
|
|
|
25867
25973
|
// src/react/hooks/use-symm-token-selection-metadata.ts
|
|
25868
|
-
async function
|
|
25974
|
+
async function fetchTickerSnapshot2(symbol) {
|
|
25869
25975
|
const resolution = resolveBinanceSymbol(symbol);
|
|
25870
25976
|
if (!resolution.binanceSymbol) return null;
|
|
25871
25977
|
const ticker = await fetch24hrTicker(resolution.binanceSymbol);
|
|
@@ -25921,7 +26027,7 @@ function useSymmTokenSelectionMetadata(selection, options = {}) {
|
|
|
25921
26027
|
const results = await Promise.all(
|
|
25922
26028
|
allSymbols.map(async ({ symbol }) => ({
|
|
25923
26029
|
symbol,
|
|
25924
|
-
ticker: await
|
|
26030
|
+
ticker: await fetchTickerSnapshot2(symbol)
|
|
25925
26031
|
}))
|
|
25926
26032
|
);
|
|
25927
26033
|
const tickerSnapshots = {};
|
|
@@ -26394,6 +26500,6 @@ function getSymmErrorMessage(error) {
|
|
|
26394
26500
|
return "An unexpected error occurred.";
|
|
26395
26501
|
}
|
|
26396
26502
|
|
|
26397
|
-
export { SymmProvider, getSymmErrorMessage, symmKeys, useBinanceMarkPriceStore, useSymmAccountData, useSymmAccountSummary, useSymmAccountsApi, useSymmAccountsLength, useSymmAccountsQuery, useSymmAccountsWithPositions, useSymmAllocateCollateralMutation, useSymmApprovalQuery, useSymmApproveMutation, useSymmAuth, useSymmAuthStore, useSymmAvailableMargin, useSymmBalances, useSymmCancelClose, useSymmCancelOpenMutation, useSymmCancelTpslMutation, useSymmCancelTwapOrderMutation, useSymmChartCandles, useSymmChartSelection, useSymmClearTriggerConfigMutation, useSymmCloseAllPositionsMutation, useSymmCloseOrder, useSymmClosePositionMutation, useSymmContext, useSymmCoreClient, useSymmCreateAccountMutation, useSymmDeallocateCollateralMutation, useSymmDelegation, useSymmDepositAndAllocateMutation, useSymmDepositMutation, useSymmEditAccountNameMutation, useSymmFunding, useSymmFundingHistory, useSymmFundingPayments, useSymmHedgerMarketById, useSymmHedgerMarketBySymbol, useSymmHedgerMarkets, useSymmInstantTradeEnsureReadyMutation, useSymmInstantTradeExecuteMutation, useSymmInternalTransferCollateralMutation, useSymmLockedParams, useSymmMarkReadNotificationMutation, useSymmMarkets, useSymmNotificationsQuery, useSymmOpenBasketMutation, useSymmOpenOrders, useSymmPendingIds, useSymmPendingInstantOpens, useSymmPerformanceOverlays, useSymmPortfolio, useSymmPositions, useSymmSetTpslMutation, useSymmSetTriggerConfigMutation, useSymmSignTermsMutation, useSymmSignatureQuery, useSymmTokenSelectionMetadata, useSymmTpslOrders, useSymmTradeHistory, useSymmTriggerConfigQuery, useSymmTriggerOrders, useSymmTwapOrder, useSymmTwapOrdersQuery, useSymmUnreadCountQuery, useSymmUpdatePositionMutation, useSymmWithdraw, useSymmWs, useSymmWsStore };
|
|
26503
|
+
export { SymmProvider, getSymmErrorMessage, symmKeys, useBinanceMarkPriceStore, useSymmAccountData, useSymmAccountSummary, useSymmAccountsApi, useSymmAccountsLength, useSymmAccountsQuery, useSymmAccountsWithPositions, useSymmAllocateCollateralMutation, useSymmApprovalQuery, useSymmApproveMutation, useSymmAuth, useSymmAuthStore, useSymmAvailableMargin, useSymmBalances, useSymmCancelClose, useSymmCancelOpenMutation, useSymmCancelTpslMutation, useSymmCancelTwapOrderMutation, useSymmChartCandles, useSymmChartSelection, useSymmClearTriggerConfigMutation, useSymmCloseAllPositionsMutation, useSymmCloseOrder, useSymmClosePositionMutation, useSymmContext, useSymmCoreClient, useSymmCreateAccountMutation, useSymmDeallocateCollateralMutation, useSymmDelegation, useSymmDepositAndAllocateMutation, useSymmDepositMutation, useSymmEditAccountNameMutation, useSymmFunding, useSymmFundingHistory, useSymmFundingPayments, useSymmHedgerMarketById, useSymmHedgerMarketBySymbol, useSymmHedgerMarkets, useSymmInstantTradeEnsureReadyMutation, useSymmInstantTradeExecuteMutation, useSymmInternalTransferCollateralMutation, useSymmLockedParams, useSymmMarkReadNotificationMutation, useSymmMarkets, useSymmNotificationsQuery, useSymmOpenBasketMutation, useSymmOpenOrders, useSymmPendingIds, useSymmPendingInstantOpens, useSymmPerformanceOverlays, useSymmPortfolio, useSymmPositions, useSymmSetTpslMutation, useSymmSetTriggerConfigMutation, useSymmSignTermsMutation, useSymmSignatureQuery, useSymmTokenSelectionMarkets, useSymmTokenSelectionMetadata, useSymmTpslOrders, useSymmTradeHistory, useSymmTriggerConfigQuery, useSymmTriggerOrders, useSymmTwapOrder, useSymmTwapOrdersQuery, useSymmUnreadCountQuery, useSymmUpdatePositionMutation, useSymmWithdraw, useSymmWs, useSymmWsStore };
|
|
26398
26504
|
//# sourceMappingURL=index.mjs.map
|
|
26399
26505
|
//# sourceMappingURL=index.mjs.map
|