@swype-org/react-sdk 0.1.121 → 0.1.124

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
@@ -811,10 +811,10 @@ function createPasskeyViaPopup(options) {
811
811
  if (result) {
812
812
  resolve(result);
813
813
  } else {
814
- reject(new Error("Passkey setup window was closed before completing."));
814
+ reject(new Error("Passkey window was closed before completing."));
815
815
  }
816
816
  }).catch(() => {
817
- reject(new Error("Passkey setup window was closed before completing."));
817
+ reject(new Error("Passkey window was closed before completing."));
818
818
  });
819
819
  }
820
820
  }, POPUP_CLOSED_GRACE_MS);
@@ -1436,6 +1436,22 @@ function useAuthorizationExecutor(options) {
1436
1436
  }),
1437
1437
  []
1438
1438
  );
1439
+ const [pendingOneTapSetup, setPendingOneTapSetup] = react.useState(null);
1440
+ const oneTapSetupResolverRef = react.useRef(null);
1441
+ const resolveOneTapSetup = react.useCallback(() => {
1442
+ if (oneTapSetupResolverRef.current) {
1443
+ oneTapSetupResolverRef.current();
1444
+ oneTapSetupResolverRef.current = null;
1445
+ setPendingOneTapSetup(null);
1446
+ }
1447
+ }, []);
1448
+ const waitForOneTapSetup = react.useCallback(
1449
+ (action) => new Promise((resolve) => {
1450
+ oneTapSetupResolverRef.current = resolve;
1451
+ setPendingOneTapSetup(action);
1452
+ }),
1453
+ []
1454
+ );
1439
1455
  const dispatchAction = react.useCallback(
1440
1456
  async (action) => {
1441
1457
  setCurrentAction(action);
@@ -1450,13 +1466,23 @@ function useAuthorizationExecutor(options) {
1450
1466
  return executeApprovePermit2(action, wagmiConfig2);
1451
1467
  case "DEPLOY_SMART_ACCOUNT":
1452
1468
  return actionSuccess(action, "Smart account deployment acknowledged.");
1453
- case "SIGN_PERMIT2":
1454
- return executeSignPermit2(action, wagmiConfig2, apiBaseUrl ?? "", sessionIdRef.current);
1469
+ case "SIGN_PERMIT2": {
1470
+ let resolvedAction = action;
1471
+ if (action.metadata?.awaitingLimit) {
1472
+ await waitForOneTapSetup(action);
1473
+ if (apiBaseUrl && sessionIdRef.current) {
1474
+ const session = await fetchAuthorizationSession(apiBaseUrl, sessionIdRef.current);
1475
+ const refreshed = session.actions.find((a) => a.id === action.id);
1476
+ if (refreshed) resolvedAction = refreshed;
1477
+ }
1478
+ }
1479
+ return executeSignPermit2(resolvedAction, wagmiConfig2, apiBaseUrl ?? "", sessionIdRef.current);
1480
+ }
1455
1481
  default:
1456
1482
  return actionError(action, `Unsupported action type: ${action.type}`);
1457
1483
  }
1458
1484
  },
1459
- [wagmiConfig2, connectors, connectAsync, switchChainAsync, apiBaseUrl, waitForSelection]
1485
+ [wagmiConfig2, connectors, connectAsync, switchChainAsync, apiBaseUrl, waitForSelection, waitForOneTapSetup]
1460
1486
  );
