@swype-org/react-sdk 0.1.100 → 0.1.103

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
@@ -161,6 +161,7 @@ var api_exports = {};
161
161
  __export(api_exports, {
162
162
  createAccount: () => createAccount,
163
163
  createTransfer: () => createTransfer,
164
+ fetchAccount: () => fetchAccount,
164
165
  fetchAccounts: () => fetchAccounts,
165
166
  fetchAuthorizationSession: () => fetchAuthorizationSession,
166
167
  fetchChains: () => fetchChains,
@@ -207,14 +208,28 @@ async function fetchAccounts(apiBaseUrl, token, credentialId) {
207
208
  const data = await res.json();
208
209
  return data.items;
209
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
+ }
210
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
+ };
211
226
  const res = await fetch(`${apiBaseUrl}/v1/accounts`, {
212
227
  method: "POST",
213
228
  headers: {
214
229
  "Content-Type": "application/json",
215
230
  Authorization: `Bearer ${token}`
216
231
  },
217
- body: JSON.stringify(params)
232
+ body: JSON.stringify(body)
218
233
  });
219
234
  if (!res.ok) await throwApiError(res);
220
235
  return await res.json();
@@ -1864,6 +1879,7 @@ 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
1885
  amount: config.depositAmount != null ? config.depositAmount.toString() : "",
@@ -1958,7 +1974,9 @@ function paymentReducer(state, action) {
1958
1974
  case "SELECT_PROVIDER":
1959
1975
  return {
1960
1976
  ...state,
1961
- selectedAccountId: null
1977
+ selectedProviderId: action.providerId,
1978
+ selectedAccountId: null,
1979
+ selectedWalletId: null
1962
1980
  };
1963
1981
  case "SELECT_ACCOUNT":
1964
1982
  return {
@@ -2027,7 +2045,7 @@ function paymentReducer(state, action) {
2027
2045
  case "MOBILE_SETUP_COMPLETE":
2028
2046
  return {
2029
2047
  ...state,
2030
- transfer: action.transfer,
2048
+ transfer: action.transfer ?? state.transfer,
2031
2049
  error: null,
2032
2050
  mobileFlow: false,
2033
2051
  deeplinkUri: null,
@@ -2049,6 +2067,7 @@ function paymentReducer(state, action) {
2049
2067
  ...state,
2050
2068
  mobileFlow: true,
2051
2069
  deeplinkUri: action.deeplinkUri,
2070
+ selectedProviderId: action.providerId ?? state.selectedProviderId,
2052
2071
  error: action.error ?? null,
2053
2072
  step: "open-wallet"
2054
2073
  };
@@ -2104,6 +2123,7 @@ function paymentReducer(state, action) {
2104
2123
  amount: action.depositAmount != null ? action.depositAmount.toString() : "",
2105
2124
  mobileFlow: false,
2106
2125
  deeplinkUri: null,
2126
+ selectedProviderId: null,
2107
2127
  selectedWalletId: null,
2108
2128
  selectedAccountId: action.firstAccountId
2109
2129
  };
@@ -2535,36 +2555,160 @@ var KNOWN_LOGOS = {
2535
2555
  base: BASE_LOGO,
2536
2556
  "trust wallet": TRUST_WALLET_LOGO
2537
2557
  };
2538
- function SourceCard({ name, address, verified, onChangeSource }) {
2558
+ function hasActiveWallet2(account) {
2559
+ return account.wallets.some((w) => w.status === "ACTIVE");
2560
+ }
2561
+ function SourceCard({
2562
+ name,
2563
+ address,
2564
+ verified,
2565
+ accounts,
2566
+ selectedAccountId,
2567
+ onSelectAccount,
2568
+ onAuthorizeAccount,
2569
+ onAddProvider
2570
+ }) {
2539
2571
  const { tokens } = useSwypeConfig();
2540
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle6(tokens), children: [
2541
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: leftStyle, children: [
2542
- KNOWN_LOGOS[name.toLowerCase()] ? /* @__PURE__ */ jsxRuntime.jsx(
2543
- "img",
2544
- {
2545
- src: KNOWN_LOGOS[name.toLowerCase()],
2546
- alt: name,
2547
- style: logoImgStyle
2548
- }
2549
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: iconStyle3(tokens.textMuted), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
2550
- "path",
2572
+ const [open, setOpen] = react.useState(false);
2573
+ const containerRef = react.useRef(null);
2574
+ const hasDropdown = accounts != null && accounts.length > 0;
2575
+ react.useEffect(() => {
2576
+ if (!open) return;
2577
+ const handleClick = (e) => {
2578
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
2579
+ setOpen(false);
2580
+ }
2581
+ };
2582
+ document.addEventListener("mousedown", handleClick);
2583
+ return () => document.removeEventListener("mousedown", handleClick);
2584
+ }, [open]);
2585
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, style: { position: "relative" }, children: [
2586
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardContainerStyle(tokens), children: [
2587
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: leftStyle, children: [
2588
+ KNOWN_LOGOS[name.toLowerCase()] ? /* @__PURE__ */ jsxRuntime.jsx(
2589
+ "img",
2590
+ {
2591
+ src: KNOWN_LOGOS[name.toLowerCase()],
2592
+ alt: name,
2593
+ style: logoImgStyle
2594
+ }
2595
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: iconStyle3(tokens.textMuted), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
2596
+ "path",
2597
+ {
2598
+ d: "M21 7H3c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm0 8H3V9h18v6z",
2599
+ fill: "currentColor"
2600
+ }
2601
+ ) }) }),
2602
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2603
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: nameRowStyle, children: [
2604
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: nameStyle(tokens.text), children: name }),
2605
+ verified && /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z", fill: tokens.accent }) })
2606
+ ] }),
2607
+ address && /* @__PURE__ */ jsxRuntime.jsx("span", { style: addressStyle(tokens.textMuted), children: address })
2608
+ ] })
2609
+ ] }),
2610
+ hasDropdown && /* @__PURE__ */ jsxRuntime.jsxs(
2611
+ "button",
2551
2612
  {
2552
- d: "M21 7H3c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm0 8H3V9h18v6z",
2553
- fill: "currentColor"
2613
+ type: "button",
2614
+ onClick: () => setOpen(!open),
2615
+ style: changeStyle(tokens.accent),
2616
+ children: [
2617
+ "Change source",
2618
+ /* @__PURE__ */ jsxRuntime.jsx(
2619
+ "svg",
2620
+ {
2621
+ width: "10",
2622
+ height: "10",
2623
+ viewBox: "0 0 24 24",
2624
+ fill: "none",
2625
+ style: {
2626
+ marginLeft: 4,
2627
+ transform: open ? "rotate(180deg)" : "rotate(0deg)",
2628
+ transition: "transform 0.15s ease"
2629
+ },
2630
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2631
+ "path",
2632
+ {
2633
+ d: "M7 10l5 5 5-5",
2634
+ stroke: tokens.accent,
2635
+ strokeWidth: "2.5",
2636
+ strokeLinecap: "round",
2637
+ strokeLinejoin: "round"
2638
+ }
2639
+ )
2640
+ }
2641
+ )
2642
+ ]
2554
2643
  }
