@pear-protocol/symmio-client 0.3.3 → 0.3.6

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.
@@ -2,7 +2,7 @@
2
2
  import { createContext, useContext, useMemo, useCallback, useRef, useEffect } from 'react';
3
3
  import { createSymmSDK, isAuthExpiredError, isNetworkError, isInsufficientMarginError, isRateLimitedError, isTimeoutError } from '@pear-protocol/symm-core';
4
4
  import { create } from 'zustand';
5
- import { useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
5
+ import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
6
6
  import { jsx } from 'react/jsx-runtime';
7
7
  import { SiweMessage } from 'siwe';
8
8
  import { isAddress, encodeFunctionData } from 'viem';
@@ -21,9 +21,7 @@ var SYMBOL_OVERRIDES = {
21
21
  // Add overrides here as needed for SYMM markets that don't map 1:1 to Binance
22
22
  // e.g., 'SOME_SYMM_SYMBOL': 'BINANCE_SYMBOL',
23
23
  };
24
- var UNSUPPORTED_SYMBOLS = /* @__PURE__ */ new Set([
25
- // Add symbols here that have no Binance equivalent
26
- ]);
24
+ var UNSUPPORTED_SYMBOLS = /* @__PURE__ */ new Set([]);
27
25
  function resolveBinanceSymbol(symmSymbol) {
28
26
  if (!symmSymbol || !symmSymbol.trim()) {
29
27
  return {
@@ -904,27 +902,116 @@ async function fetchAccessTokenEntry(walletClient, signerAddress, accountAddress
904
902
  writeStoredToken(accountAddress, chainId, cachedToken);
905
903
  return cachedToken;
906
904
  }
905
+ function authStoreKey(accountAddress, chainId, signerAddress) {
906
+ return `${accountAddress}:${chainId}:${signerAddress ?? ""}`;
907
+ }
908
+ function getEntryFromSnapshot(state, accountAddress, chainId, signerAddress) {
909
+ const signerScoped = state.entries[authStoreKey(accountAddress, chainId, signerAddress)];
910
+ if (signerScoped) {
911
+ return signerScoped;
912
+ }
913
+ return state.entries[authStoreKey(accountAddress, chainId)] ?? null;
914
+ }
915
+ function getStatusFromSnapshot(state, accountAddress, chainId, signerAddress) {
916
+ const signerScoped = state.status[authStoreKey(accountAddress, chainId, signerAddress)];
917
+ if (signerScoped) {
918
+ return signerScoped;
919
+ }
920
+ return state.status[authStoreKey(accountAddress, chainId)] ?? {
921
+ error: null,
922
+ isLoading: false
923
+ };
924
+ }
925
+ var useSymmAuthStore = create((set) => ({
926
+ entries: {},
927
+ status: {},
928
+ setEntry: (accountAddress, chainId, signerAddress, entry) => set((state) => ({
929
+ entries: {
930
+ ...state.entries,
931
+ [authStoreKey(accountAddress, chainId, signerAddress)]: entry
932
+ },
933
+ status: {
934
+ ...state.status,
935
+ [authStoreKey(accountAddress, chainId, signerAddress)]: {
936
+ error: null,
937
+ isLoading: false
938
+ }
939
+ }
940
+ })),
941
+ clearEntry: (accountAddress, chainId, signerAddress) => set((state) => {
942
+ const nextEntries = { ...state.entries };
943
+ const nextStatus = { ...state.status };
944
+ delete nextEntries[authStoreKey(accountAddress, chainId, signerAddress)];
945
+ delete nextStatus[authStoreKey(accountAddress, chainId, signerAddress)];
946
+ return {
947
+ entries: nextEntries,
948
+ status: nextStatus
949
+ };
950
+ }),
951
+ setStatus: (accountAddress, chainId, signerAddress, status) => set((state) => ({
952
+ status: {
953
+ ...state.status,
954
+ [authStoreKey(accountAddress, chainId, signerAddress)]: {
955
+ error: null,
956
+ isLoading: false,
957
+ ...state.status[authStoreKey(accountAddress, chainId, signerAddress)],
958
+ ...status
959
+ }
960
+ }
961
+ })),
962
+ reset: () => set({
963
+ entries: {},
964
+ status: {}
965
+ })
966
+ }));
967
+ function getAuthStoreEntry(accountAddress, chainId, signerAddress) {
968
+ return getEntryFromSnapshot(
969
+ useSymmAuthStore.getState(),
970
+ accountAddress,
971
+ chainId,
972
+ signerAddress
973
+ );
974
+ }
975
+ function selectAuthStoreEntry(state, accountAddress, chainId, signerAddress) {
976
+ if (!accountAddress || chainId == null) {
977
+ return null;
978
+ }
979
+ return getEntryFromSnapshot(state, accountAddress, chainId, signerAddress);
980
+ }
981
+ function selectAuthStoreStatus(state, accountAddress, chainId, signerAddress) {
982
+ if (!accountAddress || chainId == null) {
983
+ return {
984
+ error: null,
985
+ isLoading: false
986
+ };
987
+ }
988
+ return getStatusFromSnapshot(state, accountAddress, chainId, signerAddress);
989
+ }
990
+ function setAuthStoreEntry(accountAddress, chainId, signerAddress, entry) {
991
+ useSymmAuthStore.getState().setEntry(accountAddress, chainId, signerAddress, entry);
992
+ }
993
+ function setAuthStoreStatus(accountAddress, chainId, signerAddress, status) {
994
+ useSymmAuthStore.getState().setStatus(accountAddress, chainId, signerAddress, status);
995
+ }
996
+ function clearAuthStoreEntry(accountAddress, chainId, signerAddress) {
997
+ useSymmAuthStore.getState().clearEntry(accountAddress, chainId, signerAddress);
998
+ }
907
999
 
908
1000
  // src/react/auth-cache.ts
909
- function getAuthQueryData(queryClient, accountAddress, chainId, signerAddress) {
910
- return queryClient.getQueryData(
911
- symmKeys.auth(accountAddress, chainId, signerAddress)
912
- ) ?? null;
1001
+ function getAuthQueryData(accountAddress, chainId, signerAddress) {
1002
+ return getAuthStoreEntry(accountAddress, chainId, signerAddress);
913
1003
  }
914
- function setAuthQueryData(queryClient, accountAddress, chainId, signerAddress, entry) {
915
- queryClient.setQueryData(symmKeys.auth(accountAddress, chainId, signerAddress), entry);
1004
+ function setAuthQueryData(accountAddress, chainId, signerAddress, entry) {
1005
+ setAuthStoreEntry(accountAddress, chainId, signerAddress, entry);
916
1006
  }
917
- function clearAuthQueryData(queryClient, accountAddress, chainId, signerAddress) {
918
- queryClient.removeQueries({
919
- queryKey: symmKeys.auth(accountAddress, chainId, signerAddress),
920
- exact: true
921
- });
1007
+ function clearAuthQueryData(accountAddress, chainId, signerAddress) {
1008
+ clearAuthStoreEntry(accountAddress, chainId, signerAddress);
922
1009
  }
923
1010
  function clearPersistedAuthState(accountAddress, chainId) {
924
1011
  clearCachedToken(accountAddress, chainId);
925
1012
  }
926
- function getAuthTokenFromRuntimeCache(queryClient, accountAddress, chainId, signerAddress) {
927
- const inQuery = getAuthQueryData(queryClient, accountAddress, chainId, signerAddress) ?? getAuthQueryData(queryClient, accountAddress, chainId);
1013
+ function getAuthTokenFromRuntimeCache(accountAddress, chainId, signerAddress) {
1014
+ const inQuery = getAuthQueryData(accountAddress, chainId, signerAddress) ?? getAuthQueryData(accountAddress, chainId);
928
1015
  if (inQuery && inQuery.expiresAt > Date.now()) {
929
1016
  return inQuery.token;
930
1017
  }
@@ -932,11 +1019,10 @@ function getAuthTokenFromRuntimeCache(queryClient, accountAddress, chainId, sign
932
1019
  if (!persisted) {
933
1020
  return null;
934
1021
  }
935
- setAuthQueryData(queryClient, accountAddress, chainId, signerAddress, persisted);
1022
+ setAuthQueryData(accountAddress, chainId, signerAddress, persisted);
936
1023
  return persisted.token;
937
1024
  }
938
1025
  async function resolveAuthTokenEntry({
939
- queryClient,
940
1026
  walletClient,
941
1027
  signerAddress,
942
1028
  accountAddress,
@@ -948,13 +1034,13 @@ async function resolveAuthTokenEntry({
948
1034
  return null;
949
1035
  }
950
1036
  if (!force) {
951
- const inQuery = getAuthQueryData(queryClient, accountAddress, chainId, signerAddress);
1037
+ const inQuery = getAuthQueryData(accountAddress, chainId, signerAddress);
952
1038
  if (inQuery && inQuery.expiresAt > Date.now()) {
953
1039
  return inQuery;
954
1040
  }
955
1041
  const persisted = getCachedTokenEntry(accountAddress, chainId);
956
1042
  if (persisted) {
957
- setAuthQueryData(queryClient, accountAddress, chainId, signerAddress, persisted);
1043
+ setAuthQueryData(accountAddress, chainId, signerAddress, persisted);
958
1044
  return persisted;
959
1045
  }
960
1046
  }
@@ -965,25 +1051,33 @@ async function resolveAuthTokenEntry({
965
1051
  chainId,
966
1052
  siweDomain
967
1053
  );
968
- setAuthQueryData(queryClient, accountAddress, chainId, signerAddress, fresh);
1054
+ setAuthQueryData(accountAddress, chainId, signerAddress, fresh);
969
1055
  return fresh;
970
1056
  }
971
- function clearAuthState(queryClient, accountAddress, chainId, signerAddress) {
1057
+ function clearAuthState(accountAddress, chainId, signerAddress) {
972
1058
  clearPersistedAuthState(accountAddress, chainId);
973
- clearAuthQueryData(queryClient, accountAddress, chainId, signerAddress);
1059
+ clearAuthQueryData(accountAddress, chainId, signerAddress);
974
1060
  }
975
1061
 
976
1062
  // src/react/hooks/use-symm-auth.ts
977
1063
  function useSymmAuth(params) {
978
1064
  const context = useSymmContext();
979
- const queryClient = useQueryClient();
980
1065
  const address = params?.address ?? context.address;
981
1066
  const chainId = params?.chainId ?? context.chainId ?? 42161;
982
1067
  const walletClient = params?.walletClient ?? context.walletClient;
983
1068
  const siweDomain = params?.siweDomain;
984
1069
  const activeAccountAddress = params?.activeAccountAddress;
985
- const canBootstrap = !!walletClient && !!address && !!activeAccountAddress;
986
- const refreshAuth = useCallback(
1070
+ const authEntry = useSymmAuthStore(
1071
+ (state) => selectAuthStoreEntry(state, activeAccountAddress, chainId, address)
1072
+ );
1073
+ useSymmAuthStore(
1074
+ (state) => selectAuthStoreStatus(state, activeAccountAddress, chainId, address).isLoading
1075
+ );
1076
+ const error = useSymmAuthStore(
1077
+ (state) => selectAuthStoreStatus(state, activeAccountAddress, chainId, address).error
1078
+ );
1079
+ const persistedEntry = !authEntry && activeAccountAddress ? getCachedTokenEntry(activeAccountAddress, chainId) : null;
1080
+ const signIn = useCallback(
987
1081
  async (accountAddress, options) => {
988
1082
  const resolvedAccountAddress = accountAddress ?? activeAccountAddress;
989
1083
  if (!resolvedAccountAddress) {
@@ -991,8 +1085,11 @@ function useSymmAuth(params) {
991
1085
  }
992
1086
  if (!walletClient || !address) return null;
993
1087
  try {
994
- const tokenEntry = await resolveAuthTokenEntry({
995
- queryClient,
1088
+ setAuthStoreStatus(resolvedAccountAddress, chainId, address, {
1089
+ error: null,
1090
+ isLoading: true
1091
+ });
1092
+ const tokenEntry2 = await resolveAuthTokenEntry({
996
1093
  walletClient,
997
1094
  signerAddress: address,
998
1095
  accountAddress: resolvedAccountAddress,
@@ -1000,10 +1097,16 @@ function useSymmAuth(params) {
1000
1097
  siweDomain,
1001
1098
  force: options?.force
1002
1099
  });
1003
- const token2 = tokenEntry?.token ?? null;
1004
- return token2;
1005
- } catch (error) {
1006
- clearPersistedAuthState(resolvedAccountAddress, chainId);
1100
+ setAuthStoreStatus(resolvedAccountAddress, chainId, address, {
1101
+ error: null,
1102
+ isLoading: false
1103
+ });
1104
+ return tokenEntry2?.token ?? null;
1105
+ } catch (error2) {
1106
+ clearAuthState(resolvedAccountAddress, chainId, address);
1107
+ setAuthStoreStatus(resolvedAccountAddress, chainId, address, {
1108
+ error: error2 instanceof Error ? error2 : new Error("failed to sign in")
1109
+ });
1007
1110
  return null;
1008
1111
  }
1009
1112
  },
@@ -1012,46 +1115,22 @@ function useSymmAuth(params) {
1012
1115
  address,
1013
1116
  activeAccountAddress,
1014
1117
  chainId,
1015
- siweDomain,
1016
- queryClient
1118
+ siweDomain
1017
1119
  ]
1018
1120
  );
1019
- const authQuery = useQuery({
1020
- queryKey: symmKeys.auth(activeAccountAddress, chainId, address),
1021
- queryFn: async () => {
1022
- const tokenEntry = await resolveAuthTokenEntry({
1023
- queryClient,
1024
- walletClient,
1025
- signerAddress: address,
1026
- accountAddress: activeAccountAddress,
1027
- chainId,
1028
- siweDomain
1029
- });
1030
- if (!tokenEntry) {
1031
- return null;
1032
- }
1033
- return tokenEntry;
1034
- },
1035
- enabled: canBootstrap,
1036
- retry: false,
1037
- refetchOnWindowFocus: false,
1038
- refetchOnReconnect: false
1039
- });
1040
1121
  const clearAuth = useCallback(() => {
1041
1122
  if (activeAccountAddress) {
1042
- clearAuthState(queryClient, activeAccountAddress, chainId, address);
1123
+ clearAuthState(activeAccountAddress, chainId, address);
1043
1124
  }
1044
- }, [activeAccountAddress, address, chainId, queryClient]);
1045
- const token = authQuery.data?.token ?? null;
1125
+ }, [activeAccountAddress, address, chainId]);
1126
+ const tokenEntry = authEntry ?? persistedEntry;
1127
+ const token = tokenEntry?.token ?? null;
1046
1128
  return {
1047
1129
  accessToken: token,
1048
- authToken: token,
1049
1130
  isAuthenticated: !!token,
1050
- isLoading: authQuery.isLoading,
1051
- isFetching: authQuery.isFetching,
1052
- error: authQuery.error,
1053
- refresh: refreshAuth,
1054
- refreshAuth,
1131
+ error,
1132
+ signIn,
1133
+ refreshAuth: signIn,
1055
1134
  clear: clearAuth
1056
1135
  };
1057
1136
  }
@@ -1855,7 +1934,6 @@ async function ensureInstantTradeReady(deps, queryClient, request) {
1855
1934
  throw new Error("at least one delegation selector is required");
1856
1935
  }
1857
1936
  const accessToken = getAuthTokenFromRuntimeCache(
1858
- queryClient,
1859
1937
  accountAddress,
1860
1938
  chainId,
1861
1939
  signerAddress
@@ -2265,7 +2343,6 @@ function splitTradeHookArgs(paramsOrOptions, options) {
2265
2343
  }
2266
2344
  function useResolveTradeAuthToken(params = {}) {
2267
2345
  const context = useSymmContext();
2268
- const queryClient = useQueryClient();
2269
2346
  const address = params.address ?? context.address;
2270
2347
  const chainId = params.chainId ?? context.chainId;
2271
2348
  return useCallback(
@@ -2279,7 +2356,6 @@ function useResolveTradeAuthToken(params = {}) {
2279
2356
  return null;
2280
2357
  }
2281
2358
  const inMemoryToken = getAuthTokenFromRuntimeCache(
2282
- queryClient,
2283
2359
  resolvedAccountAddress,
2284
2360
  resolvedChainId,
2285
2361
  address
@@ -2289,7 +2365,7 @@ function useResolveTradeAuthToken(params = {}) {
2289
2365
  }
2290
2366
  return null;
2291
2367
  },
2292
- [address, chainId, queryClient]
2368
+ [address, chainId]
2293
2369
  );
2294
2370
  }
2295
2371
 
@@ -25916,17 +25992,17 @@ function useSymmHedgerMarkets(params) {
25916
25992
 
25917
25993
  // src/utils/binance-api.ts
25918
25994
  var BINANCE_FAPI_BASE = "https://fapi.binance.com";
25919
- async function fetchKlines(symbol, interval, startTime, endTime, limit = 1500) {
25995
+ async function fetchBinanceKlineEndpoint(endpoint, symbol, interval, startTime, endTime, limit = 1e3) {
25920
25996
  const params = new URLSearchParams({
25921
25997
  symbol,
25922
25998
  interval,
25923
- startTime: String(startTime),
25924
- endTime: String(endTime),
25925
- limit: String(Math.min(limit, 1500))
25999
+ limit: String(Math.min(limit, 1e3))
25926
26000
  });
25927
- const response = await fetch(`${BINANCE_FAPI_BASE}/fapi/v1/klines?${params}`);
26001
+ const response = await fetch(
26002
+ `${BINANCE_FAPI_BASE}/fapi/v1/${endpoint}?${params}`
26003
+ );
25928
26004
  if (!response.ok) {
25929
- throw new Error(`Binance klines failed: ${response.status}`);
26005
+ throw new Error(`Binance ${endpoint} failed: ${response.status}`);
25930
26006
  }
25931
26007
  const data = await response.json();
25932
26008
  return data.map((k) => ({
@@ -25939,9 +26015,21 @@ async function fetchKlines(symbol, interval, startTime, endTime, limit = 1500) {
25939
26015
  closeTime: Number(k[6])
25940
26016
  }));
25941
26017
  }
26018
+ async function fetchMarkPriceKlines(symbol, interval, _startTime, _endTime, _limit = 1e3) {
26019
+ return fetchBinanceKlineEndpoint(
26020
+ "markPriceKlines",
26021
+ symbol,
26022
+ interval,
26023
+ void 0,
26024
+ void 0,
26025
+ 1e3
26026
+ );
26027
+ }
25942
26028
  async function fetch24hrTicker(symbol) {
25943
26029
  const params = new URLSearchParams({ symbol });
25944
- const response = await fetch(`${BINANCE_FAPI_BASE}/fapi/v1/ticker/24hr?${params}`);
26030
+ const response = await fetch(
26031
+ `${BINANCE_FAPI_BASE}/fapi/v1/ticker/24hr?${params}`
26032
+ );
25945
26033
  if (!response.ok) return null;
25946
26034
  const data = await response.json();
25947
26035
  return {
@@ -26251,7 +26339,6 @@ function useSymmPendingInstantOpens(params) {
26251
26339
  chainId: ctxChainId,
26252
26340
  address
26253
26341
  } = useSymmContext();
26254
- const queryClient = useQueryClient();
26255
26342
  const { accountAddress, authToken: providedAuthToken } = params;
26256
26343
  const chainId = params.chainId ?? ctxChainId;
26257
26344
  const internalEnabled = !!symmCoreClient && !!accountAddress;
@@ -26260,7 +26347,6 @@ function useSymmPendingInstantOpens(params) {
26260
26347
  queryKey: symmKeys.pendingInstantOpens(accountAddress, chainId),
26261
26348
  queryFn: async () => {
26262
26349
  const authToken = providedAuthToken ?? getAuthTokenFromRuntimeCache(
26263
- queryClient,
26264
26350
  accountAddress,
26265
26351
  chainId,
26266
26352
  address
@@ -26668,12 +26754,9 @@ function areIntervalsEqual(currentInterval, nextInterval) {
26668
26754
  async function fetchSymbolKlines(symbol, interval, start, end) {
26669
26755
  const binanceSymbol = toBinanceSymbol(symbol);
26670
26756
  if (!binanceSymbol) return [];
26671
- const klines = await fetchKlines(
26757
+ const klines = await fetchMarkPriceKlines(
26672
26758
  binanceSymbol,
26673
- toBinanceInterval(interval),
26674
- start,
26675
- end
26676
- );
26759
+ toBinanceInterval(interval));
26677
26760
  return klines.map((k) => ({
26678
26761
  t: k.openTime,
26679
26762
  T: k.closeTime,
@@ -26858,7 +26941,7 @@ function useSymmChartCandles(selection) {
26858
26941
  }
26859
26942
  if (longTokens.length === 1 && shortTokens.length === 0 || shortTokens.length === 1 && longTokens.length === 0) {
26860
26943
  const activeSymbol = longSymbol ?? shortSymbol;
26861
- return activeSymbol ? fetchSymbolKlines(activeSymbol, interval, start, end) : [];
26944
+ return activeSymbol ? fetchSymbolKlines(activeSymbol, interval) : [];
26862
26945
  }
26863
26946
  const allSymbols = Array.from(/* @__PURE__ */ new Set([
26864
26947
  ...longTokens.map((token) => token.symbol),
@@ -26867,7 +26950,7 @@ function useSymmChartCandles(selection) {
26867
26950
  const entries = await Promise.all(
26868
26951
  allSymbols.map(async (symbol) => [
26869
26952
  symbol,
26870
- await fetchSymbolKlines(symbol, interval, start, end)
26953
+ await fetchSymbolKlines(symbol, interval)
26871
26954
  ])
26872
26955
  );
26873
26956
  return computeWeightedBasketCandles(
@@ -26883,7 +26966,7 @@ function useSymmChartCandles(selection) {
26883
26966
  setRealtimeInterval(interval);
26884
26967
  const parts = symbol.split(" ");
26885
26968
  const assetSymbol = parts.length >= 2 ? parts.slice(1).join(" ") : symbol;
26886
- return fetchSymbolKlines(assetSymbol, interval, start, end);
26969
+ return fetchSymbolKlines(assetSymbol, interval);
26887
26970
  },
26888
26971
  [setRealtimeInterval]
26889
26972
  );
@@ -26896,7 +26979,7 @@ function useSymmChartCandles(selection) {
26896
26979
  if (!longSymbol && !shortSymbol) return [];
26897
26980
  const symbols = [longSymbol, shortSymbol].filter(Boolean);
26898
26981
  const allKlines = await Promise.all(
26899
- symbols.map((s) => fetchSymbolKlines(s, interval, start, end))
26982
+ symbols.map((s) => fetchSymbolKlines(s, interval))
26900
26983
  );
26901
26984
  if (allKlines.length === 0 || allKlines[0].length === 0) return [];
26902
26985
  if (allKlines.length === 1) {