@swype-org/react-sdk 0.1.272 → 0.1.280

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1856,6 +1856,17 @@ function effectiveMinTransferAmountUsd(depositAmount) {
1856
1856
  }
1857
1857
  function persistMobileFlowState(data) {
1858
1858
  try {
1859
+ console.info("[blink-sdk] persistMobileFlowState", {
1860
+ isGuestPreauth: data.isGuestPreauth ?? false,
1861
+ isGuestCheckout: data.isGuestCheckout ?? false,
1862
+ isReauthorization: data.isReauthorization ?? false,
1863
+ isSetup: data.isSetup,
1864
+ hasGuestSessionToken: !!data.guestSessionToken,
1865
+ hasSessionId: !!data.sessionId,
1866
+ hasAccountId: !!data.accountId,
1867
+ hasTransferId: !!data.transferId,
1868
+ caller: new Error().stack?.split("\n")[2]?.trim()
1869
+ });
1859
1870
  sessionStorage.setItem(MOBILE_FLOW_STORAGE_KEY, JSON.stringify(data));
1860
1871
  } catch {
1861
1872
  }
@@ -1871,6 +1882,10 @@ function loadMobileFlowState() {
1871
1882
  }
1872
1883
  function clearMobileFlowState() {
1873
1884
  try {
1885
+ console.info("[blink-sdk] clearMobileFlowState", {
1886
+ hadState: sessionStorage.getItem(MOBILE_FLOW_STORAGE_KEY) != null,
1887
+ caller: new Error().stack?.split("\n")[2]?.trim()
1888
+ });
1874
1889
  sessionStorage.removeItem(MOBILE_FLOW_STORAGE_KEY);
1875
1890
  } catch {
1876
1891
  }
@@ -2196,6 +2211,25 @@ function resolvePhase(state) {
2196
2211
  } else {
2197
2212
  nextPhase = { step: "wallet-picker", reason: "entry" };
2198
2213
  }
2214
+ if (state.guestPreauthSessionId != null) {
2215
+ console.info("[blink-sdk] resolvePhase (guest preauth context)", {
2216
+ resolvedStep: nextPhase.step,
2217
+ currentStep: currentPhase.step,
2218
+ branchGuestPostPayLogin,
2219
+ branchMobileWalletSetup,
2220
+ branchLoginRequested,
2221
+ branchCompleted,
2222
+ branchKeepGuestPreauthPin,
2223
+ branchGuestSetupComplete,
2224
+ transferStatus: state.transfer?.status ?? null,
2225
+ mobileFlow: state.mobileFlow,
2226
+ deeplinkUri: state.deeplinkUri != null,
2227
+ loginRequested: state.loginRequested,
2228
+ guestPreauthorizing: state.guestPreauthorizing,
2229
+ privyAuthenticated: state.privyAuthenticated,
2230
+ isGuestFlow: state.isGuestFlow
2231
+ });
2232
+ }
2199
2233
  return nextPhase;
2200
2234
  }
2201
2235
 
@@ -2263,6 +2297,30 @@ function paymentReducer(state, action) {
2263
2297
  loginRequested: next.loginRequested
2264
2298
  });
2265
2299
  }
2300
+ if (action.type === "REQUEST_LOGIN") {
2301
+ console.info("[blink-sdk] reducer REQUEST_LOGIN", {
2302
+ resolvedPhase: phase.step,
2303
+ mobileFlow: next.mobileFlow,
2304
+ loginRequested: next.loginRequested,
2305
+ guestPreauthSessionId: next.guestPreauthSessionId,
2306
+ guestPreauthAccountId: next.guestPreauthAccountId,
2307
+ transferStatus: next.transfer?.status ?? null,
2308
+ isGuestFlow: next.isGuestFlow,
2309
+ privyReady: next.privyReady,
2310
+ privyAuthenticated: next.privyAuthenticated
2311
+ });
2312
+ }
2313
+ if (action.type === "MOBILE_SETUP_COMPLETE") {
2314
+ console.info("[blink-sdk] reducer MOBILE_SETUP_COMPLETE", {
2315
+ resolvedPhase: phase.step,
2316
+ mobileFlow: next.mobileFlow,
2317
+ deeplinkUri: next.deeplinkUri,
2318
+ loginRequested: next.loginRequested,
2319
+ guestPreauthSessionId: next.guestPreauthSessionId,
2320
+ transferStatus: next.transfer?.status ?? null,
2321
+ isGuestFlow: next.isGuestFlow
2322
+ });
2323
+ }
2266
2324
  return { ...next, phase };
