@swype-org/react-sdk 0.1.98 → 0.1.100

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,6 +159,7 @@ function useSwypeDepositAmount() {
159
159
  // src/api.ts
160
160
  var api_exports = {};
161
161
  __export(api_exports, {
162
+ createAccount: () => createAccount,
162
163
  createTransfer: () => createTransfer,
163
164
  fetchAccounts: () => fetchAccounts,
164
165
  fetchAuthorizationSession: () => fetchAuthorizationSession,
@@ -206,6 +207,18 @@ async function fetchAccounts(apiBaseUrl, token, credentialId) {
206
207
  const data = await res.json();
207
208
  return data.items;
208
209
  }
210
+ async function createAccount(apiBaseUrl, token, params) {
211
+ const res = await fetch(`${apiBaseUrl}/v1/accounts`, {
212
+ method: "POST",
213
+ headers: {
214
+ "Content-Type": "application/json",
215
+ Authorization: `Bearer ${token}`
216
+ },
217
+ body: JSON.stringify(params)
218
+ });
219
+ if (!res.ok) await throwApiError(res);
220
+ return await res.json();
221
+ }
209
222
  async function createTransfer(apiBaseUrl, token, params) {
210
223
  if (!params.merchantAuthorization) {
211
224
  throw new Error("merchantAuthorization is required for transfer creation.");
@@ -1470,15 +1483,6 @@ function useAuthorizationExecutor(options) {
1470
1483
  },
1471
1484
  [apiBaseUrl, dispatchAction]
1472
1485
  );
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
1486
  return {
1483
1487
  executing,
1484
1488
  results,
@@ -1486,8 +1490,7 @@ function useAuthorizationExecutor(options) {
1486
1490
  currentAction,
1487
1491
  pendingSelectSource,
1488
1492
  resolveSelectSource,
1489
- executeSessionById,
1490
- executeSession
1493
+ executeSessionById
1491
1494
  };
1492
1495
  }
1493
1496
  function useTransferSigning(pollIntervalMs = 2e3, options) {
@@ -1845,16 +1848,13 @@ function buildSelectSourceChoices(options) {
1845
1848
 
1846
1849
  // src/paymentReducer.ts
1847
1850
  function deriveSourceTypeAndId(state) {
1848
- if (state.connectingNewAccount) {
1849
- return { sourceType: "providerId", sourceId: state.selectedProviderId ?? "" };
1850
- }
1851
1851
  if (state.selectedWalletId) {
1852
1852
  return { sourceType: "walletId", sourceId: state.selectedWalletId };
1853
1853
  }
1854
1854
  if (state.selectedAccountId) {
1855
1855
  return { sourceType: "accountId", sourceId: state.selectedAccountId };
1856
1856
  }
1857
- return { sourceType: "providerId", sourceId: state.selectedProviderId ?? "" };
1857
+ return { sourceType: "accountId", sourceId: "" };
1858
1858
  }
1859
1859
  function createInitialState(config) {
1860
1860
  return {
@@ -1866,8 +1866,6 @@ function createInitialState(config) {
1866
1866
  loadingData: false,
1867
1867
  selectedAccountId: null,
1868
1868
  selectedWalletId: null,
1869
- selectedProviderId: null,
1870
- connectingNewAccount: false,
1871
1869
  amount: config.depositAmount != null ? config.depositAmount.toString() : "",
1872
1870
  transfer: null,
1873
1871
  creatingTransfer: false,
@@ -1932,8 +1930,6 @@ function paymentReducer(state, action) {
1932
1930
  if (action.defaults) {
1933
1931
  next.selectedAccountId = action.defaults.accountId;
1934
1932
  next.selectedWalletId = action.defaults.walletId;
1935
- } else if (action.fallbackProviderId && !state.connectingNewAccount) {
1936
- next.selectedProviderId = action.fallbackProviderId;
1937
1933
  }
1938
1934
  if (action.clearMobileState) {
1939
1935
  next.mobileFlow = false;
@@ -1955,7 +1951,6 @@ function paymentReducer(state, action) {
1955
1951
  if (action.defaults) {
1956
1952
  next.selectedAccountId = action.defaults.accountId;
1957
1953
  next.selectedWalletId = action.defaults.walletId;
1958
- next.connectingNewAccount = false;
1959
1954
  }
1960
1955
  return next;
1961
1956
  }
@@ -1963,16 +1958,13 @@ function paymentReducer(state, action) {
1963
1958
  case "SELECT_PROVIDER":
1964
1959
  return {
1965
1960
  ...state,
1966
- selectedProviderId: action.providerId,
1967
- selectedAccountId: null,
1968
- connectingNewAccount: true
1961
+ selectedAccountId: null
1969
1962
  };
1970
1963
  case "SELECT_ACCOUNT":
1971
1964
  return {
1972
1965
  ...state,
1973
1966
  selectedAccountId: action.accountId,
1974
1967
  selectedWalletId: action.walletId,
1975
- connectingNewAccount: false,
1976
1968
  step: "deposit"
1977
1969
  };
1978
1970
  // ── Transfer lifecycle ───────────────────────────────────────
@@ -2057,7 +2049,6 @@ function paymentReducer(state, action) {
2057
2049
  ...state,
2058
2050
  mobileFlow: true,
2059
2051
  deeplinkUri: action.deeplinkUri,
2060
- selectedProviderId: action.providerId,
2061
2052
  error: action.error ?? null,
2062
2053
  step: "open-wallet"
2063
2054
  };
@@ -2113,7 +2104,6 @@ function paymentReducer(state, action) {
2113
2104
  amount: action.depositAmount != null ? action.depositAmount.toString() : "",
2114
2105
  mobileFlow: false,
2115
2106
  deeplinkUri: null,
2116
- connectingNewAccount: false,
2117
2107
  selectedWalletId: null,
2118
2108
  selectedAccountId: action.firstAccountId
2119
2109
  };
@@ -5263,11 +5253,11 @@ function SwypePaymentInner({
5263
5253
  accounts: state.accounts,
5264
5254
  persistedMobileFlow: loadMobileFlowState(),
5265
5255
  mobileSetupInProgress: mobileSetupFlowRef.current,
5266
- connectingNewAccount: state.connectingNewAccount
5256
+ connectingNewAccount: false
5267
5257
  });
5268
5258
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5269
5259
  dispatch({ type: "NAVIGATE", step: resolved.step });
5270
- }, [getAccessToken, apiBaseUrl, state.accounts, state.connectingNewAccount]);
5260
+ }, [getAccessToken, apiBaseUrl, state.accounts]);
5271
5261
  const handleRegisterPasskey = react.useCallback(async () => {
5272
5262
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
5273
5263
  dispatch({ type: "SET_ERROR", error: null });
@@ -5312,7 +5302,7 @@ function SwypePaymentInner({
5312
5302
  accounts: state.accounts,
5313
5303
  persistedMobileFlow: loadMobileFlowState(),
5314
5304
  mobileSetupInProgress: mobileSetupFlowRef.current,
5315
- connectingNewAccount: state.connectingNewAccount
5305
+ connectingNewAccount: false
5316
5306
  });
5317
5307
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5318
5308
  dispatch({ type: "NAVIGATE", step: resolved.step });
@@ -5325,7 +5315,7 @@ function SwypePaymentInner({
5325
5315
  } finally {
5326
5316
  dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
5327
5317
  }
5328
- }, [user, getAccessToken, apiBaseUrl, state.accounts, state.connectingNewAccount]);
5318
+ }, [user, getAccessToken, apiBaseUrl, state.accounts]);
5329
5319
  const handleVerifyPasskeyViaPopup = react.useCallback(async () => {
5330
5320
  dispatch({ type: "SET_VERIFYING_PASSKEY", value: true });
5331
5321
  dispatch({ type: "SET_ERROR", error: null });
@@ -5349,7 +5339,7 @@ function SwypePaymentInner({
5349
5339
  accounts: state.accounts,
5350
5340
  persistedMobileFlow: loadMobileFlowState(),
5351
5341
  mobileSetupInProgress: mobileSetupFlowRef.current,
5352
- connectingNewAccount: state.connectingNewAccount
5342
+ connectingNewAccount: false
5353
5343
  });
5354
5344
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5355
5345
  dispatch({ type: "NAVIGATE", step: resolved.step });
@@ -5368,7 +5358,7 @@ function SwypePaymentInner({
5368
5358
  } finally {
5369
5359
  dispatch({ type: "SET_VERIFYING_PASSKEY", value: false });
5370
5360
  }
5371
- }, [state.knownCredentialIds, getAccessToken, apiBaseUrl, state.accounts, state.connectingNewAccount]);
5361
+ }, [state.knownCredentialIds, getAccessToken, apiBaseUrl, state.accounts]);
5372
5362
  const reloadAccounts = react.useCallback(async () => {
5373
5363
  const token = await getAccessToken();
5374
5364
  if (!token || !state.activeCredentialId) return;
@@ -5420,8 +5410,7 @@ function SwypePaymentInner({
5420
5410
  dispatch({ type: "NAVIGATE", step: "create-passkey" });
5421
5411
  return;
5422
5412
  }
5423
- const isSetupRedirect = mobileSetupFlowRef.current;
5424
- dispatch({ type: "PAY_STARTED", isSetupRedirect });
5413
+ dispatch({ type: "PAY_STARTED", isSetupRedirect: false });
5425
5414
  processingStartedAtRef.current = Date.now();
5426
5415
  try {
5427
5416
  if (state.transfer?.status === "AUTHORIZED") {
@@ -5442,23 +5431,6 @@ function SwypePaymentInner({
5442
5431
  effectiveSourceId = activeWallet.id;
5443
5432
  }
5444
5433
  }
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
5434
  const t = await createTransfer(apiBaseUrl, token, {
5463
5435
  id: idempotencyKey,
5464
5436
  credentialId: state.activeCredentialId,
@@ -5469,28 +5441,6 @@ function SwypePaymentInner({
5469
5441
  amount: payAmount
5470
5442
  });
5471
5443
  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
- }
5493
- }
5494
5444
  const signedTransfer = await transferSigning.signTransfer(t.id);
5495
5445
  dispatch({ type: "TRANSFER_SIGNED", transfer: signedTransfer });
5496
5446
  polling.startPolling(t.id);
@@ -5500,7 +5450,7 @@ function SwypePaymentInner({
5500
5450
  dispatch({
5501
5451
  type: "PAY_ERROR",
5502
5452
  error: msg,
5503
- fallbackStep: isSetupRedirect ? "wallet-picker" : "deposit"
5453
+ fallbackStep: "deposit"
5504
5454
  });
5505
5455
  onError?.(msg);
5506
5456
  } finally {
@@ -5512,15 +5462,12 @@ function SwypePaymentInner({
5512
5462
  state.activeCredentialId,
5513
5463
  state.transfer,
5514
5464
  state.accounts,
5515
- state.selectedProviderId,
5516
5465
  destination,
5517
5466
  apiBaseUrl,
5518
5467
  getAccessToken,
5519
- authExecutor,
5520
5468
  transferSigning,
5521
5469
  polling,
5522
5470
  onError,
5523
- useWalletConnectorProp,
5524
5471
  idempotencyKey,
5525
5472
  merchantAuthorization
5526
5473
  ]);
@@ -5559,23 +5506,7 @@ function SwypePaymentInner({
5559
5506
  destination,
5560
5507
  amount: parsedAmount
5561
5508
  });
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
- }
5509
+ dispatch({ type: "TRANSFER_CREATED", transfer: t });
5579
5510
  } catch (err) {
5580
5511
  captureException(err);
5581
5512
  const msg = err instanceof Error ? err.message : "Failed to increase limit";
@@ -5590,7 +5521,6 @@ function SwypePaymentInner({
5590
5521
  sourceType,
5591
5522
  state.activeCredentialId,
5592
5523
  state.accounts,
5593
- state.selectedProviderId,
5594
5524
  apiBaseUrl,
5595
5525
  getAccessToken,
5596
5526
  polling,
@@ -5627,21 +5557,65 @@ function SwypePaymentInner({
5627
5557
  polling.startPolling(transferIdToResume);
5628
5558
  }
5629
5559
  }, [handleAuthorizedMobileReturn, polling, state.transfer]);
5630
- const handleSelectProvider = react.useCallback((providerId) => {
5560
+ const handleSelectProvider = react.useCallback(async (providerId) => {
5631
5561
  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" });
5562
+ if (!state.activeCredentialId) {
5563
+ dispatch({ type: "SET_ERROR", error: "Create a passkey on this device before continuing." });
5564
+ dispatch({ type: "NAVIGATE", step: "create-passkey" });
5565
+ return;
5566
+ }
5567
+ const provider = state.providers.find((p) => p.id === providerId);
5568
+ const providerName = provider?.name ?? "Wallet";
5569
+ dispatch({ type: "PAY_STARTED", isSetupRedirect: true });
5570
+ try {
5571
+ const token = await getAccessToken();
5572
+ if (!token) throw new Error("Not authenticated");
5573
+ const account = await createAccount(apiBaseUrl, token, {
5574
+ name: providerName,
5575
+ credentialId: state.activeCredentialId,
5576
+ providerId
5577
+ });
5578
+ const session = account.authorizationSessions?.[0];
5579
+ if (!session) throw new Error("No authorization session returned.");
5580
+ const isMobile = !shouldUseWalletConnector({
5581
+ useWalletConnector: useWalletConnectorProp,
5582
+ userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
5583
+ });
5584
+ if (isMobile) {
5585
+ handlingMobileReturnRef.current = false;
5586
+ mobileSetupFlowRef.current = true;
5587
+ persistMobileFlowState({
5588
+ accountId: account.id,
5589
+ sessionId: session.id,
5590
+ deeplinkUri: session.uri,
5591
+ providerId,
5592
+ isSetup: true
5593
+ });
5594
+ dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
5595
+ triggerDeeplink(session.uri);
5596
+ } else {
5597
+ await authExecutor.executeSessionById(session.id);
5598
+ await reloadAccounts();
5599
+ dispatch({ type: "NAVIGATE", step: "deposit" });
5600
+ }
5601
+ } catch (err) {
5602
+ captureException(err);
5603
+ const msg = err instanceof Error ? err.message : "Failed to set up wallet";
5604
+ dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
5605
+ onError?.(msg);
5606
+ } finally {
5607
+ dispatch({ type: "PAY_ENDED" });
5643
5608
  }
5644
- }, [useWalletConnectorProp, depositAmount, handlePay]);
5609
+ }, [
5610
+ state.activeCredentialId,
5611
+ state.providers,
5612
+ apiBaseUrl,
5613
+ getAccessToken,
5614
+ authExecutor,
5615
+ useWalletConnectorProp,
5616
+ reloadAccounts,
5617
+ onError
5618
+ ]);
5645
5619
  const handleContinueConnection = react.useCallback(
5646
5620
  (accountId) => {
5647
5621
  const acct = state.accounts.find((a) => a.id === accountId);
@@ -5751,7 +5725,7 @@ function SwypePaymentInner({
5751
5725
  connectingNewAccount: false
5752
5726
  });
5753
5727
  if (resolved.clearPersistedFlow) clearMobileFlowState();
5754
- if (resolved.step === "deposit" && persisted && persisted.isSetup) {
5728
+ if (resolved.step === "deposit" && persisted && persisted.isSetup && persisted.transferId) {
5755
5729
  try {
5756
5730
  const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
5757
5731
  if (cancelled) return;
@@ -5762,7 +5736,12 @@ function SwypePaymentInner({
5762
5736
  } catch {
5763
5737
  }
5764
5738
  }
5765
- if (resolved.step === "open-wallet" && persisted) {
5739
+ if (resolved.step === "open-wallet" && persisted && persisted.accountId && !persisted.transferId) {
5740
+ clearMobileFlowState();
5741
+ dispatch({ type: "NAVIGATE", step: "deposit" });
5742
+ return;
5743
+ }
5744
+ if (resolved.step === "open-wallet" && persisted && persisted.transferId) {
5766
5745
  try {
5767
5746
  const existingTransfer = await fetchTransfer(apiBaseUrl, token, persisted.transferId);
5768
5747
  if (cancelled) return;
@@ -5808,9 +5787,9 @@ function SwypePaymentInner({
5808
5787
  providerId: persisted.providerId,
5809
5788
  error: err instanceof Error ? err.message : "Unable to refresh wallet authorization status."
5810
5789
  });
5811
- pollingTransferIdRef.current = persisted.transferId;
5790
+ pollingTransferIdRef.current = persisted.transferId ?? null;
5812
5791
  mobileSetupFlowRef.current = persisted.isSetup;
5813
- pollingRef.current.startPolling(persisted.transferId);
5792
+ if (persisted.transferId) pollingRef.current.startPolling(persisted.transferId);
5814
5793
  return;
5815
5794
  }
5816
5795
  dispatch({
@@ -5818,9 +5797,9 @@ function SwypePaymentInner({
5818
5797
  deeplinkUri: persisted.deeplinkUri,
5819
5798
  providerId: persisted.providerId
5820
5799
  });
5821
- pollingTransferIdRef.current = persisted.transferId;
5800
+ pollingTransferIdRef.current = persisted.transferId ?? null;
5822
5801
  mobileSetupFlowRef.current = persisted.isSetup;
5823
- pollingRef.current.startPolling(persisted.transferId);
5802
+ if (persisted.transferId) pollingRef.current.startPolling(persisted.transferId);
5824
5803
  return;
5825
5804
  }
5826
5805
  dispatch({ type: "NAVIGATE", step: resolved.step });
@@ -5927,7 +5906,7 @@ function SwypePaymentInner({
5927
5906
  accounts: accts,
5928
5907
  persistedMobileFlow: persisted,
5929
5908
  mobileSetupInProgress: mobileSetupFlowRef.current,
5930
- connectingNewAccount: state.connectingNewAccount
5909
+ connectingNewAccount: false
5931
5910
  });
5932
5911
  const correctableSteps = ["deposit", "wallet-picker", "open-wallet"];
5933
5912
  dispatch({
@@ -5936,7 +5915,6 @@ function SwypePaymentInner({
5936
5915
  accounts: accts,
5937
5916
  chains: chn,
5938
5917
  defaults,
5939
- fallbackProviderId: !defaults && prov.length > 0 ? prov[0].id : null,
5940
5918
  resolvedStep: correctableSteps.includes(state.step) ? resolved.step : void 0,
5941
5919
  clearMobileState: resolved.clearPersistedFlow
5942
5920
  });
@@ -5968,8 +5946,7 @@ function SwypePaymentInner({
5968
5946
  apiBaseUrl,
5969
5947
  getAccessToken,
5970
5948
  state.activeCredentialId,
5971
- depositAmount,
5972
- state.connectingNewAccount
5949
+ depositAmount
5973
5950
  ]);
5974
5951
  react.useEffect(() => {
5975
5952
  if (!polling.transfer) return;