@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.js
CHANGED
|
@@ -9009,6 +9009,7 @@ var safeStorage = {
|
|
|
9009
9009
|
// ../shared/src/constants/storage.ts
|
|
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
|
}
|
|
@@ -17869,15 +17897,20 @@ var CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
|
17869
17897
|
function createGetRpcUrl(deps) {
|
|
17870
17898
|
const { client, rpcOverrides } = deps;
|
|
17871
17899
|
return async function getRpcUrl(chainId) {
|
|
17900
|
+
console.log("[getRpcUrl] Getting RPC URL for chainId:", chainId);
|
|
17872
17901
|
const overrideUrl = rpcOverrides?.[chainId.toString()];
|
|
17873
17902
|
if (overrideUrl) {
|
|
17903
|
+
console.log("[getRpcUrl] Using override URL");
|
|
17874
17904
|
return overrideUrl;
|
|
17875
17905
|
}
|
|
17876
17906
|
const cached = networkCache.get(chainId);
|
|
17877
17907
|
if (cached && cached.rpcUrl && Date.now() - cached.timestamp < CACHE_TTL_MS) {
|
|
17908
|
+
console.log("[getRpcUrl] Using cached URL");
|
|
17878
17909
|
return cached.rpcUrl;
|
|
17879
17910
|
}
|
|
17911
|
+
console.log("[getRpcUrl] Fetching from backend API...");
|
|
17880
17912
|
const response = await client.get(`/networks/${chainId}?includeRpcUrl=true`);
|
|
17913
|
+
console.log("[getRpcUrl] Backend response received");
|
|
17881
17914
|
if (!response.rpcUrl) {
|
|
17882
17915
|
throw new Error(
|
|
17883
17916
|
`RPC URL not available for chainId ${chainId}. Please provide it in config.rpcOverrides[${chainId}]`
|
|
@@ -17888,6 +17921,7 @@ function createGetRpcUrl(deps) {
|
|
|
17888
17921
|
name: response.name,
|
|
17889
17922
|
timestamp: Date.now()
|
|
17890
17923
|
});
|
|
17924
|
+
console.log("[getRpcUrl] RPC URL fetched and cached");
|
|
17891
17925
|
return response.rpcUrl;
|
|
17892
17926
|
};
|
|
17893
17927
|
}
|
|
@@ -18210,31 +18244,39 @@ async function pollTransactionStatus(txId, client, maxAttempts = 60, intervalMs
|
|
|
18210
18244
|
|
|
18211
18245
|
// src/wallet/sender.ts
|
|
18212
18246
|
async function sendCalls(args) {
|
|
18247
|
+
console.log("[sendCalls] Starting sendCalls...");
|
|
18213
18248
|
const { chainId, from: from14, calls, opts, deps } = args;
|
|
18214
18249
|
if (chainId === 0) {
|
|
18215
18250
|
throw new Error("chainId cannot be 0");
|
|
18216
18251
|
}
|
|
18252
|
+
console.log("[sendCalls] Normalizing calls...");
|
|
18217
18253
|
const normalizedFrom = from14;
|
|
18218
18254
|
const normalizedCalls = normalizeCalls(calls);
|
|
18219
18255
|
validateCalls2(normalizedCalls);
|
|
18256
|
+
console.log("[sendCalls] Calls normalized");
|
|
18220
18257
|
let currentUser = deps.user;
|
|
18221
18258
|
if (deps.user?.keyStorageType === "passkey" && !deps.provider) {
|
|
18259
|
+
console.log("[sendCalls] Refreshing user data (provider not available)...");
|
|
18222
18260
|
try {
|
|
18223
|
-
const
|
|
18224
|
-
|
|
18225
|
-
|
|
18226
|
-
|
|
18227
|
-
if (refreshResponse.user) {
|
|
18228
|
-
currentUser = refreshResponse.user;
|
|
18261
|
+
const refreshedUser = await deps.client.refreshSession();
|
|
18262
|
+
if (refreshedUser) {
|
|
18263
|
+
currentUser = refreshedUser;
|
|
18264
|
+
console.log("[sendCalls] User data refreshed successfully");
|
|
18229
18265
|
}
|
|
18230
18266
|
} catch (error) {
|
|
18231
|
-
console.
|
|
18232
|
-
|
|
18233
|
-
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.`
|
|
18234
18270
|
);
|
|
18235
18271
|
}
|
|
18272
|
+
} else {
|
|
18273
|
+
console.log("[sendCalls] Skipping user refresh:", {
|
|
18274
|
+
hasProvider: !!deps.provider,
|
|
18275
|
+
keyStorageType: deps.user?.keyStorageType
|
|
18276
|
+
});
|
|
18236
18277
|
}
|
|
18237
18278
|
if (opts.preflight !== false) {
|
|
18279
|
+
console.log("[sendCalls] Running preflight estimate...");
|
|
18238
18280
|
const tolerateFundingErrors = (opts.mode ?? "sponsored") !== "self";
|
|
18239
18281
|
await preflightEstimate(
|
|
18240
18282
|
deps.publicClient,
|
|
@@ -18242,7 +18284,11 @@ async function sendCalls(args) {
|
|
|
18242
18284
|
normalizedCalls,
|
|
18243
18285
|
{ tolerateFundingErrors }
|
|
18244
18286
|
);
|
|
18287
|
+
console.log("[sendCalls] Preflight estimate done");
|
|
18288
|
+
} else {
|
|
18289
|
+
console.log("[sendCalls] Preflight skipped");
|
|
18245
18290
|
}
|
|
18291
|
+
console.log("[sendCalls] Building temp auth for first precheck...");
|
|
18246
18292
|
const tempAuthForPrecheck = buildTempAuth({
|
|
18247
18293
|
chainId,
|
|
18248
18294
|
from: normalizedFrom,
|
|
@@ -18252,11 +18298,14 @@ async function sendCalls(args) {
|
|
|
18252
18298
|
});
|
|
18253
18299
|
let precheckQuote;
|
|
18254
18300
|
try {
|
|
18301
|
+
console.log("[sendCalls] Running first precheck...");
|
|
18255
18302
|
precheckQuote = await deps.precheck({
|
|
18256
18303
|
auth: tempAuthForPrecheck,
|
|
18257
18304
|
calls: normalizedCalls
|
|
18258
18305
|
});
|
|
18306
|
+
console.log("[sendCalls] First precheck done, policyId:", precheckQuote.policyId);
|
|
18259
18307
|
} catch (err) {
|
|
18308
|
+
console.error("[sendCalls] First precheck failed:", err);
|
|
18260
18309
|
throw err instanceof Error ? err : new Error(String(err));
|
|
18261
18310
|
}
|
|
18262
18311
|
const quotePolicyId = precheckQuote.policyId;
|
|
@@ -18265,6 +18314,7 @@ async function sendCalls(args) {
|
|
|
18265
18314
|
}
|
|
18266
18315
|
const projectPolicyId = quotePolicyId;
|
|
18267
18316
|
validatePolicyId2(projectPolicyId);
|
|
18317
|
+
console.log("[sendCalls] Building temp auth for second precheck...");
|
|
18268
18318
|
const tempAuth = buildTempAuth({
|
|
18269
18319
|
chainId,
|
|
18270
18320
|
from: normalizedFrom,
|
|
@@ -18274,15 +18324,19 @@ async function sendCalls(args) {
|
|
|
18274
18324
|
});
|
|
18275
18325
|
let quote;
|
|
18276
18326
|
try {
|
|
18327
|
+
console.log("[sendCalls] Running second precheck...");
|
|
18277
18328
|
quote = await deps.precheck({ auth: tempAuth, calls: normalizedCalls });
|
|
18329
|
+
console.log("[sendCalls] Second precheck done");
|
|
18278
18330
|
} catch (err) {
|
|
18279
|
-
console.warn("[
|
|
18331
|
+
console.warn("[sendCalls] Second precheck failed:", err);
|
|
18280
18332
|
}
|
|
18333
|
+
console.log("[sendCalls] Finalizing auth with nonce...");
|
|
18281
18334
|
const auth = finalizeAuthWithNonce(tempAuth, quote);
|
|
18282
18335
|
const idempotencyKey = opts.idempotencyKey ?? defaultIdempotencyKey();
|
|
18283
18336
|
let signer;
|
|
18284
18337
|
let activeProvider = null;
|
|
18285
18338
|
try {
|
|
18339
|
+
console.log("[sendCalls] Resolving signer...");
|
|
18286
18340
|
const resolved = await resolveSigner({
|
|
18287
18341
|
explicitSigner: void 0,
|
|
18288
18342
|
// Always resolve internally
|
|
@@ -18294,13 +18348,16 @@ async function sendCalls(args) {
|
|
|
18294
18348
|
});
|
|
18295
18349
|
signer = resolved.signer;
|
|
18296
18350
|
activeProvider = resolved.activeProvider;
|
|
18351
|
+
console.log("[sendCalls] Signer resolved");
|
|
18352
|
+
console.log("[sendCalls] Calling relay...");
|
|
18297
18353
|
const result = await deps.relay(
|
|
18298
18354
|
{ chainId, from: normalizedFrom, auth, calls: normalizedCalls },
|
|
18299
18355
|
{ signer, rpcClient: deps.rpcClient, idempotencyKey }
|
|
18300
18356
|
);
|
|
18357
|
+
console.log("[sendCalls] Relay result:", result.status, result.txId);
|
|
18301
18358
|
if (result.status === "QUEUED" || result.status === "PENDING") {
|
|
18302
18359
|
console.log(
|
|
18303
|
-
`[
|
|
18360
|
+
`[sendCalls] Transaction ${result.txId} is ${result.status}, starting polling...`
|
|
18304
18361
|
);
|
|
18305
18362
|
return pollTransactionStatus(result.txId, deps.client);
|
|
18306
18363
|
}
|
|
@@ -18334,11 +18391,14 @@ function useVolrWallet() {
|
|
|
18334
18391
|
let extendedRpcClient = null;
|
|
18335
18392
|
const ensureRpcClient = async () => {
|
|
18336
18393
|
if (!publicClient) {
|
|
18394
|
+
console.log("[ensureRpcClient] Getting RPC URL for chainId:", chainId);
|
|
18337
18395
|
const rpcUrl = await getRpcUrl(chainId);
|
|
18396
|
+
console.log("[ensureRpcClient] Got RPC URL:", rpcUrl);
|
|
18338
18397
|
publicClient = createPublicClient({
|
|
18339
18398
|
transport: http(rpcUrl)
|
|
18340
18399
|
});
|
|
18341
18400
|
extendedRpcClient = createExtendedRPCClient(publicClient);
|
|
18401
|
+
console.log("[ensureRpcClient] Public client created");
|
|
18342
18402
|
}
|
|
18343
18403
|
return { publicClient, extendedRpcClient };
|
|
18344
18404
|
};
|
|
@@ -18379,8 +18439,12 @@ function useVolrWallet() {
|
|
|
18379
18439
|
});
|
|
18380
18440
|
},
|
|
18381
18441
|
sendBatch: (async (calls, opts) => {
|
|
18442
|
+
console.log("[sendBatch] Starting sendBatch...", { chainId, callsCount: calls.length });
|
|
18443
|
+
console.log("[sendBatch] Ensuring RPC client...");
|
|
18382
18444
|
const { publicClient: publicClient2, extendedRpcClient: rpcClient } = await ensureRpcClient();
|
|
18445
|
+
console.log("[sendBatch] RPC client ready");
|
|
18383
18446
|
const from14 = opts.from ?? user?.evmAddress;
|
|
18447
|
+
console.log("[sendBatch] From address:", from14);
|
|
18384
18448
|
if (!from14) {
|
|
18385
18449
|
throw new Error(
|
|
18386
18450
|
"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."
|
|
@@ -18389,7 +18453,10 @@ function useVolrWallet() {
|
|
|
18389
18453
|
const isCallArray = (calls2) => {
|
|
18390
18454
|
return Array.isArray(calls2) && calls2.length > 0 && "data" in calls2[0] && !("abi" in calls2[0]);
|
|
18391
18455
|
};
|
|
18456
|
+
console.log("[sendBatch] Building calls...");
|
|
18392
18457
|
const builtCalls = isCallArray(calls) ? calls : buildCalls(calls);
|
|
18458
|
+
console.log("[sendBatch] Calls built:", builtCalls.length);
|
|
18459
|
+
console.log("[sendBatch] Calling sendCalls...");
|
|
18393
18460
|
return sendCalls({
|
|
18394
18461
|
chainId,
|
|
18395
18462
|
from: getAddress(from14),
|
|
@@ -18452,7 +18519,7 @@ function createAxiosInstance(baseUrl, apiKey) {
|
|
|
18452
18519
|
// src/hooks/useVolrLogin.ts
|
|
18453
18520
|
function useVolrLogin() {
|
|
18454
18521
|
const { config, setUser } = useVolr();
|
|
18455
|
-
const { setAccessToken } = useInternalAuth();
|
|
18522
|
+
const { setAccessToken, setRefreshToken } = useInternalAuth();
|
|
18456
18523
|
const toVolrUser = useCallback((u) => {
|
|
18457
18524
|
return {
|
|
18458
18525
|
id: u.id,
|
|
@@ -18514,12 +18581,16 @@ function useVolrLogin() {
|
|
|
18514
18581
|
const userFromServer = verifyData?.data?.user;
|
|
18515
18582
|
const isNewUser = !!verifyData?.data?.isNewUser;
|
|
18516
18583
|
const accessToken = verifyData?.data?.accessToken || "";
|
|
18584
|
+
const refreshToken = verifyData?.data?.refreshToken || "";
|
|
18517
18585
|
if (!accessToken) {
|
|
18518
18586
|
throw new Error(
|
|
18519
18587
|
"Access token is required but was not provided by the server"
|
|
18520
18588
|
);
|
|
18521
18589
|
}
|
|
18522
18590
|
setAccessToken(accessToken);
|
|
18591
|
+
if (refreshToken) {
|
|
18592
|
+
setRefreshToken(refreshToken);
|
|
18593
|
+
}
|
|
18523
18594
|
if (userFromServer) {
|
|
18524
18595
|
setUser(toVolrUser(userFromServer));
|
|
18525
18596
|
} else {
|
|
@@ -18533,7 +18604,7 @@ function useVolrLogin() {
|
|
|
18533
18604
|
accessToken
|
|
18534
18605
|
};
|
|
18535
18606
|
},
|
|
18536
|
-
[api, setAccessToken, setUser, toVolrUser]
|
|
18607
|
+
[api, setAccessToken, setRefreshToken, setUser, toVolrUser]
|
|
18537
18608
|
);
|
|
18538
18609
|
const handleSocialLogin = useCallback(
|
|
18539
18610
|
async (provider) => {
|
|
@@ -18575,12 +18646,16 @@ function useVolrLogin() {
|
|
|
18575
18646
|
const userFromServer = verifyData?.data?.user;
|
|
18576
18647
|
const isNewUser = !!verifyData?.data?.isNewUser;
|
|
18577
18648
|
const accessToken = verifyData?.data?.accessToken || "";
|
|
18649
|
+
const refreshToken = verifyData?.data?.refreshToken || "";
|
|
18578
18650
|
if (!accessToken) {
|
|
18579
18651
|
throw new Error(
|
|
18580
18652
|
"Access token is required but was not provided by the server"
|
|
18581
18653
|
);
|
|
18582
18654
|
}
|
|
18583
18655
|
setAccessToken(accessToken);
|
|
18656
|
+
if (refreshToken) {
|
|
18657
|
+
setRefreshToken(refreshToken);
|
|
18658
|
+
}
|
|
18584
18659
|
if (userFromServer) {
|
|
18585
18660
|
setUser(toVolrUser(userFromServer));
|
|
18586
18661
|
}
|
|
@@ -18600,7 +18675,7 @@ function useVolrLogin() {
|
|
|
18600
18675
|
throw error;
|
|
18601
18676
|
}
|
|
18602
18677
|
},
|
|
18603
|
-
[api, setAccessToken, setUser, toVolrUser]
|
|
18678
|
+
[api, setAccessToken, setRefreshToken, setUser, toVolrUser]
|
|
18604
18679
|
);
|
|
18605
18680
|
const handlePasskeyComplete = useCallback(async () => {
|
|
18606
18681
|
}, []);
|
|
@@ -18615,7 +18690,7 @@ function useVolrLogin() {
|
|
|
18615
18690
|
}
|
|
18616
18691
|
function useVolrAuthCallback(options = {}) {
|
|
18617
18692
|
const { config, setUser } = useVolr();
|
|
18618
|
-
const { refreshAccessToken, setAccessToken } = useInternalAuth();
|
|
18693
|
+
const { refreshAccessToken, setAccessToken, setRefreshToken, client } = useInternalAuth();
|
|
18619
18694
|
const [isLoading, setIsLoading] = useState(true);
|
|
18620
18695
|
const [error, setError] = useState(null);
|
|
18621
18696
|
const [isNewUser, setIsNewUser] = useState(false);
|
|
@@ -18669,13 +18744,21 @@ function useVolrAuthCallback(options = {}) {
|
|
|
18669
18744
|
if (!userRes.data?.ok) {
|
|
18670
18745
|
throw new Error("Failed to fetch user details");
|
|
18671
18746
|
}
|
|
18672
|
-
const
|
|
18747
|
+
const currentRefreshToken = client.getRefreshToken();
|
|
18748
|
+
if (!currentRefreshToken) {
|
|
18749
|
+
throw new Error("No refresh token available. Please log in again.");
|
|
18750
|
+
}
|
|
18751
|
+
const refreshRes = await api.post("/auth/refresh", { refreshToken: currentRefreshToken });
|
|
18673
18752
|
if (!refreshRes.data?.ok) {
|
|
18674
18753
|
throw new Error("Failed to refresh session");
|
|
18675
18754
|
}
|
|
18676
18755
|
const userData = refreshRes.data.data.user;
|
|
18677
18756
|
const accessToken = refreshRes.data.data.accessToken;
|
|
18757
|
+
const newRefreshToken = refreshRes.data.data.refreshToken;
|
|
18678
18758
|
setAccessToken(accessToken);
|
|
18759
|
+
if (newRefreshToken) {
|
|
18760
|
+
setRefreshToken(newRefreshToken);
|
|
18761
|
+
}
|
|
18679
18762
|
const volrUser = toVolrUser(userData);
|
|
18680
18763
|
setUser(volrUser);
|
|
18681
18764
|
setLocalUser(volrUser);
|
|
@@ -18690,7 +18773,7 @@ function useVolrAuthCallback(options = {}) {
|
|
|
18690
18773
|
}
|
|
18691
18774
|
};
|
|
18692
18775
|
handleCallback();
|
|
18693
|
-
}, [apiBaseUrl, config.projectApiKey, refreshAccessToken, setAccessToken, setUser, toVolrUser]);
|
|
18776
|
+
}, [apiBaseUrl, config.projectApiKey, refreshAccessToken, setAccessToken, setRefreshToken, setUser, toVolrUser, client]);
|
|
18694
18777
|
return {
|
|
18695
18778
|
isLoading,
|
|
18696
18779
|
error,
|