@swype-org/react-sdk 0.1.271 → 0.1.277

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
@@ -1853,6 +1853,17 @@ function effectiveMinTransferAmountUsd(depositAmount) {
1853
1853
  }
1854
1854
  function persistMobileFlowState(data) {
1855
1855
  try {
1856
+ console.info("[blink-sdk] persistMobileFlowState", {
1857
+ isGuestPreauth: data.isGuestPreauth ?? false,
1858
+ isGuestCheckout: data.isGuestCheckout ?? false,
1859
+ isReauthorization: data.isReauthorization ?? false,
1860
+ isSetup: data.isSetup,
1861
+ hasGuestSessionToken: !!data.guestSessionToken,
1862
+ hasSessionId: !!data.sessionId,
1863
+ hasAccountId: !!data.accountId,
1864
+ hasTransferId: !!data.transferId,
1865
+ caller: new Error().stack?.split("\n")[2]?.trim()
1866
+ });
1856
1867
  sessionStorage.setItem(MOBILE_FLOW_STORAGE_KEY, JSON.stringify(data));
1857
1868
  } catch {
1858
1869
  }
@@ -1868,6 +1879,10 @@ function loadMobileFlowState() {
1868
1879
  }
1869
1880
  function clearMobileFlowState() {
1870
1881
  try {
1882
+ console.info("[blink-sdk] clearMobileFlowState", {
1883
+ hadState: sessionStorage.getItem(MOBILE_FLOW_STORAGE_KEY) != null,
1884
+ caller: new Error().stack?.split("\n")[2]?.trim()
1885
+ });
1871
1886
  sessionStorage.removeItem(MOBILE_FLOW_STORAGE_KEY);
1872
1887
  } catch {
1873
1888
  }
@@ -2193,6 +2208,25 @@ function resolvePhase(state) {
2193
2208
  } else {
2194
2209
  nextPhase = { step: "wallet-picker", reason: "entry" };
2195
2210
  }
2211
+ if (state.guestPreauthSessionId != null) {
2212
+ console.info("[blink-sdk] resolvePhase (guest preauth context)", {
2213
+ resolvedStep: nextPhase.step,
2214
+ currentStep: currentPhase.step,
2215
+ branchGuestPostPayLogin,
2216
+ branchMobileWalletSetup,
2217
+ branchLoginRequested,
2218
+ branchCompleted,
2219
+ branchKeepGuestPreauthPin,
2220
+ branchGuestSetupComplete,
2221
+ transferStatus: state.transfer?.status ?? null,
2222
+ mobileFlow: state.mobileFlow,
2223
+ deeplinkUri: state.deeplinkUri != null,
2224
+ loginRequested: state.loginRequested,
2225
+ guestPreauthorizing: state.guestPreauthorizing,
2226
+ privyAuthenticated: state.privyAuthenticated,
2227
+ isGuestFlow: state.isGuestFlow
2228
+ });
2229
+ }
2196
2230
  return nextPhase;
2197
2231
  }
2198
2232
 
@@ -2260,6 +2294,30 @@ function paymentReducer(state, action) {
2260
2294
  loginRequested: next.loginRequested
2261
2295
  });
2262
2296
  }
2297
+ if (action.type === "REQUEST_LOGIN") {
2298
+ console.info("[blink-sdk] reducer REQUEST_LOGIN", {
2299
+ resolvedPhase: phase.step,
2300
+ mobileFlow: next.mobileFlow,
2301
+ loginRequested: next.loginRequested,
2302
+ guestPreauthSessionId: next.guestPreauthSessionId,
2303
+ guestPreauthAccountId: next.guestPreauthAccountId,
2304
+ transferStatus: next.transfer?.status ?? null,
2305
+ isGuestFlow: next.isGuestFlow,
2306
+ privyReady: next.privyReady,
2307
+ privyAuthenticated: next.privyAuthenticated
2308
+ });
2309
+ }
2310
+ if (action.type === "MOBILE_SETUP_COMPLETE") {
2311
+ console.info("[blink-sdk] reducer MOBILE_SETUP_COMPLETE", {
2312
+ resolvedPhase: phase.step,
2313
+ mobileFlow: next.mobileFlow,
2314
+ deeplinkUri: next.deeplinkUri,
2315
+ loginRequested: next.loginRequested,
2316
+ guestPreauthSessionId: next.guestPreauthSessionId,
2317
+ transferStatus: next.transfer?.status ?? null,
2318
+ isGuestFlow: next.isGuestFlow
2319
+ });
2320
+ }
2263
2321
  return { ...next, phase };
2264
2322
  }