2555
- ) }) }),
2556
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2557
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: nameRowStyle, children: [
2558
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: nameStyle(tokens.text), children: name }),
2559
- verified && /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z", fill: tokens.accent }) })
2560
- ] }),
2561
- address && /* @__PURE__ */ jsxRuntime.jsx("span", { style: addressStyle(tokens.textMuted), children: address })
2562
- ] })
2644
+ )
2563
2645
  ] }),
2564
- onChangeSource && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onChangeSource, style: changeStyle(tokens.accent), children: "Change source" })
2646
+ open && hasDropdown && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: dropdownStyle(tokens), children: [
2647
+ accounts.map((account) => {
2648
+ const active = hasActiveWallet2(account);
2649
+ const isSelected = account.id === selectedAccountId;
2650
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2651
+ "button",
2652
+ {
2653
+ type: "button",
2654
+ onClick: () => {
2655
+ if (active) {
2656
+ onSelectAccount?.(account.id);
2657
+ } else {
2658
+ onAuthorizeAccount?.(account.id);
2659
+ }
2660
+ setOpen(false);
2661
+ },
2662
+ style: dropdownRowStyle(tokens, active, isSelected),
2663
+ children: [
2664
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: dropdownRowLeftStyle, children: [
2665
+ KNOWN_LOGOS[account.name.toLowerCase()] ? /* @__PURE__ */ jsxRuntime.jsx(
2666
+ "img",
2667
+ {
2668
+ src: KNOWN_LOGOS[account.name.toLowerCase()],
2669
+ alt: account.name,
2670
+ style: dropdownLogoStyle
2671
+ }
2672
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: dropdownFallbackIconStyle(active ? tokens.textMuted : tokens.border), children: account.name.charAt(0) }),
2673
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: dropdownNameStyle(active ? tokens.text : tokens.textMuted), children: account.name })
2674
+ ] }),
2675
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: dropdownRowRightStyle, children: [
2676
+ active ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: activeBadgeStyle(tokens), children: "Active" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: inactiveBadgeStyle(tokens), children: "Setup incomplete" }),
2677
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
2678
+ "path",
2679
+ {
2680
+ d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
2681
+ fill: tokens.accent
2682
+ }
2683
+ ) })
2684
+ ] })
2685
+ ]
2686
+ },
2687
+ account.id
2688
+ );
2689
+ }),
2690
+ onAddProvider && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2691
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: dropdownDividerStyle(tokens.border) }),
2692
+ /* @__PURE__ */ jsxRuntime.jsxs(
2693
+ "button",
2694
+ {
2695
+ type: "button",
2696
+ onClick: () => {
2697
+ onAddProvider();
2698
+ setOpen(false);
2699
+ },
2700
+ style: addProviderStyle(tokens),
2701
+ children: [
2702
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 5v14M5 12h14", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }) }),
2703
+ "Add Provider"
2704
+ ]
2705
+ }
2706
+ )
2707
+ ] })
2708
+ ] })
2565
2709
  ] });
