@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.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":
@@ -7199,7 +7263,7 @@ function useSourceSelectionHandlers(dispatch, authExecutor, options) {
7199
7263
  initializedSelectSourceActionRef
7200
7264
  };
7201
7265
  }
7202
- function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, onComplete) {
7266
+ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, guestCheckout, onComplete) {
7203
7267
  const {
7204
7268
  mobileSetupFlowRef,
7205
7269
  handlingMobileReturnRef,
@@ -7210,6 +7274,10 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
7210
7274
  onCompleteRef.current = onComplete;
7211
7275
  const guestPollingActiveRef = react.useRef(false);
7212
7276
  const guestPollingCleanupRef = react.useRef(null);
7277
+ const guestTransferIdRef = react.useRef(guestCheckout.guestTransferId);
7278
+ guestTransferIdRef.current = guestCheckout.guestTransferId;
7279
+ const guestSessionTokenRef = react.useRef(guestCheckout.guestSessionToken);
7280
+ guestSessionTokenRef.current = guestCheckout.guestSessionToken;
7213
7281
  const startGuestPolling = react.useCallback((transferId, guestSessionToken) => {
7214
7282
  if (guestPollingActiveRef.current) return;
7215
7283
  guestPollingActiveRef.current = true;
@@ -7225,14 +7293,12 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
7225
7293
  cancelled = true;
7226
7294
  guestPollingActiveRef.current = false;
7227
7295
  guestPollingCleanupRef.current = null;
7228
- clearMobileFlowState();
7229
7296
  dispatch({ type: "GUEST_TRANSFER_COMPLETED", transfer, guestSessionToken });
7230
7297
  onCompleteRef.current?.(transfer);
7231
7298
  } else if (transfer.status === "FAILED") {
7232
7299
  cancelled = true;
7233
7300
  guestPollingActiveRef.current = false;
7234
7301
  guestPollingCleanupRef.current = null;
7235
- clearMobileFlowState();
7236
7302
  dispatch({ type: "TRANSFER_FAILED", transfer, error: "Transfer failed." });
7237
7303
  }
7238
7304
  } catch {
@@ -7249,20 +7315,26 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
7249
7315
  guestPollingCleanupRef.current = cleanup;
7250
7316
  }, [apiBaseUrl, dispatch]);
7251
7317
  react.useEffect(() => {
7252
- const persisted = loadMobileFlowState();
7253
- if (persisted?.isGuestCheckout && persisted.transferId && persisted.guestSessionToken) {
7254
- startGuestPolling(persisted.transferId, persisted.guestSessionToken);
7318
+ if (guestCheckout.mobileFlow && guestCheckout.isGuestFlow && guestCheckout.guestTransferId && guestCheckout.guestSessionToken) {
7319
+ startGuestPolling(guestCheckout.guestTransferId, guestCheckout.guestSessionToken);
7255
7320
  }
7256
7321
  return () => {
7257
7322
  guestPollingCleanupRef.current?.();
7258
7323
  };
7259
- }, [startGuestPolling]);
7324
+ }, [
7325
+ guestCheckout.mobileFlow,
7326
+ guestCheckout.isGuestFlow,
7327
+ guestCheckout.guestTransferId,
7328
+ guestCheckout.guestSessionToken,
7329
+ startGuestPolling
7330
+ ]);
7260
7331
  react.useEffect(() => {
7261
7332
  const tryStartPolling = () => {
7262
7333
  if (guestPollingActiveRef.current) return;
7263
- const persisted = loadMobileFlowState();
7264
- if (persisted?.isGuestCheckout && persisted.transferId && persisted.guestSessionToken) {
7265
- startGuestPolling(persisted.transferId, persisted.guestSessionToken);
7334
+ const transferId = guestTransferIdRef.current;
7335
+ const token = guestSessionTokenRef.current;
7336
+ if (transferId && token) {
7337
+ startGuestPolling(transferId, token);
7266
7338
  }
7267
7339
  };
7268
7340
  const handleVisibility = () => {
@@ -7342,7 +7414,8 @@ function useProviderHandlers(deps) {
7342
7414
  destination,
7343
7415
  guestSessionToken,
7344
7416
  guestTransferId,
7345
- selectedProviderId
7417
+ selectedProviderId,
7418
+ startGuestAccountPolling
7346
7419
  } = deps;
7347
7420
  const wagmiConfig2 = wagmi.useConfig();
7348
7421
  const { connectAsync, connectors } = wagmi.useConnect();
@@ -7405,16 +7478,13 @@ function useProviderHandlers(deps) {
7405
7478
  dispatch({ type: "PAY_ERROR", error: "This wallet is not available on mobile." });
7406
7479
  return;
7407
7480
  }
7408
- persistMobileFlowState({
7409
- transferId: result.id,
7410
- guestSessionToken: result.guestSessionToken,
7411
- isGuestCheckout: true,
7481
+ triggerDeeplink(result.uri);
7482
+ dispatch({
7483
+ type: "MOBILE_DEEPLINK_READY",
7412
7484
  deeplinkUri: result.uri,
7413
- providerId,
7414
- isSetup: false
7485
+ guestTransferId: result.id,
7486
+ guestSessionToken: result.guestSessionToken
7415
7487
  });
7416
- triggerDeeplink(result.uri);
7417
- dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: result.uri });
7418
7488
  } else {
7419
7489
  const account = getAccount(wagmiConfig2);
7420
7490
  if (!account.isConnected) {
@@ -7750,6 +7820,14 @@ function useProviderHandlers(deps) {
7750
7820
  useWalletConnector: useWalletConnectorProp,
7751
7821
  userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
7752
7822
  });
7823
+ console.info("[blink-sdk] handlePreauthorize", {
7824
+ isMobile,
7825
+ useWalletConnectorProp,
7826
+ hasGuestSessionToken: !!guestSessionToken,
7827
+ selectedProviderId,
7828
+ guestTransferId,
7829
+ userAgent: typeof navigator === "undefined" ? null : navigator.userAgent
7830
+ });
7753
7831
  const providerName = providers.find((p) => p.id === selectedProviderId)?.name ?? "Wallet";
7754
7832
  if (!isMobile) {
7755
7833
  dispatch({ type: "GUEST_PREAUTH_BEGIN" });
@@ -7782,6 +7860,7 @@ function useProviderHandlers(deps) {
7782
7860
  triggerDeeplink(created.sessionUri);
7783
7861
  dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: created.sessionUri });
7784
7862
  }
7863
+ startGuestAccountPolling(guestSessionToken, session.id);
7785
7864
  dispatch({
7786
7865
  type: "GUEST_PREAUTH_DETECTED",
7787
7866
  accountId: created.accountId,
@@ -7809,7 +7888,8 @@ function useProviderHandlers(deps) {
7809
7888
  useWalletConnectorProp,
7810
7889
  mobileSetupFlowRef,
7811
7890
  handlingMobileReturnRef,
7812
- setupAccountIdRef
7891
+ setupAccountIdRef,
7892
+ startGuestAccountPolling
7813
7893
  ]);
7814
7894
  return {
7815
7895
  handlePrepareProvider,
@@ -8169,7 +8249,8 @@ function usePasskeyCheckEffect(deps) {
8169
8249
  setupAccountIdRef,
8170
8250
  reauthSessionIdRef,
8171
8251
  reauthTokenRef,
8172
- pollingTransferIdRef
8252
+ pollingTransferIdRef,
8253
+ startGuestAccountPolling
8173
8254
  } = deps;
8174
8255
  const { getAccessToken } = reactAuth.usePrivy();
8175
8256
  const onCompleteRef = react.useRef(deps.onComplete);
@@ -8192,8 +8273,23 @@ function usePasskeyCheckEffect(deps) {
8192
8273
  dispatch({ type: "SET_ERROR", error: null });
8193
8274
  setAuthInput("");
8194
8275
  setOtpCode("");
8276
+ const startGuestAccountPollingRef = startGuestAccountPolling;
8195
8277
  const restoreState = async (credId, token) => {
8196
8278
  const persisted = loadMobileFlowState();
8279
+ if (persisted?.isGuestPreauth && persisted.guestSessionToken && persisted.sessionId) {
8280
+ mobileSetupFlowRef.current = true;
8281
+ if (persisted.accountId) {
8282
+ setupAccountIdRef.current = persisted.accountId;
8283
+ dispatch({
8284
+ type: "GUEST_PREAUTH_DETECTED",
8285
+ accountId: persisted.accountId,
8286
+ sessionId: persisted.sessionId
8287
+ });
8288
+ }
8289
+ dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: persisted.deeplinkUri });
8290
+ startGuestAccountPollingRef(persisted.guestSessionToken, persisted.sessionId);
8291
+ return;
8292
+ }
8197
8293
  let accts = [];
8198
8294
  try {
8199
8295
  accts = await fetchAccounts(apiBaseUrl, token, credId);
@@ -8694,100 +8790,6 @@ function useMobilePollingEffect(deps) {
8694
8790
  handlingMobileReturnRef,
8695
8791
  mobileSetupFlowRef
8696
8792
  ]);
8697
- react.useEffect(() => {
8698
- if (!state.mobileFlow || !state.isGuestFlow || !state.guestPreauthSessionId || !state.guestPreauthAccountId) {
8699
- return;
8700
- }
8701
- const guestToken = state.guestSessionToken ?? loadMobileFlowState()?.guestSessionToken ?? null;
8702
- const preauthAccountId = state.guestPreauthAccountId;
8703
- const preauthSessionId = state.guestPreauthSessionId;
8704
- let cancelled = false;
8705
- let completedGuestPreauth = false;
8706
- const POLL_INTERVAL_MS = 3e3;
8707
- const finishMobileAndDispatch = async () => {
8708
- mobileSetupFlowRef.current = false;
8709
- setupAccountIdRef.current = null;
8710
- try {
8711
- await reloadAccounts();
8712
- } catch {
8713
- }
8714
- };
8715
- const completeGuestPreauthWithoutToken = async () => {
8716
- if (completedGuestPreauth) return;
8717
- completedGuestPreauth = true;
8718
- cancelled = true;
8719
- await finishMobileAndDispatch();
8720
- clearMobileFlowState();
8721
- dispatch({ type: "MOBILE_SETUP_COMPLETE" });
8722
- };
8723
- const completeGuestPreauthWithAccount = async (guestLookup) => {
8724
- if (completedGuestPreauth) return;
8725
- completedGuestPreauth = true;
8726
- cancelled = true;
8727
- await finishMobileAndDispatch();
8728
- if (guestLookup.accountId !== preauthAccountId) {
8729
- dispatch({
8730
- type: "GUEST_PREAUTH_DETECTED",
8731
- accountId: guestLookup.accountId,
8732
- sessionId: preauthSessionId ?? void 0
8733
- });
8734
- }
8735
- dispatch({ type: "REQUEST_LOGIN" });
8736
- dispatch({ type: "MOBILE_SETUP_COMPLETE" });
8737
- };
8738
- const pollGuestAccount = async () => {
8739
- try {
8740
- if (cancelled) return;
8741
- if (!guestToken) {
8742
- await completeGuestPreauthWithoutToken();
8743
- return;
8744
- }
8745
- const guestLookup = await fetchGuestAccount(apiBaseUrl, guestToken);
8746
- if (cancelled) return;
8747
- if (guestLookup != null) {
8748
- if (preauthSessionId) {
8749
- try {
8750
- const session = await fetchAuthorizationSession(
8751
- apiBaseUrl,
8752
- preauthSessionId
8753
- );
8754
- if (cancelled) return;
8755
- if (session.status !== "AUTHORIZED") return;
8756
- } catch {
8757
- return;
8758
- }
8759
- }
8760
- await completeGuestPreauthWithAccount(guestLookup);
8761
- }
8762
- } catch {
8763
- }
8764
- };
8765
- pollGuestAccount();
8766
- const intervalId = window.setInterval(pollGuestAccount, POLL_INTERVAL_MS);
8767
- const handleVisibility = () => {
8768
- if (document.visibilityState === "visible" && !cancelled) void pollGuestAccount();
8769
- };
8770
- const handlePageShow = () => {
8771
- if (document.visibilityState === "visible" && !cancelled) void pollGuestAccount();
8772
- };
8773
- document.addEventListener("visibilitychange", handleVisibility);
8774
- window.addEventListener("pageshow", handlePageShow);
8775
- return () => {
8776
- cancelled = true;
8777
- window.clearInterval(intervalId);
8778
- document.removeEventListener("visibilitychange", handleVisibility);
8779
- window.removeEventListener("pageshow", handlePageShow);
8780
- };
8781
- }, [
8782
- state.mobileFlow,
8783
- state.guestPreauthSessionId,
8784
- state.isGuestFlow,
8785
- state.guestSessionToken,
8786
- state.guestPreauthAccountId,
8787
- apiBaseUrl,
8788
- reloadAccounts,
8789
- dispatch
8790
- ]);
8791
8793
  react.useEffect(() => {
8792
8794
  if (!state.mobileFlow || !mobileSetupFlowRef.current) return;
8793
8795
  if (state.isGuestFlow && state.guestPreauthSessionId != null) return;
@@ -8926,106 +8928,82 @@ function useMobilePollingEffect(deps) {
8926
8928
  pollingTransferIdRef
8927
8929
  ]);
8928
8930
  }
8929
- var guestPreauthRestoreAttemptedKeys = /* @__PURE__ */ new Set();
8930
- function guestPreauthRestoreKey(guestToken) {
8931
- return guestToken;
8932
- }
8933
8931
  function useGuestPreauthMobileRestoreEffect(deps) {
8934
- const { dispatch, apiBaseUrl, privyReady, mobileSetupFlowRef, setupAccountIdRef } = deps;
8935
- const completedRef = react.useRef(false);
8936
- const pollingCleanupRef = react.useRef(null);
8932
+ const {
8933
+ dispatch,
8934
+ privyReady,
8935
+ mobileSetupFlowRef,
8936
+ setupAccountIdRef,
8937
+ startGuestAccountPolling
8938
+ } = deps;
8939
+ const startedRef = react.useRef(false);
8937
8940
  react.useEffect(() => {
8938
- if (!privyReady) return;
8939
- const tryStart = () => {
8940
- if (completedRef.current) return;
8941
+ if (!privyReady) {
8942
+ console.info("[blink-sdk] guestPreauthMobileRestore: skipping, privyReady=false");
8943
+ return;
8944
+ }
8945
+ const tryStart = (trigger) => {
8946
+ if (startedRef.current) {
8947
+ console.info("[blink-sdk] guestPreauthMobileRestore.tryStart: already started", { trigger });
8948
+ return;
8949
+ }
8941
8950
  const persisted = loadMobileFlowState();
8942
- if (!persisted?.isGuestPreauth || !persisted.guestSessionToken) {
8951
+ console.info("[blink-sdk] guestPreauthMobileRestore.tryStart", {
8952
+ trigger,
8953
+ hasPersistedState: !!persisted,
8954
+ isGuestPreauth: persisted?.isGuestPreauth ?? false,
8955
+ hasGuestSessionToken: !!persisted?.guestSessionToken,
8956
+ hasSessionId: !!persisted?.sessionId,
8957
+ accountId: persisted?.accountId ?? null
8958
+ });
8959
+ if (!persisted?.isGuestPreauth || !persisted.guestSessionToken || !persisted.sessionId) {
8943
8960
  return;
8944
8961
  }
8945
- const guestToken = persisted.guestSessionToken;
8946
- const key = guestPreauthRestoreKey(guestToken);
8947
- if (guestPreauthRestoreAttemptedKeys.has(key)) return;
8948
- guestPreauthRestoreAttemptedKeys.add(key);
8949
- let cancelled = false;
8950
- const POLL_INTERVAL_MS = 3e3;
8962
+ startedRef.current = true;
8951
8963
  mobileSetupFlowRef.current = true;
8952
8964
  if (persisted.accountId) {
8953
8965
  setupAccountIdRef.current = persisted.accountId;
8954
8966
  }
8955
- const handleAccountFound = async (guestLookup) => {
8956
- if (completedRef.current) return;
8957
- completedRef.current = true;
8958
- cancelled = true;
8959
- clearMobileFlowState();
8960
- mobileSetupFlowRef.current = false;
8961
- setupAccountIdRef.current = null;
8967
+ if (persisted.accountId) {
8962
8968
  dispatch({
8963
8969
  type: "GUEST_PREAUTH_DETECTED",
8964
- accountId: guestLookup.accountId,
8965
- sessionId: persisted.sessionId ?? void 0
8970
+ accountId: persisted.accountId,
8971
+ sessionId: persisted.sessionId
8966
8972
  });
8967
- dispatch({ type: "REQUEST_LOGIN" });
8968
- dispatch({ type: "MOBILE_SETUP_COMPLETE" });
8969
- };
8970
- const pollGuestAccount = async () => {
8971
- try {
8972
- if (cancelled) return;
8973
- const guestLookup = await fetchGuestAccount(apiBaseUrl, guestToken);
8974
- if (cancelled) return;
8975
- if (guestLookup != null) {
8976
- if (persisted.sessionId) {
8977
- try {
8978
- const session = await fetchAuthorizationSession(
8979
- apiBaseUrl,
8980
- persisted.sessionId
8981
- );
8982
- if (cancelled) return;
8983
- if (session.status !== "AUTHORIZED") return;
8984
- } catch {
8985
- return;
8986
- }
8987
- }
8988
- await handleAccountFound(guestLookup);
8989
- }
8990
- } catch {
8991
- }
8992
- };
8993
- pollGuestAccount();
8994
- const intervalId = window.setInterval(pollGuestAccount, POLL_INTERVAL_MS);
8995
- const handlePollVisibility = () => {
8996
- if (document.visibilityState === "visible" && !cancelled) void pollGuestAccount();
8997
- };
8998
- const handlePollPageShow = () => {
8999
- if (document.visibilityState === "visible" && !cancelled) void pollGuestAccount();
9000
- };
9001
- document.addEventListener("visibilitychange", handlePollVisibility);
9002
- window.addEventListener("pageshow", handlePollPageShow);
9003
- pollingCleanupRef.current = () => {
9004
- cancelled = true;
9005
- window.clearInterval(intervalId);
9006
- document.removeEventListener("visibilitychange", handlePollVisibility);
9007
- window.removeEventListener("pageshow", handlePollPageShow);
9008
- if (!completedRef.current) {
9009
- guestPreauthRestoreAttemptedKeys.delete(key);
9010
- }
9011
- pollingCleanupRef.current = null;
9012
- };
8973
+ }
8974
+ dispatch({
8975
+ type: "MOBILE_DEEPLINK_READY",
8976
+ deeplinkUri: persisted.deeplinkUri
8977
+ });
8978
+ console.info("[blink-sdk] guestPreauthMobileRestore: starting guest account polling", {
8979
+ trigger,
8980
+ sessionId: persisted.sessionId
8981
+ });
8982
+ startGuestAccountPolling(persisted.guestSessionToken, persisted.sessionId);
9013
8983
  };
9014
- const onOuterVisibility = () => {
9015
- if (document.visibilityState === "visible") tryStart();
8984
+ const onVisibility = () => {
8985
+ console.info("[blink-sdk] guestPreauthMobileRestore: visibilitychange fired", {
8986
+ visibilityState: document.visibilityState,
8987
+ startedRef: startedRef.current
8988
+ });
8989
+ if (document.visibilityState === "visible") tryStart("visibilitychange");
9016
8990
  };
9017
- const onOuterPageShow = () => {
9018
- if (document.visibilityState === "visible") tryStart();
8991
+ const onPageShow = (e) => {
8992
+ console.info("[blink-sdk] guestPreauthMobileRestore: pageshow fired", {
8993
+ persisted: e.persisted,
8994
+ visibilityState: document.visibilityState,
8995
+ startedRef: startedRef.current
8996
+ });
8997
+ if (document.visibilityState === "visible") tryStart("pageshow");
9019
8998
  };
9020
- tryStart();
9021
- document.addEventListener("visibilitychange", onOuterVisibility);
9022
- window.addEventListener("pageshow", onOuterPageShow);
8999
+ tryStart("initial");
9000
+ document.addEventListener("visibilitychange", onVisibility);
9001
+ window.addEventListener("pageshow", onPageShow);
9023
9002
  return () => {
9024
- document.removeEventListener("visibilitychange", onOuterVisibility);
9025
- window.removeEventListener("pageshow", onOuterPageShow);
9026
- pollingCleanupRef.current?.();
9003
+ document.removeEventListener("visibilitychange", onVisibility);
9004
+ window.removeEventListener("pageshow", onPageShow);
9027
9005
  };
9028
- }, [privyReady, apiBaseUrl, dispatch, mobileSetupFlowRef, setupAccountIdRef]);
9006
+ }, [privyReady, dispatch, mobileSetupFlowRef, setupAccountIdRef, startGuestAccountPolling]);
9029
9007
  }
9030
9008
  function useSelectSourceEffect(deps) {
9031
9009
  const {
@@ -9286,6 +9264,118 @@ function useGuestPreauthWalletSetupEffect(deps) {
9286
9264
  dispatch
9287
9265
  ]);
9288
9266
  }
9267
+ function useGuestAccountPolling(intervalMs = 3e3) {
9268
+ const { apiBaseUrl } = useBlinkConfig();
9269
+ const [guestAccount, setGuestAccount] = react.useState(null);
9270
+ const [isPolling, setIsPolling] = react.useState(false);
9271
+ const intervalRef = react.useRef(null);
9272
+ const guestTokenRef = react.useRef(null);
9273
+ const sessionIdRef = react.useRef(null);
9274
+ const apiBaseUrlRef = react.useRef(apiBaseUrl);
9275
+ apiBaseUrlRef.current = apiBaseUrl;
9276
+ const stopPolling = react.useCallback(() => {
9277
+ console.info("[blink-sdk] useGuestAccountPolling.stopPolling called", {
9278
+ hadInterval: !!intervalRef.current,
9279
+ hadToken: !!guestTokenRef.current
9280
+ });
9281
+ if (intervalRef.current) {
9282
+ clearInterval(intervalRef.current);
9283
+ intervalRef.current = null;
9284
+ }
9285
+ guestTokenRef.current = null;
9286
+ sessionIdRef.current = null;
9287
+ setIsPolling(false);
9288
+ }, []);
9289
+ const poll = react.useCallback(async () => {
9290
+ const token = guestTokenRef.current;
9291
+ const sessionId = sessionIdRef.current;
9292
+ if (!token || !sessionId) {
9293
+ console.info("[blink-sdk] useGuestAccountPolling.poll skipped (no token or sessionId)", {
9294
+ hasToken: !!token,
9295
+ hasSessionId: !!sessionId
9296
+ });
9297
+ return;
9298
+ }
9299
+ console.info("[blink-sdk] useGuestAccountPolling.poll executing", {
9300
+ apiBaseUrl: apiBaseUrlRef.current,
9301
+ tokenPrefix: token.slice(0, 8),
9302
+ sessionId
9303
+ });
9304
+ try {
9305
+ const lookup = await fetchGuestAccount(apiBaseUrlRef.current, token);
9306
+ if (!guestTokenRef.current) return;
9307
+ if (lookup == null) {
9308
+ console.info("[blink-sdk] useGuestAccountPolling.poll: account not found yet");
9309
+ return;
9310
+ }
9311
+ console.info("[blink-sdk] useGuestAccountPolling.poll: account found, checking session");
9312
+ try {
9313
+ const session = await fetchAuthorizationSession(apiBaseUrlRef.current, sessionId);
9314
+ if (!guestTokenRef.current) return;
9315
+ if (session.status !== "AUTHORIZED") {
9316
+ console.info("[blink-sdk] useGuestAccountPolling.poll: session not AUTHORIZED yet", session.status);
9317
+ return;
9318
+ }
9319
+ } catch (err) {
9320
+ console.info("[blink-sdk] useGuestAccountPolling.poll: session fetch failed", err);
9321
+ return;
9322
+ }
9323
+ console.info("[blink-sdk] useGuestAccountPolling.poll: COMPLETE \u2014 account + AUTHORIZED");
9324
+ setGuestAccount(lookup);
9325
+ stopPolling();
9326
+ } catch (err) {
9327
+ console.info("[blink-sdk] useGuestAccountPolling.poll: fetch error, will retry", err);
9328
+ }
9329
+ }, [stopPolling]);
9330
+ const startPolling = react.useCallback(
9331
+ (guestToken, sessionId) => {
9332
+ console.info("[blink-sdk] useGuestAccountPolling.startPolling called", {
9333
+ tokenPrefix: guestToken.slice(0, 8),
9334
+ sessionId,
9335
+ intervalMs
9336
+ });
9337
+ stopPolling();
9338
+ guestTokenRef.current = guestToken;
9339
+ sessionIdRef.current = sessionId;
9340
+ setGuestAccount(null);
9341
+ setIsPolling(true);
9342
+ poll();
9343
+ intervalRef.current = setInterval(poll, intervalMs);
9344
+ },
9345
+ [poll, intervalMs, stopPolling]
9346
+ );
9347
+ react.useEffect(() => {
9348
+ const handleVisibility = () => {
9349
+ console.info("[blink-sdk] useGuestAccountPolling: visibilitychange fired", {
9350
+ visibilityState: document.visibilityState,
9351
+ hasToken: !!guestTokenRef.current,
9352
+ hasSessionId: !!sessionIdRef.current
9353
+ });
9354
+ if (document.visibilityState === "visible" && guestTokenRef.current) {
9355
+ void poll();
9356
+ }
9357
+ };
9358
+ const handlePageShow = (e) => {
9359
+ console.info("[blink-sdk] useGuestAccountPolling: pageshow fired", {
9360
+ persisted: e.persisted,
9361
+ visibilityState: document.visibilityState,
9362
+ hasToken: !!guestTokenRef.current,
9363
+ hasSessionId: !!sessionIdRef.current
9364
+ });
9365
+ if (document.visibilityState === "visible" && guestTokenRef.current) {
9366
+ void poll();
9367
+ }
9368
+ };
9369
+ document.addEventListener("visibilitychange", handleVisibility);
9370
+ window.addEventListener("pageshow", handlePageShow);
9371
+ return () => {
9372
+ document.removeEventListener("visibilitychange", handleVisibility);
9373
+ window.removeEventListener("pageshow", handlePageShow);
9374
+ };
9375
+ }, [poll]);
9376
+ react.useEffect(() => () => stopPolling(), [stopPolling]);
9377
+ return { guestAccount, isPolling, startPolling, stopPolling };
9378
+ }
9289
9379
  function BlinkPayment(props) {
9290
9380
  const resetKey = react.useRef(0);
9291
9381
  const handleBoundaryReset = react.useCallback(() => {
@@ -9322,6 +9412,7 @@ function BlinkPaymentInner({
9322
9412
  );
9323
9413
  const authExecutor = useAuthorizationExecutor();
9324
9414
  const polling = useTransferPolling();
9415
+ const guestAccountPolling = useGuestAccountPolling();
9325
9416
  const transferSigning = useTransferSigning();
9326
9417
  const mobileFlowRefs = {
9327
9418
  mobileSetupFlowRef: react.useRef(false),
@@ -9366,6 +9457,12 @@ function BlinkPaymentInner({
9366
9457
  transfer.pollingTransferIdRef,
9367
9458
  state.transfer,
9368
9459
  mobileFlowRefs,
9460
+ {
9461
+ mobileFlow: state.mobileFlow,
9462
+ isGuestFlow: state.isGuestFlow,
9463
+ guestTransferId: state.guestTransferId,
9464
+ guestSessionToken: state.guestSessionToken
9465
+ },
9369
9466
  onComplete
9370
9467
  );
9371
9468
  const sourceSelection = useSourceSelectionHandlers(dispatch, authExecutor, {
@@ -9401,7 +9498,8 @@ function BlinkPaymentInner({
9401
9498
  destination,
9402
9499
  guestSessionToken: state.guestSessionToken,
9403
9500
  guestTransferId: state.guestTransferId,
9404
- selectedProviderId: state.selectedProviderId
9501
+ selectedProviderId: state.selectedProviderId,
9502
+ startGuestAccountPolling: guestAccountPolling.startPolling
9405
9503
  });
9406
9504
  const guestPostPayPreauth = react.useMemo(
9407
9505
  () => !!state.guestPreauthSessionId && state.isGuestFlow || state.guestPreauthorizing && isDesktop,
@@ -9464,11 +9562,40 @@ function BlinkPaymentInner({
9464
9562
  usePrivySessionSyncEffect({ dispatch, ready, authenticated });
9465
9563
  useGuestPreauthMobileRestoreEffect({
9466
9564
  dispatch,
9467
- apiBaseUrl,
9468
9565
  privyReady: state.privyReady,
9469
9566
  mobileSetupFlowRef: mobileFlowRefs.mobileSetupFlowRef,
9470
- setupAccountIdRef: mobileFlowRefs.setupAccountIdRef
9567
+ setupAccountIdRef: mobileFlowRefs.setupAccountIdRef,
9568
+ startGuestAccountPolling: guestAccountPolling.startPolling
9471
9569
  });
9570
+ react.useEffect(() => {
9571
+ console.info("[blink-sdk] guestPreauthCompletion effect", {
9572
+ hasGuestAccount: !!guestAccountPolling.guestAccount,
9573
+ guestAccountId: guestAccountPolling.guestAccount?.accountId ?? null,
9574
+ currentPreauthAccountId: state.guestPreauthAccountId,
9575
+ currentPhase: state.phase.step,
9576
+ mobileFlow: state.mobileFlow,
9577
+ loginRequested: state.loginRequested
9578
+ });
9579
+ if (!guestAccountPolling.guestAccount) return;
9580
+ const acct = guestAccountPolling.guestAccount;
9581
+ const needsDetect = acct.accountId !== state.guestPreauthAccountId;
9582
+ console.info("[blink-sdk] guestPreauthCompletion: dispatching REQUEST_LOGIN + MOBILE_SETUP_COMPLETE", {
9583
+ accountId: acct.accountId,
9584
+ dispatchingGuestPreauthDetected: needsDetect
9585
+ });
9586
+ if (needsDetect) {
9587
+ dispatch({
9588
+ type: "GUEST_PREAUTH_DETECTED",
9589
+ accountId: acct.accountId,
9590
+ sessionId: state.guestPreauthSessionId ?? void 0
9591
+ });
9592
+ }
9593
+ mobileFlowRefs.mobileSetupFlowRef.current = false;
9594
+ mobileFlowRefs.setupAccountIdRef.current = null;
9595
+ clearMobileFlowState();
9596
+ dispatch({ type: "REQUEST_LOGIN" });
9597
+ dispatch({ type: "MOBILE_SETUP_COMPLETE" });
9598
+ }, [guestAccountPolling.guestAccount]);
9472
9599
  useOtpEffects({
9473
9600
  state,
9474
9601
  dispatch,
@@ -9498,7 +9625,8 @@ function BlinkPaymentInner({
9498
9625
  reauthTokenRef: mobileFlowRefs.reauthTokenRef,
9499
9626
  pollingTransferIdRef: transfer.pollingTransferIdRef,
9500
9627
  handleAuthorizedMobileReturn: mobileFlow.handleAuthorizedMobileReturn,
9501
- onComplete
9628
+ onComplete,
9629
+ startGuestAccountPolling: guestAccountPolling.startPolling
9502
9630
  });
9503
9631
  useDataLoadEffect({
9504
9632
  state,