1461
1487
  const executeSessionById = react.useCallback(
1462
1488
  async (sessionId) => {
@@ -1527,6 +1553,8 @@ function useAuthorizationExecutor(options) {
1527
1553
  currentAction,
1528
1554
  pendingSelectSource,
1529
1555
  resolveSelectSource,
1556
+ pendingOneTapSetup,
1557
+ resolveOneTapSetup,
1530
1558
  executeSessionById
1531
1559
  };
1532
1560
  }
@@ -1740,6 +1768,9 @@ function resolvePostAuthStep(state) {
1740
1768
  return { step: "create-passkey", clearPersistedFlow: false };
1741
1769
  }
1742
1770
  if (state.persistedMobileFlow) {
1771
+ if (state.persistedMobileFlow.isReauthorization) {
1772
+ return { step: "open-wallet", clearPersistedFlow: false };
1773
+ }
1743
1774
  if (state.persistedMobileFlow.isSetup && hasActiveWallet(state.accounts)) {
1744
1775
  return { step: "deposit", clearPersistedFlow: true };
1745
1776
  }
@@ -3472,7 +3503,7 @@ var hintStyle = (color) => ({
3472
3503
  color,
3473
3504
  margin: "12px 0 0"
3474
3505
  });
3475
- function CreatePasskeyScreen({
3506
+ function PasskeyScreen({
3476
3507
  onCreatePasskey,
3477
3508
  onBack,
3478
3509
  creating,
@@ -3482,7 +3513,7 @@ function CreatePasskeyScreen({
3482
3513
  }) {
3483
3514
  const { tokens } = useSwypeConfig();
3484
3515
  const handleCreate = popupFallback && onCreatePasskeyViaPopup ? onCreatePasskeyViaPopup : onCreatePasskey;
3485
- const buttonLabel = popupFallback ? "Open passkey setup" : "Set up passkey";
3516
+ const buttonLabel = popupFallback ? "Open passkey window" : "Create or verify passkey";
3486
3517
  return /* @__PURE__ */ jsxRuntime.jsxs(
3487
3518
  ScreenLayout,
3488
3519
  {
@@ -3499,8 +3530,8 @@ function CreatePasskeyScreen({
3499
3530
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "15", cy: "10", r: "1", fill: tokens.accent }),
3500
3531
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 14c0 1.5 1.34 2.5 3 2.5s3-1 3-2.5", stroke: tokens.accent, strokeWidth: "1.2", strokeLinecap: "round" })
3501
3532
  ] }) }),
3502
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle3(tokens.text), children: "Set up your passkey" }),
3503
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle3(tokens.textSecondary), children: popupFallback ? "Your browser requires a separate window for passkey setup. Tap the button below to continue." : "Use Face ID to sign in instantly \u2014 no passwords, no codes." }),
3533
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle3(tokens.text), children: "Create or verify your passkey" }),
3534
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle3(tokens.textSecondary), children: popupFallback ? "Your browser requires a separate window to continue. Tap the button below to continue." : "Use Face ID to sign in instantly \u2014 no passwords, no codes." }),
3504
3535
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle2(tokens), children: error }),
3505
3536
  /* @__PURE__ */ jsxRuntime.jsx(InfoBanner, { children: "Your passkey is stored securely on your device. Swype never sees your biometric data." })
3506
3537
  ] })