2566
2710
  }
2567
- var containerStyle6 = (tokens) => ({
2711
+ var cardContainerStyle = (tokens) => ({
2568
2712
  display: "flex",
2569
2713
  alignItems: "center",
2570
2714
  justifyContent: "space-between",
@@ -2605,6 +2749,8 @@ var addressStyle = (color) => ({
2605
2749
  fontFamily: '"SF Mono", "Fira Code", monospace'
2606
2750
  });
2607
2751
  var changeStyle = (color) => ({
2752
+ display: "flex",
2753
+ alignItems: "center",
2608
2754
  background: "transparent",
2609
2755
  border: "none",
2610
2756
  color,
@@ -2614,6 +2760,117 @@ var changeStyle = (color) => ({
2614
2760
  fontFamily: "inherit",
2615
2761
  padding: 0
2616
2762
  });
2763
+ var dropdownStyle = (tokens) => ({
2764
+ position: "absolute",
2765
+ top: "100%",
2766
+ left: 0,
2767
+ right: 0,
2768
+ marginTop: 4,
2769
+ background: tokens.bgCard,
2770
+ border: `1px solid ${tokens.border}`,
2771
+ borderRadius: tokens.radiusLg,
2772
+ boxShadow: tokens.shadowLg,
2773
+ zIndex: 50,
2774
+ overflow: "hidden"
2775
+ });
2776
+ var dropdownRowStyle = (tokens, active, isSelected) => ({
2777
+ display: "flex",
2778
+ alignItems: "center",
2779
+ justifyContent: "space-between",
2780
+ width: "100%",
2781
+ padding: "10px 14px",
2782
+ background: isSelected ? tokens.accent + "12" : "transparent",
2783
+ border: "none",
2784
+ borderBottom: `1px solid ${tokens.border}`,
2785
+ cursor: "pointer",
2786
+ fontFamily: "inherit",
2787
+ fontSize: "0.85rem",
2788
+ textAlign: "left",
2789
+ outline: "none",
2790
+ opacity: active ? 1 : 0.55,
2791
+ transition: "background 0.1s ease"
2792
+ });
2793
+ var dropdownRowLeftStyle = {
2794
+ display: "flex",
2795
+ alignItems: "center",
2796
+ gap: 10,
2797
+ minWidth: 0,
2798
+ flex: 1
2799
+ };
2800
+ var dropdownRowRightStyle = {
2801
+ display: "flex",
2802
+ alignItems: "center",
2803
+ gap: 8,
2804
+ flexShrink: 0
2805
+ };
2806
+ var dropdownLogoStyle = {
2807
+ width: 20,
2808
+ height: 20,
2809
+ borderRadius: "50%",
2810
+ objectFit: "contain",
2811
+ flexShrink: 0
2812
+ };
2813
+ var dropdownFallbackIconStyle = (color) => ({
2814
+ width: 20,
2815
+ height: 20,
2816
+ borderRadius: "50%",
2817
+ display: "flex",
2818
+ alignItems: "center",
2819
+ justifyContent: "center",
2820
+ fontSize: "0.72rem",
2821
+ fontWeight: 700,
2822
+ color,
2823
+ flexShrink: 0
2824
+ });
2825
+ var dropdownNameStyle = (color) => ({
2826
+ fontWeight: 500,
2827
+ color,
2828
+ whiteSpace: "nowrap",
2829
+ overflow: "hidden",
2830
+ textOverflow: "ellipsis"
2831
+ });
2832
+ var activeBadgeStyle = (tokens) => ({
2833
+ fontSize: "0.6rem",
2834
+ fontWeight: 600,
2835
+ color: tokens.success,
2836
+ background: tokens.successBg,
2837
+ padding: "2px 7px",
2838
+ borderRadius: 999,
2839
+ textTransform: "uppercase",
2840
+ letterSpacing: "0.03em",
2841
+ whiteSpace: "nowrap"
2842
+ });
2843
+ var inactiveBadgeStyle = (tokens) => ({
2844
+ fontSize: "0.6rem",
2845
+ fontWeight: 600,
2846
+ color: tokens.warning,
2847
+ background: tokens.warningBg ?? `${tokens.warning}1a`,
2848
+ padding: "2px 7px",
2849
+ borderRadius: 999,
2850
+ textTransform: "uppercase",
2851
+ letterSpacing: "0.03em",
2852
+ whiteSpace: "nowrap"
2853
+ });
2854
+ var dropdownDividerStyle = (borderColor) => ({
2855
+ height: 0,
2856
+ borderTop: `1px solid ${borderColor}`
2857
+ });
2858
+ var addProviderStyle = (tokens) => ({
2859
+ display: "flex",
2860
+ alignItems: "center",
2861
+ gap: 8,
2862
+ width: "100%",
2863
+ padding: "10px 14px",
2864
+ background: "transparent",
2865
+ border: "none",
2866
+ color: tokens.accent,
2867
+ fontWeight: 600,
2868
+ fontSize: "0.85rem",
2869
+ cursor: "pointer",
2870
+ fontFamily: "inherit",
2871
+ textAlign: "left",
2872
+ outline: "none"
2873
+ });
2617
2874
  function StepList({ steps }) {
2618
2875
  const { tokens } = useSwypeConfig();
2619
2876
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: listStyle, children: steps.map((step, i) => {
@@ -2691,13 +2948,13 @@ function SettingsMenu({ onLogout }) {
2691
2948
  document.addEventListener("mousedown", handleClickOutside);
2692
2949
  return () => document.removeEventListener("mousedown", handleClickOutside);
2693
2950
  }, [open]);
2694
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: menuRef, style: containerStyle7, children: [
2951
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: menuRef, style: containerStyle6, children: [
2695
2952
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: toggle, style: triggerStyle(tokens.text), "aria-label": "Settings", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [
2696
2953
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "5", r: "2", fill: "currentColor" }),
2697
2954
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "2", fill: "currentColor" }),
2698
2955
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "19", r: "2", fill: "currentColor" })
2699
2956
  ] }) }),
