@swype-org/react-sdk 0.1.329 → 0.1.333

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
@@ -1951,7 +1951,7 @@ function resolvePhase(state) {
1951
1951
  const isFundingSourceSubflow = !state.loginRequested && (currentPhase.step === "token-picker" || currentPhase.step === "one-tap-setup" || currentPhase.step === "select-source" || currentPhase.step === "confirm-sign" || currentPhase.step === "guest-token-picker" && guestTokenPickerEligible);
1952
1952
  const walletPickerSwitchEligible = currentPhase.step === "wallet-picker" && currentPhase.reason === "switch" && !state.creatingTransfer && !(state.mobileFlow && state.deeplinkUri);
1953
1953
  const missingActivePasskeyCredential = state.passkeyConfigLoaded && !state.activeCredentialId;
1954
- const shouldPromptPasskeyVerification = missingActivePasskeyCredential && state.knownCredentialIds.length > 0 && state.passkeyPopupNeeded;
1954
+ const shouldPromptPasskeyVerification = missingActivePasskeyCredential && state.knownCredentialIds.length > 0;
1955
1955
  const guestPreauthClaimPending = state.guestPreauthAccountId != null && state.guestSessionToken != null && state.privyAuthenticated && state.activeCredentialId != null && !state.guestPreauthSetupCompletePending && !state.error;
1956
1956
  const branchGuestSetupComplete = state.guestPreauthSetupCompletePending && state.privyReady && state.privyAuthenticated;
1957
1957
  const branchKeepGuestPreauthPin = !branchGuestSetupComplete && guestPreauthPinsCurrentPhase;
@@ -3760,16 +3760,33 @@ function PasskeyScreen({
3760
3760
  creating,
3761
3761
  error,
3762
3762
  popupFallback = false,
3763
- onCreatePasskeyViaPopup
3763
+ onCreatePasskeyViaPopup,
3764
+ onCreateNewPasskey,
3765
+ onCreateNewPasskeyViaPopup,
3766
+ createNewPopupFallback,
3767
+ creatingNewPasskey
3764
3768
  }) {
3765
3769
  const { tokens } = useBlinkConfig();
3766
3770
  const handleCreate = popupFallback && onCreatePasskeyViaPopup ? onCreatePasskeyViaPopup : onCreatePasskey;
3767
3771
  const buttonLabel = popupFallback ? "Open Passkey Window" : "Verify Passkey";
3772
+ const showCreateNewLink = onCreateNewPasskey != null;
3773
+ const usePopupForNew = createNewPopupFallback ?? popupFallback;
3774
+ const handleCreateNew = usePopupForNew && onCreateNewPasskeyViaPopup ? onCreateNewPasskeyViaPopup : onCreateNewPasskey;
3768
3775
  return /* @__PURE__ */ jsxRuntime.jsxs(
3769
3776
  ScreenLayout,
3770
3777
  {
3771
3778
  footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3772
- /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: handleCreate, disabled: creating, loading: creating, children: buttonLabel }),
3779
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: handleCreate, disabled: creating || creatingNewPasskey, loading: creating, children: buttonLabel }),
3780
+ showCreateNewLink && /* @__PURE__ */ jsxRuntime.jsx(
3781
+ "button",
3782
+ {
3783
+ type: "button",
3784
+ onClick: handleCreateNew,
3785
+ disabled: creatingNewPasskey || creating,
3786
+ style: createNewLinkStyle(tokens.textMuted),
3787
+ children: creatingNewPasskey ? "Creating passkey\u2026" : "Create a new passkey for this device"
3788
+ }
3789
+ ),
3773
3790
  /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
3774
3791
  ] }),
3775
3792
  children: [
@@ -3804,6 +3821,17 @@ var subtitleStyle3 = (color) => ({
3804
3821
  margin: "0 0 20px",
3805
3822
  lineHeight: 1.5
3806
3823
  });
3824
+ var createNewLinkStyle = (color) => ({
3825
+ background: "none",
3826
+ border: "none",
3827
+ color,
3828
+ fontSize: "0.85rem",
3829
+ cursor: "pointer",
3830
+ padding: "8px 16px",
3831
+ textDecoration: "underline",
3832
+ fontFamily: "inherit",
3833
+ width: "100%"
3834
+ });
3807
3835
  var errorBannerStyle2 = (tokens) => ({
3808
3836
  background: tokens.errorBg,
3809
3837
  border: `1px solid ${tokens.error}66`,
@@ -4987,13 +5015,14 @@ function DepositScreen({
4987
5015
  const selectedProviderLogo = KNOWN_LOGOS[selectedProviderName.toLowerCase()];
4988
5016
  const totalAccountBalance = selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : availableBalance;
4989
5017
  const isLowBalance = availableBalance < minDepositFloor;
5018
+ const insufficientFunds = availableBalance < amount;
4990
5019
  const exceedsLimit = remainingLimit != null && amount > remainingLimit && !isLowBalance;
4991
- const canDeposit = amount >= minDepositFloor && !exceedsLimit && !isLowBalance && !processing;
5020
+ const canDeposit = amount >= minDepositFloor && !exceedsLimit && !isLowBalance && !insufficientFunds && !processing;
4992
5021
  return /* @__PURE__ */ jsxRuntime.jsxs(
4993
5022
  ScreenLayout,
4994
5023
  {
4995
5024
  footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4996
- !accountPickerOpen && !tokenPickerOpen && (exceedsLimit && onIncreaseLimit ? /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onIncreaseLimit, loading: increasingLimit, children: "Increase limit" }) : /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: "Confirm" })),
5025
+ !accountPickerOpen && !tokenPickerOpen && (exceedsLimit && onIncreaseLimit ? /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onIncreaseLimit, loading: increasingLimit, children: "Increase limit" }) : /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: insufficientFunds ? "Insufficient Funds" : "Confirm" })),
4997
5026
  /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
