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