2267
2325
  }
2268
2326
  function applyAction(state, action) {
@@ -2413,7 +2471,12 @@ function applyAction(state, action) {
2413
2471
  return {
2414
2472
  ...state,
2415
2473
  mobileFlow: true,
2416
- deeplinkUri: action.deeplinkUri
2474
+ deeplinkUri: action.deeplinkUri,
2475
+ ...action.guestTransferId != null && {
2476
+ guestTransferId: action.guestTransferId,
2477
+ guestSessionToken: action.guestSessionToken ?? null,
2478
+ isGuestFlow: true
2479
+ }
2417
2480
  };
2418
2481
  case "MOBILE_SETUP_COMPLETE":
2419
2482
  return {
@@ -2531,6 +2594,7 @@ function applyAction(state, action) {
2531
2594
  mobileFlow: false,
2532
2595
  deeplinkUri: null,
2533
2596
  isGuestFlow: true,
2597
+ guestTransferId: null,
2534
2598
  guestSessionToken: action.guestSessionToken ?? state.guestSessionToken
2535
2599
  };
2536
2600
  case "GUEST_PREAUTH_DETECTED":
@@ -6280,6 +6344,7 @@ function StepRendererContent({
6280
6344
  const {
6281
6345
  pollingTransfer,
6282
6346
  pollingError,
6347
+ guestAccountPollingError,
6283
6348
  authExecutorError,
6284
6349
  transferSigningSigning,
6285
6350
  transferSigningError,
@@ -6395,7 +6460,7 @@ function StepRendererContent({
6395
6460
  deeplinkUri: state.deeplinkUri ?? "",
6396
6461
  loading: !isDesktop ? state.creatingTransfer || !state.deeplinkUri : state.creatingTransfer,
6397
6462
  useDeeplink: !isDesktop,
6398
- error: state.error || (!isDesktop ? pollingError : authExecutorError),
6463
+ error: state.error || guestAccountPollingError || (!isDesktop ? pollingError : authExecutorError),
6399
6464
  onRetryStatus: !isDesktop ? handlers.onRetryMobileStatus : void 0,
6400
6465
  onBack: !isDesktop ? handlers.onBackFromOpenWallet : void 0,
6401
6466
  onLogout: handlers.onLogout
@@ -7199,7 +7264,7 @@ function useSourceSelectionHandlers(dispatch, authExecutor, options) {
7199
7264
  initializedSelectSourceActionRef
7200
7265
  };
7201
7266
  }
7202
- function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, onComplete) {
7267
+ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, guestCheckout, onComplete) {
7203
7268
  const {
7204
7269
  mobileSetupFlowRef,
7205
7270
  handlingMobileReturnRef,
@@ -7210,6 +7275,10 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
7210
7275
  onCompleteRef.current = onComplete;
7211
7276
  const guestPollingActiveRef = react.useRef(false);
7212
7277
  const guestPollingCleanupRef = react.useRef(null);
7278
+ const guestTransferIdRef = react.useRef(guestCheckout.guestTransferId);
7279
+ guestTransferIdRef.current = guestCheckout.guestTransferId;
7280
+ const guestSessionTokenRef = react.useRef(guestCheckout.guestSessionToken);
7281
+ guestSessionTokenRef.current = guestCheckout.guestSessionToken;
7213
7282
  const startGuestPolling = react.useCallback((transferId, guestSessionToken) => {
7214
7283
  if (guestPollingActiveRef.current) return;
7215
7284
  guestPollingActiveRef.current = true;
@@ -7225,14 +7294,12 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
7225
7294
  cancelled = true;
7226
7295
  guestPollingActiveRef.current = false;
7227
7296
  guestPollingCleanupRef.current = null;
7228
- clearMobileFlowState();
7229
7297
  dispatch({ type: "GUEST_TRANSFER_COMPLETED", transfer, guestSessionToken });
7230
7298
  onCompleteRef.current?.(transfer);
7231
7299
  } else if (transfer.status === "FAILED") {
7232
7300
  cancelled = true;
7233
7301
  guestPollingActiveRef.current = false;
7234
7302
  guestPollingCleanupRef.current = null;
7235
- clearMobileFlowState();
7236
7303
  dispatch({ type: "TRANSFER_FAILED", transfer, error: "Transfer failed." });
7237
7304
  }
7238
7305
  } catch {
@@ -7249,20 +7316,26 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
7249
7316
  guestPollingCleanupRef.current = cleanup;
7250
7317
  }, [apiBaseUrl, dispatch]);
7251
7318
  react.useEffect(() => {
7252
- const persisted = loadMobileFlowState();
7253
- if (persisted?.isGuestCheckout && persisted.transferId && persisted.guestSessionToken) {
7254
- startGuestPolling(persisted.transferId, persisted.guestSessionToken);
7319
+ if (guestCheckout.mobileFlow && guestCheckout.isGuestFlow && guestCheckout.guestTransferId && guestCheckout.guestSessionToken) {
7320
+ startGuestPolling(guestCheckout.guestTransferId, guestCheckout.guestSessionToken);
7255
7321
  }
7256
7322
  return () => {
7257
7323
  guestPollingCleanupRef.current?.();
7258
7324
  };
7259
- }, [startGuestPolling]);
7325
+ }, [
7326
+ guestCheckout.mobileFlow,
7327
+ guestCheckout.isGuestFlow,
7328
+ guestCheckout.guestTransferId,
7329
+ guestCheckout.guestSessionToken,
7330
+ startGuestPolling
7331
+ ]);
7260
7332
  react.useEffect(() => {
7261
7333
  const tryStartPolling = () => {
7262
7334
  if (guestPollingActiveRef.current) return;
7263
- const persisted = loadMobileFlowState();
7264
- if (persisted?.isGuestCheckout && persisted.transferId && persisted.guestSessionToken) {
7265
- startGuestPolling(persisted.transferId, persisted.guestSessionToken);
7335
+ const transferId = guestTransferIdRef.current;
7336
+ const token = guestSessionTokenRef.current;
7337
+ if (transferId && token) {
7338
+ startGuestPolling(transferId, token);
7266
7339
  }
7267
7340
  };
7268
7341
  const handleVisibility = () => {
@@ -7406,16 +7479,13 @@ function useProviderHandlers(deps) {
7406
7479
  dispatch({ type: "PAY_ERROR", error: "This wallet is not available on mobile." });
7407
7480
  return;
7408
7481
  }
7409
- persistMobileFlowState({
7410
- transferId: result.id,
7411
- guestSessionToken: result.guestSessionToken,
7412
- isGuestCheckout: true,
7482
+ triggerDeeplink(result.uri);
7483
+ dispatch({
7484
+ type: "MOBILE_DEEPLINK_READY",
7413
7485
  deeplinkUri: result.uri,
7414
- providerId,
7415
- isSetup: false
7486
+ guestTransferId: result.id,
7487
+ guestSessionToken: result.guestSessionToken
7416
7488
  });
7417
- triggerDeeplink(result.uri);
7418
- dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: result.uri });
7419
7489
  } else {
7420
7490
  const account = getAccount(wagmiConfig2);
7421
7491
  if (!account.isConnected) {
@@ -7751,6 +7821,14 @@ function useProviderHandlers(deps) {
7751
7821
  useWalletConnector: useWalletConnectorProp,
7752
7822
  userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
7753
7823
  });
7824
+ console.info("[blink-sdk] handlePreauthorize", {
7825
+ isMobile,
7826
+ useWalletConnectorProp,
7827
+ hasGuestSessionToken: !!guestSessionToken,
7828
+ selectedProviderId,
7829
+ guestTransferId,
7830
+ userAgent: typeof navigator === "undefined" ? null : navigator.userAgent
7831
+ });
7754
7832
  const providerName = providers.find((p) => p.id === selectedProviderId)?.name ?? "Wallet";
7755
7833
  if (!isMobile) {
7756
7834
  dispatch({ type: "GUEST_PREAUTH_BEGIN" });
@@ -8172,7 +8250,8 @@ function usePasskeyCheckEffect(deps) {
8172
8250
  setupAccountIdRef,
8173
8251
  reauthSessionIdRef,
8174
8252
  reauthTokenRef,
8175
- pollingTransferIdRef
8253
+ pollingTransferIdRef,
8254
+ startGuestAccountPolling
8176
8255
  } = deps;
8177
8256
  const { getAccessToken } = reactAuth.usePrivy();
8178
8257
  const onCompleteRef = react.useRef(deps.onComplete);
@@ -8195,8 +8274,23 @@ function usePasskeyCheckEffect(deps) {
8195
8274
  dispatch({ type: "SET_ERROR", error: null });
8196
8275
  setAuthInput("");
8197
8276
  setOtpCode("");
8277
+ const startGuestAccountPollingRef = startGuestAccountPolling;
8198
8278
  const restoreState = async (credId, token) => {
8199
8279
  const persisted = loadMobileFlowState();
8280
+ if (persisted?.isGuestPreauth && persisted.guestSessionToken && persisted.sessionId) {
8281
+ mobileSetupFlowRef.current = true;
8282
+ if (persisted.accountId) {
8283
+ setupAccountIdRef.current = persisted.accountId;
8284
+ dispatch({
8285
+ type: "GUEST_PREAUTH_DETECTED",
8286
+ accountId: persisted.accountId,
8287
+ sessionId: persisted.sessionId
8288
+ });
8289
+ }
8290
+ dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: persisted.deeplinkUri });
8291
+ startGuestAccountPollingRef(persisted.guestSessionToken, persisted.sessionId);
8292
+ return;
8293
+ }
8200
8294
  let accts = [];
8201
8295
  try {
8202
8296
  accts = await fetchAccounts(apiBaseUrl, token, credId);
@@ -8845,10 +8939,24 @@ function useGuestPreauthMobileRestoreEffect(deps) {
8845
8939
  } = deps;
8846
8940
  const startedRef = react.useRef(false);
8847
8941
  react.useEffect(() => {
8848
- if (!privyReady) return;
8849
- const tryStart = () => {
8850
- if (startedRef.current) return;
8942
+ if (!privyReady) {
8943
+ console.info("[blink-sdk] guestPreauthMobileRestore: skipping, privyReady=false");
8944
+ return;
8945
+ }
8946
+ const tryStart = (trigger) => {
8947
+ if (startedRef.current) {
8948
+ console.info("[blink-sdk] guestPreauthMobileRestore.tryStart: already started", { trigger });
8949
+ return;
8950
+ }
8851
8951
  const persisted = loadMobileFlowState();
8952
+ console.info("[blink-sdk] guestPreauthMobileRestore.tryStart", {
8953
+ trigger,
8954
+ hasPersistedState: !!persisted,
8955
+ isGuestPreauth: persisted?.isGuestPreauth ?? false,
8956
+ hasGuestSessionToken: !!persisted?.guestSessionToken,
8957
+ hasSessionId: !!persisted?.sessionId,
8958
+ accountId: persisted?.accountId ?? null
8959
+ });
8852
8960
  if (!persisted?.isGuestPreauth || !persisted.guestSessionToken || !persisted.sessionId) {
8853
8961
  return;
8854
8962
  }
@@ -8868,15 +8976,28 @@ function useGuestPreauthMobileRestoreEffect(deps) {
8868
8976
  type: "MOBILE_DEEPLINK_READY",
8869
8977
  deeplinkUri: persisted.deeplinkUri
8870
8978
  });
8979
+ console.info("[blink-sdk] guestPreauthMobileRestore: starting guest account polling", {
8980
+ trigger,
8981
+ sessionId: persisted.sessionId
8982
+ });
8871
8983
  startGuestAccountPolling(persisted.guestSessionToken, persisted.sessionId);
8872
8984
  };
8873
8985
  const onVisibility = () => {
8874
- if (document.visibilityState === "visible") tryStart();
8986
+ console.info("[blink-sdk] guestPreauthMobileRestore: visibilitychange fired", {
8987
+ visibilityState: document.visibilityState,
8988
+ startedRef: startedRef.current
8989
+ });
8990
+ if (document.visibilityState === "visible") tryStart("visibilitychange");
8875
8991
  };
8876
- const onPageShow = () => {
8877
- if (document.visibilityState === "visible") tryStart();
8992
+ const onPageShow = (e) => {
8993
+ console.info("[blink-sdk] guestPreauthMobileRestore: pageshow fired", {
8994
+ persisted: e.persisted,
8995
+ visibilityState: document.visibilityState,
8996
+ startedRef: startedRef.current
8997
+ });
8998
+ if (document.visibilityState === "visible") tryStart("pageshow");
8878
8999
  };
8879
- tryStart();
9000
+ tryStart("initial");
8880
9001
  document.addEventListener("visibilitychange", onVisibility);
8881
9002
  window.addEventListener("pageshow", onPageShow);
8882
9003
  return () => {
@@ -9144,16 +9265,37 @@ function useGuestPreauthWalletSetupEffect(deps) {
9144
9265
  dispatch
9145
9266
  ]);
9146
9267
  }
9268
+ function useGuestAccountAutoPollingEffect(deps) {
9269
+ const {
9270
+ mobileFlow,
9271
+ isGuestFlow,
9272
+ guestSessionToken,
9273
+ isPolling,
9274
+ guestAccount,
9275
+ startPolling
9276
+ } = deps;
9277
+ react.useEffect(() => {
9278
+ if (!mobileFlow || !isGuestFlow || !guestSessionToken) return;
9279
+ if (isPolling || guestAccount) return;
9280
+ startPolling(guestSessionToken);
9281
+ }, [mobileFlow, isGuestFlow, guestSessionToken, isPolling, guestAccount, startPolling]);
9282
+ }
9147
9283
  function useGuestAccountPolling(intervalMs = 3e3) {
9148
9284
  const { apiBaseUrl } = useBlinkConfig();
9149
9285
  const [guestAccount, setGuestAccount] = react.useState(null);
9150
9286
  const [isPolling, setIsPolling] = react.useState(false);
9287
+ const [error, setError] = react.useState(null);
9288
+ const consecutiveFailuresRef = react.useRef(0);
9151
9289
  const intervalRef = react.useRef(null);
9152
9290
  const guestTokenRef = react.useRef(null);
9153
9291
  const sessionIdRef = react.useRef(null);
9154
9292
  const apiBaseUrlRef = react.useRef(apiBaseUrl);
9155
9293
  apiBaseUrlRef.current = apiBaseUrl;
9156
9294
  const stopPolling = react.useCallback(() => {
9295
+ console.info("[blink-sdk] useGuestAccountPolling.stopPolling called", {
9296
+ hadInterval: !!intervalRef.current,
9297
+ hadToken: !!guestTokenRef.current
9298
+ });
9157
9299
  if (intervalRef.current) {
9158
9300
  clearInterval(intervalRef.current);
9159
9301
  intervalRef.current = null;
@@ -9165,29 +9307,70 @@ function useGuestAccountPolling(intervalMs = 3e3) {
9165
9307
  const poll = react.useCallback(async () => {
9166
9308
  const token = guestTokenRef.current;
9167
9309
  const sessionId = sessionIdRef.current;
9168
- if (!token || !sessionId) return;
9310
+ if (!token) {
9311
+ console.info("[blink-sdk] useGuestAccountPolling.poll skipped (no token)");
9312
+ return;
9313
+ }
9314
+ console.info("[blink-sdk] useGuestAccountPolling.poll executing", {
9315
+ apiBaseUrl: apiBaseUrlRef.current,
9316
+ tokenPrefix: token.slice(0, 8),
9317
+ sessionId: sessionId ?? "(none \u2014 account-only mode)"
9318
+ });
9169
9319
  try {
9170
9320
  const lookup = await fetchGuestAccount(apiBaseUrlRef.current, token);
9171
9321
  if (!guestTokenRef.current) return;
9172
- if (lookup == null) return;
9322
+ consecutiveFailuresRef.current = 0;
9323
+ setError(null);
9324
+ if (lookup == null) {
9325
+ console.info("[blink-sdk] useGuestAccountPolling.poll: account not found yet");
9326
+ return;
9327
+ }
9328
+ if (!sessionId) {
9329
+ console.info("[blink-sdk] useGuestAccountPolling.poll: COMPLETE \u2014 account found (no session check)");
9330
+ setGuestAccount(lookup);
9331
+ stopPolling();
9332
+ return;
9333
+ }
9334
+ console.info("[blink-sdk] useGuestAccountPolling.poll: account found, checking session");
9173
9335
  try {
9174
9336
  const session = await fetchAuthorizationSession(apiBaseUrlRef.current, sessionId);
9175
9337
  if (!guestTokenRef.current) return;
9176
- if (session.status !== "AUTHORIZED") return;
9177
- } catch {
9338
+ if (session.status !== "AUTHORIZED") {
9339
+ console.info("[blink-sdk] useGuestAccountPolling.poll: session not AUTHORIZED yet", session.status);
9340
+ return;
9341
+ }
9342
+ } catch (sessionErr) {
9343
+ consecutiveFailuresRef.current += 1;
9344
+ console.info("[blink-sdk] useGuestAccountPolling.poll: session fetch failed", sessionErr);
9345
+ if (consecutiveFailuresRef.current >= 3) {
9346
+ setError(sessionErr instanceof Error ? sessionErr.message : "Failed to check authorization status");
9347
+ }
9178
9348
  return;
9179
9349
  }
9350
+ console.info("[blink-sdk] useGuestAccountPolling.poll: COMPLETE \u2014 account + AUTHORIZED");
9180
9351
  setGuestAccount(lookup);
9181
9352
  stopPolling();
9182
- } catch {
9353
+ } catch (err) {
9354
+ consecutiveFailuresRef.current += 1;
9355
+ console.info("[blink-sdk] useGuestAccountPolling.poll: fetch error, will retry", err);
9356
+ if (consecutiveFailuresRef.current >= 3) {
9357
+ setError(err instanceof Error ? err.message : "Failed to check account status");
9358
+ }
9183
9359
  }
9184
9360
  }, [stopPolling]);
9185
9361
  const startPolling = react.useCallback(
9186
9362
  (guestToken, sessionId) => {
9363
+ console.info("[blink-sdk] useGuestAccountPolling.startPolling called", {
9364
+ tokenPrefix: guestToken.slice(0, 8),
9365
+ sessionId: sessionId ?? "(none \u2014 account-only mode)",
9366
+ intervalMs
9367
+ });
9187
9368
  stopPolling();
9188
9369
  guestTokenRef.current = guestToken;
9189
- sessionIdRef.current = sessionId;
9370
+ sessionIdRef.current = sessionId ?? null;
9190
9371
  setGuestAccount(null);
9372
+ setError(null);
9373
+ consecutiveFailuresRef.current = 0;
9191
9374
  setIsPolling(true);
9192
9375
  poll();
9193
9376
  intervalRef.current = setInterval(poll, intervalMs);
@@ -9196,11 +9379,22 @@ function useGuestAccountPolling(intervalMs = 3e3) {
9196
9379
  );
9197
9380
  react.useEffect(() => {
9198
9381
  const handleVisibility = () => {
9382
+ console.info("[blink-sdk] useGuestAccountPolling: visibilitychange fired", {
9383
+ visibilityState: document.visibilityState,
9384
+ hasToken: !!guestTokenRef.current,
9385
+ hasSessionId: !!sessionIdRef.current
9386
+ });
9199
9387
  if (document.visibilityState === "visible" && guestTokenRef.current) {
9200
9388
  void poll();
9201
9389
  }
9202
9390
  };
9203
- const handlePageShow = () => {
9391
+ const handlePageShow = (e) => {
9392
+ console.info("[blink-sdk] useGuestAccountPolling: pageshow fired", {
9393
+ persisted: e.persisted,
9394
+ visibilityState: document.visibilityState,
9395
+ hasToken: !!guestTokenRef.current,
9396
+ hasSessionId: !!sessionIdRef.current
9397
+ });
9204
9398
  if (document.visibilityState === "visible" && guestTokenRef.current) {
9205
9399
  void poll();
9206
9400
  }
@@ -9213,7 +9407,7 @@ function useGuestAccountPolling(intervalMs = 3e3) {
9213
9407
  };
9214
9408
  }, [poll]);
9215
9409
  react.useEffect(() => () => stopPolling(), [stopPolling]);
9216
- return { guestAccount, isPolling, startPolling, stopPolling };
9410
+ return { guestAccount, error, isPolling, startPolling, stopPolling };
9217
9411
  }
9218
9412
  function BlinkPayment(props) {
9219
9413
  const resetKey = react.useRef(0);
@@ -9296,6 +9490,12 @@ function BlinkPaymentInner({
9296
9490
  transfer.pollingTransferIdRef,
9297
9491
  state.transfer,
9298
9492
  mobileFlowRefs,
9493
+ {
9494
+ mobileFlow: state.mobileFlow,
9495
+ isGuestFlow: state.isGuestFlow,
9496
+ guestTransferId: state.guestTransferId,
9497
+ guestSessionToken: state.guestSessionToken
9498
+ },
9299
9499
  onComplete
9300
9500
  );
9301
9501
  const sourceSelection = useSourceSelectionHandlers(dispatch, authExecutor, {
@@ -9400,10 +9600,50 @@ function BlinkPaymentInner({
9400
9600
  setupAccountIdRef: mobileFlowRefs.setupAccountIdRef,
9401
9601
  startGuestAccountPolling: guestAccountPolling.startPolling
9402
9602
  });
9603
+ useGuestAccountAutoPollingEffect({
9604
+ mobileFlow: state.mobileFlow,
9605
+ isGuestFlow: state.isGuestFlow,
9606
+ guestSessionToken: state.guestSessionToken,
9607
+ isPolling: guestAccountPolling.isPolling,
9608
+ guestAccount: guestAccountPolling.guestAccount,
9609
+ startPolling: guestAccountPolling.startPolling
9610
+ });
9611
+ const guestSessionTokenRef = react.useRef(state.guestSessionToken);
9612
+ guestSessionTokenRef.current = state.guestSessionToken;
9613
+ const guestPreauthSessionIdRef = react.useRef(state.guestPreauthSessionId);
9614
+ guestPreauthSessionIdRef.current = state.guestPreauthSessionId;
9615
+ react.useEffect(() => {
9616
+ const handleVisibility = () => {
9617
+ if (document.visibilityState !== "visible") return;
9618
+ const token = guestSessionTokenRef.current;
9619
+ const sessionId = guestPreauthSessionIdRef.current;
9620
+ if (!token) return;
9621
+ if (guestAccountPolling.isPolling || guestAccountPolling.guestAccount) return;
9622
+ console.info("[blink-sdk] warm-return: restarting guest account polling from React state", {
9623
+ sessionId: sessionId ?? "(none \u2014 account-only mode)"
9624
+ });
9625
+ guestAccountPolling.startPolling(token, sessionId ?? void 0);
9626
+ };
9627
+ document.addEventListener("visibilitychange", handleVisibility);
9628
+ return () => document.removeEventListener("visibilitychange", handleVisibility);
9629
+ }, [guestAccountPolling.isPolling, guestAccountPolling.guestAccount, guestAccountPolling.startPolling]);
9403
9630
  react.useEffect(() => {
9631
+ console.info("[blink-sdk] guestPreauthCompletion effect", {
9632
+ hasGuestAccount: !!guestAccountPolling.guestAccount,
9633
+ guestAccountId: guestAccountPolling.guestAccount?.accountId ?? null,
9634
+ currentPreauthAccountId: state.guestPreauthAccountId,
9635
+ currentPhase: state.phase.step,
9636
+ mobileFlow: state.mobileFlow,
9637
+ loginRequested: state.loginRequested
9638
+ });
9404
9639
  if (!guestAccountPolling.guestAccount) return;
9405
9640
  const acct = guestAccountPolling.guestAccount;
9406
- if (acct.accountId !== state.guestPreauthAccountId) {
9641
+ const needsDetect = acct.accountId !== state.guestPreauthAccountId;
9642
+ console.info("[blink-sdk] guestPreauthCompletion: dispatching REQUEST_LOGIN + MOBILE_SETUP_COMPLETE", {
9643
+ accountId: acct.accountId,
9644
+ dispatchingGuestPreauthDetected: needsDetect
9645
+ });
9646
+ if (needsDetect) {
9407
9647
  dispatch({
9408
9648
  type: "GUEST_PREAUTH_DETECTED",
9409
9649
  accountId: acct.accountId,
@@ -9445,7 +9685,8 @@ function BlinkPaymentInner({
9445
9685
  reauthTokenRef: mobileFlowRefs.reauthTokenRef,
9446
9686
  pollingTransferIdRef: transfer.pollingTransferIdRef,
9447
9687
  handleAuthorizedMobileReturn: mobileFlow.handleAuthorizedMobileReturn,
9448
- onComplete
9688
+ onComplete,
9689
+ startGuestAccountPolling: guestAccountPolling.startPolling
9449
9690
  });
9450
9691
  useDataLoadEffect({
9451
9692
  state,
@@ -9592,6 +9833,7 @@ function BlinkPaymentInner({
9592
9833
  remote: {
9593
9834
  pollingTransfer: polling.transfer,
9594
9835
  pollingError: polling.error,
9836
+ guestAccountPollingError: guestAccountPolling.error,
9595
9837
  authExecutorError: authExecutor.error,
9596
9838
  transferSigningSigning: transferSigning.signing,
9597
9839
  transferSigningError: transferSigning.error,