2700
- open && /* @__PURE__ */ jsxRuntime.jsx("div", { style: dropdownStyle(tokens), children: /* @__PURE__ */ jsxRuntime.jsxs(
2957
+ open && /* @__PURE__ */ jsxRuntime.jsx("div", { style: dropdownStyle2(tokens), children: /* @__PURE__ */ jsxRuntime.jsxs(
2701
2958
  "button",
2702
2959
  {
2703
2960
  type: "button",
@@ -2718,7 +2975,7 @@ function SettingsMenu({ onLogout }) {
2718
2975
  ) })
2719
2976
  ] });
2720
2977
  }
2721
- var containerStyle7 = {
2978
+ var containerStyle6 = {
2722
2979
  position: "relative"
2723
2980
  };
2724
2981
  var triggerStyle = (color) => ({
@@ -2731,7 +2988,7 @@ var triggerStyle = (color) => ({
2731
2988
  alignItems: "center",
2732
2989
  justifyContent: "center"
2733
2990
  });
2734
- var dropdownStyle = (tokens) => ({
2991
+ var dropdownStyle2 = (tokens) => ({
2735
2992
  position: "absolute",
2736
2993
  right: 0,
2737
2994
  top: "100%",
@@ -3693,12 +3950,16 @@ function DepositScreen({
3693
3950
  processing,
3694
3951
  error,
3695
3952
  onDeposit,
3696
- onChangeSource,
3697
3953
  onSwitchWallet,
3698
3954
  onBack,
3699
3955
  onLogout,
3700
3956
  onIncreaseLimit,
3701
- increasingLimit
3957
+ increasingLimit,
3958
+ accounts,
3959
+ selectedAccountId,
3960
+ onSelectAccount,
3961
+ onAuthorizeAccount,
3962
+ onAddProvider
3702
3963
  }) {
3703
3964
  const { tokens } = useSwypeConfig();
3704
3965
  const amount = initialAmount;
@@ -3724,7 +3985,11 @@ function DepositScreen({
3724
3985
  name: sourceName,
3725
3986
  address: sourceAddress,
3726
3987
  verified: sourceVerified,
3727
- onChangeSource
3988
+ accounts,
3989
+ selectedAccountId,
3990
+ onSelectAccount,
3991
+ onAuthorizeAccount,
3992
+ onAddProvider
3728
3993
  }
3729
3994
  ),
3730
3995
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: amountDisplayStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: amountStyle({ ...tokens, dimmed: true }), children: [
@@ -3794,7 +4059,11 @@ function DepositScreen({
3794
4059
  name: sourceName,
3795
4060
  address: sourceAddress,
3796
4061
  verified: sourceVerified,
3797
- onChangeSource
4062
+ accounts,
4063
+ selectedAccountId,
4064
+ onSelectAccount,
4065
+ onAuthorizeAccount,
4066
+ onAddProvider
3798
4067
  }
3799
4068
  ),
3800
4069
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: amountDisplayStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: amountStyle(tokens), children: [
@@ -4927,12 +5196,16 @@ function StepRenderer({
4927
5196
  processing: state.creatingTransfer,
4928
5197
  error: state.error,
4929
5198
  onDeposit: handlers.onPay,
4930
- onChangeSource: () => handlers.onNavigate("wallet-picker"),
4931
5199
  onSwitchWallet: () => handlers.onNavigate("wallet-picker"),
4932
5200
  onBack: onBack ?? (() => handlers.onLogout()),
4933
5201
  onLogout: handlers.onLogout,
4934
5202
  onIncreaseLimit: handlers.onIncreaseLimit,
4935
- increasingLimit: state.increasingLimit
5203
+ increasingLimit: state.increasingLimit,
5204
+ accounts: state.accounts,
5205
+ selectedAccountId: state.selectedAccountId,
5206
+ onSelectAccount: handlers.onSelectAccount,
5207
+ onAuthorizeAccount: handlers.onContinueConnection,
5208
+ onAddProvider: () => handlers.onNavigate("wallet-picker")
4936
5209
  }
4937
5210
  );
4938
5211
  }
@@ -5001,10 +5274,14 @@ function StepRenderer({
5001
5274
  processing: false,
5002
5275
  error: state.error,
5003
5276
  onDeposit: handlers.onPay,
5004
- onChangeSource: () => handlers.onNavigate("wallet-picker"),
5005
5277
  onSwitchWallet: () => handlers.onNavigate("wallet-picker"),
5006
5278
  onBack: onBack ?? (() => handlers.onLogout()),
5007
- onLogout: handlers.onLogout
5279
+ onLogout: handlers.onLogout,
5280
+ accounts: state.accounts,
5281
+ selectedAccountId: state.selectedAccountId,
5282
+ onSelectAccount: handlers.onSelectAccount,
5283
+ onAuthorizeAccount: handlers.onContinueConnection,
5284
+ onAddProvider: () => handlers.onNavigate("wallet-picker")
5008
5285
  }
5009
5286
  );
5010
5287
  }
@@ -5029,7 +5306,7 @@ var PaymentErrorBoundary = class extends react.Component {
5029
5306
  if (!this.state.hasError) {
5030
5307
  return this.props.children;
5031
5308
  }
5032
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle8, children: [
5309
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle7, children: [
5033
5310
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: iconStyle4, children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", children: [
5034
5311
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "#ef4444", strokeWidth: "1.5" }),
5035
5312
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 8v5", stroke: "#ef4444", strokeWidth: "1.5", strokeLinecap: "round" }),
@@ -5041,7 +5318,7 @@ var PaymentErrorBoundary = class extends react.Component {
5041
5318
  ] });
5042
5319
  }
5043
5320
  };
5044
- var containerStyle8 = {
5321
+ var containerStyle7 = {
5045
5322
  display: "flex",
5046
5323
  flexDirection: "column",
5047
5324
  alignItems: "center",
@@ -5121,6 +5398,7 @@ function SwypePaymentInner({
5121
5398
  );
5122
5399
  const loadingDataRef = react.useRef(false);
5123
5400
  const pollingTransferIdRef = react.useRef(null);
5401
+ const setupAccountIdRef = react.useRef(null);
5124
5402
  const mobileSetupFlowRef = react.useRef(false);
5125
5403
  const handlingMobileReturnRef = react.useRef(false);
5126
5404
  const processingStartedAtRef = react.useRef(null);
@@ -5441,6 +5719,15 @@ function SwypePaymentInner({
5441
5719
  amount: payAmount
5442
5720
  });
5443
5721
  dispatch({ type: "TRANSFER_CREATED", transfer: t });
5722
+ if (t.status === "COMPLETED") {
5723
+ dispatch({ type: "TRANSFER_COMPLETED", transfer: t });
5724
+ onComplete?.(t);
5725
+ return;
5726
+ }
5727
+ if (t.status === "FAILED") {
5728
+ dispatch({ type: "TRANSFER_FAILED", transfer: t, error: "Transfer failed." });
5729
+ return;
5730
+ }
5444
5731
  const signedTransfer = await transferSigning.signTransfer(t.id);
5445
5732
  dispatch({ type: "TRANSFER_SIGNED", transfer: signedTransfer });
5446
5733
  polling.startPolling(t.id);
@@ -5468,6 +5755,7 @@ function SwypePaymentInner({
5468
5755
  transferSigning,
5469
5756
  polling,
5470
5757
  onError,
5758
+ onComplete,
5471
5759
  idempotencyKey,
5472
5760
  merchantAuthorization
5473
5761
  ]);
@@ -5498,7 +5786,6 @@ function SwypePaymentInner({
5498
5786
  }
5499
5787
  }
5500
5788
  const t = await createTransfer(apiBaseUrl, token, {
5501
- id: idempotencyKey,
5502
5789
  credentialId: state.activeCredentialId,
5503
5790
  merchantAuthorization,
5504
5791
  sourceType: effectiveSourceType,
@@ -5525,7 +5812,6 @@ function SwypePaymentInner({
5525
5812
  getAccessToken,
5526
5813
  polling,
5527
5814
  onError,
5528
- idempotencyKey,
5529
5815
  merchantAuthorization,
5530
5816
  destination
5531
5817
  ]);
@@ -5570,7 +5856,9 @@ function SwypePaymentInner({
5570
5856
  try {
5571
5857
  const token = await getAccessToken();
5572
5858
  if (!token) throw new Error("Not authenticated");
5859
+ const accountId = crypto.randomUUID();
5573
5860
  const account = await createAccount(apiBaseUrl, token, {
5861
+ id: accountId,
5574
5862
  name: providerName,
5575
5863
  credentialId: state.activeCredentialId,
5576
5864
  providerId
@@ -5584,6 +5872,7 @@ function SwypePaymentInner({
5584
5872
  if (isMobile) {
5585
5873
  handlingMobileReturnRef.current = false;
5586
5874
  mobileSetupFlowRef.current = true;
5875
+ setupAccountIdRef.current = account.id;
5587
5876
  persistMobileFlowState({
5588
5877
  accountId: account.id,
5589
5878
  sessionId: session.id,
@@ -5619,10 +5908,23 @@ function SwypePaymentInner({
5619
5908
  const handleContinueConnection = react.useCallback(
5620
5909
  (accountId) => {
5621
5910
  const acct = state.accounts.find((a) => a.id === accountId);
5911
+ if (!acct) return;
5912
+ const matchedProvider = state.providers.find((p) => p.name === acct.name);
5913
+ if (matchedProvider) {
5914
+ handleSelectProvider(matchedProvider.id);
5915
+ }
5916
+ },
5917
+ [state.accounts, state.providers, handleSelectProvider]
5918
+ );
5919
+ const handleSelectAccount = react.useCallback(
5920
+ (accountId) => {
5921
+ const acct = state.accounts.find((a) => a.id === accountId);
5922
+ if (!acct) return;
5923
+ const activeWallet = acct.wallets.find((w) => w.status === "ACTIVE") ?? null;
5622
5924
  dispatch({
5623
5925
  type: "SELECT_ACCOUNT",
5624
5926
  accountId,
5625
- walletId: acct?.wallets[0]?.id ?? null
5927
+ walletId: activeWallet?.id ?? null
5626
5928
  });
5627
5929
  },
5628
5930
  [state.accounts]
@@ -5995,6 +6297,46 @@ function SwypePaymentInner({
5995
6297
  if (!polledTransfer || polledTransfer.status !== "AUTHORIZED") return;
5996
6298
  void handleAuthorizedMobileReturn(polledTransfer, mobileSetupFlowRef.current);
5997
6299
  }, [state.mobileFlow, polling.transfer, handleAuthorizedMobileReturn]);
6300
+ react.useEffect(() => {
6301
+ if (!state.mobileFlow || !mobileSetupFlowRef.current) return;
6302
+ if (state.step !== "open-wallet") return;
6303
+ if (!state.activeCredentialId || !setupAccountIdRef.current) return;
6304
+ const accountId = setupAccountIdRef.current;
6305
+ const credentialId = state.activeCredentialId;
6306
+ let cancelled = false;
6307
+ const POLL_INTERVAL_MS = 3e3;
6308
+ const poll = async () => {
6309
+ try {
6310
+ const token = await getAccessTokenRef.current();
6311
+ if (!token || cancelled) return;
6312
+ const acct = await fetchAccount(apiBaseUrl, token, accountId, credentialId);
6313
+ if (cancelled) return;
6314
+ const hasActive = acct.wallets.some((w) => w.status === "ACTIVE");
6315
+ if (hasActive) {
6316
+ cancelled = true;
6317
+ mobileSetupFlowRef.current = false;
6318
+ setupAccountIdRef.current = null;
6319
+ clearMobileFlowState();
6320
+ await reloadAccounts();
6321
+ dispatch({ type: "MOBILE_SETUP_COMPLETE" });
6322
+ }
6323
+ } catch {
6324
+ }
6325
+ };
6326
+ poll();
6327
+ const intervalId = window.setInterval(poll, POLL_INTERVAL_MS);
6328
+ const handleVisibility = () => {
6329
+ if (document.visibilityState === "visible" && !cancelled) {
6330
+ poll();
6331
+ }
6332
+ };
6333
+ document.addEventListener("visibilitychange", handleVisibility);
6334
+ return () => {
6335
+ cancelled = true;
6336
+ window.clearInterval(intervalId);
6337
+ document.removeEventListener("visibilitychange", handleVisibility);
6338
+ };
6339
+ }, [state.mobileFlow, state.step, state.activeCredentialId, apiBaseUrl, reloadAccounts]);
5998
6340
  react.useEffect(() => {
5999
6341
  if (!state.mobileFlow) return;
6000
6342
  if (handlingMobileReturnRef.current) return;
@@ -6054,6 +6396,7 @@ function SwypePaymentInner({
6054
6396
  onVerifyPasskeyViaPopup: handleVerifyPasskeyViaPopup,
6055
6397
  onSelectProvider: handleSelectProvider,
6056
6398
  onContinueConnection: handleContinueConnection,
6399
+ onSelectAccount: handleSelectAccount,
6057
6400
  onPay: handlePay,
6058
6401
  onIncreaseLimit: handleIncreaseLimit,
6059
6402
  onConfirmSign: handleConfirmSign,
@@ -6078,6 +6421,7 @@ function SwypePaymentInner({
6078
6421
  handleVerifyPasskeyViaPopup,
6079
6422
  handleSelectProvider,
6080
6423
  handleContinueConnection,
6424
+ handleSelectAccount,
6081
6425
  handlePay,
6082
6426
  handleIncreaseLimit,
6083
6427
  handleConfirmSign,