@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.
@@ -35,16 +35,15 @@ type UseSymmAuthParams = {
35
35
  siweDomain?: string;
36
36
  };
37
37
  /**
38
- * Use case: Manage SYMM auth token lifecycle (read, refresh, clear) for an address and chain.
38
+ * Manages SYMM auth token state. Reads cached / persisted tokens on mount
39
+ * without any side effects — the wallet signature flow is only triggered
40
+ * when the caller explicitly invokes `signIn()`.
39
41
  */
40
42
  declare function useSymmAuth(params?: UseSymmAuthParams): {
41
43
  accessToken: string | null;
42
- authToken: string | null;
43
44
  isAuthenticated: boolean;
44
- isLoading: boolean;
45
- isFetching: boolean;
46
45
  error: Error | null;
47
- refresh: (accountAddress?: Address, options?: {
46
+ signIn: (accountAddress?: Address, options?: {
48
47
  force?: boolean;
49
48
  }) => Promise<string | null>;
50
49
  refreshAuth: (accountAddress?: Address, options?: {
@@ -35,16 +35,15 @@ type UseSymmAuthParams = {
35
35
  siweDomain?: string;
36
36
  };
37
37
  /**
38
- * Use case: Manage SYMM auth token lifecycle (read, refresh, clear) for an address and chain.
38
+ * Manages SYMM auth token state. Reads cached / persisted tokens on mount
39
+ * without any side effects — the wallet signature flow is only triggered
40
+ * when the caller explicitly invokes `signIn()`.
39
41
  */
40
42
  declare function useSymmAuth(params?: UseSymmAuthParams): {
41
43
  accessToken: string | null;
42
- authToken: string | null;
43
44
  isAuthenticated: boolean;
44
- isLoading: boolean;
45
- isFetching: boolean;
46
45
  error: Error | null;
47
- refresh: (accountAddress?: Address, options?: {
46
+ signIn: (accountAddress?: Address, options?: {
48
47
  force?: boolean;
49
48
  }) => Promise<string | null>;
50
49
  refreshAuth: (accountAddress?: Address, options?: {
@@ -23,9 +23,7 @@ var SYMBOL_OVERRIDES = {
23
23
  // Add overrides here as needed for SYMM markets that don't map 1:1 to Binance
24
24
  // e.g., 'SOME_SYMM_SYMBOL': 'BINANCE_SYMBOL',
25
25
  };
26
- var UNSUPPORTED_SYMBOLS = /* @__PURE__ */ new Set([
27
- // Add symbols here that have no Binance equivalent
28
- ]);
26
+ var UNSUPPORTED_SYMBOLS = /* @__PURE__ */ new Set([]);
29
27
  function resolveBinanceSymbol(symmSymbol) {
30
28
  if (!symmSymbol || !symmSymbol.trim()) {
31
29
  return {
@@ -906,27 +904,116 @@ async function fetchAccessTokenEntry(walletClient, signerAddress, accountAddress
906
904
  writeStoredToken(accountAddress, chainId, cachedToken);
907
905
  return cachedToken;
908
906
  }
907
+ function authStoreKey(accountAddress, chainId, signerAddress) {
908
+ return `${accountAddress}:${chainId}:${signerAddress ?? ""}`;
909
+ }
910
+ function getEntryFromSnapshot(state, accountAddress, chainId, signerAddress) {
911
+ const signerScoped = state.entries[authStoreKey(accountAddress, chainId, signerAddress)];
912
+ if (signerScoped) {
913
+ return signerScoped;
914
+ }
915
+ return state.entries[authStoreKey(accountAddress, chainId)] ?? null;
916
+ }
917
+ function getStatusFromSnapshot(state, accountAddress, chainId, signerAddress) {
918
+ const signerScoped = state.status[authStoreKey(accountAddress, chainId, signerAddress)];
919
+ if (signerScoped) {
920
+ return signerScoped;
921
+ }
922
+ return state.status[authStoreKey(accountAddress, chainId)] ?? {
923
+ error: null,
924
+ isLoading: false
925
+ };
926
+ }
927
+ var useSymmAuthStore = zustand.create((set) => ({
928
+ entries: {},
929
+ status: {},
930
+ setEntry: (accountAddress, chainId, signerAddress, entry) => set((state) => ({
931
+ entries: {
932
+ ...state.entries,
933
+ [authStoreKey(accountAddress, chainId, signerAddress)]: entry
934
+ },
935
+ status: {
936
+ ...state.status,
937
+ [authStoreKey(accountAddress, chainId, signerAddress)]: {
938
+ error: null,
939
+ isLoading: false
940
+ }
941
+ }
942
+ })),
943
+ clearEntry: (accountAddress, chainId, signerAddress) => set((state) => {
944
+ const nextEntries = { ...state.entries };
945
+ const nextStatus = { ...state.status };
946
+ delete nextEntries[authStoreKey(accountAddress, chainId, signerAddress)];
947
+ delete nextStatus[authStoreKey(accountAddress, chainId, signerAddress)];
948
+ return {
949
+ entries: nextEntries,
950
+ status: nextStatus
951
+ };
952
+ }),
953
+ setStatus: (accountAddress, chainId, signerAddress, status) => set((state) => ({
954
+ status: {
955
+ ...state.status,
956
+ [authStoreKey(accountAddress, chainId, signerAddress)]: {
957
+ error: null,
958
+ isLoading: false,
959
+ ...state.status[authStoreKey(accountAddress, chainId, signerAddress)],
960
+ ...status
961
+ }
962
+ }
963
+ })),
964
+ reset: () => set({
965
+ entries: {},
966
+ status: {}
967
+ })
968
+ }));
969
+ function getAuthStoreEntry(accountAddress, chainId, signerAddress) {
970
+ return getEntryFromSnapshot(
971
+ useSymmAuthStore.getState(),
972
+ accountAddress,
973
+ chainId,
974
+ signerAddress
975
+ );
976
+ }
977
+ function selectAuthStoreEntry(state, accountAddress, chainId, signerAddress) {
978
+ if (!accountAddress || chainId == null) {
979
+ return null;
980
+ }
981
+ return getEntryFromSnapshot(state, accountAddress, chainId, signerAddress);
982
+ }
983
+ function selectAuthStoreStatus(state, accountAddress, chainId, signerAddress) {
984
+ if (!accountAddress || chainId == null) {
985
+ return {
986
+ error: null,
987
+ isLoading: false
988
+ };
989
+ }
990
+ return getStatusFromSnapshot(state, accountAddress, chainId, signerAddress);
991
+ }
992
+ function setAuthStoreEntry(accountAddress, chainId, signerAddress, entry) {
993
+ useSymmAuthStore.getState().setEntry(accountAddress, chainId, signerAddress, entry);
994
+ }
995
+ function setAuthStoreStatus(accountAddress, chainId, signerAddress, status) {
996
+ useSymmAuthStore.getState().setStatus(accountAddress, chainId, signerAddress, status);
997
+ }
998
+ function clearAuthStoreEntry(accountAddress, chainId, signerAddress) {
999
+ useSymmAuthStore.getState().clearEntry(accountAddress, chainId, signerAddress);
1000
+ }
909
1001
 
910
1002
  // src/react/auth-cache.ts
911
- function getAuthQueryData(queryClient, accountAddress, chainId, signerAddress) {
912
- return queryClient.getQueryData(
913
- symmKeys.auth(accountAddress, chainId, signerAddress)
914
- ) ?? null;
1003
+ function getAuthQueryData(accountAddress, chainId, signerAddress) {
1004
+ return getAuthStoreEntry(accountAddress, chainId, signerAddress);
915
1005
  }
916
- function setAuthQueryData(queryClient, accountAddress, chainId, signerAddress, entry) {
917
- queryClient.setQueryData(symmKeys.auth(accountAddress, chainId, signerAddress), entry);
1006
+ function setAuthQueryData(accountAddress, chainId, signerAddress, entry) {
1007
+ setAuthStoreEntry(accountAddress, chainId, signerAddress, entry);
918
1008
  }
919
- function clearAuthQueryData(queryClient, accountAddress, chainId, signerAddress) {
920
- queryClient.removeQueries({
921
- queryKey: symmKeys.auth(accountAddress, chainId, signerAddress),
922
- exact: true
923
- });
1009
+ function clearAuthQueryData(accountAddress, chainId, signerAddress) {
1010
+ clearAuthStoreEntry(accountAddress, chainId, signerAddress);
924
1011
  }
925
1012
  function clearPersistedAuthState(accountAddress, chainId) {
926
1013
  clearCachedToken(accountAddress, chainId);
927
1014
  }
928
- function getAuthTokenFromRuntimeCache(queryClient, accountAddress, chainId, signerAddress) {
929
- const inQuery = getAuthQueryData(queryClient, accountAddress, chainId, signerAddress) ?? getAuthQueryData(queryClient, accountAddress, chainId);
1015
+ function getAuthTokenFromRuntimeCache(accountAddress, chainId, signerAddress) {
1016
+ const inQuery = getAuthQueryData(accountAddress, chainId, signerAddress) ?? getAuthQueryData(accountAddress, chainId);
930
1017
  if (inQuery && inQuery.expiresAt > Date.now()) {
931
1018
  return inQuery.token;
932
1019
  }
@@ -934,11 +1021,10 @@ function getAuthTokenFromRuntimeCache(queryClient, accountAddress, chainId, sign
934
1021
  if (!persisted) {
935
1022
  return null;
936
1023
  }
937
- setAuthQueryData(queryClient, accountAddress, chainId, signerAddress, persisted);
1024
+ setAuthQueryData(accountAddress, chainId, signerAddress, persisted);
938
1025
  return persisted.token;
939
1026
  }
940
1027
  async function resolveAuthTokenEntry({
941
- queryClient,
942
1028
  walletClient,
943
1029
  signerAddress,
944
1030
  accountAddress,
@@ -950,13 +1036,13 @@ async function resolveAuthTokenEntry({
950
1036
  return null;
951
1037
  }
952
1038
  if (!force) {
953
- const inQuery = getAuthQueryData(queryClient, accountAddress, chainId, signerAddress);
1039
+ const inQuery = getAuthQueryData(accountAddress, chainId, signerAddress);
954
1040
  if (inQuery && inQuery.expiresAt > Date.now()) {
955
1041
  return inQuery;
956
1042
  }
957
1043
  const persisted = getCachedTokenEntry(accountAddress, chainId);
958
1044
  if (persisted) {
959
- setAuthQueryData(queryClient, accountAddress, chainId, signerAddress, persisted);
1045
+ setAuthQueryData(accountAddress, chainId, signerAddress, persisted);
960
1046
  return persisted;
961
1047
  }
962
1048
  }
@@ -967,25 +1053,33 @@ async function resolveAuthTokenEntry({
967
1053
  chainId,
968
1054
  siweDomain
969
1055
  );
970
- setAuthQueryData(queryClient, accountAddress, chainId, signerAddress, fresh);
1056
+ setAuthQueryData(accountAddress, chainId, signerAddress, fresh);
971
1057
  return fresh;
972
1058
  }
973
- function clearAuthState(queryClient, accountAddress, chainId, signerAddress) {
1059
+ function clearAuthState(accountAddress, chainId, signerAddress) {
974
1060
  clearPersistedAuthState(accountAddress, chainId);
975
- clearAuthQueryData(queryClient, accountAddress, chainId, signerAddress);
1061
+ clearAuthQueryData(accountAddress, chainId, signerAddress);
976
1062
  }
977
1063
 
978
1064
  // src/react/hooks/use-symm-auth.ts
979
1065
  function useSymmAuth(params) {
980
1066
  const context = useSymmContext();
981
- const queryClient = reactQuery.useQueryClient();
982
1067
  const address = params?.address ?? context.address;
983
1068
  const chainId = params?.chainId ?? context.chainId ?? 42161;
984
1069
  const walletClient = params?.walletClient ?? context.walletClient;
985
1070
  const siweDomain = params?.siweDomain;
986
1071
  const activeAccountAddress = params?.activeAccountAddress;
987
- const canBootstrap = !!walletClient && !!address && !!activeAccountAddress;
988
- const refreshAuth = react.useCallback(
1072
+ const authEntry = useSymmAuthStore(
1073
+ (state) => selectAuthStoreEntry(state, activeAccountAddress, chainId, address)
1074
+ );
1075
+ useSymmAuthStore(
1076
+ (state) => selectAuthStoreStatus(state, activeAccountAddress, chainId, address).isLoading
1077
+ );
1078
+ const error = useSymmAuthStore(
1079
+ (state) => selectAuthStoreStatus(state, activeAccountAddress, chainId, address).error
1080
+ );
1081
+ const persistedEntry = !authEntry && activeAccountAddress ? getCachedTokenEntry(activeAccountAddress, chainId) : null;
1082
+ const signIn = react.useCallback(
989
1083
  async (accountAddress, options) => {
990
1084
  const resolvedAccountAddress = accountAddress ?? activeAccountAddress;
991
1085
  if (!resolvedAccountAddress) {
@@ -993,8 +1087,11 @@ function useSymmAuth(params) {
993
1087
  }
994
1088
  if (!walletClient || !address) return null;
995
1089
  try {
996
- const tokenEntry = await resolveAuthTokenEntry({
997
- queryClient,
1090
+ setAuthStoreStatus(resolvedAccountAddress, chainId, address, {
1091
+ error: null,
1092
+ isLoading: true
1093
+ });
1094
+ const tokenEntry2 = await resolveAuthTokenEntry({
998
1095
  walletClient,
999
1096
  signerAddress: address,
1000
1097
  accountAddress: resolvedAccountAddress,
@@ -1002,10 +1099,16 @@ function useSymmAuth(params) {
1002
1099
  siweDomain,
1003
1100
  force: options?.force
1004
1101
  });
1005
- const token2 = tokenEntry?.token ?? null;
1006
- return token2;
1007
- } catch (error) {
1008
- clearPersistedAuthState(resolvedAccountAddress, chainId);
1102
+ setAuthStoreStatus(resolvedAccountAddress, chainId, address, {
1103
+ error: null,
1104
+ isLoading: false
1105
+ });
1106
+ return tokenEntry2?.token ?? null;
1107
+ } catch (error2) {
1108
+ clearAuthState(resolvedAccountAddress, chainId, address);
1109
+ setAuthStoreStatus(resolvedAccountAddress, chainId, address, {
1110
+ error: error2 instanceof Error ? error2 : new Error("failed to sign in")
1111
+ });
1009
1112
  return null;
1010
1113
  }
1011
1114
  },
@@ -1014,46 +1117,22 @@ function useSymmAuth(params) {
1014
1117
  address,
1015
1118
  activeAccountAddress,
1016
1119
  chainId,
1017
- siweDomain,
1018
- queryClient
1120
+ siweDomain
1019
1121
  ]
1020
1122
  );
1021
- const authQuery = reactQuery.useQuery({
1022
- queryKey: symmKeys.auth(activeAccountAddress, chainId, address),
1023
- queryFn: async () => {
1024
- const tokenEntry = await resolveAuthTokenEntry({
1025
- queryClient,
1026
- walletClient,
1027
- signerAddress: address,
1028
- accountAddress: activeAccountAddress,
1029
- chainId,
1030
- siweDomain
1031
- });
1032
- if (!tokenEntry) {
1033
- return null;
1034
- }
1035
- return tokenEntry;
1036
- },
1037
- enabled: canBootstrap,
1038
- retry: false,
1039
- refetchOnWindowFocus: false,
1040
- refetchOnReconnect: false
1041
- });
1042
1123
  const clearAuth = react.useCallback(() => {
1043
1124
  if (activeAccountAddress) {
1044
- clearAuthState(queryClient, activeAccountAddress, chainId, address);
1125
+ clearAuthState(activeAccountAddress, chainId, address);
1045
1126
  }
1046
- }, [activeAccountAddress, address, chainId, queryClient]);
1047
- const token = authQuery.data?.token ?? null;
1127
+ }, [activeAccountAddress, address, chainId]);
1128
+ const tokenEntry = authEntry ?? persistedEntry;
1129
+ const token = tokenEntry?.token ?? null;
1048
1130
  return {
1049
1131
  accessToken: token,
1050
- authToken: token,
1051
1132
  isAuthenticated: !!token,
1052
- isLoading: authQuery.isLoading,
1053
- isFetching: authQuery.isFetching,
1054
- error: authQuery.error,
1055
- refresh: refreshAuth,
1056
- refreshAuth,
1133
+ error,
1134
+ signIn,
1135
+ refreshAuth: signIn,
1057
1136
  clear: clearAuth
1058
1137
  };
1059
1138
  }
@@ -1857,7 +1936,6 @@ async function ensureInstantTradeReady(deps, queryClient, request) {
1857
1936
  throw new Error("at least one delegation selector is required");
1858
1937
  }
1859
1938
  const accessToken = getAuthTokenFromRuntimeCache(
1860
- queryClient,
1861
1939
  accountAddress,
1862
1940
  chainId,
1863
1941
  signerAddress
@@ -2267,7 +2345,6 @@ function splitTradeHookArgs(paramsOrOptions, options) {
2267
2345
  }
2268
2346
  function useResolveTradeAuthToken(params = {}) {
2269
2347
  const context = useSymmContext();
2270
- const queryClient = reactQuery.useQueryClient();
2271
2348
  const address = params.address ?? context.address;
2272
2349
  const chainId = params.chainId ?? context.chainId;
2273
2350
  return react.useCallback(
@@ -2281,7 +2358,6 @@ function useResolveTradeAuthToken(params = {}) {
2281
2358
  return null;
2282
2359
  }
2283
2360
  const inMemoryToken = getAuthTokenFromRuntimeCache(
2284
- queryClient,
2285
2361
  resolvedAccountAddress,
2286
2362
  resolvedChainId,
2287
2363
  address
@@ -2291,7 +2367,7 @@ function useResolveTradeAuthToken(params = {}) {
2291
2367
  }
2292
2368
  return null;
2293
2369
  },
2294
- [address, chainId, queryClient]
2370
+ [address, chainId]
2295
2371
  );
2296
2372
  }
2297
2373
 
@@ -25918,17 +25994,17 @@ function useSymmHedgerMarkets(params) {
25918
25994
 
25919
25995
  // src/utils/binance-api.ts
25920
25996
  var BINANCE_FAPI_BASE = "https://fapi.binance.com";
25921
- async function fetchKlines(symbol, interval, startTime, endTime, limit = 1500) {
25997
+ async function fetchBinanceKlineEndpoint(endpoint, symbol, interval, startTime, endTime, limit = 1e3) {
25922
25998
  const params = new URLSearchParams({
25923
25999
  symbol,
25924
26000
  interval,
25925
- startTime: String(startTime),
25926
- endTime: String(endTime),
25927
- limit: String(Math.min(limit, 1500))
26001
+ limit: String(Math.min(limit, 1e3))
25928
26002
  });
25929
- const response = await fetch(`${BINANCE_FAPI_BASE}/fapi/v1/klines?${params}`);
26003
+ const response = await fetch(
26004
+ `${BINANCE_FAPI_BASE}/fapi/v1/${endpoint}?${params}`
26005
+ );
25930
26006
  if (!response.ok) {
25931
- throw new Error(`Binance klines failed: ${response.status}`);
26007
+ throw new Error(`Binance ${endpoint} failed: ${response.status}`);
25932
26008
  }
25933
26009
  const data = await response.json();
25934
26010
  return data.map((k) => ({
@@ -25941,9 +26017,21 @@ async function fetchKlines(symbol, interval, startTime, endTime, limit = 1500) {
25941
26017
  closeTime: Number(k[6])
25942
26018
  }));
25943
26019
  }
26020
+ async function fetchMarkPriceKlines(symbol, interval, _startTime, _endTime, _limit = 1e3) {
26021
+ return fetchBinanceKlineEndpoint(
26022
+ "markPriceKlines",
26023
+ symbol,
26024
+ interval,
26025
+ void 0,
26026
+ void 0,
26027
+ 1e3
26028
+ );
26029
+ }
25944
26030
  async function fetch24hrTicker(symbol) {
25945
26031
  const params = new URLSearchParams({ symbol });
25946
- const response = await fetch(`${BINANCE_FAPI_BASE}/fapi/v1/ticker/24hr?${params}`);
26032
+ const response = await fetch(
26033
+ `${BINANCE_FAPI_BASE}/fapi/v1/ticker/24hr?${params}`
26034
+ );
25947
26035
  if (!response.ok) return null;
25948
26036
  const data = await response.json();
25949
26037
  return {
@@ -26253,7 +26341,6 @@ function useSymmPendingInstantOpens(params) {
26253
26341
  chainId: ctxChainId,
26254
26342
  address
26255
26343
  } = useSymmContext();
26256
- const queryClient = reactQuery.useQueryClient();
26257
26344
  const { accountAddress, authToken: providedAuthToken } = params;
26258
26345
  const chainId = params.chainId ?? ctxChainId;
26259
26346
  const internalEnabled = !!symmCoreClient && !!accountAddress;
@@ -26262,7 +26349,6 @@ function useSymmPendingInstantOpens(params) {
26262
26349
  queryKey: symmKeys.pendingInstantOpens(accountAddress, chainId),
26263
26350
  queryFn: async () => {
26264
26351
  const authToken = providedAuthToken ?? getAuthTokenFromRuntimeCache(
26265
- queryClient,
26266
26352
  accountAddress,
26267
26353
  chainId,
26268
26354
  address
@@ -26670,12 +26756,9 @@ function areIntervalsEqual(currentInterval, nextInterval) {
26670
26756
  async function fetchSymbolKlines(symbol, interval, start, end) {
26671
26757
  const binanceSymbol = toBinanceSymbol(symbol);
26672
26758
  if (!binanceSymbol) return [];
26673
- const klines = await fetchKlines(
26759
+ const klines = await fetchMarkPriceKlines(
26674
26760
  binanceSymbol,
26675
- toBinanceInterval(interval),
26676
- start,
26677
- end
26678
- );
26761
+ toBinanceInterval(interval));
26679
26762
  return klines.map((k) => ({
26680
26763
  t: k.openTime,
26681
26764
  T: k.closeTime,
@@ -26860,7 +26943,7 @@ function useSymmChartCandles(selection) {
26860
26943
  }
26861
26944
  if (longTokens.length === 1 && shortTokens.length === 0 || shortTokens.length === 1 && longTokens.length === 0) {
26862
26945
  const activeSymbol = longSymbol ?? shortSymbol;
26863
- return activeSymbol ? fetchSymbolKlines(activeSymbol, interval, start, end) : [];
26946
+ return activeSymbol ? fetchSymbolKlines(activeSymbol, interval) : [];
26864
26947
  }
26865
26948
  const allSymbols = Array.from(/* @__PURE__ */ new Set([
26866
26949
  ...longTokens.map((token) => token.symbol),
@@ -26869,7 +26952,7 @@ function useSymmChartCandles(selection) {
26869
26952
  const entries = await Promise.all(
26870
26953
  allSymbols.map(async (symbol) => [
26871
26954
  symbol,
26872
- await fetchSymbolKlines(symbol, interval, start, end)
26955
+ await fetchSymbolKlines(symbol, interval)
26873
26956
  ])
26874
26957
  );
26875
26958
  return computeWeightedBasketCandles(
@@ -26885,7 +26968,7 @@ function useSymmChartCandles(selection) {
26885
26968
  setRealtimeInterval(interval);
26886
26969
  const parts = symbol.split(" ");
26887
26970
  const assetSymbol = parts.length >= 2 ? parts.slice(1).join(" ") : symbol;
26888
- return fetchSymbolKlines(assetSymbol, interval, start, end);
26971
+ return fetchSymbolKlines(assetSymbol, interval);
26889
26972
  },
26890
26973
  [setRealtimeInterval]
26891
26974
  );
@@ -26898,7 +26981,7 @@ function useSymmChartCandles(selection) {
26898
26981
  if (!longSymbol && !shortSymbol) return [];
26899
26982
  const symbols = [longSymbol, shortSymbol].filter(Boolean);
26900
26983
  const allKlines = await Promise.all(
26901
- symbols.map((s) => fetchSymbolKlines(s, interval, start, end))
26984
+ symbols.map((s) => fetchSymbolKlines(s, interval))
26902
26985
  );
26903
26986
  if (allKlines.length === 0 || allKlines[0].length === 0) return [];
26904
26987
  if (allKlines.length === 1) {