4998
5027
  ] }),
4999
5028
  children: [
@@ -7311,13 +7340,15 @@ function StepRendererContent({
7311
7340
  return /* @__PURE__ */ jsxRuntime.jsx(
7312
7341
  PasskeyScreen,
7313
7342
  {
7314
- onCreatePasskey: handlers.onRegisterPasskey,
7343
+ onCreatePasskey: handlers.onVerifyPasskey,
7315
7344
  onBack: handlers.onLogout,
7316
7345
  onLogout: handlers.onLogout,
7317
- creating: state.verifyingPasskeyPopup,
7346
+ creating: state.registeringPasskey,
7318
7347
  error: state.error,
7319
- popupFallback: true,
7320
- onCreatePasskeyViaPopup: handlers.onVerifyPasskeyViaPopup
7348
+ onCreateNewPasskey: handlers.onCreateNewPasskey,
7349
+ onCreateNewPasskeyViaPopup: handlers.onCreateNewPasskeyViaPopup,
7350
+ createNewPopupFallback: state.passkeyPopupNeeded,
7351
+ creatingNewPasskey: state.registeringPasskey
7321
7352
  }
7322
7353
  );
7323
7354
  case "wallet-picker": {
@@ -7867,6 +7898,53 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds)
7867
7898
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
7868
7899
  }
7869
7900
  }, [user, knownCredentialIds, activateExistingCredential, completePasskeyRegistration, dispatch]);
7901
+ const handleVerifyPasskey = react.useCallback(async () => {
7902
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
7903
+ dispatch({ type: "SET_ERROR", error: null });
7904
+ try {
7905
+ const matched = await findDevicePasskey(knownCredentialIds);
7906
+ if (matched) {
7907
+ await activateExistingCredential(matched);
7908
+ } else {
7909
+ dispatch({
7910
+ type: "SET_ERROR",
7911
+ error: "No matching passkey found on this device. Please try again."
7912
+ });
7913
+ }
7914
+ } catch (err) {
7915
+ captureException(err);
7916
+ dispatch({
7917
+ type: "SET_ERROR",
7918
+ error: err instanceof Error ? err.message : "Passkey verification failed."
7919
+ });
7920
+ } finally {
7921
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
7922
+ }
7923
+ }, [knownCredentialIds, activateExistingCredential, dispatch]);
7924
+ const handleCreateNewPasskey = react.useCallback(async () => {
7925
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
7926
+ dispatch({ type: "SET_ERROR", error: null });
7927
+ try {
7928
+ const passkeyDisplayName = user?.email?.address ?? user?.google?.name ?? user?.id ?? "Blink User";
7929
+ const { credentialId, publicKey } = await createPasskeyCredential({
7930
+ userId: user?.id ?? "unknown",
7931
+ displayName: passkeyDisplayName
7932
+ });
7933
+ await completePasskeyRegistration(credentialId, publicKey);
7934
+ } catch (err) {
7935
+ if (err instanceof PasskeyIframeBlockedError) {
7936
+ dispatch({ type: "SET_PASSKEY_POPUP_NEEDED", needed: true });
7937
+ } else {
7938
+ captureException(err);
7939
+ dispatch({
7940
+ type: "SET_ERROR",
7941
+ error: err instanceof Error ? err.message : "Failed to register passkey"
7942
+ });
7943
+ }
7944
+ } finally {
7945
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
7946
+ }
7947
+ }, [user, completePasskeyRegistration, dispatch]);
7870
7948
  const handleCreatePasskeyViaPopup = react.useCallback(async () => {
7871
7949
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
7872
7950
  dispatch({ type: "SET_ERROR", error: null });
@@ -7913,6 +7991,35 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds)
7913
7991
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
7914
7992
  }
7915
7993
  }, [user, knownCredentialIds, getAccessToken, apiBaseUrl, activateExistingCredential, dispatch]);
