@swype-org/react-sdk 0.1.241 → 0.1.256

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
@@ -1850,7 +1850,10 @@ function useTransferSigning(pollIntervalMs = 2e3, options) {
1850
1850
  // src/paymentHelpers.ts
1851
1851
  var ACTIVE_CREDENTIAL_STORAGE_KEY = "blink_active_credential_id";
1852
1852
  var MOBILE_FLOW_STORAGE_KEY = "blink_mobile_flow";
1853
- var MIN_SEND_AMOUNT_USD = 0.25;
1853
+ var DEFAULT_MIN_SEND_AMOUNT_USD = 0.25;
1854
+ function effectiveMinTransferAmountUsd(depositAmount) {
1855
+ return depositAmount != null ? depositAmount : DEFAULT_MIN_SEND_AMOUNT_USD;
1856
+ }
1854
1857
  function persistMobileFlowState(data) {
1855
1858
  try {
1856
1859
  sessionStorage.setItem(MOBILE_FLOW_STORAGE_KEY, JSON.stringify(data));
@@ -2011,7 +2014,8 @@ function isGuestPreauthCompletedTransferPinPhase(phase) {
2011
2014
  case "one-tap-setup":
2012
2015
  case "token-picker":
2013
2016
  case "login":
2014
- case "otp-verify":
2017
+ // otp-verify not pinned: after OTP, verificationTarget clears but phase can be stale until
2018
+ // resolvePhase runs; pinning would block passkey.
2015
2019
  case "passkey-create":
2016
2020
  case "passkey-verify":
2017
2021
  case "data-loading":
@@ -2024,68 +2028,142 @@ function isGuestPreauthCompletedTransferPinPhase(phase) {
2024
2028
  }
2025
2029
  function resolvePhase(state) {
2026
2030
  const p = state.phase;
2027
- if (state.transfer?.status === "COMPLETED" && state.guestPreauthorizing && isGuestPreauthCompletedTransferPinPhase(p)) {
2028
- return p;
2029
- }
2030
- if (state.transfer?.status === "COMPLETED") {
2031
- return { step: "completed", transfer: state.transfer };
2032
- }
2033
- if (state.transfer?.status === "FAILED") {
2034
- return { step: "failed", transfer: state.transfer, error: state.error ?? "Transfer failed." };
2035
- }
2036
- if (state.creatingTransfer || isTransferInFlight(state.transfer)) {
2037
- return { step: "processing", transfer: state.transfer };
2038
- }
2039
- 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")) {
2040
- return p;
2031
+ const transferCompleted = state.transfer?.status === "COMPLETED";
2032
+ const needsPasskeyBootstrap = state.privyAuthenticated && !state.activeCredentialId;
2033
+ const guestPreauthPin = transferCompleted && state.guestPreauthorizing && !state.verificationTarget && isGuestPreauthCompletedTransferPinPhase(p);
2034
+ const guestPostPayLogin = transferCompleted && state.isGuestFlow && state.guestPreauthSessionId != null && !state.guestPreauthorizing && !state.verificationTarget && !state.privyAuthenticated;
2035
+ const pinSubflow = !state.loginRequested && (p.step === "token-picker" || p.step === "one-tap-setup" || p.step === "select-source" || p.step === "confirm-sign" || p.step === "guest-token-picker");
2036
+ const guestTokenPicker = state.isGuestFlow && state.selectedProviderId != null && !state.transfer && !state.guestPreauthAccountId;
2037
+ const walletPickerSwitch = p.step === "wallet-picker" && p.reason === "switch" && !state.creatingTransfer && !(state.mobileFlow && state.deeplinkUri);
2038
+ const passkeyBlock = state.passkeyConfigLoaded && !state.activeCredentialId;
2039
+ const passkeyVerify = passkeyBlock && state.knownCredentialIds.length > 0 && state.passkeyPopupNeeded;
2040
+ const c1 = state.guestPreauthSetupCompletePending && state.privyReady && state.privyAuthenticated;
2041
+ const c2 = !c1 && guestPreauthPin;
2042
+ const c3 = !c1 && !c2 && guestPostPayLogin;
2043
+ const c4 = !c1 && !c2 && !c3 && transferCompleted && !state.verificationTarget && !needsPasskeyBootstrap;
2044
+ const c5 = !c1 && !c2 && !c3 && !c4 && state.transfer?.status === "FAILED";
2045
+ const c6 = !c1 && !c2 && !c3 && !c4 && !c5 && (state.creatingTransfer || isTransferInFlight(state.transfer));
2046
+ const c7 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && pinSubflow;
2047
+ const c8 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && state.mobileFlow && state.deeplinkUri != null;
2048
+ const c9 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && p.step === "wallet-setup" && p.mobile == null && state.guestPreauthorizing;
2049
+ const c10 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && guestTokenPicker;
2050
+ const c11 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && walletPickerSwitch;
2051
+ const c12 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && !c11 && !state.privyReady;
2052
+ const c13 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && !c11 && !c12 && state.privyAuthenticated && !state.activeCredentialId && !state.passkeyConfigLoaded;
2053
+ const c14 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && !c11 && !c12 && !c13 && state.verificationTarget != null && !state.privyAuthenticated;
2054
+ const c15 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && !c11 && !c12 && !c13 && !c14 && state.loginRequested;
2055
+ const c16 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && !c11 && !c12 && !c13 && !c14 && !c15 && passkeyVerify;
2056
+ const c17 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && !c11 && !c12 && !c13 && !c14 && !c15 && !c16 && passkeyBlock;
2057
+ const c18 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && !c11 && !c12 && !c13 && !c14 && !c15 && !c16 && !c17 && state.loadingData && state.activeCredentialId != null && hasActiveWallet(state.accounts);
2058
+ const c19 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && !c11 && !c12 && !c13 && !c14 && !c15 && !c16 && !c17 && !c18 && state.activeCredentialId != null && !hasActiveWallet(state.accounts) && !state.mobileFlow;
2059
+ const c20 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && !c11 && !c12 && !c13 && !c14 && !c15 && !c16 && !c17 && !c18 && !c19 && state.activeCredentialId != null && hasActiveWallet(state.accounts) && !state.loadingData;
2060
+ const c21 = !c1 && !c2 && !c3 && !c4 && !c5 && !c6 && !c7 && !c8 && !c9 && !c10 && !c11 && !c12 && !c13 && !c14 && !c15 && !c16 && !c17 && !c18 && !c19 && !c20 && state.isGuestFlow;
2061
+ const flags = [
2062
+ c1,
2063
+ c2,
2064
+ c3,
2065
+ c4,
2066
+ c5,
2067
+ c6,
2068
+ c7,
2069
+ c8,
2070
+ c9,
2071
+ c10,
2072
+ c11,
2073
+ c12,
2074
+ c13,
2075
+ c14,
2076
+ c15,
2077
+ c16,
2078
+ c17,
2079
+ c18,
2080
+ c19,
2081
+ c20,
2082
+ c21
2083
+ ];
2084
+ const matchCount = flags.filter(Boolean).length;
2085
+ if (matchCount > 1) {
2086
+ console.error("resolvePhase: multiple exclusive branches matched", {
2087
+ flags: {
2088
+ c1,
2089
+ c2,
2090
+ c3,
2091
+ c4,
2092
+ c5,
2093
+ c6,
2094
+ c7,
2095
+ c8,
2096
+ c9,
2097
+ c10,
2098
+ c11,
2099
+ c12,
2100
+ c13,
2101
+ c14,
2102
+ c15,
2103
+ c16,
2104
+ c17,
2105
+ c18,
2106
+ c19,
2107
+ c20,
2108
+ c21
2109
+ }
2110
+ });
2041
2111
  }
2042
- if (state.mobileFlow && state.deeplinkUri) {
2043
- return {
2112
+ let resolved;
2113
+ if (c1) {
2114
+ resolved = { step: "guest-setup-complete" };
2115
+ } else if (c2) {
2116
+ resolved = p;
2117
+ } else if (c3) {
2118
+ resolved = { step: "login" };
2119
+ } else if (c4) {
2120
+ resolved = { step: "completed", transfer: state.transfer };
2121
+ } else if (c5) {
2122
+ resolved = {
2123
+ step: "failed",
2124
+ transfer: state.transfer,
2125
+ error: state.error ?? "Transfer failed."
2126
+ };
2127
+ } else if (c6) {
2128
+ resolved = { step: "processing", transfer: state.transfer };
2129
+ } else if (c7) {
2130
+ resolved = p;
2131
+ } else if (c8) {
2132
+ resolved = {
2044
2133
  step: "wallet-setup",
2045
2134
  mobile: { deeplinkUri: state.deeplinkUri, providerId: state.selectedProviderId },
2046
2135
  accountId: null
2047
2136
  };
2137
+ } else if (c9) {
2138
+ resolved = p;
2139
+ } else if (c10) {
2140
+ resolved = { step: "guest-token-picker" };
2141
+ } else if (c11) {
2142
+ resolved = p;
2143
+ } else if (c12) {
2144
+ resolved = { step: "initializing" };
2145
+ } else if (c13) {
2146
+ resolved = { step: "initializing" };
2147
+ } else if (c14) {
2148
+ resolved = { step: "otp-verify", target: state.verificationTarget };
2149
+ } else if (c15) {
2150
+ resolved = { step: "login" };
2151
+ } else if (c16) {
2152
+ resolved = { step: "passkey-verify" };
2153
+ } else if (c17) {
2154
+ resolved = { step: "passkey-create", popupFallback: state.passkeyPopupNeeded };
2155
+ } else if (c18) {
2156
+ resolved = { step: "data-loading" };
2157
+ } else if (c19) {
2158
+ resolved = { step: "wallet-picker", reason: "link" };
2159
+ } else if (c20) {
2160
+ resolved = { step: "deposit" };
2161
+ } else if (c21) {
2162
+ resolved = { step: "wallet-picker", reason: "guest-entry" };
2163
+ } else {
2164
+ resolved = { step: "wallet-picker", reason: "entry" };
2048
2165
  }
2049
- if (p.step === "wallet-setup" && p.mobile == null) {
2050
- return p;
2051
- }
2052
- if (state.isGuestFlow && state.selectedProviderId != null && !state.transfer) {
2053
- return { step: "guest-token-picker" };
2054
- }
2055
- if (p.step === "wallet-picker" && !state.creatingTransfer && !(state.mobileFlow && state.deeplinkUri)) {
2056
- return p;
2057
- }
2058
- if (!state.privyReady) {
2059
- return { step: "initializing" };
2060
- }
2061
- if (state.privyAuthenticated && !state.activeCredentialId && !state.passkeyConfigLoaded) {
2062
- return { step: "initializing" };
2063
- }
2064
- if (state.verificationTarget) {
2065
- return { step: "otp-verify", target: state.verificationTarget };
2066
- }
2067
- if (state.loginRequested) {
2068
- return { step: "login" };
2069
- }
2070
- if (state.passkeyConfigLoaded && !state.activeCredentialId) {
2071
- if (state.knownCredentialIds.length > 0 && state.passkeyPopupNeeded) {
2072
- return { step: "passkey-verify" };
2073
- }
2074
- return { step: "passkey-create", popupFallback: state.passkeyPopupNeeded };
2075
- }
2076
- if (state.loadingData && state.activeCredentialId && hasActiveWallet(state.accounts)) {
2077
- return { step: "data-loading" };
2078
- }
2079
- if (state.activeCredentialId && !hasActiveWallet(state.accounts) && !state.mobileFlow) {
2080
- return { step: "wallet-picker", reason: "link" };
2081
- }
2082
- if (state.activeCredentialId && hasActiveWallet(state.accounts) && !state.loadingData) {
2083
- return { step: "deposit" };
2084
- }
2085
- if (state.isGuestFlow) {
2086
- return { step: "wallet-picker", reason: "guest-entry" };
2087
- }
2088
- return { step: "wallet-picker", reason: "entry" };
2166
+ return resolved;
2089
2167
  }
2090
2168
 
2091
2169
  // src/paymentReducer.ts
@@ -2133,13 +2211,26 @@ function createInitialState(config) {
2133
2211
  activePublicKey: null,
2134
2212
  loginRequested: false,
2135
2213
  guestPreauthorizing: false,
2214
+ guestPreauthSetupCompletePending: false,
2136
2215
  privyReady: false,
2137
2216
  privyAuthenticated: false
2138
2217
  };
2139
2218
  }
2140
2219
  function paymentReducer(state, action) {
2141
2220
  const next = applyAction(state, action);
2142
- return { ...next, phase: resolvePhase(next) };
2221
+ const phase = resolvePhase(next);
2222
+ if (action.type === "CODE_SENT") {
2223
+ console.debug("[Swype SDK] login code sent", {
2224
+ resolvedPhase: phase.step,
2225
+ verificationTargetKind: action.target.kind,
2226
+ guestPreauthorizing: next.guestPreauthorizing,
2227
+ transferStatus: next.transfer?.status ?? null,
2228
+ isGuestFlow: next.isGuestFlow,
2229
+ hasGuestPreauthSessionId: next.guestPreauthSessionId != null,
2230
+ loginRequested: next.loginRequested
2231
+ });
2232
+ }
2233
+ return { ...next, phase };
2143
2234
  }
2144
2235
  function applyAction(state, action) {
2145
2236
  switch (action.type) {
@@ -2400,13 +2491,20 @@ function applyAction(state, action) {
2400
2491
  case "ACCOUNT_OWNER_SET":
2401
2492
  return {
2402
2493
  ...state,
2494
+ transfer: null,
2403
2495
  guestPreauthAccountId: null,
2404
2496
  guestPreauthSessionId: null,
2405
2497
  activePublicKey: null,
2406
2498
  error: null,
2407
2499
  guestPreauthorizing: false,
2408
- phase: { step: "one-tap-setup", action: null }
2500
+ isGuestFlow: false,
2501
+ selectedProviderId: null,
2502
+ guestTransferId: null,
2503
+ guestSessionToken: null,
2504
+ guestPreauthSetupCompletePending: true
2409
2505
  };
2506
+ case "GUEST_PREAUTH_SETUP_COMPLETE_DISMISSED":
2507
+ return { ...state, guestPreauthSetupCompletePending: false };
2410
2508
  // ── User intent & error ──────────────────────────────────────
2411
2509
  case "SET_USER_INTENT":
2412
2510
  return { ...state, phase: action.intent };
@@ -2441,7 +2539,8 @@ function applyAction(state, action) {
2441
2539
  activePublicKey: null,
2442
2540
  loginRequested: false,
2443
2541
  oneTapLimitSavedDuringSetup: false,
2444
- guestPreauthorizing: false
2542
+ guestPreauthorizing: false,
2543
+ guestPreauthSetupCompletePending: false
2445
2544
  };
2446
2545
  case "LOGOUT":
2447
2546
  return {
@@ -2457,7 +2556,10 @@ function applyAction(state, action) {
2457
2556
  return {
2458
2557
  ...state,
2459
2558
  privyReady: action.ready,
2460
- privyAuthenticated: action.authenticated
2559
+ privyAuthenticated: action.authenticated,
2560
+ // OTP complete: Privy is source of truth; clear so resolvePhase can leave otp-verify
2561
+ // and guest-preauth pin rules cannot re-pin a stale otp-verify phase.
2562
+ ...action.authenticated ? { verificationTarget: null, loginRequested: false } : {}
2461
2563
  };
2462
2564
  case "SYNC_AMOUNT":
2463
2565
  return { ...state, amount: action.amount };
@@ -2523,7 +2625,10 @@ function screenForPhase(phase) {
2523
2625
  case "wallet-picker":
2524
2626
  return "wallet-picker";
2525
2627
  case "wallet-setup":
2526
- return phase.mobile ? "open-wallet" : "setup-status";
2628
+ if (phase.mobile || phase.guestDesktopExtension) {
2629
+ return "open-wallet";
2630
+ }
2631
+ return "setup-status";
2527
2632
  case "select-source":
2528
2633
  return phase.isDesktop ? "setup" : "select-source";
2529
2634
  case "one-tap-setup":
@@ -2541,6 +2646,8 @@ function screenForPhase(phase) {
2541
2646
  case "completed":
2542
2647
  case "failed":
2543
2648
  return "success";
2649
+ case "guest-setup-complete":
2650
+ return "guest-setup-complete";
2544
2651
  }
2545
2652
  }
2546
2653
  var MUTED = "#7fa4b0";
@@ -4322,13 +4429,13 @@ var waitHintStyle = (color) => ({
4322
4429
  color,
4323
4430
  margin: 0
4324
4431
  });
4325
- var MIN_DEPOSIT = 0.25;
4326
4432
  function DepositScreen({
4327
4433
  merchantName,
4328
4434
  availableBalance,
4329
4435
  remainingLimit,
4330
4436
  tokenCount,
4331
4437
  initialAmount,
4438
+ minDepositFloor,
4332
4439
  processing,
4333
4440
  error,
4334
4441
  onDeposit,
@@ -4364,9 +4471,9 @@ function DepositScreen({
4364
4471
  const selectedProviderName = selectedAccount?.name ?? "Wallet";
4365
4472
  const selectedProviderLogo = KNOWN_LOGOS[selectedProviderName.toLowerCase()];
4366
4473
  const totalAccountBalance = selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : availableBalance;
4367
- const isLowBalance = availableBalance < MIN_DEPOSIT;
4474
+ const isLowBalance = availableBalance < minDepositFloor;
4368
4475
  const exceedsLimit = remainingLimit != null && amount > remainingLimit && !isLowBalance;
4369
- const canDeposit = amount >= MIN_DEPOSIT && !exceedsLimit && !isLowBalance && !processing;
4476
+ const canDeposit = amount >= minDepositFloor && !exceedsLimit && !isLowBalance && !processing;
4370
4477
  return /* @__PURE__ */ jsxRuntime.jsxs(
4371
4478
  ScreenLayout,
4372
4479
  {
@@ -4501,7 +4608,7 @@ function DepositScreen({
4501
4608
  "Your wallet balance is $",
4502
4609
  availableBalance.toFixed(2),
4503
4610
  " \u2014 you need at least $",
4504
- MIN_DEPOSIT.toFixed(2),
4611
+ minDepositFloor.toFixed(2),
4505
4612
  " to deposit via One-Tap."
4506
4613
  ] }),
4507
4614
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle5(tokens), children: error })
@@ -6010,6 +6117,60 @@ var emptyStyle = (color) => ({
6010
6117
  padding: "32px 0",
6011
6118
  lineHeight: 1.5
6012
6119
  });
6120
+ function GuestPreauthSetupCompleteScreen({
6121
+ onClose,
6122
+ onLogout
6123
+ }) {
6124
+ const { tokens } = useBlinkConfig();
6125
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6126
+ ScreenLayout,
6127
+ {
6128
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6129
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onClose, children: "Close" }),
6130
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
6131
+ ] }),
6132
+ children: [
6133
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onLogout }),
6134
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle9, children: [
6135
+ /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "success", size: 64, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
6136
+ "path",
6137
+ {
6138
+ d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
6139
+ fill: tokens.success
6140
+ }
6141
+ ) }) }),
6142
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle12(tokens.text), children: "Setup complete" }),
6143
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle10(tokens.textSecondary), children: "Your account is linked and ready. You can close this window or make another deposit." })
6144
+ ] })
6145
+ ]
6146
+ }
6147
+ );
6148
+ }
6149
+ var contentStyle9 = {
6150
+ display: "flex",
6151
+ flexDirection: "column",
6152
+ alignItems: "center",
6153
+ textAlign: "center",
6154
+ gap: 12,
6155
+ paddingTop: 8
6156
+ };
6157
+ function headingStyle12(color) {
6158
+ return {
6159
+ margin: 0,
6160
+ fontSize: 22,
6161
+ fontWeight: 600,
6162
+ color
6163
+ };
6164
+ }
6165
+ function subtitleStyle10(color) {
6166
+ return {
6167
+ margin: 0,
6168
+ fontSize: 15,
6169
+ lineHeight: 1.45,
6170
+ color,
6171
+ maxWidth: 320
6172
+ };
6173
+ }
6013
6174
  var LINK_SCREENS = /* @__PURE__ */ new Set([
6014
6175
  "create-passkey",
6015
6176
  "verify-passkey",
@@ -6024,6 +6185,7 @@ var DEPOSIT_SCREENS = /* @__PURE__ */ new Set([
6024
6185
  "processing",
6025
6186
  "success"
6026
6187
  ]);
6188
+ var DEFAULT_MIN_DEPOSIT_USD = 0.25;
6027
6189
  function getFlowPhase(screen, phase) {
6028
6190
  if (LINK_SCREENS.has(screen)) return "link";
6029
6191
  if (DEPOSIT_SCREENS.has(screen)) return "deposit";
@@ -6232,6 +6394,7 @@ function StepRendererContent({
6232
6394
  }
6233
6395
  case "deposit": {
6234
6396
  const parsedAmt = depositAmount != null ? depositAmount : 5;
6397
+ const minDepositFloor = depositAmount != null ? depositAmount : DEFAULT_MIN_DEPOSIT_USD;
6235
6398
  return /* @__PURE__ */ jsxRuntime.jsx(
6236
6399
  DepositScreen,
6237
6400
  {
@@ -6255,7 +6418,8 @@ function StepRendererContent({
6255
6418
  onAddProvider: () => handlers.onSetPhase({ step: "wallet-picker", reason: "switch" }),
6256
6419
  onSelectToken: handlers.onSelectToken,
6257
6420
  selectedSourceLabel,
6258
- selectedTokenSymbol: selectedSource?.token.symbol
6421
+ selectedTokenSymbol: selectedSource?.token.symbol,
6422
+ minDepositFloor
6259
6423
  }
6260
6424
  );
6261
6425
  }
@@ -6311,6 +6475,14 @@ function StepRendererContent({
6311
6475
  onBack: handlers.onGuestBackFromTokenPicker
6312
6476
  }
6313
6477
  );
6478
+ case "guest-setup-complete":
6479
+ return /* @__PURE__ */ jsxRuntime.jsx(
6480
+ GuestPreauthSetupCompleteScreen,
6481
+ {
6482
+ onClose: handlers.onGuestSetupCompleteClose,
6483
+ onLogout: handlers.onLogout
6484
+ }
6485
+ );
6314
6486
  case "processing": {
6315
6487
  const polledStatus = pollingTransfer?.status;
6316
6488
  const transferPhase = state.creatingTransfer ? "creating" : polledStatus === "SENDING" || polledStatus === "SENT" ? "sent" : "verifying";
@@ -6404,7 +6576,7 @@ var PaymentErrorBoundary = class extends react.Component {
6404
6576
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 8v5", stroke: "#ef4444", strokeWidth: "1.5", strokeLinecap: "round" }),
6405
6577
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "16", r: "0.75", fill: "#ef4444" })
6406
6578
  ] }) }),
6407
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle12, children: "Something went wrong" }),
6579
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle13, children: "Something went wrong" }),
6408
6580
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: messageStyle, children: "An unexpected error occurred. Please try again." }),
6409
6581
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: this.handleReset, style: buttonStyle3, children: "Try again" })
6410
6582
  ] });
