@volr/react 0.1.14 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9006,9 +9006,10 @@ var safeStorage = {
9006
9006
  }
9007
9007
  };
9008
9008
 
9009
- // ../shared/src/constants/storage.ts
9009
+ // ../shared/dist/constants/storage.js
9010
9010
  var STORAGE_KEYS = {
9011
9011
  accessToken: "volr:accessToken",
9012
+ refreshToken: "volr:refreshToken",
9012
9013
  user: "volr:user",
9013
9014
  provider: "volr:provider",
9014
9015
  credentialId: "volr:credentialId",
@@ -9024,9 +9025,11 @@ var APIClient = class {
9024
9025
  constructor(config) {
9025
9026
  this.refreshPromise = null;
9026
9027
  this.accessToken = null;
9028
+ this.refreshToken = null;
9027
9029
  this.apiKey = null;
9028
9030
  this.apiKey = config.apiKey || null;
9029
9031
  this.accessToken = safeStorage.getItem(STORAGE_KEYS.accessToken);
9032
+ this.refreshToken = safeStorage.getItem(STORAGE_KEYS.refreshToken);
9030
9033
  this.api = axios.create({
9031
9034
  baseURL: config.baseUrl.replace(/\/+$/, ""),
9032
9035
  withCredentials: true,
@@ -9063,15 +9066,23 @@ var APIClient = class {
9063
9066
  (response) => response,
9064
9067
  async (error) => {
9065
9068
  const originalRequest = error.config;
9069
+ console.log(`[APIClient] Response error:`, error.response?.status, originalRequest?.url);
9070
+ if (originalRequest?.url?.includes("/auth/refresh")) {
9071
+ console.log("[APIClient] Refresh endpoint failed, not retrying");
9072
+ return Promise.reject(error);
9073
+ }
9066
9074
  if (error.response?.status === 401 && !originalRequest._retry) {
9075
+ console.log("[APIClient] 401 received, attempting token refresh...");
9067
9076
  originalRequest._retry = true;
9068
9077
  try {
9069
9078
  await this.refreshAccessToken();
9070
9079
  if (this.accessToken) {
9071
9080
  originalRequest.headers["Authorization"] = `Bearer ${this.accessToken}`;
9072
9081
  }
9082
+ console.log("[APIClient] Token refreshed, retrying original request");
9073
9083
  return this.api(originalRequest);
9074
9084
  } catch (refreshError) {
9085
+ console.error("[APIClient] Token refresh failed:", refreshError);
9075
9086
  return Promise.reject(refreshError);
9076
9087
  }
9077
9088
  }
@@ -9108,6 +9119,76 @@ var APIClient = class {
9108
9119
  getAccessToken() {
9109
9120
  return this.accessToken;
9110
9121
  }
9122
+ /**
9123
+ * Set refresh token
9124
+ */
9125
+ setRefreshToken(token) {
9126
+ this.refreshToken = token;
9127
+ if (token) {
9128
+ safeStorage.setItem(STORAGE_KEYS.refreshToken, token);
9129
+ } else {
9130
+ safeStorage.removeItem(STORAGE_KEYS.refreshToken);
9131
+ }
9132
+ }
9133
+ /**
9134
+ * Get refresh token
9135
+ */
9136
+ getRefreshToken() {
9137
+ return this.refreshToken;
9138
+ }
9139
+ /**
9140
+ * Ensure access token is valid, refresh if missing or expired
9141
+ * Use this before making authenticated requests that need a valid token upfront
9142
+ * Note: Most requests don't need this as the 401 interceptor handles refresh automatically
9143
+ */
9144
+ async ensureAccessToken() {
9145
+ if (this.accessToken) {
9146
+ return;
9147
+ }
9148
+ if (!this.refreshToken) {
9149
+ return;
9150
+ }
9151
+ try {
9152
+ await this.refreshAccessToken();
9153
+ } catch {
9154
+ }
9155
+ }
9156
+ /**
9157
+ * Refresh session and return user data
9158
+ * Use this when you need fresh user data (e.g., before passkey restoration)
9159
+ * @param timeoutMs - Timeout in milliseconds (default: 10000)
9160
+ * @returns User data from refresh response, or null if refresh fails
9161
+ */
9162
+ async refreshSession(timeoutMs = 1e4) {
9163
+ if (!this.refreshToken) {
9164
+ throw new Error("No refresh token available. Please log in again.");
9165
+ }
9166
+ const timeoutPromise = new Promise(
9167
+ (_, reject) => setTimeout(
9168
+ () => reject(new Error("Session refresh timeout. Please check your network connection.")),
9169
+ timeoutMs
9170
+ )
9171
+ );
9172
+ const refreshPromise = this.api.post(
9173
+ "/auth/refresh",
9174
+ { refreshToken: this.refreshToken }
9175
+ );
9176
+ const response = await Promise.race([refreshPromise, timeoutPromise]);
9177
+ const data = response.data;
9178
+ if (isErrorResponse(data)) {
9179
+ this.setAccessToken(null);
9180
+ this.setRefreshToken(null);
9181
+ throw new Error(data.error.message);
9182
+ }
9183
+ this.setAccessToken(data.data.accessToken);
9184
+ if (data.data.refreshToken) {
9185
+ this.setRefreshToken(data.data.refreshToken);
9186
+ }
9187
+ if (data.data.user) {
9188
+ safeStorage.setItem(STORAGE_KEYS.user, JSON.stringify(data.data.user));
9189
+ }
9190
+ return data.data.user ?? null;
9191
+ }
9111
9192
  /**
9112
9193
  * Refresh access token (single-flight)
9113
9194
  */
@@ -9115,19 +9196,26 @@ var APIClient = class {
9115
9196
  if (this.refreshPromise) {
9116
9197
  return this.refreshPromise;
9117
9198
  }
9199
+ if (!this.refreshToken) {
9200
+ throw new Error("No refresh token available. Please log in again.");
9201
+ }
9118
9202
  this.refreshPromise = (async () => {
9119
9203
  try {
9120
9204
  const response = await this.api.post(
9121
9205
  "/auth/refresh",
9122
- {}
9206
+ { refreshToken: this.refreshToken }
9123
9207
  );
9124
9208
  const data = response.data;
9125
9209
  if (isErrorResponse(data)) {
9126
9210
  this.setAccessToken(null);
9211
+ this.setRefreshToken(null);
9127
9212
  safeStorage.removeItem(STORAGE_KEYS.user);
9128
9213
  throw new Error(data.error.message);
9129
9214
  }
9130
9215
  this.setAccessToken(data.data.accessToken);
9216
+ if (data.data.refreshToken) {
9217
+ this.setRefreshToken(data.data.refreshToken);
9218
+ }
9131
9219
  if (data.data.user) {
9132
9220
  safeStorage.setItem(STORAGE_KEYS.user, JSON.stringify(data.data.user));
9133
9221
  }
@@ -9163,6 +9251,7 @@ var APIClient = class {
9163
9251
  */
9164
9252
  async post(endpoint, body, idempotencyKey) {
9165
9253
  const normalizedEndpoint = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
9254
+ console.log(`[APIClient] POST ${normalizedEndpoint}`);
9166
9255
  const config = {
9167
9256
  method: "POST",
9168
9257
  url: normalizedEndpoint,
@@ -9173,8 +9262,14 @@ var APIClient = class {
9173
9262
  "Idempotency-Key": idempotencyKey
9174
9263
  };
9175
9264
  }
9176
- const response = await this.api.request(config);
9177
- return unwrapResponse(response.data);
9265
+ try {
9266
+ const response = await this.api.request(config);
9267
+ console.log(`[APIClient] POST ${normalizedEndpoint} response:`, response.data);
9268
+ return unwrapResponse(response.data);
9269
+ } catch (error) {
9270
+ console.error(`[APIClient] POST ${normalizedEndpoint} error:`, error);
9271
+ throw error;
9272
+ }
9178
9273
  }
9179
9274
  /**
9180
9275
  * POST request that returns raw binary (ArrayBuffer)
@@ -9508,16 +9603,12 @@ async function restorePasskey(params) {
9508
9603
  );
9509
9604
  console.log("[restorePasskey] prfInput:", prfInput);
9510
9605
  console.log("[restorePasskey] Step 1: Ensuring access token is fresh...");
9511
- const currentToken = client.getAccessToken();
9512
- if (!currentToken) {
9513
- console.log("[restorePasskey] No access token found, calling /auth/refresh...");
9514
- try {
9515
- await client.post("/auth/refresh", {});
9516
- console.log("[restorePasskey] Access token refreshed successfully");
9517
- } catch (error) {
9518
- console.error("[restorePasskey] Failed to refresh access token:", error);
9519
- throw new Error("Failed to refresh access token. Please log in again.");
9520
- }
9606
+ try {
9607
+ await client.ensureAccessToken();
9608
+ console.log("[restorePasskey] Access token ensured");
9609
+ } catch (error) {
9610
+ console.error("[restorePasskey] Failed to ensure access token:", error);
9611
+ throw new Error("Failed to refresh access token. Please log in again.");
9521
9612
  }
9522
9613
  console.log("[restorePasskey] Step 2: Downloading blob via backend proxy for blobUrl:", blobUrl);
9523
9614
  const apiKey = client.getApiKey();
@@ -9629,6 +9720,9 @@ function VolrProvider({ config, children }) {
9629
9720
  const [accessToken, setAccessTokenState] = useState(() => {
9630
9721
  return client.getAccessToken();
9631
9722
  });
9723
+ const [refreshToken, setRefreshTokenState] = useState(() => {
9724
+ return client.getRefreshToken();
9725
+ });
9632
9726
  const syncRef = useRef(null);
9633
9727
  useEffect(() => {
9634
9728
  syncRef.current = new SessionSync();
@@ -9644,7 +9738,9 @@ function VolrProvider({ config, children }) {
9644
9738
  client.setApiKey(config.projectApiKey);
9645
9739
  } else if (event.type === "LOGOUT") {
9646
9740
  client.setAccessToken(null);
9741
+ client.setRefreshToken(null);
9647
9742
  setAccessTokenState(null);
9743
+ setRefreshTokenState(null);
9648
9744
  setUser(null);
9649
9745
  setProviderState(null);
9650
9746
  safeStorage.removeItem(STORAGE_KEYS.user);
@@ -9673,49 +9769,16 @@ function VolrProvider({ config, children }) {
9673
9769
  const keyStorageType = newProvider.keyStorageType;
9674
9770
  setProviderState(newProvider);
9675
9771
  try {
9676
- const refreshResponse = await client.post(
9677
- "/auth/refresh",
9678
- {}
9679
- );
9680
- if (refreshResponse.user) {
9681
- console.log(
9682
- "[Provider] setProvider: User data refreshed from backend:",
9683
- refreshResponse.user
9684
- );
9685
- setUser(refreshResponse.user);
9686
- safeStorage.setItem(
9687
- STORAGE_KEYS.user,
9688
- JSON.stringify(refreshResponse.user)
9689
- );
9772
+ const refreshedUser = await client.refreshSession();
9773
+ if (refreshedUser) {
9774
+ console.log("[Provider] setProvider: User data refreshed:", refreshedUser);
9775
+ setUser(refreshedUser);
9690
9776
  } else {
9691
- setUser((prev) => ({
9692
- ...prev,
9693
- keyStorageType
9694
- }));
9695
- safeStorage.setItem(
9696
- STORAGE_KEYS.user,
9697
- JSON.stringify({
9698
- ...user,
9699
- keyStorageType
9700
- })
9701
- );
9777
+ setUser((prev) => ({ ...prev, keyStorageType }));
9702
9778
  }
9703
9779
  } catch (error2) {
9704
- console.warn(
9705
- "[Provider] setProvider: Failed to refresh user data, using partial update:",
9706
- error2
9707
- );
9708
- setUser((prev) => ({
9709
- ...prev,
9710
- keyStorageType
9711
- }));
9712
- safeStorage.setItem(
9713
- STORAGE_KEYS.user,
9714
- JSON.stringify({
9715
- ...user,
9716
- keyStorageType
9717
- })
9718
- );
9780
+ console.warn("[Provider] setProvider: Failed to refresh user data:", error2);
9781
+ setUser((prev) => ({ ...prev, keyStorageType }));
9719
9782
  }
9720
9783
  safeStorage.setItem(STORAGE_KEYS.provider, keyStorageType);
9721
9784
  syncRef.current?.broadcast({
@@ -9740,70 +9803,38 @@ function VolrProvider({ config, children }) {
9740
9803
  const recover = async () => {
9741
9804
  try {
9742
9805
  setIsLoading(true);
9743
- const response = await client.post(
9744
- "/auth/refresh",
9745
- {}
9746
- );
9747
- console.log("[Provider] /auth/refresh response:", response);
9748
- const refreshedToken = client.getAccessToken();
9749
- if (refreshedToken) {
9750
- if (response.user) {
9751
- console.log(
9752
- "[Provider] Setting user from response:",
9753
- response.user
9754
- );
9755
- console.log("[Provider] User fields:", {
9756
- id: response.user.id,
9757
- email: response.user.email,
9758
- accountId: response.user.accountId,
9759
- evmAddress: response.user.evmAddress,
9760
- signerType: response.user.signerType,
9761
- keyStorageType: response.user.keyStorageType,
9762
- walletConnector: response.user.walletConnector,
9763
- blobUrl: response.user.blobUrl,
9764
- prfInput: response.user.prfInput,
9765
- credentialId: response.user.credentialId
9766
- });
9767
- setUser(response.user);
9768
- safeStorage.setItem(
9769
- STORAGE_KEYS.user,
9770
- JSON.stringify(response.user)
9771
- );
9772
- if (!REQUIRE_USER_GESTURE_TO_RESTORE) ; else {
9773
- if (response.user.keyStorageType === "passkey") {
9774
- console.log(
9775
- "[Provider] TTL=0 mode: Provider restoration deferred until transaction (requires user gesture)"
9776
- );
9777
- if (!response.user.blobUrl || !response.user.prfInput) {
9778
- console.warn(
9779
- "[Provider] Passkey user detected but missing blobUrl or prfInput. User needs to re-enroll passkey."
9780
- );
9781
- }
9782
- }
9806
+ if (!client.getRefreshToken()) {
9807
+ console.log("[Provider] No refresh token found, skipping auto-recover");
9808
+ setIsLoading(false);
9809
+ return;
9810
+ }
9811
+ const refreshedUser = await client.refreshSession();
9812
+ console.log("[Provider] Session refreshed, user:", refreshedUser);
9813
+ setAccessTokenState(client.getAccessToken());
9814
+ setRefreshTokenState(client.getRefreshToken());
9815
+ if (refreshedUser) {
9816
+ setUser(refreshedUser);
9817
+ if (!REQUIRE_USER_GESTURE_TO_RESTORE) ; else if (refreshedUser.keyStorageType === "passkey") {
9818
+ console.log("[Provider] TTL=0 mode: Provider restoration deferred");
9819
+ if (!refreshedUser.blobUrl || !refreshedUser.prfInput) {
9820
+ console.warn("[Provider] Passkey user missing blobUrl or prfInput");
9783
9821
  }
9784
- } else {
9785
- console.log(
9786
- "[Provider] No user in response, loading from storage"
9787
- );
9788
- const userStr = safeStorage.getItem(STORAGE_KEYS.user);
9789
- if (userStr) {
9790
- try {
9791
- const storedUser = JSON.parse(userStr);
9792
- console.log(
9793
- "[Provider] Loaded user from storage:",
9794
- storedUser
9795
- );
9796
- setUser(storedUser);
9797
- } catch {
9798
- safeStorage.removeItem(STORAGE_KEYS.user);
9799
- }
9822
+ }
9823
+ } else {
9824
+ const userStr = safeStorage.getItem(STORAGE_KEYS.user);
9825
+ if (userStr) {
9826
+ try {
9827
+ setUser(JSON.parse(userStr));
9828
+ } catch {
9829
+ safeStorage.removeItem(STORAGE_KEYS.user);
9800
9830
  }
9801
9831
  }
9802
- setAccessTokenState(refreshedToken);
9803
9832
  }
9804
9833
  } catch {
9805
9834
  client.setAccessToken(null);
9835
+ client.setRefreshToken(null);
9806
9836
  setAccessTokenState(null);
9837
+ setRefreshTokenState(null);
9807
9838
  setUser(null);
9808
9839
  setProviderState(null);
9809
9840
  safeStorage.removeItem(STORAGE_KEYS.user);
@@ -9821,12 +9852,7 @@ function VolrProvider({ config, children }) {
9821
9852
  async (input) => {
9822
9853
  try {
9823
9854
  setError(null);
9824
- if (!client.getAccessToken()) {
9825
- try {
9826
- await client.post("/auth/refresh", {});
9827
- } catch {
9828
- }
9829
- }
9855
+ await client.ensureAccessToken();
9830
9856
  const response = await client.post(
9831
9857
  "/wallet/precheck",
9832
9858
  input
@@ -9848,12 +9874,7 @@ function VolrProvider({ config, children }) {
9848
9874
  async (input, opts) => {
9849
9875
  try {
9850
9876
  setError(null);
9851
- if (!client.getAccessToken()) {
9852
- try {
9853
- await client.post("/auth/refresh", {});
9854
- } catch {
9855
- }
9856
- }
9877
+ await client.ensureAccessToken();
9857
9878
  const idempotencyKey = opts?.idempotencyKey ?? (typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}-${Math.random()}`);
9858
9879
  const serializedInput = serializeBigIntDeep(input);
9859
9880
  const response = await client.post(
@@ -9878,10 +9899,14 @@ function VolrProvider({ config, children }) {
9878
9899
  try {
9879
9900
  setError(null);
9880
9901
  client.setAccessToken(null);
9902
+ client.setRefreshToken(null);
9903
+ setAccessTokenState(null);
9904
+ setRefreshTokenState(null);
9881
9905
  setUser(null);
9882
9906
  setProviderState(null);
9883
9907
  safeStorage.removeItem(STORAGE_KEYS.user);
9884
9908
  safeStorage.removeItem(STORAGE_KEYS.accessToken);
9909
+ safeStorage.removeItem(STORAGE_KEYS.refreshToken);
9885
9910
  safeStorage.removeItem(STORAGE_KEYS.provider);
9886
9911
  syncRef.current?.broadcast({ type: "LOGOUT" });
9887
9912
  } catch (err) {
@@ -9966,22 +9991,25 @@ function VolrProvider({ config, children }) {
9966
9991
  () => ({
9967
9992
  session: {
9968
9993
  accessToken,
9969
- refreshToken: null
9970
- // Cookie-based, opaque
9994
+ refreshToken
9971
9995
  },
9972
9996
  refreshAccessToken: async () => {
9973
- await client.post("/auth/refresh", {});
9974
- const token = client.getAccessToken();
9975
- setAccessTokenState(token);
9997
+ await client.ensureAccessToken();
9998
+ setAccessTokenState(client.getAccessToken());
9999
+ setRefreshTokenState(client.getRefreshToken());
9976
10000
  },
9977
10001
  setAccessToken: (token) => {
9978
10002
  client.setAccessToken(token);
9979
10003
  setAccessTokenState(token);
9980
10004
  },
10005
+ setRefreshToken: (token) => {
10006
+ client.setRefreshToken(token);
10007
+ setRefreshTokenState(token);
10008
+ },
9981
10009
  client
9982
10010
  // Expose APIClient instance
9983
10011
  }),
9984
- [client, accessToken]
10012
+ [client, accessToken, refreshToken]
9985
10013
  );
9986
10014
  return /* @__PURE__ */ jsx(VolrContext.Provider, { value: publicValue, children: /* @__PURE__ */ jsx(InternalAuthContext.Provider, { value: internalValue, children }) });
9987
10015
  }
@@ -18228,22 +18256,24 @@ async function sendCalls(args) {
18228
18256
  console.log("[sendCalls] Calls normalized");
18229
18257
  let currentUser = deps.user;
18230
18258
  if (deps.user?.keyStorageType === "passkey" && !deps.provider) {
18231
- console.log("[sendCalls] Refreshing user data...");
18259
+ console.log("[sendCalls] Refreshing user data (provider not available)...");
18232
18260
  try {
18233
- const refreshResponse = await deps.client.post(
18234
- "/auth/refresh",
18235
- {}
18236
- );
18237
- if (refreshResponse.user) {
18238
- currentUser = refreshResponse.user;
18239
- console.log("[sendCalls] User data refreshed");
18261
+ const refreshedUser = await deps.client.refreshSession();
18262
+ if (refreshedUser) {
18263
+ currentUser = refreshedUser;
18264
+ console.log("[sendCalls] User data refreshed successfully");
18240
18265
  }
18241
18266
  } catch (error) {
18242
- console.warn(
18243
- "[sendCalls] Failed to refresh user data before transaction:",
18244
- error
18267
+ console.error("[sendCalls] Failed to refresh session:", error);
18268
+ throw new Error(
18269
+ `Failed to refresh session before transaction. ${error instanceof Error ? error.message : "Unknown error"}. Please try logging in again.`
18245
18270
  );
18246
18271
  }
18272
+ } else {
18273
+ console.log("[sendCalls] Skipping user refresh:", {
18274
+ hasProvider: !!deps.provider,
18275
+ keyStorageType: deps.user?.keyStorageType
18276
+ });
18247
18277
  }
18248
18278
  if (opts.preflight !== false) {
18249
18279
  console.log("[sendCalls] Running preflight estimate...");
@@ -18455,41 +18485,9 @@ function useVolrWallet() {
18455
18485
  );
18456
18486
  return { evm };
18457
18487
  }
18458
- function createAxiosInstance(baseUrl, apiKey) {
18459
- const instance = axios.create({
18460
- baseURL: baseUrl.replace(/\/+$/, ""),
18461
- // Remove trailing slashes
18462
- withCredentials: true,
18463
- // Include cookies
18464
- headers: {
18465
- "Content-Type": "application/json"
18466
- }
18467
- });
18468
- instance.interceptors.request.use((config) => {
18469
- if (apiKey) {
18470
- config.headers["X-API-Key"] = apiKey;
18471
- }
18472
- return config;
18473
- });
18474
- instance.interceptors.response.use(
18475
- (response) => response,
18476
- (error) => {
18477
- if (error.response?.data) {
18478
- const errorData = error.response.data;
18479
- if (errorData.error?.message) {
18480
- error.message = errorData.error.message;
18481
- }
18482
- }
18483
- return Promise.reject(error);
18484
- }
18485
- );
18486
- return instance;
18487
- }
18488
-
18489
- // src/hooks/useVolrLogin.ts
18490
18488
  function useVolrLogin() {
18491
18489
  const { config, setUser } = useVolr();
18492
- const { setAccessToken } = useInternalAuth();
18490
+ const { setAccessToken, setRefreshToken, client } = useInternalAuth();
18493
18491
  const toVolrUser = useCallback((u) => {
18494
18492
  return {
18495
18493
  id: u.id,
@@ -18506,27 +18504,18 @@ function useVolrLogin() {
18506
18504
  };
18507
18505
  }, []);
18508
18506
  const apiBaseUrl = resolveApiBaseUrl(config);
18509
- const api = useMemo(
18510
- () => createAxiosInstance(apiBaseUrl, config.projectApiKey),
18511
- [apiBaseUrl, config.projectApiKey]
18512
- );
18513
18507
  const requestEmailCode = useCallback(
18514
18508
  async (email) => {
18515
18509
  const normalizedEmail = email.trim().toLowerCase();
18516
18510
  if (!normalizedEmail || !normalizedEmail.includes("@")) {
18517
18511
  throw new Error("Invalid email address");
18518
18512
  }
18519
- const response = await api.post("/auth/email/send", {
18513
+ await client.post("/auth/email/send", {
18520
18514
  email: normalizedEmail
18521
18515
  });
18522
- if (!response.data?.ok) {
18523
- throw new Error(
18524
- response.data?.error?.message || "Failed to send verification code"
18525
- );
18526
- }
18527
18516
  safeStorage.setItem(STORAGE_KEYS.lastEmail, normalizedEmail);
18528
18517
  },
18529
- [api]
18518
+ [client]
18530
18519
  );
18531
18520
  const verifyEmailCode = useCallback(
18532
18521
  async (email, code) => {
@@ -18538,25 +18527,18 @@ function useVolrLogin() {
18538
18527
  if (!/^\d{6}$/.test(normalizedCode)) {
18539
18528
  throw new Error("Invalid code format");
18540
18529
  }
18541
- const response = await api.post("/auth/email/verify", {
18530
+ const response = await client.post("/auth/email/verify", {
18542
18531
  email: normalizedEmail,
18543
18532
  code: normalizedCode
18544
18533
  });
18545
- if (!response.data?.ok) {
18546
- throw new Error(
18547
- response.data?.error?.message || "Invalid verification code"
18548
- );
18549
- }
18550
- const verifyData = response.data;
18551
- const userFromServer = verifyData?.data?.user;
18552
- const isNewUser = !!verifyData?.data?.isNewUser;
18553
- const accessToken = verifyData?.data?.accessToken || "";
18534
+ const { user: userFromServer, isNewUser, accessToken, refreshToken } = response;
18554
18535
  if (!accessToken) {
18555
- throw new Error(
18556
- "Access token is required but was not provided by the server"
18557
- );
18536
+ throw new Error("Access token is required but was not provided by the server");
18558
18537
  }
18559
18538
  setAccessToken(accessToken);
18539
+ if (refreshToken) {
18540
+ setRefreshToken(refreshToken);
18541
+ }
18560
18542
  if (userFromServer) {
18561
18543
  setUser(toVolrUser(userFromServer));
18562
18544
  } else {
@@ -18570,7 +18552,7 @@ function useVolrLogin() {
18570
18552
  accessToken
18571
18553
  };
18572
18554
  },
18573
- [api, setAccessToken, setUser, toVolrUser]
18555
+ [client, setAccessToken, setRefreshToken, setUser, toVolrUser]
18574
18556
  );
18575
18557
  const handleSocialLogin = useCallback(
18576
18558
  async (provider) => {
@@ -18582,42 +18564,26 @@ function useVolrLogin() {
18582
18564
  [apiBaseUrl, config.projectApiKey]
18583
18565
  );
18584
18566
  const requestSiweNonce = useCallback(async () => {
18585
- const response = await api.get("/auth/siwe/nonce");
18586
- if (!response.data?.ok) {
18587
- throw new Error(
18588
- response.data?.error?.message || "Failed to generate nonce"
18589
- );
18590
- }
18591
- return response.data.data.nonce;
18592
- }, [api]);
18567
+ const response = await client.get("/auth/siwe/nonce");
18568
+ return response.nonce;
18569
+ }, [client]);
18593
18570
  const verifySiweSignature = useCallback(
18594
18571
  async (message, signature, options) => {
18595
18572
  try {
18596
- const response = await api.post("/auth/siwe/verify", {
18573
+ const response = await client.post("/auth/siwe/verify", {
18597
18574
  message,
18598
18575
  signature,
18599
18576
  walletConnector: options?.walletConnector,
18600
18577
  chainId: options?.chainId
18601
18578
  });
18602
- if (!response.data?.ok) {
18603
- console.error(
18604
- "[verifySiweSignature] Backend returned error:",
18605
- response.data
18606
- );
18607
- throw new Error(
18608
- response.data?.error?.message || "Invalid SIWE signature"
18609
- );
18610
- }
18611
- const verifyData = response.data;
18612
- const userFromServer = verifyData?.data?.user;
18613
- const isNewUser = !!verifyData?.data?.isNewUser;
18614
- const accessToken = verifyData?.data?.accessToken || "";
18579
+ const { user: userFromServer, isNewUser, accessToken, refreshToken } = response;
18615
18580
  if (!accessToken) {
18616
- throw new Error(
18617
- "Access token is required but was not provided by the server"
18618
- );
18581
+ throw new Error("Access token is required but was not provided by the server");
18619
18582
  }
18620
18583
  setAccessToken(accessToken);
18584
+ if (refreshToken) {
18585
+ setRefreshToken(refreshToken);
18586
+ }
18621
18587
  if (userFromServer) {
18622
18588
  setUser(toVolrUser(userFromServer));
18623
18589
  }
@@ -18637,7 +18603,7 @@ function useVolrLogin() {
18637
18603
  throw error;
18638
18604
  }
18639
18605
  },
18640
- [api, setAccessToken, setUser, toVolrUser]
18606
+ [client, setAccessToken, setRefreshToken, setUser, toVolrUser]
18641
18607
  );
18642
18608
  const handlePasskeyComplete = useCallback(async () => {
18643
18609
  }, []);
@@ -18650,9 +18616,41 @@ function useVolrLogin() {
18650
18616
  handlePasskeyComplete
18651
18617
  };
18652
18618
  }
18619
+ function createAxiosInstance(baseUrl, apiKey) {
18620
+ const instance = axios.create({
18621
+ baseURL: baseUrl.replace(/\/+$/, ""),
18622
+ // Remove trailing slashes
18623
+ withCredentials: true,
18624
+ // Include cookies
18625
+ headers: {
18626
+ "Content-Type": "application/json"
18627
+ }
18628
+ });
18629
+ instance.interceptors.request.use((config) => {
18630
+ if (apiKey) {
18631
+ config.headers["X-API-Key"] = apiKey;
18632
+ }
18633
+ return config;
18634
+ });
18635
+ instance.interceptors.response.use(
18636
+ (response) => response,
18637
+ (error) => {
18638
+ if (error.response?.data) {
18639
+ const errorData = error.response.data;
18640
+ if (errorData.error?.message) {
18641
+ error.message = errorData.error.message;
18642
+ }
18643
+ }
18644
+ return Promise.reject(error);
18645
+ }
18646
+ );
18647
+ return instance;
18648
+ }
18649
+
18650
+ // src/hooks/useVolrAuthCallback.ts
18653
18651
  function useVolrAuthCallback(options = {}) {
18654
18652
  const { config, setUser } = useVolr();
18655
- const { refreshAccessToken, setAccessToken } = useInternalAuth();
18653
+ const { refreshAccessToken, setAccessToken, setRefreshToken, client } = useInternalAuth();
18656
18654
  const [isLoading, setIsLoading] = useState(true);
18657
18655
  const [error, setError] = useState(null);
18658
18656
  const [isNewUser, setIsNewUser] = useState(false);
@@ -18706,13 +18704,21 @@ function useVolrAuthCallback(options = {}) {
18706
18704
  if (!userRes.data?.ok) {
18707
18705
  throw new Error("Failed to fetch user details");
18708
18706
  }
18709
- const refreshRes = await api.post("/auth/refresh");
18707
+ const currentRefreshToken = client.getRefreshToken();
18708
+ if (!currentRefreshToken) {
18709
+ throw new Error("No refresh token available. Please log in again.");
18710
+ }
18711
+ const refreshRes = await api.post("/auth/refresh", { refreshToken: currentRefreshToken });
18710
18712
  if (!refreshRes.data?.ok) {
18711
18713
  throw new Error("Failed to refresh session");
18712
18714
  }
18713
18715
  const userData = refreshRes.data.data.user;
18714
18716
  const accessToken = refreshRes.data.data.accessToken;
18717
+ const newRefreshToken = refreshRes.data.data.refreshToken;
18715
18718
  setAccessToken(accessToken);
18719
+ if (newRefreshToken) {
18720
+ setRefreshToken(newRefreshToken);
18721
+ }
18716
18722
  const volrUser = toVolrUser(userData);
18717
18723
  setUser(volrUser);
18718
18724
  setLocalUser(volrUser);
@@ -18727,7 +18733,7 @@ function useVolrAuthCallback(options = {}) {
18727
18733
  }
18728
18734
  };
18729
18735
  handleCallback();
18730
- }, [apiBaseUrl, config.projectApiKey, refreshAccessToken, setAccessToken, setUser, toVolrUser]);
18736
+ }, [apiBaseUrl, config.projectApiKey, refreshAccessToken, setAccessToken, setRefreshToken, setUser, toVolrUser, client]);
18731
18737
  return {
18732
18738
  isLoading,
18733
18739
  error,