@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.cjs
CHANGED
|
@@ -9030,9 +9030,10 @@ var safeStorage = {
|
|
|
9030
9030
|
}
|
|
9031
9031
|
};
|
|
9032
9032
|
|
|
9033
|
-
// ../shared/
|
|
9033
|
+
// ../shared/dist/constants/storage.js
|
|
9034
9034
|
var STORAGE_KEYS = {
|
|
9035
9035
|
accessToken: "volr:accessToken",
|
|
9036
|
+
refreshToken: "volr:refreshToken",
|
|
9036
9037
|
user: "volr:user",
|
|
9037
9038
|
provider: "volr:provider",
|
|
9038
9039
|
credentialId: "volr:credentialId",
|
|
@@ -9048,9 +9049,11 @@ var APIClient = class {
|
|
|
9048
9049
|
constructor(config) {
|
|
9049
9050
|
this.refreshPromise = null;
|
|
9050
9051
|
this.accessToken = null;
|
|
9052
|
+
this.refreshToken = null;
|
|
9051
9053
|
this.apiKey = null;
|
|
9052
9054
|
this.apiKey = config.apiKey || null;
|
|
9053
9055
|
this.accessToken = safeStorage.getItem(STORAGE_KEYS.accessToken);
|
|
9056
|
+
this.refreshToken = safeStorage.getItem(STORAGE_KEYS.refreshToken);
|
|
9054
9057
|
this.api = axios__default.default.create({
|
|
9055
9058
|
baseURL: config.baseUrl.replace(/\/+$/, ""),
|
|
9056
9059
|
withCredentials: true,
|
|
@@ -9087,15 +9090,23 @@ var APIClient = class {
|
|
|
9087
9090
|
(response) => response,
|
|
9088
9091
|
async (error) => {
|
|
9089
9092
|
const originalRequest = error.config;
|
|
9093
|
+
console.log(`[APIClient] Response error:`, error.response?.status, originalRequest?.url);
|
|
9094
|
+
if (originalRequest?.url?.includes("/auth/refresh")) {
|
|
9095
|
+
console.log("[APIClient] Refresh endpoint failed, not retrying");
|
|
9096
|
+
return Promise.reject(error);
|
|
9097
|
+
}
|
|
9090
9098
|
if (error.response?.status === 401 && !originalRequest._retry) {
|
|
9099
|
+
console.log("[APIClient] 401 received, attempting token refresh...");
|
|
9091
9100
|
originalRequest._retry = true;
|
|
9092
9101
|
try {
|
|
9093
9102
|
await this.refreshAccessToken();
|
|
9094
9103
|
if (this.accessToken) {
|
|
9095
9104
|
originalRequest.headers["Authorization"] = `Bearer ${this.accessToken}`;
|
|
9096
9105
|
}
|
|
9106
|
+
console.log("[APIClient] Token refreshed, retrying original request");
|
|
9097
9107
|
return this.api(originalRequest);
|
|
9098
9108
|
} catch (refreshError) {
|
|
9109
|
+
console.error("[APIClient] Token refresh failed:", refreshError);
|
|
9099
9110
|
return Promise.reject(refreshError);
|
|
9100
9111
|
}
|
|
9101
9112
|
}
|
|
@@ -9132,6 +9143,76 @@ var APIClient = class {
|
|
|
9132
9143
|
getAccessToken() {
|
|
9133
9144
|
return this.accessToken;
|
|
9134
9145
|
}
|
|
9146
|
+
/**
|
|
9147
|
+
* Set refresh token
|
|
9148
|
+
*/
|
|
9149
|
+
setRefreshToken(token) {
|
|
9150
|
+
this.refreshToken = token;
|
|
9151
|
+
if (token) {
|
|
9152
|
+
safeStorage.setItem(STORAGE_KEYS.refreshToken, token);
|
|
9153
|
+
} else {
|
|
9154
|
+
safeStorage.removeItem(STORAGE_KEYS.refreshToken);
|
|
9155
|
+
}
|
|
9156
|
+
}
|
|
9157
|
+
/**
|
|
9158
|
+
* Get refresh token
|
|
9159
|
+
*/
|
|
9160
|
+
getRefreshToken() {
|
|
9161
|
+
return this.refreshToken;
|
|
9162
|
+
}
|
|
9163
|
+
/**
|
|
9164
|
+
* Ensure access token is valid, refresh if missing or expired
|
|
9165
|
+
* Use this before making authenticated requests that need a valid token upfront
|
|
9166
|
+
* Note: Most requests don't need this as the 401 interceptor handles refresh automatically
|
|
9167
|
+
*/
|
|
9168
|
+
async ensureAccessToken() {
|
|
9169
|
+
if (this.accessToken) {
|
|
9170
|
+
return;
|
|
9171
|
+
}
|
|
9172
|
+
if (!this.refreshToken) {
|
|
9173
|
+
return;
|
|
9174
|
+
}
|
|
9175
|
+
try {
|
|
9176
|
+
await this.refreshAccessToken();
|
|
9177
|
+
} catch {
|
|
9178
|
+
}
|
|
9179
|
+
}
|
|
9180
|
+
/**
|
|
9181
|
+
* Refresh session and return user data
|
|
9182
|
+
* Use this when you need fresh user data (e.g., before passkey restoration)
|
|
9183
|
+
* @param timeoutMs - Timeout in milliseconds (default: 10000)
|
|
9184
|
+
* @returns User data from refresh response, or null if refresh fails
|
|
9185
|
+
*/
|
|
9186
|
+
async refreshSession(timeoutMs = 1e4) {
|
|
9187
|
+
if (!this.refreshToken) {
|
|
9188
|
+
throw new Error("No refresh token available. Please log in again.");
|
|
9189
|
+
}
|
|
9190
|
+
const timeoutPromise = new Promise(
|
|
9191
|
+
(_, reject) => setTimeout(
|
|
9192
|
+
() => reject(new Error("Session refresh timeout. Please check your network connection.")),
|
|
9193
|
+
timeoutMs
|
|
9194
|
+
)
|
|
9195
|
+
);
|
|
9196
|
+
const refreshPromise = this.api.post(
|
|
9197
|
+
"/auth/refresh",
|
|
9198
|
+
{ refreshToken: this.refreshToken }
|
|
9199
|
+
);
|
|
9200
|
+
const response = await Promise.race([refreshPromise, timeoutPromise]);
|
|
9201
|
+
const data = response.data;
|
|
9202
|
+
if (isErrorResponse(data)) {
|
|
9203
|
+
this.setAccessToken(null);
|
|
9204
|
+
this.setRefreshToken(null);
|
|
9205
|
+
throw new Error(data.error.message);
|
|
9206
|
+
}
|
|
9207
|
+
this.setAccessToken(data.data.accessToken);
|
|
9208
|
+
if (data.data.refreshToken) {
|
|
9209
|
+
this.setRefreshToken(data.data.refreshToken);
|
|
9210
|
+
}
|
|
9211
|
+
if (data.data.user) {
|
|
9212
|
+
safeStorage.setItem(STORAGE_KEYS.user, JSON.stringify(data.data.user));
|
|
9213
|
+
}
|
|
9214
|
+
return data.data.user ?? null;
|
|
9215
|
+
}
|
|
9135
9216
|
/**
|
|
9136
9217
|
* Refresh access token (single-flight)
|
|
9137
9218
|
*/
|
|
@@ -9139,19 +9220,26 @@ var APIClient = class {
|
|
|
9139
9220
|
if (this.refreshPromise) {
|
|
9140
9221
|
return this.refreshPromise;
|
|
9141
9222
|
}
|
|
9223
|
+
if (!this.refreshToken) {
|
|
9224
|
+
throw new Error("No refresh token available. Please log in again.");
|
|
9225
|
+
}
|
|
9142
9226
|
this.refreshPromise = (async () => {
|
|
9143
9227
|
try {
|
|
9144
9228
|
const response = await this.api.post(
|
|
9145
9229
|
"/auth/refresh",
|
|
9146
|
-
{}
|
|
9230
|
+
{ refreshToken: this.refreshToken }
|
|
9147
9231
|
);
|
|
9148
9232
|
const data = response.data;
|
|
9149
9233
|
if (isErrorResponse(data)) {
|
|
9150
9234
|
this.setAccessToken(null);
|
|
9235
|
+
this.setRefreshToken(null);
|
|
9151
9236
|
safeStorage.removeItem(STORAGE_KEYS.user);
|
|
9152
9237
|
throw new Error(data.error.message);
|
|
9153
9238
|
}
|
|
9154
9239
|
this.setAccessToken(data.data.accessToken);
|
|
9240
|
+
if (data.data.refreshToken) {
|
|
9241
|
+
this.setRefreshToken(data.data.refreshToken);
|
|
9242
|
+
}
|
|
9155
9243
|
if (data.data.user) {
|
|
9156
9244
|
safeStorage.setItem(STORAGE_KEYS.user, JSON.stringify(data.data.user));
|
|
9157
9245
|
}
|
|
@@ -9187,6 +9275,7 @@ var APIClient = class {
|
|
|
9187
9275
|
*/
|
|
9188
9276
|
async post(endpoint, body, idempotencyKey) {
|
|
9189
9277
|
const normalizedEndpoint = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
|
|
9278
|
+
console.log(`[APIClient] POST ${normalizedEndpoint}`);
|
|
9190
9279
|
const config = {
|
|
9191
9280
|
method: "POST",
|
|
9192
9281
|
url: normalizedEndpoint,
|
|
@@ -9197,8 +9286,14 @@ var APIClient = class {
|
|
|
9197
9286
|
"Idempotency-Key": idempotencyKey
|
|
9198
9287
|
};
|
|
9199
9288
|
}
|
|
9200
|
-
|
|
9201
|
-
|
|
9289
|
+
try {
|
|
9290
|
+
const response = await this.api.request(config);
|
|
9291
|
+
console.log(`[APIClient] POST ${normalizedEndpoint} response:`, response.data);
|
|
9292
|
+
return unwrapResponse(response.data);
|
|
9293
|
+
} catch (error) {
|
|
9294
|
+
console.error(`[APIClient] POST ${normalizedEndpoint} error:`, error);
|
|
9295
|
+
throw error;
|
|
9296
|
+
}
|
|
9202
9297
|
}
|
|
9203
9298
|
/**
|
|
9204
9299
|
* POST request that returns raw binary (ArrayBuffer)
|
|
@@ -9532,16 +9627,12 @@ async function restorePasskey(params) {
|
|
|
9532
9627
|
);
|
|
9533
9628
|
console.log("[restorePasskey] prfInput:", prfInput);
|
|
9534
9629
|
console.log("[restorePasskey] Step 1: Ensuring access token is fresh...");
|
|
9535
|
-
|
|
9536
|
-
|
|
9537
|
-
console.log("[restorePasskey]
|
|
9538
|
-
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
} catch (error) {
|
|
9542
|
-
console.error("[restorePasskey] Failed to refresh access token:", error);
|
|
9543
|
-
throw new Error("Failed to refresh access token. Please log in again.");
|
|
9544
|
-
}
|
|
9630
|
+
try {
|
|
9631
|
+
await client.ensureAccessToken();
|
|
9632
|
+
console.log("[restorePasskey] Access token ensured");
|
|
9633
|
+
} catch (error) {
|
|
9634
|
+
console.error("[restorePasskey] Failed to ensure access token:", error);
|
|
9635
|
+
throw new Error("Failed to refresh access token. Please log in again.");
|
|
9545
9636
|
}
|
|
9546
9637
|
console.log("[restorePasskey] Step 2: Downloading blob via backend proxy for blobUrl:", blobUrl);
|
|
9547
9638
|
const apiKey = client.getApiKey();
|
|
@@ -9653,6 +9744,9 @@ function VolrProvider({ config, children }) {
|
|
|
9653
9744
|
const [accessToken, setAccessTokenState] = react.useState(() => {
|
|
9654
9745
|
return client.getAccessToken();
|
|
9655
9746
|
});
|
|
9747
|
+
const [refreshToken, setRefreshTokenState] = react.useState(() => {
|
|
9748
|
+
return client.getRefreshToken();
|
|
9749
|
+
});
|
|
9656
9750
|
const syncRef = react.useRef(null);
|
|
9657
9751
|
react.useEffect(() => {
|
|
9658
9752
|
syncRef.current = new SessionSync();
|
|
@@ -9668,7 +9762,9 @@ function VolrProvider({ config, children }) {
|
|
|
9668
9762
|
client.setApiKey(config.projectApiKey);
|
|
9669
9763
|
} else if (event.type === "LOGOUT") {
|
|
9670
9764
|
client.setAccessToken(null);
|
|
9765
|
+
client.setRefreshToken(null);
|
|
9671
9766
|
setAccessTokenState(null);
|
|
9767
|
+
setRefreshTokenState(null);
|
|
9672
9768
|
setUser(null);
|
|
9673
9769
|
setProviderState(null);
|
|
9674
9770
|
safeStorage.removeItem(STORAGE_KEYS.user);
|
|
@@ -9697,49 +9793,16 @@ function VolrProvider({ config, children }) {
|
|
|
9697
9793
|
const keyStorageType = newProvider.keyStorageType;
|
|
9698
9794
|
setProviderState(newProvider);
|
|
9699
9795
|
try {
|
|
9700
|
-
const
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
if (refreshResponse.user) {
|
|
9705
|
-
console.log(
|
|
9706
|
-
"[Provider] setProvider: User data refreshed from backend:",
|
|
9707
|
-
refreshResponse.user
|
|
9708
|
-
);
|
|
9709
|
-
setUser(refreshResponse.user);
|
|
9710
|
-
safeStorage.setItem(
|
|
9711
|
-
STORAGE_KEYS.user,
|
|
9712
|
-
JSON.stringify(refreshResponse.user)
|
|
9713
|
-
);
|
|
9796
|
+
const refreshedUser = await client.refreshSession();
|
|
9797
|
+
if (refreshedUser) {
|
|
9798
|
+
console.log("[Provider] setProvider: User data refreshed:", refreshedUser);
|
|
9799
|
+
setUser(refreshedUser);
|
|
9714
9800
|
} else {
|
|
9715
|
-
setUser((prev) => ({
|
|
9716
|
-
...prev,
|
|
9717
|
-
keyStorageType
|
|
9718
|
-
}));
|
|
9719
|
-
safeStorage.setItem(
|
|
9720
|
-
STORAGE_KEYS.user,
|
|
9721
|
-
JSON.stringify({
|
|
9722
|
-
...user,
|
|
9723
|
-
keyStorageType
|
|
9724
|
-
})
|
|
9725
|
-
);
|
|
9801
|
+
setUser((prev) => ({ ...prev, keyStorageType }));
|
|
9726
9802
|
}
|
|
9727
9803
|
} catch (error2) {
|
|
9728
|
-
console.warn(
|
|
9729
|
-
|
|
9730
|
-
error2
|
|
9731
|
-
);
|
|
9732
|
-
setUser((prev) => ({
|
|
9733
|
-
...prev,
|
|
9734
|
-
keyStorageType
|
|
9735
|
-
}));
|
|
9736
|
-
safeStorage.setItem(
|
|
9737
|
-
STORAGE_KEYS.user,
|
|
9738
|
-
JSON.stringify({
|
|
9739
|
-
...user,
|
|
9740
|
-
keyStorageType
|
|
9741
|
-
})
|
|
9742
|
-
);
|
|
9804
|
+
console.warn("[Provider] setProvider: Failed to refresh user data:", error2);
|
|
9805
|
+
setUser((prev) => ({ ...prev, keyStorageType }));
|
|
9743
9806
|
}
|
|
9744
9807
|
safeStorage.setItem(STORAGE_KEYS.provider, keyStorageType);
|
|
9745
9808
|
syncRef.current?.broadcast({
|
|
@@ -9764,70 +9827,38 @@ function VolrProvider({ config, children }) {
|
|
|
9764
9827
|
const recover = async () => {
|
|
9765
9828
|
try {
|
|
9766
9829
|
setIsLoading(true);
|
|
9767
|
-
|
|
9768
|
-
"
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
const
|
|
9773
|
-
|
|
9774
|
-
|
|
9775
|
-
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
console.log("[Provider]
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
accountId: response.user.accountId,
|
|
9783
|
-
evmAddress: response.user.evmAddress,
|
|
9784
|
-
signerType: response.user.signerType,
|
|
9785
|
-
keyStorageType: response.user.keyStorageType,
|
|
9786
|
-
walletConnector: response.user.walletConnector,
|
|
9787
|
-
blobUrl: response.user.blobUrl,
|
|
9788
|
-
prfInput: response.user.prfInput,
|
|
9789
|
-
credentialId: response.user.credentialId
|
|
9790
|
-
});
|
|
9791
|
-
setUser(response.user);
|
|
9792
|
-
safeStorage.setItem(
|
|
9793
|
-
STORAGE_KEYS.user,
|
|
9794
|
-
JSON.stringify(response.user)
|
|
9795
|
-
);
|
|
9796
|
-
if (!REQUIRE_USER_GESTURE_TO_RESTORE) ; else {
|
|
9797
|
-
if (response.user.keyStorageType === "passkey") {
|
|
9798
|
-
console.log(
|
|
9799
|
-
"[Provider] TTL=0 mode: Provider restoration deferred until transaction (requires user gesture)"
|
|
9800
|
-
);
|
|
9801
|
-
if (!response.user.blobUrl || !response.user.prfInput) {
|
|
9802
|
-
console.warn(
|
|
9803
|
-
"[Provider] Passkey user detected but missing blobUrl or prfInput. User needs to re-enroll passkey."
|
|
9804
|
-
);
|
|
9805
|
-
}
|
|
9806
|
-
}
|
|
9830
|
+
if (!client.getRefreshToken()) {
|
|
9831
|
+
console.log("[Provider] No refresh token found, skipping auto-recover");
|
|
9832
|
+
setIsLoading(false);
|
|
9833
|
+
return;
|
|
9834
|
+
}
|
|
9835
|
+
const refreshedUser = await client.refreshSession();
|
|
9836
|
+
console.log("[Provider] Session refreshed, user:", refreshedUser);
|
|
9837
|
+
setAccessTokenState(client.getAccessToken());
|
|
9838
|
+
setRefreshTokenState(client.getRefreshToken());
|
|
9839
|
+
if (refreshedUser) {
|
|
9840
|
+
setUser(refreshedUser);
|
|
9841
|
+
if (!REQUIRE_USER_GESTURE_TO_RESTORE) ; else if (refreshedUser.keyStorageType === "passkey") {
|
|
9842
|
+
console.log("[Provider] TTL=0 mode: Provider restoration deferred");
|
|
9843
|
+
if (!refreshedUser.blobUrl || !refreshedUser.prfInput) {
|
|
9844
|
+
console.warn("[Provider] Passkey user missing blobUrl or prfInput");
|
|
9807
9845
|
}
|
|
9808
|
-
}
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
console.log(
|
|
9817
|
-
"[Provider] Loaded user from storage:",
|
|
9818
|
-
storedUser
|
|
9819
|
-
);
|
|
9820
|
-
setUser(storedUser);
|
|
9821
|
-
} catch {
|
|
9822
|
-
safeStorage.removeItem(STORAGE_KEYS.user);
|
|
9823
|
-
}
|
|
9846
|
+
}
|
|
9847
|
+
} else {
|
|
9848
|
+
const userStr = safeStorage.getItem(STORAGE_KEYS.user);
|
|
9849
|
+
if (userStr) {
|
|
9850
|
+
try {
|
|
9851
|
+
setUser(JSON.parse(userStr));
|
|
9852
|
+
} catch {
|
|
9853
|
+
safeStorage.removeItem(STORAGE_KEYS.user);
|
|
9824
9854
|
}
|
|
9825
9855
|
}
|
|
9826
|
-
setAccessTokenState(refreshedToken);
|
|
9827
9856
|
}
|
|
9828
9857
|
} catch {
|
|
9829
9858
|
client.setAccessToken(null);
|
|
9859
|
+
client.setRefreshToken(null);
|
|
9830
9860
|
setAccessTokenState(null);
|
|
9861
|
+
setRefreshTokenState(null);
|
|
9831
9862
|
setUser(null);
|
|
9832
9863
|
setProviderState(null);
|
|
9833
9864
|
safeStorage.removeItem(STORAGE_KEYS.user);
|
|
@@ -9845,12 +9876,7 @@ function VolrProvider({ config, children }) {
|
|
|
9845
9876
|
async (input) => {
|
|
9846
9877
|
try {
|
|
9847
9878
|
setError(null);
|
|
9848
|
-
|
|
9849
|
-
try {
|
|
9850
|
-
await client.post("/auth/refresh", {});
|
|
9851
|
-
} catch {
|
|
9852
|
-
}
|
|
9853
|
-
}
|
|
9879
|
+
await client.ensureAccessToken();
|
|
9854
9880
|
const response = await client.post(
|
|
9855
9881
|
"/wallet/precheck",
|
|
9856
9882
|
input
|
|
@@ -9872,12 +9898,7 @@ function VolrProvider({ config, children }) {
|
|
|
9872
9898
|
async (input, opts) => {
|
|
9873
9899
|
try {
|
|
9874
9900
|
setError(null);
|
|
9875
|
-
|
|
9876
|
-
try {
|
|
9877
|
-
await client.post("/auth/refresh", {});
|
|
9878
|
-
} catch {
|
|
9879
|
-
}
|
|
9880
|
-
}
|
|
9901
|
+
await client.ensureAccessToken();
|
|
9881
9902
|
const idempotencyKey = opts?.idempotencyKey ?? (typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}-${Math.random()}`);
|
|
9882
9903
|
const serializedInput = serializeBigIntDeep(input);
|
|
9883
9904
|
const response = await client.post(
|
|
@@ -9902,10 +9923,14 @@ function VolrProvider({ config, children }) {
|
|
|
9902
9923
|
try {
|
|
9903
9924
|
setError(null);
|
|
9904
9925
|
client.setAccessToken(null);
|
|
9926
|
+
client.setRefreshToken(null);
|
|
9927
|
+
setAccessTokenState(null);
|
|
9928
|
+
setRefreshTokenState(null);
|
|
9905
9929
|
setUser(null);
|
|
9906
9930
|
setProviderState(null);
|
|
9907
9931
|
safeStorage.removeItem(STORAGE_KEYS.user);
|
|
9908
9932
|
safeStorage.removeItem(STORAGE_KEYS.accessToken);
|
|
9933
|
+
safeStorage.removeItem(STORAGE_KEYS.refreshToken);
|
|
9909
9934
|
safeStorage.removeItem(STORAGE_KEYS.provider);
|
|
9910
9935
|
syncRef.current?.broadcast({ type: "LOGOUT" });
|
|
9911
9936
|
} catch (err) {
|
|
@@ -9990,22 +10015,25 @@ function VolrProvider({ config, children }) {
|
|
|
9990
10015
|
() => ({
|
|
9991
10016
|
session: {
|
|
9992
10017
|
accessToken,
|
|
9993
|
-
refreshToken
|
|
9994
|
-
// Cookie-based, opaque
|
|
10018
|
+
refreshToken
|
|
9995
10019
|
},
|
|
9996
10020
|
refreshAccessToken: async () => {
|
|
9997
|
-
await client.
|
|
9998
|
-
|
|
9999
|
-
|
|
10021
|
+
await client.ensureAccessToken();
|
|
10022
|
+
setAccessTokenState(client.getAccessToken());
|
|
10023
|
+
setRefreshTokenState(client.getRefreshToken());
|
|
10000
10024
|
},
|
|
10001
10025
|
setAccessToken: (token) => {
|
|
10002
10026
|
client.setAccessToken(token);
|
|
10003
10027
|
setAccessTokenState(token);
|
|
10004
10028
|
},
|
|
10029
|
+
setRefreshToken: (token) => {
|
|
10030
|
+
client.setRefreshToken(token);
|
|
10031
|
+
setRefreshTokenState(token);
|
|
10032
|
+
},
|
|
10005
10033
|
client
|
|
10006
10034
|
// Expose APIClient instance
|
|
10007
10035
|
}),
|
|
10008
|
-
[client, accessToken]
|
|
10036
|
+
[client, accessToken, refreshToken]
|
|
10009
10037
|
);
|
|
10010
10038
|
return /* @__PURE__ */ jsxRuntime.jsx(VolrContext.Provider, { value: publicValue, children: /* @__PURE__ */ jsxRuntime.jsx(InternalAuthContext.Provider, { value: internalValue, children }) });
|
|
10011
10039
|
}
|
|
@@ -18252,22 +18280,24 @@ async function sendCalls(args) {
|
|
|
18252
18280
|
console.log("[sendCalls] Calls normalized");
|
|
18253
18281
|
let currentUser = deps.user;
|
|
18254
18282
|
if (deps.user?.keyStorageType === "passkey" && !deps.provider) {
|
|
18255
|
-
console.log("[sendCalls] Refreshing user data...");
|
|
18283
|
+
console.log("[sendCalls] Refreshing user data (provider not available)...");
|
|
18256
18284
|
try {
|
|
18257
|
-
const
|
|
18258
|
-
|
|
18259
|
-
|
|
18260
|
-
|
|
18261
|
-
if (refreshResponse.user) {
|
|
18262
|
-
currentUser = refreshResponse.user;
|
|
18263
|
-
console.log("[sendCalls] User data refreshed");
|
|
18285
|
+
const refreshedUser = await deps.client.refreshSession();
|
|
18286
|
+
if (refreshedUser) {
|
|
18287
|
+
currentUser = refreshedUser;
|
|
18288
|
+
console.log("[sendCalls] User data refreshed successfully");
|
|
18264
18289
|
}
|
|
18265
18290
|
} catch (error) {
|
|
18266
|
-
console.
|
|
18267
|
-
|
|
18268
|
-
error
|
|
18291
|
+
console.error("[sendCalls] Failed to refresh session:", error);
|
|
18292
|
+
throw new Error(
|
|
18293
|
+
`Failed to refresh session before transaction. ${error instanceof Error ? error.message : "Unknown error"}. Please try logging in again.`
|
|
18269
18294
|
);
|
|
18270
18295
|
}
|
|
18296
|
+
} else {
|
|
18297
|
+
console.log("[sendCalls] Skipping user refresh:", {
|
|
18298
|
+
hasProvider: !!deps.provider,
|
|
18299
|
+
keyStorageType: deps.user?.keyStorageType
|
|
18300
|
+
});
|
|
18271
18301
|
}
|
|
18272
18302
|
if (opts.preflight !== false) {
|
|
18273
18303
|
console.log("[sendCalls] Running preflight estimate...");
|
|
@@ -18479,41 +18509,9 @@ function useVolrWallet() {
|
|
|
18479
18509
|
);
|
|
18480
18510
|
return { evm };
|
|
18481
18511
|
}
|
|
18482
|
-
function createAxiosInstance(baseUrl, apiKey) {
|
|
18483
|
-
const instance = axios__default.default.create({
|
|
18484
|
-
baseURL: baseUrl.replace(/\/+$/, ""),
|
|
18485
|
-
// Remove trailing slashes
|
|
18486
|
-
withCredentials: true,
|
|
18487
|
-
// Include cookies
|
|
18488
|
-
headers: {
|
|
18489
|
-
"Content-Type": "application/json"
|
|
18490
|
-
}
|
|
18491
|
-
});
|
|
18492
|
-
instance.interceptors.request.use((config) => {
|
|
18493
|
-
if (apiKey) {
|
|
18494
|
-
config.headers["X-API-Key"] = apiKey;
|
|
18495
|
-
}
|
|
18496
|
-
return config;
|
|
18497
|
-
});
|
|
18498
|
-
instance.interceptors.response.use(
|
|
18499
|
-
(response) => response,
|
|
18500
|
-
(error) => {
|
|
18501
|
-
if (error.response?.data) {
|
|
18502
|
-
const errorData = error.response.data;
|
|
18503
|
-
if (errorData.error?.message) {
|
|
18504
|
-
error.message = errorData.error.message;
|
|
18505
|
-
}
|
|
18506
|
-
}
|
|
18507
|
-
return Promise.reject(error);
|
|
18508
|
-
}
|
|
18509
|
-
);
|
|
18510
|
-
return instance;
|
|
18511
|
-
}
|
|
18512
|
-
|
|
18513
|
-
// src/hooks/useVolrLogin.ts
|
|
18514
18512
|
function useVolrLogin() {
|
|
18515
18513
|
const { config, setUser } = useVolr();
|
|
18516
|
-
const { setAccessToken } = useInternalAuth();
|
|
18514
|
+
const { setAccessToken, setRefreshToken, client } = useInternalAuth();
|
|
18517
18515
|
const toVolrUser = react.useCallback((u) => {
|
|
18518
18516
|
return {
|
|
18519
18517
|
id: u.id,
|
|
@@ -18530,27 +18528,18 @@ function useVolrLogin() {
|
|
|
18530
18528
|
};
|
|
18531
18529
|
}, []);
|
|
18532
18530
|
const apiBaseUrl = resolveApiBaseUrl(config);
|
|
18533
|
-
const api = react.useMemo(
|
|
18534
|
-
() => createAxiosInstance(apiBaseUrl, config.projectApiKey),
|
|
18535
|
-
[apiBaseUrl, config.projectApiKey]
|
|
18536
|
-
);
|
|
18537
18531
|
const requestEmailCode = react.useCallback(
|
|
18538
18532
|
async (email) => {
|
|
18539
18533
|
const normalizedEmail = email.trim().toLowerCase();
|
|
18540
18534
|
if (!normalizedEmail || !normalizedEmail.includes("@")) {
|
|
18541
18535
|
throw new Error("Invalid email address");
|
|
18542
18536
|
}
|
|
18543
|
-
|
|
18537
|
+
await client.post("/auth/email/send", {
|
|
18544
18538
|
email: normalizedEmail
|
|
18545
18539
|
});
|
|
18546
|
-
if (!response.data?.ok) {
|
|
18547
|
-
throw new Error(
|
|
18548
|
-
response.data?.error?.message || "Failed to send verification code"
|
|
18549
|
-
);
|
|
18550
|
-
}
|
|
18551
18540
|
safeStorage.setItem(STORAGE_KEYS.lastEmail, normalizedEmail);
|
|
18552
18541
|
},
|
|
18553
|
-
[
|
|
18542
|
+
[client]
|
|
18554
18543
|
);
|
|
18555
18544
|
const verifyEmailCode = react.useCallback(
|
|
18556
18545
|
async (email, code) => {
|
|
@@ -18562,25 +18551,18 @@ function useVolrLogin() {
|
|
|
18562
18551
|
if (!/^\d{6}$/.test(normalizedCode)) {
|
|
18563
18552
|
throw new Error("Invalid code format");
|
|
18564
18553
|
}
|
|
18565
|
-
const response = await
|
|
18554
|
+
const response = await client.post("/auth/email/verify", {
|
|
18566
18555
|
email: normalizedEmail,
|
|
18567
18556
|
code: normalizedCode
|
|
18568
18557
|
});
|
|
18569
|
-
|
|
18570
|
-
throw new Error(
|
|
18571
|
-
response.data?.error?.message || "Invalid verification code"
|
|
18572
|
-
);
|
|
18573
|
-
}
|
|
18574
|
-
const verifyData = response.data;
|
|
18575
|
-
const userFromServer = verifyData?.data?.user;
|
|
18576
|
-
const isNewUser = !!verifyData?.data?.isNewUser;
|
|
18577
|
-
const accessToken = verifyData?.data?.accessToken || "";
|
|
18558
|
+
const { user: userFromServer, isNewUser, accessToken, refreshToken } = response;
|
|
18578
18559
|
if (!accessToken) {
|
|
18579
|
-
throw new Error(
|
|
18580
|
-
"Access token is required but was not provided by the server"
|
|
18581
|
-
);
|
|
18560
|
+
throw new Error("Access token is required but was not provided by the server");
|
|
18582
18561
|
}
|
|
18583
18562
|
setAccessToken(accessToken);
|
|
18563
|
+
if (refreshToken) {
|
|
18564
|
+
setRefreshToken(refreshToken);
|
|
18565
|
+
}
|
|
18584
18566
|
if (userFromServer) {
|
|
18585
18567
|
setUser(toVolrUser(userFromServer));
|
|
18586
18568
|
} else {
|
|
@@ -18594,7 +18576,7 @@ function useVolrLogin() {
|
|
|
18594
18576
|
accessToken
|
|
18595
18577
|
};
|
|
18596
18578
|
},
|
|
18597
|
-
[
|
|
18579
|
+
[client, setAccessToken, setRefreshToken, setUser, toVolrUser]
|
|
18598
18580
|
);
|
|
18599
18581
|
const handleSocialLogin = react.useCallback(
|
|
18600
18582
|
async (provider) => {
|
|
@@ -18606,42 +18588,26 @@ function useVolrLogin() {
|
|
|
18606
18588
|
[apiBaseUrl, config.projectApiKey]
|
|
18607
18589
|
);
|
|
18608
18590
|
const requestSiweNonce = react.useCallback(async () => {
|
|
18609
|
-
const response = await
|
|
18610
|
-
|
|
18611
|
-
|
|
18612
|
-
response.data?.error?.message || "Failed to generate nonce"
|
|
18613
|
-
);
|
|
18614
|
-
}
|
|
18615
|
-
return response.data.data.nonce;
|
|
18616
|
-
}, [api]);
|
|
18591
|
+
const response = await client.get("/auth/siwe/nonce");
|
|
18592
|
+
return response.nonce;
|
|
18593
|
+
}, [client]);
|
|
18617
18594
|
const verifySiweSignature = react.useCallback(
|
|
18618
18595
|
async (message, signature, options) => {
|
|
18619
18596
|
try {
|
|
18620
|
-
const response = await
|
|
18597
|
+
const response = await client.post("/auth/siwe/verify", {
|
|
18621
18598
|
message,
|
|
18622
18599
|
signature,
|
|
18623
18600
|
walletConnector: options?.walletConnector,
|
|
18624
18601
|
chainId: options?.chainId
|
|
18625
18602
|
});
|
|
18626
|
-
|
|
18627
|
-
console.error(
|
|
18628
|
-
"[verifySiweSignature] Backend returned error:",
|
|
18629
|
-
response.data
|
|
18630
|
-
);
|
|
18631
|
-
throw new Error(
|
|
18632
|
-
response.data?.error?.message || "Invalid SIWE signature"
|
|
18633
|
-
);
|
|
18634
|
-
}
|
|
18635
|
-
const verifyData = response.data;
|
|
18636
|
-
const userFromServer = verifyData?.data?.user;
|
|
18637
|
-
const isNewUser = !!verifyData?.data?.isNewUser;
|
|
18638
|
-
const accessToken = verifyData?.data?.accessToken || "";
|
|
18603
|
+
const { user: userFromServer, isNewUser, accessToken, refreshToken } = response;
|
|
18639
18604
|
if (!accessToken) {
|
|
18640
|
-
throw new Error(
|
|
18641
|
-
"Access token is required but was not provided by the server"
|
|
18642
|
-
);
|
|
18605
|
+
throw new Error("Access token is required but was not provided by the server");
|
|
18643
18606
|
}
|
|
18644
18607
|
setAccessToken(accessToken);
|
|
18608
|
+
if (refreshToken) {
|
|
18609
|
+
setRefreshToken(refreshToken);
|
|
18610
|
+
}
|
|
18645
18611
|
if (userFromServer) {
|
|
18646
18612
|
setUser(toVolrUser(userFromServer));
|
|
18647
18613
|
}
|
|
@@ -18661,7 +18627,7 @@ function useVolrLogin() {
|
|
|
18661
18627
|
throw error;
|
|
18662
18628
|
}
|
|
18663
18629
|
},
|
|
18664
|
-
[
|
|
18630
|
+
[client, setAccessToken, setRefreshToken, setUser, toVolrUser]
|
|
18665
18631
|
);
|
|
18666
18632
|
const handlePasskeyComplete = react.useCallback(async () => {
|
|
18667
18633
|
}, []);
|
|
@@ -18674,9 +18640,41 @@ function useVolrLogin() {
|
|
|
18674
18640
|
handlePasskeyComplete
|
|
18675
18641
|
};
|
|
18676
18642
|
}
|
|
18643
|
+
function createAxiosInstance(baseUrl, apiKey) {
|
|
18644
|
+
const instance = axios__default.default.create({
|
|
18645
|
+
baseURL: baseUrl.replace(/\/+$/, ""),
|
|
18646
|
+
// Remove trailing slashes
|
|
18647
|
+
withCredentials: true,
|
|
18648
|
+
// Include cookies
|
|
18649
|
+
headers: {
|
|
18650
|
+
"Content-Type": "application/json"
|
|
18651
|
+
}
|
|
18652
|
+
});
|
|
18653
|
+
instance.interceptors.request.use((config) => {
|
|
18654
|
+
if (apiKey) {
|
|
18655
|
+
config.headers["X-API-Key"] = apiKey;
|
|
18656
|
+
}
|
|
18657
|
+
return config;
|
|
18658
|
+
});
|
|
18659
|
+
instance.interceptors.response.use(
|
|
18660
|
+
(response) => response,
|
|
18661
|
+
(error) => {
|
|
18662
|
+
if (error.response?.data) {
|
|
18663
|
+
const errorData = error.response.data;
|
|
18664
|
+
if (errorData.error?.message) {
|
|
18665
|
+
error.message = errorData.error.message;
|
|
18666
|
+
}
|
|
18667
|
+
}
|
|
18668
|
+
return Promise.reject(error);
|
|
18669
|
+
}
|
|
18670
|
+
);
|
|
18671
|
+
return instance;
|
|
18672
|
+
}
|
|
18673
|
+
|
|
18674
|
+
// src/hooks/useVolrAuthCallback.ts
|
|
18677
18675
|
function useVolrAuthCallback(options = {}) {
|
|
18678
18676
|
const { config, setUser } = useVolr();
|
|
18679
|
-
const { refreshAccessToken, setAccessToken } = useInternalAuth();
|
|
18677
|
+
const { refreshAccessToken, setAccessToken, setRefreshToken, client } = useInternalAuth();
|
|
18680
18678
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
18681
18679
|
const [error, setError] = react.useState(null);
|
|
18682
18680
|
const [isNewUser, setIsNewUser] = react.useState(false);
|
|
@@ -18730,13 +18728,21 @@ function useVolrAuthCallback(options = {}) {
|
|
|
18730
18728
|
if (!userRes.data?.ok) {
|
|
18731
18729
|
throw new Error("Failed to fetch user details");
|
|
18732
18730
|
}
|
|
18733
|
-
const
|
|
18731
|
+
const currentRefreshToken = client.getRefreshToken();
|
|
18732
|
+
if (!currentRefreshToken) {
|
|
18733
|
+
throw new Error("No refresh token available. Please log in again.");
|
|
18734
|
+
}
|
|
18735
|
+
const refreshRes = await api.post("/auth/refresh", { refreshToken: currentRefreshToken });
|
|
18734
18736
|
if (!refreshRes.data?.ok) {
|
|
18735
18737
|
throw new Error("Failed to refresh session");
|
|
18736
18738
|
}
|
|
18737
18739
|
const userData = refreshRes.data.data.user;
|
|
18738
18740
|
const accessToken = refreshRes.data.data.accessToken;
|
|
18741
|
+
const newRefreshToken = refreshRes.data.data.refreshToken;
|
|
18739
18742
|
setAccessToken(accessToken);
|
|
18743
|
+
if (newRefreshToken) {
|
|
18744
|
+
setRefreshToken(newRefreshToken);
|
|
18745
|
+
}
|
|
18740
18746
|
const volrUser = toVolrUser(userData);
|
|
18741
18747
|
setUser(volrUser);
|
|
18742
18748
|
setLocalUser(volrUser);
|
|
@@ -18751,7 +18757,7 @@ function useVolrAuthCallback(options = {}) {
|
|
|
18751
18757
|
}
|
|
18752
18758
|
};
|
|
18753
18759
|
handleCallback();
|
|
18754
|
-
}, [apiBaseUrl, config.projectApiKey, refreshAccessToken, setAccessToken, setUser, toVolrUser]);
|
|
18760
|
+
}, [apiBaseUrl, config.projectApiKey, refreshAccessToken, setAccessToken, setRefreshToken, setUser, toVolrUser, client]);
|
|
18755
18761
|
return {
|
|
18756
18762
|
isLoading,
|
|
18757
18763
|
error,
|