@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.js CHANGED
@@ -156,7 +156,9 @@ function useSwypeDepositAmount() {
156
156
  // src/api.ts
157
157
  var api_exports = {};
158
158
  __export(api_exports, {
159
+ createAccount: () => createAccount,
159
160
  createTransfer: () => createTransfer,
161
+ fetchAccount: () => fetchAccount,
160
162
  fetchAccounts: () => fetchAccounts,
161
163
  fetchAuthorizationSession: () => fetchAuthorizationSession,
162
164
  fetchChains: () => fetchChains,
@@ -203,6 +205,32 @@ async function fetchAccounts(apiBaseUrl, token, credentialId) {
203
205
  const data = await res.json();
204
206
  return data.items;
205
207
  }
208
+ async function fetchAccount(apiBaseUrl, token, accountId, credentialId) {
209
+ const params = new URLSearchParams({ credentialId });
210
+ const res = await fetch(`${apiBaseUrl}/v1/accounts/${accountId}?${params.toString()}`, {
211
+ headers: { Authorization: `Bearer ${token}` }
212
+ });
213
+ if (!res.ok) await throwApiError(res);
214
+ return await res.json();
215
+ }
216
+ async function createAccount(apiBaseUrl, token, params) {
217
+ const body = {
218
+ id: params.id ?? crypto.randomUUID(),
219
+ name: params.name,
220
+ credentialId: params.credentialId,
221
+ providerId: params.providerId
222
+ };
223
+ const res = await fetch(`${apiBaseUrl}/v1/accounts`, {
224
+ method: "POST",
225
+ headers: {
226
+ "Content-Type": "application/json",
227
+ Authorization: `Bearer ${token}`
228
+ },
229
+ body: JSON.stringify(body)
230
+ });
231
+ if (!res.ok) await throwApiError(res);
232
+ return await res.json();
233
+ }
206
234
  async function createTransfer(apiBaseUrl, token, params) {
207
235
  if (!params.merchantAuthorization) {
208
236
  throw new Error("merchantAuthorization is required for transfer creation.");
@@ -1467,15 +1495,6 @@ function useAuthorizationExecutor(options) {
1467
1495
  },
1468
1496
  [apiBaseUrl, dispatchAction]
1469
1497
  );
1470
- const executeSession = useCallback(
1471
- async (transfer) => {
1472
- if (!transfer.authorizationSessions?.length) {
1473
- throw new Error("No authorization sessions available.");
1474
- }
1475
- await executeSessionById(transfer.authorizationSessions[0].id);
1476
- },
1477
- [executeSessionById]
1478
- );
1479
1498
  return {
1480
1499
  executing,
1481
1500
  results,
@@ -1483,8 +1502,7 @@ function useAuthorizationExecutor(options) {
1483
1502
  currentAction,
1484
1503
  pendingSelectSource,
1485
1504
  resolveSelectSource,
1486
- executeSessionById,
1487
- executeSession
1505
+ executeSessionById
1488
1506
  };
1489
1507
  }
1490
1508
  function useTransferSigning(pollIntervalMs = 2e3, options) {
@@ -1842,16 +1860,13 @@ function buildSelectSourceChoices(options) {
1842
1860
 
1843
1861
  // src/paymentReducer.ts
1844
1862
  function deriveSourceTypeAndId(state) {
1845
- if (state.connectingNewAccount) {
1846
- return { sourceType: "providerId", sourceId: state.selectedProviderId ?? "" };
1847
- }
1848
1863
  if (state.selectedWalletId) {
1849
1864
  return { sourceType: "walletId", sourceId: state.selectedWalletId };
1850
1865
  }
1851
1866
  if (state.selectedAccountId) {
1852
1867
  return { sourceType: "accountId", sourceId: state.selectedAccountId };
1853
1868
  }
1854
- return { sourceType: "providerId", sourceId: state.selectedProviderId ?? "" };
1869
+ return { sourceType: "accountId", sourceId: "" };
1855
1870
  }
1856
1871
  function createInitialState(config) {
1857
1872
  return {
@@ -1861,10 +1876,9 @@ function createInitialState(config) {
1861
1876
  accounts: [],
1862
1877
  chains: [],
1863
1878
  loadingData: false,
1879
+ selectedProviderId: null,
1864
1880
  selectedAccountId: null,
1865
1881
  selectedWalletId: null,
1866
- selectedProviderId: null,
1867
- connectingNewAccount: false,
1868
1882
  amount: config.depositAmount != null ? config.depositAmount.toString() : "",
1869
1883
  transfer: null,
1870
1884
  creatingTransfer: false,
@@ -1929,8 +1943,6 @@ function paymentReducer(state, action) {
1929
1943
  if (action.defaults) {
1930
1944
  next.selectedAccountId = action.defaults.accountId;
1931
1945
  next.selectedWalletId = action.defaults.walletId;
1932
- } else if (action.fallbackProviderId && !state.connectingNewAccount) {
1933
- next.selectedProviderId = action.fallbackProviderId;
1934
1946
  }
1935
1947
  if (action.clearMobileState) {
1936
1948
  next.mobileFlow = false;
@@ -1952,7 +1964,6 @@ function paymentReducer(state, action) {
1952
1964
  if (action.defaults) {
1953
1965
  next.selectedAccountId = action.defaults.accountId;
1954
1966
  next.selectedWalletId = action.defaults.walletId;
1955
- next.connectingNewAccount = false;
1956
1967
  }
1957
1968
  return next;
1958
1969
  }
@@ -1962,14 +1973,13 @@ function paymentReducer(state, action) {
1962
1973
  ...state,
1963
1974
  selectedProviderId: action.providerId,
1964
1975
  selectedAccountId: null,
1965
- connectingNewAccount: true
1976
+ selectedWalletId: null
1966
1977
  };
1967
1978
  case "SELECT_ACCOUNT":
1968
1979
  return {
1969
1980
  ...state,
1970
1981
  selectedAccountId: action.accountId,
1971
1982
  selectedWalletId: action.walletId,
1972
- connectingNewAccount: false,
1973
1983
  step: "deposit"
1974
1984
  };
1975
1985
  // ── Transfer lifecycle ───────────────────────────────────────
@@ -2032,7 +2042,7 @@ function paymentReducer(state, action) {
2032
2042
  case "MOBILE_SETUP_COMPLETE":
2033
2043
  return {
2034
2044
  ...state,
2035
- transfer: action.transfer,
2045
+ transfer: action.transfer ?? state.transfer,
2036
2046
  error: null,
2037
2047
  mobileFlow: false,
2038
2048
  deeplinkUri: null,
@@ -2054,7 +2064,7 @@ function paymentReducer(state, action) {
2054
2064
  ...state,
2055
2065
  mobileFlow: true,
2056
2066
  deeplinkUri: action.deeplinkUri,
2057
- selectedProviderId: action.providerId,
2067
+ selectedProviderId: action.providerId ?? state.selectedProviderId,
2058
2068
  error: action.error ?? null,
2059
2069
  step: "open-wallet"
2060
2070
  };
@@ -2110,7 +2120,7 @@ function paymentReducer(state, action) {
2110
2120
  amount: action.depositAmount != null ? action.depositAmount.toString() : "",
2111
2121
  mobileFlow: false,
2112
2122
  deeplinkUri: null,
2113
- connectingNewAccount: false,
2123
+ selectedProviderId: null,
2114
2124
  selectedWalletId: null,
2115
2125
  selectedAccountId: action.firstAccountId
2116
2126
  };
@@ -5128,6 +5138,7 @@ function SwypePaymentInner({
5128
5138
  );
5129
5139
  const loadingDataRef = useRef(false);
5130
5140
  const pollingTransferIdRef = useRef(null);
5141
+ const setupAccountIdRef = useRef(null);
5131
5142
  const mobileSetupFlowRef = useRef(false);
5132
5143
  const handlingMobileReturnRef = useRef(false);
5133
5144
  const processingStartedAtRef = useRef(null);
@@ -5260,11 +5271,11 @@ function SwypePaymentInner({
5260
5271
  accounts: state.accounts,
5261
5272
  persistedMobileFlow: loadMobileFlowState(),
5262
5273
  mobileSetupInProgress: mobileSetupFlowRef.current,
5263
- connectingNewAccount: state.connectingNewAccount
5274
+ connectingNewAccount: false
5264
5275
  });
5265
5276
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5266
5277
  dispatch({ type: "NAVIGATE", step: resolved.step });
5267
- }, [getAccessToken, apiBaseUrl, state.accounts, state.connectingNewAccount]);
5278
+ }, [getAccessToken, apiBaseUrl, state.accounts]);
5268
5279
  const handleRegisterPasskey = useCallback(async () => {
5269
5280
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
5270
5281
  dispatch({ type: "SET_ERROR", error: null });
@@ -5309,7 +5320,7 @@ function SwypePaymentInner({
5309
5320
  accounts: state.accounts,
5310
5321
  persistedMobileFlow: loadMobileFlowState(),
5311
5322
  mobileSetupInProgress: mobileSetupFlowRef.current,
5312
- connectingNewAccount: state.connectingNewAccount
5323
+ connectingNewAccount: false
5313
5324
  });
5314
5325
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5315
5326
  dispatch({ type: "NAVIGATE", step: resolved.step });
@@ -5322,7 +5333,7 @@ function SwypePaymentInner({
5322
5333
  } finally {
5323
5334
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
5324
5335
  }
5325
- }, [user, getAccessToken, apiBaseUrl, state.accounts, state.connectingNewAccount]);
5336
+ }, [user, getAccessToken, apiBaseUrl, state.accounts]);
5326
5337
  const handleVerifyPasskeyViaPopup = useCallback(async () => {
5327
5338
  dispatch({ type: "SET_VERIFYING_PASSKEY", value: true });
5328
5339
  dispatch({ type: "SET_ERROR", error: null });
@@ -5346,7 +5357,7 @@ function SwypePaymentInner({
5346
5357
  accounts: state.accounts,
5347
5358
  persistedMobileFlow: loadMobileFlowState(),
5348
5359
  mobileSetupInProgress: mobileSetupFlowRef.current,
5349
- connectingNewAccount: state.connectingNewAccount
5360
+ connectingNewAccount: false
5350
5361
  });
5351
5362
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5352
5363
  dispatch({ type: "NAVIGATE", step: resolved.step });
@@ -5365,7 +5376,7 @@ function SwypePaymentInner({
5365
5376
  } finally {
5366
5377
  dispatch({ type: "SET_VERIFYING_PASSKEY", value: false });
5367
5378
  }
5368
- }, [state.knownCredentialIds, getAccessToken, apiBaseUrl, state.accounts, state.connectingNewAccount]);
5379
+ }, [state.knownCredentialIds, getAccessToken, apiBaseUrl, state.accounts]);
5369
5380
  const reloadAccounts = useCallback(async () => {
5370
5381
  const token = await getAccessToken();
5371
5382
  if (!token || !state.activeCredentialId) return;
@@ -5417,8 +5428,7 @@ function SwypePaymentInner({
5417
5428
  dispatch({ type: "NAVIGATE", step: "create-passkey" });
5418
5429
  return;
5419
5430
  }
5420
- const isSetupRedirect = mobileSetupFlowRef.current;
5421
- dispatch({ type: "PAY_STARTED", isSetupRedirect });
5431
+ dispatch({ type: "PAY_STARTED", isSetupRedirect: false });
5422
5432
  processingStartedAtRef.current = Date.now();
5423
5433
  try {
5424
5434
  if (state.transfer?.status === "AUTHORIZED") {
@@ -5439,23 +5449,6 @@ function SwypePaymentInner({
5439
5449
  effectiveSourceId = activeWallet.id;
5440
5450
  }
5441
5451
  }
5442
- const isActiveWallet = effectiveSourceType === "walletId" && state.accounts.some(
5443
- (a) => a.wallets.some((w) => w.id === effectiveSourceId && w.status === "ACTIVE")
5444
- );
5445
- if (!isActiveWallet && !isSetupRedirect) {
5446
- let found = false;
5447
- for (const acct of state.accounts) {
5448
- for (const wallet of acct.wallets) {
5449
- if (wallet.status === "ACTIVE" && wallet.sources.some((s) => s.balance.available.amount >= payAmount)) {
5450
- effectiveSourceType = "walletId";
5451
- effectiveSourceId = wallet.id;
5452
- found = true;
5453
- break;
5454
- }
5455
- }
5456
- if (found) break;
5457
- }
5458
- }
5459
5452
  const t = await createTransfer(apiBaseUrl, token, {
5460
5453
  id: idempotencyKey,
5461
5454
  credentialId: state.activeCredentialId,
@@ -5466,27 +5459,14 @@ function SwypePaymentInner({
5466
5459
  amount: payAmount
5467
5460
  });
5468
5461
  dispatch({ type: "TRANSFER_CREATED", transfer: t });
5469
- if (t.authorizationSessions && t.authorizationSessions.length > 0) {
5470
- const useConnector = shouldUseWalletConnector({
5471
- useWalletConnector: useWalletConnectorProp,
5472
- userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
5473
- });
5474
- if (!useConnector) {
5475
- const uri = t.authorizationSessions[0].uri;
5476
- pollingTransferIdRef.current = t.id;
5477
- polling.startPolling(t.id);
5478
- dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: uri });
5479
- persistMobileFlowState({
5480
- transferId: t.id,
5481
- deeplinkUri: uri,
5482
- providerId: sourceOverrides?.sourceType === "providerId" ? sourceOverrides.sourceId : state.selectedProviderId,
5483
- isSetup: mobileSetupFlowRef.current
5484
- });
5485
- triggerDeeplink(uri);
5486
- return;
5487
- } else {
5488
- await authExecutor.executeSession(t);
5489
- }
5462
+ if (t.status === "COMPLETED") {
5463
+ dispatch({ type: "TRANSFER_COMPLETED", transfer: t });
5464
+ onComplete?.(t);
5465
+ return;
5466
+ }
5467
+ if (t.status === "FAILED") {
5468
+ dispatch({ type: "TRANSFER_FAILED", transfer: t, error: "Transfer failed." });
5469
+ return;
5490
5470
  }
5491
5471
  const signedTransfer = await transferSigning.signTransfer(t.id);
5492
5472
  dispatch({ type: "TRANSFER_SIGNED", transfer: signedTransfer });
@@ -5497,7 +5477,7 @@ function SwypePaymentInner({
5497
5477
  dispatch({
5498
5478
  type: "PAY_ERROR",
5499
5479
  error: msg,
5500
- fallbackStep: isSetupRedirect ? "wallet-picker" : "deposit"
5480
+ fallbackStep: "deposit"
5501
5481
  });
5502
5482
  onError?.(msg);
5503
5483
  } finally {
@@ -5509,15 +5489,13 @@ function SwypePaymentInner({
5509
5489
  state.activeCredentialId,
5510
5490
  state.transfer,
5511
5491
  state.accounts,
5512
- state.selectedProviderId,
5513
5492
  destination,
5514
5493
  apiBaseUrl,
5515
5494
  getAccessToken,
5516
- authExecutor,
5517
5495
  transferSigning,
5518
5496
  polling,
5519
5497
  onError,
5520
- useWalletConnectorProp,
5498
+ onComplete,
5521
5499
  idempotencyKey,
5522
5500
  merchantAuthorization
5523
5501
  ]);
@@ -5548,7 +5526,6 @@ function SwypePaymentInner({
5548
5526
  }
5549
5527
  }
5550
5528
  const t = await createTransfer(apiBaseUrl, token, {
5551
- id: idempotencyKey,
5552
5529
  credentialId: state.activeCredentialId,
5553
5530
  merchantAuthorization,
5554
5531
  sourceType: effectiveSourceType,
@@ -5556,23 +5533,7 @@ function SwypePaymentInner({
5556
5533
  destination,
5557
5534
  amount: parsedAmount
5558
5535
  });
5559
- if (t.authorizationSessions && t.authorizationSessions.length > 0) {
5560
- const uri = t.authorizationSessions[0].uri;
5561
- pollingTransferIdRef.current = t.id;
5562
- mobileSetupFlowRef.current = true;
5563
- handlingMobileReturnRef.current = false;
5564
- polling.startPolling(t.id);
5565
- dispatch({ type: "INCREASE_LIMIT_DEEPLINK", transfer: t, deeplinkUri: uri });
5566
- persistMobileFlowState({
5567
- transferId: t.id,
5568
- deeplinkUri: uri,
5569
- providerId: state.selectedProviderId,
5570
- isSetup: true
5571
- });
5572
- triggerDeeplink(uri);
5573
- } else {
5574
- dispatch({ type: "TRANSFER_CREATED", transfer: t });
5575
- }
5536
+ dispatch({ type: "TRANSFER_CREATED", transfer: t });
5576
5537
  } catch (err) {
5577
5538
  captureException(err);
5578
5539
  const msg = err instanceof Error ? err.message : "Failed to increase limit";
@@ -5587,12 +5548,10 @@ function SwypePaymentInner({
5587
5548
  sourceType,
5588
5549
  state.activeCredentialId,
5589
5550
  state.accounts,
5590
- state.selectedProviderId,
5591
5551
  apiBaseUrl,
5592
5552
  getAccessToken,
5593
5553
  polling,
5594
5554
  onError,
5595
- idempotencyKey,
5596
5555
  merchantAuthorization,
5597
5556
  destination
5598
5557
  ]);
@@ -5624,31 +5583,78 @@ function SwypePaymentInner({
5624
5583
  polling.startPolling(transferIdToResume);
5625
5584
  }
5626
5585
  }, [handleAuthorizedMobileReturn, polling, state.transfer]);
5627
- const handleSelectProvider = useCallback((providerId) => {
5586
+ const handleSelectProvider = useCallback(async (providerId) => {
5628
5587
  dispatch({ type: "SELECT_PROVIDER", providerId });
5629
- const isMobile = !shouldUseWalletConnector({
5630
- useWalletConnector: useWalletConnectorProp,
5631
- userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
5632
- });
5633
- if (isMobile) {
5634
- handlingMobileReturnRef.current = false;
5635
- mobileSetupFlowRef.current = true;
5636
- const amount = depositAmount ?? 5;
5637
- handlePay(amount, { sourceType: "providerId", sourceId: providerId });
5638
- } else {
5639
- dispatch({ type: "NAVIGATE", step: "deposit" });
5588
+ if (!state.activeCredentialId) {
5589
+ dispatch({ type: "SET_ERROR", error: "Create a passkey on this device before continuing." });
5590
+ dispatch({ type: "NAVIGATE", step: "create-passkey" });
5591
+ return;
5592
+ }
5593
+ const provider = state.providers.find((p) => p.id === providerId);
5594
+ const providerName = provider?.name ?? "Wallet";
5595
+ dispatch({ type: "PAY_STARTED", isSetupRedirect: true });
5596
+ try {
5597
+ const token = await getAccessToken();
5598
+ if (!token) throw new Error("Not authenticated");
5599
+ const accountId = crypto.randomUUID();
5600
+ const account = await createAccount(apiBaseUrl, token, {
5601
+ id: accountId,
5602
+ name: providerName,
5603
+ credentialId: state.activeCredentialId,
5604
+ providerId
5605
+ });
5606
+ const session = account.authorizationSessions?.[0];
5607
+ if (!session) throw new Error("No authorization session returned.");
5608
+ const isMobile = !shouldUseWalletConnector({
5609
+ useWalletConnector: useWalletConnectorProp,
5610
+ userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
5611
+ });
5612
+ if (isMobile) {
5613
+ handlingMobileReturnRef.current = false;
5614
+ mobileSetupFlowRef.current = true;
5615
+ setupAccountIdRef.current = account.id;
5616
+ persistMobileFlowState({
5617
+ accountId: account.id,
5618
+ sessionId: session.id,
5619
+ deeplinkUri: session.uri,
5620
+ providerId,
5621
+ isSetup: true
5622
+ });
5623
+ dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
5624
+ triggerDeeplink(session.uri);
5625
+ } else {
5626
+ await authExecutor.executeSessionById(session.id);
5627
+ await reloadAccounts();
5628
+ dispatch({ type: "NAVIGATE", step: "deposit" });
5629
+ }
5630
+ } catch (err) {
5631
+ captureException(err);
5632
+ const msg = err instanceof Error ? err.message : "Failed to set up wallet";
5633
+ dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
5634
+ onError?.(msg);
5635
+ } finally {
5636
+ dispatch({ type: "PAY_ENDED" });
5640
5637
  }
5641
- }, [useWalletConnectorProp, depositAmount, handlePay]);
5638
+ }, [
5639
+ state.activeCredentialId,
5640
+ state.providers,
5641
+ apiBaseUrl,
5642
+ getAccessToken,
5643
+ authExecutor,
5644
+ useWalletConnectorProp,
5645
+ reloadAccounts,
5646
+ onError
5647
+ ]);
5642
5648
  const handleContinueConnection = useCallback(
5643
5649
  (accountId) => {
5644
5650
  const acct = state.accounts.find((a) => a.id === accountId);
5645
- dispatch({
5646
- type: "SELECT_ACCOUNT",
5647
- accountId,
5648
- walletId: acct?.wallets[0]?.id ?? null
5649
- });
5651
+ if (!acct) return;
5652
+ const matchedProvider = state.providers.find((p) => p.name === acct.name);
5653
+ if (matchedProvider) {
5654
+ handleSelectProvider(matchedProvider.id);
5655
+ }
5650
5656
  },
5651
- [state.accounts]
5657
+ [state.accounts, state.providers, handleSelectProvider]
5652
5658
  );
5653
5659
  const handleNewPayment = useCallback(() => {
5654
5660
  clearMobileFlowState();
@@ -5748,7 +5754,7 @@ function SwypePaymentInner({
5748
5754
  connectingNewAccount: false
5749
5755
  });
5750
5756
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5751
- if (resolved.step === "deposit" && persisted && persisted.isSetup) {
5757
+ if (resolved.step === "deposit" && persisted && persisted.isSetup && persisted.transferId) {
5752
5758
  try {
5753
5759
  const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
5754
5760
  if (cancelled) return;
@@ -5759,7 +5765,12 @@ function SwypePaymentInner({
5759
5765
  } catch {
5760
5766
  }
5761
5767
  }
5762
- if (resolved.step === "open-wallet" && persisted) {
5768
+ if (resolved.step === "open-wallet" && persisted && persisted.accountId && !persisted.transferId) {
5769
+ clearMobileFlowState();
5770
+ dispatch({ type: "NAVIGATE", step: "deposit" });
5771
+ return;
5772
+ }
5773
+ if (resolved.step === "open-wallet" && persisted && persisted.transferId) {
5763
5774
  try {
5764
5775
  const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
5765
5776
  if (cancelled) return;
@@ -5805,9 +5816,9 @@ function SwypePaymentInner({
5805
5816
  providerId: persisted.providerId,
5806
5817
  error: err instanceof Error ? err.message : "Unable to refresh wallet authorization status."
5807
5818
  });
5808
- pollingTransferIdRef.current = persisted.transferId;
5819
+ pollingTransferIdRef.current = persisted.transferId ?? null;
5809
5820
  mobileSetupFlowRef.current = persisted.isSetup;
5810
- pollingRef.current.startPolling(persisted.transferId);
5821
+ if (persisted.transferId) pollingRef.current.startPolling(persisted.transferId);
5811
5822
  return;
5812
5823
  }
5813
5824
  dispatch({
@@ -5815,9 +5826,9 @@ function SwypePaymentInner({
5815
5826
  deeplinkUri: persisted.deeplinkUri,
5816
5827
  providerId: persisted.providerId
5817
5828
  });
5818
- pollingTransferIdRef.current = persisted.transferId;
5829
+ pollingTransferIdRef.current = persisted.transferId ?? null;
5819
5830
  mobileSetupFlowRef.current = persisted.isSetup;
5820
- pollingRef.current.startPolling(persisted.transferId);
5831
+ if (persisted.transferId) pollingRef.current.startPolling(persisted.transferId);
5821
5832
  return;
5822
5833
  }
5823
5834
  dispatch({ type: "NAVIGATE", step: resolved.step });
@@ -5924,7 +5935,7 @@ function SwypePaymentInner({
5924
5935
  accounts: accts,
5925
5936
  persistedMobileFlow: persisted,
5926
5937
  mobileSetupInProgress: mobileSetupFlowRef.current,
5927
- connectingNewAccount: state.connectingNewAccount
5938
+ connectingNewAccount: false
5928
5939
  });
5929
5940
  const correctableSteps = ["deposit", "wallet-picker", "open-wallet"];
5930
5941
  dispatch({
@@ -5933,7 +5944,6 @@ function SwypePaymentInner({
5933
5944
  accounts: accts,
5934
5945
  chains: chn,
5935
5946
  defaults,
5936
- fallbackProviderId: !defaults && prov.length > 0 ? prov[0].id : null,
5937
5947
  resolvedStep: correctableSteps.includes(state.step) ? resolved.step : void 0,
5938
5948
  clearMobileState: resolved.clearPersistedFlow
5939
5949
  });
@@ -5965,8 +5975,7 @@ function SwypePaymentInner({
5965
5975
  apiBaseUrl,
5966
5976
  getAccessToken,
5967
5977
  state.activeCredentialId,
5968
- depositAmount,
5969
- state.connectingNewAccount
5978
+ depositAmount
5970
5979
  ]);
5971
5980
  useEffect(() => {
5972
5981
  if (!polling.transfer) return;
@@ -6015,6 +6024,46 @@ function SwypePaymentInner({
6015
6024
  if (!polledTransfer || polledTransfer.status !== "AUTHORIZED") return;
6016
6025
  void handleAuthorizedMobileReturn(polledTransfer, mobileSetupFlowRef.current);
6017
6026
  }, [state.mobileFlow, polling.transfer, handleAuthorizedMobileReturn]);
6027
+ useEffect(() => {
6028
+ if (!state.mobileFlow || !mobileSetupFlowRef.current) return;
6029
+ if (state.step !== "open-wallet") return;
6030
+ if (!state.activeCredentialId || !setupAccountIdRef.current) return;
6031
+ const accountId = setupAccountIdRef.current;
6032
+ const credentialId = state.activeCredentialId;
6033
+ let cancelled = false;
6034
+ const POLL_INTERVAL_MS = 3e3;
6035
+ const poll = async () => {
6036
+ try {
6037
+ const token = await getAccessTokenRef.current();
6038
+ if (!token || cancelled) return;
6039
+ const acct = await fetchAccount(apiBaseUrl, token, accountId, credentialId);
6040
+ if (cancelled) return;
6041
+ const hasActive = acct.wallets.some((w) => w.status === "ACTIVE");
6042
+ if (hasActive) {
6043
+ cancelled = true;
6044
+ mobileSetupFlowRef.current = false;
6045
+ setupAccountIdRef.current = null;
6046
+ clearMobileFlowState();
6047
+ await reloadAccounts();
6048
+ dispatch({ type: "MOBILE_SETUP_COMPLETE" });
6049
+ }
6050
+ } catch {
6051
+ }
6052
+ };
6053
+ poll();
6054
+ const intervalId = window.setInterval(poll, POLL_INTERVAL_MS);
6055
+ const handleVisibility = () => {
6056
+ if (document.visibilityState === "visible" && !cancelled) {
6057
+ poll();
6058
+ }
6059
+ };
6060
+ document.addEventListener("visibilitychange", handleVisibility);
6061
+ return () => {
6062
+ cancelled = true;
6063
+ window.clearInterval(intervalId);
6064
+ document.removeEventListener("visibilitychange", handleVisibility);
6065
+ };
6066
+ }, [state.mobileFlow, state.step, state.activeCredentialId, apiBaseUrl, reloadAccounts]);
6018
6067
  useEffect(() => {
6019
6068
  if (!state.mobileFlow) return;
6020
6069
  if (handlingMobileReturnRef.current) return;