@@ -5632,7 +5663,7 @@ function StepRenderer({
5632
5663
  }
5633
5664
  if (step === "create-passkey") {
5634
5665
  return /* @__PURE__ */ jsxRuntime.jsx(
5635
- CreatePasskeyScreen,
5666
+ PasskeyScreen,
5636
5667
  {
5637
5668
  onCreatePasskey: handlers.onRegisterPasskey,
5638
5669
  onBack: handlers.onLogout,
@@ -5645,7 +5676,7 @@ function StepRenderer({
5645
5676
  }
5646
5677
  if (step === "verify-passkey") {
5647
5678
  return /* @__PURE__ */ jsxRuntime.jsx(
5648
- CreatePasskeyScreen,
5679
+ PasskeyScreen,
5649
5680
  {
5650
5681
  onCreatePasskey: handlers.onRegisterPasskey,
5651
5682
  onBack: handlers.onLogout,
@@ -5970,6 +6001,8 @@ function SwypePaymentInner({
5970
6001
  const initializedSelectSourceActionRef = react.useRef(null);
5971
6002
  const preSelectSourceStepRef = react.useRef(null);
5972
6003
  const pendingTokenAuthRef = react.useRef(null);
6004
+ const reauthSessionIdRef = react.useRef(null);
6005
+ const reauthTokenRef = react.useRef(null);
5973
6006
  const checkingPasskeyRef = react.useRef(false);
5974
6007
  const onCompleteRef = react.useRef(onComplete);
5975
6008
  onCompleteRef.current = onComplete;
@@ -6263,7 +6296,7 @@ function SwypePaymentInner({
6263
6296
  return;
6264
6297
  }
6265
6298
  if (!state.activeCredentialId) {
6266
- dispatch({ type: "SET_ERROR", error: "Set up a passkey on this device before continuing." });
6299
+ dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
6267
6300
  dispatch({ type: "NAVIGATE", step: "create-passkey" });
6268
6301
  return;
6269
6302
  }
@@ -6344,7 +6377,7 @@ function SwypePaymentInner({
6344
6377
  return;
6345
6378
  }
6346
6379
  if (!state.activeCredentialId) {
6347
- dispatch({ type: "SET_ERROR", error: "Set up a passkey on this device before continuing." });
6380
+ dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
6348
6381
  dispatch({ type: "NAVIGATE", step: "create-passkey" });
6349
6382
  return;
6350
6383
  }
@@ -6372,12 +6405,15 @@ function SwypePaymentInner({
6372
6405
  handlingMobileReturnRef.current = false;
6373
6406
  mobileSetupFlowRef.current = true;
6374
6407
  setupAccountIdRef.current = state.selectedAccountId;
6408
+ reauthSessionIdRef.current = session.id;
6409
+ reauthTokenRef.current = null;
6375
6410
  persistMobileFlowState({
6376
6411
  accountId: state.selectedAccountId,
6377
6412
  sessionId: session.id,
6378
6413
  deeplinkUri: session.uri,
6379
6414
  providerId: matchedProvider?.id ?? null,
6380
- isSetup: true
6415
+ isSetup: true,
6416
+ isReauthorization: true
6381
6417
  });
6382
6418
  dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
6383
6419
  triggerDeeplink(session.uri);
@@ -6418,7 +6454,7 @@ function SwypePaymentInner({
6418
6454
  return;
6419
6455
  }
6420
6456
  if (!state.activeCredentialId) {
6421
- dispatch({ type: "SET_ERROR", error: "Set up a passkey on this device before continuing." });
6457
+ dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
6422
6458
  dispatch({ type: "NAVIGATE", step: "create-passkey" });
6423
6459
  return;
6424
6460
  }
@@ -6448,12 +6484,16 @@ function SwypePaymentInner({
6448
6484
  handlingMobileReturnRef.current = false;
6449
6485
  mobileSetupFlowRef.current = true;
6450
6486
  setupAccountIdRef.current = state.selectedAccountId;
6487
+ reauthSessionIdRef.current = session.id;
6488
+ reauthTokenRef.current = { walletId: _walletId, tokenSymbol };
6451
6489
  persistMobileFlowState({
6452
6490
  accountId: state.selectedAccountId,
6453
6491
  sessionId: session.id,
6454
6492
  deeplinkUri: session.uri,
6455
6493
  providerId: matchedProvider?.id ?? null,
6456
- isSetup: true
6494
+ isSetup: true,
6495
+ isReauthorization: true,
6496
+ reauthorizationToken: { walletId: _walletId, tokenSymbol }
6457
6497
  });
6458
6498
  dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
6459
6499
  triggerDeeplink(session.uri);
@@ -6515,7 +6555,7 @@ function SwypePaymentInner({
6515
6555
  const handleSelectProvider = react.useCallback(async (providerId) => {
6516
6556
  dispatch({ type: "SELECT_PROVIDER", providerId });
6517
6557
  if (!state.activeCredentialId) {
6518
- dispatch({ type: "SET_ERROR", error: "Set up a passkey on this device before continuing." });
6558
+ dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
6519
6559
  dispatch({ type: "NAVIGATE", step: "create-passkey" });
6520
6560
  return;
6521
6561
  }
@@ -6559,7 +6599,7 @@ function SwypePaymentInner({
6559
6599
  } else {
6560
6600
  await authExecutor.executeSessionById(session.id);
6561
6601
  await reloadAccounts();
6562
- dispatch({ type: "NAVIGATE", step: "setup" });
6602
+ dispatch({ type: "NAVIGATE", step: "deposit" });
6563
6603
  }
6564
6604
  } catch (err) {
6565
6605
  captureException(err);
@@ -6608,7 +6648,11 @@ function SwypePaymentInner({
6608
6648
  const token = await getAccessToken();
6609
6649
  if (!token) throw new Error("Not authenticated");
6610
6650
  await updateUserConfig(apiBaseUrl, token, { defaultAllowance: limit });
6611
- dispatch({ type: "NAVIGATE", step: "deposit" });
6651
+ if (authExecutor.pendingOneTapSetup) {
6652
+ authExecutor.resolveOneTapSetup();
6653
+ } else {
6654
+ dispatch({ type: "NAVIGATE", step: "deposit" });
6655
+ }
6612
6656
  } catch (err) {
6613
6657
  captureException(err);
6614
6658
  dispatch({
@@ -6616,7 +6660,7 @@ function SwypePaymentInner({
6616
6660
  error: err instanceof Error ? err.message : "Failed to save One-Tap limit"
6617
6661
  });
6618
6662
  }
6619
- }, [getAccessToken, apiBaseUrl]);
6663
+ }, [getAccessToken, apiBaseUrl, authExecutor]);
6620
6664
  const handleNewPayment = react.useCallback(() => {
6621
6665
  clearMobileFlowState();
6622
6666
  processingStartedAtRef.current = null;
@@ -6726,6 +6770,31 @@ function SwypePaymentInner({
6726
6770
  } catch {
6727
6771
  }
6728
6772
  }
6773
+ if (resolved.step === "open-wallet" && persisted && persisted.isReauthorization && persisted.sessionId) {
6774
+ try {
6775
+ const session = await fetchAuthorizationSession(apiBaseUrl, persisted.sessionId);
6776
+ if (cancelled) return;
6777
+ if (session.status === "AUTHORIZED") {
6778
+ clearMobileFlowState();
6779
+ dispatch({ type: "NAVIGATE", step: "deposit" });
6780
+ if (persisted.reauthorizationToken) {
6781
+ dispatch({ type: "SELECT_TOKEN", walletId: persisted.reauthorizationToken.walletId, tokenSymbol: persisted.reauthorizationToken.tokenSymbol });
6782
+ }
6783
+ return;
6784
+ }
6785
+ } catch {
6786
+ }
6787
+ reauthSessionIdRef.current = persisted.sessionId;
6788
+ reauthTokenRef.current = persisted.reauthorizationToken ?? null;
6789
+ mobileSetupFlowRef.current = true;
6790
+ setupAccountIdRef.current = persisted.accountId ?? null;
6791
+ dispatch({
6792
+ type: "ENTER_MOBILE_FLOW",
6793
+ deeplinkUri: persisted.deeplinkUri,
6794
+ providerId: persisted.providerId
6795
+ });
6796
+ return;
6797
+ }
6729
6798
  if (resolved.step === "open-wallet" && persisted && persisted.accountId && !persisted.transferId) {
6730
6799
  clearMobileFlowState();
6731
6800
  dispatch({ type: "NAVIGATE", step: "deposit" });
@@ -6995,9 +7064,36 @@ function SwypePaymentInner({
6995
7064
  if (!state.activeCredentialId || !setupAccountIdRef.current) return;
6996
7065
  const accountId = setupAccountIdRef.current;
6997
7066
  const credentialId = state.activeCredentialId;
7067
+ const isReauth = !!reauthSessionIdRef.current;
7068
+ const sessionId = reauthSessionIdRef.current;
7069
+ const tokenSelection = reauthTokenRef.current;
6998
7070
  let cancelled = false;
6999
7071
  const POLL_INTERVAL_MS = 3e3;
7000
- const poll = async () => {
7072
+ const pollReauthorization = async () => {
7073
+ try {
7074
+ if (!sessionId || cancelled) return;
7075
+ const session = await fetchAuthorizationSession(apiBaseUrl, sessionId);
7076
+ if (cancelled) return;
7077
+ if (session.status === "AUTHORIZED") {
7078
+ cancelled = true;
7079
+ mobileSetupFlowRef.current = false;
7080
+ setupAccountIdRef.current = null;
7081
+ reauthSessionIdRef.current = null;
7082
+ reauthTokenRef.current = null;
7083
+ clearMobileFlowState();
7084
+ try {
7085
+ await reloadAccounts();
7086
+ } catch {
7087
+ }
7088
+ dispatch({ type: "MOBILE_SETUP_COMPLETE" });
7089
+ if (tokenSelection) {
7090
+ dispatch({ type: "SELECT_TOKEN", walletId: tokenSelection.walletId, tokenSymbol: tokenSelection.tokenSymbol });
7091
+ }
7092
+ }
7093
+ } catch {
7094
+ }
7095
+ };
7096
+ const pollWalletActive = async () => {
7001
7097
  try {
7002
7098
  const token = await getAccessTokenRef.current();
7003
7099
  if (!token || cancelled) return;
@@ -7018,6 +7114,7 @@ function SwypePaymentInner({
7018
7114
  } catch {
7019
7115
  }
7020
7116
  };
7117
+ const poll = isReauth ? pollReauthorization : pollWalletActive;
7021
7118
  poll();
7022
7119
  const intervalId = window.setInterval(poll, POLL_INTERVAL_MS);
7023
7120
  const handleVisibility = () => {
@@ -7093,6 +7190,17 @@ function SwypePaymentInner({
7093
7190
  });
7094
7191
  }
7095
7192
  }, [pendingSelectSourceAction, authExecutor]);
7193
+ const pendingOneTapSetupAction = authExecutor.pendingOneTapSetup;
7194
+ const preOneTapSetupStepRef = react.useRef(null);
7195
+ react.useEffect(() => {
7196
+ if (pendingOneTapSetupAction && state.step === "setup-status") {
7197
+ preOneTapSetupStepRef.current = state.step;
7198
+ dispatch({ type: "NAVIGATE", step: "setup" });
7199
+ } else if (!pendingOneTapSetupAction && state.step === "setup" && preOneTapSetupStepRef.current) {
7200
+ dispatch({ type: "NAVIGATE", step: preOneTapSetupStepRef.current });
7201
+ preOneTapSetupStepRef.current = null;
7202
+ }
7203
+ }, [pendingOneTapSetupAction, state.step]);
7096
7204
  const handlers = react.useMemo(() => ({
7097
7205
  onSendLoginCode: handleSendLoginCode,
7098
7206
  onVerifyLoginCode: handleVerifyLoginCode,
@@ -7187,11 +7295,11 @@ function SwypePaymentInner({
7187
7295
  }
7188
7296
 
7189
7297
  exports.AdvancedSourceScreen = AdvancedSourceScreen;
7190
- exports.CreatePasskeyScreen = CreatePasskeyScreen;
7191
7298
  exports.IconCircle = IconCircle;
7192
7299
  exports.InfoBanner = InfoBanner;
7193
7300
  exports.OutlineButton = OutlineButton;
7194
7301
  exports.PasskeyIframeBlockedError = PasskeyIframeBlockedError;
7302
+ exports.PasskeyScreen = PasskeyScreen;
7195
7303
  exports.PoweredByFooter = PoweredByFooter;
7196
7304
  exports.PrimaryButton = PrimaryButton;
7197
7305
  exports.ScreenHeader = ScreenHeader;