@swype-org/react-sdk 0.1.98 → 0.1.102

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
@@ -159,7 +159,9 @@ function useSwypeDepositAmount() {
159
159
  // src/api.ts
160
160
  var api_exports = {};
161
161
  __export(api_exports, {
162
+ createAccount: () => createAccount,
162
163
  createTransfer: () => createTransfer,
164
+ fetchAccount: () => fetchAccount,
163
165
  fetchAccounts: () => fetchAccounts,
164
166
  fetchAuthorizationSession: () => fetchAuthorizationSession,
165
167
  fetchChains: () => fetchChains,
@@ -206,6 +208,32 @@ async function fetchAccounts(apiBaseUrl, token, credentialId) {
206
208
  const data = await res.json();
207
209
  return data.items;
208
210
  }
211
+ async function fetchAccount(apiBaseUrl, token, accountId, credentialId) {
212
+ const params = new URLSearchParams({ credentialId });
213
+ const res = await fetch(`${apiBaseUrl}/v1/accounts/${accountId}?${params.toString()}`, {
214
+ headers: { Authorization: `Bearer ${token}` }
215
+ });
216
+ if (!res.ok) await throwApiError(res);
217
+ return await res.json();
218
+ }
219
+ async function createAccount(apiBaseUrl, token, params) {
220
+ const body = {
221
+ id: params.id ?? crypto.randomUUID(),
222
+ name: params.name,
223
+ credentialId: params.credentialId,
224
+ providerId: params.providerId
225
+ };
226
+ const res = await fetch(`${apiBaseUrl}/v1/accounts`, {
227
+ method: "POST",
228
+ headers: {
229
+ "Content-Type": "application/json",
230
+ Authorization: `Bearer ${token}`
231
+ },
232
+ body: JSON.stringify(body)
233
+ });
234
+ if (!res.ok) await throwApiError(res);
235
+ return await res.json();
236
+ }
209
237
  async function createTransfer(apiBaseUrl, token, params) {
210
238
  if (!params.merchantAuthorization) {
211
239
  throw new Error("merchantAuthorization is required for transfer creation.");
@@ -1470,15 +1498,6 @@ function useAuthorizationExecutor(options) {
1470
1498
  },
1471
1499
  [apiBaseUrl, dispatchAction]
1472
1500
  );
1473
- const executeSession = react.useCallback(
1474
- async (transfer) => {
1475
- if (!transfer.authorizationSessions?.length) {
1476
- throw new Error("No authorization sessions available.");
1477
- }
1478
- await executeSessionById(transfer.authorizationSessions[0].id);
1479
- },
1480
- [executeSessionById]
1481
- );
1482
1501
  return {
1483
1502
  executing,
1484
1503
  results,
@@ -1486,8 +1505,7 @@ function useAuthorizationExecutor(options) {
1486
1505
  currentAction,
1487
1506
  pendingSelectSource,
1488
1507
  resolveSelectSource,
1489
- executeSessionById,
1490
- executeSession
1508
+ executeSessionById
1491
1509
  };
1492
1510
  }
1493
1511
  function useTransferSigning(pollIntervalMs = 2e3, options) {
@@ -1845,16 +1863,13 @@ function buildSelectSourceChoices(options) {
1845
1863
 
1846
1864
  // src/paymentReducer.ts
1847
1865
  function deriveSourceTypeAndId(state) {
1848
- if (state.connectingNewAccount) {
1849
- return { sourceType: "providerId", sourceId: state.selectedProviderId ?? "" };
1850
- }
1851
1866
  if (state.selectedWalletId) {
1852
1867
  return { sourceType: "walletId", sourceId: state.selectedWalletId };
1853
1868
  }
1854
1869
  if (state.selectedAccountId) {
1855
1870
  return { sourceType: "accountId", sourceId: state.selectedAccountId };
1856
1871
  }
1857
- return { sourceType: "providerId", sourceId: state.selectedProviderId ?? "" };
1872
+ return { sourceType: "accountId", sourceId: "" };
1858
1873
  }
1859
1874
  function createInitialState(config) {
1860
1875
  return {
@@ -1864,10 +1879,9 @@ function createInitialState(config) {
1864
1879
  accounts: [],
1865
1880
  chains: [],
1866
1881
  loadingData: false,
1882
+ selectedProviderId: null,
1867
1883
  selectedAccountId: null,
1868
1884
  selectedWalletId: null,
1869
- selectedProviderId: null,
1870
- connectingNewAccount: false,
1871
1885
  amount: config.depositAmount != null ? config.depositAmount.toString() : "",
1872
1886
  transfer: null,
1873
1887
  creatingTransfer: false,
@@ -1932,8 +1946,6 @@ function paymentReducer(state, action) {
1932
1946
  if (action.defaults) {
1933
1947
  next.selectedAccountId = action.defaults.accountId;
1934
1948
  next.selectedWalletId = action.defaults.walletId;
1935
- } else if (action.fallbackProviderId && !state.connectingNewAccount) {
1936
- next.selectedProviderId = action.fallbackProviderId;
1937
1949
  }
1938
1950
  if (action.clearMobileState) {
1939
1951
  next.mobileFlow = false;
@@ -1955,7 +1967,6 @@ function paymentReducer(state, action) {
1955
1967
  if (action.defaults) {
1956
1968
  next.selectedAccountId = action.defaults.accountId;
1957
1969
  next.selectedWalletId = action.defaults.walletId;
1958
- next.connectingNewAccount = false;
1959
1970
  }
1960
1971
  return next;
1961
1972
  }
@@ -1965,14 +1976,13 @@ function paymentReducer(state, action) {
1965
1976
  ...state,
1966
1977
  selectedProviderId: action.providerId,
1967
1978
  selectedAccountId: null,
1968
- connectingNewAccount: true
1979
+ selectedWalletId: null
1969
1980
  };
1970
1981
  case "SELECT_ACCOUNT":
1971
1982
  return {
1972
1983
  ...state,
1973
1984
  selectedAccountId: action.accountId,
1974
1985
  selectedWalletId: action.walletId,
1975
- connectingNewAccount: false,
1976
1986
  step: "deposit"
1977
1987
  };
1978
1988
  // ── Transfer lifecycle ───────────────────────────────────────
@@ -2035,7 +2045,7 @@ function paymentReducer(state, action) {
2035
2045
  case "MOBILE_SETUP_COMPLETE":
2036
2046
  return {
2037
2047
  ...state,
2038
- transfer: action.transfer,
2048
+ transfer: action.transfer ?? state.transfer,
2039
2049
  error: null,
2040
2050
  mobileFlow: false,
2041
2051
  deeplinkUri: null,
@@ -2057,7 +2067,7 @@ function paymentReducer(state, action) {
2057
2067
  ...state,
2058
2068
  mobileFlow: true,
2059
2069
  deeplinkUri: action.deeplinkUri,
2060
- selectedProviderId: action.providerId,
2070
+ selectedProviderId: action.providerId ?? state.selectedProviderId,
2061
2071
  error: action.error ?? null,
2062
2072
  step: "open-wallet"
2063
2073
  };
@@ -2113,7 +2123,7 @@ function paymentReducer(state, action) {
2113
2123
  amount: action.depositAmount != null ? action.depositAmount.toString() : "",
2114
2124
  mobileFlow: false,
2115
2125
  deeplinkUri: null,
2116
- connectingNewAccount: false,
2126
+ selectedProviderId: null,
2117
2127
  selectedWalletId: null,
2118
2128
  selectedAccountId: action.firstAccountId
2119
2129
  };
@@ -5131,6 +5141,7 @@ function SwypePaymentInner({
5131
5141
  );
5132
5142
  const loadingDataRef = react.useRef(false);
5133
5143
  const pollingTransferIdRef = react.useRef(null);
5144
+ const setupAccountIdRef = react.useRef(null);
5134
5145
  const mobileSetupFlowRef = react.useRef(false);
5135
5146
  const handlingMobileReturnRef = react.useRef(false);
5136
5147
  const processingStartedAtRef = react.useRef(null);
@@ -5263,11 +5274,11 @@ function SwypePaymentInner({
5263
5274
  accounts: state.accounts,
5264
5275
  persistedMobileFlow: loadMobileFlowState(),
5265
5276
  mobileSetupInProgress: mobileSetupFlowRef.current,
5266
- connectingNewAccount: state.connectingNewAccount
5277
+ connectingNewAccount: false
5267
5278
  });
5268
5279
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5269
5280
  dispatch({ type: "NAVIGATE", step: resolved.step });
5270
- }, [getAccessToken, apiBaseUrl, state.accounts, state.connectingNewAccount]);
5281
+ }, [getAccessToken, apiBaseUrl, state.accounts]);
5271
5282
  const handleRegisterPasskey = react.useCallback(async () => {
5272
5283
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
5273
5284
  dispatch({ type: "SET_ERROR", error: null });
@@ -5312,7 +5323,7 @@ function SwypePaymentInner({
5312
5323
  accounts: state.accounts,
5313
5324
  persistedMobileFlow: loadMobileFlowState(),
5314
5325
  mobileSetupInProgress: mobileSetupFlowRef.current,
5315
- connectingNewAccount: state.connectingNewAccount
5326
+ connectingNewAccount: false
5316
5327
  });
5317
5328
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5318
5329
  dispatch({ type: "NAVIGATE", step: resolved.step });
@@ -5325,7 +5336,7 @@ function SwypePaymentInner({
5325
5336
  } finally {
5326
5337
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
5327
5338
  }
5328
- }, [user, getAccessToken, apiBaseUrl, state.accounts, state.connectingNewAccount]);
5339
+ }, [user, getAccessToken, apiBaseUrl, state.accounts]);
5329
5340
  const handleVerifyPasskeyViaPopup = react.useCallback(async () => {
5330
5341
  dispatch({ type: "SET_VERIFYING_PASSKEY", value: true });
5331
5342
  dispatch({ type: "SET_ERROR", error: null });
@@ -5349,7 +5360,7 @@ function SwypePaymentInner({
5349
5360
  accounts: state.accounts,
5350
5361
  persistedMobileFlow: loadMobileFlowState(),
5351
5362
  mobileSetupInProgress: mobileSetupFlowRef.current,
5352
- connectingNewAccount: state.connectingNewAccount
5363
+ connectingNewAccount: false
5353
5364
  });
5354
5365
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5355
5366
  dispatch({ type: "NAVIGATE", step: resolved.step });
@@ -5368,7 +5379,7 @@ function SwypePaymentInner({
5368
5379
  } finally {
5369
5380
  dispatch({ type: "SET_VERIFYING_PASSKEY", value: false });
5370
5381
  }
5371
- }, [state.knownCredentialIds, getAccessToken, apiBaseUrl, state.accounts, state.connectingNewAccount]);
5382
+ }, [state.knownCredentialIds, getAccessToken, apiBaseUrl, state.accounts]);
5372
5383
  const reloadAccounts = react.useCallback(async () => {
5373
5384
  const token = await getAccessToken();
5374
5385
  if (!token || !state.activeCredentialId) return;
@@ -5420,8 +5431,7 @@ function SwypePaymentInner({
5420
5431
  dispatch({ type: "NAVIGATE", step: "create-passkey" });
5421
5432
  return;
5422
5433
  }
5423
- const isSetupRedirect = mobileSetupFlowRef.current;
5424
- dispatch({ type: "PAY_STARTED", isSetupRedirect });
5434
+ dispatch({ type: "PAY_STARTED", isSetupRedirect: false });
5425
5435
  processingStartedAtRef.current = Date.now();
5426
5436
  try {
5427
5437
  if (state.transfer?.status === "AUTHORIZED") {
@@ -5442,23 +5452,6 @@ function SwypePaymentInner({
5442
5452
  effectiveSourceId = activeWallet.id;
5443
5453
  }
5444
5454
  }
5445
- const isActiveWallet = effectiveSourceType === "walletId" && state.accounts.some(
5446
- (a) => a.wallets.some((w) => w.id === effectiveSourceId && w.status === "ACTIVE")
5447
- );
5448
- if (!isActiveWallet && !isSetupRedirect) {
5449
- let found = false;
5450
- for (const acct of state.accounts) {
5451
- for (const wallet of acct.wallets) {
5452
- if (wallet.status === "ACTIVE" && wallet.sources.some((s) => s.balance.available.amount >= payAmount)) {
5453
- effectiveSourceType = "walletId";
5454
- effectiveSourceId = wallet.id;
5455
- found = true;
5456
- break;
5457
- }
5458
- }
5459
- if (found) break;
5460
- }
5461
- }
5462
5455
  const t = await createTransfer(apiBaseUrl, token, {
5463
5456
  id: idempotencyKey,
5464
5457
  credentialId: state.activeCredentialId,
@@ -5469,27 +5462,14 @@ function SwypePaymentInner({
5469
5462
  amount: payAmount
5470
5463
  });
5471
5464
  dispatch({ type: "TRANSFER_CREATED", transfer: t });
5472
- if (t.authorizationSessions && t.authorizationSessions.length > 0) {
5473
- const useConnector = shouldUseWalletConnector({
5474
- useWalletConnector: useWalletConnectorProp,
5475
- userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
5476
- });
5477
- if (!useConnector) {
5478
- const uri = t.authorizationSessions[0].uri;
5479
- pollingTransferIdRef.current = t.id;
5480
- polling.startPolling(t.id);
5481
- dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: uri });
5482
- persistMobileFlowState({
5483
- transferId: t.id,
5484
- deeplinkUri: uri,
5485
- providerId: sourceOverrides?.sourceType === "providerId" ? sourceOverrides.sourceId : state.selectedProviderId,
5486
- isSetup: mobileSetupFlowRef.current
5487
- });
5488
- triggerDeeplink(uri);
5489
- return;
5490
- } else {
5491
- await authExecutor.executeSession(t);
5492
- }
5465
+ if (t.status === "COMPLETED") {
5466
+ dispatch({ type: "TRANSFER_COMPLETED", transfer: t });
5467
+ onComplete?.(t);
5468
+ return;
5469
+ }
5470
+ if (t.status === "FAILED") {
5471
+ dispatch({ type: "TRANSFER_FAILED", transfer: t, error: "Transfer failed." });
5472
+ return;
5493
5473
  }
5494
5474
  const signedTransfer = await transferSigning.signTransfer(t.id);
5495
5475
  dispatch({ type: "TRANSFER_SIGNED", transfer: signedTransfer });
@@ -5500,7 +5480,7 @@ function SwypePaymentInner({
5500
5480
  dispatch({
5501
5481
  type: "PAY_ERROR",
5502
5482
  error: msg,
5503
- fallbackStep: isSetupRedirect ? "wallet-picker" : "deposit"
5483
+ fallbackStep: "deposit"
5504
5484
  });
5505
5485
  onError?.(msg);
5506
5486
  } finally {
@@ -5512,15 +5492,13 @@ function SwypePaymentInner({
5512
5492
  state.activeCredentialId,
5513
5493
  state.transfer,
5514
5494
  state.accounts,
5515
- state.selectedProviderId,
5516
5495
  destination,
5517
5496
  apiBaseUrl,
5518
5497
  getAccessToken,
5519
- authExecutor,
5520
5498
  transferSigning,
5521
5499
  polling,
5522
5500
  onError,
5523
- useWalletConnectorProp,
5501
+ onComplete,
5524
5502
  idempotencyKey,
5525
5503
  merchantAuthorization
5526
5504
  ]);
@@ -5551,7 +5529,6 @@ function SwypePaymentInner({
5551
5529
  }
5552
5530
  }
5553
5531
  const t = await createTransfer(apiBaseUrl, token, {
5554
- id: idempotencyKey,
5555
5532
  credentialId: state.activeCredentialId,
5556
5533
  merchantAuthorization,
5557
5534
  sourceType: effectiveSourceType,
@@ -5559,23 +5536,7 @@ function SwypePaymentInner({
5559
5536
  destination,
5560
5537
  amount: parsedAmount
5561
5538
  });
5562
- if (t.authorizationSessions && t.authorizationSessions.length > 0) {
5563
- const uri = t.authorizationSessions[0].uri;
5564
- pollingTransferIdRef.current = t.id;
5565
- mobileSetupFlowRef.current = true;
5566
- handlingMobileReturnRef.current = false;
5567
- polling.startPolling(t.id);
5568
- dispatch({ type: "INCREASE_LIMIT_DEEPLINK", transfer: t, deeplinkUri: uri });
5569
- persistMobileFlowState({
5570
- transferId: t.id,
5571
- deeplinkUri: uri,
5572
- providerId: state.selectedProviderId,
5573
- isSetup: true
5574
- });
5575
- triggerDeeplink(uri);
5576
- } else {
5577
- dispatch({ type: "TRANSFER_CREATED", transfer: t });
5578
- }
5539
+ dispatch({ type: "TRANSFER_CREATED", transfer: t });
5579
5540
  } catch (err) {
5580
5541
  captureException(err);
5581
5542
  const msg = err instanceof Error ? err.message : "Failed to increase limit";
@@ -5590,12 +5551,10 @@ function SwypePaymentInner({
5590
5551
  sourceType,
5591
5552
  state.activeCredentialId,
5592
5553
  state.accounts,
5593
- state.selectedProviderId,
5594
5554
  apiBaseUrl,
5595
5555
  getAccessToken,
5596
5556
  polling,
5597
5557
  onError,
5598
- idempotencyKey,
5599
5558
  merchantAuthorization,
5600
5559
  destination
5601
5560
  ]);
@@ -5627,31 +5586,78 @@ function SwypePaymentInner({
5627
5586
  polling.startPolling(transferIdToResume);
5628
5587
  }
5629
5588
  }, [handleAuthorizedMobileReturn, polling, state.transfer]);
5630
- const handleSelectProvider = react.useCallback((providerId) => {
5589
+ const handleSelectProvider = react.useCallback(async (providerId) => {
5631
5590
  dispatch({ type: "SELECT_PROVIDER", providerId });
5632
- const isMobile = !shouldUseWalletConnector({
5633
- useWalletConnector: useWalletConnectorProp,
5634
- userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
5635
- });
5636
- if (isMobile) {
5637
- handlingMobileReturnRef.current = false;
5638
- mobileSetupFlowRef.current = true;
5639
- const amount = depositAmount ?? 5;
5640
- handlePay(amount, { sourceType: "providerId", sourceId: providerId });
5641
- } else {
5642
- dispatch({ type: "NAVIGATE", step: "deposit" });
5591
+ if (!state.activeCredentialId) {
5592
+ dispatch({ type: "SET_ERROR", error: "Create a passkey on this device before continuing." });
5593
+ dispatch({ type: "NAVIGATE", step: "create-passkey" });
5594
+ return;
5595
+ }
5596
+ const provider = state.providers.find((p) => p.id === providerId);
5597
+ const providerName = provider?.name ?? "Wallet";
5598
+ dispatch({ type: "PAY_STARTED", isSetupRedirect: true });
5599
+ try {
5600
+ const token = await getAccessToken();
5601
+ if (!token) throw new Error("Not authenticated");
5602
+ const accountId = crypto.randomUUID();
5603
+ const account = await createAccount(apiBaseUrl, token, {
5604
+ id: accountId,
5605
+ name: providerName,
5606
+ credentialId: state.activeCredentialId,
5607
+ providerId
5608
+ });
5609
+ const session = account.authorizationSessions?.[0];
5610
+ if (!session) throw new Error("No authorization session returned.");
5611
+ const isMobile = !shouldUseWalletConnector({
5612
+ useWalletConnector: useWalletConnectorProp,
5613
+ userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
5614
+ });
5615
+ if (isMobile) {
5616
+ handlingMobileReturnRef.current = false;
5617
+ mobileSetupFlowRef.current = true;
5618
+ setupAccountIdRef.current = account.id;
5619
+ persistMobileFlowState({
5620
+ accountId: account.id,
5621
+ sessionId: session.id,
5622
+ deeplinkUri: session.uri,
5623
+ providerId,
5624
+ isSetup: true
5625
+ });
5626
+ dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
5627
+ triggerDeeplink(session.uri);
5628
+ } else {
5629
+ await authExecutor.executeSessionById(session.id);
5630
+ await reloadAccounts();
5631
+ dispatch({ type: "NAVIGATE", step: "deposit" });
5632
+ }
5633
+ } catch (err) {
5634
+ captureException(err);
5635
+ const msg = err instanceof Error ? err.message : "Failed to set up wallet";
5636
+ dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
5637
+ onError?.(msg);
5638
+ } finally {
5639
+ dispatch({ type: "PAY_ENDED" });
5643
5640
  }
5644
- }, [useWalletConnectorProp, depositAmount, handlePay]);
5641
+ }, [
5642
+ state.activeCredentialId,
5643
+ state.providers,
5644
+ apiBaseUrl,
5645
+ getAccessToken,
5646
+ authExecutor,
5647
+ useWalletConnectorProp,
5648
+ reloadAccounts,
5649
+ onError
5650
+ ]);
5645
5651
  const handleContinueConnection = react.useCallback(
5646
5652
  (accountId) => {
5647
5653
  const acct = state.accounts.find((a) => a.id === accountId);
5648
- dispatch({
5649
- type: "SELECT_ACCOUNT",
5650
- accountId,
5651
- walletId: acct?.wallets[0]?.id ?? null
5652
- });
5654
+ if (!acct) return;
5655
+ const matchedProvider = state.providers.find((p) => p.name === acct.name);
5656
+ if (matchedProvider) {
5657
+ handleSelectProvider(matchedProvider.id);
5658
+ }
5653
5659
  },
5654
- [state.accounts]
5660
+ [state.accounts, state.providers, handleSelectProvider]
5655
5661
  );
5656
5662
  const handleNewPayment = react.useCallback(() => {
5657
5663
  clearMobileFlowState();
@@ -5751,7 +5757,7 @@ function SwypePaymentInner({
5751
5757
  connectingNewAccount: false
5752
5758
  });
5753
5759
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5754
- if (resolved.step === "deposit" && persisted && persisted.isSetup) {
5760
+ if (resolved.step === "deposit" && persisted && persisted.isSetup && persisted.transferId) {
5755
5761
  try {
5756
5762
  const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
5757
5763
  if (cancelled) return;
@@ -5762,7 +5768,12 @@ function SwypePaymentInner({
5762
5768
  } catch {
5763
5769
  }
5764
5770
  }
5765
- if (resolved.step === "open-wallet" && persisted) {
5771
+ if (resolved.step === "open-wallet" && persisted && persisted.accountId && !persisted.transferId) {
5772
+ clearMobileFlowState();
5773
+ dispatch({ type: "NAVIGATE", step: "deposit" });
5774
+ return;
5775
+ }
5776
+ if (resolved.step === "open-wallet" && persisted && persisted.transferId) {
5766
5777
  try {
5767
5778
  const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
5768
5779
  if (cancelled) return;
@@ -5808,9 +5819,9 @@ function SwypePaymentInner({
5808
5819
  providerId: persisted.providerId,
5809
5820
  error: err instanceof Error ? err.message : "Unable to refresh wallet authorization status."
5810
5821
  });
5811
- pollingTransferIdRef.current = persisted.transferId;
5822
+ pollingTransferIdRef.current = persisted.transferId ?? null;
5812
5823
  mobileSetupFlowRef.current = persisted.isSetup;
5813
- pollingRef.current.startPolling(persisted.transferId);
5824
+ if (persisted.transferId) pollingRef.current.startPolling(persisted.transferId);
5814
5825
  return;
5815
5826
  }
5816
5827
  dispatch({
@@ -5818,9 +5829,9 @@ function SwypePaymentInner({
5818
5829
  deeplinkUri: persisted.deeplinkUri,
5819
5830
  providerId: persisted.providerId
5820
5831
  });
5821
- pollingTransferIdRef.current = persisted.transferId;
5832
+ pollingTransferIdRef.current = persisted.transferId ?? null;
5822
5833
  mobileSetupFlowRef.current = persisted.isSetup;
5823
- pollingRef.current.startPolling(persisted.transferId);
5834
+ if (persisted.transferId) pollingRef.current.startPolling(persisted.transferId);
5824
5835
  return;
5825
5836
  }
5826
5837
  dispatch({ type: "NAVIGATE", step: resolved.step });
@@ -5927,7 +5938,7 @@ function SwypePaymentInner({
5927
5938
  accounts: accts,
5928
5939
  persistedMobileFlow: persisted,
5929
5940
  mobileSetupInProgress: mobileSetupFlowRef.current,
5930
- connectingNewAccount: state.connectingNewAccount
5941
+ connectingNewAccount: false
5931
5942
  });
5932
5943
  const correctableSteps = ["deposit", "wallet-picker", "open-wallet"];
5933
5944
  dispatch({
@@ -5936,7 +5947,6 @@ function SwypePaymentInner({
5936
5947
  accounts: accts,
5937
5948
  chains: chn,
5938
5949
  defaults,
5939
- fallbackProviderId: !defaults && prov.length > 0 ? prov[0].id : null,
5940
5950
  resolvedStep: correctableSteps.includes(state.step) ? resolved.step : void 0,
5941
5951
  clearMobileState: resolved.clearPersistedFlow
5942
5952
  });
@@ -5968,8 +5978,7 @@ function SwypePaymentInner({
5968
5978
  apiBaseUrl,
5969
5979
  getAccessToken,
5970
5980
  state.activeCredentialId,
5971
- depositAmount,
5972
- state.connectingNewAccount
5981
+ depositAmount
5973
5982
  ]);
5974
5983
  react.useEffect(() => {
5975
5984
  if (!polling.transfer) return;
@@ -6018,6 +6027,46 @@ function SwypePaymentInner({
6018
6027
  if (!polledTransfer || polledTransfer.status !== "AUTHORIZED") return;
6019
6028
  void handleAuthorizedMobileReturn(polledTransfer, mobileSetupFlowRef.current);
6020
6029
  }, [state.mobileFlow, polling.transfer, handleAuthorizedMobileReturn]);
6030
+ react.useEffect(() => {
6031
+ if (!state.mobileFlow || !mobileSetupFlowRef.current) return;
6032
+ if (state.step !== "open-wallet") return;
6033
+ if (!state.activeCredentialId || !setupAccountIdRef.current) return;
6034
+ const accountId = setupAccountIdRef.current;
6035
+ const credentialId = state.activeCredentialId;
6036
+ let cancelled = false;
6037
+ const POLL_INTERVAL_MS = 3e3;
6038
+ const poll = async () => {
6039
+ try {
6040
+ const token = await getAccessTokenRef.current();
6041
+ if (!token || cancelled) return;
6042
+ const acct = await fetchAccount(apiBaseUrl, token, accountId, credentialId);
6043
+ if (cancelled) return;
6044
+ const hasActive = acct.wallets.some((w) => w.status === "ACTIVE");
6045
+ if (hasActive) {
6046
+ cancelled = true;
6047
+ mobileSetupFlowRef.current = false;
6048
+ setupAccountIdRef.current = null;
6049
+ clearMobileFlowState();
6050
+ await reloadAccounts();
6051
+ dispatch({ type: "MOBILE_SETUP_COMPLETE" });
6052
+ }
6053
+ } catch {
6054
+ }
6055
+ };
6056
+ poll();
6057
+ const intervalId = window.setInterval(poll, POLL_INTERVAL_MS);
6058
+ const handleVisibility = () => {
6059
+ if (document.visibilityState === "visible" && !cancelled) {
6060
+ poll();
6061
+ }
6062
+ };
6063
+ document.addEventListener("visibilitychange", handleVisibility);
6064
+ return () => {
6065
+ cancelled = true;
6066
+ window.clearInterval(intervalId);
6067
+ document.removeEventListener("visibilitychange", handleVisibility);
6068
+ };
6069
+ }, [state.mobileFlow, state.step, state.activeCredentialId, apiBaseUrl, reloadAccounts]);
6021
6070
  react.useEffect(() => {
6022
6071
  if (!state.mobileFlow) return;
6023
6072
  if (handlingMobileReturnRef.current) return;