@@ -6424,7 +6596,7 @@ var containerStyle9 = {
6424
6596
  var iconStyle3 = {
6425
6597
  marginBottom: 20
6426
6598
  };
6427
- var headingStyle12 = {
6599
+ var headingStyle13 = {
6428
6600
  fontSize: "1.25rem",
6429
6601
  fontWeight: 700,
6430
6602
  color: "#1a1a1a",
@@ -6773,8 +6945,9 @@ function useTransferHandlers(deps) {
6773
6945
  dispatch({ type: "ACCOUNTS_RELOADED", accounts: accts, providers: prov, defaults });
6774
6946
  }, [getAccessToken, activeCredentialId, selectedAccountId, apiBaseUrl, depositAmount, dispatch]);
6775
6947
  const handlePay = react.useCallback(async (payAmount, sourceOverrides) => {
6776
- if (isNaN(payAmount) || payAmount < MIN_SEND_AMOUNT_USD) {
6777
- dispatch({ type: "SET_ERROR", error: `Minimum amount is $${MIN_SEND_AMOUNT_USD.toFixed(2)}.` });
6948
+ const minUsd = effectiveMinTransferAmountUsd(depositAmount);
6949
+ if (isNaN(payAmount) || payAmount < minUsd) {
6950
+ dispatch({ type: "SET_ERROR", error: `Minimum amount is $${minUsd.toFixed(2)}.` });
6778
6951
  return;
6779
6952
  }
6780
6953
  if (!sourceOverrides?.sourceId && !sourceId) {
@@ -6853,7 +7026,8 @@ function useTransferHandlers(deps) {
6853
7026
  onComplete,
6854
7027
  idempotencyKey,
6855
7028
  merchantAuthorization,
6856
- dispatch
7029
+ dispatch,
7030
+ depositAmount
6857
7031
  ]);
6858
7032
  const handleConfirmSign = react.useCallback(async () => {
6859
7033
  const t = transfer ?? polling.transfer;
@@ -6923,18 +7097,31 @@ function useSourceSelectionHandlers(dispatch, authExecutor, options) {
6923
7097
  [selectSourceChoices, selectSourceRecommended]
6924
7098
  );
6925
7099
  const handleConfirmSelectSource = react.useCallback(() => {
7100
+ const guestPostPayPreauth = !!options?.guestPreauthSessionId && !!options?.isGuestFlow || !!options?.guestPreauthorizing && !!options?.isDesktop;
7101
+ if (guestPostPayPreauth) {
7102
+ dispatch({ type: "REQUEST_LOGIN" });
7103
+ if (options?.guestPreauthAccountId != null) {
7104
+ const intent = {
7105
+ step: "wallet-setup",
7106
+ mobile: null,
7107
+ accountId: options.guestPreauthAccountId,
7108
+ guestDesktopExtension: true
7109
+ };
7110
+ dispatch({ type: "SET_USER_INTENT", intent });
7111
+ }
7112
+ }
6926
7113
  authExecutor.resolveSelectSource({
6927
7114
  chainName: selectSourceChainName,
6928
7115
  tokenSymbol: selectSourceTokenSymbol
6929
7116
  });
6930
- if (options?.guestPreauthorizing && options?.isDesktop) {
6931
- dispatch({ type: "REQUEST_LOGIN" });
6932
- }
6933
7117
  }, [
6934
7118
  authExecutor,
6935
7119
  dispatch,
7120
+ options?.guestPreauthSessionId,
7121
+ options?.guestPreauthAccountId,
6936
7122
  options?.guestPreauthorizing,
6937
7123
  options?.isDesktop,
7124
+ options?.isGuestFlow,
6938
7125
  selectSourceChainName,
6939
7126
  selectSourceTokenSymbol
6940
7127
  ]);
@@ -7792,7 +7979,9 @@ function useOneTapSetupHandlers(deps) {
7792
7979
  authExecutor,
7793
7980
  selectSourceChainName,
7794
7981
  selectSourceTokenSymbol,
7795
- authorizationSessionIdForGuest
7982
+ authorizationSessionIdForGuest,
7983
+ guestPostPayPreauth,
7984
+ guestPreauthAccountId
7796
7985
  } = deps;
7797
7986
  const [savingOneTapLimit, setSavingOneTapLimit] = react.useState(false);
7798
7987
  const handleSetupOneTap = react.useCallback(async (limit) => {
@@ -7809,6 +7998,19 @@ function useOneTapSetupHandlers(deps) {
7809
7998
  if (!token) throw new Error("Not authenticated");
7810
7999
  await updateUserConfig(apiBaseUrl, token, { defaultAllowance: limit });
7811
8000
  }
8001
+ const willResolveSession = authExecutor.pendingSelectSource != null || authExecutor.pendingOneTapSetup != null;
8002
+ if (guestPostPayPreauth && willResolveSession) {
8003
+ dispatch({ type: "REQUEST_LOGIN" });
8004
+ if (guestPreauthAccountId != null) {
8005
+ const intent = {
8006
+ step: "wallet-setup",
8007
+ mobile: null,
8008
+ accountId: guestPreauthAccountId,
8009
+ guestDesktopExtension: true
8010
+ };
8011
+ dispatch({ type: "SET_USER_INTENT", intent });
8012
+ }
8013
+ }
7812
8014
  if (authExecutor.pendingSelectSource) {
7813
8015
  const action = authExecutor.pendingSelectSource;
7814
8016
  const recommended = action.metadata?.recommended;
@@ -7828,7 +8030,9 @@ function useOneTapSetupHandlers(deps) {
7828
8030
  } else if (authExecutor.pendingOneTapSetup) {
7829
8031
  authExecutor.resolveOneTapSetup();
7830
8032
  }
7831
- dispatch({ type: "SET_USER_INTENT", intent: { step: "deposit" } });
8033
+ if (!guestPostPayPreauth || !willResolveSession) {
8034
+ dispatch({ type: "SET_USER_INTENT", intent: { step: "deposit" } });
8035
+ }
7832
8036
  } catch (err) {
7833
8037
  captureException(err);
7834
8038
  dispatch({
@@ -7845,7 +8049,9 @@ function useOneTapSetupHandlers(deps) {
7845
8049
  dispatch,
7846
8050
  selectSourceChainName,
7847
8051
  selectSourceTokenSymbol,
7848
- authorizationSessionIdForGuest
8052
+ authorizationSessionIdForGuest,
8053
+ guestPostPayPreauth,
8054
+ guestPreauthAccountId
7849
8055
  ]);
7850
8056
  return {
7851
8057
  handleSetupOneTap,
@@ -8311,6 +8517,10 @@ function useProcessingEffect(deps) {
8311
8517
  } = deps;
8312
8518
  react.useEffect(() => {
8313
8519
  if (!polling.transfer) return;
8520
+ if (state.loginRequested || state.verificationTarget) return;
8521
+ if (!state.transfer && (polling.transfer.status === "COMPLETED" || polling.transfer.status === "FAILED")) {
8522
+ return;
8523
+ }
8314
8524
  if (polling.transfer.status === "COMPLETED") {
8315
8525
  clearMobileFlowState();
8316
8526
  dispatch({ type: "TRANSFER_COMPLETED", transfer: polling.transfer });
@@ -8320,7 +8530,15 @@ function useProcessingEffect(deps) {
8320
8530
  clearMobileFlowState();
8321
8531
  dispatch({ type: "TRANSFER_FAILED", transfer: polling.transfer, error: "Transfer failed." });
8322
8532
  }
8323
- }, [polling.transfer, onComplete, dispatch, reloadAccounts]);
8533
+ }, [
8534
+ polling.transfer,
8535
+ state.transfer,
8536
+ state.loginRequested,
8537
+ state.verificationTarget,
8538
+ onComplete,
8539
+ dispatch,
8540
+ reloadAccounts
8541
+ ]);
8324
8542
  react.useEffect(() => {
8325
8543
  const isProcessing = state.creatingTransfer || state.transfer != null && ["CREATED", "SENDING", "SENT"].includes(state.transfer.status);
8326
8544
  if (!isProcessing) {
@@ -8571,6 +8789,42 @@ function useOneTapAutoResolveEffect(deps) {
8571
8789
  }
8572
8790
  }, [pendingOneTapSetupAction, reloadAccounts, oneTapLimitSavedDuringSetup]);
8573
8791
  }
8792
+
8793
+ // src/guestPreauthClaimWait.ts
8794
+ var GUEST_PREAUTH_SESSION_POLL_INTERVAL_MS = 1e3;
8795
+ var GUEST_PREAUTH_SESSION_POLL_TIMEOUT_MS = 12e4;
8796
+ async function waitForGuestPreauthAuthorizationSession(apiBaseUrl, sessionId, fetchSession, signal, options) {
8797
+ const intervalMs = GUEST_PREAUTH_SESSION_POLL_INTERVAL_MS;
8798
+ const timeoutMs = GUEST_PREAUTH_SESSION_POLL_TIMEOUT_MS;
8799
+ const deadline = Date.now() + timeoutMs;
8800
+ const sleepAbortable = (ms) => new Promise((resolve, reject) => {
8801
+ if (signal.aborted) {
8802
+ reject(new DOMException("Aborted", "AbortError"));
8803
+ return;
8804
+ }
8805
+ const t = setTimeout(() => {
8806
+ signal.removeEventListener("abort", onAbort);
8807
+ resolve();
8808
+ }, ms);
8809
+ const onAbort = () => {
8810
+ clearTimeout(t);
8811
+ signal.removeEventListener("abort", onAbort);
8812
+ reject(new DOMException("Aborted", "AbortError"));
8813
+ };
8814
+ signal.addEventListener("abort", onAbort, { once: true });
8815
+ });
8816
+ while (Date.now() < deadline) {
8817
+ if (signal.aborted) {
8818
+ throw new DOMException("Aborted", "AbortError");
8819
+ }
8820
+ const session = await fetchSession(apiBaseUrl, sessionId);
8821
+ if (session.status === "AUTHORIZED") return;
8822
+ await sleepAbortable(intervalMs);
8823
+ }
8824
+ throw new Error("Authorization session did not become AUTHORIZED in time.");
8825
+ }
8826
+
8827
+ // src/hooks/useGuestPreauthEffect.ts
8574
8828
  function useGuestPreauthEffect(deps) {
8575
8829
  const { state, dispatch, authenticated, apiBaseUrl, reloadAccounts } = deps;
8576
8830
  const { getAccessToken } = reactAuth.usePrivy();
@@ -8584,12 +8838,25 @@ function useGuestPreauthEffect(deps) {
8584
8838
  if (!authenticated) return;
8585
8839
  if (!state.guestSessionToken) return;
8586
8840
  if (settingOwnerRef.current) return;
8587
- const hasActive = state.accounts.some((a) => a.wallets.some((w) => w.status === "ACTIVE"));
8588
- if (!hasActive) return;
8589
8841
  settingOwnerRef.current = true;
8842
+ const abort = new AbortController();
8590
8843
  let cancelled = false;
8591
8844
  const setOwner = async () => {
8592
8845
  try {
8846
+ if (state.guestPreauthSessionId) {
8847
+ try {
8848
+ await waitForGuestPreauthAuthorizationSession(
8849
+ apiBaseUrl,
8850
+ state.guestPreauthSessionId,
8851
+ fetchAuthorizationSession,
8852
+ abort.signal
8853
+ );
8854
+ } catch (waitErr) {
8855
+ if (waitErr instanceof DOMException && waitErr.name === "AbortError") return;
8856
+ throw waitErr;
8857
+ }
8858
+ }
8859
+ if (cancelled) return;
8593
8860
  const token = await getAccessTokenRef.current();
8594
8861
  if (!token || cancelled) return;
8595
8862
  await setAccountOwner(apiBaseUrl, token, state.guestPreauthAccountId, state.guestSessionToken, {
@@ -8614,16 +8881,17 @@ function useGuestPreauthEffect(deps) {
8614
8881
  settingOwnerRef.current = false;
8615
8882
  }
8616
8883
  };
8617
- setOwner();
8884
+ void setOwner();
8618
8885
  return () => {
8619
8886
  cancelled = true;
8887
+ abort.abort();
8620
8888
  };
8621
8889
  }, [
8622
8890
  state.guestPreauthAccountId,
8891
+ state.guestPreauthSessionId,
8623
8892
  state.activeCredentialId,
8624
8893
  state.activePublicKey,
8625
8894
  state.guestSessionToken,
8626
- state.accounts,
8627
8895
  authenticated,
8628
8896
  apiBaseUrl,
8629
8897
  dispatch,
@@ -8694,24 +8962,23 @@ function useGuestPreauthPhaseSyncEffect(deps) {
8694
8962
  ]);
8695
8963
  }
8696
8964
  function useGuestPreauthWalletSetupEffect(deps) {
8697
- const { state, dispatch, authExecutor, isDesktop, privyAuthenticated } = deps;
8965
+ const { state, dispatch, authExecutor, isDesktop } = deps;
8698
8966
  react.useEffect(() => {
8699
8967
  if (!isDesktop || !state.guestPreauthorizing || !state.guestPreauthSessionId) return;
8968
+ if (!state.guestPreauthAccountId) return;
8700
8969
  if (!authExecutor.executing || authExecutor.pendingSelectSource) return;
8701
- if (!privyAuthenticated || !state.activeCredentialId) return;
8702
8970
  if (state.verificationTarget) return;
8703
- if (state.loginRequested) return;
8704
8971
  const p = state.phase;
8705
- if (p.step === "wallet-setup" && p.mobile == null) {
8706
- const id = state.guestPreauthAccountId;
8707
- if (id != null && p.accountId === id) return;
8972
+ if (p.step === "wallet-setup" && p.mobile == null && p.guestDesktopExtension && p.accountId === state.guestPreauthAccountId) {
8973
+ return;
8708
8974
  }
8709
8975
  dispatch({
8710
8976
  type: "SET_USER_INTENT",
8711
8977
  intent: {
8712
8978
  step: "wallet-setup",
8713
8979
  mobile: null,
8714
- accountId: state.guestPreauthAccountId
8980
+ accountId: state.guestPreauthAccountId,
8981
+ guestDesktopExtension: true
8715
8982
  }
8716
8983
  });
8717
8984
  }, [
@@ -8719,14 +8986,11 @@ function useGuestPreauthWalletSetupEffect(deps) {
8719
8986
  state.guestPreauthorizing,
8720
8987
  state.guestPreauthSessionId,
8721
8988
  state.guestPreauthAccountId,
8722
- state.activeCredentialId,
8723
8989
  state.verificationTarget,
8724
- state.loginRequested,
8725
8990
  state.phase,
8726
8991
  authExecutor.executing,
8727
8992
  authExecutor.pendingSelectSource,
8728
- dispatch,
8729
- privyAuthenticated
8993
+ dispatch
8730
8994
  ]);
8731
8995
  }
8732
8996
  function BlinkPayment(props) {
@@ -8814,6 +9078,9 @@ function BlinkPaymentInner({
8814
9078
  onComplete
8815
9079
  );
8816
9080
  const sourceSelection = useSourceSelectionHandlers(dispatch, authExecutor, {
9081
+ guestPreauthSessionId: state.guestPreauthSessionId,
9082
+ guestPreauthAccountId: state.guestPreauthAccountId,
9083
+ isGuestFlow: state.isGuestFlow,
8817
9084
  guestPreauthorizing: state.guestPreauthorizing,
8818
9085
  isDesktop
8819
9086
  });
@@ -8844,6 +9111,15 @@ function BlinkPaymentInner({
8844
9111
  guestSessionToken: state.guestSessionToken,
8845
9112
  selectedProviderId: state.selectedProviderId
8846
9113
  });
9114
+ const guestPostPayPreauth = react.useMemo(
9115
+ () => !!state.guestPreauthSessionId && state.isGuestFlow || state.guestPreauthorizing && isDesktop,
9116
+ [
9117
+ state.guestPreauthSessionId,
9118
+ state.isGuestFlow,
9119
+ state.guestPreauthorizing,
9120
+ isDesktop
9121
+ ]
9122
+ );
8847
9123
  const oneTapSetup = useOneTapSetupHandlers({
8848
9124
  dispatch,
8849
9125
  getAccessToken,
@@ -8851,7 +9127,9 @@ function BlinkPaymentInner({
8851
9127
  authExecutor,
8852
9128
  selectSourceChainName: sourceSelection.selectSourceChainName,
8853
9129
  selectSourceTokenSymbol: sourceSelection.selectSourceTokenSymbol,
8854
- authorizationSessionIdForGuest: state.guestPreauthSessionId
9130
+ authorizationSessionIdForGuest: state.guestPreauthSessionId,
9131
+ guestPostPayPreauth,
9132
+ guestPreauthAccountId: state.guestPreauthAccountId
8855
9133
  });
8856
9134
  const guestTransfer = useGuestTransferHandlers({
8857
9135
  dispatch,
@@ -8993,8 +9271,7 @@ function BlinkPaymentInner({
8993
9271
  state,
8994
9272
  dispatch,
8995
9273
  authExecutor,
8996
- isDesktop,
8997
- privyAuthenticated: authenticated
9274
+ isDesktop
8998
9275
  });
8999
9276
  const handlers = react.useMemo(() => ({
9000
9277
  onSendLoginCode: auth.handleSendLoginCode,
@@ -9034,7 +9311,11 @@ function BlinkPaymentInner({
9034
9311
  onSelectGuestToken: guestTransfer.handleSelectGuestToken,
9035
9312
  onGuestBackFromTokenPicker: guestTransfer.handleGuestBackFromTokenPicker,
9036
9313
  onLogin: () => dispatch({ type: "REQUEST_LOGIN" }),
9037
- onPreauthorize: provider.handlePreauthorize
9314
+ onPreauthorize: provider.handlePreauthorize,
9315
+ onGuestSetupCompleteClose: () => {
9316
+ dispatch({ type: "GUEST_PREAUTH_SETUP_COMPLETE_DISMISSED" });
9317
+ onDismiss?.();
9318
+ }
9038
9319
  }), [
9039
9320
  auth,
9040
9321
  passkey,
@@ -9045,7 +9326,9 @@ function BlinkPaymentInner({
9045
9326
  oneTapSetup,
9046
9327
  guestTransfer,
9047
9328
  handleLogout,
9048
- handleNewPayment
9329
+ handleNewPayment,
9330
+ onDismiss,
9331
+ dispatch
9049
9332
  ]);
9050
9333
  return /* @__PURE__ */ jsxRuntime.jsx(
9051
9334
  StepRenderer,