@swype-org/react-sdk 0.1.225 → 0.1.227

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
@@ -1935,9 +1935,7 @@ function deriveSourceTypeAndId(state) {
1935
1935
  return { sourceType: "accountId", sourceId: "" };
1936
1936
  }
1937
1937
  function createInitialState(config) {
1938
- const isReturningUser = config.activeCredentialId != null;
1939
1938
  return {
1940
- step: isReturningUser ? "login" : "wallet-picker",
1941
1939
  error: null,
1942
1940
  providers: [],
1943
1941
  accounts: [],
@@ -1953,6 +1951,7 @@ function createInitialState(config) {
1953
1951
  registeringPasskey: false,
1954
1952
  verifyingPasskeyPopup: false,
1955
1953
  passkeyPopupNeeded: config.passkeyPopupNeeded,
1954
+ passkeyConfigLoaded: false,
1956
1955
  activeCredentialId: config.activeCredentialId,
1957
1956
  knownCredentialIds: [],
1958
1957
  verificationTarget: null,
@@ -1960,12 +1959,12 @@ function createInitialState(config) {
1960
1959
  mobileFlow: false,
1961
1960
  deeplinkUri: null,
1962
1961
  increasingLimit: false,
1963
- previousStep: null,
1964
1962
  isGuestFlow: false,
1965
1963
  guestTransferId: null,
1966
1964
  guestSessionToken: null,
1967
1965
  guestPreauthAccountId: null,
1968
- activePublicKey: null
1966
+ activePublicKey: null,
1967
+ userIntent: null
1969
1968
  };
1970
1969
  }
1971
1970
  function paymentReducer(state, action) {
@@ -1975,21 +1974,20 @@ function paymentReducer(state, action) {
1975
1974
  return {
1976
1975
  ...state,
1977
1976
  verificationTarget: action.target,
1978
- error: null,
1979
- step: "otp-verify"
1977
+ error: null
1980
1978
  };
1981
1979
  case "BACK_TO_LOGIN":
1982
1980
  return {
1983
1981
  ...state,
1984
1982
  verificationTarget: null,
1985
- error: null,
1986
- step: "login"
1983
+ error: null
1987
1984
  };
1988
1985
  // ── Passkey ──────────────────────────────────────────────────
1989
1986
  case "PASSKEY_CONFIG_LOADED":
1990
1987
  return {
1991
1988
  ...state,
1992
1989
  knownCredentialIds: action.knownIds,
1990
+ passkeyConfigLoaded: true,
1993
1991
  oneTapLimit: action.oneTapLimit ?? state.oneTapLimit
1994
1992
  };
1995
1993
  case "PASSKEY_ACTIVATED":
@@ -2023,9 +2021,6 @@ function paymentReducer(state, action) {
2023
2021
  next.mobileFlow = false;
2024
2022
  next.deeplinkUri = null;
2025
2023
  }
2026
- if (action.resolvedStep !== void 0) {
2027
- next.step = action.resolvedStep;
2028
- }
2029
2024
  return next;
2030
2025
  }
2031
2026
  case "DATA_LOAD_END":
@@ -2049,7 +2044,8 @@ function paymentReducer(state, action) {
2049
2044
  selectedProviderId: action.providerId,
2050
2045
  selectedAccountId: null,
2051
2046
  selectedWalletId: null,
2052
- selectedTokenSymbol: null
2047
+ selectedTokenSymbol: null,
2048
+ userIntent: null
2053
2049
  };
2054
2050
  case "SELECT_ACCOUNT":
2055
2051
  return {
@@ -2057,24 +2053,24 @@ function paymentReducer(state, action) {
2057
2053
  selectedAccountId: action.accountId,
2058
2054
  selectedWalletId: action.walletId,
2059
2055
  selectedTokenSymbol: null,
2060
- step: "deposit"
2056
+ userIntent: null
2061
2057
  };
2062
2058
  case "SELECT_TOKEN":
2063
2059
  return {
2064
2060
  ...state,
2065
2061
  selectedWalletId: action.walletId,
2066
2062
  selectedTokenSymbol: action.tokenSymbol,
2067
- step: "deposit"
2063
+ userIntent: null
2068
2064
  };
2069
2065
  // ── Transfer lifecycle ───────────────────────────────────────
2070
2066
  case "PAY_STARTED":
2071
2067
  return {
2072
2068
  ...state,
2073
- step: action.isSetupRedirect ? "open-wallet" : "processing",
2074
2069
  error: null,
2075
2070
  creatingTransfer: true,
2076
2071
  deeplinkUri: null,
2077
- mobileFlow: false
2072
+ mobileFlow: false,
2073
+ userIntent: null
2078
2074
  };
2079
2075
  case "PAY_ENDED":
2080
2076
  return { ...state, creatingTransfer: false };
@@ -2082,7 +2078,7 @@ function paymentReducer(state, action) {
2082
2078
  return {
2083
2079
  ...state,
2084
2080
  error: action.error,
2085
- step: action.fallbackStep
2081
+ creatingTransfer: false
2086
2082
  };
2087
2083
  case "TRANSFER_CREATED":
2088
2084
  return { ...state, transfer: action.transfer };
@@ -2092,7 +2088,6 @@ function paymentReducer(state, action) {
2092
2088
  return {
2093
2089
  ...state,
2094
2090
  transfer: action.transfer,
2095
- step: "success",
2096
2091
  mobileFlow: false,
2097
2092
  deeplinkUri: null
2098
2093
  };
@@ -2101,17 +2096,20 @@ function paymentReducer(state, action) {
2101
2096
  ...state,
2102
2097
  transfer: action.transfer,
2103
2098
  error: action.error,
2104
- step: "success",
2105
2099
  mobileFlow: false,
2106
2100
  deeplinkUri: null
2107
2101
  };
2108
2102
  case "PROCESSING_TIMEOUT":
2109
- return { ...state, error: action.error, step: "deposit" };
2103
+ return {
2104
+ ...state,
2105
+ error: action.error,
2106
+ transfer: null,
2107
+ creatingTransfer: false
2108
+ };
2110
2109
  case "CONFIRM_SIGN_SUCCESS":
2111
2110
  return {
2112
2111
  ...state,
2113
2112
  transfer: action.transfer,
2114
- step: "processing",
2115
2113
  mobileFlow: false,
2116
2114
  deeplinkUri: null
2117
2115
  };
@@ -2120,8 +2118,7 @@ function paymentReducer(state, action) {
2120
2118
  return {
2121
2119
  ...state,
2122
2120
  mobileFlow: true,
2123
- deeplinkUri: action.deeplinkUri,
2124
- step: "open-wallet"
2121
+ deeplinkUri: action.deeplinkUri
2125
2122
  };
2126
2123
  case "MOBILE_SETUP_COMPLETE":
2127
2124
  return {
@@ -2129,8 +2126,7 @@ function paymentReducer(state, action) {
2129
2126
  transfer: action.transfer ?? state.transfer,
2130
2127
  error: null,
2131
2128
  mobileFlow: false,
2132
- deeplinkUri: null,
2133
- step: "deposit"
2129
+ deeplinkUri: null
2134
2130
  };
2135
2131
  case "MOBILE_SIGN_READY":
2136
2132
  return {
@@ -2138,8 +2134,7 @@ function paymentReducer(state, action) {
2138
2134
  transfer: action.transfer,
2139
2135
  error: null,
2140
2136
  mobileFlow: false,
2141
- deeplinkUri: null,
2142
- step: "confirm-sign"
2137
+ deeplinkUri: null
2143
2138
  };
2144
2139
  case "CLEAR_MOBILE_STATE":
2145
2140
  return { ...state, mobileFlow: false, deeplinkUri: null };
@@ -2149,8 +2144,7 @@ function paymentReducer(state, action) {
2149
2144
  mobileFlow: true,
2150
2145
  deeplinkUri: action.deeplinkUri,
2151
2146
  selectedProviderId: action.providerId ?? state.selectedProviderId,
2152
- error: action.error ?? null,
2153
- step: "open-wallet"
2147
+ error: action.error ?? null
2154
2148
  };
2155
2149
  case "MOBILE_RESUME_SUCCESS":
2156
2150
  return {
@@ -2158,8 +2152,7 @@ function paymentReducer(state, action) {
2158
2152
  transfer: action.transfer,
2159
2153
  error: null,
2160
2154
  mobileFlow: false,
2161
- deeplinkUri: null,
2162
- step: "success"
2155
+ deeplinkUri: null
2163
2156
  };
2164
2157
  case "MOBILE_RESUME_FAILED":
2165
2158
  return {
@@ -2167,8 +2160,7 @@ function paymentReducer(state, action) {
2167
2160
  transfer: action.transfer,
2168
2161
  error: "Transfer failed.",
2169
2162
  mobileFlow: false,
2170
- deeplinkUri: null,
2171
- step: "success"
2163
+ deeplinkUri: null
2172
2164
  };
2173
2165
  case "MOBILE_RESUME_PROCESSING":
2174
2166
  return {
@@ -2176,8 +2168,7 @@ function paymentReducer(state, action) {
2176
2168
  transfer: action.transfer,
2177
2169
  error: null,
2178
2170
  mobileFlow: false,
2179
- deeplinkUri: null,
2180
- step: "processing"
2171
+ deeplinkUri: null
2181
2172
  };
2182
2173
  // ── Increase limit ───────────────────────────────────────────
2183
2174
  case "SET_INCREASING_LIMIT":
@@ -2199,14 +2190,12 @@ function paymentReducer(state, action) {
2199
2190
  guestSessionToken: action.guestSessionToken,
2200
2191
  selectedAccountId: null,
2201
2192
  selectedWalletId: null,
2202
- selectedTokenSymbol: null,
2203
- step: "token-picker"
2193
+ selectedTokenSymbol: null
2204
2194
  };
2205
2195
  case "GUEST_TRANSFER_COMPLETED":
2206
2196
  return {
2207
2197
  ...state,
2208
2198
  transfer: action.transfer,
2209
- step: "success",
2210
2199
  mobileFlow: false,
2211
2200
  deeplinkUri: null,
2212
2201
  isGuestFlow: true,
@@ -2215,27 +2204,24 @@ function paymentReducer(state, action) {
2215
2204
  case "GUEST_PREAUTH_DETECTED":
2216
2205
  return {
2217
2206
  ...state,
2218
- guestPreauthAccountId: action.accountId,
2219
- step: "login"
2207
+ guestPreauthAccountId: action.accountId
2220
2208
  };
2221
2209
  case "ACCOUNT_OWNER_SET":
2222
2210
  return {
2223
2211
  ...state,
2224
2212
  guestPreauthAccountId: null,
2225
2213
  activePublicKey: null,
2226
- step: "deposit",
2227
2214
  error: null
2228
2215
  };
2229
- // ── Navigation & error ───────────────────────────────────────
2230
- case "NAVIGATE":
2231
- return { ...state, step: action.step, previousStep: state.step, error: null };
2216
+ // ── User intent & error ──────────────────────────────────────
2217
+ case "SET_USER_INTENT":
2218
+ return { ...state, userIntent: action.intent };
2232
2219
  case "SET_ERROR":
2233
2220
  return { ...state, error: action.error };
2234
2221
  // ── Lifecycle ────────────────────────────────────────────────
2235
2222
  case "NEW_PAYMENT":
2236
2223
  return {
2237
2224
  ...state,
2238
- step: state.isGuestFlow ? "wallet-picker" : "deposit",
2239
2225
  transfer: null,
2240
2226
  error: null,
2241
2227
  amount: action.depositAmount != null ? action.depositAmount.toString() : "",
@@ -2248,7 +2234,8 @@ function paymentReducer(state, action) {
2248
2234
  guestTransferId: null,
2249
2235
  guestSessionToken: null,
2250
2236
  guestPreauthAccountId: null,
2251
- activePublicKey: null
2237
+ activePublicKey: null,
2238
+ userIntent: null
2252
2239
  };
2253
2240
  case "LOGOUT":
2254
2241
  return {
@@ -2316,6 +2303,87 @@ function isMobileUserAgent(userAgent) {
2316
2303
  function shouldUseWalletConnector(options) {
2317
2304
  return options.useWalletConnector ?? !isMobileUserAgent(options.userAgent);
2318
2305
  }
2306
+
2307
+ // src/resolveScreen.ts
2308
+ function hasActiveWallet(accounts) {
2309
+ return accounts.some((a) => a.wallets.some((w) => w.status === "ACTIVE"));
2310
+ }
2311
+ function isTransferTerminal(transfer) {
2312
+ return transfer?.status === "COMPLETED" || transfer?.status === "FAILED";
2313
+ }
2314
+ function isTransferInFlight(transfer) {
2315
+ if (!transfer) return false;
2316
+ return ["CREATED", "SENDING", "SENT"].includes(transfer.status);
2317
+ }
2318
+ function isSetupTransfer(transfer) {
2319
+ if (!transfer) return false;
2320
+ return transfer.sources?.some(
2321
+ (s) => s.wallets && Array.isArray(s.wallets) && s.wallets.length === 0
2322
+ ) ?? false;
2323
+ }
2324
+ function resolveScreen(state) {
2325
+ if (!state.privyReady) {
2326
+ return "loading";
2327
+ }
2328
+ if (state.authenticated && !state.activeCredentialId && !state.passkeyConfigLoaded) {
2329
+ return "loading";
2330
+ }
2331
+ if (!state.authenticated && !state.verificationTarget && !state.isGuestFlow && (state.isReturningUser || state.guestPreauthRedirect)) {
2332
+ return "login";
2333
+ }
2334
+ if (!state.authenticated && state.verificationTarget != null) {
2335
+ return "otp-verify";
2336
+ }
2337
+ if (state.authenticated && !state.activeCredentialId && state.passkeyConfigLoaded && (state.knownCredentialIds.length === 0 || !state.passkeyPopupNeeded)) {
2338
+ return "create-passkey";
2339
+ }
2340
+ if (state.authenticated && !state.activeCredentialId && state.passkeyConfigLoaded && state.knownCredentialIds.length > 0 && state.passkeyPopupNeeded) {
2341
+ return "verify-passkey";
2342
+ }
2343
+ if (isTransferTerminal(state.transfer)) {
2344
+ return "success";
2345
+ }
2346
+ if (state.creatingTransfer || state.transfer != null && isTransferInFlight(state.transfer)) {
2347
+ return "processing";
2348
+ }
2349
+ if (state.transfer?.status === "AUTHORIZED" && !state.isDesktop && !isSetupTransfer(state.transfer)) {
2350
+ return "confirm-sign";
2351
+ }
2352
+ if (state.pendingSelectSource != null) {
2353
+ return state.isDesktop ? "setup" : "select-source";
2354
+ }
2355
+ if (state.pendingOneTapSetup != null && !state.oneTapLimitAlreadySaved) {
2356
+ return "setup";
2357
+ }
2358
+ if (state.mobileFlow || state.inlineAuthorizationExecuting) {
2359
+ return state.isDesktop ? "setup-status" : "open-wallet";
2360
+ }
2361
+ if (state.isGuestFlow && state.selectedProviderId != null && !state.transfer && !state.guestSettingSender) {
2362
+ return "guest-token-picker";
2363
+ }
2364
+ if (state.activeCredentialId && !hasActiveWallet(state.accounts) && !state.mobileFlow || !state.authenticated && !state.isReturningUser && !state.isGuestFlow) {
2365
+ return "wallet-picker";
2366
+ }
2367
+ if (state.loadingData && state.activeCredentialId != null && hasActiveWallet(state.accounts)) {
2368
+ return "loading";
2369
+ }
2370
+ if (state.userIntent === "pick-token" && state.selectedAccount != null) {
2371
+ return "token-picker";
2372
+ }
2373
+ if (state.userIntent === "configure-one-tap") {
2374
+ return "setup";
2375
+ }
2376
+ if (state.userIntent === "switch-wallet") {
2377
+ return "wallet-picker";
2378
+ }
2379
+ if (state.activeCredentialId != null && hasActiveWallet(state.accounts) && !state.loadingData) {
2380
+ return "deposit";
2381
+ }
2382
+ if (state.isGuestFlow) {
2383
+ return "wallet-picker";
2384
+ }
2385
+ return "wallet-picker";
2386
+ }
2319
2387
  var MUTED = "#7fa4b0";
2320
2388
  var LOGO_SIZE = 48;
2321
2389
  function BlinkLoadingScreen() {
@@ -5783,7 +5851,7 @@ var emptyStyle = (color) => ({
5783
5851
  padding: "32px 0",
5784
5852
  lineHeight: 1.5
5785
5853
  });
5786
- var LINK_STEPS = /* @__PURE__ */ new Set([
5854
+ var LINK_SCREENS = /* @__PURE__ */ new Set([
5787
5855
  "create-passkey",
5788
5856
  "verify-passkey",
5789
5857
  "wallet-picker",
@@ -5792,27 +5860,56 @@ var LINK_STEPS = /* @__PURE__ */ new Set([
5792
5860
  "setup",
5793
5861
  "confirm-sign"
5794
5862
  ]);
5795
- var DEPOSIT_STEPS = /* @__PURE__ */ new Set([
5863
+ var DEPOSIT_SCREENS = /* @__PURE__ */ new Set([
5796
5864
  "deposit",
5797
- "low-balance",
5798
5865
  "processing",
5799
5866
  "success"
5800
5867
  ]);
5801
- function getFlowPhase(step, previousStep) {
5802
- if (LINK_STEPS.has(step)) return "link";
5803
- if (DEPOSIT_STEPS.has(step)) return "deposit";
5804
- if (step === "token-picker" || step === "select-source") {
5805
- return previousStep === "setup" ? "link" : "deposit";
5868
+ function getFlowPhase(screen, userIntent) {
5869
+ if (LINK_SCREENS.has(screen)) return "link";
5870
+ if (DEPOSIT_SCREENS.has(screen)) return "deposit";
5871
+ if (screen === "token-picker" || screen === "select-source" || screen === "guest-token-picker") {
5872
+ return userIntent === "configure-one-tap" ? "link" : "deposit";
5806
5873
  }
5807
5874
  return null;
5808
5875
  }
5809
5876
  function StepRenderer(props) {
5810
- const phase = getFlowPhase(props.state.step, props.state.previousStep);
5811
- return /* @__PURE__ */ jsxRuntime.jsx(FlowPhaseProvider, { phase, children: /* @__PURE__ */ jsxRuntime.jsx(StepRendererContent, { ...props }) });
5877
+ const isDesktop = shouldUseWalletConnector({
5878
+ userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
5879
+ });
5880
+ const isReturningUser = props.state.activeCredentialId != null || typeof window !== "undefined" && window.localStorage.getItem("blink_active_credential") != null;
5881
+ const screenState = {
5882
+ privyReady: props.ready,
5883
+ authenticated: props.authenticated,
5884
+ verificationTarget: props.state.verificationTarget,
5885
+ activeCredentialId: props.state.activeCredentialId,
5886
+ knownCredentialIds: props.state.knownCredentialIds,
5887
+ passkeyConfigLoaded: props.state.passkeyConfigLoaded,
5888
+ passkeyPopupNeeded: props.state.passkeyPopupNeeded,
5889
+ accounts: props.state.accounts,
5890
+ isGuestFlow: props.state.isGuestFlow,
5891
+ selectedProviderId: props.state.selectedProviderId,
5892
+ mobileFlow: props.state.mobileFlow,
5893
+ inlineAuthorizationExecuting: props.inlineAuthorizationExecuting,
5894
+ creatingTransfer: props.state.creatingTransfer,
5895
+ transfer: props.state.transfer,
5896
+ pendingSelectSource: props.pendingSelectSource,
5897
+ pendingOneTapSetup: props.pendingOneTapSetup,
5898
+ oneTapLimitAlreadySaved: props.oneTapLimitAlreadySaved,
5899
+ loadingData: props.state.loadingData,
5900
+ isDesktop,
5901
+ isReturningUser,
5902
+ guestPreauthRedirect: props.state.guestPreauthAccountId != null,
5903
+ userIntent: props.state.userIntent,
5904
+ selectedAccount: props.selectedAccount,
5905
+ guestSettingSender: props.guestSettingSender
5906
+ };
5907
+ const screen = resolveScreen(screenState);
5908
+ const phase = getFlowPhase(screen, props.state.userIntent);
5909
+ return /* @__PURE__ */ jsxRuntime.jsx(FlowPhaseProvider, { phase, children: /* @__PURE__ */ jsxRuntime.jsx(StepRendererContent, { ...props, screen, isDesktop }) });
5812
5910
  }
5813
5911
  function StepRendererContent({
5814
5912
  state,
5815
- ready,
5816
5913
  authenticated,
5817
5914
  activeOtpStatus,
5818
5915
  pollingTransfer,
@@ -5842,204 +5939,204 @@ function StepRendererContent({
5842
5939
  onBack,
5843
5940
  onDismiss,
5844
5941
  depositAmount,
5845
- handlers
5942
+ handlers,
5943
+ screen,
5944
+ isDesktop
5846
5945
  }) {
5847
- const { step } = state;
5848
5946
  const selectedWallet = selectedAccount?.wallets.find((w) => w.id === state.selectedWalletId);
5849
5947
  const selectedSourceLabel = selectedSource && selectedWallet ? `${selectedSource.token.symbol} on ${selectedWallet.chain.name}` : void 0;
5850
- if (!ready) {
5851
- return /* @__PURE__ */ jsxRuntime.jsx(BlinkLoadingScreen, {});
5852
- }
5853
- if (step === "login") {
5854
- if (authenticated) {
5948
+ switch (screen) {
5949
+ case "loading":
5855
5950
  return /* @__PURE__ */ jsxRuntime.jsx(BlinkLoadingScreen, {});
5951
+ case "login":
5952
+ return /* @__PURE__ */ jsxRuntime.jsx(
5953
+ LoginScreen,
5954
+ {
5955
+ authInput,
5956
+ onAuthInputChange: handlers.onSetAuthInput,
5957
+ onSubmit: handlers.onSendLoginCode,
5958
+ sending: activeOtpStatus === "sending-code",
5959
+ error: state.error,
5960
+ onBack,
5961
+ merchantInitials: merchantName ? merchantName.slice(0, 2).toUpperCase() : void 0
5962
+ }
5963
+ );
5964
+ case "otp-verify":
5965
+ return /* @__PURE__ */ jsxRuntime.jsx(
5966
+ OtpVerifyScreen,
5967
+ {
5968
+ maskedIdentifier: state.verificationTarget ? maskAuthIdentifier(state.verificationTarget) : "",
5969
+ otpCode,
5970
+ onOtpChange: (code) => {
5971
+ handlers.onSetOtpCode(code);
5972
+ },
5973
+ onVerify: handlers.onVerifyLoginCode,
5974
+ onResend: handlers.onResendLoginCode,
5975
+ onBack: handlers.onBackFromOtp,
5976
+ verifying: activeOtpStatus === "submitting-code" || authenticated,
5977
+ error: state.error
5978
+ }
5979
+ );
5980
+ case "create-passkey":
5981
+ return /* @__PURE__ */ jsxRuntime.jsx(
5982
+ PasskeyScreen,
5983
+ {
5984
+ onCreatePasskey: handlers.onRegisterPasskey,
5985
+ onBack: handlers.onLogout,
5986
+ onLogout: handlers.onLogout,
5987
+ creating: state.registeringPasskey,
5988
+ error: state.error,
5989
+ popupFallback: state.passkeyPopupNeeded,
5990
+ onCreatePasskeyViaPopup: handlers.onCreatePasskeyViaPopup
5991
+ }
5992
+ );
5993
+ case "verify-passkey":
5994
+ return /* @__PURE__ */ jsxRuntime.jsx(
5995
+ PasskeyScreen,
5996
+ {
5997
+ onCreatePasskey: handlers.onRegisterPasskey,
5998
+ onBack: handlers.onLogout,
5999
+ onLogout: handlers.onLogout,
6000
+ creating: state.verifyingPasskeyPopup,
6001
+ error: state.error,
6002
+ popupFallback: true,
6003
+ onCreatePasskeyViaPopup: handlers.onVerifyPasskeyViaPopup
6004
+ }
6005
+ );
6006
+ case "wallet-picker": {
6007
+ const isEntryPoint = !state.isGuestFlow && !authenticated;
6008
+ return /* @__PURE__ */ jsxRuntime.jsx(
6009
+ WalletPickerScreen,
6010
+ {
6011
+ providers: state.providers,
6012
+ pendingConnections,
6013
+ loading: state.creatingTransfer,
6014
+ useDeeplink: !isDesktop,
6015
+ onPrepareProvider: handlers.onPrepareProvider,
6016
+ onSelectProvider: handlers.onSelectProvider,
6017
+ onContinueConnection: handlers.onContinueConnection,
6018
+ onBack: isEntryPoint ? onBack : () => handlers.onSetUserIntent(null),
6019
+ onLogout: authenticated ? handlers.onLogout : void 0,
6020
+ onLogin: handlers.onLogin,
6021
+ showLoginOption: isEntryPoint
6022
+ }
6023
+ );
5856
6024
  }
5857
- return /* @__PURE__ */ jsxRuntime.jsx(
5858
- LoginScreen,
5859
- {
5860
- authInput,
5861
- onAuthInputChange: handlers.onSetAuthInput,
5862
- onSubmit: handlers.onSendLoginCode,
5863
- sending: activeOtpStatus === "sending-code",
5864
- error: state.error,
5865
- onBack,
5866
- merchantInitials: merchantName ? merchantName.slice(0, 2).toUpperCase() : void 0
5867
- }
5868
- );
5869
- }
5870
- if (step === "otp-verify") {
5871
- return /* @__PURE__ */ jsxRuntime.jsx(
5872
- OtpVerifyScreen,
5873
- {
5874
- maskedIdentifier: state.verificationTarget ? maskAuthIdentifier(state.verificationTarget) : "",
5875
- otpCode,
5876
- onOtpChange: (code) => {
5877
- handlers.onSetOtpCode(code);
5878
- },
5879
- onVerify: handlers.onVerifyLoginCode,
5880
- onResend: handlers.onResendLoginCode,
5881
- onBack: handlers.onBackFromOtp,
5882
- verifying: activeOtpStatus === "submitting-code" || authenticated,
5883
- error: state.error
5884
- }
5885
- );
5886
- }
5887
- if (step === "create-passkey") {
5888
- return /* @__PURE__ */ jsxRuntime.jsx(
5889
- PasskeyScreen,
5890
- {
5891
- onCreatePasskey: handlers.onRegisterPasskey,
5892
- onBack: handlers.onLogout,
5893
- onLogout: handlers.onLogout,
5894
- creating: state.registeringPasskey,
5895
- error: state.error,
5896
- popupFallback: state.passkeyPopupNeeded,
5897
- onCreatePasskeyViaPopup: handlers.onCreatePasskeyViaPopup
5898
- }
5899
- );
5900
- }
5901
- if (step === "verify-passkey") {
5902
- return /* @__PURE__ */ jsxRuntime.jsx(
5903
- PasskeyScreen,
5904
- {
5905
- onCreatePasskey: handlers.onRegisterPasskey,
5906
- onBack: handlers.onLogout,
5907
- onLogout: handlers.onLogout,
5908
- creating: state.verifyingPasskeyPopup,
5909
- error: state.error,
5910
- popupFallback: true,
5911
- onCreatePasskeyViaPopup: handlers.onVerifyPasskeyViaPopup
5912
- }
5913
- );
5914
- }
5915
- if (step === "wallet-picker") {
5916
- if (state.isGuestFlow && state.selectedProviderId && state.activeCredentialId) {
5917
- return /* @__PURE__ */ jsxRuntime.jsx(BlinkLoadingScreen, {});
6025
+ case "open-wallet": {
6026
+ const providerName = state.providers.find((p) => p.id === state.selectedProviderId)?.name ?? null;
6027
+ return /* @__PURE__ */ jsxRuntime.jsx(
6028
+ OpenWalletScreen,
6029
+ {
6030
+ walletName: providerName,
6031
+ deeplinkUri: state.deeplinkUri ?? "",
6032
+ loading: !isDesktop ? state.creatingTransfer || !state.deeplinkUri : state.creatingTransfer,
6033
+ useDeeplink: !isDesktop,
6034
+ error: state.error || (!isDesktop ? pollingError : authExecutorError),
6035
+ onRetryStatus: !isDesktop ? handlers.onRetryMobileStatus : void 0,
6036
+ onBack: !isDesktop ? () => handlers.onSetUserIntent(null) : void 0,
6037
+ onLogout: handlers.onLogout
6038
+ }
6039
+ );
5918
6040
  }
5919
- const isEntryPoint = !state.isGuestFlow && !authenticated;
5920
- return /* @__PURE__ */ jsxRuntime.jsx(
5921
- WalletPickerScreen,
5922
- {
5923
- providers: state.providers,
5924
- pendingConnections,
5925
- loading: state.creatingTransfer,
5926
- useDeeplink: !shouldUseWalletConnector({
5927
- userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
5928
- }),
5929
- onPrepareProvider: handlers.onPrepareProvider,
5930
- onSelectProvider: handlers.onSelectProvider,
5931
- onContinueConnection: handlers.onContinueConnection,
5932
- onBack: isEntryPoint ? onBack : () => handlers.onNavigate(state.activeCredentialId ? "deposit" : "create-passkey"),
5933
- onLogout: authenticated ? handlers.onLogout : void 0,
5934
- onLogin: handlers.onLogin,
5935
- showLoginOption: isEntryPoint
5936
- }
5937
- );
5938
- }
5939
- if (step === "open-wallet") {
5940
- const providerName = state.providers.find((p) => p.id === state.selectedProviderId)?.name ?? null;
5941
- const useDeeplink = !shouldUseWalletConnector({
5942
- userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
5943
- });
5944
- return /* @__PURE__ */ jsxRuntime.jsx(
5945
- OpenWalletScreen,
5946
- {
5947
- walletName: providerName,
5948
- deeplinkUri: state.deeplinkUri ?? "",
5949
- loading: useDeeplink ? state.creatingTransfer || !state.deeplinkUri : state.creatingTransfer,
5950
- useDeeplink,
5951
- error: state.error || (useDeeplink ? pollingError : authExecutorError),
5952
- onRetryStatus: useDeeplink ? handlers.onRetryMobileStatus : void 0,
5953
- onBack: useDeeplink ? () => handlers.onNavigate("wallet-picker") : void 0,
5954
- onLogout: handlers.onLogout
5955
- }
5956
- );
5957
- }
5958
- if (step === "setup-status") {
5959
- return /* @__PURE__ */ jsxRuntime.jsx(
5960
- SetupStatusScreen,
5961
- {
5962
- complete: false,
5963
- limit: state.oneTapLimit,
5964
- tokensApproved: 0,
5965
- merchantName,
5966
- onContinue: () => handlers.onNavigate("setup"),
5967
- onLogout: handlers.onLogout,
5968
- error: state.error || authExecutorError
5969
- }
5970
- );
5971
- }
5972
- if (step === "setup") {
5973
- const selectSourceTokenCount = selectSourceChoices.reduce(
5974
- (sum, chain) => sum + chain.tokens.length,
5975
- 0
5976
- );
5977
- const effectiveTokenCount = tokenCount > 0 ? tokenCount : selectSourceTokenCount;
5978
- const effectiveSourceLabel = selectedSourceLabel ?? (selectSourceChainName && selectSourceTokenSymbol ? `${selectSourceTokenSymbol} on ${selectSourceChainName}` : void 0);
5979
- return /* @__PURE__ */ jsxRuntime.jsx(
5980
- SetupScreen,
5981
- {
5982
- availableBalance: selectedSource ? selectedSource.balance.available.amount : selectSourceAvailableBalance > 0 ? selectSourceAvailableBalance : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
5983
- tokenCount: effectiveTokenCount,
5984
- sourceName,
5985
- onSetupOneTap: handlers.onSetupOneTap,
5986
- onBack: () => handlers.onNavigate("deposit"),
5987
- onLogout: handlers.onLogout,
5988
- onAdvanced: handlers.onSelectToken,
5989
- selectedSourceLabel: effectiveSourceLabel,
5990
- loading: savingOneTapLimit,
5991
- error: state.error,
5992
- selectedTokenSymbol: selectedSource?.token.symbol ?? selectSourceTokenSymbol
5993
- }
5994
- );
5995
- }
5996
- if (step === "confirm-sign") {
5997
- const providerName = state.providers.find((p) => p.id === state.selectedProviderId)?.name ?? null;
5998
- return /* @__PURE__ */ jsxRuntime.jsx(
5999
- ConfirmSignScreen,
6000
- {
6001
- walletName: providerName,
6002
- signing: transferSigningSigning,
6003
- error: state.error || transferSigningError,
6004
- onSign: handlers.onConfirmSign,
6005
- onLogout: handlers.onLogout
6006
- }
6007
- );
6008
- }
6009
- if (step === "deposit") {
6010
- if (state.loadingData) {
6011
- return /* @__PURE__ */ jsxRuntime.jsx(BlinkLoadingScreen, {});
6041
+ case "setup-status":
6042
+ return /* @__PURE__ */ jsxRuntime.jsx(
6043
+ SetupStatusScreen,
6044
+ {
6045
+ complete: false,
6046
+ limit: state.oneTapLimit,
6047
+ tokensApproved: 0,
6048
+ merchantName,
6049
+ onContinue: () => handlers.onSetUserIntent("configure-one-tap"),
6050
+ onLogout: handlers.onLogout,
6051
+ error: state.error || authExecutorError
6052
+ }
6053
+ );
6054
+ case "setup": {
6055
+ const selectSourceTokenCount = selectSourceChoices.reduce(
6056
+ (sum, chain) => sum + chain.tokens.length,
6057
+ 0
6058
+ );
6059
+ const effectiveTokenCount = tokenCount > 0 ? tokenCount : selectSourceTokenCount;
6060
+ const effectiveSourceLabel = selectedSourceLabel ?? (selectSourceChainName && selectSourceTokenSymbol ? `${selectSourceTokenSymbol} on ${selectSourceChainName}` : void 0);
6061
+ return /* @__PURE__ */ jsxRuntime.jsx(
6062
+ SetupScreen,
6063
+ {
6064
+ availableBalance: selectedSource ? selectedSource.balance.available.amount : selectSourceAvailableBalance > 0 ? selectSourceAvailableBalance : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
6065
+ tokenCount: effectiveTokenCount,
6066
+ sourceName,
6067
+ onSetupOneTap: handlers.onSetupOneTap,
6068
+ onBack: () => handlers.onSetUserIntent(null),
6069
+ onLogout: handlers.onLogout,
6070
+ onAdvanced: handlers.onSelectToken,
6071
+ selectedSourceLabel: effectiveSourceLabel,
6072
+ loading: savingOneTapLimit,
6073
+ error: state.error,
6074
+ selectedTokenSymbol: selectedSource?.token.symbol ?? selectSourceTokenSymbol
6075
+ }
6076
+ );
6012
6077
  }
6013
- const parsedAmt = depositAmount != null ? depositAmount : 5;
6014
- return /* @__PURE__ */ jsxRuntime.jsx(
6015
- DepositScreen,
6016
- {
6017
- merchantName,
6018
- availableBalance: selectedSource ? selectedSource.balance.available.amount : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
6019
- remainingLimit: selectedSource != null ? selectedSource.remainingAllowance ?? null : selectedAccount?.remainingAllowance ?? null,
6020
- tokenCount,
6021
- initialAmount: parsedAmt,
6022
- processing: state.creatingTransfer,
6023
- error: state.error,
6024
- onDeposit: handlers.onPay,
6025
- onSwitchWallet: () => handlers.onNavigate("wallet-picker"),
6026
- onBack: onBack ?? (() => handlers.onLogout()),
6027
- onLogout: handlers.onLogout,
6028
- onIncreaseLimit: handlers.onIncreaseLimit,
6029
- increasingLimit: state.increasingLimit,
6030
- accounts: depositEligibleAccounts,
6031
- selectedAccountId: state.selectedAccountId,
6032
- onSelectAccount: handlers.onSelectAccount,
6033
- onAuthorizeAccount: handlers.onContinueConnection,
6034
- onAddProvider: () => handlers.onNavigate("wallet-picker"),
6035
- onSelectToken: handlers.onSelectToken,
6036
- selectedSourceLabel,
6037
- selectedTokenSymbol: selectedSource?.token.symbol
6078
+ case "confirm-sign": {
6079
+ const providerName = state.providers.find((p) => p.id === state.selectedProviderId)?.name ?? null;
6080
+ return /* @__PURE__ */ jsxRuntime.jsx(
6081
+ ConfirmSignScreen,
6082
+ {
6083
+ walletName: providerName,
6084
+ signing: transferSigningSigning,
6085
+ error: state.error || transferSigningError,
6086
+ onSign: handlers.onConfirmSign,
6087
+ onLogout: handlers.onLogout
6088
+ }
6089
+ );
6090
+ }
6091
+ case "deposit": {
6092
+ const parsedAmt = depositAmount != null ? depositAmount : 5;
6093
+ return /* @__PURE__ */ jsxRuntime.jsx(
6094
+ DepositScreen,
6095
+ {
6096
+ merchantName,
6097
+ availableBalance: selectedSource ? selectedSource.balance.available.amount : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
6098
+ remainingLimit: selectedSource != null ? selectedSource.remainingAllowance ?? null : selectedAccount?.remainingAllowance ?? null,
6099
+ tokenCount,
6100
+ initialAmount: parsedAmt,
6101
+ processing: state.creatingTransfer,
6102
+ error: state.error,
6103
+ onDeposit: handlers.onPay,
6104
+ onSwitchWallet: () => handlers.onSetUserIntent("switch-wallet"),
6105
+ onBack: onBack ?? (() => handlers.onLogout()),
6106
+ onLogout: handlers.onLogout,
6107
+ onIncreaseLimit: handlers.onIncreaseLimit,
6108
+ increasingLimit: state.increasingLimit,
6109
+ accounts: depositEligibleAccounts,
6110
+ selectedAccountId: state.selectedAccountId,
6111
+ onSelectAccount: handlers.onSelectAccount,
6112
+ onAuthorizeAccount: handlers.onContinueConnection,
6113
+ onAddProvider: () => handlers.onSetUserIntent("switch-wallet"),
6114
+ onSelectToken: handlers.onSelectToken,
6115
+ selectedSourceLabel,
6116
+ selectedTokenSymbol: selectedSource?.token.symbol
6117
+ }
6118
+ );
6119
+ }
6120
+ case "token-picker": {
6121
+ if (!selectedAccount) {
6122
+ return /* @__PURE__ */ jsxRuntime.jsx(BlinkLoadingScreen, {});
6038
6123
  }
6039
- );
6040
- }
6041
- if (step === "token-picker") {
6042
- if (state.isGuestFlow) {
6124
+ return /* @__PURE__ */ jsxRuntime.jsx(
6125
+ TokenPickerScreen,
6126
+ {
6127
+ account: selectedAccount,
6128
+ chains: state.chains,
6129
+ onSelectAuthorized: handlers.onSelectAuthorizedToken,
6130
+ onAuthorizeToken: handlers.onAuthorizeToken,
6131
+ onBack: () => handlers.onSetUserIntent(null),
6132
+ onLogout: handlers.onLogout,
6133
+ depositAmount: depositAmount ?? void 0,
6134
+ selectedTokenSymbol: selectedSource?.token.symbol,
6135
+ selectedWalletId: state.selectedWalletId ?? void 0
6136
+ }
6137
+ );
6138
+ }
6139
+ case "guest-token-picker":
6043
6140
  return /* @__PURE__ */ jsxRuntime.jsx(
6044
6141
  GuestTokenPickerScreen,
6045
6142
  {
@@ -6049,107 +6146,60 @@ function StepRendererContent({
6049
6146
  depositAmount: depositAmount ?? void 0,
6050
6147
  error: state.error,
6051
6148
  onSelect: handlers.onSelectGuestToken,
6052
- onBack: () => handlers.onNavigate("wallet-picker")
6149
+ onBack: () => handlers.onSetUserIntent(null)
6150
+ }
6151
+ );
6152
+ case "processing": {
6153
+ const polledStatus = pollingTransfer?.status;
6154
+ const transferPhase = state.creatingTransfer ? "creating" : polledStatus === "SENDING" || polledStatus === "SENT" ? "sent" : "verifying";
6155
+ return /* @__PURE__ */ jsxRuntime.jsx(
6156
+ TransferStatusScreen,
6157
+ {
6158
+ phase: transferPhase,
6159
+ error: state.error || authExecutorError || transferSigningError || pollingError,
6160
+ onLogout: handlers.onLogout
6053
6161
  }
6054
6162
  );
6055
6163
  }
6056
- if (!selectedAccount) {
6057
- return /* @__PURE__ */ jsxRuntime.jsx(BlinkLoadingScreen, {});
6164
+ case "select-source":
6165
+ return /* @__PURE__ */ jsxRuntime.jsx(
6166
+ SelectSourceScreen,
6167
+ {
6168
+ choices: selectSourceChoices,
6169
+ selectedChainName: selectSourceChainName,
6170
+ selectedTokenSymbol: selectSourceTokenSymbol,
6171
+ recommended: selectSourceRecommended,
6172
+ onChainChange: handlers.onSelectSourceChainChange,
6173
+ onTokenChange: handlers.onSetSelectSourceTokenSymbol,
6174
+ onConfirm: handlers.onConfirmSelectSource,
6175
+ onLogout: handlers.onLogout
6176
+ }
6177
+ );
6178
+ case "success": {
6179
+ const succeeded = state.transfer?.status === "COMPLETED";
6180
+ const displayAmount = state.transfer?.amount?.amount ?? 0;
6181
+ const displayCurrency = state.transfer?.amount?.currency ?? "USD";
6182
+ return /* @__PURE__ */ jsxRuntime.jsx(
6183
+ SuccessScreen,
6184
+ {
6185
+ amount: displayAmount,
6186
+ currency: displayCurrency,
6187
+ succeeded,
6188
+ error: state.error,
6189
+ merchantName,
6190
+ sourceName,
6191
+ remainingLimit: succeeded ? (() => {
6192
+ const limit = selectedSource != null ? selectedSource.remainingAllowance ?? null : selectedAccount?.remainingAllowance ?? null;
6193
+ if (limit == null) return null;
6194
+ return limit > displayAmount ? limit - displayAmount : 0;
6195
+ })() : void 0,
6196
+ onDone: onDismiss ?? handlers.onNewPayment,
6197
+ onLogout: handlers.onLogout,
6198
+ onPreauthorize: state.isGuestFlow ? handlers.onPreauthorize : void 0
6199
+ }
6200
+ );
6058
6201
  }
6059
- return /* @__PURE__ */ jsxRuntime.jsx(
6060
- TokenPickerScreen,
6061
- {
6062
- account: selectedAccount,
6063
- chains: state.chains,
6064
- onSelectAuthorized: handlers.onSelectAuthorizedToken,
6065
- onAuthorizeToken: handlers.onAuthorizeToken,
6066
- onBack: () => handlers.onNavigate(state.previousStep === "setup" ? "setup" : "deposit"),
6067
- onLogout: handlers.onLogout,
6068
- depositAmount: depositAmount ?? void 0,
6069
- selectedTokenSymbol: selectedSource?.token.symbol,
6070
- selectedWalletId: state.selectedWalletId
6071
- }
6072
- );
6073
- }
6074
- if (step === "processing") {
6075
- const polledStatus = pollingTransfer?.status;
6076
- const transferPhase = state.creatingTransfer ? "creating" : polledStatus === "SENDING" || polledStatus === "SENT" ? "sent" : "verifying";
6077
- return /* @__PURE__ */ jsxRuntime.jsx(
6078
- TransferStatusScreen,
6079
- {
6080
- phase: transferPhase,
6081
- error: state.error || authExecutorError || transferSigningError || pollingError,
6082
- onLogout: handlers.onLogout
6083
- }
6084
- );
6085
- }
6086
- if (step === "select-source") {
6087
- const cameFromSetup = state.previousStep === "setup";
6088
- return /* @__PURE__ */ jsxRuntime.jsx(
6089
- SelectSourceScreen,
6090
- {
6091
- choices: selectSourceChoices,
6092
- selectedChainName: selectSourceChainName,
6093
- selectedTokenSymbol: selectSourceTokenSymbol,
6094
- recommended: selectSourceRecommended,
6095
- onChainChange: handlers.onSelectSourceChainChange,
6096
- onTokenChange: handlers.onSetSelectSourceTokenSymbol,
6097
- onConfirm: cameFromSetup ? () => handlers.onNavigate("setup") : handlers.onConfirmSelectSource,
6098
- onBack: cameFromSetup ? () => handlers.onNavigate("setup") : void 0,
6099
- onLogout: handlers.onLogout
6100
- }
6101
- );
6102
6202
  }
6103
- if (step === "success") {
6104
- const succeeded = state.transfer?.status === "COMPLETED";
6105
- const displayAmount = state.transfer?.amount?.amount ?? 0;
6106
- const displayCurrency = state.transfer?.amount?.currency ?? "USD";
6107
- return /* @__PURE__ */ jsxRuntime.jsx(
6108
- SuccessScreen,
6109
- {
6110
- amount: displayAmount,
6111
- currency: displayCurrency,
6112
- succeeded,
6113
- error: state.error,
6114
- merchantName,
6115
- sourceName,
6116
- remainingLimit: succeeded ? (() => {
6117
- const limit = selectedSource != null ? selectedSource.remainingAllowance ?? null : selectedAccount?.remainingAllowance ?? null;
6118
- if (limit == null) return null;
6119
- return limit > displayAmount ? limit - displayAmount : 0;
6120
- })() : void 0,
6121
- onDone: onDismiss ?? handlers.onNewPayment,
6122
- onLogout: handlers.onLogout,
6123
- onPreauthorize: state.isGuestFlow ? handlers.onPreauthorize : void 0
6124
- }
6125
- );
6126
- }
6127
- if (step === "low-balance") {
6128
- return /* @__PURE__ */ jsxRuntime.jsx(
6129
- DepositScreen,
6130
- {
6131
- merchantName,
6132
- availableBalance: 0,
6133
- remainingLimit: selectedSource != null ? selectedSource.remainingAllowance ?? null : selectedAccount?.remainingAllowance ?? null,
6134
- tokenCount,
6135
- initialAmount: depositAmount ?? 5,
6136
- processing: false,
6137
- error: state.error,
6138
- onDeposit: handlers.onPay,
6139
- onSwitchWallet: () => handlers.onNavigate("wallet-picker"),
6140
- onBack: onBack ?? (() => handlers.onLogout()),
6141
- onLogout: handlers.onLogout,
6142
- accounts: depositEligibleAccounts,
6143
- selectedAccountId: state.selectedAccountId,
6144
- onSelectAccount: handlers.onSelectAccount,
6145
- onAuthorizeAccount: handlers.onContinueConnection,
6146
- onAddProvider: () => handlers.onNavigate("wallet-picker"),
6147
- selectedSourceLabel,
6148
- selectedTokenSymbol: selectedSource?.token.symbol
6149
- }
6150
- );
6151
- }
6152
- return null;
6153
6203
  }
6154
6204
 
6155
6205
  // src/sentry.ts
@@ -6386,52 +6436,6 @@ function useAuthHandlers(dispatch, verificationTarget) {
6386
6436
  handleResendLoginCode
6387
6437
  };
6388
6438
  }
6389
-
6390
- // src/mobileFlow.ts
6391
- function hasActiveWallet(accounts) {
6392
- return accounts.some((account) => account.wallets.some((wallet) => wallet.status === "ACTIVE"));
6393
- }
6394
- function resolvePostAuthStep(state) {
6395
- if (!state.hasPasskey) {
6396
- return { step: "create-passkey", clearPersistedFlow: false };
6397
- }
6398
- if (state.persistedMobileFlow) {
6399
- if (state.persistedMobileFlow.isReauthorization) {
6400
- return { step: "open-wallet", clearPersistedFlow: false };
6401
- }
6402
- if (state.persistedMobileFlow.isSetup && hasActiveWallet(state.accounts)) {
6403
- return { step: "deposit", clearPersistedFlow: true };
6404
- }
6405
- return { step: "open-wallet", clearPersistedFlow: false };
6406
- }
6407
- if (state.mobileSetupInProgress && !hasActiveWallet(state.accounts)) {
6408
- return { step: "open-wallet", clearPersistedFlow: false };
6409
- }
6410
- if ((state.accounts.length === 0 || !hasActiveWallet(state.accounts)) && !state.connectingNewAccount) {
6411
- return { step: "wallet-picker", clearPersistedFlow: false };
6412
- }
6413
- return { step: "deposit", clearPersistedFlow: false };
6414
- }
6415
- function resolveRestoredMobileFlow(transferStatus, isSetup) {
6416
- if (transferStatus === "AUTHORIZED") {
6417
- return isSetup ? { kind: "resume-setup-deposit", step: "deposit", clearPersistedFlow: true } : { kind: "resume-confirm-sign", step: "confirm-sign", clearPersistedFlow: true };
6418
- }
6419
- if (transferStatus === "COMPLETED") {
6420
- return { kind: "resume-success", step: "success", clearPersistedFlow: true };
6421
- }
6422
- if (transferStatus === "FAILED") {
6423
- return { kind: "resume-failed", step: "success", clearPersistedFlow: true };
6424
- }
6425
- if (transferStatus === "SENDING" || transferStatus === "SENT") {
6426
- return { kind: "resume-processing", step: "processing", clearPersistedFlow: true };
6427
- }
6428
- if (isSetup) {
6429
- return { kind: "resume-stale-setup", step: "wallet-picker", clearPersistedFlow: true };
6430
- }
6431
- return { kind: "resume-open-wallet", step: "open-wallet", clearPersistedFlow: false };
6432
- }
6433
-
6434
- // src/hooks/usePasskeyHandlers.ts
6435
6439
  function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds, mobileSetupFlowRef, guestPreauthAccountId) {
6436
6440
  const { user, getAccessToken } = reactAuth.usePrivy();
6437
6441
  const checkingPasskeyRef = react.useRef(false);
@@ -6443,35 +6447,14 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6443
6447
  reportPasskeyActivity(apiBaseUrl, token, credentialId).catch(() => {
6444
6448
  });
6445
6449
  }
6446
- const resolved = resolvePostAuthStep({
6447
- hasPasskey: true,
6448
- accounts,
6449
- persistedMobileFlow: loadMobileFlowState(),
6450
- mobileSetupInProgress: mobileSetupFlowRef.current,
6451
- connectingNewAccount: false
6452
- });
6453
- if (resolved.clearPersistedFlow) clearMobileFlowState();
6454
- dispatch({ type: "NAVIGATE", step: resolved.step });
6455
- }, [getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, dispatch]);
6450
+ }, [getAccessToken, apiBaseUrl, dispatch]);
6456
6451
  const completePasskeyRegistration = react.useCallback(async (credentialId, publicKey) => {
6457
6452
  const token = await getAccessToken();
6458
6453
  if (!token) throw new Error("Not authenticated");
6459
6454
  await registerPasskey(apiBaseUrl, token, credentialId, publicKey);
6460
6455
  dispatch({ type: "PASSKEY_ACTIVATED", credentialId, publicKey });
6461
6456
  window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
6462
- if (guestPreauthAccountId) {
6463
- return;
6464
- }
6465
- const resolved = resolvePostAuthStep({
6466
- hasPasskey: true,
6467
- accounts,
6468
- persistedMobileFlow: loadMobileFlowState(),
6469
- mobileSetupInProgress: mobileSetupFlowRef.current,
6470
- connectingNewAccount: false
6471
- });
6472
- if (resolved.clearPersistedFlow) clearMobileFlowState();
6473
- dispatch({ type: "NAVIGATE", step: resolved.step });
6474
- }, [getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, guestPreauthAccountId, dispatch]);
6457
+ }, [getAccessToken, apiBaseUrl, dispatch]);
6475
6458
  const handleRegisterPasskey = react.useCallback(async () => {
6476
6459
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
6477
6460
  dispatch({ type: "SET_ERROR", error: null });
@@ -6535,15 +6518,6 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6535
6518
  const { credentialId } = await createPasskeyViaPopup(popupOptions);
6536
6519
  dispatch({ type: "PASSKEY_ACTIVATED", credentialId });
6537
6520
  localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
6538
- const resolved = resolvePostAuthStep({
6539
- hasPasskey: true,
6540
- accounts,
6541
- persistedMobileFlow: loadMobileFlowState(),
6542
- mobileSetupInProgress: mobileSetupFlowRef.current,
6543
- connectingNewAccount: false
6544
- });
6545
- if (resolved.clearPersistedFlow) clearMobileFlowState();
6546
- dispatch({ type: "NAVIGATE", step: resolved.step });
6547
6521
  } catch (err) {
6548
6522
  captureException(err);
6549
6523
  dispatch({
@@ -6553,7 +6527,7 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6553
6527
  } finally {
6554
6528
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
6555
6529
  }
6556
- }, [user, knownCredentialIds, getAccessToken, apiBaseUrl, activateExistingCredential, accounts, mobileSetupFlowRef, dispatch]);
6530
+ }, [user, knownCredentialIds, getAccessToken, apiBaseUrl, activateExistingCredential, dispatch]);
6557
6531
  const handleVerifyPasskeyViaPopup = react.useCallback(async () => {
6558
6532
  dispatch({ type: "SET_VERIFYING_PASSKEY", value: true });
6559
6533
  dispatch({ type: "SET_ERROR", error: null });
@@ -6572,15 +6546,6 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6572
6546
  reportPasskeyActivity(apiBaseUrl, token, matched).catch(() => {
6573
6547
  });
6574
6548
  }
6575
- const resolved = resolvePostAuthStep({
6576
- hasPasskey: true,
6577
- accounts,
6578
- persistedMobileFlow: loadMobileFlowState(),
6579
- mobileSetupInProgress: mobileSetupFlowRef.current,
6580
- connectingNewAccount: false
6581
- });
6582
- if (resolved.clearPersistedFlow) clearMobileFlowState();
6583
- dispatch({ type: "NAVIGATE", step: resolved.step });
6584
6549
  } else {
6585
6550
  dispatch({
6586
6551
  type: "SET_ERROR",
@@ -6596,7 +6561,7 @@ function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds,
6596
6561
  } finally {
6597
6562
  dispatch({ type: "SET_VERIFYING_PASSKEY", value: false });
6598
6563
  }
6599
- }, [knownCredentialIds, getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, dispatch]);
6564
+ }, [knownCredentialIds, getAccessToken, apiBaseUrl, dispatch]);
6600
6565
  return {
6601
6566
  handleRegisterPasskey,
6602
6567
  handleCreatePasskeyViaPopup,
@@ -6649,10 +6614,9 @@ function useTransferHandlers(deps) {
6649
6614
  }
6650
6615
  if (!activeCredentialId) {
6651
6616
  dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
6652
- dispatch({ type: "NAVIGATE", step: "create-passkey" });
6653
6617
  return;
6654
6618
  }
6655
- dispatch({ type: "PAY_STARTED", isSetupRedirect: false });
6619
+ dispatch({ type: "PAY_STARTED" });
6656
6620
  processingStartedAtRef.current = Date.now();
6657
6621
  try {
6658
6622
  if (transfer?.status === "AUTHORIZED") {
@@ -6699,7 +6663,7 @@ function useTransferHandlers(deps) {
6699
6663
  } catch (err) {
6700
6664
  captureException(err);
6701
6665
  const msg = err instanceof Error ? err.message : "Transfer failed";
6702
- dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "deposit" });
6666
+ dispatch({ type: "PAY_ERROR", error: msg });
6703
6667
  onError?.(msg);
6704
6668
  } finally {
6705
6669
  dispatch({ type: "PAY_ENDED" });
@@ -6749,7 +6713,6 @@ function useSourceSelectionHandlers(dispatch, authExecutor) {
6749
6713
  const [selectSourceChainName, setSelectSourceChainName] = react.useState("");
6750
6714
  const [selectSourceTokenSymbol, setSelectSourceTokenSymbol] = react.useState("");
6751
6715
  const initializedSelectSourceActionRef = react.useRef(null);
6752
- const preSelectSourceStepRef = react.useRef(null);
6753
6716
  const pendingSelectSourceAction = authExecutor.pendingSelectSource;
6754
6717
  const selectSourceChoices = react.useMemo(() => {
6755
6718
  if (!pendingSelectSourceAction) return [];
@@ -6807,8 +6770,7 @@ function useSourceSelectionHandlers(dispatch, authExecutor) {
6807
6770
  handleSelectSourceChainChange,
6808
6771
  handleConfirmSelectSource,
6809
6772
  pendingSelectSourceAction,
6810
- initializedSelectSourceActionRef,
6811
- preSelectSourceStepRef
6773
+ initializedSelectSourceActionRef
6812
6774
  };
6813
6775
  }
6814
6776
  function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, onComplete) {
@@ -6821,16 +6783,13 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
6821
6783
  const onCompleteRef = react.useRef(onComplete);
6822
6784
  onCompleteRef.current = onComplete;
6823
6785
  const guestPollingActiveRef = react.useRef(false);
6824
- react.useEffect(() => {
6825
- const persisted = loadMobileFlowState();
6826
- if (!persisted?.isGuestCheckout || !persisted.transferId || !persisted.guestSessionToken) return;
6786
+ const guestPollingCleanupRef = react.useRef(null);
6787
+ const startGuestPolling = react.useCallback((transferId, guestSessionToken) => {
6827
6788
  if (guestPollingActiveRef.current) return;
6828
6789
  guestPollingActiveRef.current = true;
6829
- const transferId = persisted.transferId;
6830
- const guestSessionToken = persisted.guestSessionToken;
6831
6790
  let cancelled = false;
6832
6791
  const POLL_INTERVAL_MS = 3e3;
6833
- dispatch({ type: "NAVIGATE", step: "processing" });
6792
+ dispatch({ type: "SET_ERROR", error: null });
6834
6793
  const poll = async () => {
6835
6794
  if (cancelled) return;
6836
6795
  try {
@@ -6839,12 +6798,14 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
6839
6798
  if (transfer.status === "COMPLETED") {
6840
6799
  cancelled = true;
6841
6800
  guestPollingActiveRef.current = false;
6801
+ guestPollingCleanupRef.current = null;
6842
6802
  clearMobileFlowState();
6843
6803
  dispatch({ type: "GUEST_TRANSFER_COMPLETED", transfer, guestSessionToken });
6844
6804
  onCompleteRef.current?.(transfer);
6845
6805
  } else if (transfer.status === "FAILED") {
6846
6806
  cancelled = true;
6847
6807
  guestPollingActiveRef.current = false;
6808
+ guestPollingCleanupRef.current = null;
6848
6809
  clearMobileFlowState();
6849
6810
  dispatch({ type: "TRANSFER_FAILED", transfer, error: "Transfer failed." });
6850
6811
  }
@@ -6853,26 +6814,44 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
6853
6814
  };
6854
6815
  poll();
6855
6816
  const intervalId = window.setInterval(poll, POLL_INTERVAL_MS);
6856
- const handleVisibility = () => {
6857
- if (document.visibilityState === "visible" && !cancelled) {
6858
- poll();
6817
+ const cleanup = () => {
6818
+ cancelled = true;
6819
+ guestPollingActiveRef.current = false;
6820
+ guestPollingCleanupRef.current = null;
6821
+ window.clearInterval(intervalId);
6822
+ };
6823
+ guestPollingCleanupRef.current = cleanup;
6824
+ }, [apiBaseUrl, dispatch]);
6825
+ react.useEffect(() => {
6826
+ const persisted = loadMobileFlowState();
6827
+ if (persisted?.isGuestCheckout && persisted.transferId && persisted.guestSessionToken) {
6828
+ startGuestPolling(persisted.transferId, persisted.guestSessionToken);
6829
+ }
6830
+ return () => {
6831
+ guestPollingCleanupRef.current?.();
6832
+ };
6833
+ }, [startGuestPolling]);
6834
+ react.useEffect(() => {
6835
+ const tryStartPolling = () => {
6836
+ if (guestPollingActiveRef.current) return;
6837
+ const persisted = loadMobileFlowState();
6838
+ if (persisted?.isGuestCheckout && persisted.transferId && persisted.guestSessionToken) {
6839
+ startGuestPolling(persisted.transferId, persisted.guestSessionToken);
6859
6840
  }
6860
6841
  };
6842
+ const handleVisibility = () => {
6843
+ if (document.visibilityState === "visible") tryStartPolling();
6844
+ };
6861
6845
  const handlePageShow = (e) => {
6862
- if (e.persisted && !cancelled) {
6863
- poll();
6864
- }
6846
+ if (e.persisted) tryStartPolling();
6865
6847
  };
6866
6848
  document.addEventListener("visibilitychange", handleVisibility);
6867
6849
  window.addEventListener("pageshow", handlePageShow);
6868
6850
  return () => {
6869
- cancelled = true;
6870
- guestPollingActiveRef.current = false;
6871
- window.clearInterval(intervalId);
6872
6851
  document.removeEventListener("visibilitychange", handleVisibility);
6873
6852
  window.removeEventListener("pageshow", handlePageShow);
6874
6853
  };
6875
- }, [apiBaseUrl, dispatch]);
6854
+ }, [startGuestPolling]);
6876
6855
  const handleAuthorizedMobileReturn = react.useCallback(async (authorizedTransfer, isSetup) => {
6877
6856
  if (handlingMobileReturnRef.current) return;
6878
6857
  handlingMobileReturnRef.current = true;
@@ -6944,7 +6923,6 @@ function useProviderHandlers(deps) {
6944
6923
  }
6945
6924
  if (!activeCredentialId) {
6946
6925
  dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
6947
- dispatch({ type: "NAVIGATE", step: "create-passkey" });
6948
6926
  return null;
6949
6927
  }
6950
6928
  const provider = providers.find((p) => p.id === providerId);
@@ -6965,7 +6943,7 @@ function useProviderHandlers(deps) {
6965
6943
  } catch (err) {
6966
6944
  captureException(err);
6967
6945
  const msg = err instanceof Error ? err.message : "Failed to set up wallet";
6968
- dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
6946
+ dispatch({ type: "PAY_ERROR", error: msg });
6969
6947
  onError?.(msg);
6970
6948
  return null;
6971
6949
  }
@@ -6973,7 +6951,7 @@ function useProviderHandlers(deps) {
6973
6951
  const handleGuestSelectProvider = react.useCallback(async (providerId) => {
6974
6952
  if (!merchantAuthorization || !destination) {
6975
6953
  const msg = "Missing payment configuration for guest checkout.";
6976
- dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
6954
+ dispatch({ type: "PAY_ERROR", error: msg });
6977
6955
  onError?.(msg);
6978
6956
  return;
6979
6957
  }
@@ -6995,7 +6973,7 @@ function useProviderHandlers(deps) {
6995
6973
  });
6996
6974
  if (isMobile) {
6997
6975
  if (!result.uri) {
6998
- dispatch({ type: "PAY_ERROR", error: "This wallet is not available on mobile.", fallbackStep: "wallet-picker" });
6976
+ dispatch({ type: "PAY_ERROR", error: "This wallet is not available on mobile." });
6999
6977
  return;
7000
6978
  }
7001
6979
  persistMobileFlowState({
@@ -7013,7 +6991,7 @@ function useProviderHandlers(deps) {
7013
6991
  if (!account.isConnected) {
7014
6992
  const connector = connectors.find((c) => c.type === "injected") ?? connectors[0];
7015
6993
  if (!connector) {
7016
- dispatch({ type: "PAY_ERROR", error: "No wallet extension found. Please install a supported wallet.", fallbackStep: "wallet-picker" });
6994
+ dispatch({ type: "PAY_ERROR", error: "No wallet extension found. Please install a supported wallet." });
7017
6995
  return;
7018
6996
  }
7019
6997
  await connectAsync({ connector });
@@ -7028,7 +7006,7 @@ function useProviderHandlers(deps) {
7028
7006
  } catch (err) {
7029
7007
  captureException(err);
7030
7008
  const msg = err instanceof Error ? err.message : "Failed to start guest checkout";
7031
- dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
7009
+ dispatch({ type: "PAY_ERROR", error: msg });
7032
7010
  onError?.(msg);
7033
7011
  }
7034
7012
  }, [
@@ -7051,7 +7029,6 @@ function useProviderHandlers(deps) {
7051
7029
  dispatch({ type: "SELECT_PROVIDER", providerId });
7052
7030
  if (!activeCredentialId) {
7053
7031
  dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
7054
- dispatch({ type: "NAVIGATE", step: "create-passkey" });
7055
7032
  return;
7056
7033
  }
7057
7034
  const provider = providers.find((p) => p.id === providerId);
@@ -7061,8 +7038,7 @@ function useProviderHandlers(deps) {
7061
7038
  userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
7062
7039
  });
7063
7040
  if (!isMobile) {
7064
- dispatch({ type: "PAY_STARTED", isSetupRedirect: false });
7065
- dispatch({ type: "NAVIGATE", step: "open-wallet" });
7041
+ dispatch({ type: "PAY_STARTED" });
7066
7042
  }
7067
7043
  try {
7068
7044
  let accountId;
@@ -7104,12 +7080,11 @@ function useProviderHandlers(deps) {
7104
7080
  } else {
7105
7081
  await authExecutor.executeSessionById(sessionId);
7106
7082
  await reloadAccounts();
7107
- dispatch({ type: "NAVIGATE", step: "deposit" });
7108
7083
  }
7109
7084
  } catch (err) {
7110
7085
  captureException(err);
7111
7086
  const msg = err instanceof Error ? err.message : "Failed to set up wallet";
7112
- dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
7087
+ dispatch({ type: "PAY_ERROR", error: msg });
7113
7088
  onError?.(msg);
7114
7089
  } finally {
7115
7090
  if (!isMobile) {
@@ -7173,7 +7148,6 @@ function useProviderHandlers(deps) {
7173
7148
  }
7174
7149
  if (!activeCredentialId) {
7175
7150
  dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
7176
- dispatch({ type: "NAVIGATE", step: "create-passkey" });
7177
7151
  return;
7178
7152
  }
7179
7153
  const acct = accounts.find((a) => a.id === selectedAccountId);
@@ -7219,10 +7193,8 @@ function useProviderHandlers(deps) {
7219
7193
  dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
7220
7194
  triggerDeeplink(session.uri);
7221
7195
  } else {
7222
- dispatch({ type: "NAVIGATE", step: "open-wallet" });
7223
7196
  await authExecutor.executeSessionById(session.id);
7224
7197
  await reloadAccounts();
7225
- dispatch({ type: "NAVIGATE", step: "deposit" });
7226
7198
  }
7227
7199
  } catch (err) {
7228
7200
  captureException(err);
@@ -7254,12 +7226,8 @@ function useProviderHandlers(deps) {
7254
7226
  reauthTokenRef
7255
7227
  ]);
7256
7228
  const handleNavigateToTokenPicker = react.useCallback(() => {
7257
- if (authExecutor.pendingSelectSource) {
7258
- dispatch({ type: "NAVIGATE", step: "select-source" });
7259
- } else {
7260
- dispatch({ type: "NAVIGATE", step: "token-picker" });
7261
- }
7262
- }, [dispatch, authExecutor.pendingSelectSource]);
7229
+ dispatch({ type: "SET_USER_INTENT", intent: "pick-token" });
7230
+ }, [dispatch]);
7263
7231
  const handleSelectAuthorizedToken = react.useCallback((walletId, tokenSymbol) => {
7264
7232
  dispatch({ type: "SELECT_TOKEN", walletId, tokenSymbol });
7265
7233
  }, [dispatch]);
@@ -7270,7 +7238,6 @@ function useProviderHandlers(deps) {
7270
7238
  }
7271
7239
  if (!activeCredentialId) {
7272
7240
  dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
7273
- dispatch({ type: "NAVIGATE", step: "create-passkey" });
7274
7241
  return;
7275
7242
  }
7276
7243
  const acct = accounts.find((a) => a.id === selectedAccountId);
@@ -7312,7 +7279,6 @@ function useProviderHandlers(deps) {
7312
7279
  dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
7313
7280
  triggerDeeplink(session.uri);
7314
7281
  } else {
7315
- dispatch({ type: "NAVIGATE", step: "open-wallet" });
7316
7282
  await authExecutor.executeSessionById(session.id);
7317
7283
  await reloadAccounts();
7318
7284
  dispatch({ type: "SELECT_TOKEN", walletId: _walletId, tokenSymbol });
@@ -7384,7 +7350,6 @@ function useGuestTransferHandlers(deps) {
7384
7350
  isGuestFlow,
7385
7351
  guestTransferId,
7386
7352
  guestSessionToken,
7387
- step,
7388
7353
  onComplete,
7389
7354
  onError
7390
7355
  } = deps;
@@ -7398,8 +7363,7 @@ function useGuestTransferHandlers(deps) {
7398
7363
  const fetchedRef = react.useRef(false);
7399
7364
  const selectedGuestTokenRef = react.useRef(null);
7400
7365
  react.useEffect(() => {
7401
- if (!isGuestFlow || step !== "token-picker" || fetchedRef.current) return;
7402
- if (!guestTransferId || !guestSessionToken) return;
7366
+ if (!isGuestFlow || !guestTransferId || !guestSessionToken || fetchedRef.current) return;
7403
7367
  const account = getAccount(wagmiConfig2);
7404
7368
  if (!account.address) return;
7405
7369
  fetchedRef.current = true;
@@ -7413,7 +7377,7 @@ function useGuestTransferHandlers(deps) {
7413
7377
  captureException(err);
7414
7378
  dispatch({ type: "SET_ERROR", error: "Failed to fetch token balances." });
7415
7379
  }).finally(() => setLoadingBalances(false));
7416
- }, [isGuestFlow, step, guestTransferId, guestSessionToken, apiBaseUrl, wagmiConfig2, dispatch]);
7380
+ }, [isGuestFlow, guestTransferId, guestSessionToken, apiBaseUrl, wagmiConfig2, dispatch]);
7417
7381
  react.useEffect(() => {
7418
7382
  if (!isGuestFlow) {
7419
7383
  fetchedRef.current = false;
@@ -7442,7 +7406,6 @@ function useGuestTransferHandlers(deps) {
7442
7406
  entry.tokenAddress
7443
7407
  );
7444
7408
  selectedGuestTokenRef.current = entry;
7445
- dispatch({ type: "NAVIGATE", step: "processing" });
7446
7409
  } catch (err) {
7447
7410
  captureException(err);
7448
7411
  const msg = err instanceof Error ? err.message : "Failed to set transfer sender";
@@ -7453,7 +7416,7 @@ function useGuestTransferHandlers(deps) {
7453
7416
  }
7454
7417
  }, [guestTransferId, guestSessionToken, wagmiConfig2, apiBaseUrl, dispatch, onError]);
7455
7418
  react.useEffect(() => {
7456
- if (!isGuestFlow || step !== "processing" || !guestTransferId || !guestSessionToken) return;
7419
+ if (!isGuestFlow || !guestTransferId || !guestSessionToken || !selectedGuestTokenRef.current) return;
7457
7420
  if (executingBridgeRef.current) return;
7458
7421
  executingBridgeRef.current = true;
7459
7422
  const execute = async () => {
@@ -7467,7 +7430,7 @@ function useGuestTransferHandlers(deps) {
7467
7430
  break;
7468
7431
  }
7469
7432
  if (transfer.status === "FAILED") {
7470
- dispatch({ type: "PAY_ERROR", error: "Transfer failed.", fallbackStep: "wallet-picker" });
7433
+ dispatch({ type: "PAY_ERROR", error: "Transfer failed." });
7471
7434
  return;
7472
7435
  }
7473
7436
  await new Promise((r) => setTimeout(r, GUEST_SIGN_POLL_MS));
@@ -7475,8 +7438,7 @@ function useGuestTransferHandlers(deps) {
7475
7438
  if (!signPayload) {
7476
7439
  dispatch({
7477
7440
  type: "PAY_ERROR",
7478
- error: "Timed out waiting for bridge quote. Please try again.",
7479
- fallbackStep: "wallet-picker"
7441
+ error: "Timed out waiting for bridge quote. Please try again."
7480
7442
  });
7481
7443
  return;
7482
7444
  }
@@ -7496,7 +7458,7 @@ function useGuestTransferHandlers(deps) {
7496
7458
  const walletClient = await getWalletClient(wagmiConfig2);
7497
7459
  const sender = account.address;
7498
7460
  if (!sender) {
7499
- dispatch({ type: "PAY_ERROR", error: "Wallet not connected.", fallbackStep: "wallet-picker" });
7461
+ dispatch({ type: "PAY_ERROR", error: "Wallet not connected." });
7500
7462
  return;
7501
7463
  }
7502
7464
  let lastTxHash = null;
@@ -7521,7 +7483,7 @@ function useGuestTransferHandlers(deps) {
7521
7483
  lastTxHash = txHash;
7522
7484
  }
7523
7485
  if (!lastTxHash) {
7524
- dispatch({ type: "PAY_ERROR", error: "No bridge transactions were executed.", fallbackStep: "wallet-picker" });
7486
+ dispatch({ type: "PAY_ERROR", error: "No bridge transactions were executed." });
7525
7487
  return;
7526
7488
  }
7527
7489
  console.info(`[blink-sdk] type=guest Submitting originTxHash: ${lastTxHash}`);
@@ -7542,22 +7504,21 @@ function useGuestTransferHandlers(deps) {
7542
7504
  }
7543
7505
  dispatch({
7544
7506
  type: "PAY_ERROR",
7545
- error: "Transfer is taking longer than expected. It may still complete.",
7546
- fallbackStep: "wallet-picker"
7507
+ error: "Transfer is taking longer than expected. It may still complete."
7547
7508
  });
7548
7509
  } catch (err) {
7549
7510
  captureException(err);
7550
7511
  const msg = err instanceof Error ? err.message : "Bridge execution failed";
7551
7512
  console.error("[blink-sdk] type=guest Bridge execution error:", err);
7552
7513
  const displayMsg = isUserRejection2(msg) ? "You rejected the transaction. Please approve in your wallet to continue." : msg;
7553
- dispatch({ type: "PAY_ERROR", error: displayMsg, fallbackStep: "wallet-picker" });
7514
+ dispatch({ type: "PAY_ERROR", error: displayMsg });
7554
7515
  onError?.(displayMsg);
7555
7516
  } finally {
7556
7517
  executingBridgeRef.current = false;
7557
7518
  }
7558
7519
  };
7559
7520
  execute();
7560
- }, [isGuestFlow, step, guestTransferId, guestSessionToken, apiBaseUrl, wagmiConfig2, switchChainAsync, dispatch, onComplete, onError]);
7521
+ }, [isGuestFlow, guestTransferId, guestSessionToken, settingSender, apiBaseUrl, wagmiConfig2, switchChainAsync, dispatch, onComplete, onError]);
7561
7522
  return {
7562
7523
  guestTokenEntries,
7563
7524
  loadingBalances,
@@ -7598,12 +7559,10 @@ function useOneTapSetupHandlers(deps) {
7598
7559
  }
7599
7560
  oneTapLimitSavedDuringSetupRef.current = true;
7600
7561
  authExecutor.resolveSelectSource({ chainName, tokenSymbol });
7601
- dispatch({ type: "NAVIGATE", step: "open-wallet" });
7602
7562
  } else if (authExecutor.pendingOneTapSetup) {
7603
7563
  authExecutor.resolveOneTapSetup();
7604
- } else {
7605
- dispatch({ type: "NAVIGATE", step: "deposit" });
7606
7564
  }
7565
+ dispatch({ type: "SET_USER_INTENT", intent: null });
7607
7566
  } catch (err) {
7608
7567
  captureException(err);
7609
7568
  dispatch({
@@ -7624,12 +7583,11 @@ function useOneTapSetupHandlers(deps) {
7624
7583
  // src/dataLoading.ts
7625
7584
  function resolveDataLoadAction({
7626
7585
  authenticated,
7627
- step,
7628
7586
  accountsCount,
7629
7587
  hasActiveCredential,
7630
7588
  loading
7631
7589
  }) {
7632
- if (!authenticated || step === "login" || step === "otp-verify" || accountsCount > 0 || !hasActiveCredential) {
7590
+ if (!authenticated || accountsCount > 0 || !hasActiveCredential) {
7633
7591
  return "reset";
7634
7592
  }
7635
7593
  if (loading) {
@@ -7676,7 +7634,6 @@ function usePaymentEffects(deps) {
7676
7634
  authenticated,
7677
7635
  apiBaseUrl,
7678
7636
  depositAmount,
7679
- useWalletConnectorProp,
7680
7637
  onComplete,
7681
7638
  onError,
7682
7639
  polling,
@@ -7703,7 +7660,6 @@ function usePaymentEffects(deps) {
7703
7660
  setSelectSourceChainName,
7704
7661
  setSelectSourceTokenSymbol,
7705
7662
  initializedSelectSourceActionRef,
7706
- preSelectSourceStepRef,
7707
7663
  oneTapLimitSavedDuringSetupRef,
7708
7664
  handleAuthorizedMobileReturn
7709
7665
  } = deps;
@@ -7723,27 +7679,27 @@ function usePaymentEffects(deps) {
7723
7679
  }
7724
7680
  }, [depositAmount, dispatch]);
7725
7681
  react.useEffect(() => {
7726
- if (authenticated || state.step !== "otp-verify") return;
7682
+ if (authenticated || !state.verificationTarget) return;
7727
7683
  if (activeOtpErrorMessage) dispatch({ type: "SET_ERROR", error: activeOtpErrorMessage });
7728
- }, [activeOtpErrorMessage, authenticated, state.step, dispatch]);
7684
+ }, [activeOtpErrorMessage, authenticated, state.verificationTarget, dispatch]);
7729
7685
  react.useEffect(() => {
7730
- if (state.step === "otp-verify" && /^\d{6}$/.test(otpCode.trim()) && activeOtpStatus === "awaiting-code-input") {
7686
+ if (state.verificationTarget && !authenticated && /^\d{6}$/.test(otpCode.trim()) && activeOtpStatus === "awaiting-code-input") {
7731
7687
  handleVerifyLoginCode();
7732
7688
  }
7733
- }, [otpCode, state.step, activeOtpStatus, handleVerifyLoginCode]);
7689
+ }, [otpCode, state.verificationTarget, authenticated, activeOtpStatus, handleVerifyLoginCode]);
7734
7690
  react.useEffect(() => {
7735
7691
  if (!ready || !authenticated) {
7736
7692
  checkingPasskeyRef.current = false;
7737
7693
  return;
7738
7694
  }
7739
- if (state.step !== "login" && state.step !== "otp-verify") return;
7695
+ if (state.passkeyConfigLoaded || state.activeCredentialId) return;
7740
7696
  if (checkingPasskeyRef.current) return;
7741
7697
  checkingPasskeyRef.current = true;
7742
7698
  let cancelled = false;
7743
7699
  dispatch({ type: "SET_ERROR", error: null });
7744
7700
  setAuthInput("");
7745
7701
  setOtpCode("");
7746
- const restoreOrDeposit = async (credId, token) => {
7702
+ const restoreState = async (credId, token) => {
7747
7703
  const persisted = loadMobileFlowState();
7748
7704
  let accts = [];
7749
7705
  try {
@@ -7751,117 +7707,118 @@ function usePaymentEffects(deps) {
7751
7707
  if (cancelled) return;
7752
7708
  } catch {
7753
7709
  }
7754
- const resolved = resolvePostAuthStep({
7755
- hasPasskey: true,
7756
- accounts: accts,
7757
- persistedMobileFlow: persisted,
7758
- mobileSetupInProgress: false,
7759
- connectingNewAccount: false
7760
- });
7761
- if (resolved.clearPersistedFlow) clearMobileFlowState();
7762
- if (resolved.step === "deposit" && persisted && persisted.isSetup && persisted.transferId) {
7763
- try {
7764
- const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
7765
- if (cancelled) return;
7766
- if (existingTransfer.status === "AUTHORIZED") {
7767
- await handleAuthorizedMobileReturnRef.current(existingTransfer, true);
7768
- return;
7769
- }
7770
- } catch {
7771
- }
7772
- }
7773
- if (resolved.step === "open-wallet" && persisted && persisted.isReauthorization && persisted.sessionId) {
7774
- try {
7775
- const session = await fetchAuthorizationSession(apiBaseUrl, persisted.sessionId);
7776
- if (cancelled) return;
7777
- if (session.status === "AUTHORIZED") {
7778
- clearMobileFlowState();
7779
- dispatch({ type: "NAVIGATE", step: "deposit" });
7780
- if (persisted.reauthorizationToken) {
7781
- dispatch({ type: "SELECT_TOKEN", walletId: persisted.reauthorizationToken.walletId, tokenSymbol: persisted.reauthorizationToken.tokenSymbol });
7782
- }
7783
- return;
7784
- }
7785
- } catch {
7786
- }
7787
- reauthSessionIdRef.current = persisted.sessionId;
7788
- reauthTokenRef.current = persisted.reauthorizationToken ?? null;
7789
- mobileSetupFlowRef.current = true;
7790
- setupAccountIdRef.current = persisted.accountId ?? null;
7791
- dispatch({
7792
- type: "ENTER_MOBILE_FLOW",
7793
- deeplinkUri: persisted.deeplinkUri,
7794
- providerId: persisted.providerId
7795
- });
7796
- return;
7797
- }
7798
- if (resolved.step === "open-wallet" && persisted && persisted.accountId && !persisted.transferId) {
7799
- if (persisted.sessionId) {
7710
+ if (persisted) {
7711
+ if (persisted.isReauthorization && persisted.sessionId) {
7800
7712
  try {
7801
7713
  const session = await fetchAuthorizationSession(apiBaseUrl, persisted.sessionId);
7802
7714
  if (cancelled) return;
7803
7715
  if (session.status === "AUTHORIZED") {
7804
7716
  clearMobileFlowState();
7805
- dispatch({ type: "NAVIGATE", step: "deposit" });
7717
+ if (persisted.reauthorizationToken) {
7718
+ dispatch({ type: "SELECT_TOKEN", walletId: persisted.reauthorizationToken.walletId, tokenSymbol: persisted.reauthorizationToken.tokenSymbol });
7719
+ }
7806
7720
  return;
7807
7721
  }
7808
7722
  } catch {
7809
7723
  }
7724
+ reauthSessionIdRef.current = persisted.sessionId;
7725
+ reauthTokenRef.current = persisted.reauthorizationToken ?? null;
7726
+ mobileSetupFlowRef.current = true;
7727
+ setupAccountIdRef.current = persisted.accountId ?? null;
7728
+ dispatch({
7729
+ type: "ENTER_MOBILE_FLOW",
7730
+ deeplinkUri: persisted.deeplinkUri,
7731
+ providerId: persisted.providerId
7732
+ });
7733
+ return;
7810
7734
  }
7811
- mobileSetupFlowRef.current = true;
7812
- setupAccountIdRef.current = persisted.accountId;
7813
- dispatch({
7814
- type: "ENTER_MOBILE_FLOW",
7815
- deeplinkUri: persisted.deeplinkUri,
7816
- providerId: persisted.providerId
7817
- });
7818
- return;
7819
- }
7820
- if (resolved.step === "open-wallet" && persisted && persisted.transferId) {
7821
- try {
7822
- const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
7823
- if (cancelled) return;
7824
- const mobileResolution = resolveRestoredMobileFlow(
7825
- existingTransfer.status,
7826
- persisted.isSetup
7827
- );
7828
- if (mobileResolution.kind === "resume-setup-deposit") {
7829
- await handleAuthorizedMobileReturnRef.current(existingTransfer, true);
7830
- return;
7831
- }
7832
- if (mobileResolution.kind === "resume-confirm-sign") {
7833
- await handleAuthorizedMobileReturnRef.current(existingTransfer, false);
7834
- return;
7835
- }
7836
- if (mobileResolution.kind === "resume-success") {
7837
- clearMobileFlowState();
7838
- dispatch({ type: "MOBILE_RESUME_SUCCESS", transfer: existingTransfer });
7839
- onCompleteRef.current?.(existingTransfer);
7840
- return;
7841
- }
7842
- if (mobileResolution.kind === "resume-failed") {
7843
- clearMobileFlowState();
7844
- dispatch({ type: "MOBILE_RESUME_FAILED", transfer: existingTransfer });
7845
- return;
7735
+ if (persisted.isSetup && persisted.transferId) {
7736
+ try {
7737
+ const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
7738
+ if (cancelled) return;
7739
+ if (existingTransfer.status === "AUTHORIZED") {
7740
+ await handleAuthorizedMobileReturnRef.current(existingTransfer, true);
7741
+ return;
7742
+ }
7743
+ } catch {
7846
7744
  }
7847
- if (mobileResolution.kind === "resume-processing") {
7848
- clearMobileFlowState();
7849
- dispatch({ type: "MOBILE_RESUME_PROCESSING", transfer: existingTransfer });
7850
- pollingRef.current.startPolling(existingTransfer.id);
7851
- return;
7745
+ }
7746
+ if (persisted.isSetup && accts.some((a) => a.wallets.some((w) => w.status === "ACTIVE"))) {
7747
+ clearMobileFlowState();
7748
+ return;
7749
+ }
7750
+ if (persisted.accountId && !persisted.transferId) {
7751
+ if (persisted.sessionId) {
7752
+ try {
7753
+ const session = await fetchAuthorizationSession(apiBaseUrl, persisted.sessionId);
7754
+ if (cancelled) return;
7755
+ if (session.status === "AUTHORIZED") {
7756
+ clearMobileFlowState();
7757
+ return;
7758
+ }
7759
+ } catch {
7760
+ }
7852
7761
  }
7853
- if (mobileResolution.kind === "resume-stale-setup") {
7854
- clearMobileFlowState();
7855
- if (!cancelled) dispatch({ type: "NAVIGATE", step: "wallet-picker" });
7762
+ mobileSetupFlowRef.current = true;
7763
+ setupAccountIdRef.current = persisted.accountId;
7764
+ dispatch({
7765
+ type: "ENTER_MOBILE_FLOW",
7766
+ deeplinkUri: persisted.deeplinkUri,
7767
+ providerId: persisted.providerId
7768
+ });
7769
+ return;
7770
+ }
7771
+ if (persisted.transferId) {
7772
+ try {
7773
+ const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
7774
+ if (cancelled) return;
7775
+ if (existingTransfer.status === "COMPLETED") {
7776
+ clearMobileFlowState();
7777
+ dispatch({ type: "MOBILE_RESUME_SUCCESS", transfer: existingTransfer });
7778
+ onCompleteRef.current?.(existingTransfer);
7779
+ return;
7780
+ }
7781
+ if (existingTransfer.status === "FAILED") {
7782
+ clearMobileFlowState();
7783
+ dispatch({ type: "MOBILE_RESUME_FAILED", transfer: existingTransfer });
7784
+ return;
7785
+ }
7786
+ if (existingTransfer.status === "SENDING" || existingTransfer.status === "SENT") {
7787
+ clearMobileFlowState();
7788
+ dispatch({ type: "MOBILE_RESUME_PROCESSING", transfer: existingTransfer });
7789
+ pollingRef.current.startPolling(existingTransfer.id);
7790
+ return;
7791
+ }
7792
+ if (existingTransfer.status === "AUTHORIZED") {
7793
+ if (persisted.isSetup) {
7794
+ await handleAuthorizedMobileReturnRef.current(existingTransfer, true);
7795
+ } else {
7796
+ await handleAuthorizedMobileReturnRef.current(existingTransfer, false);
7797
+ }
7798
+ return;
7799
+ }
7800
+ if (persisted.isSetup) {
7801
+ clearMobileFlowState();
7802
+ return;
7803
+ }
7804
+ } catch (err) {
7805
+ if (cancelled) return;
7806
+ dispatch({
7807
+ type: "ENTER_MOBILE_FLOW",
7808
+ deeplinkUri: persisted.deeplinkUri,
7809
+ providerId: persisted.providerId,
7810
+ error: err instanceof Error ? err.message : "Unable to refresh wallet authorization status."
7811
+ });
7812
+ pollingTransferIdRef.current = persisted.transferId ?? null;
7813
+ mobileSetupFlowRef.current = persisted.isSetup;
7814
+ setupAccountIdRef.current = persisted.accountId ?? null;
7815
+ if (persisted.transferId) pollingRef.current.startPolling(persisted.transferId);
7856
7816
  return;
7857
7817
  }
7858
- } catch (err) {
7859
- if (cancelled) return;
7860
7818
  dispatch({
7861
7819
  type: "ENTER_MOBILE_FLOW",
7862
7820
  deeplinkUri: persisted.deeplinkUri,
7863
- providerId: persisted.providerId,
7864
- error: err instanceof Error ? err.message : "Unable to refresh wallet authorization status."
7821
+ providerId: persisted.providerId
7865
7822
  });
7866
7823
  pollingTransferIdRef.current = persisted.transferId ?? null;
7867
7824
  mobileSetupFlowRef.current = persisted.isSetup;
@@ -7869,18 +7826,7 @@ function usePaymentEffects(deps) {
7869
7826
  if (persisted.transferId) pollingRef.current.startPolling(persisted.transferId);
7870
7827
  return;
7871
7828
  }
7872
- dispatch({
7873
- type: "ENTER_MOBILE_FLOW",
7874
- deeplinkUri: persisted.deeplinkUri,
7875
- providerId: persisted.providerId
7876
- });
7877
- pollingTransferIdRef.current = persisted.transferId ?? null;
7878
- mobileSetupFlowRef.current = persisted.isSetup;
7879
- setupAccountIdRef.current = persisted.accountId ?? null;
7880
- if (persisted.transferId) pollingRef.current.startPolling(persisted.transferId);
7881
- return;
7882
7829
  }
7883
- dispatch({ type: "NAVIGATE", step: resolved.step });
7884
7830
  };
7885
7831
  const checkPasskey = async () => {
7886
7832
  try {
@@ -7890,11 +7836,7 @@ function usePaymentEffects(deps) {
7890
7836
  if (token || cancelled) break;
7891
7837
  await new Promise((r) => setTimeout(r, 1e3));
7892
7838
  }
7893
- if (!token) {
7894
- if (!cancelled) dispatch({ type: "NAVIGATE", step: "create-passkey" });
7895
- return;
7896
- }
7897
- if (cancelled) return;
7839
+ if (!token || cancelled) return;
7898
7840
  const { config } = await fetchUserConfig(apiBaseUrl, token);
7899
7841
  if (cancelled) return;
7900
7842
  const allPasskeys = config.passkeys ?? (config.passkey ? [config.passkey] : []);
@@ -7904,11 +7846,10 @@ function usePaymentEffects(deps) {
7904
7846
  oneTapLimit: config.defaultAllowance ?? void 0
7905
7847
  });
7906
7848
  if (allPasskeys.length === 0) {
7907
- dispatch({ type: "NAVIGATE", step: "create-passkey" });
7908
7849
  return;
7909
7850
  }
7910
7851
  if (state.activeCredentialId && allPasskeys.some((p) => p.credentialId === state.activeCredentialId)) {
7911
- await restoreOrDeposit(state.activeCredentialId, token);
7852
+ await restoreState(state.activeCredentialId, token);
7912
7853
  return;
7913
7854
  }
7914
7855
  if (cancelled) return;
@@ -7930,12 +7871,9 @@ function usePaymentEffects(deps) {
7930
7871
  window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
7931
7872
  reportPasskeyActivity(apiBaseUrl, token, matched).catch(() => {
7932
7873
  });
7933
- await restoreOrDeposit(matched, token);
7934
- return;
7874
+ await restoreState(matched, token);
7935
7875
  }
7936
- dispatch({ type: "NAVIGATE", step: "create-passkey" });
7937
7876
  } catch {
7938
- if (!cancelled) dispatch({ type: "NAVIGATE", step: "create-passkey" });
7939
7877
  }
7940
7878
  };
7941
7879
  checkPasskey();
@@ -7943,11 +7881,10 @@ function usePaymentEffects(deps) {
7943
7881
  cancelled = true;
7944
7882
  checkingPasskeyRef.current = false;
7945
7883
  };
7946
- }, [ready, authenticated, state.step, apiBaseUrl, state.activeCredentialId]);
7884
+ }, [ready, authenticated, apiBaseUrl, state.activeCredentialId, state.passkeyConfigLoaded]);
7947
7885
  react.useEffect(() => {
7948
7886
  const loadAction = resolveDataLoadAction({
7949
7887
  authenticated,
7950
- step: state.step,
7951
7888
  accountsCount: state.accounts.length,
7952
7889
  hasActiveCredential: !!state.activeCredentialId,
7953
7890
  loading: loadingDataRef.current
@@ -7980,24 +7917,16 @@ function usePaymentEffects(deps) {
7980
7917
  const parsedAmt = depositAmount != null ? depositAmount : 0;
7981
7918
  const defaults = resolveDepositSelection(accts, parsedAmt, state.selectedAccountId);
7982
7919
  const persisted = loadMobileFlowState();
7983
- const resolved = resolvePostAuthStep({
7984
- hasPasskey: !!state.activeCredentialId,
7985
- accounts: accts,
7986
- persistedMobileFlow: persisted,
7987
- mobileSetupInProgress: mobileSetupFlowRef.current,
7988
- connectingNewAccount: false
7989
- });
7990
- const correctableSteps = ["deposit", "wallet-picker", "open-wallet"];
7920
+ const clearMobile = persisted?.isSetup && accts.some((a) => a.wallets.some((w) => w.status === "ACTIVE"));
7991
7921
  dispatch({
7992
7922
  type: "DATA_LOADED",
7993
7923
  providers: prov,
7994
7924
  accounts: accts,
7995
7925
  chains: chn,
7996
7926
  defaults,
7997
- resolvedStep: correctableSteps.includes(state.step) && !state.creatingTransfer ? resolved.step : void 0,
7998
- clearMobileState: resolved.clearPersistedFlow
7927
+ clearMobileState: clearMobile
7999
7928
  });
8000
- if (resolved.clearPersistedFlow) clearMobileFlowState();
7929
+ if (clearMobile) clearMobileFlowState();
8001
7930
  } catch (err) {
8002
7931
  if (!cancelled) {
8003
7932
  captureException(err);
@@ -8020,7 +7949,6 @@ function usePaymentEffects(deps) {
8020
7949
  };
8021
7950
  }, [
8022
7951
  authenticated,
8023
- state.step,
8024
7952
  state.accounts.length,
8025
7953
  apiBaseUrl,
8026
7954
  state.activeCredentialId,
@@ -8029,7 +7957,7 @@ function usePaymentEffects(deps) {
8029
7957
  ]);
8030
7958
  react.useEffect(() => {
8031
7959
  if (authenticated || state.providers.length > 0) return;
8032
- if (state.step !== "wallet-picker") return;
7960
+ if (state.activeCredentialId) return;
8033
7961
  let cancelled = false;
8034
7962
  const loadProviders = async () => {
8035
7963
  try {
@@ -8052,7 +7980,7 @@ function usePaymentEffects(deps) {
8052
7980
  return () => {
8053
7981
  cancelled = true;
8054
7982
  };
8055
- }, [authenticated, state.step, state.providers.length, apiBaseUrl]);
7983
+ }, [authenticated, state.providers.length, state.activeCredentialId, apiBaseUrl]);
8056
7984
  react.useEffect(() => {
8057
7985
  if (!polling.transfer) return;
8058
7986
  if (polling.transfer.status === "COMPLETED") {
@@ -8066,13 +7994,21 @@ function usePaymentEffects(deps) {
8066
7994
  }
8067
7995
  }, [polling.transfer, onComplete, dispatch, reloadAccounts]);
8068
7996
  react.useEffect(() => {
8069
- if (state.step === "deposit" && state.accounts.length > 0 && authenticated && Date.now() - lastAccountFetchRef.current > 15e3) {
7997
+ if (state.accounts.length > 0 && state.activeCredentialId && !state.loadingData && !state.transfer && authenticated && Date.now() - lastAccountFetchRef.current > 15e3) {
8070
7998
  lastAccountFetchRef.current = Date.now();
8071
7999
  reloadAccounts();
8072
8000
  }
8073
- }, [state.step, state.accounts.length, authenticated, reloadAccounts]);
8001
+ }, [
8002
+ state.accounts.length,
8003
+ state.activeCredentialId,
8004
+ state.loadingData,
8005
+ state.transfer,
8006
+ authenticated,
8007
+ reloadAccounts
8008
+ ]);
8074
8009
  react.useEffect(() => {
8075
- if (state.step !== "processing") {
8010
+ const isProcessing = state.creatingTransfer || state.transfer != null && ["CREATED", "SENDING", "SENT"].includes(state.transfer.status);
8011
+ if (!isProcessing) {
8076
8012
  processingStartedAtRef.current = null;
8077
8013
  return;
8078
8014
  }
@@ -8096,7 +8032,15 @@ function usePaymentEffects(deps) {
8096
8032
  }
8097
8033
  const timeoutId = window.setTimeout(handleTimeout, remainingMs);
8098
8034
  return () => window.clearTimeout(timeoutId);
8099
- }, [state.step, polling.transfer, state.transfer, polling.stopPolling, onError, dispatch, processingStartedAtRef]);
8035
+ }, [
8036
+ state.creatingTransfer,
8037
+ state.transfer,
8038
+ polling.transfer,
8039
+ polling.stopPolling,
8040
+ onError,
8041
+ dispatch,
8042
+ processingStartedAtRef
8043
+ ]);
8100
8044
  react.useEffect(() => {
8101
8045
  if (!state.mobileFlow) {
8102
8046
  handlingMobileReturnRef.current = false;
@@ -8109,7 +8053,6 @@ function usePaymentEffects(deps) {
8109
8053
  }, [state.mobileFlow, polling.transfer, handleAuthorizedMobileReturn, handlingMobileReturnRef, mobileSetupFlowRef]);
8110
8054
  react.useEffect(() => {
8111
8055
  if (!state.mobileFlow || !mobileSetupFlowRef.current) return;
8112
- if (state.step !== "open-wallet") return;
8113
8056
  if (!state.activeCredentialId || !setupAccountIdRef.current) return;
8114
8057
  const accountId = setupAccountIdRef.current;
8115
8058
  const credentialId = state.activeCredentialId;
@@ -8202,7 +8145,6 @@ function usePaymentEffects(deps) {
8202
8145
  };
8203
8146
  }, [
8204
8147
  state.mobileFlow,
8205
- state.step,
8206
8148
  state.activeCredentialId,
8207
8149
  apiBaseUrl,
8208
8150
  reloadAccounts,
@@ -8272,46 +8214,22 @@ function usePaymentEffects(deps) {
8272
8214
  setSelectSourceTokenSymbol,
8273
8215
  initializedSelectSourceActionRef
8274
8216
  ]);
8217
+ const pendingOneTapSetupAction = authExecutor.pendingOneTapSetup;
8275
8218
  react.useEffect(() => {
8276
- if (pendingSelectSourceAction && (state.step === "processing" || state.step === "open-wallet" || state.step === "setup-status")) {
8277
- const isDesktop = shouldUseWalletConnector({
8278
- useWalletConnector: useWalletConnectorProp,
8279
- userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
8280
- });
8281
- if (isDesktop && (state.step === "setup-status" || state.step === "open-wallet")) {
8282
- preSelectSourceStepRef.current = state.step;
8283
- dispatch({ type: "NAVIGATE", step: "setup" });
8284
- return;
8285
- }
8286
- preSelectSourceStepRef.current = state.step;
8287
- dispatch({ type: "NAVIGATE", step: "select-source" });
8288
- } else if (!pendingSelectSourceAction && state.step === "select-source") {
8289
- dispatch({ type: "NAVIGATE", step: preSelectSourceStepRef.current ?? "processing" });
8290
- preSelectSourceStepRef.current = null;
8219
+ if (pendingOneTapSetupAction && oneTapLimitSavedDuringSetupRef.current) {
8220
+ oneTapLimitSavedDuringSetupRef.current = false;
8221
+ authExecutor.resolveOneTapSetup();
8291
8222
  }
8292
- }, [pendingSelectSourceAction, state.step, useWalletConnectorProp, dispatch, preSelectSourceStepRef, authExecutor]);
8293
- const pendingOneTapSetupAction = authExecutor.pendingOneTapSetup;
8294
- const preOneTapSetupStepRef = react.useRef(null);
8223
+ }, [pendingOneTapSetupAction, authExecutor, oneTapLimitSavedDuringSetupRef]);
8295
8224
  react.useEffect(() => {
8296
- if (pendingOneTapSetupAction && (state.step === "setup-status" || state.step === "open-wallet")) {
8297
- if (oneTapLimitSavedDuringSetupRef.current) {
8298
- oneTapLimitSavedDuringSetupRef.current = false;
8299
- authExecutor.resolveOneTapSetup();
8300
- } else {
8301
- preOneTapSetupStepRef.current = state.step;
8302
- reloadAccounts().then(() => {
8303
- dispatch({ type: "NAVIGATE", step: "setup" });
8304
- });
8305
- }
8306
- } else if (!pendingOneTapSetupAction && state.step === "setup" && preOneTapSetupStepRef.current) {
8307
- dispatch({ type: "NAVIGATE", step: preOneTapSetupStepRef.current });
8308
- preOneTapSetupStepRef.current = null;
8225
+ if (pendingOneTapSetupAction && !oneTapLimitSavedDuringSetupRef.current) {
8226
+ reloadAccounts();
8309
8227
  }
8310
- }, [pendingOneTapSetupAction, state.step, reloadAccounts, authExecutor, dispatch, oneTapLimitSavedDuringSetupRef]);
8228
+ }, [pendingOneTapSetupAction, reloadAccounts, oneTapLimitSavedDuringSetupRef]);
8311
8229
  react.useEffect(() => {
8312
- if (state.step !== "success") return;
8313
8230
  if (!state.guestSessionToken) return;
8314
8231
  if (state.guestPreauthAccountId) return;
8232
+ if (!state.transfer || state.transfer.status !== "COMPLETED") return;
8315
8233
  let cancelled = false;
8316
8234
  const checkPreauth = async () => {
8317
8235
  try {
@@ -8327,7 +8245,7 @@ function usePaymentEffects(deps) {
8327
8245
  return () => {
8328
8246
  cancelled = true;
8329
8247
  };
8330
- }, [state.step, state.guestSessionToken, state.guestPreauthAccountId, apiBaseUrl, dispatch]);
8248
+ }, [state.transfer, state.guestSessionToken, state.guestPreauthAccountId, apiBaseUrl, dispatch]);
8331
8249
  const settingOwnerRef = react.useRef(false);
8332
8250
  react.useEffect(() => {
8333
8251
  if (!state.guestPreauthAccountId) return;
@@ -8498,7 +8416,6 @@ function BlinkPaymentInner({
8498
8416
  isGuestFlow: state.isGuestFlow,
8499
8417
  guestTransferId: state.guestTransferId,
8500
8418
  guestSessionToken: state.guestSessionToken,
8501
- step: state.step,
8502
8419
  onComplete,
8503
8420
  onError
8504
8421
  });
@@ -8506,14 +8423,13 @@ function BlinkPaymentInner({
8506
8423
  clearMobileFlowState();
8507
8424
  transfer.processingStartedAtRef.current = null;
8508
8425
  transfer.pollingTransferIdRef.current = null;
8509
- sourceSelection.preSelectSourceStepRef.current = null;
8510
8426
  oneTapSetup.oneTapLimitSavedDuringSetupRef.current = false;
8511
8427
  dispatch({
8512
8428
  type: "NEW_PAYMENT",
8513
8429
  depositAmount,
8514
8430
  firstAccountId: state.accounts.length > 0 ? state.accounts[0].id : null
8515
8431
  });
8516
- }, [depositAmount, state.accounts, transfer, sourceSelection, provider, oneTapSetup]);
8432
+ }, [depositAmount, state.accounts, transfer, oneTapSetup]);
8517
8433
  const handleLogout = react.useCallback(async () => {
8518
8434
  try {
8519
8435
  await logout();
@@ -8524,13 +8440,12 @@ function BlinkPaymentInner({
8524
8440
  window.localStorage.removeItem(ACTIVE_CREDENTIAL_STORAGE_KEY);
8525
8441
  }
8526
8442
  polling.stopPolling();
8527
- sourceSelection.preSelectSourceStepRef.current = null;
8528
8443
  passkey.checkingPasskeyRef.current = false;
8529
8444
  oneTapSetup.oneTapLimitSavedDuringSetupRef.current = false;
8530
8445
  auth.setAuthInput("");
8531
8446
  auth.setOtpCode("");
8532
8447
  dispatch({ type: "LOGOUT", depositAmount });
8533
- }, [logout, polling, depositAmount, auth, sourceSelection, provider, passkey, oneTapSetup]);
8448
+ }, [logout, polling, depositAmount, auth, passkey, oneTapSetup]);
8534
8449
  usePaymentEffects({
8535
8450
  state,
8536
8451
  dispatch,
@@ -8538,7 +8453,6 @@ function BlinkPaymentInner({
8538
8453
  authenticated,
8539
8454
  apiBaseUrl,
8540
8455
  depositAmount,
8541
- useWalletConnectorProp,
8542
8456
  onComplete,
8543
8457
  onError,
8544
8458
  polling,
@@ -8565,22 +8479,24 @@ function BlinkPaymentInner({
8565
8479
  setSelectSourceChainName: sourceSelection.setSelectSourceChainName,
8566
8480
  setSelectSourceTokenSymbol: sourceSelection.setSelectSourceTokenSymbol,
8567
8481
  initializedSelectSourceActionRef: sourceSelection.initializedSelectSourceActionRef,
8568
- preSelectSourceStepRef: sourceSelection.preSelectSourceStepRef,
8569
8482
  oneTapLimitSavedDuringSetupRef: oneTapSetup.oneTapLimitSavedDuringSetupRef,
8570
8483
  handleAuthorizedMobileReturn: mobileFlow.handleAuthorizedMobileReturn
8571
8484
  });
8572
8485
  const autoSelectingRef = react.useRef(false);
8573
8486
  react.useEffect(() => {
8574
- if (state.step !== "wallet-picker" || !state.isGuestFlow || !state.selectedProviderId || !state.activeCredentialId || !authenticated || autoSelectingRef.current) return;
8487
+ if (!state.isGuestFlow || !state.selectedProviderId || !state.activeCredentialId || !authenticated || autoSelectingRef.current || state.transfer != null) return;
8488
+ const hasActive = state.accounts.some((a) => a.wallets.some((w) => w.status === "ACTIVE"));
8489
+ if (hasActive) return;
8575
8490
  autoSelectingRef.current = true;
8576
8491
  provider.handleSelectProvider(state.selectedProviderId).finally(() => {
8577
8492
  autoSelectingRef.current = false;
8578
8493
  });
8579
8494
  }, [
8580
- state.step,
8581
8495
  state.isGuestFlow,
8582
8496
  state.selectedProviderId,
8583
8497
  state.activeCredentialId,
8498
+ state.transfer,
8499
+ state.accounts,
8584
8500
  authenticated,
8585
8501
  provider
8586
8502
  ]);
@@ -8605,7 +8521,7 @@ function BlinkPaymentInner({
8605
8521
  onRetryMobileStatus: mobileFlow.handleRetryMobileStatus,
8606
8522
  onLogout: handleLogout,
8607
8523
  onNewPayment: handleNewPayment,
8608
- onNavigate: (step) => dispatch({ type: "NAVIGATE", step }),
8524
+ onSetUserIntent: (intent) => dispatch({ type: "SET_USER_INTENT", intent }),
8609
8525
  onSetAuthInput: auth.setAuthInput,
8610
8526
  onSetOtpCode: (code) => {
8611
8527
  auth.setOtpCode(code);
@@ -8619,8 +8535,8 @@ function BlinkPaymentInner({
8619
8535
  onSelectAuthorizedToken: provider.handleSelectAuthorizedToken,
8620
8536
  onAuthorizeToken: provider.handleAuthorizeToken,
8621
8537
  onSelectGuestToken: guestTransfer.handleSelectGuestToken,
8622
- onLogin: () => dispatch({ type: "NAVIGATE", step: "login" }),
8623
- onPreauthorize: () => dispatch({ type: "NAVIGATE", step: "login" })
8538
+ onLogin: () => dispatch({ type: "SET_USER_INTENT", intent: null }),
8539
+ onPreauthorize: () => dispatch({ type: "SET_USER_INTENT", intent: null })
8624
8540
  }), [
8625
8541
  auth,
8626
8542
  passkey,
@@ -8643,8 +8559,12 @@ function BlinkPaymentInner({
8643
8559
  pollingTransfer: polling.transfer,
8644
8560
  pollingError: polling.error,
8645
8561
  authExecutorError: authExecutor.error,
8562
+ inlineAuthorizationExecuting: authExecutor.executing,
8646
8563
  transferSigningSigning: transferSigning.signing,
8647
8564
  transferSigningError: transferSigning.error,
8565
+ pendingSelectSource: authExecutor.pendingSelectSource,
8566
+ pendingOneTapSetup: authExecutor.pendingOneTapSetup,
8567
+ oneTapLimitAlreadySaved: oneTapSetup.oneTapLimitSavedDuringSetupRef.current,
8648
8568
  pendingConnections: derived.pendingConnections,
8649
8569
  depositEligibleAccounts: derived.depositEligibleAccounts,
8650
8570
  sourceName: derived.sourceName,
@@ -8705,6 +8625,7 @@ exports.findDevicePasskeyViaPopup = findDevicePasskeyViaPopup;
8705
8625
  exports.getTheme = getTheme;
8706
8626
  exports.lightTheme = lightTheme;
8707
8627
  exports.resolvePasskeyRpId = resolvePasskeyRpId;
8628
+ exports.resolveScreen = resolveScreen;
8708
8629
  exports.useAuthorizationExecutor = useAuthorizationExecutor;
8709
8630
  exports.useBlinkConfig = useBlinkConfig;
8710
8631
  exports.useBlinkDepositAmount = useBlinkDepositAmount;