7994
+ const handleCreateNewPasskeyViaPopup = react.useCallback(async () => {
7995
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
7996
+ dispatch({ type: "SET_ERROR", error: null });
7997
+ try {
7998
+ const token = await getAccessToken();
7999
+ const passkeyDisplayName = user?.email?.address ?? user?.google?.name ?? user?.id ?? "Blink User";
8000
+ const popupOptions = buildPasskeyPopupOptions({
8001
+ userId: user?.id ?? "unknown",
8002
+ displayName: passkeyDisplayName,
8003
+ authToken: token ?? void 0,
8004
+ apiBaseUrl
8005
+ });
8006
+ const { credentialId, publicKey } = await createPasskeyViaPopup(popupOptions);
8007
+ dispatch({ type: "PASSKEY_ACTIVATED", credentialId, publicKey });
8008
+ localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
8009
+ if (token) {
8010
+ reportPasskeyActivity(apiBaseUrl, token, credentialId).catch(() => {
8011
+ });
8012
+ }
8013
+ } catch (err) {
8014
+ captureException(err);
8015
+ dispatch({
8016
+ type: "SET_ERROR",
8017
+ error: err instanceof Error ? err.message : "Failed to register passkey"
8018
+ });
8019
+ } finally {
8020
+ dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
8021
+ }
8022
+ }, [user, getAccessToken, apiBaseUrl, dispatch]);
7916
8023
  const handleVerifyPasskeyViaPopup = react.useCallback(async () => {
7917
8024
  dispatch({ type: "SET_VERIFYING_PASSKEY", value: true });
7918
8025
  dispatch({ type: "SET_ERROR", error: null });
@@ -7955,7 +8062,10 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds)
7955
8062
  }, [knownCredentialIds, getAccessToken, apiBaseUrl, dispatch]);
7956
8063
  return {
7957
8064
  handleRegisterPasskey,
8065
+ handleVerifyPasskey,
8066
+ handleCreateNewPasskey,
7958
8067
  handleCreatePasskeyViaPopup,
8068
+ handleCreateNewPasskeyViaPopup,
7959
8069
  handleVerifyPasskeyViaPopup,
7960
8070
  checkingPasskeyRef
7961
8071
  };
@@ -9573,28 +9683,6 @@ function usePasskeyCheckEffect(deps) {
9573
9683
  await restoreState(activeCredentialId, token);
9574
9684
  return;
9575
9685
  }
9576
- if (cancelled) return;
9577
- const credentialIds = allPasskeys.map((p) => p.credentialId);
9578
- let matched = null;
9579
- if (isSafari() && isInCrossOriginIframe()) {
9580
- matched = await findDevicePasskeyViaPopup({
9581
- credentialIds,
9582
- rpId: resolvePasskeyRpId(),
9583
- authToken: token ?? void 0,
9584
- apiBaseUrl
9585
- });
9586
- } else {
9587
- matched = await findDevicePasskey(credentialIds);
9588
- }
9589
- if (cancelled) return;
9590
- if (matched) {
9591
- const publicKey = allPasskeys.find((p) => p.credentialId === matched)?.publicKey;
9592
- dispatch({ type: "PASSKEY_ACTIVATED", credentialId: matched, publicKey });
9593
- window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
9594
- reportPasskeyActivity(apiBaseUrl, token, matched).catch(() => {
9595
- });
9596
- await restoreState(matched, token);
9597
- }
9598
9686
  } catch (err) {
9599
9687
  dispatch({
9600
9688
  type: "PASSKEY_CONFIG_LOADED",
@@ -10657,7 +10745,7 @@ function BlinkPaymentInner({
10657
10745
  paymentReducer,
10658
10746
  {
10659
10747
  depositAmount,
10660
- passkeyPopupNeeded: isSafari() && isInCrossOriginIframe(),
10748
+ passkeyPopupNeeded: isSafari() && isInCrossOriginIframe() && !isDesktop,
10661
10749
  activeCredentialId: typeof window === "undefined" ? null : window.localStorage.getItem(ACTIVE_CREDENTIAL_STORAGE_KEY)
10662
10750
  },
10663
10751
  createInitialState
@@ -11013,7 +11101,10 @@ function BlinkPaymentInner({
11013
11101
  dispatch({ type: "BACK_TO_LOGIN" });
11014
11102
  },
11015
11103
  onRegisterPasskey: passkey.handleRegisterPasskey,
11104
+ onVerifyPasskey: passkey.handleVerifyPasskey,
11105
+ onCreateNewPasskey: passkey.handleCreateNewPasskey,
11016
11106
  onCreatePasskeyViaPopup: passkey.handleCreatePasskeyViaPopup,
11107
+ onCreateNewPasskeyViaPopup: passkey.handleCreateNewPasskeyViaPopup,
11017
11108
  onVerifyPasskeyViaPopup: passkey.handleVerifyPasskeyViaPopup,
11018
11109
  onPrepareProvider: provider.handlePrepareProvider,
11019
11110
  onSelectProvider: provider.handleSelectProvider,