@swype-org/react-sdk 0.1.232 → 0.1.241

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.d.cts CHANGED
@@ -375,11 +375,12 @@ declare function updateUserConfig(apiBaseUrl: string, token: string, config: {
375
375
  defaultAllowance: number;
376
376
  }): Promise<void>;
377
377
  /**
378
- * Updates the user's default allowance, authenticated by session ID.
378
+ * Updates default allowance for the authorization session.
379
379
  * PATCH /v1/authorization-sessions/{id}/user-config
380
380
  *
381
- * This does not require a bearer token — the session ID itself serves
382
- * as proof of authorization.
381
+ * No bearer token — the session ID is the credential. When the session has no
382
+ * linked user yet (e.g. guest account setup), config is stored on the session
383
+ * and used as the account allowance until the user is claimed.
383
384
  */
384
385
  declare function updateUserConfigBySession(apiBaseUrl: string, sessionId: string, config: {
385
386
  defaultAllowance: number;
@@ -857,7 +858,6 @@ type PaymentPhase = {
857
858
  step: 'select-source';
858
859
  action: AuthorizationAction;
859
860
  isDesktop: boolean;
860
- skipOneTapLimit?: boolean;
861
861
  } | {
862
862
  step: 'one-tap-setup';
863
863
  action: AuthorizationAction | null;
package/dist/index.d.ts CHANGED
@@ -375,11 +375,12 @@ declare function updateUserConfig(apiBaseUrl: string, token: string, config: {
375
375
  defaultAllowance: number;
376
376
  }): Promise<void>;
377
377
  /**
378
- * Updates the user's default allowance, authenticated by session ID.
378
+ * Updates default allowance for the authorization session.
379
379
  * PATCH /v1/authorization-sessions/{id}/user-config
380
380
  *
381
- * This does not require a bearer token — the session ID itself serves
382
- * as proof of authorization.
381
+ * No bearer token — the session ID is the credential. When the session has no
382
+ * linked user yet (e.g. guest account setup), config is stored on the session
383
+ * and used as the account allowance until the user is claimed.
383
384
  */
384
385
  declare function updateUserConfigBySession(apiBaseUrl: string, sessionId: string, config: {
385
386
  defaultAllowance: number;
@@ -857,7 +858,6 @@ type PaymentPhase = {
857
858
  step: 'select-source';
858
859
  action: AuthorizationAction;
859
860
  isDesktop: boolean;
860
- skipOneTapLimit?: boolean;
861
861
  } | {
862
862
  step: 'one-tap-setup';
863
863
  action: AuthorizationAction | null;
package/dist/index.js CHANGED
@@ -2001,14 +2001,29 @@ function isTransferInFlight(transfer) {
2001
2001
  if (!transfer) return false;
2002
2002
  return ["CREATED", "SENDING", "SENT"].includes(transfer.status);
2003
2003
  }
2004
+ function isGuestPreauthCompletedTransferPinPhase(phase) {
2005
+ switch (phase.step) {
2006
+ case "completed":
2007
+ case "select-source":
2008
+ case "one-tap-setup":
2009
+ case "token-picker":
2010
+ case "login":
2011
+ case "otp-verify":
2012
+ case "passkey-create":
2013
+ case "passkey-verify":
2014
+ case "data-loading":
2015
+ return true;
2016
+ case "wallet-setup":
2017
+ return phase.mobile == null;
2018
+ default:
2019
+ return false;
2020
+ }
2021
+ }
2004
2022
  function resolvePhase(state) {
2005
2023
  const p = state.phase;
2006
- if (p.step === "select-source" && state.transfer?.status === "COMPLETED" && state.guestPreauthorizing) {
2024
+ if (state.transfer?.status === "COMPLETED" && state.guestPreauthorizing && isGuestPreauthCompletedTransferPinPhase(p)) {
2007
2025
  return p;
2008
2026
  }
2009
- if (state.transfer?.status === "COMPLETED" && state.guestPreauthorizing) {
2010
- return { step: "processing", transfer: state.transfer };
2011
- }
2012
2027
  if (state.transfer?.status === "COMPLETED") {
2013
2028
  return { step: "completed", transfer: state.transfer };
2014
2029
  }
@@ -2018,10 +2033,9 @@ function resolvePhase(state) {
2018
2033
  if (state.creatingTransfer || isTransferInFlight(state.transfer)) {
2019
2034
  return { step: "processing", transfer: state.transfer };
2020
2035
  }
2021
- if (p.step === "token-picker" || p.step === "one-tap-setup" || p.step === "select-source" || p.step === "confirm-sign" || p.step === "guest-token-picker") {
2036
+ if (!state.loginRequested && (p.step === "token-picker" || p.step === "one-tap-setup" || p.step === "select-source" || p.step === "confirm-sign" || p.step === "guest-token-picker")) {
2022
2037
  return p;
2023
2038
  }
2024
- if (p.step === "wallet-setup") return p;
2025
2039
  if (state.mobileFlow && state.deeplinkUri) {
2026
2040
  return {
2027
2041
  step: "wallet-setup",
@@ -2029,7 +2043,19 @@ function resolvePhase(state) {
2029
2043
  accountId: null
2030
2044
  };
2031
2045
  }
2032
- if (!state.activeCredentialId && !state.passkeyConfigLoaded) {
2046
+ if (p.step === "wallet-setup" && p.mobile == null) {
2047
+ return p;
2048
+ }
2049
+ if (state.isGuestFlow && state.selectedProviderId != null && !state.transfer) {
2050
+ return { step: "guest-token-picker" };
2051
+ }
2052
+ if (p.step === "wallet-picker" && !state.creatingTransfer && !(state.mobileFlow && state.deeplinkUri)) {
2053
+ return p;
2054
+ }
2055
+ if (!state.privyReady) {
2056
+ return { step: "initializing" };
2057
+ }
2058
+ if (state.privyAuthenticated && !state.activeCredentialId && !state.passkeyConfigLoaded) {
2033
2059
  return { step: "initializing" };
2034
2060
  }
2035
2061
  if (state.verificationTarget) {
@@ -2047,9 +2073,6 @@ function resolvePhase(state) {
2047
2073
  if (state.loadingData && state.activeCredentialId && hasActiveWallet(state.accounts)) {
2048
2074
  return { step: "data-loading" };
2049
2075
  }
2050
- if (state.isGuestFlow && state.selectedProviderId != null && !state.transfer) {
2051
- return { step: "guest-token-picker" };
2052
- }
2053
2076
  if (state.activeCredentialId && !hasActiveWallet(state.accounts) && !state.mobileFlow) {
2054
2077
  return { step: "wallet-picker", reason: "link" };
2055
2078
  }
@@ -2106,7 +2129,9 @@ function createInitialState(config) {
2106
2129
  guestPreauthSessionId: null,
2107
2130
  activePublicKey: null,
2108
2131
  loginRequested: false,
2109
- guestPreauthorizing: false
2132
+ guestPreauthorizing: false,
2133
+ privyReady: false,
2134
+ privyAuthenticated: false
2110
2135
  };
2111
2136
  }
2112
2137
  function paymentReducer(state, action) {
@@ -2336,6 +2361,17 @@ function applyAction(state, action) {
2336
2361
  selectedWalletId: null,
2337
2362
  selectedTokenSymbol: null
2338
2363
  };
2364
+ case "GUEST_BACK_FROM_TOKEN_PICKER":
2365
+ return {
2366
+ ...state,
2367
+ selectedProviderId: null,
2368
+ guestTransferId: null,
2369
+ guestSessionToken: null,
2370
+ selectedAccountId: null,
2371
+ selectedWalletId: null,
2372
+ selectedTokenSymbol: null,
2373
+ error: null
2374
+ };
2339
2375
  case "GUEST_TRANSFER_COMPLETED":
2340
2376
  return {
2341
2377
  ...state,
@@ -2349,7 +2385,10 @@ function applyAction(state, action) {
2349
2385
  return {
2350
2386
  ...state,
2351
2387
  guestPreauthAccountId: action.accountId,
2352
- guestPreauthSessionId: action.sessionId ?? state.guestPreauthSessionId
2388
+ guestPreauthSessionId: action.sessionId ?? state.guestPreauthSessionId,
2389
+ selectedAccountId: action.accountId,
2390
+ selectedWalletId: null,
2391
+ selectedTokenSymbol: null
2353
2392
  };
2354
2393
  case "GUEST_PREAUTH_BEGIN":
2355
2394
  return { ...state, guestPreauthorizing: true, error: null };
@@ -2407,7 +2446,15 @@ function applyAction(state, action) {
2407
2446
  depositAmount: action.depositAmount,
2408
2447
  passkeyPopupNeeded: state.passkeyPopupNeeded,
2409
2448
  activeCredentialId: null
2410
- })
2449
+ }),
2450
+ privyReady: action.privyReady,
2451
+ privyAuthenticated: false
2452
+ };
2453
+ case "SYNC_PRIVY_SESSION":
2454
+ return {
2455
+ ...state,
2456
+ privyReady: action.ready,
2457
+ privyAuthenticated: action.authenticated
2411
2458
  };
2412
2459
  case "SYNC_AMOUNT":
2413
2460
  return { ...state, amount: action.amount };
@@ -2475,7 +2522,6 @@ function screenForPhase(phase) {
2475
2522
  case "wallet-setup":
2476
2523
  return phase.mobile ? "open-wallet" : "setup-status";
2477
2524
  case "select-source":
2478
- if (phase.skipOneTapLimit) return "select-source";
2479
2525
  return phase.isDesktop ? "setup" : "select-source";
2480
2526
  case "one-tap-setup":
2481
2527
  return "setup";
@@ -6011,7 +6057,8 @@ function StepRendererContent({
6011
6057
  pollingError,
6012
6058
  authExecutorError,
6013
6059
  transferSigningSigning,
6014
- transferSigningError
6060
+ transferSigningError,
6061
+ pendingSelectSource
6015
6062
  } = remote;
6016
6063
  const {
6017
6064
  pendingConnections,
@@ -6211,6 +6258,26 @@ function StepRendererContent({
6211
6258
  }
6212
6259
  case "token-picker": {
6213
6260
  if (!selectedAccount) {
6261
+ if (pendingSelectSource && selectSourceChoices.length > 0) {
6262
+ return /* @__PURE__ */ jsx(
6263
+ SelectSourceScreen,
6264
+ {
6265
+ choices: selectSourceChoices,
6266
+ selectedChainName: selectSourceChainName,
6267
+ selectedTokenSymbol: selectSourceTokenSymbol,
6268
+ recommended: selectSourceRecommended,
6269
+ onChainChange: handlers.onSelectSourceChainChange,
6270
+ onTokenChange: handlers.onSetSelectSourceTokenSymbol,
6271
+ onConfirm: handlers.onConfirmSelectSource,
6272
+ onBack: () => handlers.onSetPhase({
6273
+ step: "select-source",
6274
+ action: pendingSelectSource,
6275
+ isDesktop
6276
+ }),
6277
+ onLogout: handlers.onLogout
6278
+ }
6279
+ );
6280
+ }
6214
6281
  return /* @__PURE__ */ jsx(BlinkLoadingScreen, {});
6215
6282
  }
6216
6283
  return /* @__PURE__ */ jsx(
@@ -6238,7 +6305,7 @@ function StepRendererContent({
6238
6305
  depositAmount: depositAmount ?? void 0,
6239
6306
  error: state.error,
6240
6307
  onSelect: handlers.onSelectGuestToken,
6241
- onBack: () => handlers.onSetPhase({ step: "wallet-picker", reason: "guest-entry" })
6308
+ onBack: handlers.onGuestBackFromTokenPicker
6242
6309
  }
6243
6310
  );
6244
6311
  case "processing": {
@@ -6520,9 +6587,18 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6520
6587
  const { user, getAccessToken } = usePrivy();
6521
6588
  const checkingPasskeyRef = useRef(false);
6522
6589
  const activateExistingCredential = useCallback(async (credentialId) => {
6523
- dispatch({ type: "PASSKEY_ACTIVATED", credentialId });
6524
- window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
6525
6590
  const token = await getAccessToken();
6591
+ let publicKey;
6592
+ if (token) {
6593
+ try {
6594
+ const { config } = await fetchUserConfig(apiBaseUrl, token);
6595
+ const allPasskeys = config.passkeys ?? (config.passkey ? [config.passkey] : []);
6596
+ publicKey = allPasskeys.find((p) => p.credentialId === credentialId)?.publicKey;
6597
+ } catch {
6598
+ }
6599
+ }
6600
+ dispatch({ type: "PASSKEY_ACTIVATED", credentialId, publicKey });
6601
+ window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
6526
6602
  if (token) {
6527
6603
  reportPasskeyActivity(apiBaseUrl, token, credentialId).catch(() => {
6528
6604
  });
@@ -6595,9 +6671,13 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6595
6671
  authToken: token ?? void 0,
6596
6672
  apiBaseUrl
6597
6673
  });
6598
- const { credentialId } = await createPasskeyViaPopup(popupOptions);
6599
- dispatch({ type: "PASSKEY_ACTIVATED", credentialId });
6674
+ const { credentialId, publicKey } = await createPasskeyViaPopup(popupOptions);
6675
+ dispatch({ type: "PASSKEY_ACTIVATED", credentialId, publicKey });
6600
6676
  localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
6677
+ if (token) {
6678
+ reportPasskeyActivity(apiBaseUrl, token, credentialId).catch(() => {
6679
+ });
6680
+ }
6601
6681
  } catch (err) {
6602
6682
  captureException(err);
6603
6683
  dispatch({
@@ -6613,19 +6693,25 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6613
6693
  dispatch({ type: "SET_ERROR", error: null });
6614
6694
  try {
6615
6695
  const token = await getAccessToken();
6696
+ if (!token) throw new Error("Not authenticated");
6616
6697
  const matched = await findDevicePasskeyViaPopup({
6617
6698
  credentialIds: knownCredentialIds,
6618
6699
  rpId: resolvePasskeyRpId(),
6619
- authToken: token ?? void 0,
6700
+ authToken: token,
6620
6701
  apiBaseUrl
6621
6702
  });
6622
6703
  if (matched) {
6623
- dispatch({ type: "PASSKEY_ACTIVATED", credentialId: matched });
6624
- window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
6625
- if (token) {
6626
- reportPasskeyActivity(apiBaseUrl, token, matched).catch(() => {
6627
- });
6704
+ let publicKey;
6705
+ try {
6706
+ const { config } = await fetchUserConfig(apiBaseUrl, token);
6707
+ const allPasskeys = config.passkeys ?? (config.passkey ? [config.passkey] : []);
6708
+ publicKey = allPasskeys.find((p) => p.credentialId === matched)?.publicKey;
6709
+ } catch {
6628
6710
  }
6711
+ dispatch({ type: "PASSKEY_ACTIVATED", credentialId: matched, publicKey });
6712
+ window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
6713
+ reportPasskeyActivity(apiBaseUrl, token, matched).catch(() => {
6714
+ });
6629
6715
  } else {
6630
6716
  dispatch({
6631
6717
  type: "SET_ERROR",
@@ -6789,15 +6875,15 @@ function useTransferHandlers(deps) {
6789
6875
  pollingTransferIdRef
6790
6876
  };
6791
6877
  }
6792
- function useSourceSelectionHandlers(dispatch, authExecutor) {
6878
+ function useSourceSelectionHandlers(dispatch, authExecutor, options) {
6793
6879
  const [selectSourceChainName, setSelectSourceChainName] = useState("");
6794
6880
  const [selectSourceTokenSymbol, setSelectSourceTokenSymbol] = useState("");
6795
6881
  const initializedSelectSourceActionRef = useRef(null);
6796
6882
  const pendingSelectSourceAction = authExecutor.pendingSelectSource;
6797
6883
  const selectSourceChoices = useMemo(() => {
6798
6884
  if (!pendingSelectSourceAction) return [];
6799
- const options = pendingSelectSourceAction.metadata?.options ?? [];
6800
- return buildSelectSourceChoices(options);
6885
+ const options2 = pendingSelectSourceAction.metadata?.options ?? [];
6886
+ return buildSelectSourceChoices(options2);
6801
6887
  }, [pendingSelectSourceAction]);
6802
6888
  const selectSourceRecommended = useMemo(() => {
6803
6889
  if (!pendingSelectSourceAction) return null;
@@ -6805,16 +6891,16 @@ function useSourceSelectionHandlers(dispatch, authExecutor) {
6805
6891
  }, [pendingSelectSourceAction]);
6806
6892
  const selectSourceAvailableBalance = useMemo(() => {
6807
6893
  if (!pendingSelectSourceAction) return 0;
6808
- const options = pendingSelectSourceAction.metadata?.options ?? [];
6894
+ const options2 = pendingSelectSourceAction.metadata?.options ?? [];
6809
6895
  const recommended = selectSourceRecommended;
6810
6896
  if (recommended) {
6811
- const match = options.find(
6897
+ const match = options2.find(
6812
6898
  (opt) => opt.chainName === recommended.chainName && opt.tokenSymbol === recommended.tokenSymbol
6813
6899
  );
6814
6900
  if (match) return Number(match.rawBalance) / Math.pow(10, match.decimals);
6815
6901
  }
6816
6902
  let max = 0;
6817
- for (const opt of options) {
6903
+ for (const opt of options2) {
6818
6904
  const bal = Number(opt.rawBalance) / Math.pow(10, opt.decimals);
6819
6905
  if (bal > max) max = bal;
6820
6906
  }
@@ -6838,7 +6924,17 @@ function useSourceSelectionHandlers(dispatch, authExecutor) {
6838
6924
  chainName: selectSourceChainName,
6839
6925
  tokenSymbol: selectSourceTokenSymbol
6840
6926
  });
6841
- }, [authExecutor, selectSourceChainName, selectSourceTokenSymbol]);
6927
+ if (options?.guestPreauthorizing && options?.isDesktop) {
6928
+ dispatch({ type: "REQUEST_LOGIN" });
6929
+ }
6930
+ }, [
6931
+ authExecutor,
6932
+ dispatch,
6933
+ options?.guestPreauthorizing,
6934
+ options?.isDesktop,
6935
+ selectSourceChainName,
6936
+ selectSourceTokenSymbol
6937
+ ]);
6842
6938
  return {
6843
6939
  selectSourceChainName,
6844
6940
  selectSourceTokenSymbol,
@@ -7674,11 +7770,15 @@ function useGuestTransferHandlers(deps) {
7674
7770
  };
7675
7771
  execute();
7676
7772
  }, [isGuestFlow, guestTransferId, guestSessionToken, settingSender, apiBaseUrl, wagmiConfig2, switchChainAsync, dispatch, onComplete, onError]);
7773
+ const handleGuestBackFromTokenPicker = useCallback(() => {
7774
+ dispatch({ type: "GUEST_BACK_FROM_TOKEN_PICKER" });
7775
+ }, [dispatch]);
7677
7776
  return {
7678
7777
  guestTokenEntries,
7679
7778
  loadingBalances,
7680
7779
  settingSender,
7681
- handleSelectGuestToken
7780
+ handleSelectGuestToken,
7781
+ handleGuestBackFromTokenPicker
7682
7782
  };
7683
7783
  }
7684
7784
  function useOneTapSetupHandlers(deps) {
@@ -7688,15 +7788,24 @@ function useOneTapSetupHandlers(deps) {
7688
7788
  apiBaseUrl,
7689
7789
  authExecutor,
7690
7790
  selectSourceChainName,
7691
- selectSourceTokenSymbol
7791
+ selectSourceTokenSymbol,
7792
+ authorizationSessionIdForGuest
7692
7793
  } = deps;
7693
7794
  const [savingOneTapLimit, setSavingOneTapLimit] = useState(false);
7694
7795
  const handleSetupOneTap = useCallback(async (limit) => {
7695
7796
  setSavingOneTapLimit(true);
7696
7797
  try {
7697
- const token = await getAccessToken();
7698
- if (!token) throw new Error("Not authenticated");
7699
- await updateUserConfig(apiBaseUrl, token, { defaultAllowance: limit });
7798
+ if (authorizationSessionIdForGuest) {
7799
+ await updateUserConfigBySession(
7800
+ apiBaseUrl,
7801
+ authorizationSessionIdForGuest,
7802
+ { defaultAllowance: limit }
7803
+ );
7804
+ } else {
7805
+ const token = await getAccessToken();
7806
+ if (!token) throw new Error("Not authenticated");
7807
+ await updateUserConfig(apiBaseUrl, token, { defaultAllowance: limit });
7808
+ }
7700
7809
  if (authExecutor.pendingSelectSource) {
7701
7810
  const action = authExecutor.pendingSelectSource;
7702
7811
  const recommended = action.metadata?.recommended;
@@ -7726,12 +7835,30 @@ function useOneTapSetupHandlers(deps) {
7726
7835
  } finally {
7727
7836
  setSavingOneTapLimit(false);
7728
7837
  }
7729
- }, [getAccessToken, apiBaseUrl, authExecutor, dispatch, selectSourceChainName, selectSourceTokenSymbol]);
7838
+ }, [
7839
+ getAccessToken,
7840
+ apiBaseUrl,
7841
+ authExecutor,
7842
+ dispatch,
7843
+ selectSourceChainName,
7844
+ selectSourceTokenSymbol,
7845
+ authorizationSessionIdForGuest
7846
+ ]);
7730
7847
  return {
7731
7848
  handleSetupOneTap,
7732
7849
  savingOneTapLimit
7733
7850
  };
7734
7851
  }
7852
+ function usePrivySessionSyncEffect(deps) {
7853
+ const { dispatch, ready, authenticated } = deps;
7854
+ useEffect(() => {
7855
+ dispatch({
7856
+ type: "SYNC_PRIVY_SESSION",
7857
+ ready,
7858
+ authenticated
7859
+ });
7860
+ }, [dispatch, ready, authenticated]);
7861
+ }
7735
7862
  function useOtpEffects(deps) {
7736
7863
  const {
7737
7864
  state,
@@ -7925,7 +8052,18 @@ function usePasskeyCheckEffect(deps) {
7925
8052
  if (token || cancelled) break;
7926
8053
  await new Promise((r) => setTimeout(r, 1e3));
7927
8054
  }
7928
- if (!token || cancelled) return;
8055
+ if (cancelled) return;
8056
+ if (!token) {
8057
+ dispatch({
8058
+ type: "PASSKEY_CONFIG_LOADED",
8059
+ knownIds: []
8060
+ });
8061
+ dispatch({
8062
+ type: "SET_ERROR",
8063
+ error: "Could not refresh your session. Try signing in again."
8064
+ });
8065
+ return;
8066
+ }
7929
8067
  const { config } = await fetchUserConfig(apiBaseUrl, token);
7930
8068
  if (cancelled) return;
7931
8069
  const allPasskeys = config.passkeys ?? (config.passkey ? [config.passkey] : []);
@@ -7936,6 +8074,10 @@ function usePasskeyCheckEffect(deps) {
7936
8074
  });
7937
8075
  if (allPasskeys.length === 0) return;
7938
8076
  if (activeCredentialId && allPasskeys.some((p) => p.credentialId === activeCredentialId)) {
8077
+ const pk = allPasskeys.find((p) => p.credentialId === activeCredentialId)?.publicKey;
8078
+ if (pk) {
8079
+ dispatch({ type: "PASSKEY_ACTIVATED", credentialId: activeCredentialId, publicKey: pk });
8080
+ }
7939
8081
  await restoreState(activeCredentialId, token);
7940
8082
  return;
7941
8083
  }
@@ -7954,13 +8096,22 @@ function usePasskeyCheckEffect(deps) {
7954
8096
  }
7955
8097
  if (cancelled) return;
7956
8098
  if (matched) {
7957
- dispatch({ type: "PASSKEY_ACTIVATED", credentialId: matched });
8099
+ const publicKey = allPasskeys.find((p) => p.credentialId === matched)?.publicKey;
8100
+ dispatch({ type: "PASSKEY_ACTIVATED", credentialId: matched, publicKey });
7958
8101
  window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
7959
8102
  reportPasskeyActivity(apiBaseUrl, token, matched).catch(() => {
7960
8103
  });
7961
8104
  await restoreState(matched, token);
7962
8105
  }
7963
- } catch {
8106
+ } catch (err) {
8107
+ dispatch({
8108
+ type: "PASSKEY_CONFIG_LOADED",
8109
+ knownIds: []
8110
+ });
8111
+ dispatch({
8112
+ type: "SET_ERROR",
8113
+ error: err instanceof Error ? err.message : "Unable to load passkey settings."
8114
+ });
7964
8115
  }
7965
8116
  };
7966
8117
  checkPasskey();
@@ -8510,22 +8661,25 @@ function useGuestPreauthPhaseSyncEffect(deps) {
8510
8661
  if (!state.guestPreauthorizing || !isDesktop) return;
8511
8662
  const pending = authExecutor.pendingSelectSource;
8512
8663
  if (pending) {
8664
+ if (state.phase.step === "token-picker") {
8665
+ return;
8666
+ }
8513
8667
  const intent = {
8514
8668
  step: "select-source",
8515
8669
  action: pending,
8516
- isDesktop,
8517
- skipOneTapLimit: true
8670
+ isDesktop
8518
8671
  };
8519
- if (state.phase.step === "select-source") {
8520
- const ph = state.phase;
8521
- if (ph.skipOneTapLimit && ph.action.id === pending.id) {
8522
- return;
8523
- }
8672
+ if (state.phase.step === "select-source" && state.phase.action.id === pending.id) {
8673
+ return;
8524
8674
  }
8525
8675
  dispatch({ type: "SET_USER_INTENT", intent });
8526
8676
  return;
8527
8677
  }
8528
- if (state.phase.step === "select-source" && state.phase.skipOneTapLimit === true) {
8678
+ if (state.phase.step === "select-source") {
8679
+ dispatch({ type: "SET_USER_INTENT", intent: { step: "one-tap-setup", action: null } });
8680
+ return;
8681
+ }
8682
+ if (state.phase.step === "token-picker") {
8529
8683
  dispatch({ type: "SET_USER_INTENT", intent: { step: "one-tap-setup", action: null } });
8530
8684
  }
8531
8685
  }, [
@@ -8536,6 +8690,42 @@ function useGuestPreauthPhaseSyncEffect(deps) {
8536
8690
  dispatch
8537
8691
  ]);
8538
8692
  }
8693
+ function useGuestPreauthWalletSetupEffect(deps) {
8694
+ const { state, dispatch, authExecutor, isDesktop, privyAuthenticated } = deps;
8695
+ useEffect(() => {
8696
+ if (!isDesktop || !state.guestPreauthorizing || !state.guestPreauthSessionId) return;
8697
+ if (!authExecutor.executing || authExecutor.pendingSelectSource) return;
8698
+ if (!privyAuthenticated || !state.activeCredentialId) return;
8699
+ if (state.verificationTarget) return;
8700
+ if (state.loginRequested) return;
8701
+ const p = state.phase;
8702
+ if (p.step === "wallet-setup" && p.mobile == null) {
8703
+ const id = state.guestPreauthAccountId;
8704
+ if (id != null && p.accountId === id) return;
8705
+ }
8706
+ dispatch({
8707
+ type: "SET_USER_INTENT",
8708
+ intent: {
8709
+ step: "wallet-setup",
8710
+ mobile: null,
8711
+ accountId: state.guestPreauthAccountId
8712
+ }
8713
+ });
8714
+ }, [
8715
+ isDesktop,
8716
+ state.guestPreauthorizing,
8717
+ state.guestPreauthSessionId,
8718
+ state.guestPreauthAccountId,
8719
+ state.activeCredentialId,
8720
+ state.verificationTarget,
8721
+ state.loginRequested,
8722
+ state.phase,
8723
+ authExecutor.executing,
8724
+ authExecutor.pendingSelectSource,
8725
+ dispatch,
8726
+ privyAuthenticated
8727
+ ]);
8728
+ }
8539
8729
  function BlinkPayment(props) {
8540
8730
  const resetKey = useRef(0);
8541
8731
  const handleBoundaryReset = useCallback(() => {
@@ -8620,7 +8810,10 @@ function BlinkPaymentInner({
8620
8810
  mobileFlowRefs,
8621
8811
  onComplete
8622
8812
  );
8623
- const sourceSelection = useSourceSelectionHandlers(dispatch, authExecutor);
8813
+ const sourceSelection = useSourceSelectionHandlers(dispatch, authExecutor, {
8814
+ guestPreauthorizing: state.guestPreauthorizing,
8815
+ isDesktop
8816
+ });
8624
8817
  const provider = useProviderHandlers({
8625
8818
  dispatch,
8626
8819
  getAccessToken,
@@ -8654,7 +8847,8 @@ function BlinkPaymentInner({
8654
8847
  apiBaseUrl,
8655
8848
  authExecutor,
8656
8849
  selectSourceChainName: sourceSelection.selectSourceChainName,
8657
- selectSourceTokenSymbol: sourceSelection.selectSourceTokenSymbol
8850
+ selectSourceTokenSymbol: sourceSelection.selectSourceTokenSymbol,
8851
+ authorizationSessionIdForGuest: state.guestPreauthSessionId
8658
8852
  });
8659
8853
  const guestTransfer = useGuestTransferHandlers({
8660
8854
  dispatch,
@@ -8687,13 +8881,14 @@ function BlinkPaymentInner({
8687
8881
  passkey.checkingPasskeyRef.current = false;
8688
8882
  auth.setAuthInput("");
8689
8883
  auth.setOtpCode("");
8690
- dispatch({ type: "LOGOUT", depositAmount });
8691
- }, [logout, polling, depositAmount, auth, passkey]);
8884
+ dispatch({ type: "LOGOUT", depositAmount, privyReady: ready });
8885
+ }, [logout, polling, depositAmount, auth, passkey, ready]);
8692
8886
  useEffect(() => {
8693
8887
  if (depositAmount != null) {
8694
8888
  dispatch({ type: "SYNC_AMOUNT", amount: depositAmount.toString() });
8695
8889
  }
8696
8890
  }, [depositAmount, dispatch]);
8891
+ usePrivySessionSyncEffect({ dispatch, ready, authenticated });
8697
8892
  useOtpEffects({
8698
8893
  state,
8699
8894
  dispatch,
@@ -8791,6 +8986,13 @@ function BlinkPaymentInner({
8791
8986
  dispatch,
8792
8987
  desktopGuestPreauth: isDesktop
8793
8988
  });
8989
+ useGuestPreauthWalletSetupEffect({
8990
+ state,
8991
+ dispatch,
8992
+ authExecutor,
8993
+ isDesktop,
8994
+ privyAuthenticated: authenticated
8995
+ });
8794
8996
  const handlers = useMemo(() => ({
8795
8997
  onSendLoginCode: auth.handleSendLoginCode,
8796
8998
  onVerifyLoginCode: auth.handleVerifyLoginCode,
@@ -8827,6 +9029,7 @@ function BlinkPaymentInner({
8827
9029
  onSelectAuthorizedToken: provider.handleSelectAuthorizedToken,
8828
9030
  onAuthorizeToken: provider.handleAuthorizeToken,
8829
9031
  onSelectGuestToken: guestTransfer.handleSelectGuestToken,
9032
+ onGuestBackFromTokenPicker: guestTransfer.handleGuestBackFromTokenPicker,
8830
9033
  onLogin: () => dispatch({ type: "REQUEST_LOGIN" }),
8831
9034
  onPreauthorize: provider.handlePreauthorize
8832
9035
  }), [