@volr/react 0.1.129 → 0.1.131
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 +279 -100
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -2
- package/dist/index.d.ts +63 -2
- package/dist/index.js +277 -102
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -9293,12 +9293,13 @@ var APIClient = class {
|
|
|
9293
9293
|
headers: {
|
|
9294
9294
|
"Content-Type": "application/json"
|
|
9295
9295
|
},
|
|
9296
|
+
// Transform BigInt to string before JSON serialization
|
|
9296
9297
|
transformRequest: [
|
|
9297
9298
|
(data) => {
|
|
9298
9299
|
if (data && typeof data === "object") {
|
|
9299
9300
|
return JSON.stringify(
|
|
9300
9301
|
data,
|
|
9301
|
-
(
|
|
9302
|
+
(_key, value) => typeof value === "bigint" ? value.toString() : value
|
|
9302
9303
|
);
|
|
9303
9304
|
}
|
|
9304
9305
|
return data;
|
|
@@ -9322,6 +9323,9 @@ var APIClient = class {
|
|
|
9322
9323
|
this.api.interceptors.response.use(
|
|
9323
9324
|
(response) => response,
|
|
9324
9325
|
async (error) => {
|
|
9326
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV === "test") {
|
|
9327
|
+
sanitizeAxiosErrorForTest(error);
|
|
9328
|
+
}
|
|
9325
9329
|
const originalRequest = error.config;
|
|
9326
9330
|
const requestUrl = originalRequest?.url || "";
|
|
9327
9331
|
const responseData = error.response?.data;
|
|
@@ -9358,7 +9362,14 @@ var APIClient = class {
|
|
|
9358
9362
|
}
|
|
9359
9363
|
return this.api(originalRequest);
|
|
9360
9364
|
} catch (refreshError) {
|
|
9361
|
-
|
|
9365
|
+
const anyErr = refreshError;
|
|
9366
|
+
const status = anyErr?.response?.status;
|
|
9367
|
+
const backendCode = anyErr?.response?.data?.error?.code;
|
|
9368
|
+
const backendMessage = anyErr?.response?.data?.error?.message;
|
|
9369
|
+
const message = backendMessage || anyErr?.message || "Unknown error";
|
|
9370
|
+
console.error(
|
|
9371
|
+
`[APIClient] Token refresh failed${typeof status === "number" ? ` (${status})` : ""}: ${backendCode ? `${backendCode}: ` : ""}${message}`
|
|
9372
|
+
);
|
|
9362
9373
|
return Promise.reject(refreshError);
|
|
9363
9374
|
}
|
|
9364
9375
|
}
|
|
@@ -9439,17 +9450,11 @@ var APIClient = class {
|
|
|
9439
9450
|
if (!this.refreshToken) {
|
|
9440
9451
|
throw new Error("No refresh token available. Please log in again.");
|
|
9441
9452
|
}
|
|
9442
|
-
const
|
|
9443
|
-
(_, reject) => setTimeout(
|
|
9444
|
-
() => reject(new Error("Session refresh timeout. Please check your network connection.")),
|
|
9445
|
-
timeoutMs
|
|
9446
|
-
)
|
|
9447
|
-
);
|
|
9448
|
-
const refreshPromise = this.api.post(
|
|
9453
|
+
const response = await this.api.post(
|
|
9449
9454
|
"/auth/refresh",
|
|
9450
|
-
{ refreshToken: this.refreshToken }
|
|
9455
|
+
{ refreshToken: this.refreshToken },
|
|
9456
|
+
{ timeout: timeoutMs }
|
|
9451
9457
|
);
|
|
9452
|
-
const response = await Promise.race([refreshPromise, timeoutPromise]);
|
|
9453
9458
|
const data = response.data;
|
|
9454
9459
|
if (isErrorResponse(data)) {
|
|
9455
9460
|
this.setAccessToken(null);
|
|
@@ -9477,23 +9482,27 @@ var APIClient = class {
|
|
|
9477
9482
|
}
|
|
9478
9483
|
this.refreshPromise = (async () => {
|
|
9479
9484
|
try {
|
|
9480
|
-
|
|
9481
|
-
"/auth/refresh",
|
|
9482
|
-
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
|
|
9485
|
+
try {
|
|
9486
|
+
const response = await this.api.post("/auth/refresh", { refreshToken: this.refreshToken });
|
|
9487
|
+
const data = response.data;
|
|
9488
|
+
if (isErrorResponse(data)) {
|
|
9489
|
+
this.setAccessToken(null);
|
|
9490
|
+
this.setRefreshToken(null);
|
|
9491
|
+
safeStorage.removeItem(STORAGE_KEYS.user);
|
|
9492
|
+
throw new Error(data.error.message);
|
|
9493
|
+
}
|
|
9494
|
+
this.setAccessToken(data.data.accessToken);
|
|
9495
|
+
if (data.data.refreshToken) {
|
|
9496
|
+
this.setRefreshToken(data.data.refreshToken);
|
|
9497
|
+
}
|
|
9498
|
+
if (data.data.user) {
|
|
9499
|
+
safeStorage.setItem(STORAGE_KEYS.user, JSON.stringify(data.data.user));
|
|
9500
|
+
}
|
|
9501
|
+
} catch (err) {
|
|
9486
9502
|
this.setAccessToken(null);
|
|
9487
9503
|
this.setRefreshToken(null);
|
|
9488
9504
|
safeStorage.removeItem(STORAGE_KEYS.user);
|
|
9489
|
-
throw
|
|
9490
|
-
}
|
|
9491
|
-
this.setAccessToken(data.data.accessToken);
|
|
9492
|
-
if (data.data.refreshToken) {
|
|
9493
|
-
this.setRefreshToken(data.data.refreshToken);
|
|
9494
|
-
}
|
|
9495
|
-
if (data.data.user) {
|
|
9496
|
-
safeStorage.setItem(STORAGE_KEYS.user, JSON.stringify(data.data.user));
|
|
9505
|
+
throw err;
|
|
9497
9506
|
}
|
|
9498
9507
|
} finally {
|
|
9499
9508
|
this.refreshPromise = null;
|
|
@@ -9541,7 +9550,14 @@ var APIClient = class {
|
|
|
9541
9550
|
const response = await this.api.request(config);
|
|
9542
9551
|
return unwrapResponse(response.data);
|
|
9543
9552
|
} catch (error) {
|
|
9544
|
-
|
|
9553
|
+
const anyErr = error;
|
|
9554
|
+
const status = anyErr?.response?.status;
|
|
9555
|
+
const backendCode = anyErr?.response?.data?.error?.code;
|
|
9556
|
+
const backendMessage = anyErr?.response?.data?.error?.message;
|
|
9557
|
+
const message = backendMessage || anyErr?.message || "Unknown error";
|
|
9558
|
+
console.error(
|
|
9559
|
+
`[APIClient] POST ${normalizedEndpoint} error${typeof status === "number" ? ` (${status})` : ""}: ${backendCode ? `${backendCode}: ` : ""}${message}`
|
|
9560
|
+
);
|
|
9545
9561
|
throw error;
|
|
9546
9562
|
}
|
|
9547
9563
|
}
|
|
@@ -9578,7 +9594,36 @@ var APIClient = class {
|
|
|
9578
9594
|
const response = await this.api.get(normalizedEndpoint);
|
|
9579
9595
|
return unwrapResponse(response.data);
|
|
9580
9596
|
}
|
|
9597
|
+
/**
|
|
9598
|
+
* Internal helper to sanitize Axios errors in test environment so that Vitest
|
|
9599
|
+
* can safely structured-clone them between workers.
|
|
9600
|
+
*
|
|
9601
|
+
* NOTE: This function is exported only for tests. It is a no-op in production
|
|
9602
|
+
* builds where NODE_ENV !== 'test'.
|
|
9603
|
+
*/
|
|
9604
|
+
static sanitizeAxiosErrorForTest(error) {
|
|
9605
|
+
sanitizeAxiosErrorForTest(error);
|
|
9606
|
+
}
|
|
9581
9607
|
};
|
|
9608
|
+
function sanitizeAxiosErrorForTest(error) {
|
|
9609
|
+
if (!error || typeof error !== "object") return;
|
|
9610
|
+
try {
|
|
9611
|
+
const anyErr = error;
|
|
9612
|
+
const cfg = anyErr.config;
|
|
9613
|
+
if (cfg && typeof cfg === "object") {
|
|
9614
|
+
if ("transformRequest" in cfg) cfg.transformRequest = void 0;
|
|
9615
|
+
if ("transformResponse" in cfg) cfg.transformResponse = void 0;
|
|
9616
|
+
if ("adapter" in cfg) cfg.adapter = void 0;
|
|
9617
|
+
}
|
|
9618
|
+
if (anyErr.request) {
|
|
9619
|
+
anyErr.request = void 0;
|
|
9620
|
+
}
|
|
9621
|
+
if (anyErr.response && anyErr.response.request) {
|
|
9622
|
+
anyErr.response.request = void 0;
|
|
9623
|
+
}
|
|
9624
|
+
} catch {
|
|
9625
|
+
}
|
|
9626
|
+
}
|
|
9582
9627
|
|
|
9583
9628
|
// src/config/backend.ts
|
|
9584
9629
|
var DEFAULT_API_BASE_URL = "https://api.volr.io";
|
|
@@ -9651,7 +9696,9 @@ var SessionSync = class {
|
|
|
9651
9696
|
try {
|
|
9652
9697
|
listener(event);
|
|
9653
9698
|
} catch (error) {
|
|
9654
|
-
console.error(
|
|
9699
|
+
console.error(
|
|
9700
|
+
`SessionSync listener error: ${error instanceof Error ? error.message : String(error)}`
|
|
9701
|
+
);
|
|
9655
9702
|
}
|
|
9656
9703
|
}
|
|
9657
9704
|
}
|
|
@@ -9727,10 +9774,41 @@ function useSessionSync({
|
|
|
9727
9774
|
}
|
|
9728
9775
|
|
|
9729
9776
|
// src/config/webauthn.ts
|
|
9777
|
+
function isWindows() {
|
|
9778
|
+
if (typeof navigator === "undefined") return false;
|
|
9779
|
+
const platform = navigator.platform || "";
|
|
9780
|
+
return /Win/.test(platform);
|
|
9781
|
+
}
|
|
9782
|
+
function isLinux() {
|
|
9783
|
+
if (typeof navigator === "undefined") return false;
|
|
9784
|
+
const platform = navigator.platform || "";
|
|
9785
|
+
const ua = navigator.userAgent;
|
|
9786
|
+
return /Linux/.test(platform) && !/CrOS/.test(ua) && !/Android/.test(ua);
|
|
9787
|
+
}
|
|
9788
|
+
function shouldForceCrossDevice() {
|
|
9789
|
+
return isWindows() || isLinux();
|
|
9790
|
+
}
|
|
9730
9791
|
var AUTHENTICATOR_SELECTION = {
|
|
9731
9792
|
userVerification: "required",
|
|
9732
9793
|
residentKey: "required"
|
|
9733
9794
|
};
|
|
9795
|
+
var AUTHENTICATOR_SELECTION_CROSS_DEVICE = {
|
|
9796
|
+
userVerification: "required",
|
|
9797
|
+
residentKey: "required",
|
|
9798
|
+
authenticatorAttachment: "cross-platform"
|
|
9799
|
+
};
|
|
9800
|
+
function getAuthenticatorSelection() {
|
|
9801
|
+
if (shouldForceCrossDevice()) {
|
|
9802
|
+
return AUTHENTICATOR_SELECTION_CROSS_DEVICE;
|
|
9803
|
+
}
|
|
9804
|
+
return AUTHENTICATOR_SELECTION;
|
|
9805
|
+
}
|
|
9806
|
+
function getWebAuthnHints() {
|
|
9807
|
+
if (shouldForceCrossDevice()) {
|
|
9808
|
+
return ["hybrid"];
|
|
9809
|
+
}
|
|
9810
|
+
return void 0;
|
|
9811
|
+
}
|
|
9734
9812
|
var CREDENTIAL_MEDIATION = "required";
|
|
9735
9813
|
var USER_VERIFICATION = "required";
|
|
9736
9814
|
var WEBAUTHN_TIMEOUT = 6e4;
|
|
@@ -9771,6 +9849,17 @@ var PrfNotSupportedError = class _PrfNotSupportedError extends Error {
|
|
|
9771
9849
|
Object.setPrototypeOf(this, _PrfNotSupportedError.prototype);
|
|
9772
9850
|
}
|
|
9773
9851
|
};
|
|
9852
|
+
var WebAuthnBusyError = class _WebAuthnBusyError extends Error {
|
|
9853
|
+
constructor(message) {
|
|
9854
|
+
super(
|
|
9855
|
+
message || "Another passkey authentication is in progress. Please wait a moment and try again."
|
|
9856
|
+
);
|
|
9857
|
+
this.code = "WEBAUTHN_BUSY";
|
|
9858
|
+
this.isRetryable = true;
|
|
9859
|
+
this.name = "WebAuthnBusyError";
|
|
9860
|
+
Object.setPrototypeOf(this, _WebAuthnBusyError.prototype);
|
|
9861
|
+
}
|
|
9862
|
+
};
|
|
9774
9863
|
function isUserCancelledError(error) {
|
|
9775
9864
|
if (error instanceof UserCancelledError) {
|
|
9776
9865
|
return true;
|
|
@@ -9788,8 +9877,40 @@ function isUserCancelledError(error) {
|
|
|
9788
9877
|
}
|
|
9789
9878
|
return false;
|
|
9790
9879
|
}
|
|
9880
|
+
function isWebAuthnBusyError(error) {
|
|
9881
|
+
if (error instanceof WebAuthnBusyError) {
|
|
9882
|
+
return true;
|
|
9883
|
+
}
|
|
9884
|
+
if (error instanceof Error) {
|
|
9885
|
+
const msg = error.message.toLowerCase();
|
|
9886
|
+
if (msg.includes("already in progress") || msg.includes("already pending") || msg.includes("\uC774\uBBF8 \uC694\uCCAD\uC774 \uB300\uAE30 \uC911") || // Korean locale
|
|
9887
|
+
msg.includes("authentication is already in progress") || msg.includes("operation already in progress") || msg.includes("request is already in progress")) {
|
|
9888
|
+
return true;
|
|
9889
|
+
}
|
|
9890
|
+
}
|
|
9891
|
+
return false;
|
|
9892
|
+
}
|
|
9791
9893
|
|
|
9792
9894
|
// src/adapters/passkey.ts
|
|
9895
|
+
var pendingWebAuthnPromise = null;
|
|
9896
|
+
async function withWebAuthnLock(fn) {
|
|
9897
|
+
if (pendingWebAuthnPromise) {
|
|
9898
|
+
try {
|
|
9899
|
+
await pendingWebAuthnPromise;
|
|
9900
|
+
} catch {
|
|
9901
|
+
}
|
|
9902
|
+
}
|
|
9903
|
+
const promise = fn();
|
|
9904
|
+
pendingWebAuthnPromise = promise;
|
|
9905
|
+
try {
|
|
9906
|
+
const result = await promise;
|
|
9907
|
+
return result;
|
|
9908
|
+
} finally {
|
|
9909
|
+
if (pendingWebAuthnPromise === promise) {
|
|
9910
|
+
pendingWebAuthnPromise = null;
|
|
9911
|
+
}
|
|
9912
|
+
}
|
|
9913
|
+
}
|
|
9793
9914
|
function createPasskeyAdapter(options = {}) {
|
|
9794
9915
|
const rpId = options.rpId || (typeof window !== "undefined" ? window.location.hostname : "localhost");
|
|
9795
9916
|
return {
|
|
@@ -9892,72 +10013,88 @@ function createPasskeyAdapter(options = {}) {
|
|
|
9892
10013
|
type: "public-key"
|
|
9893
10014
|
}
|
|
9894
10015
|
];
|
|
9895
|
-
|
|
9896
|
-
|
|
9897
|
-
credential =
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
|
|
9902
|
-
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
10016
|
+
const hints = getWebAuthnHints();
|
|
10017
|
+
return withWebAuthnLock(async () => {
|
|
10018
|
+
let credential = null;
|
|
10019
|
+
try {
|
|
10020
|
+
const requestOptions = {
|
|
10021
|
+
publicKey: {
|
|
10022
|
+
challenge: crypto.getRandomValues(new Uint8Array(32)),
|
|
10023
|
+
rpId,
|
|
10024
|
+
allowCredentials,
|
|
10025
|
+
userVerification: USER_VERIFICATION,
|
|
10026
|
+
// Shared constant
|
|
10027
|
+
extensions: {
|
|
10028
|
+
prf: {
|
|
10029
|
+
eval: {
|
|
10030
|
+
first: prfInput.salt.buffer
|
|
10031
|
+
}
|
|
9908
10032
|
}
|
|
9909
|
-
}
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
10033
|
+
},
|
|
10034
|
+
// Chrome 128+ supports hints to prioritize certain authenticator types
|
|
10035
|
+
// On Windows/Linux, this prioritizes QR code over USB security key prompt
|
|
10036
|
+
...hints && { hints }
|
|
10037
|
+
},
|
|
10038
|
+
mediation: CREDENTIAL_MEDIATION
|
|
10039
|
+
// Use shared constant
|
|
10040
|
+
};
|
|
10041
|
+
credential = await navigator.credentials.get(requestOptions);
|
|
10042
|
+
} catch (error) {
|
|
10043
|
+
console.error("[PasskeyAdapter] WebAuthn get() failed:", error);
|
|
10044
|
+
console.error("[PasskeyAdapter] Error name:", error?.name);
|
|
10045
|
+
console.error("[PasskeyAdapter] Error message:", error?.message);
|
|
10046
|
+
const msg = (error?.message || "").toLowerCase();
|
|
10047
|
+
if (msg.includes("already in progress") || msg.includes("already pending") || msg.includes("\uC774\uBBF8 \uC694\uCCAD\uC774 \uB300\uAE30 \uC911") || // Korean
|
|
10048
|
+
msg.includes("operation already in progress") || msg.includes("request is already in progress")) {
|
|
10049
|
+
throw new WebAuthnBusyError(
|
|
10050
|
+
"Another passkey authentication is in progress. Please wait a moment and try again."
|
|
10051
|
+
);
|
|
10052
|
+
}
|
|
10053
|
+
if (error?.name === "NotAllowedError") {
|
|
10054
|
+
throw new UserCancelledError(
|
|
10055
|
+
"User cancelled the passkey prompt or authentication was denied."
|
|
10056
|
+
);
|
|
10057
|
+
}
|
|
10058
|
+
if (error?.name === "NotFoundError" || error?.name === "InvalidStateError") {
|
|
10059
|
+
throw new PasskeyNotFoundError(
|
|
10060
|
+
"No passkey found matching the provided credentialId. This may happen if the passkey was deleted or the credentialId is incorrect."
|
|
10061
|
+
);
|
|
10062
|
+
}
|
|
10063
|
+
if (error?.name === "NotSupportedError") {
|
|
10064
|
+
throw new PrfNotSupportedError(
|
|
10065
|
+
"WebAuthn PRF extension is not supported by this browser or device. Please use a browser that supports WebAuthn PRF extension (Chrome 108+, Edge 108+, Safari 16.4+)."
|
|
10066
|
+
);
|
|
10067
|
+
}
|
|
10068
|
+
throw new Error(
|
|
10069
|
+
`[PasskeyAdapter] WebAuthn authentication failed: ${error?.message || "Unknown error"}`
|
|
9922
10070
|
);
|
|
9923
10071
|
}
|
|
9924
|
-
if (
|
|
9925
|
-
|
|
9926
|
-
"
|
|
10072
|
+
if (!credential || !credential.response) {
|
|
10073
|
+
console.error(
|
|
10074
|
+
"[PasskeyAdapter] credential is null or missing response"
|
|
10075
|
+
);
|
|
10076
|
+
throw new Error(
|
|
10077
|
+
"[PasskeyAdapter] Failed to get passkey credential for PRF. The passkey prompt may have been cancelled or no matching credential was found."
|
|
9927
10078
|
);
|
|
9928
10079
|
}
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
10080
|
+
const extensionResults = credential.getClientExtensionResults();
|
|
10081
|
+
if (!extensionResults.prf || !extensionResults.prf.results || !extensionResults.prf.results.first) {
|
|
10082
|
+
throw new Error(
|
|
10083
|
+
"[PasskeyAdapter] PRF extension not supported or PRF output missing"
|
|
9932
10084
|
);
|
|
9933
10085
|
}
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
);
|
|
9937
|
-
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
}
|
|
9946
|
-
const extensionResults = credential.getClientExtensionResults();
|
|
9947
|
-
if (!extensionResults.prf || !extensionResults.prf.results || !extensionResults.prf.results.first) {
|
|
9948
|
-
throw new Error(
|
|
9949
|
-
"[PasskeyAdapter] PRF extension not supported or PRF output missing"
|
|
9950
|
-
);
|
|
9951
|
-
}
|
|
9952
|
-
const prfOutputBuffer = extensionResults.prf.results.first;
|
|
9953
|
-
const prfOutput = new Uint8Array(prfOutputBuffer);
|
|
9954
|
-
const credentialIdBytes = new Uint8Array(credential.rawId);
|
|
9955
|
-
const credentialIdBase64 = btoa(String.fromCharCode(...credentialIdBytes)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
9956
|
-
console.log("[PasskeyAdapter] WebAuthn prompt completed successfully");
|
|
9957
|
-
return {
|
|
9958
|
-
prfOutput,
|
|
9959
|
-
credentialId: credentialIdBase64
|
|
9960
|
-
};
|
|
10086
|
+
const prfOutputBuffer = extensionResults.prf.results.first;
|
|
10087
|
+
const prfOutput = new Uint8Array(prfOutputBuffer);
|
|
10088
|
+
const credentialIdBytes = new Uint8Array(credential.rawId);
|
|
10089
|
+
const credentialIdBase64 = btoa(
|
|
10090
|
+
String.fromCharCode(...credentialIdBytes)
|
|
10091
|
+
).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
10092
|
+
console.log("[PasskeyAdapter] WebAuthn prompt completed successfully");
|
|
10093
|
+
return {
|
|
10094
|
+
prfOutput,
|
|
10095
|
+
credentialId: credentialIdBase64
|
|
10096
|
+
};
|
|
10097
|
+
});
|
|
9961
10098
|
}
|
|
9962
10099
|
};
|
|
9963
10100
|
}
|
|
@@ -10323,7 +10460,9 @@ function VolrProvider({ config, children }) {
|
|
|
10323
10460
|
setUser((prev) => ({ ...prev, keyStorageType }));
|
|
10324
10461
|
}
|
|
10325
10462
|
} catch (error2) {
|
|
10326
|
-
console.warn(
|
|
10463
|
+
console.warn(
|
|
10464
|
+
`[Provider] setProvider: Failed to refresh user data: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
10465
|
+
);
|
|
10327
10466
|
setUser((prev) => ({ ...prev, keyStorageType }));
|
|
10328
10467
|
}
|
|
10329
10468
|
}
|
|
@@ -18674,7 +18813,9 @@ async function pollTransactionStatus(txId, client, maxAttempts = 60) {
|
|
|
18674
18813
|
const intervalMs = getPollingInterval(attempt);
|
|
18675
18814
|
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
18676
18815
|
} catch (error) {
|
|
18677
|
-
console.error(
|
|
18816
|
+
console.error(
|
|
18817
|
+
`[pollTransactionStatus] Error polling transaction ${txId}: ${error instanceof Error ? error.message : String(error)}`
|
|
18818
|
+
);
|
|
18678
18819
|
const intervalMs = getPollingInterval(attempt);
|
|
18679
18820
|
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
18680
18821
|
}
|
|
@@ -18695,6 +18836,11 @@ async function sendCalls(args) {
|
|
|
18695
18836
|
const normalizedFrom = from14;
|
|
18696
18837
|
const normalizedCalls = normalizeCalls(calls);
|
|
18697
18838
|
validateCalls2(normalizedCalls);
|
|
18839
|
+
if (!deps.provider && deps.user?.keyStorageType !== "passkey") {
|
|
18840
|
+
throw new Error(
|
|
18841
|
+
"No wallet provider configured. Please set up a Passkey provider to sign transactions. SIWE is authentication-only."
|
|
18842
|
+
);
|
|
18843
|
+
}
|
|
18698
18844
|
let currentUser = deps.user;
|
|
18699
18845
|
if (deps.user?.keyStorageType === "passkey" && !deps.provider) {
|
|
18700
18846
|
try {
|
|
@@ -18703,7 +18849,9 @@ async function sendCalls(args) {
|
|
|
18703
18849
|
currentUser = refreshedUser;
|
|
18704
18850
|
}
|
|
18705
18851
|
} catch (error) {
|
|
18706
|
-
console.error(
|
|
18852
|
+
console.error(
|
|
18853
|
+
`[sendCalls] Failed to refresh session: ${error instanceof Error ? error.message : String(error)}`
|
|
18854
|
+
);
|
|
18707
18855
|
throw new Error(
|
|
18708
18856
|
`Failed to refresh session before transaction. ${error instanceof Error ? error.message : "Unknown error"}. Please try logging in again.`
|
|
18709
18857
|
);
|
|
@@ -18723,7 +18871,9 @@ async function sendCalls(args) {
|
|
|
18723
18871
|
calls: normalizedCalls
|
|
18724
18872
|
});
|
|
18725
18873
|
} catch (err) {
|
|
18726
|
-
console.error(
|
|
18874
|
+
console.error(
|
|
18875
|
+
`[sendCalls] First precheck failed: ${err instanceof Error ? err.message : String(err)}`
|
|
18876
|
+
);
|
|
18727
18877
|
throw err instanceof Error ? err : new Error(String(err));
|
|
18728
18878
|
}
|
|
18729
18879
|
if (precheckQuote.simulationSuccess === false && precheckQuote.simulationErrors?.length) {
|
|
@@ -19313,7 +19463,9 @@ function useVolrAuthCallback(options = {}) {
|
|
|
19313
19463
|
setIsLoading(false);
|
|
19314
19464
|
options.onSuccess?.(volrUser);
|
|
19315
19465
|
} catch (err) {
|
|
19316
|
-
console.error(
|
|
19466
|
+
console.error(
|
|
19467
|
+
`[useVolrAuthCallback] Token exchange error: ${err instanceof Error ? err.message : String(err)}`
|
|
19468
|
+
);
|
|
19317
19469
|
let errorMsg = "Failed to complete authentication";
|
|
19318
19470
|
if (err instanceof Error) {
|
|
19319
19471
|
if (err.message.includes("AUTH_CODE_EXPIRED")) {
|
|
@@ -19417,7 +19569,9 @@ function useDepositListener(input) {
|
|
|
19417
19569
|
if (cancelled) return;
|
|
19418
19570
|
setStatus({ state: "listening", balance: initial });
|
|
19419
19571
|
} catch (e) {
|
|
19420
|
-
console.error(
|
|
19572
|
+
console.error(
|
|
19573
|
+
`[DepositListener] Error: ${e instanceof Error ? e.message : String(e)}`
|
|
19574
|
+
);
|
|
19421
19575
|
if (cancelled) return;
|
|
19422
19576
|
setStatus({ state: "error", message: e.message || String(e) });
|
|
19423
19577
|
return;
|
|
@@ -19453,7 +19607,9 @@ function useDepositListener(input) {
|
|
|
19453
19607
|
return prev;
|
|
19454
19608
|
});
|
|
19455
19609
|
} catch (err) {
|
|
19456
|
-
console.error(
|
|
19610
|
+
console.error(
|
|
19611
|
+
`[DepositListener] Polling error: ${err instanceof Error ? err.message : String(err)}`
|
|
19612
|
+
);
|
|
19457
19613
|
if (cancelled) return;
|
|
19458
19614
|
setStatus({ state: "error", message: err.message || String(err) });
|
|
19459
19615
|
}
|
|
@@ -19556,6 +19712,8 @@ async function enrollPasskey(params) {
|
|
|
19556
19712
|
};
|
|
19557
19713
|
const prfSalt = sdkCore.deriveWrapKey(tempPrfInput);
|
|
19558
19714
|
const displayName = buildDisplayName(userEmail, userEvmAddress, userId);
|
|
19715
|
+
const authenticatorSelection = getAuthenticatorSelection();
|
|
19716
|
+
const hints = getWebAuthnHints();
|
|
19559
19717
|
const publicKeyCredentialCreationOptions = {
|
|
19560
19718
|
challenge: challenge2,
|
|
19561
19719
|
rp: {
|
|
@@ -19568,7 +19726,7 @@ async function enrollPasskey(params) {
|
|
|
19568
19726
|
displayName
|
|
19569
19727
|
},
|
|
19570
19728
|
pubKeyCredParams: PUBKEY_CRED_PARAMS,
|
|
19571
|
-
authenticatorSelection
|
|
19729
|
+
authenticatorSelection,
|
|
19572
19730
|
timeout: WEBAUTHN_TIMEOUT,
|
|
19573
19731
|
attestation: ATTESTATION,
|
|
19574
19732
|
extensions: {
|
|
@@ -19577,7 +19735,10 @@ async function enrollPasskey(params) {
|
|
|
19577
19735
|
first: prfSalt.buffer
|
|
19578
19736
|
}
|
|
19579
19737
|
}
|
|
19580
|
-
}
|
|
19738
|
+
},
|
|
19739
|
+
// Chrome 128+ supports hints to prioritize certain authenticator types
|
|
19740
|
+
// On Windows/Linux, this prioritizes QR code over USB security key prompt
|
|
19741
|
+
...hints && { hints }
|
|
19581
19742
|
};
|
|
19582
19743
|
const credential = await navigator.credentials.create({
|
|
19583
19744
|
publicKey: publicKeyCredentialCreationOptions
|
|
@@ -20086,7 +20247,9 @@ function useUserBalances() {
|
|
|
20086
20247
|
});
|
|
20087
20248
|
setBalances(initialBalances);
|
|
20088
20249
|
}).catch((err) => {
|
|
20089
|
-
console.error(
|
|
20250
|
+
console.error(
|
|
20251
|
+
`[useUserBalances] Failed to fetch branding: ${err instanceof Error ? err.message : String(err)}`
|
|
20252
|
+
);
|
|
20090
20253
|
setError(err instanceof Error ? err : new Error("Failed to fetch branding"));
|
|
20091
20254
|
}).finally(() => {
|
|
20092
20255
|
setIsLoadingBranding(false);
|
|
@@ -20127,7 +20290,9 @@ function useUserBalances() {
|
|
|
20127
20290
|
error: void 0
|
|
20128
20291
|
};
|
|
20129
20292
|
} catch (err) {
|
|
20130
|
-
console.error(
|
|
20293
|
+
console.error(
|
|
20294
|
+
`[useUserBalances] Failed to fetch balance for ${id}: ${err instanceof Error ? err.message : String(err)}`
|
|
20295
|
+
);
|
|
20131
20296
|
return {
|
|
20132
20297
|
id,
|
|
20133
20298
|
balanceRaw: 0n,
|
|
@@ -20767,7 +20932,12 @@ function getPlatformHint(platform) {
|
|
|
20767
20932
|
case "Windows":
|
|
20768
20933
|
return {
|
|
20769
20934
|
hintKey: "passkey.hint.windows",
|
|
20770
|
-
noteKey: "passkey.hint.
|
|
20935
|
+
noteKey: "passkey.hint.windowsNote"
|
|
20936
|
+
};
|
|
20937
|
+
case "Linux":
|
|
20938
|
+
return {
|
|
20939
|
+
hintKey: "passkey.hint.linux",
|
|
20940
|
+
noteKey: "passkey.hint.windowsNote"
|
|
20771
20941
|
};
|
|
20772
20942
|
default:
|
|
20773
20943
|
return {
|
|
@@ -20961,6 +21131,8 @@ async function completeMigration(params) {
|
|
|
20961
21131
|
credentialId: tempCredentialId
|
|
20962
21132
|
};
|
|
20963
21133
|
const prfSalt = sdkCore.deriveWrapKey(tempPrfInput);
|
|
21134
|
+
const authenticatorSelection = getAuthenticatorSelection();
|
|
21135
|
+
const hints = getWebAuthnHints();
|
|
20964
21136
|
const publicKeyCredentialCreationOptions = {
|
|
20965
21137
|
challenge: challenge2,
|
|
20966
21138
|
rp: {
|
|
@@ -20973,7 +21145,7 @@ async function completeMigration(params) {
|
|
|
20973
21145
|
displayName
|
|
20974
21146
|
},
|
|
20975
21147
|
pubKeyCredParams: PUBKEY_CRED_PARAMS,
|
|
20976
|
-
authenticatorSelection
|
|
21148
|
+
authenticatorSelection,
|
|
20977
21149
|
timeout: WEBAUTHN_TIMEOUT,
|
|
20978
21150
|
attestation: ATTESTATION,
|
|
20979
21151
|
extensions: {
|
|
@@ -20982,7 +21154,10 @@ async function completeMigration(params) {
|
|
|
20982
21154
|
first: prfSalt.buffer
|
|
20983
21155
|
}
|
|
20984
21156
|
}
|
|
20985
|
-
}
|
|
21157
|
+
},
|
|
21158
|
+
// Chrome 128+ supports hints to prioritize certain authenticator types
|
|
21159
|
+
// On Windows/Linux, this prioritizes QR code over USB security key prompt
|
|
21160
|
+
...hints && { hints }
|
|
20986
21161
|
};
|
|
20987
21162
|
const credential = await navigator.credentials.create({
|
|
20988
21163
|
publicKey: publicKeyCredentialCreationOptions
|
|
@@ -21184,6 +21359,7 @@ exports.PasskeyNotFoundError = PasskeyNotFoundError;
|
|
|
21184
21359
|
exports.PrfNotSupportedError = PrfNotSupportedError;
|
|
21185
21360
|
exports.UserCancelledError = UserCancelledError;
|
|
21186
21361
|
exports.VolrProvider = VolrProvider;
|
|
21362
|
+
exports.WebAuthnBusyError = WebAuthnBusyError;
|
|
21187
21363
|
exports.analyzeContractForEIP7702 = analyzeContractForEIP7702;
|
|
21188
21364
|
exports.buildCall = buildCall;
|
|
21189
21365
|
exports.buildCalls = buildCalls;
|
|
@@ -21210,6 +21386,7 @@ exports.getWalletState = getWalletState;
|
|
|
21210
21386
|
exports.isEIP7702Delegated = isEIP7702Delegated;
|
|
21211
21387
|
exports.isInAppBrowser = isInAppBrowser;
|
|
21212
21388
|
exports.isUserCancelledError = isUserCancelledError;
|
|
21389
|
+
exports.isWebAuthnBusyError = isWebAuthnBusyError;
|
|
21213
21390
|
exports.listenForSeedRequests = listenForSeedRequests;
|
|
21214
21391
|
exports.normalizeHex = normalizeHex;
|
|
21215
21392
|
exports.normalizeHexArray = normalizeHexArray;
|
|
@@ -21223,6 +21400,8 @@ exports.useEIP6963 = useEIP6963;
|
|
|
21223
21400
|
exports.useInternalAuth = useInternalAuth;
|
|
21224
21401
|
exports.useMpcConnection = useMpcConnection;
|
|
21225
21402
|
exports.usePasskeyEnrollment = usePasskeyEnrollment;
|
|
21403
|
+
exports.usePrecheck = usePrecheck;
|
|
21404
|
+
exports.useRelay = useRelay;
|
|
21226
21405
|
exports.useUserBalances = useUserBalances;
|
|
21227
21406
|
exports.useVolr = useVolr;
|
|
21228
21407
|
exports.useVolrAuthCallback = useVolrAuthCallback;
|