@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.cjs +233 -227
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -2
- package/dist/index.d.ts +27 -2
- package/dist/index.js +233 -227
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -9006,9 +9006,10 @@ var safeStorage = {
|
|
|
9006
9006
|
}
|
|
9007
9007
|
};
|
|
9008
9008
|
|
|
9009
|
-
// ../shared/
|
|
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
|
-
|
|
9177
|
-
|
|
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
|
-
|
|
9512
|
-
|
|
9513
|
-
console.log("[restorePasskey]
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
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
|
|
9677
|
-
|
|
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
|
-
|
|
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
|
-
|
|
9744
|
-
"
|
|
9745
|
-
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
const
|
|
9749
|
-
|
|
9750
|
-
|
|
9751
|
-
|
|
9752
|
-
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
console.log("[Provider]
|
|
9756
|
-
|
|
9757
|
-
|
|
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
|
-
}
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
9970
|
-
// Cookie-based, opaque
|
|
9994
|
+
refreshToken
|
|
9971
9995
|
},
|
|
9972
9996
|
refreshAccessToken: async () => {
|
|
9973
|
-
await client.
|
|
9974
|
-
|
|
9975
|
-
|
|
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
|
|
18234
|
-
|
|
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.
|
|
18243
|
-
|
|
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
|
-
|
|
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
|
-
[
|
|
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
|
|
18530
|
+
const response = await client.post("/auth/email/verify", {
|
|
18542
18531
|
email: normalizedEmail,
|
|
18543
18532
|
code: normalizedCode
|
|
18544
18533
|
});
|
|
18545
|
-
|
|
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
|
-
[
|
|
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
|
|
18586
|
-
|
|
18587
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
[
|
|
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
|
|
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,
|