@volr/react 0.1.13 → 0.1.15
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 +228 -145
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +228 -145
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -9033,6 +9033,7 @@ var safeStorage = {
|
|
|
9033
9033
|
// ../shared/src/constants/storage.ts
|
|
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
|
}
|
|
@@ -17893,15 +17921,20 @@ var CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
|
17893
17921
|
function createGetRpcUrl(deps) {
|
|
17894
17922
|
const { client, rpcOverrides } = deps;
|
|
17895
17923
|
return async function getRpcUrl(chainId) {
|
|
17924
|
+
console.log("[getRpcUrl] Getting RPC URL for chainId:", chainId);
|
|
17896
17925
|
const overrideUrl = rpcOverrides?.[chainId.toString()];
|
|
17897
17926
|
if (overrideUrl) {
|
|
17927
|
+
console.log("[getRpcUrl] Using override URL");
|
|
17898
17928
|
return overrideUrl;
|
|
17899
17929
|
}
|
|
17900
17930
|
const cached = networkCache.get(chainId);
|
|
17901
17931
|
if (cached && cached.rpcUrl && Date.now() - cached.timestamp < CACHE_TTL_MS) {
|
|
17932
|
+
console.log("[getRpcUrl] Using cached URL");
|
|
17902
17933
|
return cached.rpcUrl;
|
|
17903
17934
|
}
|
|
17935
|
+
console.log("[getRpcUrl] Fetching from backend API...");
|
|
17904
17936
|
const response = await client.get(`/networks/${chainId}?includeRpcUrl=true`);
|
|
17937
|
+
console.log("[getRpcUrl] Backend response received");
|
|
17905
17938
|
if (!response.rpcUrl) {
|
|
17906
17939
|
throw new Error(
|
|
17907
17940
|
`RPC URL not available for chainId ${chainId}. Please provide it in config.rpcOverrides[${chainId}]`
|
|
@@ -17912,6 +17945,7 @@ function createGetRpcUrl(deps) {
|
|
|
17912
17945
|
name: response.name,
|
|
17913
17946
|
timestamp: Date.now()
|
|
17914
17947
|
});
|
|
17948
|
+
console.log("[getRpcUrl] RPC URL fetched and cached");
|
|
17915
17949
|
return response.rpcUrl;
|
|
17916
17950
|
};
|
|
17917
17951
|
}
|
|
@@ -18234,31 +18268,39 @@ async function pollTransactionStatus(txId, client, maxAttempts = 60, intervalMs
|
|
|
18234
18268
|
|
|
18235
18269
|
// src/wallet/sender.ts
|
|
18236
18270
|
async function sendCalls(args) {
|
|
18271
|
+
console.log("[sendCalls] Starting sendCalls...");
|
|
18237
18272
|
const { chainId, from: from14, calls, opts, deps } = args;
|
|
18238
18273
|
if (chainId === 0) {
|
|
18239
18274
|
throw new Error("chainId cannot be 0");
|
|
18240
18275
|
}
|
|
18276
|
+
console.log("[sendCalls] Normalizing calls...");
|
|
18241
18277
|
const normalizedFrom = from14;
|
|
18242
18278
|
const normalizedCalls = normalizeCalls(calls);
|
|
18243
18279
|
validateCalls2(normalizedCalls);
|
|
18280
|
+
console.log("[sendCalls] Calls normalized");
|
|
18244
18281
|
let currentUser = deps.user;
|
|
18245
18282
|
if (deps.user?.keyStorageType === "passkey" && !deps.provider) {
|
|
18283
|
+
console.log("[sendCalls] Refreshing user data (provider not available)...");
|
|
18246
18284
|
try {
|
|
18247
|
-
const
|
|
18248
|
-
|
|
18249
|
-
|
|
18250
|
-
|
|
18251
|
-
if (refreshResponse.user) {
|
|
18252
|
-
currentUser = refreshResponse.user;
|
|
18285
|
+
const refreshedUser = await deps.client.refreshSession();
|
|
18286
|
+
if (refreshedUser) {
|
|
18287
|
+
currentUser = refreshedUser;
|
|
18288
|
+
console.log("[sendCalls] User data refreshed successfully");
|
|
18253
18289
|
}
|
|
18254
18290
|
} catch (error) {
|
|
18255
|
-
console.
|
|
18256
|
-
|
|
18257
|
-
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.`
|
|
18258
18294
|
);
|
|
18259
18295
|
}
|
|
18296
|
+
} else {
|
|
18297
|
+
console.log("[sendCalls] Skipping user refresh:", {
|
|
18298
|
+
hasProvider: !!deps.provider,
|
|
18299
|
+
keyStorageType: deps.user?.keyStorageType
|
|
18300
|
+
});
|
|
18260
18301
|
}
|
|
18261
18302
|
if (opts.preflight !== false) {
|
|
18303
|
+
console.log("[sendCalls] Running preflight estimate...");
|
|
18262
18304
|
const tolerateFundingErrors = (opts.mode ?? "sponsored") !== "self";
|
|
18263
18305
|
await preflightEstimate(
|
|
18264
18306
|
deps.publicClient,
|
|
@@ -18266,7 +18308,11 @@ async function sendCalls(args) {
|
|
|
18266
18308
|
normalizedCalls,
|
|
18267
18309
|
{ tolerateFundingErrors }
|
|
18268
18310
|
);
|
|
18311
|
+
console.log("[sendCalls] Preflight estimate done");
|
|
18312
|
+
} else {
|
|
18313
|
+
console.log("[sendCalls] Preflight skipped");
|
|
18269
18314
|
}
|
|
18315
|
+
console.log("[sendCalls] Building temp auth for first precheck...");
|
|
18270
18316
|
const tempAuthForPrecheck = buildTempAuth({
|
|
18271
18317
|
chainId,
|
|
18272
18318
|
from: normalizedFrom,
|
|
@@ -18276,11 +18322,14 @@ async function sendCalls(args) {
|
|
|
18276
18322
|
});
|
|
18277
18323
|
let precheckQuote;
|
|
18278
18324
|
try {
|
|
18325
|
+
console.log("[sendCalls] Running first precheck...");
|
|
18279
18326
|
precheckQuote = await deps.precheck({
|
|
18280
18327
|
auth: tempAuthForPrecheck,
|
|
18281
18328
|
calls: normalizedCalls
|
|
18282
18329
|
});
|
|
18330
|
+
console.log("[sendCalls] First precheck done, policyId:", precheckQuote.policyId);
|
|
18283
18331
|
} catch (err) {
|
|
18332
|
+
console.error("[sendCalls] First precheck failed:", err);
|
|
18284
18333
|
throw err instanceof Error ? err : new Error(String(err));
|
|
18285
18334
|
}
|
|
18286
18335
|
const quotePolicyId = precheckQuote.policyId;
|
|
@@ -18289,6 +18338,7 @@ async function sendCalls(args) {
|
|
|
18289
18338
|
}
|
|
18290
18339
|
const projectPolicyId = quotePolicyId;
|
|
18291
18340
|
validatePolicyId2(projectPolicyId);
|
|
18341
|
+
console.log("[sendCalls] Building temp auth for second precheck...");
|
|
18292
18342
|
const tempAuth = buildTempAuth({
|
|
18293
18343
|
chainId,
|
|
18294
18344
|
from: normalizedFrom,
|
|
@@ -18298,15 +18348,19 @@ async function sendCalls(args) {
|
|
|
18298
18348
|
});
|
|
18299
18349
|
let quote;
|
|
18300
18350
|
try {
|
|
18351
|
+
console.log("[sendCalls] Running second precheck...");
|
|
18301
18352
|
quote = await deps.precheck({ auth: tempAuth, calls: normalizedCalls });
|
|
18353
|
+
console.log("[sendCalls] Second precheck done");
|
|
18302
18354
|
} catch (err) {
|
|
18303
|
-
console.warn("[
|
|
18355
|
+
console.warn("[sendCalls] Second precheck failed:", err);
|
|
18304
18356
|
}
|
|
18357
|
+
console.log("[sendCalls] Finalizing auth with nonce...");
|
|
18305
18358
|
const auth = finalizeAuthWithNonce(tempAuth, quote);
|
|
18306
18359
|
const idempotencyKey = opts.idempotencyKey ?? defaultIdempotencyKey();
|
|
18307
18360
|
let signer;
|
|
18308
18361
|
let activeProvider = null;
|
|
18309
18362
|
try {
|
|
18363
|
+
console.log("[sendCalls] Resolving signer...");
|
|
18310
18364
|
const resolved = await resolveSigner({
|
|
18311
18365
|
explicitSigner: void 0,
|
|
18312
18366
|
// Always resolve internally
|
|
@@ -18318,13 +18372,16 @@ async function sendCalls(args) {
|
|
|
18318
18372
|
});
|
|
18319
18373
|
signer = resolved.signer;
|
|
18320
18374
|
activeProvider = resolved.activeProvider;
|
|
18375
|
+
console.log("[sendCalls] Signer resolved");
|
|
18376
|
+
console.log("[sendCalls] Calling relay...");
|
|
18321
18377
|
const result = await deps.relay(
|
|
18322
18378
|
{ chainId, from: normalizedFrom, auth, calls: normalizedCalls },
|
|
18323
18379
|
{ signer, rpcClient: deps.rpcClient, idempotencyKey }
|
|
18324
18380
|
);
|
|
18381
|
+
console.log("[sendCalls] Relay result:", result.status, result.txId);
|
|
18325
18382
|
if (result.status === "QUEUED" || result.status === "PENDING") {
|
|
18326
18383
|
console.log(
|
|
18327
|
-
`[
|
|
18384
|
+
`[sendCalls] Transaction ${result.txId} is ${result.status}, starting polling...`
|
|
18328
18385
|
);
|
|
18329
18386
|
return pollTransactionStatus(result.txId, deps.client);
|
|
18330
18387
|
}
|
|
@@ -18358,11 +18415,14 @@ function useVolrWallet() {
|
|
|
18358
18415
|
let extendedRpcClient = null;
|
|
18359
18416
|
const ensureRpcClient = async () => {
|
|
18360
18417
|
if (!publicClient) {
|
|
18418
|
+
console.log("[ensureRpcClient] Getting RPC URL for chainId:", chainId);
|
|
18361
18419
|
const rpcUrl = await getRpcUrl(chainId);
|
|
18420
|
+
console.log("[ensureRpcClient] Got RPC URL:", rpcUrl);
|
|
18362
18421
|
publicClient = createPublicClient({
|
|
18363
18422
|
transport: http(rpcUrl)
|
|
18364
18423
|
});
|
|
18365
18424
|
extendedRpcClient = createExtendedRPCClient(publicClient);
|
|
18425
|
+
console.log("[ensureRpcClient] Public client created");
|
|
18366
18426
|
}
|
|
18367
18427
|
return { publicClient, extendedRpcClient };
|
|
18368
18428
|
};
|
|
@@ -18403,8 +18463,12 @@ function useVolrWallet() {
|
|
|
18403
18463
|
});
|
|
18404
18464
|
},
|
|
18405
18465
|
sendBatch: (async (calls, opts) => {
|
|
18466
|
+
console.log("[sendBatch] Starting sendBatch...", { chainId, callsCount: calls.length });
|
|
18467
|
+
console.log("[sendBatch] Ensuring RPC client...");
|
|
18406
18468
|
const { publicClient: publicClient2, extendedRpcClient: rpcClient } = await ensureRpcClient();
|
|
18469
|
+
console.log("[sendBatch] RPC client ready");
|
|
18407
18470
|
const from14 = opts.from ?? user?.evmAddress;
|
|
18471
|
+
console.log("[sendBatch] From address:", from14);
|
|
18408
18472
|
if (!from14) {
|
|
18409
18473
|
throw new Error(
|
|
18410
18474
|
"from address is required. Provide it in opts.from or set user.evmAddress in VolrProvider. If you haven't set up a wallet provider yet, please complete the onboarding flow."
|
|
@@ -18413,7 +18477,10 @@ function useVolrWallet() {
|
|
|
18413
18477
|
const isCallArray = (calls2) => {
|
|
18414
18478
|
return Array.isArray(calls2) && calls2.length > 0 && "data" in calls2[0] && !("abi" in calls2[0]);
|
|
18415
18479
|
};
|
|
18480
|
+
console.log("[sendBatch] Building calls...");
|
|
18416
18481
|
const builtCalls = isCallArray(calls) ? calls : buildCalls(calls);
|
|
18482
|
+
console.log("[sendBatch] Calls built:", builtCalls.length);
|
|
18483
|
+
console.log("[sendBatch] Calling sendCalls...");
|
|
18417
18484
|
return sendCalls({
|
|
18418
18485
|
chainId,
|
|
18419
18486
|
from: getAddress(from14),
|
|
@@ -18476,7 +18543,7 @@ function createAxiosInstance(baseUrl, apiKey) {
|
|
|
18476
18543
|
// src/hooks/useVolrLogin.ts
|
|
18477
18544
|
function useVolrLogin() {
|
|
18478
18545
|
const { config, setUser } = useVolr();
|
|
18479
|
-
const { setAccessToken } = useInternalAuth();
|
|
18546
|
+
const { setAccessToken, setRefreshToken } = useInternalAuth();
|
|
18480
18547
|
const toVolrUser = react.useCallback((u) => {
|
|
18481
18548
|
return {
|
|
18482
18549
|
id: u.id,
|
|
@@ -18538,12 +18605,16 @@ function useVolrLogin() {
|
|
|
18538
18605
|
const userFromServer = verifyData?.data?.user;
|
|
18539
18606
|
const isNewUser = !!verifyData?.data?.isNewUser;
|
|
18540
18607
|
const accessToken = verifyData?.data?.accessToken || "";
|
|
18608
|
+
const refreshToken = verifyData?.data?.refreshToken || "";
|
|
18541
18609
|
if (!accessToken) {
|
|
18542
18610
|
throw new Error(
|
|
18543
18611
|
"Access token is required but was not provided by the server"
|
|
18544
18612
|
);
|
|
18545
18613
|
}
|
|
18546
18614
|
setAccessToken(accessToken);
|
|
18615
|
+
if (refreshToken) {
|
|
18616
|
+
setRefreshToken(refreshToken);
|
|
18617
|
+
}
|
|
18547
18618
|
if (userFromServer) {
|
|
18548
18619
|
setUser(toVolrUser(userFromServer));
|
|
18549
18620
|
} else {
|
|
@@ -18557,7 +18628,7 @@ function useVolrLogin() {
|
|
|
18557
18628
|
accessToken
|
|
18558
18629
|
};
|
|
18559
18630
|
},
|
|
18560
|
-
[api, setAccessToken, setUser, toVolrUser]
|
|
18631
|
+
[api, setAccessToken, setRefreshToken, setUser, toVolrUser]
|
|
18561
18632
|
);
|
|
18562
18633
|
const handleSocialLogin = react.useCallback(
|
|
18563
18634
|
async (provider) => {
|
|
@@ -18599,12 +18670,16 @@ function useVolrLogin() {
|
|
|
18599
18670
|
const userFromServer = verifyData?.data?.user;
|
|
18600
18671
|
const isNewUser = !!verifyData?.data?.isNewUser;
|
|
18601
18672
|
const accessToken = verifyData?.data?.accessToken || "";
|
|
18673
|
+
const refreshToken = verifyData?.data?.refreshToken || "";
|
|
18602
18674
|
if (!accessToken) {
|
|
18603
18675
|
throw new Error(
|
|
18604
18676
|
"Access token is required but was not provided by the server"
|
|
18605
18677
|
);
|
|
18606
18678
|
}
|
|
18607
18679
|
setAccessToken(accessToken);
|
|
18680
|
+
if (refreshToken) {
|
|
18681
|
+
setRefreshToken(refreshToken);
|
|
18682
|
+
}
|
|
18608
18683
|
if (userFromServer) {
|
|
18609
18684
|
setUser(toVolrUser(userFromServer));
|
|
18610
18685
|
}
|
|
@@ -18624,7 +18699,7 @@ function useVolrLogin() {
|
|
|
18624
18699
|
throw error;
|
|
18625
18700
|
}
|
|
18626
18701
|
},
|
|
18627
|
-
[api, setAccessToken, setUser, toVolrUser]
|
|
18702
|
+
[api, setAccessToken, setRefreshToken, setUser, toVolrUser]
|
|
18628
18703
|
);
|
|
18629
18704
|
const handlePasskeyComplete = react.useCallback(async () => {
|
|
18630
18705
|
}, []);
|
|
@@ -18639,7 +18714,7 @@ function useVolrLogin() {
|
|
|
18639
18714
|
}
|
|
18640
18715
|
function useVolrAuthCallback(options = {}) {
|
|
18641
18716
|
const { config, setUser } = useVolr();
|
|
18642
|
-
const { refreshAccessToken, setAccessToken } = useInternalAuth();
|
|
18717
|
+
const { refreshAccessToken, setAccessToken, setRefreshToken, client } = useInternalAuth();
|
|
18643
18718
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
18644
18719
|
const [error, setError] = react.useState(null);
|
|
18645
18720
|
const [isNewUser, setIsNewUser] = react.useState(false);
|
|
@@ -18693,13 +18768,21 @@ function useVolrAuthCallback(options = {}) {
|
|
|
18693
18768
|
if (!userRes.data?.ok) {
|
|
18694
18769
|
throw new Error("Failed to fetch user details");
|
|
18695
18770
|
}
|
|
18696
|
-
const
|
|
18771
|
+
const currentRefreshToken = client.getRefreshToken();
|
|
18772
|
+
if (!currentRefreshToken) {
|
|
18773
|
+
throw new Error("No refresh token available. Please log in again.");
|
|
18774
|
+
}
|
|
18775
|
+
const refreshRes = await api.post("/auth/refresh", { refreshToken: currentRefreshToken });
|
|
18697
18776
|
if (!refreshRes.data?.ok) {
|
|
18698
18777
|
throw new Error("Failed to refresh session");
|
|
18699
18778
|
}
|
|
18700
18779
|
const userData = refreshRes.data.data.user;
|
|
18701
18780
|
const accessToken = refreshRes.data.data.accessToken;
|
|
18781
|
+
const newRefreshToken = refreshRes.data.data.refreshToken;
|
|
18702
18782
|
setAccessToken(accessToken);
|
|
18783
|
+
if (newRefreshToken) {
|
|
18784
|
+
setRefreshToken(newRefreshToken);
|
|
18785
|
+
}
|
|
18703
18786
|
const volrUser = toVolrUser(userData);
|
|
18704
18787
|
setUser(volrUser);
|
|
18705
18788
|
setLocalUser(volrUser);
|
|
@@ -18714,7 +18797,7 @@ function useVolrAuthCallback(options = {}) {
|
|
|
18714
18797
|
}
|
|
18715
18798
|
};
|
|
18716
18799
|
handleCallback();
|
|
18717
|
-
}, [apiBaseUrl, config.projectApiKey, refreshAccessToken, setAccessToken, setUser, toVolrUser]);
|
|
18800
|
+
}, [apiBaseUrl, config.projectApiKey, refreshAccessToken, setAccessToken, setRefreshToken, setUser, toVolrUser, client]);
|
|
18718
18801
|
return {
|
|
18719
18802
|
isLoading,
|
|
18720
18803
|
error,
|