2265
2323
  function applyAction(state, action) {
@@ -2410,7 +2468,12 @@ function applyAction(state, action) {
2410
2468
  return {
2411
2469
  ...state,
2412
2470
  mobileFlow: true,
2413
- deeplinkUri: action.deeplinkUri
2471
+ deeplinkUri: action.deeplinkUri,
2472
+ ...action.guestTransferId != null && {
2473
+ guestTransferId: action.guestTransferId,
2474
+ guestSessionToken: action.guestSessionToken ?? null,
2475
+ isGuestFlow: true
2476
+ }
2414
2477
  };
2415
2478
  case "MOBILE_SETUP_COMPLETE":
2416
2479
  return {
@@ -2528,6 +2591,7 @@ function applyAction(state, action) {
2528
2591
  mobileFlow: false,
2529
2592
  deeplinkUri: null,
2530
2593
  isGuestFlow: true,
2594
+ guestTransferId: null,
2531
2595
  guestSessionToken: action.guestSessionToken ?? state.guestSessionToken
2532
2596
  };
2533
2597
  case "GUEST_PREAUTH_DETECTED":
@@ -7196,7 +7260,7 @@ function useSourceSelectionHandlers(dispatch, authExecutor, options) {
7196
7260
  initializedSelectSourceActionRef
7197
7261
  };
7198
7262
  }
7199
- function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, onComplete) {
7263
+ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, guestCheckout, onComplete) {
7200
7264
  const {
7201
7265
  mobileSetupFlowRef,
7202
7266
  handlingMobileReturnRef,
@@ -7207,6 +7271,10 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
7207
7271
  onCompleteRef.current = onComplete;
7208
7272
  const guestPollingActiveRef = useRef(false);
7209
7273
  const guestPollingCleanupRef = useRef(null);
7274
+ const guestTransferIdRef = useRef(guestCheckout.guestTransferId);
7275
+ guestTransferIdRef.current = guestCheckout.guestTransferId;
7276
+ const guestSessionTokenRef = useRef(guestCheckout.guestSessionToken);
7277
+ guestSessionTokenRef.current = guestCheckout.guestSessionToken;
7210
7278
  const startGuestPolling = useCallback((transferId, guestSessionToken) => {
7211
7279
  if (guestPollingActiveRef.current) return;
7212
7280
  guestPollingActiveRef.current = true;
@@ -7222,14 +7290,12 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
7222
7290
  cancelled = true;
7223
7291
  guestPollingActiveRef.current = false;
7224
7292
  guestPollingCleanupRef.current = null;
7225
- clearMobileFlowState();
7226
7293
  dispatch({ type: "GUEST_TRANSFER_COMPLETED", transfer, guestSessionToken });
7227
7294
  onCompleteRef.current?.(transfer);
7228
7295
  } else if (transfer.status === "FAILED") {
7229
7296
  cancelled = true;
7230
7297
  guestPollingActiveRef.current = false;
7231
7298
  guestPollingCleanupRef.current = null;
7232
- clearMobileFlowState();
7233
7299
  dispatch({ type: "TRANSFER_FAILED", transfer, error: "Transfer failed." });
7234
7300
  }
7235
7301
  } catch {
@@ -7246,20 +7312,26 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
7246
7312
  guestPollingCleanupRef.current = cleanup;
7247
7313
  }, [apiBaseUrl, dispatch]);
7248
7314
  useEffect(() => {
7249
- const persisted = loadMobileFlowState();
7250
- if (persisted?.isGuestCheckout && persisted.transferId && persisted.guestSessionToken) {
7251
- startGuestPolling(persisted.transferId, persisted.guestSessionToken);
7315
+ if (guestCheckout.mobileFlow && guestCheckout.isGuestFlow && guestCheckout.guestTransferId && guestCheckout.guestSessionToken) {
7316
+ startGuestPolling(guestCheckout.guestTransferId, guestCheckout.guestSessionToken);
7252
7317
  }
7253
7318
  return () => {
7254
7319
  guestPollingCleanupRef.current?.();
7255
7320
  };
7256
- }, [startGuestPolling]);
7321
+ }, [
7322
+ guestCheckout.mobileFlow,
7323
+ guestCheckout.isGuestFlow,
7324
+ guestCheckout.guestTransferId,
7325
+ guestCheckout.guestSessionToken,
7326
+ startGuestPolling
7327
+ ]);
7257
7328
  useEffect(() => {
7258
7329
  const tryStartPolling = () => {
7259
7330
  if (guestPollingActiveRef.current) return;
7260
- const persisted = loadMobileFlowState();
7261
- if (persisted?.isGuestCheckout && persisted.transferId && persisted.guestSessionToken) {
7262
- startGuestPolling(persisted.transferId, persisted.guestSessionToken);
7331
+ const transferId = guestTransferIdRef.current;
7332
+ const token = guestSessionTokenRef.current;
7333
+ if (transferId && token) {
7334
+ startGuestPolling(transferId, token);
7263
7335
  }
7264
7336
  };
7265
7337
  const handleVisibility = () => {
@@ -7339,7 +7411,8 @@ function useProviderHandlers(deps) {
7339
7411
  destination,
7340
7412
  guestSessionToken,
7341
7413
  guestTransferId,
7342
- selectedProviderId
7414
+ selectedProviderId,
7415
+ startGuestAccountPolling
7343
7416
  } = deps;
7344
7417
  const wagmiConfig2 = useConfig();
7345
7418
  const { connectAsync, connectors } = useConnect();
@@ -7402,16 +7475,13 @@ function useProviderHandlers(deps) {
7402
7475
  dispatch({ type: "PAY_ERROR", error: "This wallet is not available on mobile." });
7403
7476
  return;
7404
7477
  }
7405
- persistMobileFlowState({
7406
- transferId: result.id,
7407
- guestSessionToken: result.guestSessionToken,
7408
- isGuestCheckout: true,
7478
+ triggerDeeplink(result.uri);
7479
+ dispatch({
7480
+ type: "MOBILE_DEEPLINK_READY",
7409
7481
  deeplinkUri: result.uri,
7410
- providerId,
7411
- isSetup: false
7482
+ guestTransferId: result.id,
7483
+ guestSessionToken: result.guestSessionToken
7412
7484
  });
7413
- triggerDeeplink(result.uri);
7414
- dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: result.uri });
7415
7485
  } else {
7416
7486
  const account = getAccount(wagmiConfig2);
7417
7487
  if (!account.isConnected) {
@@ -7747,6 +7817,14 @@ function useProviderHandlers(deps) {
7747
7817
  useWalletConnector: useWalletConnectorProp,
7748
7818
  userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
7749
7819
  });
7820
+ console.info("[blink-sdk] handlePreauthorize", {
7821
+ isMobile,
7822
+ useWalletConnectorProp,
7823
+ hasGuestSessionToken: !!guestSessionToken,
7824
+ selectedProviderId,
7825
+ guestTransferId,
7826
+ userAgent: typeof navigator === "undefined" ? null : navigator.userAgent
7827
+ });
7750
7828
  const providerName = providers.find((p) => p.id === selectedProviderId)?.name ?? "Wallet";
7751
7829
  if (!isMobile) {
7752
7830
  dispatch({ type: "GUEST_PREAUTH_BEGIN" });
@@ -7779,6 +7857,7 @@ function useProviderHandlers(deps) {
7779
7857
  triggerDeeplink(created.sessionUri);
7780
7858
  dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: created.sessionUri });
7781
7859
  }
7860
+ startGuestAccountPolling(guestSessionToken, session.id);
7782
7861
  dispatch({
7783
7862
  type: "GUEST_PREAUTH_DETECTED",
7784
7863
  accountId: created.accountId,
@@ -7806,7 +7885,8 @@ function useProviderHandlers(deps) {
7806
7885
  useWalletConnectorProp,
7807
7886
  mobileSetupFlowRef,
7808
7887
  handlingMobileReturnRef,
7809
- setupAccountIdRef
7888
+ setupAccountIdRef,
7889
+ startGuestAccountPolling
7810
7890
  ]);
7811
7891
  return {
7812
7892
  handlePrepareProvider,
@@ -8166,7 +8246,8 @@ function usePasskeyCheckEffect(deps) {
8166
8246
  setupAccountIdRef,
8167
8247
  reauthSessionIdRef,
8168
8248
  reauthTokenRef,
8169
- pollingTransferIdRef
8249
+ pollingTransferIdRef,
8250
+ startGuestAccountPolling
8170
8251
  } = deps;
8171
8252
  const { getAccessToken } = usePrivy();
8172
8253
  const onCompleteRef = useRef(deps.onComplete);
@@ -8189,8 +8270,23 @@ function usePasskeyCheckEffect(deps) {
8189
8270
  dispatch({ type: "SET_ERROR", error: null });
8190
8271
  setAuthInput("");
8191
8272
  setOtpCode("");
8273
+ const startGuestAccountPollingRef = startGuestAccountPolling;
8192
8274
  const restoreState = async (credId, token) => {
8193
8275
  const persisted = loadMobileFlowState();
8276
+ if (persisted?.isGuestPreauth && persisted.guestSessionToken && persisted.sessionId) {
8277
+ mobileSetupFlowRef.current = true;
8278
+ if (persisted.accountId) {
8279
+ setupAccountIdRef.current = persisted.accountId;
8280
+ dispatch({
8281
+ type: "GUEST_PREAUTH_DETECTED",
8282
+ accountId: persisted.accountId,
8283
+ sessionId: persisted.sessionId
8284
+ });
8285
+ }
8286
+ dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: persisted.deeplinkUri });
8287
+ startGuestAccountPollingRef(persisted.guestSessionToken, persisted.sessionId);
8288
+ return;
8289
+ }
8194
8290
  let accts = [];
8195
8291
  try {
8196
8292
  accts = await fetchAccounts(apiBaseUrl, token, credId);
@@ -8691,100 +8787,6 @@ function useMobilePollingEffect(deps) {
8691
8787
  handlingMobileReturnRef,
8692
8788
  mobileSetupFlowRef
8693
8789
  ]);
8694
- useEffect(() => {
8695
- if (!state.mobileFlow || !state.isGuestFlow || !state.guestPreauthSessionId || !state.guestPreauthAccountId) {
8696
- return;
8697
- }
8698
- const guestToken = state.guestSessionToken ?? loadMobileFlowState()?.guestSessionToken ?? null;
8699
- const preauthAccountId = state.guestPreauthAccountId;
8700
- const preauthSessionId = state.guestPreauthSessionId;
8701
- let cancelled = false;
8702
- let completedGuestPreauth = false;
8703
- const POLL_INTERVAL_MS = 3e3;
8704
- const finishMobileAndDispatch = async () => {
8705
- mobileSetupFlowRef.current = false;
8706
- setupAccountIdRef.current = null;
8707
- try {
8708
- await reloadAccounts();
8709
- } catch {
8710
- }
8711
- };
8712
- const completeGuestPreauthWithoutToken = async () => {
8713
- if (completedGuestPreauth) return;
8714
- completedGuestPreauth = true;
8715
- cancelled = true;
8716
- await finishMobileAndDispatch();
8717
- clearMobileFlowState();
8718
- dispatch({ type: "MOBILE_SETUP_COMPLETE" });
8719
- };
8720
- const completeGuestPreauthWithAccount = async (guestLookup) => {
8721
- if (completedGuestPreauth) return;
8722
- completedGuestPreauth = true;
8723
- cancelled = true;
8724
- await finishMobileAndDispatch();
8725
- if (guestLookup.accountId !== preauthAccountId) {
8726
- dispatch({
8727
- type: "GUEST_PREAUTH_DETECTED",
8728
- accountId: guestLookup.accountId,
8729
- sessionId: preauthSessionId ?? void 0
8730
- });
8731
- }
8732
- dispatch({ type: "REQUEST_LOGIN" });
8733
- dispatch({ type: "MOBILE_SETUP_COMPLETE" });
8734
- };
8735
- const pollGuestAccount = async () => {
8736
- try {
8737
- if (cancelled) return;
8738
- if (!guestToken) {
8739
- await completeGuestPreauthWithoutToken();
8740
- return;
8741
- }
8742
- const guestLookup = await fetchGuestAccount(apiBaseUrl, guestToken);
8743
- if (cancelled) return;
8744
- if (guestLookup != null) {
8745
- if (preauthSessionId) {
8746
- try {
8747
- const session = await fetchAuthorizationSession(
8748
- apiBaseUrl,
8749
- preauthSessionId
8750
- );
8751
- if (cancelled) return;
8752
- if (session.status !== "AUTHORIZED") return;
8753
- } catch {
8754
- return;
8755
- }
8756
- }
8757
- await completeGuestPreauthWithAccount(guestLookup);
8758
- }
8759
- } catch {
8760
- }
8761
- };
8762
- pollGuestAccount();
8763
- const intervalId = window.setInterval(pollGuestAccount, POLL_INTERVAL_MS);
8764
- const handleVisibility = () => {
8765
- if (document.visibilityState === "visible" && !cancelled) void pollGuestAccount();
8766
- };
8767
- const handlePageShow = () => {
8768
- if (document.visibilityState === "visible" && !cancelled) void pollGuestAccount();
8769
- };
8770
- document.addEventListener("visibilitychange", handleVisibility);
8771
- window.addEventListener("pageshow", handlePageShow);
8772
- return () => {
8773
- cancelled = true;
8774
- window.clearInterval(intervalId);
8775
- document.removeEventListener("visibilitychange", handleVisibility);
8776
- window.removeEventListener("pageshow", handlePageShow);
8777
- };
8778
- }, [
8779
- state.mobileFlow,
8780
- state.guestPreauthSessionId,
8781
- state.isGuestFlow,
8782
- state.guestSessionToken,
8783
- state.guestPreauthAccountId,
8784
- apiBaseUrl,
8785
- reloadAccounts,
8786
- dispatch
8787
- ]);
8788
8790
  useEffect(() => {
8789
8791
  if (!state.mobileFlow || !mobileSetupFlowRef.current) return;
8790
8792
  if (state.isGuestFlow && state.guestPreauthSessionId != null) return;
@@ -8923,106 +8925,82 @@ function useMobilePollingEffect(deps) {
8923
8925
  pollingTransferIdRef
8924
8926
  ]);
8925
8927
  }
8926
- var guestPreauthRestoreAttemptedKeys = /* @__PURE__ */ new Set();
8927
- function guestPreauthRestoreKey(guestToken) {
8928
- return guestToken;
8929
- }
8930
8928
  function useGuestPreauthMobileRestoreEffect(deps) {
8931
- const { dispatch, apiBaseUrl, privyReady, mobileSetupFlowRef, setupAccountIdRef } = deps;
8932
- const completedRef = useRef(false);
8933
- const pollingCleanupRef = useRef(null);
8929
+ const {
8930
+ dispatch,
8931
+ privyReady,
8932
+ mobileSetupFlowRef,
8933
+ setupAccountIdRef,
8934
+ startGuestAccountPolling
8935
+ } = deps;
8936
+ const startedRef = useRef(false);
8934
8937
  useEffect(() => {
8935
- if (!privyReady) return;
8936
- const tryStart = () => {
8937
- if (completedRef.current) return;
8938
+ if (!privyReady) {
8939
+ console.info("[blink-sdk] guestPreauthMobileRestore: skipping, privyReady=false");
8940
+ return;
8941
+ }
8942
+ const tryStart = (trigger) => {
8943
+ if (startedRef.current) {
8944
+ console.info("[blink-sdk] guestPreauthMobileRestore.tryStart: already started", { trigger });
8945
+ return;
8946
+ }
8938
8947
  const persisted = loadMobileFlowState();
8939
- if (!persisted?.isGuestPreauth || !persisted.guestSessionToken) {
8948
+ console.info("[blink-sdk] guestPreauthMobileRestore.tryStart", {
8949
+ trigger,
8950
+ hasPersistedState: !!persisted,
8951
+ isGuestPreauth: persisted?.isGuestPreauth ?? false,
8952
+ hasGuestSessionToken: !!persisted?.guestSessionToken,
8953
+ hasSessionId: !!persisted?.sessionId,
8954
+ accountId: persisted?.accountId ?? null
8955
+ });
8956
+ if (!persisted?.isGuestPreauth || !persisted.guestSessionToken || !persisted.sessionId) {
8940
8957
  return;
8941
8958
  }
8942
- const guestToken = persisted.guestSessionToken;
8943
- const key = guestPreauthRestoreKey(guestToken);
8944
- if (guestPreauthRestoreAttemptedKeys.has(key)) return;
8945
- guestPreauthRestoreAttemptedKeys.add(key);
8946
- let cancelled = false;
8947
- const POLL_INTERVAL_MS = 3e3;
8959
+ startedRef.current = true;
8948
8960
  mobileSetupFlowRef.current = true;
8949
8961
  if (persisted.accountId) {
8950
8962
  setupAccountIdRef.current = persisted.accountId;
8951
8963
  }
8952
- const handleAccountFound = async (guestLookup) => {
8953
- if (completedRef.current) return;
8954
- completedRef.current = true;
8955
- cancelled = true;
8956
- clearMobileFlowState();
8957
- mobileSetupFlowRef.current = false;
8958
- setupAccountIdRef.current = null;
8964
+ if (persisted.accountId) {
8959
8965
  dispatch({
8960
8966
  type: "GUEST_PREAUTH_DETECTED",
8961
- accountId: guestLookup.accountId,
8962
- sessionId: persisted.sessionId ?? void 0
8967
+ accountId: persisted.accountId,
8968
+ sessionId: persisted.sessionId
8963
8969
  });
8964
- dispatch({ type: "REQUEST_LOGIN" });
8965
- dispatch({ type: "MOBILE_SETUP_COMPLETE" });
8966
- };
8967
- const pollGuestAccount = async () => {
8968
- try {
8969
- if (cancelled) return;
8970
- const guestLookup = await fetchGuestAccount(apiBaseUrl, guestToken);
8971
- if (cancelled) return;
8972
- if (guestLookup != null) {
8973
- if (persisted.sessionId) {
8974
- try {
8975
- const session = await fetchAuthorizationSession(
8976
- apiBaseUrl,
8977
- persisted.sessionId
8978
- );
8979
- if (cancelled) return;
8980
- if (session.status !== "AUTHORIZED") return;
8981
- } catch {
8982
- return;
8983
- }
8984
- }
8985
- await handleAccountFound(guestLookup);
8986
- }
8987
- } catch {
8988
- }
8989
- };
8990
- pollGuestAccount();
8991
- const intervalId = window.setInterval(pollGuestAccount, POLL_INTERVAL_MS);
8992
- const handlePollVisibility = () => {
8993
- if (document.visibilityState === "visible" && !cancelled) void pollGuestAccount();
8994
- };
8995
- const handlePollPageShow = () => {
8996
- if (document.visibilityState === "visible" && !cancelled) void pollGuestAccount();
8997
- };
8998
- document.addEventListener("visibilitychange", handlePollVisibility);
8999
- window.addEventListener("pageshow", handlePollPageShow);
9000
- pollingCleanupRef.current = () => {
9001
- cancelled = true;
9002
- window.clearInterval(intervalId);
9003
- document.removeEventListener("visibilitychange", handlePollVisibility);
9004
- window.removeEventListener("pageshow", handlePollPageShow);
9005
- if (!completedRef.current) {
9006
- guestPreauthRestoreAttemptedKeys.delete(key);
9007
- }
9008
- pollingCleanupRef.current = null;
9009
- };
8970
+ }
8971
+ dispatch({
8972
+ type: "MOBILE_DEEPLINK_READY",
8973
+ deeplinkUri: persisted.deeplinkUri
8974
+ });
8975
+ console.info("[blink-sdk] guestPreauthMobileRestore: starting guest account polling", {
8976
+ trigger,
8977
+ sessionId: persisted.sessionId
8978
+ });
8979
+ startGuestAccountPolling(persisted.guestSessionToken, persisted.sessionId);
9010
8980
  };
9011
- const onOuterVisibility = () => {
9012
- if (document.visibilityState === "visible") tryStart();
8981
+ const onVisibility = () => {
8982
+ console.info("[blink-sdk] guestPreauthMobileRestore: visibilitychange fired", {
8983
+ visibilityState: document.visibilityState,
8984
+ startedRef: startedRef.current
8985
+ });
8986
+ if (document.visibilityState === "visible") tryStart("visibilitychange");
9013
8987
  };
9014
- const onOuterPageShow = () => {
9015
- if (document.visibilityState === "visible") tryStart();
8988
+ const onPageShow = (e) => {
8989
+ console.info("[blink-sdk] guestPreauthMobileRestore: pageshow fired", {
8990
+ persisted: e.persisted,
8991
+ visibilityState: document.visibilityState,
8992
+ startedRef: startedRef.current
8993
+ });
8994
+ if (document.visibilityState === "visible") tryStart("pageshow");
9016
8995
  };
9017
- tryStart();
9018
- document.addEventListener("visibilitychange", onOuterVisibility);
9019
- window.addEventListener("pageshow", onOuterPageShow);
8996
+ tryStart("initial");
8997
+ document.addEventListener("visibilitychange", onVisibility);
8998
+ window.addEventListener("pageshow", onPageShow);
9020
8999
  return () => {
9021
- document.removeEventListener("visibilitychange", onOuterVisibility);
9022
- window.removeEventListener("pageshow", onOuterPageShow);
9023
- pollingCleanupRef.current?.();
9000
+ document.removeEventListener("visibilitychange", onVisibility);
9001
+ window.removeEventListener("pageshow", onPageShow);
9024
9002
  };
9025
- }, [privyReady, apiBaseUrl, dispatch, mobileSetupFlowRef, setupAccountIdRef]);
9003
+ }, [privyReady, dispatch, mobileSetupFlowRef, setupAccountIdRef, startGuestAccountPolling]);
9026
9004
  }
9027
9005
  function useSelectSourceEffect(deps) {
9028
9006
  const {
@@ -9283,6 +9261,118 @@ function useGuestPreauthWalletSetupEffect(deps) {
9283
9261
  dispatch
9284
9262
  ]);
9285
9263
  }
9264
+ function useGuestAccountPolling(intervalMs = 3e3) {
9265
+ const { apiBaseUrl } = useBlinkConfig();
9266
+ const [guestAccount, setGuestAccount] = useState(null);
9267
+ const [isPolling, setIsPolling] = useState(false);
9268
+ const intervalRef = useRef(null);
9269
+ const guestTokenRef = useRef(null);
9270
+ const sessionIdRef = useRef(null);
9271
+ const apiBaseUrlRef = useRef(apiBaseUrl);
9272
+ apiBaseUrlRef.current = apiBaseUrl;
9273
+ const stopPolling = useCallback(() => {
9274
+ console.info("[blink-sdk] useGuestAccountPolling.stopPolling called", {
9275
+ hadInterval: !!intervalRef.current,
9276
+ hadToken: !!guestTokenRef.current
9277
+ });
9278
+ if (intervalRef.current) {
9279
+ clearInterval(intervalRef.current);
9280
+ intervalRef.current = null;
9281
+ }
9282
+ guestTokenRef.current = null;
9283
+ sessionIdRef.current = null;
9284
+ setIsPolling(false);
9285
+ }, []);
9286
+ const poll = useCallback(async () => {
9287
+ const token = guestTokenRef.current;
9288
+ const sessionId = sessionIdRef.current;
9289
+ if (!token || !sessionId) {
9290
+ console.info("[blink-sdk] useGuestAccountPolling.poll skipped (no token or sessionId)", {
9291
+ hasToken: !!token,
9292
+ hasSessionId: !!sessionId
9293
+ });
9294
+ return;
9295
+ }
9296
+ console.info("[blink-sdk] useGuestAccountPolling.poll executing", {
9297
+ apiBaseUrl: apiBaseUrlRef.current,
9298
+ tokenPrefix: token.slice(0, 8),
9299
+ sessionId
9300
+ });
9301
+ try {
9302
+ const lookup = await fetchGuestAccount(apiBaseUrlRef.current, token);
9303
+ if (!guestTokenRef.current) return;
9304
+ if (lookup == null) {
9305
+ console.info("[blink-sdk] useGuestAccountPolling.poll: account not found yet");
9306
+ return;
9307
+ }
9308
+ console.info("[blink-sdk] useGuestAccountPolling.poll: account found, checking session");
9309
+ try {
9310
+ const session = await fetchAuthorizationSession(apiBaseUrlRef.current, sessionId);
9311
+ if (!guestTokenRef.current) return;
9312
+ if (session.status !== "AUTHORIZED") {
9313
+ console.info("[blink-sdk] useGuestAccountPolling.poll: session not AUTHORIZED yet", session.status);
9314
+ return;
9315
+ }
9316
+ } catch (err) {
9317
+ console.info("[blink-sdk] useGuestAccountPolling.poll: session fetch failed", err);
9318
+ return;
9319
+ }
9320
+ console.info("[blink-sdk] useGuestAccountPolling.poll: COMPLETE \u2014 account + AUTHORIZED");
9321
+ setGuestAccount(lookup);
9322
+ stopPolling();
9323
+ } catch (err) {
9324
+ console.info("[blink-sdk] useGuestAccountPolling.poll: fetch error, will retry", err);
9325
+ }
9326
+ }, [stopPolling]);
9327
+ const startPolling = useCallback(
9328
+ (guestToken, sessionId) => {
9329
+ console.info("[blink-sdk] useGuestAccountPolling.startPolling called", {
9330
+ tokenPrefix: guestToken.slice(0, 8),
9331
+ sessionId,
9332
+ intervalMs
9333
+ });
9334
+ stopPolling();
9335
+ guestTokenRef.current = guestToken;
9336
+ sessionIdRef.current = sessionId;
9337
+ setGuestAccount(null);
9338
+ setIsPolling(true);
9339
+ poll();
9340
+ intervalRef.current = setInterval(poll, intervalMs);
9341
+ },
9342
+ [poll, intervalMs, stopPolling]
9343
+ );
9344
+ useEffect(() => {
9345
+ const handleVisibility = () => {
9346
+ console.info("[blink-sdk] useGuestAccountPolling: visibilitychange fired", {
9347
+ visibilityState: document.visibilityState,
9348
+ hasToken: !!guestTokenRef.current,
9349
+ hasSessionId: !!sessionIdRef.current
9350
+ });
9351
+ if (document.visibilityState === "visible" && guestTokenRef.current) {
9352
+ void poll();
9353
+ }
9354
+ };
9355
+ const handlePageShow = (e) => {
9356
+ console.info("[blink-sdk] useGuestAccountPolling: pageshow fired", {
9357
+ persisted: e.persisted,
9358
+ visibilityState: document.visibilityState,
9359
+ hasToken: !!guestTokenRef.current,
9360
+ hasSessionId: !!sessionIdRef.current
9361
+ });
9362
+ if (document.visibilityState === "visible" && guestTokenRef.current) {
9363
+ void poll();
9364
+ }
9365
+ };
9366
+ document.addEventListener("visibilitychange", handleVisibility);
9367
+ window.addEventListener("pageshow", handlePageShow);
9368
+ return () => {
9369
+ document.removeEventListener("visibilitychange", handleVisibility);
9370
+ window.removeEventListener("pageshow", handlePageShow);
9371
+ };
9372
+ }, [poll]);
9373
+ useEffect(() => () => stopPolling(), [stopPolling]);
9374
+ return { guestAccount, isPolling, startPolling, stopPolling };
9375
+ }
9286
9376
  function BlinkPayment(props) {
9287
9377
  const resetKey = useRef(0);
9288
9378
  const handleBoundaryReset = useCallback(() => {
@@ -9319,6 +9409,7 @@ function BlinkPaymentInner({
9319
9409
  );
9320
9410
  const authExecutor = useAuthorizationExecutor();
9321
9411
  const polling = useTransferPolling();
9412
+ const guestAccountPolling = useGuestAccountPolling();
9322
9413
  const transferSigning = useTransferSigning();
9323
9414
  const mobileFlowRefs = {
9324
9415
  mobileSetupFlowRef: useRef(false),
@@ -9363,6 +9454,12 @@ function BlinkPaymentInner({
9363
9454
  transfer.pollingTransferIdRef,
9364
9455
  state.transfer,
9365
9456
  mobileFlowRefs,
9457
+ {
9458
+ mobileFlow: state.mobileFlow,
9459
+ isGuestFlow: state.isGuestFlow,
9460
+ guestTransferId: state.guestTransferId,
9461
+ guestSessionToken: state.guestSessionToken
9462
+ },
9366
9463
  onComplete
9367
9464
  );
9368
9465
  const sourceSelection = useSourceSelectionHandlers(dispatch, authExecutor, {
@@ -9398,7 +9495,8 @@ function BlinkPaymentInner({
9398
9495
  destination,
9399
9496
  guestSessionToken: state.guestSessionToken,
9400
9497
  guestTransferId: state.guestTransferId,
9401
- selectedProviderId: state.selectedProviderId
9498
+ selectedProviderId: state.selectedProviderId,
9499
+ startGuestAccountPolling: guestAccountPolling.startPolling
9402
9500
  });
9403
9501
  const guestPostPayPreauth = useMemo(
9404
9502
  () => !!state.guestPreauthSessionId && state.isGuestFlow || state.guestPreauthorizing && isDesktop,
@@ -9461,11 +9559,40 @@ function BlinkPaymentInner({
9461
9559
  usePrivySessionSyncEffect({ dispatch, ready, authenticated });
9462
9560
  useGuestPreauthMobileRestoreEffect({
9463
9561
  dispatch,
9464
- apiBaseUrl,
9465
9562
  privyReady: state.privyReady,
9466
9563
  mobileSetupFlowRef: mobileFlowRefs.mobileSetupFlowRef,
9467
- setupAccountIdRef: mobileFlowRefs.setupAccountIdRef
9564
+ setupAccountIdRef: mobileFlowRefs.setupAccountIdRef,
9565
+ startGuestAccountPolling: guestAccountPolling.startPolling
9468
9566
  });
9567
+ useEffect(() => {
9568
+ console.info("[blink-sdk] guestPreauthCompletion effect", {
9569
+ hasGuestAccount: !!guestAccountPolling.guestAccount,
9570
+ guestAccountId: guestAccountPolling.guestAccount?.accountId ?? null,
9571
+ currentPreauthAccountId: state.guestPreauthAccountId,
9572
+ currentPhase: state.phase.step,
9573
+ mobileFlow: state.mobileFlow,
9574
+ loginRequested: state.loginRequested
9575
+ });
9576
+ if (!guestAccountPolling.guestAccount) return;
9577
+ const acct = guestAccountPolling.guestAccount;
9578
+ const needsDetect = acct.accountId !== state.guestPreauthAccountId;
9579
+ console.info("[blink-sdk] guestPreauthCompletion: dispatching REQUEST_LOGIN + MOBILE_SETUP_COMPLETE", {
9580
+ accountId: acct.accountId,
9581
+ dispatchingGuestPreauthDetected: needsDetect
9582
+ });
9583
+ if (needsDetect) {
9584
+ dispatch({
9585
+ type: "GUEST_PREAUTH_DETECTED",
9586
+ accountId: acct.accountId,
9587
+ sessionId: state.guestPreauthSessionId ?? void 0
9588
+ });
9589
+ }
9590
+ mobileFlowRefs.mobileSetupFlowRef.current = false;
9591
+ mobileFlowRefs.setupAccountIdRef.current = null;
9592
+ clearMobileFlowState();
9593
+ dispatch({ type: "REQUEST_LOGIN" });
9594
+ dispatch({ type: "MOBILE_SETUP_COMPLETE" });
9595
+ }, [guestAccountPolling.guestAccount]);
9469
9596
  useOtpEffects({
9470
9597
  state,
9471
9598
  dispatch,
@@ -9495,7 +9622,8 @@ function BlinkPaymentInner({
9495
9622
  reauthTokenRef: mobileFlowRefs.reauthTokenRef,
9496
9623
  pollingTransferIdRef: transfer.pollingTransferIdRef,
9497
9624
  handleAuthorizedMobileReturn: mobileFlow.handleAuthorizedMobileReturn,
9498
- onComplete
9625
+ onComplete,
9626
+ startGuestAccountPolling: guestAccountPolling.startPolling
9499
9627
  });
9500
9628
  useDataLoadEffect({
9501
9629
  state,