@volr/react 0.1.131 → 0.1.132

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 CHANGED
@@ -9809,6 +9809,7 @@ function getWebAuthnHints() {
9809
9809
  }
9810
9810
  return void 0;
9811
9811
  }
9812
+ var AUTHENTICATOR_TRANSPORTS = ["internal", "hybrid"];
9812
9813
  var CREDENTIAL_MEDIATION = "required";
9813
9814
  var USER_VERIFICATION = "required";
9814
9815
  var WEBAUTHN_TIMEOUT = 6e4;
@@ -9976,43 +9977,41 @@ function createPasskeyAdapter(options = {}) {
9976
9977
  return { r, s };
9977
9978
  },
9978
9979
  async authenticate(prfInput) {
9979
- if (!prfInput.credentialId) {
9980
- throw new Error(
9981
- "[PasskeyAdapter] credentialId is required for authentication. This usually means the passkey was not properly registered or user data is incomplete. Please re-enroll your passkey."
9982
- );
9983
- }
9984
- const hexString = prfInput.credentialId.startsWith("0x") ? prfInput.credentialId.slice(2) : prfInput.credentialId;
9985
- if (!/^[0-9a-fA-F]+$/.test(hexString)) {
9986
- console.error(
9987
- "[PasskeyAdapter] Invalid credentialId format (not hex):",
9988
- prfInput.credentialId
9989
- );
9990
- throw new Error(
9991
- `[PasskeyAdapter] Invalid credentialId format. Expected hex string, got: ${prfInput.credentialId}`
9992
- );
9993
- }
9994
- const normalizedHex = hexString.length % 2 === 0 ? hexString : "0" + hexString;
9995
- const hexPairs = normalizedHex.match(/.{1,2}/g);
9996
- if (!hexPairs) {
9997
- throw new Error(
9998
- `[PasskeyAdapter] Failed to parse hex string: ${normalizedHex}`
9999
- );
10000
- }
10001
- const credIdBytes = new Uint8Array(
10002
- hexPairs.map((byte) => parseInt(byte, 16))
10003
- );
10004
- const reconvertedHex = Array.from(credIdBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
10005
- if (reconvertedHex.toLowerCase() !== normalizedHex.toLowerCase()) {
10006
- throw new Error(
10007
- `[PasskeyAdapter] credentialId conversion failed. Original: ${normalizedHex}, Reconverted: ${reconvertedHex}`
9980
+ const allowCredentials = [];
9981
+ if (prfInput.credentialId) {
9982
+ const hexString = prfInput.credentialId.startsWith("0x") ? prfInput.credentialId.slice(2) : prfInput.credentialId;
9983
+ if (!/^[0-9a-fA-F]+$/.test(hexString)) {
9984
+ console.error(
9985
+ "[PasskeyAdapter] Invalid credentialId format (not hex):",
9986
+ prfInput.credentialId
9987
+ );
9988
+ throw new Error(
9989
+ `[PasskeyAdapter] Invalid credentialId format. Expected hex string, got: ${prfInput.credentialId}`
9990
+ );
9991
+ }
9992
+ const normalizedHex = hexString.length % 2 === 0 ? hexString : "0" + hexString;
9993
+ const hexPairs = normalizedHex.match(/.{1,2}/g);
9994
+ if (!hexPairs) {
9995
+ throw new Error(
9996
+ `[PasskeyAdapter] Failed to parse hex string: ${normalizedHex}`
9997
+ );
9998
+ }
9999
+ const credIdBytes = new Uint8Array(
10000
+ hexPairs.map((byte) => parseInt(byte, 16))
10008
10001
  );
10009
- }
10010
- const allowCredentials = [
10011
- {
10012
- id: credIdBytes,
10013
- type: "public-key"
10002
+ const reconvertedHex = Array.from(credIdBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
10003
+ if (reconvertedHex.toLowerCase() !== normalizedHex.toLowerCase()) {
10004
+ throw new Error(
10005
+ `[PasskeyAdapter] credentialId conversion failed. Original: ${normalizedHex}, Reconverted: ${reconvertedHex}`
10006
+ );
10014
10007
  }
10015
- ];
10008
+ const transports = shouldForceCrossDevice() ? ["hybrid"] : AUTHENTICATOR_TRANSPORTS;
10009
+ allowCredentials.push({
10010
+ id: credIdBytes,
10011
+ type: "public-key",
10012
+ transports
10013
+ });
10014
+ }
10016
10015
  const hints = getWebAuthnHints();
10017
10016
  return withWebAuthnLock(async () => {
10018
10017
  let credential = null;
@@ -10021,6 +10020,8 @@ function createPasskeyAdapter(options = {}) {
10021
10020
  publicKey: {
10022
10021
  challenge: crypto.getRandomValues(new Uint8Array(32)),
10023
10022
  rpId,
10023
+ // If allowCredentials is empty, the browser will use discoverable credentials.
10024
+ // This enables the account chooser and cross-device (hybrid) QR flows.
10024
10025
  allowCredentials,
10025
10026
  userVerification: USER_VERIFICATION,
10026
10027
  // Shared constant
@@ -10424,6 +10425,10 @@ function VolrProvider({ config, children }) {
10424
10425
  const [isLoading, setIsLoading] = react.useState(true);
10425
10426
  const [error, setError] = react.useState(null);
10426
10427
  const [chainId] = react.useState(config.defaultChainId);
10428
+ const userRef = react.useRef(null);
10429
+ react.useEffect(() => {
10430
+ userRef.current = user;
10431
+ }, [user]);
10427
10432
  const [accessToken, setAccessTokenState] = react.useState(() => {
10428
10433
  return client.getAccessToken();
10429
10434
  });
@@ -10444,10 +10449,11 @@ function VolrProvider({ config, children }) {
10444
10449
  setError(null);
10445
10450
  const keyStorageType = newProvider.keyStorageType;
10446
10451
  setProviderState(newProvider);
10447
- const userHasCompleteData = user?.keyStorageType === "passkey" && user?.blobUrl && user?.prfInput && user?.id;
10452
+ const currentUser = userRef.current;
10453
+ const userHasCompleteData = currentUser?.keyStorageType === "passkey" && currentUser?.blobUrl && currentUser?.prfInput && currentUser?.id;
10448
10454
  if (userHasCompleteData) {
10449
10455
  console.log("[Provider] setProvider: User data already complete, skipping refresh");
10450
- if (user.keyStorageType !== keyStorageType) {
10456
+ if (currentUser?.keyStorageType !== keyStorageType) {
10451
10457
  setUser((prev) => ({ ...prev, keyStorageType }));
10452
10458
  }
10453
10459
  } else {
@@ -10479,7 +10485,7 @@ function VolrProvider({ config, children }) {
10479
10485
  throw error2;
10480
10486
  }
10481
10487
  },
10482
- [client, user, syncRef]
10488
+ [client, syncRef]
10483
10489
  );
10484
10490
  useAutoRecover({
10485
10491
  client,
@@ -18539,26 +18545,28 @@ function createGetRpcUrl(deps) {
18539
18545
  };
18540
18546
  }
18541
18547
  function createGetNetworkInfo(deps) {
18542
- const { client } = deps;
18548
+ const { client, rpcOverrides } = deps;
18543
18549
  return async function getNetworkInfo(chainId, includeRpcUrl = false) {
18550
+ const overrideUrl = rpcOverrides?.[chainId.toString()];
18544
18551
  const cached = networkCache.get(chainId);
18545
18552
  if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
18546
18553
  return {
18547
18554
  name: cached.name || `Chain ${chainId}`,
18548
- rpcUrl: includeRpcUrl ? cached.rpcUrl : void 0,
18555
+ rpcUrl: includeRpcUrl ? overrideUrl ?? cached.rpcUrl : void 0,
18549
18556
  invokerAddress: cached.invokerAddress
18550
18557
  };
18551
18558
  }
18552
18559
  const response = await client.get(`/networks/${chainId}${includeRpcUrl ? "?includeRpcUrl=true" : ""}`);
18553
18560
  networkCache.set(chainId, {
18554
18561
  name: response.name,
18555
- rpcUrl: response.rpcUrl,
18562
+ // If an override exists, cache it as the effective rpcUrl for this chainId
18563
+ rpcUrl: overrideUrl ?? response.rpcUrl,
18556
18564
  invokerAddress: response.invokerAddress,
18557
18565
  timestamp: Date.now()
18558
18566
  });
18559
18567
  return {
18560
18568
  name: response.name,
18561
- rpcUrl: includeRpcUrl ? response.rpcUrl : void 0,
18569
+ rpcUrl: includeRpcUrl ? overrideUrl ?? response.rpcUrl : void 0,
18562
18570
  invokerAddress: response.invokerAddress
18563
18571
  };
18564
18572
  };
@@ -18597,7 +18605,7 @@ function validateCalls2(calls) {
18597
18605
 
18598
18606
  // src/wallet/normalize.ts
18599
18607
  function normalizeCall(call2) {
18600
- const normalizedTarget = getAddress(call2.target);
18608
+ const normalizedTarget = normalizeHex(getAddress(call2.target));
18601
18609
  const normalizedData = normalizeHex(call2.data);
18602
18610
  const value = call2.value ?? 0n;
18603
18611
  const gasLimit = call2.gasLimit ?? 0n;
@@ -18833,7 +18841,7 @@ async function sendCalls(args) {
18833
18841
  if (chainId === 0) {
18834
18842
  throw new Error("chainId cannot be 0");
18835
18843
  }
18836
- const normalizedFrom = from14;
18844
+ const normalizedFrom = normalizeHex(from14);
18837
18845
  const normalizedCalls = normalizeCalls(calls);
18838
18846
  validateCalls2(normalizedCalls);
18839
18847
  if (!deps.provider && deps.user?.keyStorageType !== "passkey") {
@@ -18897,7 +18905,7 @@ async function sendCalls(args) {
18897
18905
  if (!quotePolicyId) {
18898
18906
  throw new Error("Backend did not return policyId in precheck response");
18899
18907
  }
18900
- const projectPolicyId = quotePolicyId;
18908
+ const projectPolicyId = normalizeHex(quotePolicyId);
18901
18909
  validatePolicyId2(projectPolicyId);
18902
18910
  const tempAuth = buildTempAuth({
18903
18911
  chainId,