@swype-org/react-sdk 0.1.29 → 0.1.31

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
@@ -36,6 +36,9 @@ var darkTheme = {
36
36
  successBg: "#0f2f2a",
37
37
  error: "#d46a72",
38
38
  errorBg: "#301d21",
39
+ warning: "#F57C00",
40
+ warningBg: "#3D2E00",
41
+ warningText: "#FFB74D",
39
42
  shadow: "0 1px 4px rgba(0,0,0,0.35)",
40
43
  shadowLg: "0 18px 44px rgba(0,0,0,0.42)",
41
44
  radius: "14px",
@@ -60,6 +63,9 @@ var lightTheme = {
60
63
  successBg: "#e6f7f1",
61
64
  error: "#ce6670",
62
65
  errorBg: "#fdf1f2",
66
+ warning: "#F57C00",
67
+ warningBg: "#FFF8E1",
68
+ warningText: "#5D4037",
63
69
  shadow: "0 1px 3px rgba(12, 31, 39, 0.08)",
64
70
  shadowLg: "0 20px 48px rgba(19, 61, 75, 0.14)",
65
71
  radius: "14px",
@@ -1391,703 +1397,6 @@ function Spinner({ size = 40, label }) {
1391
1397
  }
1392
1398
  );
1393
1399
  }
1394
- function ProviderCard({ provider, selected, onClick }) {
1395
- const { tokens } = useSwypeConfig();
1396
- const [hovered, setHovered] = react.useState(false);
1397
- return /* @__PURE__ */ jsxRuntime.jsxs(
1398
- "button",
1399
- {
1400
- onClick,
1401
- onMouseEnter: () => setHovered(true),
1402
- onMouseLeave: () => setHovered(false),
1403
- style: {
1404
- display: "flex",
1405
- alignItems: "center",
1406
- gap: "12px",
1407
- width: "100%",
1408
- padding: "14px 16px",
1409
- background: selected ? tokens.accent + "18" : hovered ? tokens.bgHover : tokens.bgInput,
1410
- border: `1.5px solid ${selected ? tokens.accent : tokens.border}`,
1411
- borderRadius: tokens.radiusLg,
1412
- cursor: "pointer",
1413
- transition: "all 0.15s ease",
1414
- color: tokens.text,
1415
- fontFamily: "inherit",
1416
- fontSize: "0.95rem",
1417
- fontWeight: 500,
1418
- textAlign: "left",
1419
- outline: "none"
1420
- },
1421
- children: [
1422
- provider.logoURI ? /* @__PURE__ */ jsxRuntime.jsx(
1423
- "img",
1424
- {
1425
- src: provider.logoURI,
1426
- alt: provider.name,
1427
- style: {
1428
- width: 32,
1429
- height: 32,
1430
- borderRadius: "50%",
1431
- objectFit: "contain"
1432
- }
1433
- }
1434
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1435
- "div",
1436
- {
1437
- style: {
1438
- width: 32,
1439
- height: 32,
1440
- borderRadius: "50%",
1441
- background: tokens.accent + "30",
1442
- display: "flex",
1443
- alignItems: "center",
1444
- justifyContent: "center",
1445
- fontSize: "0.875rem",
1446
- fontWeight: 700,
1447
- color: tokens.accent,
1448
- flexShrink: 0
1449
- },
1450
- children: provider.name.charAt(0).toUpperCase()
1451
- }
1452
- ),
1453
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: provider.name }),
1454
- selected && /* @__PURE__ */ jsxRuntime.jsx(
1455
- "svg",
1456
- {
1457
- width: "18",
1458
- height: "18",
1459
- viewBox: "0 0 24 24",
1460
- fill: "none",
1461
- style: { marginLeft: "auto", flexShrink: 0 },
1462
- children: /* @__PURE__ */ jsxRuntime.jsx(
1463
- "path",
1464
- {
1465
- d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
1466
- fill: tokens.accent
1467
- }
1468
- )
1469
- }
1470
- )
1471
- ]
1472
- }
1473
- );
1474
- }
1475
- function AccountDropdown({
1476
- accounts,
1477
- selectedAccountId,
1478
- onSelect,
1479
- selectedWalletId,
1480
- onWalletSelect
1481
- }) {
1482
- const { tokens } = useSwypeConfig();
1483
- const [open, setOpen] = react.useState(false);
1484
- const containerRef = react.useRef(null);
1485
- const selected = accounts.find((a) => a.id === selectedAccountId);
1486
- const selectedWallet = selected?.wallets.find(
1487
- (w) => w.id === selectedWalletId
1488
- );
1489
- react.useEffect(() => {
1490
- if (!open) return;
1491
- const handleClick = (e) => {
1492
- if (containerRef.current && !containerRef.current.contains(e.target)) {
1493
- setOpen(false);
1494
- }
1495
- };
1496
- document.addEventListener("mousedown", handleClick);
1497
- return () => document.removeEventListener("mousedown", handleClick);
1498
- }, [open]);
1499
- if (accounts.length === 0) return null;
1500
- const hasMultipleChoices = accounts.length > 1 || accounts.length === 1 && onWalletSelect && accounts[0].wallets.filter((w) => w.balance.available.amount > 0).length > 1;
1501
- if (!hasMultipleChoices) {
1502
- return /* @__PURE__ */ jsxRuntime.jsxs(
1503
- "div",
1504
- {
1505
- style: {
1506
- display: "flex",
1507
- alignItems: "center",
1508
- gap: "6px",
1509
- fontSize: "0.85rem",
1510
- color: tokens.textSecondary
1511
- },
1512
- children: [
1513
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: accounts[0].name }),
1514
- (selectedWallet ?? accounts[0].wallets[0]) && /* @__PURE__ */ jsxRuntime.jsx(
1515
- "span",
1516
- {
1517
- style: {
1518
- fontSize: "0.75rem",
1519
- color: tokens.textMuted,
1520
- fontFamily: '"SF Mono", "Fira Code", monospace'
1521
- },
1522
- children: selectedWallet ? `${selectedWallet.chain.name} \xB7 ${selectedWallet.name}` : accounts[0].wallets[0]?.name
1523
- }
1524
- )
1525
- ]
1526
- }
1527
- );
1528
- }
1529
- const getAccountBalance = (account) => {
1530
- let total = 0;
1531
- for (const w of account.wallets) {
1532
- total += w.balance.available.amount;
1533
- }
1534
- return total > 0 ? `$${total.toFixed(2)}` : "";
1535
- };
1536
- const hasActiveWallet = (account) => account.wallets.some((w) => w.status === "ACTIVE");
1537
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, style: { position: "relative" }, children: [
1538
- /* @__PURE__ */ jsxRuntime.jsxs(
1539
- "button",
1540
- {
1541
- onClick: () => setOpen(!open),
1542
- style: {
1543
- display: "flex",
1544
- alignItems: "center",
1545
- gap: "6px",
1546
- background: tokens.bgCard,
1547
- border: `1px solid ${tokens.border}`,
1548
- cursor: "pointer",
1549
- padding: "7px 10px",
1550
- borderRadius: "999px",
1551
- color: tokens.textSecondary,
1552
- fontFamily: "inherit",
1553
- fontSize: "0.85rem",
1554
- outline: "none"
1555
- },
1556
- children: [
1557
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500, color: tokens.text }, children: selected?.name ?? "Select account" }),
1558
- (selectedWallet ?? selected?.wallets?.[0]) && /* @__PURE__ */ jsxRuntime.jsx(
1559
- "span",
1560
- {
1561
- style: {
1562
- fontSize: "0.75rem",
1563
- color: tokens.textMuted,
1564
- fontFamily: '"SF Mono", "Fira Code", monospace'
1565
- },
1566
- children: selectedWallet ? `${selectedWallet.chain.name} \xB7 ${selectedWallet.name}` : selected.wallets[0].name
1567
- }
1568
- ),
1569
- /* @__PURE__ */ jsxRuntime.jsx(
1570
- "svg",
1571
- {
1572
- width: "12",
1573
- height: "12",
1574
- viewBox: "0 0 24 24",
1575
- fill: "none",
1576
- style: {
1577
- transform: open ? "rotate(180deg)" : "rotate(0deg)",
1578
- transition: "transform 0.15s ease",
1579
- flexShrink: 0
1580
- },
1581
- children: /* @__PURE__ */ jsxRuntime.jsx(
1582
- "path",
1583
- {
1584
- d: "M7 10l5 5 5-5",
1585
- stroke: tokens.textMuted,
1586
- strokeWidth: "2",
1587
- strokeLinecap: "round",
1588
- strokeLinejoin: "round"
1589
- }
1590
- )
1591
- }
1592
- )
1593
- ]
1594
- }
1595
- ),
1596
- open && /* @__PURE__ */ jsxRuntime.jsx(
1597
- "div",
1598
- {
1599
- style: {
1600
- position: "absolute",
1601
- top: "100%",
1602
- left: 0,
1603
- right: 0,
1604
- marginTop: "4px",
1605
- background: tokens.bgCard,
1606
- border: `1px solid ${tokens.border}`,
1607
- borderRadius: tokens.radiusLg,
1608
- boxShadow: tokens.shadowLg,
1609
- zIndex: 50,
1610
- overflow: "hidden",
1611
- minWidth: "220px"
1612
- },
1613
- children: accounts.map((account) => {
1614
- const isAcctSelected = account.id === selectedAccountId;
1615
- const balance = getAccountBalance(account);
1616
- const active = hasActiveWallet(account);
1617
- const walletsWithBalance = account.wallets.filter(
1618
- (w) => w.balance.available.amount > 0
1619
- );
1620
- const showWallets = onWalletSelect && walletsWithBalance.length > 0;
1621
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1622
- /* @__PURE__ */ jsxRuntime.jsxs(
1623
- "button",
1624
- {
1625
- onClick: () => {
1626
- onSelect(account.id);
1627
- if (!showWallets) setOpen(false);
1628
- },
1629
- style: {
1630
- display: "flex",
1631
- alignItems: "center",
1632
- justifyContent: "space-between",
1633
- width: "100%",
1634
- padding: "10px 14px",
1635
- background: isAcctSelected && !selectedWalletId ? tokens.accent + "12" : "transparent",
1636
- border: "none",
1637
- borderBottom: showWallets ? "none" : `1px solid ${tokens.border}`,
1638
- cursor: "pointer",
1639
- color: tokens.text,
1640
- fontFamily: "inherit",
1641
- fontSize: "0.85rem",
1642
- textAlign: "left",
1643
- outline: "none",
1644
- transition: "background 0.1s ease"
1645
- },
1646
- children: [
1647
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minWidth: 0, flex: 1 }, children: [
1648
- /* @__PURE__ */ jsxRuntime.jsxs(
1649
- "div",
1650
- {
1651
- style: {
1652
- display: "flex",
1653
- alignItems: "center",
1654
- gap: "6px"
1655
- },
1656
- children: [
1657
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: account.name }),
1658
- active && /* @__PURE__ */ jsxRuntime.jsx(
1659
- "span",
1660
- {
1661
- style: {
1662
- fontSize: "0.6rem",
1663
- fontWeight: 600,
1664
- color: tokens.success,
1665
- background: tokens.successBg,
1666
- padding: "2px 7px",
1667
- borderRadius: "999px",
1668
- textTransform: "uppercase",
1669
- letterSpacing: "0.03em"
1670
- },
1671
- children: "Active"
1672
- }
1673
- )
1674
- ]
1675
- }
1676
- ),
1677
- balance && /* @__PURE__ */ jsxRuntime.jsx(
1678
- "div",
1679
- {
1680
- style: {
1681
- fontSize: "0.75rem",
1682
- color: tokens.textMuted,
1683
- marginTop: "2px"
1684
- },
1685
- children: balance
1686
- }
1687
- )
1688
- ] }),
1689
- isAcctSelected && !selectedWalletId && /* @__PURE__ */ jsxRuntime.jsx(
1690
- "svg",
1691
- {
1692
- width: "14",
1693
- height: "14",
1694
- viewBox: "0 0 24 24",
1695
- fill: "none",
1696
- style: { flexShrink: 0, marginLeft: "8px" },
1697
- children: /* @__PURE__ */ jsxRuntime.jsx(
1698
- "path",
1699
- {
1700
- d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
1701
- fill: tokens.accent
1702
- }
1703
- )
1704
- }
1705
- )
1706
- ]
1707
- }
1708
- ),
1709
- showWallets && walletsWithBalance.map((wallet, wIdx) => {
1710
- const isWalletSelected = isAcctSelected && wallet.id === selectedWalletId;
1711
- const walletBal = wallet.balance.available.amount > 0 ? `$${wallet.balance.available.amount.toFixed(2)}` : "";
1712
- const isLastWallet = wIdx === walletsWithBalance.length - 1;
1713
- return /* @__PURE__ */ jsxRuntime.jsxs(
1714
- "button",
1715
- {
1716
- onClick: () => {
1717
- onWalletSelect(account.id, wallet.id);
1718
- setOpen(false);
1719
- },
1720
- style: {
1721
- display: "flex",
1722
- alignItems: "center",
1723
- justifyContent: "space-between",
1724
- width: "100%",
1725
- padding: "8px 14px 8px 28px",
1726
- background: isWalletSelected ? tokens.accent + "12" : "transparent",
1727
- border: "none",
1728
- borderBottom: isLastWallet ? `1px solid ${tokens.border}` : "none",
1729
- cursor: "pointer",
1730
- color: tokens.text,
1731
- fontFamily: "inherit",
1732
- fontSize: "0.8rem",
1733
- textAlign: "left",
1734
- outline: "none",
1735
- transition: "background 0.1s ease"
1736
- },
1737
- children: [
1738
- /* @__PURE__ */ jsxRuntime.jsxs(
1739
- "div",
1740
- {
1741
- style: {
1742
- display: "flex",
1743
- alignItems: "center",
1744
- gap: "6px",
1745
- minWidth: 0,
1746
- flex: 1
1747
- },
1748
- children: [
1749
- /* @__PURE__ */ jsxRuntime.jsx(
1750
- "span",
1751
- {
1752
- style: {
1753
- fontWeight: 500,
1754
- fontSize: "0.8rem"
1755
- },
1756
- children: wallet.chain.name
1757
- }
1758
- ),
1759
- /* @__PURE__ */ jsxRuntime.jsx(
1760
- "span",
1761
- {
1762
- style: {
1763
- fontSize: "0.7rem",
1764
- color: tokens.textMuted,
1765
- fontFamily: '"SF Mono", "Fira Code", monospace'
1766
- },
1767
- children: wallet.name
1768
- }
1769
- ),
1770
- walletBal && /* @__PURE__ */ jsxRuntime.jsx(
1771
- "span",
1772
- {
1773
- style: {
1774
- fontSize: "0.7rem",
1775
- color: tokens.textMuted,
1776
- marginLeft: "auto"
1777
- },
1778
- children: walletBal
1779
- }
1780
- )
1781
- ]
1782
- }
1783
- ),
1784
- isWalletSelected && /* @__PURE__ */ jsxRuntime.jsx(
1785
- "svg",
1786
- {
1787
- width: "12",
1788
- height: "12",
1789
- viewBox: "0 0 24 24",
1790
- fill: "none",
1791
- style: {
1792
- flexShrink: 0,
1793
- marginLeft: "8px"
1794
- },
1795
- children: /* @__PURE__ */ jsxRuntime.jsx(
1796
- "path",
1797
- {
1798
- d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
1799
- fill: tokens.accent
1800
- }
1801
- )
1802
- }
1803
- )
1804
- ]
1805
- },
1806
- wallet.id
1807
- );
1808
- })
1809
- ] }, account.id);
1810
- })
1811
- }
1812
- )
1813
- ] });
1814
- }
1815
- var ASSETS = ["USDC", "USDT"];
1816
- function AdvancedSettings({
1817
- settings,
1818
- onChange,
1819
- chains,
1820
- providers,
1821
- onConnectNewAccount,
1822
- connectingNewAccount
1823
- }) {
1824
- const { tokens } = useSwypeConfig();
1825
- const [open, setOpen] = react.useState(false);
1826
- const [showProviders, setShowProviders] = react.useState(false);
1827
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "12px" }, children: [
1828
- /* @__PURE__ */ jsxRuntime.jsxs(
1829
- "button",
1830
- {
1831
- onClick: () => setOpen(!open),
1832
- style: {
1833
- display: "flex",
1834
- alignItems: "center",
1835
- gap: "6px",
1836
- background: "transparent",
1837
- border: "none",
1838
- cursor: "pointer",
1839
- padding: "4px 0",
1840
- color: tokens.textMuted,
1841
- fontFamily: "inherit",
1842
- fontSize: "0.8rem",
1843
- fontWeight: 500,
1844
- outline: "none",
1845
- letterSpacing: "0.02em"
1846
- },
1847
- children: [
1848
- /* @__PURE__ */ jsxRuntime.jsx(
1849
- "svg",
1850
- {
1851
- width: "10",
1852
- height: "10",
1853
- viewBox: "0 0 24 24",
1854
- fill: "none",
1855
- style: {
1856
- transform: open ? "rotate(180deg)" : "rotate(0deg)",
1857
- transition: "transform 0.15s ease"
1858
- },
1859
- children: /* @__PURE__ */ jsxRuntime.jsx(
1860
- "path",
1861
- {
1862
- d: "M7 10l5 5 5-5",
1863
- stroke: tokens.textMuted,
1864
- strokeWidth: "2.5",
1865
- strokeLinecap: "round",
1866
- strokeLinejoin: "round"
1867
- }
1868
- )
1869
- }
1870
- ),
1871
- "Advanced options"
1872
- ]
1873
- }
1874
- ),
1875
- open && /* @__PURE__ */ jsxRuntime.jsxs(
1876
- "div",
1877
- {
1878
- style: {
1879
- marginTop: "10px",
1880
- padding: "14px",
1881
- background: tokens.bgInput,
1882
- borderRadius: tokens.radiusLg,
1883
- border: `1px solid ${tokens.border}`
1884
- },
1885
- children: [
1886
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "14px" }, children: [
1887
- /* @__PURE__ */ jsxRuntime.jsx(
1888
- "label",
1889
- {
1890
- style: {
1891
- display: "block",
1892
- fontSize: "0.7rem",
1893
- fontWeight: 600,
1894
- color: tokens.textMuted,
1895
- textTransform: "uppercase",
1896
- letterSpacing: "0.05em",
1897
- marginBottom: "6px"
1898
- },
1899
- children: "Asset"
1900
- }
1901
- ),
1902
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: "6px" }, children: ASSETS.map((asset) => {
1903
- const isSelected = settings.asset === asset;
1904
- return /* @__PURE__ */ jsxRuntime.jsx(
1905
- "button",
1906
- {
1907
- onClick: () => onChange({
1908
- ...settings,
1909
- asset: isSelected ? null : asset
1910
- }),
1911
- style: {
1912
- padding: "7px 14px",
1913
- fontSize: "0.8rem",
1914
- fontWeight: 600,
1915
- fontFamily: "inherit",
1916
- borderRadius: "999px",
1917
- border: `1.5px solid ${isSelected ? tokens.accent : tokens.border}`,
1918
- background: isSelected ? tokens.accent + "18" : tokens.bgCard,
1919
- color: isSelected ? tokens.accent : tokens.text,
1920
- cursor: "pointer",
1921
- outline: "none",
1922
- transition: "all 0.12s ease"
1923
- },
1924
- children: asset
1925
- },
1926
- asset
1927
- );
1928
- }) })
1929
- ] }),
1930
- chains.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "14px" }, children: [
1931
- /* @__PURE__ */ jsxRuntime.jsx(
1932
- "label",
1933
- {
1934
- style: {
1935
- display: "block",
1936
- fontSize: "0.7rem",
1937
- fontWeight: 600,
1938
- color: tokens.textMuted,
1939
- textTransform: "uppercase",
1940
- letterSpacing: "0.05em",
1941
- marginBottom: "6px"
1942
- },
1943
- children: "Chain"
1944
- }
1945
- ),
1946
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: chains.map((chain) => {
1947
- const isSelected = settings.chain === chain.name;
1948
- return /* @__PURE__ */ jsxRuntime.jsx(
1949
- "button",
1950
- {
1951
- onClick: () => onChange({
1952
- ...settings,
1953
- chain: isSelected ? null : chain.name
1954
- }),
1955
- style: {
1956
- padding: "7px 14px",
1957
- fontSize: "0.8rem",
1958
- fontWeight: 600,
1959
- fontFamily: "inherit",
1960
- borderRadius: "999px",
1961
- border: `1.5px solid ${isSelected ? tokens.accent : tokens.border}`,
1962
- background: isSelected ? tokens.accent + "18" : tokens.bgCard,
1963
- color: isSelected ? tokens.accent : tokens.text,
1964
- cursor: "pointer",
1965
- outline: "none",
1966
- transition: "all 0.12s ease"
1967
- },
1968
- children: chain.name
1969
- },
1970
- chain.id
1971
- );
1972
- }) })
1973
- ] }),
1974
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: !showProviders ? /* @__PURE__ */ jsxRuntime.jsxs(
1975
- "button",
1976
- {
1977
- onClick: () => setShowProviders(true),
1978
- disabled: connectingNewAccount,
1979
- style: {
1980
- display: "flex",
1981
- alignItems: "center",
1982
- gap: "6px",
1983
- background: tokens.bgCard,
1984
- border: `1px dashed ${tokens.border}`,
1985
- borderRadius: "999px",
1986
- padding: "10px 14px",
1987
- width: "100%",
1988
- cursor: connectingNewAccount ? "not-allowed" : "pointer",
1989
- color: tokens.textSecondary,
1990
- fontFamily: "inherit",
1991
- fontSize: "0.825rem",
1992
- fontWeight: 500,
1993
- outline: "none",
1994
- opacity: connectingNewAccount ? 0.5 : 1,
1995
- transition: "opacity 0.1s ease"
1996
- },
1997
- children: [
1998
- /* @__PURE__ */ jsxRuntime.jsx(
1999
- "svg",
2000
- {
2001
- width: "14",
2002
- height: "14",
2003
- viewBox: "0 0 24 24",
2004
- fill: "none",
2005
- children: /* @__PURE__ */ jsxRuntime.jsx(
2006
- "path",
2007
- {
2008
- d: "M12 5v14M5 12h14",
2009
- stroke: tokens.textMuted,
2010
- strokeWidth: "2",
2011
- strokeLinecap: "round"
2012
- }
2013
- )
2014
- }
2015
- ),
2016
- "Connect new account"
2017
- ]
2018
- }
2019
- ) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2020
- /* @__PURE__ */ jsxRuntime.jsxs(
2021
- "div",
2022
- {
2023
- style: {
2024
- display: "flex",
2025
- alignItems: "center",
2026
- justifyContent: "space-between",
2027
- marginBottom: "8px"
2028
- },
2029
- children: [
2030
- /* @__PURE__ */ jsxRuntime.jsx(
2031
- "label",
2032
- {
2033
- style: {
2034
- fontSize: "0.7rem",
2035
- fontWeight: 600,
2036
- color: tokens.textMuted,
2037
- textTransform: "uppercase",
2038
- letterSpacing: "0.05em"
2039
- },
2040
- children: "Select provider"
2041
- }
2042
- ),
2043
- /* @__PURE__ */ jsxRuntime.jsx(
2044
- "button",
2045
- {
2046
- onClick: () => setShowProviders(false),
2047
- style: {
2048
- background: "transparent",
2049
- border: "none",
2050
- cursor: "pointer",
2051
- color: tokens.textMuted,
2052
- fontSize: "0.75rem",
2053
- fontFamily: "inherit",
2054
- outline: "none",
2055
- padding: "2px 4px"
2056
- },
2057
- children: "Cancel"
2058
- }
2059
- )
2060
- ]
2061
- }
2062
- ),
2063
- /* @__PURE__ */ jsxRuntime.jsx(
2064
- "div",
2065
- {
2066
- style: {
2067
- display: "flex",
2068
- flexDirection: "column",
2069
- gap: "6px"
2070
- },
2071
- children: providers.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
2072
- ProviderCard,
2073
- {
2074
- provider: p,
2075
- selected: false,
2076
- onClick: () => {
2077
- onConnectNewAccount(p.id);
2078
- setShowProviders(false);
2079
- }
2080
- },
2081
- p.id
2082
- ))
2083
- }
2084
- )
2085
- ] }) })
2086
- ]
2087
- }
2088
- )
2089
- ] });
2090
- }
2091
1400
 
2092
1401
  // src/auth.ts
2093
1402
  var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
@@ -2138,14 +1447,6 @@ function getTransferStatus(polledTransfer, localTransfer) {
2138
1447
  const transfer = resolvePreferredTransfer(polledTransfer, localTransfer);
2139
1448
  return transfer?.status ?? "UNKNOWN";
2140
1449
  }
2141
- function getDisplayTransferStatus(polledTransfer, localTransfer) {
2142
- return getTransferStatus(polledTransfer, localTransfer).toUpperCase();
2143
- }
2144
- function getTransferIdSuffix(polledTransfer, localTransfer) {
2145
- const transfer = resolvePreferredTransfer(polledTransfer, localTransfer);
2146
- if (!transfer?.id) return "n/a";
2147
- return transfer.id.slice(-8);
2148
- }
2149
1450
  function hasProcessingTimedOut(processingStartedAtMs, nowMs) {
2150
1451
  if (!processingStartedAtMs) return false;
2151
1452
  return nowMs - processingStartedAtMs >= PROCESSING_TIMEOUT_MS;
@@ -2153,100 +1454,1928 @@ function hasProcessingTimedOut(processingStartedAtMs, nowMs) {
2153
1454
  function buildProcessingTimeoutMessage(status) {
2154
1455
  return `Payment is taking longer than expected (status: ${status}). Please try again.`;
2155
1456
  }
2156
- var ACTIVE_CREDENTIAL_STORAGE_KEY = "swype_active_credential_id";
2157
- var MIN_SEND_AMOUNT_USD = 0.25;
2158
- function isMobile() {
2159
- if (typeof navigator === "undefined") return false;
2160
- return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
2161
- navigator.userAgent
2162
- );
1457
+
1458
+ // src/walletFlow.ts
1459
+ var MOBILE_USER_AGENT_PATTERN = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
1460
+ function isMobileUserAgent(userAgent) {
1461
+ if (!userAgent) {
1462
+ return false;
1463
+ }
1464
+ return MOBILE_USER_AGENT_PATTERN.test(userAgent);
2163
1465
  }
2164
- function computeSmartDefaults(accts, transferAmount) {
2165
- if (accts.length === 0) return null;
2166
- for (const acct of accts) {
2167
- for (const wallet of acct.wallets) {
2168
- if (wallet.status === "ACTIVE") {
2169
- const bestSource = wallet.sources.find(
2170
- (s) => s.balance.available.amount >= transferAmount
2171
- );
2172
- if (bestSource) {
2173
- return { accountId: acct.id, walletId: wallet.id };
2174
- }
1466
+ function shouldUseWalletConnector(options) {
1467
+ return options.useWalletConnector ?? !isMobileUserAgent(options.userAgent);
1468
+ }
1469
+ function ScreenLayout({ children, footer }) {
1470
+ const { tokens } = useSwypeConfig();
1471
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle(tokens.bgCard), children: [
1472
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: bodyStyle, children }),
1473
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { style: footerStyle, children: footer })
1474
+ ] });
1475
+ }
1476
+ var containerStyle = (bg) => ({
1477
+ display: "flex",
1478
+ flexDirection: "column",
1479
+ minHeight: "100%",
1480
+ maxWidth: 420,
1481
+ width: "100%",
1482
+ margin: "0 auto",
1483
+ background: bg,
1484
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
1485
+ boxSizing: "border-box"
1486
+ });
1487
+ var bodyStyle = {
1488
+ flex: 1,
1489
+ padding: "0 24px",
1490
+ display: "flex",
1491
+ flexDirection: "column"
1492
+ };
1493
+ var footerStyle = {
1494
+ padding: "16px 24px 24px",
1495
+ marginTop: "auto"
1496
+ };
1497
+ function ScreenHeader({ title, right, onBack, badge }) {
1498
+ const { tokens } = useSwypeConfig();
1499
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyle, children: [
1500
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: leftSlotStyle, children: onBack && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onBack, style: backButtonStyle(tokens.text), "aria-label": "Go back", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 18l-6-6 6-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }) }),
1501
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: centerSlotStyle, children: [
1502
+ title && /* @__PURE__ */ jsxRuntime.jsx("span", { style: titleStyle(tokens.text), children: title }),
1503
+ badge && /* @__PURE__ */ jsxRuntime.jsx("span", { style: badgeStyle(tokens.textMuted), children: badge })
1504
+ ] }),
1505
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: rightSlotStyle, children: right })
1506
+ ] });
1507
+ }
1508
+ var headerStyle = {
1509
+ display: "flex",
1510
+ alignItems: "center",
1511
+ padding: "16px 0",
1512
+ minHeight: 52
1513
+ };
1514
+ var leftSlotStyle = { flex: "0 0 40px" };
1515
+ var rightSlotStyle = { flex: "0 0 40px", display: "flex", justifyContent: "flex-end" };
1516
+ var centerSlotStyle = {
1517
+ flex: 1,
1518
+ display: "flex",
1519
+ alignItems: "center",
1520
+ justifyContent: "center",
1521
+ gap: 8
1522
+ };
1523
+ var backButtonStyle = (color) => ({
1524
+ background: "transparent",
1525
+ border: "none",
1526
+ cursor: "pointer",
1527
+ padding: 4,
1528
+ color,
1529
+ display: "flex",
1530
+ alignItems: "center",
1531
+ justifyContent: "center"
1532
+ });
1533
+ var titleStyle = (color) => ({
1534
+ fontSize: "0.9rem",
1535
+ fontWeight: 600,
1536
+ color,
1537
+ letterSpacing: "-0.01em"
1538
+ });
1539
+ var badgeStyle = (color) => ({
1540
+ fontSize: "0.78rem",
1541
+ fontWeight: 500,
1542
+ color
1543
+ });
1544
+ function PoweredByFooter() {
1545
+ const { tokens } = useSwypeConfig();
1546
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle2(tokens.textMuted), children: [
1547
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
1548
+ "path",
1549
+ {
1550
+ d: "M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM12 17c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3-9H9V6c0-1.66 1.34-3 3-3s3 1.34 3 3v2z",
1551
+ fill: "currentColor"
2175
1552
  }
1553
+ ) }),
1554
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Powered by Swype" }),
1555
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: dotStyle, children: "\xB7" }),
1556
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Non-custodial" })
1557
+ ] });
1558
+ }
1559
+ var containerStyle2 = (color) => ({
1560
+ display: "flex",
1561
+ alignItems: "center",
1562
+ justifyContent: "center",
1563
+ gap: 6,
1564
+ fontSize: "0.75rem",
1565
+ color,
1566
+ padding: "12px 0 4px"
1567
+ });
1568
+ var dotStyle = { opacity: 0.5 };
1569
+ function PrimaryButton({ children, onClick, disabled, loading, icon }) {
1570
+ const { tokens } = useSwypeConfig();
1571
+ const isDisabled = disabled || loading;
1572
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1573
+ "button",
1574
+ {
1575
+ type: "button",
1576
+ onClick,
1577
+ disabled: isDisabled,
1578
+ style: buttonStyle(tokens, isDisabled),
1579
+ children: [
1580
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { style: iconWrapStyle, children: icon }),
1581
+ loading ? "Please wait..." : children
1582
+ ]
2176
1583
  }
2177
- }
2178
- let bestAccount = null;
2179
- let bestWallet = null;
2180
- let bestBalance = -1;
2181
- let bestIsActive = false;
2182
- for (const acct of accts) {
2183
- for (const wallet of acct.wallets) {
2184
- const walletBal = wallet.balance.available.amount;
2185
- const isActive = wallet.status === "ACTIVE";
2186
- if (walletBal > bestBalance || walletBal === bestBalance && isActive && !bestIsActive) {
2187
- bestBalance = walletBal;
2188
- bestAccount = acct;
2189
- bestWallet = wallet;
2190
- bestIsActive = isActive;
2191
- }
1584
+ );
1585
+ }
1586
+ var buttonStyle = (tokens, disabled) => ({
1587
+ width: "100%",
1588
+ padding: "16px 24px",
1589
+ background: `linear-gradient(180deg, ${tokens.accent}, ${tokens.accentHover})`,
1590
+ color: tokens.accentText,
1591
+ border: "none",
1592
+ borderRadius: 999,
1593
+ fontSize: "1rem",
1594
+ fontWeight: 700,
1595
+ cursor: disabled ? "not-allowed" : "pointer",
1596
+ opacity: disabled ? 0.5 : 1,
1597
+ transition: "filter 0.15s ease, transform 0.15s ease",
1598
+ fontFamily: "inherit",
1599
+ boxShadow: "0 8px 18px rgba(40, 182, 122, 0.22)",
1600
+ display: "flex",
1601
+ alignItems: "center",
1602
+ justifyContent: "center",
1603
+ gap: 8
1604
+ });
1605
+ var iconWrapStyle = {
1606
+ display: "flex",
1607
+ alignItems: "center"
1608
+ };
1609
+ function OutlineButton({ children, onClick, disabled }) {
1610
+ const { tokens } = useSwypeConfig();
1611
+ return /* @__PURE__ */ jsxRuntime.jsx(
1612
+ "button",
1613
+ {
1614
+ type: "button",
1615
+ onClick,
1616
+ disabled,
1617
+ style: buttonStyle2(tokens, disabled),
1618
+ children
2192
1619
  }
1620
+ );
1621
+ }
1622
+ var buttonStyle2 = (tokens, disabled) => ({
1623
+ width: "100%",
1624
+ padding: "16px 24px",
1625
+ background: tokens.bgCard,
1626
+ color: tokens.text,
1627
+ border: `1.5px solid ${tokens.border}`,
1628
+ borderRadius: 999,
1629
+ fontSize: "0.95rem",
1630
+ fontWeight: 600,
1631
+ cursor: disabled ? "not-allowed" : "pointer",
1632
+ opacity: disabled ? 0.5 : 1,
1633
+ fontFamily: "inherit",
1634
+ transition: "opacity 0.15s ease"
1635
+ });
1636
+ var defaultIcon = /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
1637
+ "path",
1638
+ {
1639
+ d: "M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z",
1640
+ fill: "currentColor"
2193
1641
  }
2194
- if (bestAccount) {
2195
- return {
2196
- accountId: bestAccount.id,
2197
- walletId: bestWallet?.id ?? null
2198
- };
2199
- }
2200
- return { accountId: accts[0].id, walletId: null };
1642
+ ) });
1643
+ function InfoBanner({ children, icon }) {
1644
+ const { tokens } = useSwypeConfig();
1645
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle3(tokens.accent), children: [
1646
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: iconStyle, children: icon ?? defaultIcon }),
1647
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: textStyle, children })
1648
+ ] });
2201
1649
  }
2202
- function parseRawBalance(rawBalance, decimals) {
2203
- const parsed = Number(rawBalance);
2204
- if (!Number.isFinite(parsed)) return 0;
2205
- return parsed / 10 ** decimals;
1650
+ var containerStyle3 = (accent) => ({
1651
+ display: "flex",
1652
+ alignItems: "flex-start",
1653
+ gap: 10,
1654
+ padding: "14px 16px",
1655
+ background: `${accent}0D`,
1656
+ borderRadius: 16,
1657
+ fontSize: "0.82rem",
1658
+ lineHeight: 1.5,
1659
+ color: "inherit"
1660
+ });
1661
+ var iconStyle = {
1662
+ flexShrink: 0,
1663
+ marginTop: 1,
1664
+ display: "flex"
1665
+ };
1666
+ var textStyle = { flex: 1 };
1667
+ function WarningBanner({ title, children }) {
1668
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle4, children: [
1669
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyle2, children: [
1670
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", style: iconStyle2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z", fill: "#F57C00" }) }),
1671
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: title })
1672
+ ] }),
1673
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: bodyStyle2, children })
1674
+ ] });
2206
1675
  }
2207
- function buildSelectSourceChoices(options) {
2208
- const chainChoices = [];
2209
- const chainIndexByName = /* @__PURE__ */ new Map();
2210
- for (const option of options) {
2211
- const chainName = option.chainName;
2212
- const tokenSymbol = option.tokenSymbol;
2213
- const balance = parseRawBalance(option.rawBalance, option.decimals);
2214
- let chainChoice;
2215
- const existingChainIdx = chainIndexByName.get(chainName);
2216
- if (existingChainIdx === void 0) {
2217
- chainChoice = { chainName, balance: 0, tokens: [] };
2218
- chainIndexByName.set(chainName, chainChoices.length);
2219
- chainChoices.push(chainChoice);
2220
- } else {
2221
- chainChoice = chainChoices[existingChainIdx];
1676
+ var containerStyle4 = {
1677
+ padding: "14px 16px",
1678
+ background: "#FFF8E1",
1679
+ border: "1px solid #FFE082",
1680
+ borderRadius: 16,
1681
+ fontSize: "0.84rem",
1682
+ lineHeight: 1.5,
1683
+ color: "#5D4037"
1684
+ };
1685
+ var headerStyle2 = {
1686
+ display: "flex",
1687
+ alignItems: "center",
1688
+ gap: 8,
1689
+ marginBottom: 4,
1690
+ fontWeight: 600,
1691
+ color: "#37474F"
1692
+ };
1693
+ var iconStyle2 = { flexShrink: 0 };
1694
+ var bodyStyle2 = { color: "#6D4C41" };
1695
+ function IconCircle({ children, variant = "accent", size = 56 }) {
1696
+ const { tokens } = useSwypeConfig();
1697
+ const bgMap = {
1698
+ accent: `${tokens.accent}18`,
1699
+ success: tokens.successBg,
1700
+ error: tokens.errorBg
1701
+ };
1702
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: circleStyle(bgMap[variant], size), children });
1703
+ }
1704
+ var circleStyle = (bg, size) => ({
1705
+ width: size,
1706
+ height: size,
1707
+ borderRadius: "50%",
1708
+ background: bg,
1709
+ display: "flex",
1710
+ alignItems: "center",
1711
+ justifyContent: "center",
1712
+ margin: "0 auto",
1713
+ flexShrink: 0
1714
+ });
1715
+ function OtpInput({ value, onChange, length = 6, disabled }) {
1716
+ const { tokens } = useSwypeConfig();
1717
+ const inputsRef = react.useRef([]);
1718
+ const digits = value.padEnd(length, "").split("").slice(0, length);
1719
+ const focusInput = react.useCallback((index) => {
1720
+ const clamped = Math.max(0, Math.min(index, length - 1));
1721
+ inputsRef.current[clamped]?.focus();
1722
+ }, [length]);
1723
+ const handleChange = react.useCallback((index, char) => {
1724
+ const digit = char.replace(/\D/g, "").slice(0, 1);
1725
+ const next = digits.slice();
1726
+ next[index] = digit;
1727
+ const joined = next.join("").replace(/\s/g, "");
1728
+ onChange(joined);
1729
+ if (digit && index < length - 1) {
1730
+ focusInput(index + 1);
2222
1731
  }
2223
- chainChoice.balance += balance;
2224
- const existingToken = chainChoice.tokens.find((token) => token.tokenSymbol === tokenSymbol);
2225
- if (existingToken) {
2226
- existingToken.balance += balance;
2227
- } else {
2228
- chainChoice.tokens.push({ tokenSymbol, balance });
1732
+ }, [digits, onChange, length, focusInput]);
1733
+ const handleKeyDown = react.useCallback((index, e) => {
1734
+ if (e.key === "Backspace" && !digits[index] && index > 0) {
1735
+ focusInput(index - 1);
1736
+ } else if (e.key === "ArrowLeft" && index > 0) {
1737
+ focusInput(index - 1);
1738
+ } else if (e.key === "ArrowRight" && index < length - 1) {
1739
+ focusInput(index + 1);
2229
1740
  }
2230
- }
2231
- return chainChoices;
1741
+ }, [digits, focusInput, length]);
1742
+ const handlePaste = react.useCallback((e) => {
1743
+ e.preventDefault();
1744
+ const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, length);
1745
+ onChange(pasted);
1746
+ focusInput(Math.min(pasted.length, length - 1));
1747
+ }, [onChange, length, focusInput]);
1748
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: containerStyle5, children: digits.map((digit, i) => /* @__PURE__ */ jsxRuntime.jsx(
1749
+ "input",
1750
+ {
1751
+ ref: (el) => {
1752
+ inputsRef.current[i] = el;
1753
+ },
1754
+ type: "text",
1755
+ inputMode: "numeric",
1756
+ autoComplete: i === 0 ? "one-time-code" : "off",
1757
+ maxLength: 1,
1758
+ value: digit.trim(),
1759
+ disabled,
1760
+ onChange: (e) => handleChange(i, e.target.value),
1761
+ onKeyDown: (e) => handleKeyDown(i, e),
1762
+ onPaste: i === 0 ? handlePaste : void 0,
1763
+ onFocus: (e) => e.target.select(),
1764
+ style: inputStyle(tokens, !!digit.trim())
1765
+ },
1766
+ i
1767
+ )) });
2232
1768
  }
2233
- function SwypePayment({
2234
- destination,
2235
- onComplete,
2236
- onError,
2237
- useWalletConnector,
2238
- idempotencyKey,
2239
- merchantAuthorization
1769
+ var containerStyle5 = {
1770
+ display: "flex",
1771
+ gap: 8,
1772
+ justifyContent: "center"
1773
+ };
1774
+ var inputStyle = (tokens, filled) => ({
1775
+ width: 44,
1776
+ height: 52,
1777
+ borderRadius: 12,
1778
+ border: `1.5px solid ${filled ? tokens.borderFocus : tokens.border}`,
1779
+ background: tokens.bgInput,
1780
+ color: tokens.text,
1781
+ fontSize: "1.25rem",
1782
+ fontWeight: 600,
1783
+ fontFamily: "inherit",
1784
+ textAlign: "center",
1785
+ outline: "none",
1786
+ caretColor: tokens.borderFocus,
1787
+ transition: "border-color 0.15s ease"
1788
+ });
1789
+ function LimitSlider({
1790
+ value,
1791
+ min,
1792
+ max,
1793
+ step = 1,
1794
+ onChange,
1795
+ ticks,
1796
+ disabled
2240
1797
  }) {
2241
- const { apiBaseUrl, tokens, depositAmount } = useSwypeConfig();
2242
- const { ready, authenticated, user, logout, getAccessToken } = reactAuth.usePrivy();
2243
- const {
2244
- sendCode: sendEmailCode,
2245
- loginWithCode: loginWithEmailCode,
2246
- state: emailLoginState
2247
- } = reactAuth.useLoginWithEmail();
2248
- const {
2249
- sendCode: sendSmsCode,
1798
+ const { tokens } = useSwypeConfig();
1799
+ const pct = (value - min) / (max - min) * 100;
1800
+ const handleChange = react.useCallback(
1801
+ (e) => onChange(Number(e.target.value)),
1802
+ [onChange]
1803
+ );
1804
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: wrapperStyle, children: [
1805
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: trackContainerStyle, children: [
1806
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: trackBgStyle(tokens.border) }),
1807
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: trackFillStyle(tokens.accent, pct) }),
1808
+ /* @__PURE__ */ jsxRuntime.jsx(
1809
+ "input",
1810
+ {
1811
+ type: "range",
1812
+ min,
1813
+ max,
1814
+ step,
1815
+ value,
1816
+ onChange: handleChange,
1817
+ disabled,
1818
+ style: rangeInputStyle(tokens.accent)
1819
+ }
1820
+ )
1821
+ ] }),
1822
+ ticks && ticks.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: ticksStyle, children: ticks.map((tick) => /* @__PURE__ */ jsxRuntime.jsxs("span", { style: tickLabelStyle(tokens.textMuted), children: [
1823
+ "$",
1824
+ tick
1825
+ ] }, tick)) }),
1826
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: sliderThumbCss(tokens.accent) })
1827
+ ] });
1828
+ }
1829
+ var wrapperStyle = { width: "100%" };
1830
+ var trackContainerStyle = {
1831
+ position: "relative",
1832
+ height: 28,
1833
+ display: "flex",
1834
+ alignItems: "center"
1835
+ };
1836
+ var trackBgStyle = (color) => ({
1837
+ position: "absolute",
1838
+ left: 0,
1839
+ right: 0,
1840
+ height: 4,
1841
+ borderRadius: 2,
1842
+ background: color
1843
+ });
1844
+ var trackFillStyle = (color, pct) => ({
1845
+ position: "absolute",
1846
+ left: 0,
1847
+ width: `${pct}%`,
1848
+ height: 4,
1849
+ borderRadius: 2,
1850
+ background: color
1851
+ });
1852
+ var rangeInputStyle = (_accent) => ({
1853
+ position: "absolute",
1854
+ left: 0,
1855
+ right: 0,
1856
+ width: "100%",
1857
+ height: 28,
1858
+ margin: 0,
1859
+ opacity: 0,
1860
+ cursor: "pointer",
1861
+ zIndex: 2
1862
+ });
1863
+ var ticksStyle = {
1864
+ display: "flex",
1865
+ justifyContent: "space-between",
1866
+ marginTop: 6
1867
+ };
1868
+ var tickLabelStyle = (color) => ({
1869
+ fontSize: "0.72rem",
1870
+ fontWeight: 500,
1871
+ color
1872
+ });
1873
+ var sliderThumbCss = (accent) => `
1874
+ .swype-slider-wrap input[type="range"] {
1875
+ -webkit-appearance: none;
1876
+ appearance: none;
1877
+ opacity: 1 !important;
1878
+ background: transparent;
1879
+ }
1880
+ .swype-slider-wrap input[type="range"]::-webkit-slider-thumb {
1881
+ -webkit-appearance: none;
1882
+ width: 20px;
1883
+ height: 20px;
1884
+ border-radius: 50%;
1885
+ background: ${accent};
1886
+ border: 3px solid #fff;
1887
+ box-shadow: 0 2px 6px rgba(0,0,0,0.15);
1888
+ cursor: pointer;
1889
+ }
1890
+ `;
1891
+ function SourceCard({ name, address, verified, onChangeSource }) {
1892
+ const { tokens } = useSwypeConfig();
1893
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle6(tokens), children: [
1894
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: leftStyle, children: [
1895
+ /* @__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(
1896
+ "path",
1897
+ {
1898
+ 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",
1899
+ fill: "currentColor"
1900
+ }
1901
+ ) }) }),
1902
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1903
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: nameRowStyle, children: [
1904
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: nameStyle(tokens.text), children: name }),
1905
+ 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 }) })
1906
+ ] }),
1907
+ address && /* @__PURE__ */ jsxRuntime.jsx("span", { style: addressStyle(tokens.textMuted), children: address })
1908
+ ] })
1909
+ ] }),
1910
+ onChangeSource && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onChangeSource, style: changeStyle(tokens.accent), children: "Change source" })
1911
+ ] });
1912
+ }
1913
+ var containerStyle6 = (tokens) => ({
1914
+ display: "flex",
1915
+ alignItems: "center",
1916
+ justifyContent: "space-between",
1917
+ padding: "12px 16px",
1918
+ background: tokens.bgInput,
1919
+ border: `1px solid ${tokens.border}`,
1920
+ borderRadius: 16
1921
+ });
1922
+ var leftStyle = {
1923
+ display: "flex",
1924
+ alignItems: "center",
1925
+ gap: 10
1926
+ };
1927
+ var iconStyle3 = (color) => ({
1928
+ color,
1929
+ display: "flex",
1930
+ alignItems: "center"
1931
+ });
1932
+ var nameRowStyle = {
1933
+ display: "flex",
1934
+ alignItems: "center",
1935
+ gap: 4
1936
+ };
1937
+ var nameStyle = (color) => ({
1938
+ fontWeight: 600,
1939
+ fontSize: "0.9rem",
1940
+ color
1941
+ });
1942
+ var addressStyle = (color) => ({
1943
+ fontSize: "0.72rem",
1944
+ color,
1945
+ fontFamily: '"SF Mono", "Fira Code", monospace'
1946
+ });
1947
+ var changeStyle = (color) => ({
1948
+ background: "transparent",
1949
+ border: "none",
1950
+ color,
1951
+ fontWeight: 600,
1952
+ fontSize: "0.82rem",
1953
+ cursor: "pointer",
1954
+ fontFamily: "inherit",
1955
+ padding: 0
1956
+ });
1957
+ function StepList({ steps }) {
1958
+ const { tokens } = useSwypeConfig();
1959
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: listStyle, children: steps.map((step, i) => {
1960
+ const isComplete = step.status === "complete";
1961
+ const isActive = step.status === "active";
1962
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: rowStyle, children: [
1963
+ /* @__PURE__ */ jsxRuntime.jsx(
1964
+ "div",
1965
+ {
1966
+ style: badgeStyle2(
1967
+ isComplete ? tokens.accent : isActive ? tokens.accent : tokens.border,
1968
+ isComplete || isActive
1969
+ ),
1970
+ children: isComplete ? /* @__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: "#fff" }) }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: badgeNumberStyle(isActive), children: i + 1 })
1971
+ }
1972
+ ),
1973
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: labelContainerStyle, children: [
1974
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: labelStyle(isComplete || isActive ? tokens.text : tokens.textMuted), children: step.label }),
1975
+ step.detail && /* @__PURE__ */ jsxRuntime.jsx("span", { style: detailStyle(tokens.textMuted), children: step.detail })
1976
+ ] })
1977
+ ] }, i);
1978
+ }) });
1979
+ }
1980
+ var listStyle = {
1981
+ display: "flex",
1982
+ flexDirection: "column",
1983
+ gap: 12
1984
+ };
1985
+ var rowStyle = {
1986
+ display: "flex",
1987
+ alignItems: "center",
1988
+ gap: 12
1989
+ };
1990
+ var badgeStyle2 = (color, filled) => ({
1991
+ width: 28,
1992
+ height: 28,
1993
+ borderRadius: "50%",
1994
+ background: filled ? color : "transparent",
1995
+ border: filled ? "none" : `1.5px solid ${color}`,
1996
+ display: "flex",
1997
+ alignItems: "center",
1998
+ justifyContent: "center",
1999
+ flexShrink: 0
2000
+ });
2001
+ var badgeNumberStyle = (active) => ({
2002
+ fontSize: "0.75rem",
2003
+ fontWeight: 600,
2004
+ color: active ? "#fff" : "inherit"
2005
+ });
2006
+ var labelContainerStyle = {
2007
+ display: "flex",
2008
+ flexDirection: "column"
2009
+ };
2010
+ var labelStyle = (color) => ({
2011
+ fontSize: "0.9rem",
2012
+ fontWeight: 500,
2013
+ color
2014
+ });
2015
+ var detailStyle = (color) => ({
2016
+ fontSize: "0.75rem",
2017
+ color
2018
+ });
2019
+ function LoginScreen({
2020
+ authInput,
2021
+ onAuthInputChange,
2022
+ onSubmit,
2023
+ sending,
2024
+ error,
2025
+ onBack
2026
+ }) {
2027
+ const { tokens } = useSwypeConfig();
2028
+ const disabled = authInput.trim().length === 0 || sending;
2029
+ const walletLogos = ["MM", "R", "O", "P", "+"];
2030
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2031
+ ScreenLayout,
2032
+ {
2033
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2034
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onSubmit, disabled, loading: sending, children: "Continue" }),
2035
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: dividerStyle(tokens), children: [
2036
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerLineStyle(tokens.border) }),
2037
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "works with" }),
2038
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerLineStyle(tokens.border) })
2039
+ ] }),
2040
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: logosRowStyle, children: walletLogos.map((label) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: logoCircleStyle(tokens), children: label }, label)) }),
2041
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2042
+ ] }),
2043
+ children: [
2044
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onBack }),
2045
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle, children: [
2046
+ /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "accent", size: 56, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
2047
+ "path",
2048
+ {
2049
+ d: "M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z",
2050
+ fill: tokens.accent
2051
+ }
2052
+ ) }) }),
2053
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle(tokens.text), children: "One-time setup.\nOne-tap deposits after." }),
2054
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle(tokens.textSecondary), children: "Protected by Face ID." }),
2055
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorStyle(tokens), children: error }),
2056
+ /* @__PURE__ */ jsxRuntime.jsx(
2057
+ "input",
2058
+ {
2059
+ id: "swype-login-identifier",
2060
+ type: "text",
2061
+ inputMode: "text",
2062
+ autoComplete: "username",
2063
+ placeholder: "Email or phone number",
2064
+ value: authInput,
2065
+ onChange: (e) => onAuthInputChange(e.target.value),
2066
+ onKeyDown: (e) => {
2067
+ if (e.key === "Enter" && !disabled) onSubmit();
2068
+ },
2069
+ style: inputStyle2(tokens)
2070
+ }
2071
+ )
2072
+ ] })
2073
+ ]
2074
+ }
2075
+ );
2076
+ }
2077
+ var contentStyle = {
2078
+ textAlign: "center",
2079
+ flex: 1,
2080
+ display: "flex",
2081
+ flexDirection: "column",
2082
+ alignItems: "center",
2083
+ paddingTop: 24
2084
+ };
2085
+ var headingStyle = (color) => ({
2086
+ fontSize: "1.65rem",
2087
+ fontWeight: 700,
2088
+ lineHeight: 1.2,
2089
+ letterSpacing: "-0.02em",
2090
+ color,
2091
+ margin: "20px 0 8px",
2092
+ whiteSpace: "pre-line"
2093
+ });
2094
+ var subtitleStyle = (color) => ({
2095
+ fontSize: "0.84rem",
2096
+ color,
2097
+ margin: "0 0 24px",
2098
+ lineHeight: 1.5
2099
+ });
2100
+ var inputStyle2 = (tokens) => ({
2101
+ width: "100%",
2102
+ padding: "15px 16px",
2103
+ borderRadius: 16,
2104
+ border: `1px solid ${tokens.border}`,
2105
+ background: tokens.bgInput,
2106
+ color: tokens.text,
2107
+ fontSize: "0.95rem",
2108
+ fontFamily: "inherit",
2109
+ outline: "none",
2110
+ boxSizing: "border-box"
2111
+ });
2112
+ var errorStyle = (tokens) => ({
2113
+ background: tokens.errorBg,
2114
+ border: `1px solid ${tokens.error}66`,
2115
+ borderRadius: 16,
2116
+ padding: "11px 14px",
2117
+ color: tokens.error,
2118
+ fontSize: "0.84rem",
2119
+ marginBottom: 14,
2120
+ lineHeight: 1.5,
2121
+ width: "100%",
2122
+ textAlign: "left"
2123
+ });
2124
+ var dividerStyle = (tokens) => ({
2125
+ display: "flex",
2126
+ alignItems: "center",
2127
+ gap: 10,
2128
+ margin: "20px 0 14px",
2129
+ color: tokens.textMuted,
2130
+ fontSize: "0.82rem"
2131
+ });
2132
+ var dividerLineStyle = (color) => ({
2133
+ flex: 1,
2134
+ height: 1,
2135
+ background: color
2136
+ });
2137
+ var logosRowStyle = {
2138
+ display: "flex",
2139
+ justifyContent: "center",
2140
+ gap: 12,
2141
+ marginBottom: 8
2142
+ };
2143
+ var logoCircleStyle = (tokens) => ({
2144
+ width: 34,
2145
+ height: 34,
2146
+ borderRadius: 999,
2147
+ border: `1px solid ${tokens.border}`,
2148
+ background: tokens.bgInput,
2149
+ color: tokens.textMuted,
2150
+ display: "flex",
2151
+ alignItems: "center",
2152
+ justifyContent: "center",
2153
+ fontSize: "0.72rem",
2154
+ fontWeight: 600
2155
+ });
2156
+ var RESEND_COOLDOWN_SECONDS = 30;
2157
+ function OtpVerifyScreen({
2158
+ maskedIdentifier,
2159
+ otpCode,
2160
+ onOtpChange,
2161
+ onVerify,
2162
+ onResend,
2163
+ onBack,
2164
+ verifying,
2165
+ error
2166
+ }) {
2167
+ const { tokens } = useSwypeConfig();
2168
+ const disabled = otpCode.trim().length !== 6 || verifying;
2169
+ const [cooldown, setCooldown] = react.useState(RESEND_COOLDOWN_SECONDS);
2170
+ const intervalRef = react.useRef(null);
2171
+ react.useEffect(() => {
2172
+ setCooldown(RESEND_COOLDOWN_SECONDS);
2173
+ intervalRef.current = setInterval(() => {
2174
+ setCooldown((prev) => {
2175
+ if (prev <= 1) {
2176
+ if (intervalRef.current) clearInterval(intervalRef.current);
2177
+ return 0;
2178
+ }
2179
+ return prev - 1;
2180
+ });
2181
+ }, 1e3);
2182
+ return () => {
2183
+ if (intervalRef.current) clearInterval(intervalRef.current);
2184
+ };
2185
+ }, []);
2186
+ const handleResend = react.useCallback(() => {
2187
+ if (cooldown > 0) return;
2188
+ onResend();
2189
+ setCooldown(RESEND_COOLDOWN_SECONDS);
2190
+ intervalRef.current = setInterval(() => {
2191
+ setCooldown((prev) => {
2192
+ if (prev <= 1) {
2193
+ if (intervalRef.current) clearInterval(intervalRef.current);
2194
+ return 0;
2195
+ }
2196
+ return prev - 1;
2197
+ });
2198
+ }, 1e3);
2199
+ }, [cooldown, onResend]);
2200
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2201
+ ScreenLayout,
2202
+ {
2203
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2204
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onVerify, disabled, loading: verifying, children: "Verify" }),
2205
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: hintStyle(tokens.textMuted), children: "Didn't get the code? Check your spam folder" }),
2206
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2207
+ ] }),
2208
+ children: [
2209
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onBack }),
2210
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle2, children: [
2211
+ /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "accent", size: 56, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
2212
+ "path",
2213
+ {
2214
+ d: "M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z",
2215
+ fill: tokens.accent
2216
+ }
2217
+ ) }) }),
2218
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle2(tokens.text), children: "Check your email" }),
2219
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle2(tokens.textSecondary), children: [
2220
+ "We sent a 6-digit code to",
2221
+ "\n",
2222
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: maskedIdentifier })
2223
+ ] }),
2224
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle(tokens), children: error }),
2225
+ /* @__PURE__ */ jsxRuntime.jsx(OtpInput, { value: otpCode, onChange: onOtpChange, disabled: verifying }),
2226
+ /* @__PURE__ */ jsxRuntime.jsx(
2227
+ "button",
2228
+ {
2229
+ type: "button",
2230
+ onClick: handleResend,
2231
+ disabled: cooldown > 0,
2232
+ style: resendStyle(tokens.textMuted, cooldown > 0),
2233
+ children: cooldown > 0 ? `Resend code in ${cooldown}s` : "Resend code"
2234
+ }
2235
+ )
2236
+ ] })
2237
+ ]
2238
+ }
2239
+ );
2240
+ }
2241
+ var contentStyle2 = {
2242
+ textAlign: "center",
2243
+ flex: 1,
2244
+ display: "flex",
2245
+ flexDirection: "column",
2246
+ alignItems: "center",
2247
+ paddingTop: 24
2248
+ };
2249
+ var headingStyle2 = (color) => ({
2250
+ fontSize: "1.5rem",
2251
+ fontWeight: 700,
2252
+ letterSpacing: "-0.02em",
2253
+ color,
2254
+ margin: "20px 0 8px"
2255
+ });
2256
+ var subtitleStyle2 = (color) => ({
2257
+ fontSize: "0.88rem",
2258
+ color,
2259
+ margin: "0 0 28px",
2260
+ lineHeight: 1.5,
2261
+ whiteSpace: "pre-line"
2262
+ });
2263
+ var errorBannerStyle = (tokens) => ({
2264
+ background: tokens.errorBg,
2265
+ border: `1px solid ${tokens.error}66`,
2266
+ borderRadius: 16,
2267
+ padding: "11px 14px",
2268
+ color: tokens.error,
2269
+ fontSize: "0.84rem",
2270
+ marginBottom: 14,
2271
+ lineHeight: 1.5,
2272
+ width: "100%",
2273
+ textAlign: "left"
2274
+ });
2275
+ var resendStyle = (color, disabled) => ({
2276
+ background: "transparent",
2277
+ border: "none",
2278
+ color,
2279
+ cursor: disabled ? "default" : "pointer",
2280
+ fontFamily: "inherit",
2281
+ fontSize: "0.82rem",
2282
+ marginTop: 16,
2283
+ padding: 0,
2284
+ opacity: disabled ? 0.6 : 1
2285
+ });
2286
+ var hintStyle = (color) => ({
2287
+ textAlign: "center",
2288
+ fontSize: "0.78rem",
2289
+ color,
2290
+ margin: "12px 0 0"
2291
+ });
2292
+ function CreatePasskeyScreen({
2293
+ onCreatePasskey,
2294
+ onSkip,
2295
+ onBack,
2296
+ creating,
2297
+ error
2298
+ }) {
2299
+ const { tokens } = useSwypeConfig();
2300
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2301
+ ScreenLayout,
2302
+ {
2303
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2304
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onCreatePasskey, disabled: creating, loading: creating, children: "Create passkey" }),
2305
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onSkip, style: skipStyle(tokens.textMuted), disabled: creating, children: "Skip for now" }),
2306
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2307
+ ] }),
2308
+ children: [
2309
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onBack }),
2310
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle3, children: [
2311
+ /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "accent", size: 64, children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "36", height: "36", viewBox: "0 0 24 24", fill: "none", children: [
2312
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "3", stroke: tokens.accent, strokeWidth: "1.5", strokeDasharray: "3 2" }),
2313
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "10", r: "1", fill: tokens.accent }),
2314
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "15", cy: "10", r: "1", fill: tokens.accent }),
2315
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 14c0 1.5 1.34 2.5 3 2.5s3-1 3-2.5", stroke: tokens.accent, strokeWidth: "1.2", strokeLinecap: "round" })
2316
+ ] }) }),
2317
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle3(tokens.text), children: "Create your passkey" }),
2318
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle3(tokens.textSecondary), children: "Use Face ID to sign in instantly \u2014 no passwords, no codes." }),
2319
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle2(tokens), children: error }),
2320
+ /* @__PURE__ */ jsxRuntime.jsx(InfoBanner, { children: "Your passkey is stored securely on your device. Swype never sees your biometric data." })
2321
+ ] })
2322
+ ]
2323
+ }
2324
+ );
2325
+ }
2326
+ var contentStyle3 = {
2327
+ textAlign: "center",
2328
+ flex: 1,
2329
+ display: "flex",
2330
+ flexDirection: "column",
2331
+ alignItems: "center",
2332
+ paddingTop: 32
2333
+ };
2334
+ var headingStyle3 = (color) => ({
2335
+ fontSize: "1.45rem",
2336
+ fontWeight: 700,
2337
+ letterSpacing: "-0.02em",
2338
+ color,
2339
+ margin: "24px 0 8px"
2340
+ });
2341
+ var subtitleStyle3 = (color) => ({
2342
+ fontSize: "0.9rem",
2343
+ color,
2344
+ margin: "0 0 28px",
2345
+ lineHeight: 1.5,
2346
+ maxWidth: 280
2347
+ });
2348
+ var errorBannerStyle2 = (tokens) => ({
2349
+ background: tokens.errorBg,
2350
+ border: `1px solid ${tokens.error}66`,
2351
+ borderRadius: 16,
2352
+ padding: "11px 14px",
2353
+ color: tokens.error,
2354
+ fontSize: "0.84rem",
2355
+ marginBottom: 14,
2356
+ lineHeight: 1.5,
2357
+ width: "100%",
2358
+ textAlign: "left"
2359
+ });
2360
+ var skipStyle = (color) => ({
2361
+ background: "transparent",
2362
+ border: "none",
2363
+ color,
2364
+ cursor: "pointer",
2365
+ fontFamily: "inherit",
2366
+ fontSize: "0.88rem",
2367
+ fontWeight: 500,
2368
+ display: "block",
2369
+ width: "100%",
2370
+ textAlign: "center",
2371
+ padding: "12px 0 0"
2372
+ });
2373
+ var WALLET_EMOJIS = {
2374
+ metamask: "\u{1F98A}",
2375
+ rabby: "\u{1F430}",
2376
+ ora: "\u2666\uFE0F",
2377
+ phantom: "\u{1F47B}"
2378
+ };
2379
+ function WalletPickerScreen({
2380
+ providers,
2381
+ onSelectProvider,
2382
+ onBack
2383
+ }) {
2384
+ const { tokens } = useSwypeConfig();
2385
+ const [hoveredId, setHoveredId] = react.useState(null);
2386
+ const displayProviders = providers.length > 0 ? providers : [
2387
+ { id: "metamask", name: "MetaMask" },
2388
+ { id: "rabby", name: "Rabby" },
2389
+ { id: "ora", name: "Ora" },
2390
+ { id: "phantom", name: "Phantom" }
2391
+ ];
2392
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2393
+ ScreenLayout,
2394
+ {
2395
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2396
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: hintStyle2(tokens.textMuted), children: "You'll set your deposit limit in your wallet app." }),
2397
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2398
+ ] }),
2399
+ children: [
2400
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: "Set up Swype", onBack }),
2401
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle4(tokens.text), children: "Where are your stablecoins?" }),
2402
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle4(tokens.textSecondary), children: "Select the wallet you want to deposit from" }),
2403
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: gridStyle, children: [
2404
+ displayProviders.map((p) => {
2405
+ const emoji = WALLET_EMOJIS[p.name.toLowerCase()] ?? p.name.charAt(0);
2406
+ const isHovered = hoveredId === p.id;
2407
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2408
+ "button",
2409
+ {
2410
+ onClick: () => onSelectProvider(p.id),
2411
+ onMouseEnter: () => setHoveredId(p.id),
2412
+ onMouseLeave: () => setHoveredId(null),
2413
+ style: cardStyle(tokens, isHovered),
2414
+ children: [
2415
+ "logoURI" in p && p.logoURI ? /* @__PURE__ */ jsxRuntime.jsx(
2416
+ "img",
2417
+ {
2418
+ src: p.logoURI,
2419
+ alt: p.name,
2420
+ style: logoImgStyle
2421
+ }
2422
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: emojiStyle, children: emoji }),
2423
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: nameStyle2(tokens.text), children: p.name })
2424
+ ]
2425
+ },
2426
+ p.id
2427
+ );
2428
+ }),
2429
+ /* @__PURE__ */ jsxRuntime.jsxs(
2430
+ "button",
2431
+ {
2432
+ onClick: () => onSelectProvider("other"),
2433
+ onMouseEnter: () => setHoveredId("other"),
2434
+ onMouseLeave: () => setHoveredId(null),
2435
+ style: cardStyle(tokens, hoveredId === "other"),
2436
+ children: [
2437
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { margin: "0 auto" }, children: /* @__PURE__ */ jsxRuntime.jsx(
2438
+ "path",
2439
+ {
2440
+ d: "M19 19H5V5h7V3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z",
2441
+ fill: tokens.textMuted
2442
+ }
2443
+ ) }),
2444
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: nameStyle2(tokens.text), children: "Other" })
2445
+ ]
2446
+ }
2447
+ )
2448
+ ] })
2449
+ ]
2450
+ }
2451
+ );
2452
+ }
2453
+ var headingStyle4 = (color) => ({
2454
+ fontSize: "1.35rem",
2455
+ fontWeight: 700,
2456
+ letterSpacing: "-0.02em",
2457
+ color,
2458
+ margin: "8px 0 4px"
2459
+ });
2460
+ var subtitleStyle4 = (color) => ({
2461
+ fontSize: "0.88rem",
2462
+ color,
2463
+ margin: "0 0 24px"
2464
+ });
2465
+ var gridStyle = {
2466
+ display: "grid",
2467
+ gridTemplateColumns: "1fr 1fr",
2468
+ gap: 12
2469
+ };
2470
+ var cardStyle = (tokens, hovered) => ({
2471
+ display: "flex",
2472
+ flexDirection: "column",
2473
+ alignItems: "center",
2474
+ justifyContent: "center",
2475
+ gap: 8,
2476
+ padding: "20px 12px",
2477
+ background: hovered ? tokens.bgHover : tokens.bgInput,
2478
+ border: `1.5px solid ${tokens.border}`,
2479
+ borderRadius: 16,
2480
+ cursor: "pointer",
2481
+ fontFamily: "inherit",
2482
+ transition: "background 0.15s ease",
2483
+ outline: "none"
2484
+ });
2485
+ var emojiStyle = {
2486
+ fontSize: "1.75rem",
2487
+ lineHeight: 1
2488
+ };
2489
+ var logoImgStyle = {
2490
+ width: 32,
2491
+ height: 32,
2492
+ borderRadius: 8,
2493
+ objectFit: "contain"
2494
+ };
2495
+ var nameStyle2 = (color) => ({
2496
+ fontSize: "0.88rem",
2497
+ fontWeight: 600,
2498
+ color
2499
+ });
2500
+ var hintStyle2 = (color) => ({
2501
+ textAlign: "center",
2502
+ fontSize: "0.82rem",
2503
+ color,
2504
+ margin: "0 0 4px"
2505
+ });
2506
+ var DEFAULT_TICKS = [25, 100, 250, 500];
2507
+ var DEFAULT_MIN = 25;
2508
+ var DEFAULT_MAX = 500;
2509
+ function SetupScreen({
2510
+ availableBalance,
2511
+ tokenCount,
2512
+ sourceName,
2513
+ onSetupOneTap,
2514
+ onBack,
2515
+ loading,
2516
+ error
2517
+ }) {
2518
+ const { tokens } = useSwypeConfig();
2519
+ const [limit, setLimit] = react.useState(100);
2520
+ const effectiveMax = Math.min(DEFAULT_MAX, availableBalance > 0 ? availableBalance : DEFAULT_MAX);
2521
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2522
+ ScreenLayout,
2523
+ {
2524
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2525
+ /* @__PURE__ */ jsxRuntime.jsx(
2526
+ PrimaryButton,
2527
+ {
2528
+ onClick: () => onSetupOneTap(limit),
2529
+ disabled: loading,
2530
+ loading,
2531
+ children: "Set up One-Tap"
2532
+ }
2533
+ ),
2534
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2535
+ ] }),
2536
+ children: [
2537
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: "Swype Setup", badge: "Simple", onBack }),
2538
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle5(tokens.text), children: "Set up One-Tap deposits" }),
2539
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle5(tokens.textSecondary), children: "Set your limit for instant deposits. Like a contactless card \u2014 you choose the max." }),
2540
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle3(tokens), children: error }),
2541
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceRowStyle, children: [
2542
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceLeftStyle, children: [
2543
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: coinIconStyle(tokens.accent), children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [
2544
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", fill: "currentColor" }),
2545
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: "12", y: "16", textAnchor: "middle", fontSize: "12", fill: "#fff", fontWeight: "700", children: "$" })
2546
+ ] }) }),
2547
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2548
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: balanceLabelStyle(tokens.textMuted), children: "Available" }),
2549
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceValueStyle(tokens.text), children: [
2550
+ "$",
2551
+ availableBalance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
2552
+ ] })
2553
+ ] })
2554
+ ] }),
2555
+ tokenCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenBadgeStyle(tokens), children: [
2556
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDotStyle(tokens.accent) }),
2557
+ tokenCount,
2558
+ " ",
2559
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: chevronStyle, children: ">" })
2560
+ ] })
2561
+ ] }),
2562
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: limitSectionStyle, children: [
2563
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: limitLabelStyle(tokens.textMuted), children: "Your One-Tap limit" }),
2564
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: limitValueStyle(tokens.text), children: [
2565
+ "$",
2566
+ limit
2567
+ ] }),
2568
+ /* @__PURE__ */ jsxRuntime.jsx(
2569
+ LimitSlider,
2570
+ {
2571
+ value: limit,
2572
+ min: DEFAULT_MIN,
2573
+ max: effectiveMax,
2574
+ step: 5,
2575
+ ticks: DEFAULT_TICKS.filter((t) => t <= effectiveMax),
2576
+ onChange: setLimit
2577
+ }
2578
+ )
2579
+ ] }),
2580
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: bannerWrapStyle, children: /* @__PURE__ */ jsxRuntime.jsx(InfoBanner, { children: "Funds stay in your wallet until you deposit. Swype never holds your money." }) }),
2581
+ /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", style: linkStyle(tokens.accent), children: [
2582
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", style: { marginRight: 6 }, children: [
2583
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2" }),
2584
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 16v-4M12 8h.01", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
2585
+ ] }),
2586
+ "How does this work?"
2587
+ ] })
2588
+ ]
2589
+ }
2590
+ );
2591
+ }
2592
+ var headingStyle5 = (color) => ({
2593
+ fontSize: "1.3rem",
2594
+ fontWeight: 700,
2595
+ letterSpacing: "-0.02em",
2596
+ color,
2597
+ margin: "8px 0 4px"
2598
+ });
2599
+ var subtitleStyle5 = (color) => ({
2600
+ fontSize: "0.86rem",
2601
+ color,
2602
+ margin: "0 0 24px",
2603
+ lineHeight: 1.5
2604
+ });
2605
+ var errorBannerStyle3 = (tokens) => ({
2606
+ background: tokens.errorBg,
2607
+ border: `1px solid ${tokens.error}66`,
2608
+ borderRadius: 16,
2609
+ padding: "11px 14px",
2610
+ color: tokens.error,
2611
+ fontSize: "0.84rem",
2612
+ marginBottom: 14,
2613
+ lineHeight: 1.5
2614
+ });
2615
+ var balanceRowStyle = {
2616
+ display: "flex",
2617
+ alignItems: "center",
2618
+ justifyContent: "space-between",
2619
+ marginBottom: 24
2620
+ };
2621
+ var balanceLeftStyle = {
2622
+ display: "flex",
2623
+ alignItems: "center",
2624
+ gap: 10
2625
+ };
2626
+ var coinIconStyle = (color) => ({
2627
+ color,
2628
+ display: "flex",
2629
+ alignItems: "center"
2630
+ });
2631
+ var balanceLabelStyle = (color) => ({
2632
+ fontSize: "0.72rem",
2633
+ color,
2634
+ fontWeight: 500
2635
+ });
2636
+ var balanceValueStyle = (color) => ({
2637
+ fontSize: "1.1rem",
2638
+ fontWeight: 700,
2639
+ color
2640
+ });
2641
+ var tokenBadgeStyle = (tokens) => ({
2642
+ display: "flex",
2643
+ alignItems: "center",
2644
+ gap: 4,
2645
+ fontSize: "0.78rem",
2646
+ color: tokens.textMuted,
2647
+ border: `1px solid ${tokens.border}`,
2648
+ borderRadius: 999,
2649
+ padding: "4px 10px"
2650
+ });
2651
+ var tokenDotStyle = (color) => ({
2652
+ width: 8,
2653
+ height: 8,
2654
+ borderRadius: "50%",
2655
+ background: color,
2656
+ display: "inline-block"
2657
+ });
2658
+ var chevronStyle = { fontSize: "0.68rem", marginLeft: 2 };
2659
+ var limitSectionStyle = {
2660
+ textAlign: "center",
2661
+ marginBottom: 24
2662
+ };
2663
+ var limitLabelStyle = (color) => ({
2664
+ fontSize: "0.8rem",
2665
+ color,
2666
+ marginBottom: 4
2667
+ });
2668
+ var limitValueStyle = (color) => ({
2669
+ fontSize: "2.2rem",
2670
+ fontWeight: 700,
2671
+ color,
2672
+ marginBottom: 12
2673
+ });
2674
+ var bannerWrapStyle = { marginBottom: 16 };
2675
+ var linkStyle = (color) => ({
2676
+ background: "transparent",
2677
+ border: "none",
2678
+ color,
2679
+ cursor: "pointer",
2680
+ fontFamily: "inherit",
2681
+ fontSize: "0.82rem",
2682
+ fontWeight: 500,
2683
+ display: "flex",
2684
+ alignItems: "center",
2685
+ padding: 0,
2686
+ marginBottom: 16
2687
+ });
2688
+ function SetupStatusScreen({
2689
+ complete,
2690
+ limit,
2691
+ tokensApproved,
2692
+ currentStepLabel,
2693
+ merchantName,
2694
+ onContinue,
2695
+ error
2696
+ }) {
2697
+ const { tokens } = useSwypeConfig();
2698
+ const steps = complete ? [
2699
+ {
2700
+ label: "One-Tap ready",
2701
+ detail: `$${limit} limit \xB7 ${tokensApproved} token${tokensApproved !== 1 ? "s" : ""} approved`,
2702
+ status: "complete"
2703
+ },
2704
+ { label: "Done", status: "complete" }
2705
+ ] : [
2706
+ {
2707
+ label: currentStepLabel ?? "Approving tokens",
2708
+ status: "active"
2709
+ },
2710
+ { label: "Done", status: "pending" }
2711
+ ];
2712
+ return /* @__PURE__ */ jsxRuntime.jsx(
2713
+ ScreenLayout,
2714
+ {
2715
+ footer: complete ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2716
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onContinue, children: merchantName ? `Return to ${merchantName}` : "Continue" }),
2717
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: swipeHintStyle(tokens.textMuted), children: "Swipe to deposit \u2014 no approvals needed." })
2718
+ ] }) : void 0,
2719
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle4, children: [
2720
+ complete ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2721
+ /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "success", size: 64, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "32", height: "32", 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.success }) }) }),
2722
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "You're all set!" })
2723
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2724
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
2725
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "Setting up One-Tap..." })
2726
+ ] }),
2727
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle4(tokens), children: error }),
2728
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: stepsWrapStyle, children: /* @__PURE__ */ jsxRuntime.jsx(StepList, { steps }) }),
2729
+ !complete && /* @__PURE__ */ jsxRuntime.jsx("p", { style: waitHintStyle(tokens.textMuted), children: "Usually takes a few seconds" }),
2730
+ complete && /* @__PURE__ */ jsxRuntime.jsx("p", { style: readyHintStyle(tokens.textSecondary), children: "You can now deposit instantly from any partner app." })
2731
+ ] })
2732
+ }
2733
+ );
2734
+ }
2735
+ var contentStyle4 = {
2736
+ flex: 1,
2737
+ display: "flex",
2738
+ flexDirection: "column",
2739
+ alignItems: "center",
2740
+ justifyContent: "center",
2741
+ textAlign: "center",
2742
+ padding: "0 24px"
2743
+ };
2744
+ var headingStyle6 = (color) => ({
2745
+ fontSize: "1.45rem",
2746
+ fontWeight: 700,
2747
+ letterSpacing: "-0.02em",
2748
+ color,
2749
+ margin: "20px 0 16px"
2750
+ });
2751
+ var errorBannerStyle4 = (tokens) => ({
2752
+ background: tokens.errorBg,
2753
+ border: `1px solid ${tokens.error}66`,
2754
+ borderRadius: 16,
2755
+ padding: "11px 14px",
2756
+ color: tokens.error,
2757
+ fontSize: "0.84rem",
2758
+ marginBottom: 14,
2759
+ lineHeight: 1.5,
2760
+ width: "100%",
2761
+ textAlign: "left"
2762
+ });
2763
+ var stepsWrapStyle = {
2764
+ width: "100%",
2765
+ maxWidth: 280,
2766
+ textAlign: "left",
2767
+ marginBottom: 16
2768
+ };
2769
+ var waitHintStyle = (color) => ({
2770
+ fontSize: "0.82rem",
2771
+ color,
2772
+ margin: 0
2773
+ });
2774
+ var readyHintStyle = (color) => ({
2775
+ fontSize: "0.88rem",
2776
+ color,
2777
+ margin: "8px 0 0",
2778
+ lineHeight: 1.5,
2779
+ maxWidth: 280
2780
+ });
2781
+ var swipeHintStyle = (color) => ({
2782
+ textAlign: "center",
2783
+ fontSize: "0.8rem",
2784
+ color,
2785
+ margin: "12px 0 0"
2786
+ });
2787
+ var MIN_DEPOSIT = 1;
2788
+ function DepositScreen({
2789
+ merchantName,
2790
+ sourceName,
2791
+ sourceAddress,
2792
+ sourceVerified,
2793
+ availableBalance,
2794
+ remainingLimit,
2795
+ tokenCount,
2796
+ initialAmount,
2797
+ estimatedFeePct,
2798
+ estimatedFeeUsd,
2799
+ processing,
2800
+ error,
2801
+ onDeposit,
2802
+ onChangeSource,
2803
+ onSwitchWallet,
2804
+ onBack
2805
+ }) {
2806
+ const { tokens } = useSwypeConfig();
2807
+ const [amount, setAmount] = react.useState(initialAmount);
2808
+ const sliderMax = Math.min(remainingLimit, availableBalance, 500);
2809
+ const isLowBalance = availableBalance < MIN_DEPOSIT;
2810
+ const canDeposit = amount >= MIN_DEPOSIT && amount <= remainingLimit && !isLowBalance && !processing;
2811
+ const headerTitle = merchantName ? `Deposit to ${merchantName}` : "Deposit";
2812
+ const trackRef = react.useRef(null);
2813
+ const [swipeX, setSwipeX] = react.useState(0);
2814
+ const [swiping, setSwiping] = react.useState(false);
2815
+ const startXRef = react.useRef(0);
2816
+ const handleTouchStart = react.useCallback((e) => {
2817
+ if (!canDeposit) return;
2818
+ startXRef.current = e.touches[0].clientX - swipeX;
2819
+ setSwiping(true);
2820
+ }, [canDeposit, swipeX]);
2821
+ const handleTouchMove = react.useCallback((e) => {
2822
+ if (!swiping || !trackRef.current) return;
2823
+ const trackWidth = trackRef.current.offsetWidth - 52;
2824
+ const x = Math.max(0, Math.min(e.touches[0].clientX - startXRef.current, trackWidth));
2825
+ setSwipeX(x);
2826
+ }, [swiping]);
2827
+ const handleTouchEnd = react.useCallback(() => {
2828
+ if (!trackRef.current) return;
2829
+ const trackWidth = trackRef.current.offsetWidth - 52;
2830
+ if (swipeX > trackWidth * 0.75) {
2831
+ onDeposit(amount);
2832
+ }
2833
+ setSwipeX(0);
2834
+ setSwiping(false);
2835
+ }, [swipeX, amount, onDeposit]);
2836
+ if (isLowBalance) {
2837
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2838
+ ScreenLayout,
2839
+ {
2840
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2841
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onSwitchWallet, children: "Switch wallet" }),
2842
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: switchHintStyle(tokens.textMuted), children: "Use a different wallet with more balance" }),
2843
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: outlineBtnWrapStyle, children: /* @__PURE__ */ jsxRuntime.jsx(OutlineButton, { onClick: onBack, children: "Back to deposit options" }) }),
2844
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2845
+ ] }),
2846
+ children: [
2847
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: headerTitle, onBack }),
2848
+ /* @__PURE__ */ jsxRuntime.jsx(
2849
+ SourceCard,
2850
+ {
2851
+ name: sourceName,
2852
+ address: sourceAddress,
2853
+ verified: sourceVerified,
2854
+ onChangeSource
2855
+ }
2856
+ ),
2857
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: amountDisplayStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: amountStyle({ ...tokens, dimmed: true }), children: [
2858
+ "$",
2859
+ amount.toFixed(2)
2860
+ ] }) }),
2861
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceRowStyle2, children: [
2862
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceLeftStyle2, children: [
2863
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: coinIconStyle2(tokens.warning), children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [
2864
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", fill: "currentColor" }),
2865
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: "12", y: "16", textAnchor: "middle", fontSize: "12", fill: "#fff", fontWeight: "700", children: "$" })
2866
+ ] }) }),
2867
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2868
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: balanceLabelStyle2(tokens.textMuted), children: "Available" }),
2869
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { ...balanceAmountStyle, color: tokens.warning }, children: [
2870
+ "$",
2871
+ availableBalance.toFixed(2)
2872
+ ] })
2873
+ ] })
2874
+ ] }),
2875
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z", fill: tokens.warning }) })
2876
+ ] }),
2877
+ /* @__PURE__ */ jsxRuntime.jsxs(WarningBanner, { title: "Not enough funds", children: [
2878
+ "Your wallet balance is $",
2879
+ availableBalance.toFixed(2),
2880
+ " \u2014 you need at least $",
2881
+ MIN_DEPOSIT.toFixed(2),
2882
+ " to deposit via One-Tap."
2883
+ ] })
2884
+ ]
2885
+ }
2886
+ );
2887
+ }
2888
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2889
+ ScreenLayout,
2890
+ {
2891
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2892
+ /* @__PURE__ */ jsxRuntime.jsxs(
2893
+ "div",
2894
+ {
2895
+ ref: trackRef,
2896
+ style: swipeTrackStyle(tokens),
2897
+ onTouchStart: handleTouchStart,
2898
+ onTouchMove: handleTouchMove,
2899
+ onTouchEnd: handleTouchEnd,
2900
+ children: [
2901
+ /* @__PURE__ */ jsxRuntime.jsx(
2902
+ "div",
2903
+ {
2904
+ style: swipeThumbStyle(tokens, swipeX),
2905
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5l8 7-8 7", stroke: "#fff", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
2906
+ }
2907
+ ),
2908
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: swipeLabelStyle, children: processing ? "Processing..." : `Deposit $${amount.toFixed(2)}` })
2909
+ ]
2910
+ }
2911
+ ),
2912
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: desktopFallbackStyle, children: /* @__PURE__ */ jsxRuntime.jsxs(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: [
2913
+ "Deposit $",
2914
+ amount.toFixed(2)
2915
+ ] }) }),
2916
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: noApprovalStyle(tokens.textMuted), children: "No approval needed \xB7 within your One-Tap limit" }),
2917
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: routeStyle(tokens.textMuted), children: [
2918
+ "From ",
2919
+ sourceName,
2920
+ " ",
2921
+ merchantName ? `\u2192 ${merchantName}` : ""
2922
+ ] }),
2923
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2924
+ ] }),
2925
+ children: [
2926
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: headerTitle, badge: "Simple", onBack }),
2927
+ /* @__PURE__ */ jsxRuntime.jsx(
2928
+ SourceCard,
2929
+ {
2930
+ name: sourceName,
2931
+ address: sourceAddress,
2932
+ verified: sourceVerified,
2933
+ onChangeSource
2934
+ }
2935
+ ),
2936
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: amountDisplayStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: amountStyle(tokens), children: [
2937
+ "$",
2938
+ amount.toFixed(2)
2939
+ ] }) }),
2940
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceRowStyle2, children: [
2941
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceLeftStyle2, children: [
2942
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: coinIconStyle2(tokens.accent), children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [
2943
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", fill: "currentColor" }),
2944
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: "12", y: "16", textAnchor: "middle", fontSize: "12", fill: "#fff", fontWeight: "700", children: "$" })
2945
+ ] }) }),
2946
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2947
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceLabelStyle2(tokens.textMuted), children: [
2948
+ "Paying from ",
2949
+ sourceName
2950
+ ] }),
2951
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceAmountStyle, children: [
2952
+ "$",
2953
+ availableBalance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
2954
+ ] })
2955
+ ] })
2956
+ ] }),
2957
+ tokenCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenBadgeStyle2(tokens), children: [
2958
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDotStyle2(tokens.accent) }),
2959
+ tokenCount,
2960
+ " ",
2961
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: chevronStyle2, children: ">" })
2962
+ ] })
2963
+ ] }),
2964
+ /* @__PURE__ */ jsxRuntime.jsx(
2965
+ LimitSlider,
2966
+ {
2967
+ value: amount,
2968
+ min: MIN_DEPOSIT,
2969
+ max: sliderMax > MIN_DEPOSIT ? sliderMax : 20,
2970
+ step: 0.5,
2971
+ ticks: [MIN_DEPOSIT, 5, 10, 20].filter((t) => t <= sliderMax || t <= 20),
2972
+ onChange: setAmount
2973
+ }
2974
+ ),
2975
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: detailsStyle, children: [
2976
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: detailRowStyle(tokens.textMuted), children: [
2977
+ "Remaining limit: ",
2978
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { style: { color: tokens.text }, children: [
2979
+ "$",
2980
+ remainingLimit.toFixed(2)
2981
+ ] })
2982
+ ] }),
2983
+ estimatedFeeUsd != null && estimatedFeePct != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: detailRowStyle(tokens.textMuted), children: [
2984
+ "Fee: ~$",
2985
+ estimatedFeeUsd.toFixed(2),
2986
+ " (",
2987
+ estimatedFeePct.toFixed(1),
2988
+ "%)"
2989
+ ] })
2990
+ ] }),
2991
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle5(tokens), children: error })
2992
+ ]
2993
+ }
2994
+ );
2995
+ }
2996
+ var amountDisplayStyle = {
2997
+ textAlign: "center",
2998
+ padding: "20px 0 8px"
2999
+ };
3000
+ var amountStyle = (opts) => ({
3001
+ fontSize: "2.5rem",
3002
+ fontWeight: 700,
3003
+ color: opts.dimmed ? "#ccc" : opts.text ?? "#12222b",
3004
+ letterSpacing: "-0.02em"
3005
+ });
3006
+ var balanceRowStyle2 = {
3007
+ display: "flex",
3008
+ alignItems: "center",
3009
+ justifyContent: "space-between",
3010
+ marginBottom: 16
3011
+ };
3012
+ var balanceLeftStyle2 = {
3013
+ display: "flex",
3014
+ alignItems: "center",
3015
+ gap: 10
3016
+ };
3017
+ var coinIconStyle2 = (color) => ({
3018
+ color,
3019
+ display: "flex",
3020
+ alignItems: "center"
3021
+ });
3022
+ var balanceLabelStyle2 = (color) => ({
3023
+ fontSize: "0.72rem",
3024
+ color,
3025
+ fontWeight: 500
3026
+ });
3027
+ var balanceAmountStyle = {
3028
+ fontSize: "1rem",
3029
+ fontWeight: 700
3030
+ };
3031
+ var tokenBadgeStyle2 = (tokens) => ({
3032
+ display: "flex",
3033
+ alignItems: "center",
3034
+ gap: 4,
3035
+ fontSize: "0.78rem",
3036
+ color: tokens.textMuted,
3037
+ border: `1px solid ${tokens.border}`,
3038
+ borderRadius: 999,
3039
+ padding: "4px 10px"
3040
+ });
3041
+ var tokenDotStyle2 = (color) => ({
3042
+ width: 8,
3043
+ height: 8,
3044
+ borderRadius: "50%",
3045
+ background: color,
3046
+ display: "inline-block"
3047
+ });
3048
+ var chevronStyle2 = { fontSize: "0.68rem", marginLeft: 2 };
3049
+ var detailsStyle = {
3050
+ textAlign: "center",
3051
+ marginTop: 12,
3052
+ marginBottom: 8
3053
+ };
3054
+ var detailRowStyle = (color) => ({
3055
+ fontSize: "0.8rem",
3056
+ color,
3057
+ marginBottom: 4
3058
+ });
3059
+ var errorBannerStyle5 = (tokens) => ({
3060
+ background: tokens.errorBg,
3061
+ border: `1px solid ${tokens.error}66`,
3062
+ borderRadius: 16,
3063
+ padding: "11px 14px",
3064
+ color: tokens.error,
3065
+ fontSize: "0.84rem",
3066
+ marginTop: 8,
3067
+ lineHeight: 1.5
3068
+ });
3069
+ var swipeTrackStyle = (tokens) => ({
3070
+ position: "relative",
3071
+ height: 56,
3072
+ borderRadius: 999,
3073
+ background: `linear-gradient(180deg, ${tokens.accent}, ${tokens.accent}dd)`,
3074
+ overflow: "hidden",
3075
+ display: "flex",
3076
+ alignItems: "center",
3077
+ touchAction: "none",
3078
+ userSelect: "none"
3079
+ });
3080
+ var swipeThumbStyle = (tokens, x) => ({
3081
+ position: "absolute",
3082
+ left: 4 + x,
3083
+ top: 4,
3084
+ width: 48,
3085
+ height: 48,
3086
+ borderRadius: "50%",
3087
+ background: `${tokens.accent}`,
3088
+ border: "2px solid rgba(255,255,255,0.4)",
3089
+ display: "flex",
3090
+ alignItems: "center",
3091
+ justifyContent: "center",
3092
+ zIndex: 2,
3093
+ transition: x === 0 ? "left 0.25s ease" : "none",
3094
+ cursor: "grab"
3095
+ });
3096
+ var swipeLabelStyle = {
3097
+ flex: 1,
3098
+ textAlign: "center",
3099
+ color: "#fff",
3100
+ fontWeight: 700,
3101
+ fontSize: "0.95rem",
3102
+ zIndex: 1,
3103
+ pointerEvents: "none"
3104
+ };
3105
+ var desktopFallbackStyle = {
3106
+ marginTop: 8
3107
+ };
3108
+ var noApprovalStyle = (color) => ({
3109
+ textAlign: "center",
3110
+ fontSize: "0.78rem",
3111
+ color,
3112
+ margin: "12px 0 2px"
3113
+ });
3114
+ var routeStyle = (color) => ({
3115
+ textAlign: "center",
3116
+ fontSize: "0.75rem",
3117
+ color,
3118
+ margin: "0 0 4px"
3119
+ });
3120
+ var switchHintStyle = (color) => ({
3121
+ textAlign: "center",
3122
+ fontSize: "0.8rem",
3123
+ color,
3124
+ margin: "10px 0"
3125
+ });
3126
+ var outlineBtnWrapStyle = {
3127
+ marginBottom: 8
3128
+ };
3129
+ function SuccessScreen({
3130
+ amount,
3131
+ currency,
3132
+ merchantName,
3133
+ sourceName,
3134
+ remainingLimit,
3135
+ onDone,
3136
+ onIncreaseLimits,
3137
+ onManageAccount
3138
+ }) {
3139
+ const { tokens } = useSwypeConfig();
3140
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3141
+ ScreenLayout,
3142
+ {
3143
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3144
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onDone, children: "Done" }),
3145
+ onManageAccount && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onManageAccount, style: manageStyle(tokens.textMuted), children: "Manage Swype account \u2192" }),
3146
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
3147
+ ] }),
3148
+ children: [
3149
+ /* @__PURE__ */ jsxRuntime.jsx(
3150
+ ScreenHeader,
3151
+ {
3152
+ right: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onDone, style: closeButtonStyle(tokens.textMuted), "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
3153
+ }
3154
+ ),
3155
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle5, children: [
3156
+ /* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "success", size: 64, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "32", height: "32", 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.success }) }) }),
3157
+ /* @__PURE__ */ jsxRuntime.jsxs("h2", { style: headingStyle7(tokens.text), children: [
3158
+ "$",
3159
+ amount.toFixed(2),
3160
+ " deposited"
3161
+ ] }),
3162
+ merchantName && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle6(tokens.textSecondary), children: [
3163
+ "to ",
3164
+ merchantName
3165
+ ] }),
3166
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryCardStyle(tokens), children: [
3167
+ sourceName && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3168
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryLabelStyle(tokens.textMuted), children: "From" }),
3169
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryValueStyle(tokens.text), children: sourceName })
3170
+ ] }),
3171
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3172
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryLabelStyle(tokens.textMuted), children: "Time" }),
3173
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryValueStyle(tokens.text), children: "just now" })
3174
+ ] }),
3175
+ remainingLimit != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3176
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryLabelStyle(tokens.textMuted), children: "Remaining limit" }),
3177
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { ...summaryValueStyle(tokens.text), color: tokens.accent }, children: [
3178
+ "$",
3179
+ remainingLimit.toFixed(2)
3180
+ ] })
3181
+ ] })
3182
+ ] }),
3183
+ onIncreaseLimits && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: upsellCardStyle(tokens), children: [
3184
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: upsellHeaderStyle, children: [
3185
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { marginRight: 6 }, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 14l5-5 5 5", stroke: tokens.accent, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
3186
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Want higher limits?" })
3187
+ ] }),
3188
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: upsellBodyStyle(tokens.textSecondary), children: "Increase your One-Tap limit to deposit more without re-approving." }),
3189
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onIncreaseLimits, style: upsellLinkStyle(tokens.accent), children: "Increase One-Tap limit" })
3190
+ ] })
3191
+ ] })
3192
+ ]
3193
+ }
3194
+ );
3195
+ }
3196
+ var contentStyle5 = {
3197
+ flex: 1,
3198
+ display: "flex",
3199
+ flexDirection: "column",
3200
+ alignItems: "center",
3201
+ paddingTop: 16
3202
+ };
3203
+ var headingStyle7 = (color) => ({
3204
+ fontSize: "1.5rem",
3205
+ fontWeight: 700,
3206
+ letterSpacing: "-0.02em",
3207
+ color,
3208
+ margin: "20px 0 4px"
3209
+ });
3210
+ var subtitleStyle6 = (color) => ({
3211
+ fontSize: "0.9rem",
3212
+ color,
3213
+ margin: "0 0 20px"
3214
+ });
3215
+ var summaryCardStyle = (tokens) => ({
3216
+ width: "100%",
3217
+ padding: "14px 16px",
3218
+ background: tokens.bgInput,
3219
+ border: `1px solid ${tokens.border}`,
3220
+ borderRadius: 20,
3221
+ marginBottom: 16
3222
+ });
3223
+ var summaryRowStyle = {
3224
+ display: "flex",
3225
+ justifyContent: "space-between",
3226
+ alignItems: "center",
3227
+ padding: "6px 0"
3228
+ };
3229
+ var summaryLabelStyle = (color) => ({
3230
+ fontSize: "0.84rem",
3231
+ color
3232
+ });
3233
+ var summaryValueStyle = (color) => ({
3234
+ fontSize: "0.88rem",
3235
+ fontWeight: 600,
3236
+ color
3237
+ });
3238
+ var upsellCardStyle = (tokens) => ({
3239
+ width: "100%",
3240
+ padding: "16px",
3241
+ background: tokens.bgInput,
3242
+ border: `1px solid ${tokens.border}`,
3243
+ borderRadius: 20,
3244
+ marginBottom: 16
3245
+ });
3246
+ var upsellHeaderStyle = {
3247
+ display: "flex",
3248
+ alignItems: "center",
3249
+ fontSize: "0.88rem",
3250
+ marginBottom: 4
3251
+ };
3252
+ var upsellBodyStyle = (color) => ({
3253
+ fontSize: "0.8rem",
3254
+ color,
3255
+ margin: "4px 0 10px",
3256
+ lineHeight: 1.5
3257
+ });
3258
+ var upsellLinkStyle = (color) => ({
3259
+ background: "transparent",
3260
+ border: "none",
3261
+ color,
3262
+ fontWeight: 600,
3263
+ fontSize: "0.84rem",
3264
+ cursor: "pointer",
3265
+ fontFamily: "inherit",
3266
+ padding: 0
3267
+ });
3268
+ var closeButtonStyle = (color) => ({
3269
+ background: "transparent",
3270
+ border: "none",
3271
+ cursor: "pointer",
3272
+ color,
3273
+ padding: 4,
3274
+ display: "flex",
3275
+ alignItems: "center"
3276
+ });
3277
+ var manageStyle = (color) => ({
3278
+ background: "transparent",
3279
+ border: "none",
3280
+ color,
3281
+ cursor: "pointer",
3282
+ fontFamily: "inherit",
3283
+ fontSize: "0.84rem",
3284
+ fontWeight: 500,
3285
+ display: "block",
3286
+ width: "100%",
3287
+ textAlign: "center",
3288
+ padding: "12px 0 0"
3289
+ });
3290
+ var ACTIVE_CREDENTIAL_STORAGE_KEY = "swype_active_credential_id";
3291
+ var MIN_SEND_AMOUNT_USD = 0.25;
3292
+ function computeSmartDefaults(accts, transferAmount) {
3293
+ if (accts.length === 0) return null;
3294
+ for (const acct of accts) {
3295
+ for (const wallet of acct.wallets) {
3296
+ if (wallet.status === "ACTIVE") {
3297
+ const bestSource = wallet.sources.find(
3298
+ (s) => s.balance.available.amount >= transferAmount
3299
+ );
3300
+ if (bestSource) {
3301
+ return { accountId: acct.id, walletId: wallet.id };
3302
+ }
3303
+ }
3304
+ }
3305
+ }
3306
+ let bestAccount = null;
3307
+ let bestWallet = null;
3308
+ let bestBalance = -1;
3309
+ let bestIsActive = false;
3310
+ for (const acct of accts) {
3311
+ for (const wallet of acct.wallets) {
3312
+ const walletBal = wallet.balance.available.amount;
3313
+ const isActive = wallet.status === "ACTIVE";
3314
+ if (walletBal > bestBalance || walletBal === bestBalance && isActive && !bestIsActive) {
3315
+ bestBalance = walletBal;
3316
+ bestAccount = acct;
3317
+ bestWallet = wallet;
3318
+ bestIsActive = isActive;
3319
+ }
3320
+ }
3321
+ }
3322
+ if (bestAccount) {
3323
+ return {
3324
+ accountId: bestAccount.id,
3325
+ walletId: bestWallet?.id ?? null
3326
+ };
3327
+ }
3328
+ return { accountId: accts[0].id, walletId: null };
3329
+ }
3330
+ function parseRawBalance(rawBalance, decimals) {
3331
+ const parsed = Number(rawBalance);
3332
+ if (!Number.isFinite(parsed)) return 0;
3333
+ return parsed / 10 ** decimals;
3334
+ }
3335
+ function buildSelectSourceChoices(options) {
3336
+ const chainChoices = [];
3337
+ const chainIndexByName = /* @__PURE__ */ new Map();
3338
+ for (const option of options) {
3339
+ const { chainName, tokenSymbol } = option;
3340
+ const balance = parseRawBalance(option.rawBalance, option.decimals);
3341
+ let chainChoice;
3342
+ const existingIdx = chainIndexByName.get(chainName);
3343
+ if (existingIdx === void 0) {
3344
+ chainChoice = { chainName, balance: 0, tokens: [] };
3345
+ chainIndexByName.set(chainName, chainChoices.length);
3346
+ chainChoices.push(chainChoice);
3347
+ } else {
3348
+ chainChoice = chainChoices[existingIdx];
3349
+ }
3350
+ chainChoice.balance += balance;
3351
+ const existing = chainChoice.tokens.find((t) => t.tokenSymbol === tokenSymbol);
3352
+ if (existing) {
3353
+ existing.balance += balance;
3354
+ } else {
3355
+ chainChoice.tokens.push({ tokenSymbol, balance });
3356
+ }
3357
+ }
3358
+ return chainChoices;
3359
+ }
3360
+ function SwypePayment({
3361
+ destination,
3362
+ onComplete,
3363
+ onError,
3364
+ useWalletConnector,
3365
+ idempotencyKey,
3366
+ merchantAuthorization,
3367
+ merchantName,
3368
+ onBack
3369
+ }) {
3370
+ const { apiBaseUrl, tokens, depositAmount } = useSwypeConfig();
3371
+ const { ready, authenticated, user, logout, getAccessToken } = reactAuth.usePrivy();
3372
+ const {
3373
+ sendCode: sendEmailCode,
3374
+ loginWithCode: loginWithEmailCode,
3375
+ state: emailLoginState
3376
+ } = reactAuth.useLoginWithEmail();
3377
+ const {
3378
+ sendCode: sendSmsCode,
2250
3379
  loginWithCode: loginWithSmsCode,
2251
3380
  state: smsLoginState
2252
3381
  } = reactAuth.useLoginWithSms();
@@ -2263,10 +3392,6 @@ function SwypePayment({
2263
3392
  const [amount, setAmount] = react.useState(
2264
3393
  depositAmount != null ? depositAmount.toString() : ""
2265
3394
  );
2266
- const [advancedSettings, setAdvancedSettings] = react.useState({
2267
- asset: null,
2268
- chain: null
2269
- });
2270
3395
  const [transfer, setTransfer] = react.useState(null);
2271
3396
  const [creatingTransfer, setCreatingTransfer] = react.useState(false);
2272
3397
  const [registeringPasskey, setRegisteringPasskey] = react.useState(false);
@@ -2275,10 +3400,11 @@ function SwypePayment({
2275
3400
  return window.localStorage.getItem(ACTIVE_CREDENTIAL_STORAGE_KEY);
2276
3401
  });
2277
3402
  const [authInput, setAuthInput] = react.useState("");
2278
- const [verificationTarget, setVerificationTarget] = react.useState(
2279
- null
2280
- );
3403
+ const [verificationTarget, setVerificationTarget] = react.useState(null);
2281
3404
  const [otpCode, setOtpCode] = react.useState("");
3405
+ const [oneTapLimit, setOneTapLimit] = react.useState(100);
3406
+ const [setupComplete, setSetupComplete] = react.useState(false);
3407
+ const [setupStepLabel, setSetupStepLabel] = react.useState(void 0);
2282
3408
  const [mobileFlow, setMobileFlow] = react.useState(false);
2283
3409
  const pollingTransferIdRef = react.useRef(null);
2284
3410
  const mobileSigningTransferIdRef = react.useRef(null);
@@ -2304,9 +3430,7 @@ function SwypePayment({
2304
3430
  const activeOtpStatus = verificationTarget?.kind === "email" ? emailLoginState.status : verificationTarget?.kind === "phone" ? smsLoginState.status : "initial";
2305
3431
  const activeOtpErrorMessage = verificationTarget?.kind === "email" && emailLoginState.status === "error" ? emailLoginState.error?.message ?? "Failed to continue with email." : verificationTarget?.kind === "phone" && smsLoginState.status === "error" ? smsLoginState.error?.message ?? "Failed to continue with phone number." : null;
2306
3432
  react.useEffect(() => {
2307
- if (activeOtpErrorMessage) {
2308
- setError(activeOtpErrorMessage);
2309
- }
3433
+ if (activeOtpErrorMessage) setError(activeOtpErrorMessage);
2310
3434
  }, [activeOtpErrorMessage]);
2311
3435
  const handleSendLoginCode = react.useCallback(async () => {
2312
3436
  const normalizedIdentifier = normalizeAuthIdentifier(authInput);
@@ -2323,9 +3447,9 @@ function SwypePayment({
2323
3447
  await sendSmsCode({ phoneNumber: normalizedIdentifier.value });
2324
3448
  }
2325
3449
  setVerificationTarget(normalizedIdentifier);
3450
+ setStep("otp-verify");
2326
3451
  } catch (err) {
2327
- const msg = err instanceof Error ? err.message : "Failed to send verification code";
2328
- setError(msg);
3452
+ setError(err instanceof Error ? err.message : "Failed to send verification code");
2329
3453
  }
2330
3454
  }, [authInput, sendEmailCode, sendSmsCode]);
2331
3455
  const handleVerifyLoginCode = react.useCallback(async () => {
@@ -2343,8 +3467,7 @@ function SwypePayment({
2343
3467
  await loginWithSmsCode({ code: trimmedCode });
2344
3468
  }
2345
3469
  } catch (err) {
2346
- const msg = err instanceof Error ? err.message : "Failed to verify code";
2347
- setError(msg);
3470
+ setError(err instanceof Error ? err.message : "Failed to verify code");
2348
3471
  }
2349
3472
  }, [verificationTarget, otpCode, loginWithEmailCode, loginWithSmsCode]);
2350
3473
  const handleResendLoginCode = react.useCallback(async () => {
@@ -2357,17 +3480,12 @@ function SwypePayment({
2357
3480
  await sendSmsCode({ phoneNumber: verificationTarget.value });
2358
3481
  }
2359
3482
  } catch (err) {
2360
- const msg = err instanceof Error ? err.message : "Failed to resend code";
2361
- setError(msg);
3483
+ setError(err instanceof Error ? err.message : "Failed to resend code");
2362
3484
  }
2363
3485
  }, [verificationTarget, sendEmailCode, sendSmsCode]);
2364
- const handleEditIdentifier = react.useCallback(() => {
2365
- setError(null);
2366
- setVerificationTarget(null);
2367
- setOtpCode("");
2368
- }, []);
2369
3486
  react.useEffect(() => {
2370
- if (!ready || !authenticated || step !== "login") return;
3487
+ if (!ready || !authenticated) return;
3488
+ if (step !== "login" && step !== "otp-verify") return;
2371
3489
  let cancelled = false;
2372
3490
  setError(null);
2373
3491
  resetHeadlessLogin();
@@ -2379,15 +3497,11 @@ function SwypePayment({
2379
3497
  if (cancelled) return;
2380
3498
  const allPasskeys = config.passkeys ?? (config.passkey ? [config.passkey] : []);
2381
3499
  if (allPasskeys.length === 0) {
2382
- setStep("register-passkey");
3500
+ setStep("create-passkey");
2383
3501
  return;
2384
3502
  }
2385
3503
  if (activeCredentialId && allPasskeys.some((p) => p.credentialId === activeCredentialId)) {
2386
- if (depositAmount != null && depositAmount > 0) {
2387
- setStep("ready");
2388
- } else {
2389
- setStep("enter-amount");
2390
- }
3504
+ setStep("deposit");
2391
3505
  return;
2392
3506
  }
2393
3507
  if (cancelled) return;
@@ -2397,42 +3511,23 @@ function SwypePayment({
2397
3511
  if (matched) {
2398
3512
  setActiveCredentialId(matched);
2399
3513
  window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
2400
- if (depositAmount != null && depositAmount > 0) {
2401
- setStep("ready");
2402
- } else {
2403
- setStep("enter-amount");
2404
- }
3514
+ setStep("deposit");
2405
3515
  return;
2406
3516
  }
2407
- setStep("register-passkey");
3517
+ setStep("create-passkey");
2408
3518
  } catch {
2409
- if (!cancelled) {
2410
- if (depositAmount != null && depositAmount > 0) {
2411
- setStep("ready");
2412
- } else {
2413
- setStep("enter-amount");
2414
- }
2415
- }
3519
+ if (!cancelled) setStep("deposit");
2416
3520
  }
2417
3521
  };
2418
3522
  checkPasskey();
2419
3523
  return () => {
2420
3524
  cancelled = true;
2421
3525
  };
2422
- }, [
2423
- ready,
2424
- authenticated,
2425
- step,
2426
- depositAmount,
2427
- apiBaseUrl,
2428
- getAccessToken,
2429
- activeCredentialId,
2430
- resetHeadlessLogin
2431
- ]);
3526
+ }, [ready, authenticated, step, apiBaseUrl, getAccessToken, activeCredentialId, resetHeadlessLogin]);
2432
3527
  const loadingDataRef = react.useRef(false);
2433
3528
  react.useEffect(() => {
2434
3529
  if (!authenticated) return;
2435
- if (step === "login") return;
3530
+ if (step === "login" || step === "otp-verify") return;
2436
3531
  if (accounts.length > 0 || loadingDataRef.current) return;
2437
3532
  if (!activeCredentialId) return;
2438
3533
  let cancelled = false;
@@ -2460,10 +3555,12 @@ function SwypePayment({
2460
3555
  } else if (prov.length > 0) {
2461
3556
  setSelectedProviderId(prov[0].id);
2462
3557
  }
3558
+ if (accts.length === 0 && step === "deposit") {
3559
+ setStep("wallet-picker");
3560
+ }
2463
3561
  } catch (err) {
2464
3562
  if (!cancelled) {
2465
- const msg = err instanceof Error ? err.message : "Failed to load data";
2466
- setError(msg);
3563
+ setError(err instanceof Error ? err.message : "Failed to load data");
2467
3564
  }
2468
3565
  } finally {
2469
3566
  if (!cancelled) {
@@ -2477,15 +3574,15 @@ function SwypePayment({
2477
3574
  cancelled = true;
2478
3575
  loadingDataRef.current = false;
2479
3576
  };
2480
- }, [authenticated, step, accounts.length, apiBaseUrl, getAccessToken, activeCredentialId]);
3577
+ }, [authenticated, step, accounts.length, apiBaseUrl, getAccessToken, activeCredentialId, depositAmount]);
2481
3578
  react.useEffect(() => {
2482
3579
  if (!polling.transfer) return;
2483
3580
  if (polling.transfer.status === "COMPLETED") {
2484
- setStep("complete");
3581
+ setStep("success");
2485
3582
  setTransfer(polling.transfer);
2486
3583
  onComplete?.(polling.transfer);
2487
3584
  } else if (polling.transfer.status === "FAILED") {
2488
- setStep("complete");
3585
+ setStep("success");
2489
3586
  setTransfer(polling.transfer);
2490
3587
  setError("Transfer failed.");
2491
3588
  }
@@ -2501,13 +3598,11 @@ function SwypePayment({
2501
3598
  const elapsedMs = Date.now() - processingStartedAtRef.current;
2502
3599
  const remainingMs = PROCESSING_TIMEOUT_MS - elapsedMs;
2503
3600
  const handleTimeout = () => {
2504
- if (!hasProcessingTimedOut(processingStartedAtRef.current, Date.now())) {
2505
- return;
2506
- }
3601
+ if (!hasProcessingTimedOut(processingStartedAtRef.current, Date.now())) return;
2507
3602
  const status = getTransferStatus(polling.transfer, transfer);
2508
3603
  const msg = buildProcessingTimeoutMessage(status);
2509
3604
  polling.stopPolling();
2510
- setStep("ready");
3605
+ setStep("deposit");
2511
3606
  setError(msg);
2512
3607
  onError?.(msg);
2513
3608
  };
@@ -2516,15 +3611,12 @@ function SwypePayment({
2516
3611
  return;
2517
3612
  }
2518
3613
  const timeoutId = window.setTimeout(handleTimeout, remainingMs);
2519
- return () => {
2520
- window.clearTimeout(timeoutId);
2521
- };
3614
+ return () => window.clearTimeout(timeoutId);
2522
3615
  }, [step, polling.transfer, transfer, polling.stopPolling, onError]);
2523
3616
  react.useEffect(() => {
2524
3617
  if (!mobileFlow) return;
2525
3618
  const polledTransfer = polling.transfer;
2526
- if (!polledTransfer) return;
2527
- if (polledTransfer.status !== "AUTHORIZED") return;
3619
+ if (!polledTransfer || polledTransfer.status !== "AUTHORIZED") return;
2528
3620
  if (transferSigning.signing) return;
2529
3621
  if (mobileSigningTransferIdRef.current === polledTransfer.id) return;
2530
3622
  mobileSigningTransferIdRef.current = polledTransfer.id;
@@ -2545,18 +3637,14 @@ function SwypePayment({
2545
3637
  if (!mobileFlow) return;
2546
3638
  const transferIdToResume = pollingTransferIdRef.current ?? transfer?.id;
2547
3639
  if (!transferIdToResume) return;
2548
- if (!polling.isPolling) {
2549
- polling.startPolling(transferIdToResume);
2550
- }
3640
+ if (!polling.isPolling) polling.startPolling(transferIdToResume);
2551
3641
  const handleVisibility = () => {
2552
3642
  if (document.visibilityState === "visible") {
2553
3643
  polling.startPolling(transferIdToResume);
2554
3644
  }
2555
3645
  };
2556
3646
  document.addEventListener("visibilitychange", handleVisibility);
2557
- return () => {
2558
- document.removeEventListener("visibilitychange", handleVisibility);
2559
- };
3647
+ return () => document.removeEventListener("visibilitychange", handleVisibility);
2560
3648
  }, [mobileFlow, transfer?.id, polling.isPolling, polling.startPolling]);
2561
3649
  const pendingSelectSourceAction = authExecutor.pendingSelectSource;
2562
3650
  const selectSourceChoices = react.useMemo(() => {
@@ -2575,15 +3663,11 @@ function SwypePayment({
2575
3663
  setSelectSourceTokenSymbol("");
2576
3664
  return;
2577
3665
  }
2578
- if (initializedSelectSourceActionRef.current === pendingSelectSourceAction.id) {
2579
- return;
2580
- }
2581
- const hasRecommendedOption = !!selectSourceRecommended && selectSourceChoices.some(
2582
- (chain) => chain.chainName === selectSourceRecommended.chainName && chain.tokens.some(
2583
- (token) => token.tokenSymbol === selectSourceRecommended.tokenSymbol
2584
- )
3666
+ if (initializedSelectSourceActionRef.current === pendingSelectSourceAction.id) return;
3667
+ const hasRecommended = !!selectSourceRecommended && selectSourceChoices.some(
3668
+ (chain) => chain.chainName === selectSourceRecommended.chainName && chain.tokens.some((t) => t.tokenSymbol === selectSourceRecommended.tokenSymbol)
2585
3669
  );
2586
- if (hasRecommendedOption && selectSourceRecommended) {
3670
+ if (hasRecommended && selectSourceRecommended) {
2587
3671
  setSelectSourceChainName(selectSourceRecommended.chainName);
2588
3672
  setSelectSourceTokenSymbol(selectSourceRecommended.tokenSymbol);
2589
3673
  } else if (selectSourceChoices.length > 0 && selectSourceChoices[0].tokens.length > 0) {
@@ -2595,8 +3679,35 @@ function SwypePayment({
2595
3679
  }
2596
3680
  initializedSelectSourceActionRef.current = pendingSelectSourceAction.id;
2597
3681
  }, [pendingSelectSourceAction, selectSourceChoices, selectSourceRecommended]);
2598
- const handlePay = react.useCallback(async () => {
2599
- const parsedAmount = parseFloat(amount);
3682
+ const selectedAccount = accounts.find((a) => a.id === selectedAccountId);
3683
+ const selectedWallet = selectedAccount?.wallets.find((w) => w.id === selectedWalletId);
3684
+ const sourceName = selectedAccount?.name ?? selectedWallet?.chain.name ?? "Wallet";
3685
+ const sourceAddress = selectedWallet ? `${selectedWallet.name.slice(0, 6)}...${selectedWallet.name.slice(-4)}` : void 0;
3686
+ const sourceVerified = selectedWallet?.status === "ACTIVE";
3687
+ const maxSourceBalance = react.useMemo(() => {
3688
+ let max = 0;
3689
+ for (const acct of accounts) {
3690
+ for (const wallet of acct.wallets) {
3691
+ for (const source of wallet.sources) {
3692
+ if (source.balance.available.amount > max) {
3693
+ max = source.balance.available.amount;
3694
+ }
3695
+ }
3696
+ }
3697
+ }
3698
+ return max;
3699
+ }, [accounts]);
3700
+ const tokenCount = react.useMemo(() => {
3701
+ let count = 0;
3702
+ for (const acct of accounts) {
3703
+ for (const wallet of acct.wallets) {
3704
+ count += wallet.sources.length;
3705
+ }
3706
+ }
3707
+ return count;
3708
+ }, [accounts]);
3709
+ const handlePay = react.useCallback(async (depositAmount2) => {
3710
+ const parsedAmount = depositAmount2;
2600
3711
  if (isNaN(parsedAmount) || parsedAmount < MIN_SEND_AMOUNT_USD) {
2601
3712
  setError(`Minimum amount is $${MIN_SEND_AMOUNT_USD.toFixed(2)}.`);
2602
3713
  return;
@@ -2607,7 +3718,7 @@ function SwypePayment({
2607
3718
  }
2608
3719
  if (!activeCredentialId) {
2609
3720
  setError("Create a passkey on this device before continuing.");
2610
- setStep("register-passkey");
3721
+ setStep("create-passkey");
2611
3722
  return;
2612
3723
  }
2613
3724
  setStep("processing");
@@ -2656,8 +3767,11 @@ function SwypePayment({
2656
3767
  });
2657
3768
  setTransfer(t);
2658
3769
  if (t.authorizationSessions && t.authorizationSessions.length > 0) {
2659
- const shouldUseWalletConnector = useWalletConnector ?? !isMobile();
2660
- if (!shouldUseWalletConnector) {
3770
+ const shouldUseConnector = shouldUseWalletConnector({
3771
+ useWalletConnector,
3772
+ userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
3773
+ });
3774
+ if (!shouldUseConnector) {
2661
3775
  setMobileFlow(true);
2662
3776
  pollingTransferIdRef.current = t.id;
2663
3777
  polling.startPolling(t.id);
@@ -2674,12 +3788,11 @@ function SwypePayment({
2674
3788
  const msg = err instanceof Error ? err.message : "Transfer failed";
2675
3789
  setError(msg);
2676
3790
  onError?.(msg);
2677
- setStep("ready");
3791
+ setStep("deposit");
2678
3792
  } finally {
2679
3793
  setCreatingTransfer(false);
2680
3794
  }
2681
3795
  }, [
2682
- amount,
2683
3796
  sourceId,
2684
3797
  sourceType,
2685
3798
  activeCredentialId,
@@ -2691,1164 +3804,312 @@ function SwypePayment({
2691
3804
  transferSigning,
2692
3805
  polling,
2693
3806
  onError,
2694
- useWalletConnector
3807
+ useWalletConnector,
3808
+ idempotencyKey,
3809
+ merchantAuthorization
2695
3810
  ]);
2696
- const handleNewPayment = () => {
2697
- setStep("ready");
2698
- setTransfer(null);
3811
+ const handleRegisterPasskey = react.useCallback(async () => {
3812
+ setRegisteringPasskey(true);
2699
3813
  setError(null);
2700
- setAmount(depositAmount != null ? depositAmount.toString() : "");
2701
- setMobileFlow(false);
2702
- processingStartedAtRef.current = null;
2703
- pollingTransferIdRef.current = null;
2704
- mobileSigningTransferIdRef.current = null;
2705
- setConnectingNewAccount(false);
2706
- setSelectedWalletId(null);
2707
- setAdvancedSettings({ asset: null, chain: null });
2708
- if (accounts.length > 0) setSelectedAccountId(accounts[0].id);
2709
- };
2710
- const handleLogout = react.useCallback(async () => {
2711
3814
  try {
2712
- await logout();
2713
- } catch {
3815
+ const token = await getAccessToken();
3816
+ if (!token) throw new Error("Not authenticated");
3817
+ const passkeyDisplayName = user?.email?.address ?? user?.google?.name ?? user?.id ?? "Swype User";
3818
+ const { credentialId, publicKey } = await createPasskeyCredential({
3819
+ userId: user?.id ?? "unknown",
3820
+ displayName: passkeyDisplayName
3821
+ });
3822
+ await registerPasskey(apiBaseUrl, token, credentialId, publicKey);
3823
+ setActiveCredentialId(credentialId);
3824
+ window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
3825
+ if (accounts.length === 0) {
3826
+ setStep("wallet-picker");
3827
+ } else {
3828
+ setStep("deposit");
3829
+ }
3830
+ } catch (err) {
3831
+ setError(err instanceof Error ? err.message : "Failed to register passkey");
3832
+ } finally {
3833
+ setRegisteringPasskey(false);
2714
3834
  }
2715
- if (typeof window !== "undefined") {
2716
- window.localStorage.removeItem(ACTIVE_CREDENTIAL_STORAGE_KEY);
3835
+ }, [getAccessToken, user, apiBaseUrl, accounts.length]);
3836
+ const handleSkipPasskey = react.useCallback(() => {
3837
+ if (accounts.length === 0) {
3838
+ setStep("wallet-picker");
3839
+ } else {
3840
+ setStep("deposit");
2717
3841
  }
2718
- polling.stopPolling();
2719
- setActiveCredentialId(null);
2720
- setStep("login");
3842
+ }, [accounts.length]);
3843
+ const handleSetupOneTap = react.useCallback(async (limit) => {
3844
+ setOneTapLimit(limit);
3845
+ setStep("setup-status");
3846
+ setSetupComplete(false);
3847
+ setSetupStepLabel("Approving tokens");
2721
3848
  setError(null);
2722
- setTransfer(null);
2723
- setCreatingTransfer(false);
2724
- setRegisteringPasskey(false);
2725
- setProviders([]);
2726
- setAccounts([]);
2727
- setChains([]);
3849
+ try {
3850
+ const token = await getAccessToken();
3851
+ if (!token) throw new Error("Not authenticated");
3852
+ if (!sourceId) {
3853
+ throw new Error("No wallet selected for setup.");
3854
+ }
3855
+ const t = await createTransfer(apiBaseUrl, token, {
3856
+ credentialId: activeCredentialId ?? "",
3857
+ merchantAuthorization,
3858
+ sourceType,
3859
+ sourceId,
3860
+ destination,
3861
+ amount: 0
3862
+ });
3863
+ if (t.authorizationSessions && t.authorizationSessions.length > 0) {
3864
+ const shouldUseConnector = shouldUseWalletConnector({
3865
+ useWalletConnector,
3866
+ userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
3867
+ });
3868
+ if (!shouldUseConnector) {
3869
+ setMobileFlow(true);
3870
+ window.location.href = t.authorizationSessions[0].uri;
3871
+ } else {
3872
+ await authExecutor.executeSession(t);
3873
+ }
3874
+ }
3875
+ setSetupStepLabel(void 0);
3876
+ setSetupComplete(true);
3877
+ } catch (err) {
3878
+ const msg = err instanceof Error ? err.message : "Setup failed";
3879
+ setError(msg);
3880
+ onError?.(msg);
3881
+ }
3882
+ }, [
3883
+ getAccessToken,
3884
+ sourceId,
3885
+ sourceType,
3886
+ activeCredentialId,
3887
+ destination,
3888
+ apiBaseUrl,
3889
+ merchantAuthorization,
3890
+ useWalletConnector,
3891
+ authExecutor,
3892
+ onError
3893
+ ]);
3894
+ const handleSelectProvider = react.useCallback((providerId) => {
3895
+ setSelectedProviderId(providerId);
2728
3896
  setSelectedAccountId(null);
2729
- setSelectedWalletId(null);
2730
- setSelectedProviderId(null);
2731
- setConnectingNewAccount(false);
3897
+ setConnectingNewAccount(true);
3898
+ setStep("setup");
3899
+ }, []);
3900
+ const handleNewPayment = react.useCallback(() => {
3901
+ setStep("deposit");
3902
+ setTransfer(null);
3903
+ setError(null);
2732
3904
  setAmount(depositAmount != null ? depositAmount.toString() : "");
2733
- setAdvancedSettings({ asset: null, chain: null });
2734
3905
  setMobileFlow(false);
2735
- setSelectSourceChainName("");
2736
- setSelectSourceTokenSymbol("");
2737
- initializedSelectSourceActionRef.current = null;
2738
3906
  processingStartedAtRef.current = null;
2739
3907
  pollingTransferIdRef.current = null;
2740
3908
  mobileSigningTransferIdRef.current = null;
2741
- resetHeadlessLogin();
2742
- }, [logout, polling, depositAmount, resetHeadlessLogin]);
2743
- const handleConnectNewAccount = (providerId) => {
2744
- setSelectedProviderId(providerId);
2745
- setSelectedAccountId(null);
2746
- setConnectingNewAccount(true);
2747
- };
2748
- const cardStyle = {
2749
- background: tokens.bgCard,
2750
- borderRadius: tokens.radiusLg,
2751
- border: `1px solid ${tokens.border}`,
2752
- padding: "30px 24px 24px",
2753
- maxWidth: 420,
2754
- width: "100%",
2755
- boxShadow: tokens.shadowLg,
2756
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
2757
- color: tokens.text
2758
- };
2759
- const headingStyle = {
2760
- fontSize: "2rem",
2761
- fontWeight: 700,
2762
- margin: "0 0 18px 0",
2763
- letterSpacing: "-0.02em",
2764
- color: tokens.text,
2765
- textAlign: "center"
2766
- };
2767
- const btnPrimary = {
2768
- width: "100%",
2769
- padding: "15px 18px",
2770
- background: `linear-gradient(180deg, ${tokens.accent}, ${tokens.accentHover})`,
2771
- color: tokens.accentText,
2772
- border: "none",
2773
- borderRadius: "999px",
2774
- fontSize: "1.03rem",
2775
- fontWeight: 700,
2776
- cursor: "pointer",
2777
- transition: "filter 0.15s ease, transform 0.15s ease",
2778
- fontFamily: "inherit",
2779
- boxShadow: "0 8px 18px rgba(40, 182, 122, 0.28)"
2780
- };
2781
- const btnDisabled = {
2782
- ...btnPrimary,
2783
- opacity: 0.5,
2784
- cursor: "not-allowed"
2785
- };
2786
- ({
2787
- ...btnPrimary,
2788
- background: tokens.bgCard,
2789
- color: tokens.textSecondary,
2790
- border: `1px solid ${tokens.border}`});
2791
- const textFieldStyle = {
2792
- width: "100%",
2793
- padding: "15px 16px",
2794
- borderRadius: "16px",
2795
- border: `1px solid ${tokens.border}`,
2796
- background: tokens.bgInput,
2797
- color: tokens.text,
2798
- fontSize: "0.98rem",
2799
- fontFamily: "inherit",
2800
- outline: "none",
2801
- boxSizing: "border-box"
2802
- };
2803
- const authCaptionStyle = {
2804
- fontSize: "0.84rem",
2805
- color: tokens.textSecondary,
2806
- margin: 0,
2807
- lineHeight: 1.5
2808
- };
2809
- const authTertiaryButtonStyle = {
2810
- background: "transparent",
2811
- border: "none",
2812
- color: tokens.textMuted,
2813
- cursor: "pointer",
2814
- fontFamily: "inherit",
2815
- fontSize: "0.84rem",
2816
- padding: 0
2817
- };
2818
- const errorStyle = {
2819
- background: tokens.errorBg,
2820
- border: `1px solid ${tokens.error}66`,
2821
- borderRadius: tokens.radiusLg,
2822
- padding: "11px 14px",
2823
- color: tokens.error,
2824
- fontSize: "0.86rem",
2825
- marginBottom: "14px",
2826
- lineHeight: 1.5
2827
- };
2828
- const stepBadge = (label) => /* @__PURE__ */ jsxRuntime.jsxs(
2829
- "div",
2830
- {
2831
- style: {
2832
- display: "flex",
2833
- alignItems: "center",
2834
- justifyContent: "center",
2835
- gap: "10px",
2836
- marginBottom: "20px"
2837
- },
2838
- children: [
2839
- /* @__PURE__ */ jsxRuntime.jsx(
2840
- "div",
2841
- {
2842
- style: {
2843
- width: 28,
2844
- height: 7,
2845
- borderRadius: 999,
2846
- background: tokens.accent,
2847
- opacity: 0.95
2848
- }
2849
- }
2850
- ),
2851
- /* @__PURE__ */ jsxRuntime.jsx(
2852
- "div",
2853
- {
2854
- style: {
2855
- width: 8,
2856
- height: 8,
2857
- borderRadius: 999,
2858
- background: tokens.border
2859
- }
2860
- }
2861
- ),
2862
- /* @__PURE__ */ jsxRuntime.jsx(
2863
- "span",
2864
- {
2865
- style: {
2866
- fontSize: "0.75rem",
2867
- textTransform: "uppercase",
2868
- letterSpacing: "0.06em",
2869
- color: tokens.textMuted,
2870
- fontWeight: 600
2871
- },
2872
- children: label
2873
- }
2874
- )
2875
- ]
2876
- }
2877
- );
2878
- const placeholderProviders = ["A", "B", "C", "D", "E"];
2879
- const displayedSelectSourceChoices = selectSourceChoices.length > 0 ? selectSourceChoices : [
2880
- {
2881
- chainName: "Base",
2882
- balance: 0,
2883
- tokens: [{ tokenSymbol: "USDC", balance: 0 }]
2884
- }
2885
- ];
2886
- const selectedChainChoice = displayedSelectSourceChoices.find(
2887
- (choice) => choice.chainName === selectSourceChainName
2888
- ) ?? displayedSelectSourceChoices[0];
2889
- const selectSourceTokenChoices = selectedChainChoice?.tokens ?? [];
2890
- const resolvedSelectSourceChainName = selectedChainChoice?.chainName ?? selectSourceChainName;
2891
- const resolvedSelectSourceTokenSymbol = selectSourceTokenChoices.find(
2892
- (token) => token.tokenSymbol === selectSourceTokenSymbol
2893
- )?.tokenSymbol ?? selectSourceTokenChoices[0]?.tokenSymbol ?? "";
2894
- const canConfirmSelectSource = !!resolvedSelectSourceChainName && !!resolvedSelectSourceTokenSymbol;
2895
- const handleSelectSourceChainChange = (chainName) => {
2896
- setSelectSourceChainName(chainName);
2897
- const nextChain = displayedSelectSourceChoices.find(
2898
- (choice) => choice.chainName === chainName
2899
- );
2900
- if (!nextChain || nextChain.tokens.length === 0) {
2901
- setSelectSourceTokenSymbol("");
2902
- return;
2903
- }
2904
- const recommendedTokenForChain = selectSourceRecommended?.chainName === chainName ? selectSourceRecommended.tokenSymbol : null;
2905
- const hasRecommendedToken = !!recommendedTokenForChain && nextChain.tokens.some((token) => token.tokenSymbol === recommendedTokenForChain);
2906
- setSelectSourceTokenSymbol(
2907
- hasRecommendedToken && recommendedTokenForChain ? recommendedTokenForChain : nextChain.tokens[0].tokenSymbol
2908
- );
2909
- };
2910
- if (!ready) {
2911
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "24px 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { label: "Initializing..." }) }) });
2912
- }
2913
- if (step === "login" && !authenticated) {
2914
- const isAwaitingOtp = verificationTarget !== null;
2915
- const isSendingCode = activeOtpStatus === "sending-code";
2916
- const isSubmittingCode = activeOtpStatus === "submitting-code";
2917
- const continueDisabled = authInput.trim().length === 0 || isSendingCode || isSubmittingCode;
2918
- const verifyDisabled = otpCode.trim().length !== 6 || isSubmittingCode;
2919
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center" }, children: [
2920
- /* @__PURE__ */ jsxRuntime.jsx(
2921
- "div",
2922
- {
2923
- style: {
2924
- width: 56,
2925
- height: 56,
2926
- borderRadius: 14,
2927
- background: tokens.accent,
2928
- color: tokens.accentText,
2929
- display: "flex",
2930
- alignItems: "center",
2931
- justifyContent: "center",
2932
- fontWeight: 700,
2933
- fontSize: "1.35rem",
2934
- margin: "0 auto 24px",
2935
- boxShadow: "0 10px 20px rgba(40, 182, 122, 0.22)"
2936
- },
2937
- children: "S"
2938
- }
2939
- ),
2940
- /* @__PURE__ */ jsxRuntime.jsx(
2941
- "h2",
2942
- {
2943
- style: {
2944
- ...headingStyle,
2945
- fontSize: "2.05rem",
2946
- lineHeight: 1.15,
2947
- marginBottom: "10px",
2948
- whiteSpace: "pre-line"
2949
- },
2950
- children: isAwaitingOtp ? "Enter your code." : "One-time setup.\nOne-tap deposits after."
2951
- }
2952
- ),
2953
- /* @__PURE__ */ jsxRuntime.jsx(
2954
- "p",
2955
- {
2956
- style: {
2957
- ...authCaptionStyle,
2958
- margin: "0 0 26px 0",
2959
- whiteSpace: "pre-line"
2960
- },
2961
- children: isAwaitingOtp ? `We sent a 6-digit code to ${maskAuthIdentifier(verificationTarget)}.` : "Protected by Face ID."
2962
- }
2963
- ),
2964
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorStyle, children: error }),
2965
- isAwaitingOtp ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2966
- /* @__PURE__ */ jsxRuntime.jsx(
2967
- "input",
2968
- {
2969
- id: "swype-login-code",
2970
- type: "text",
2971
- inputMode: "numeric",
2972
- autoComplete: "one-time-code",
2973
- placeholder: "Verification code",
2974
- value: otpCode,
2975
- onChange: (event) => {
2976
- setOtpCode(event.target.value.replace(/\D/g, "").slice(0, 6));
2977
- },
2978
- style: {
2979
- ...textFieldStyle,
2980
- textAlign: "center",
2981
- letterSpacing: "0.24em",
2982
- marginBottom: "14px"
2983
- }
2984
- }
2985
- ),
2986
- /* @__PURE__ */ jsxRuntime.jsx(
2987
- "button",
2988
- {
2989
- style: verifyDisabled ? btnDisabled : btnPrimary,
2990
- disabled: verifyDisabled,
2991
- onClick: handleVerifyLoginCode,
2992
- children: isSubmittingCode ? "Verifying..." : "Continue"
2993
- }
2994
- ),
2995
- /* @__PURE__ */ jsxRuntime.jsxs(
2996
- "div",
2997
- {
2998
- style: {
2999
- display: "flex",
3000
- justifyContent: "space-between",
3001
- gap: "12px",
3002
- marginTop: "14px"
3003
- },
3004
- children: [
3005
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: authTertiaryButtonStyle, onClick: handleEditIdentifier, children: "Use a different email or phone" }),
3006
- /* @__PURE__ */ jsxRuntime.jsx(
3007
- "button",
3008
- {
3009
- type: "button",
3010
- style: authTertiaryButtonStyle,
3011
- onClick: handleResendLoginCode,
3012
- disabled: isSendingCode || isSubmittingCode,
3013
- children: isSendingCode ? "Sending..." : "Resend code"
3014
- }
3015
- )
3016
- ]
3017
- }
3018
- )
3019
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3020
- /* @__PURE__ */ jsxRuntime.jsx(
3021
- "input",
3022
- {
3023
- id: "swype-login-identifier",
3024
- type: "text",
3025
- inputMode: "text",
3026
- autoComplete: "username",
3027
- placeholder: "Email or phone number",
3028
- value: authInput,
3029
- onChange: (event) => setAuthInput(event.target.value),
3030
- style: { ...textFieldStyle, marginBottom: "14px" }
3031
- }
3032
- ),
3033
- /* @__PURE__ */ jsxRuntime.jsx(
3034
- "button",
3035
- {
3036
- style: continueDisabled ? btnDisabled : btnPrimary,
3037
- disabled: continueDisabled,
3038
- onClick: handleSendLoginCode,
3039
- children: isSendingCode ? "Sending code..." : "Continue"
3040
- }
3041
- ),
3042
- /* @__PURE__ */ jsxRuntime.jsxs(
3043
- "div",
3044
- {
3045
- style: {
3046
- display: "flex",
3047
- alignItems: "center",
3048
- gap: "10px",
3049
- margin: "22px 0 14px",
3050
- color: tokens.textMuted,
3051
- fontSize: "0.82rem"
3052
- },
3053
- children: [
3054
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, height: 1, background: tokens.border } }),
3055
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "works with" }),
3056
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, height: 1, background: tokens.border } })
3057
- ]
3058
- }
3059
- ),
3060
- /* @__PURE__ */ jsxRuntime.jsx(
3061
- "div",
3062
- {
3063
- "aria-label": "Works with placeholder providers",
3064
- style: {
3065
- display: "flex",
3066
- justifyContent: "center",
3067
- gap: "12px",
3068
- marginBottom: "18px"
3069
- },
3070
- children: placeholderProviders.map((providerLabel) => /* @__PURE__ */ jsxRuntime.jsx(
3071
- "div",
3072
- {
3073
- style: {
3074
- width: 34,
3075
- height: 34,
3076
- borderRadius: 999,
3077
- border: `1px solid ${tokens.border}`,
3078
- background: tokens.bgInput,
3079
- color: tokens.textMuted,
3080
- display: "flex",
3081
- alignItems: "center",
3082
- justifyContent: "center",
3083
- fontSize: "0.78rem",
3084
- fontWeight: 600
3085
- },
3086
- children: providerLabel
3087
- },
3088
- providerLabel
3089
- ))
3090
- }
3091
- ),
3092
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...authCaptionStyle, color: tokens.textMuted }, children: "Powered by Swype. Non-custodial." })
3093
- ] })
3094
- ] }) });
3909
+ setConnectingNewAccount(false);
3910
+ setSelectedWalletId(null);
3911
+ setSetupComplete(false);
3912
+ if (accounts.length > 0) setSelectedAccountId(accounts[0].id);
3913
+ }, [depositAmount, accounts]);
3914
+ const handleLogout = react.useCallback(async () => {
3915
+ try {
3916
+ await logout();
3917
+ } catch {
3918
+ }
3919
+ if (typeof window !== "undefined") {
3920
+ window.localStorage.removeItem(ACTIVE_CREDENTIAL_STORAGE_KEY);
3921
+ }
3922
+ polling.stopPolling();
3923
+ setActiveCredentialId(null);
3924
+ setStep("login");
3925
+ setError(null);
3926
+ setTransfer(null);
3927
+ setCreatingTransfer(false);
3928
+ setRegisteringPasskey(false);
3929
+ setProviders([]);
3930
+ setAccounts([]);
3931
+ setChains([]);
3932
+ setSelectedAccountId(null);
3933
+ setSelectedWalletId(null);
3934
+ setSelectedProviderId(null);
3935
+ setConnectingNewAccount(false);
3936
+ setAmount(depositAmount != null ? depositAmount.toString() : "");
3937
+ setMobileFlow(false);
3938
+ setSetupComplete(false);
3939
+ resetHeadlessLogin();
3940
+ }, [logout, polling, depositAmount, resetHeadlessLogin]);
3941
+ if (!ready) {
3942
+ return /* @__PURE__ */ jsxRuntime.jsx(ScreenLayout, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "48px 0", flex: 1, display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { label: "Initializing..." }) }) });
3095
3943
  }
3096
- if (step === "register-passkey") {
3097
- const handleRegisterPasskey = async () => {
3098
- setRegisteringPasskey(true);
3099
- setError(null);
3100
- try {
3101
- const token = await getAccessToken();
3102
- if (!token) throw new Error("Not authenticated");
3103
- const passkeyDisplayName = user?.email?.address ?? user?.google?.name ?? user?.id ?? "Swype User";
3104
- const { credentialId, publicKey } = await createPasskeyCredential({
3105
- userId: user?.id ?? "unknown",
3106
- displayName: passkeyDisplayName
3107
- });
3108
- await registerPasskey(apiBaseUrl, token, credentialId, publicKey);
3109
- setActiveCredentialId(credentialId);
3110
- window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
3111
- if (depositAmount != null && depositAmount > 0) {
3112
- setStep("ready");
3113
- } else {
3114
- setStep("enter-amount");
3115
- }
3116
- } catch (err) {
3117
- const msg = err instanceof Error ? err.message : "Failed to register passkey";
3118
- setError(msg);
3119
- } finally {
3120
- setRegisteringPasskey(false);
3944
+ if (step === "login" && !authenticated) {
3945
+ return /* @__PURE__ */ jsxRuntime.jsx(
3946
+ LoginScreen,
3947
+ {
3948
+ authInput,
3949
+ onAuthInputChange: setAuthInput,
3950
+ onSubmit: handleSendLoginCode,
3951
+ sending: activeOtpStatus === "sending-code",
3952
+ error,
3953
+ onBack
3121
3954
  }
3122
- };
3123
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center" }, children: [
3124
- /* @__PURE__ */ jsxRuntime.jsxs(
3125
- "svg",
3126
- {
3127
- width: "48",
3128
- height: "48",
3129
- viewBox: "0 0 48 48",
3130
- fill: "none",
3131
- style: { margin: "0 auto 16px" },
3132
- children: [
3133
- /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "48", height: "48", rx: "12", fill: tokens.accent + "20" }),
3134
- /* @__PURE__ */ jsxRuntime.jsx(
3135
- "path",
3136
- {
3137
- d: "M24 16c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 10c-4.42 0-8 1.79-8 4v2h16v-2c0-2.21-3.58-4-8-4z",
3138
- fill: tokens.accent
3139
- }
3140
- )
3141
- ]
3142
- }
3143
- ),
3144
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { ...headingStyle, marginBottom: "8px" }, children: "Set Up Passkey" }),
3145
- /* @__PURE__ */ jsxRuntime.jsx(
3146
- "p",
3147
- {
3148
- style: {
3149
- fontSize: "0.875rem",
3150
- color: tokens.textSecondary,
3151
- margin: "0 0 24px 0",
3152
- lineHeight: 1.5
3153
- },
3154
- children: "Create a passkey for secure, one-touch payments. This only needs to be done once."
3155
- }
3156
- ),
3157
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorStyle, children: error }),
3158
- /* @__PURE__ */ jsxRuntime.jsx(
3159
- "button",
3160
- {
3161
- style: registeringPasskey ? btnDisabled : btnPrimary,
3162
- disabled: registeringPasskey,
3163
- onClick: handleRegisterPasskey,
3164
- children: registeringPasskey ? "Creating passkey..." : "Create Passkey"
3165
- }
3166
- )
3167
- ] }) });
3955
+ );
3168
3956
  }
3169
- if (step === "enter-amount") {
3170
- const parsedAmount = parseFloat(amount);
3171
- const canContinue = !isNaN(parsedAmount) && parsedAmount >= MIN_SEND_AMOUNT_USD;
3172
- let maxSourceBalance = null;
3173
- for (const acct of accounts) {
3174
- for (const wallet of acct.wallets) {
3175
- for (const source of wallet.sources) {
3176
- const bal = source.balance.available.amount;
3177
- if (maxSourceBalance === null || bal > maxSourceBalance) {
3178
- maxSourceBalance = bal;
3179
- }
3180
- }
3957
+ if (step === "otp-verify" && !authenticated) {
3958
+ return /* @__PURE__ */ jsxRuntime.jsx(
3959
+ OtpVerifyScreen,
3960
+ {
3961
+ maskedIdentifier: verificationTarget ? maskAuthIdentifier(verificationTarget) : "",
3962
+ otpCode,
3963
+ onOtpChange: (code) => {
3964
+ setOtpCode(code);
3965
+ setError(null);
3966
+ },
3967
+ onVerify: handleVerifyLoginCode,
3968
+ onResend: handleResendLoginCode,
3969
+ onBack: () => {
3970
+ setVerificationTarget(null);
3971
+ setOtpCode("");
3972
+ setError(null);
3973
+ setStep("login");
3974
+ },
3975
+ verifying: activeOtpStatus === "submitting-code",
3976
+ error
3977
+ }
3978
+ );
3979
+ }
3980
+ if (step === "create-passkey") {
3981
+ return /* @__PURE__ */ jsxRuntime.jsx(
3982
+ CreatePasskeyScreen,
3983
+ {
3984
+ onCreatePasskey: handleRegisterPasskey,
3985
+ onSkip: handleSkipPasskey,
3986
+ onBack: () => setStep("login"),
3987
+ creating: registeringPasskey,
3988
+ error
3989
+ }
3990
+ );
3991
+ }
3992
+ if (step === "wallet-picker") {
3993
+ return /* @__PURE__ */ jsxRuntime.jsx(
3994
+ WalletPickerScreen,
3995
+ {
3996
+ providers,
3997
+ onSelectProvider: handleSelectProvider,
3998
+ onBack: () => setStep("create-passkey")
3999
+ }
4000
+ );
4001
+ }
4002
+ if (step === "setup") {
4003
+ return /* @__PURE__ */ jsxRuntime.jsx(
4004
+ SetupScreen,
4005
+ {
4006
+ availableBalance: maxSourceBalance,
4007
+ tokenCount,
4008
+ sourceName,
4009
+ onSetupOneTap: handleSetupOneTap,
4010
+ onBack: () => setStep("wallet-picker"),
4011
+ loading: loadingData,
4012
+ error
4013
+ }
4014
+ );
4015
+ }
4016
+ if (step === "setup-status") {
4017
+ return /* @__PURE__ */ jsxRuntime.jsx(
4018
+ SetupStatusScreen,
4019
+ {
4020
+ complete: setupComplete,
4021
+ limit: oneTapLimit,
4022
+ tokensApproved: tokenCount,
4023
+ currentStepLabel: setupStepLabel,
4024
+ merchantName,
4025
+ onContinue: () => setStep("deposit"),
4026
+ error
3181
4027
  }
4028
+ );
4029
+ }
4030
+ if (step === "deposit") {
4031
+ if (loadingData) {
4032
+ return /* @__PURE__ */ jsxRuntime.jsx(ScreenLayout, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "48px 0", flex: 1, display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { label: "Loading..." }) }) });
3182
4033
  }
3183
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardStyle, children: [
3184
- stepBadge("Enter amount"),
3185
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle, children: "How much?" }),
3186
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorStyle, children: error }),
3187
- /* @__PURE__ */ jsxRuntime.jsxs(
3188
- "div",
3189
- {
3190
- style: {
3191
- display: "flex",
3192
- alignItems: "center",
3193
- gap: "8px",
3194
- background: tokens.bgInput,
3195
- border: `1px solid ${tokens.border}`,
3196
- borderRadius: tokens.radiusLg,
3197
- padding: "6px 14px 6px 8px",
3198
- marginBottom: "8px"
3199
- },
3200
- children: [
3201
- /* @__PURE__ */ jsxRuntime.jsx(
3202
- "span",
3203
- {
3204
- style: {
3205
- fontSize: "1.5rem",
3206
- fontWeight: 600,
3207
- color: tokens.textMuted,
3208
- paddingLeft: "10px",
3209
- userSelect: "none"
3210
- },
3211
- children: "$"
3212
- }
3213
- ),
3214
- /* @__PURE__ */ jsxRuntime.jsx(
3215
- "input",
3216
- {
3217
- type: "number",
3218
- min: MIN_SEND_AMOUNT_USD.toFixed(2),
3219
- step: "0.01",
3220
- value: amount,
3221
- onChange: (e) => setAmount(e.target.value),
3222
- placeholder: "0.00",
3223
- style: {
3224
- flex: 1,
3225
- background: "transparent",
3226
- border: "none",
3227
- outline: "none",
3228
- color: tokens.text,
3229
- fontSize: "1.5rem",
3230
- fontWeight: 600,
3231
- fontFamily: "inherit",
3232
- padding: "10px 0"
3233
- },
3234
- autoFocus: true
3235
- }
3236
- ),
3237
- /* @__PURE__ */ jsxRuntime.jsx(
3238
- "span",
3239
- {
3240
- style: {
3241
- fontSize: "0.825rem",
3242
- fontWeight: 600,
3243
- color: tokens.textMuted,
3244
- background: tokens.bgCard,
3245
- padding: "6px 12px",
3246
- border: `1px solid ${tokens.border}`,
3247
- borderRadius: "999px"
3248
- },
3249
- children: "USD"
3250
- }
3251
- )
3252
- ]
3253
- }
3254
- ),
3255
- /* @__PURE__ */ jsxRuntime.jsx(
3256
- "div",
3257
- {
3258
- style: {
3259
- fontSize: "0.8rem",
3260
- color: tokens.textMuted,
3261
- marginBottom: "20px",
3262
- paddingLeft: "2px"
3263
- },
3264
- children: loadingData ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Loading balance..." }) : maxSourceBalance !== null && maxSourceBalance > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
3265
- "Available: ",
3266
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontWeight: 600, color: tokens.textSecondary }, children: [
3267
- "$",
3268
- maxSourceBalance.toFixed(2)
3269
- ] })
3270
- ] }) : null
3271
- }
3272
- ),
3273
- /* @__PURE__ */ jsxRuntime.jsx(
3274
- "button",
3275
- {
3276
- style: canContinue ? btnPrimary : btnDisabled,
3277
- disabled: !canContinue,
3278
- onClick: () => {
3279
- setError(null);
3280
- setStep("ready");
3281
- },
3282
- children: "Continue"
3283
- }
3284
- )
3285
- ] });
3286
- }
3287
- if (step === "ready") {
3288
- const parsedAmount = parseFloat(amount);
3289
- const canPay = !isNaN(parsedAmount) && parsedAmount >= MIN_SEND_AMOUNT_USD && !!sourceId && !loadingData;
3290
- const noAccounts = !loadingData && accounts.length === 0;
3291
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardStyle, children: [
3292
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
3293
- stepBadge("Review & pay"),
3294
- /* @__PURE__ */ jsxRuntime.jsx(
3295
- "button",
3296
- {
3297
- type: "button",
3298
- onClick: handleLogout,
3299
- style: {
3300
- position: "absolute",
3301
- top: 0,
3302
- right: 0,
3303
- background: "transparent",
3304
- border: "none",
3305
- color: tokens.textMuted,
3306
- cursor: "pointer",
3307
- fontSize: "0.75rem",
3308
- fontWeight: 600,
3309
- letterSpacing: "0.04em",
3310
- textTransform: "uppercase",
3311
- fontFamily: "inherit",
3312
- padding: 0
3313
- },
3314
- children: "Logout"
3315
- }
3316
- )
3317
- ] }),
3318
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorStyle, children: error }),
3319
- loadingData ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "24px 0", textAlign: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { label: "Loading..." }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3320
- /* @__PURE__ */ jsxRuntime.jsxs(
3321
- "div",
3322
- {
3323
- style: {
3324
- textAlign: "center",
3325
- marginBottom: "20px"
3326
- },
3327
- children: [
3328
- /* @__PURE__ */ jsxRuntime.jsxs(
3329
- "div",
3330
- {
3331
- style: {
3332
- fontSize: "2rem",
3333
- fontWeight: 700,
3334
- color: tokens.text,
3335
- lineHeight: 1.2
3336
- },
3337
- children: [
3338
- "$",
3339
- parsedAmount > 0 ? parsedAmount.toFixed(2) : "0.00"
3340
- ]
3341
- }
3342
- ),
3343
- /* @__PURE__ */ jsxRuntime.jsx(
3344
- "button",
3345
- {
3346
- onClick: () => setStep("enter-amount"),
3347
- style: {
3348
- background: "transparent",
3349
- border: "none",
3350
- cursor: "pointer",
3351
- color: tokens.textMuted,
3352
- fontSize: "0.75rem",
3353
- fontFamily: "inherit",
3354
- outline: "none",
3355
- padding: "4px 8px",
3356
- marginTop: "4px"
3357
- },
3358
- children: "Change amount"
3359
- }
3360
- )
3361
- ]
3362
- }
3363
- ),
3364
- /* @__PURE__ */ jsxRuntime.jsx(
3365
- "div",
3366
- {
3367
- style: {
3368
- fontSize: "0.825rem",
3369
- color: tokens.textSecondary,
3370
- marginBottom: "16px",
3371
- padding: "12px 14px",
3372
- background: tokens.bgInput,
3373
- borderRadius: tokens.radiusLg,
3374
- border: `1px solid ${tokens.border}`,
3375
- lineHeight: 1.7
3376
- },
3377
- children: /* @__PURE__ */ jsxRuntime.jsx(
3378
- "div",
3379
- {
3380
- style: {
3381
- display: "flex",
3382
- justifyContent: "space-between",
3383
- alignItems: "center"
3384
- },
3385
- children: noAccounts ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {}) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3386
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "From" }),
3387
- /* @__PURE__ */ jsxRuntime.jsx(
3388
- AccountDropdown,
3389
- {
3390
- accounts,
3391
- selectedAccountId,
3392
- selectedWalletId,
3393
- onSelect: (id) => {
3394
- setSelectedAccountId(id);
3395
- setSelectedWalletId(null);
3396
- setConnectingNewAccount(false);
3397
- setSelectedProviderId(null);
3398
- },
3399
- onWalletSelect: (accountId, walletId) => {
3400
- setSelectedAccountId(accountId);
3401
- setSelectedWalletId(walletId);
3402
- setConnectingNewAccount(false);
3403
- setSelectedProviderId(null);
3404
- }
3405
- }
3406
- )
3407
- ] })
3408
- }
3409
- )
3410
- }
3411
- ),
3412
- noAccounts && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "16px" }, children: [
3413
- /* @__PURE__ */ jsxRuntime.jsx(
3414
- "label",
3415
- {
3416
- style: {
3417
- display: "block",
3418
- fontSize: "0.8rem",
3419
- color: tokens.textMuted,
3420
- marginBottom: "8px",
3421
- fontWeight: 500,
3422
- textTransform: "uppercase",
3423
- letterSpacing: "0.05em"
3424
- },
3425
- children: "Connect a wallet"
3426
- }
3427
- ),
3428
- /* @__PURE__ */ jsxRuntime.jsx(
3429
- "div",
3430
- {
3431
- style: {
3432
- display: "flex",
3433
- flexDirection: "column",
3434
- gap: "8px"
3435
- },
3436
- children: providers.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
3437
- ProviderCard,
3438
- {
3439
- provider: p,
3440
- selected: selectedProviderId === p.id,
3441
- onClick: () => {
3442
- setSelectedProviderId(p.id);
3443
- setSelectedAccountId(null);
3444
- setConnectingNewAccount(false);
3445
- }
3446
- },
3447
- p.id
3448
- ))
3449
- }
3450
- )
3451
- ] }),
3452
- /* @__PURE__ */ jsxRuntime.jsxs(
3453
- "button",
3454
- {
3455
- style: canPay ? btnPrimary : btnDisabled,
3456
- disabled: !canPay,
3457
- onClick: handlePay,
3458
- children: [
3459
- "Pay $",
3460
- parsedAmount > 0 ? parsedAmount.toFixed(2) : "0.00"
3461
- ]
3462
- }
3463
- ),
3464
- !noAccounts && /* @__PURE__ */ jsxRuntime.jsx(
3465
- AdvancedSettings,
3466
- {
3467
- settings: advancedSettings,
3468
- onChange: setAdvancedSettings,
3469
- chains,
3470
- providers,
3471
- onConnectNewAccount: handleConnectNewAccount,
3472
- connectingNewAccount
3473
- }
3474
- )
3475
- ] })
3476
- ] });
4034
+ const parsedAmt = depositAmount != null ? depositAmount : 5;
4035
+ return /* @__PURE__ */ jsxRuntime.jsx(
4036
+ DepositScreen,
4037
+ {
4038
+ merchantName,
4039
+ sourceName,
4040
+ sourceAddress,
4041
+ sourceVerified,
4042
+ availableBalance: maxSourceBalance,
4043
+ remainingLimit: oneTapLimit,
4044
+ tokenCount,
4045
+ initialAmount: parsedAmt,
4046
+ estimatedFeePct: 0.6,
4047
+ estimatedFeeUsd: parsedAmt * 6e-3,
4048
+ processing: creatingTransfer,
4049
+ error,
4050
+ onDeposit: handlePay,
4051
+ onChangeSource: () => setStep("wallet-picker"),
4052
+ onSwitchWallet: () => setStep("wallet-picker"),
4053
+ onBack: onBack ?? (() => handleLogout())
4054
+ }
4055
+ );
3477
4056
  }
3478
4057
  if (step === "processing") {
3479
- if (pendingSelectSourceAction) {
3480
- const chainValue = resolvedSelectSourceChainName;
3481
- const tokenValue = resolvedSelectSourceTokenSymbol;
3482
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardStyle, children: [
3483
- stepBadge("Select source"),
3484
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", marginBottom: "16px" }, children: [
3485
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { ...headingStyle, marginBottom: "8px" }, children: "Select payment source" }),
3486
- /* @__PURE__ */ jsxRuntime.jsx(
3487
- "p",
3488
- {
3489
- style: {
3490
- fontSize: "0.85rem",
3491
- color: tokens.textSecondary,
3492
- margin: 0,
3493
- lineHeight: 1.5
3494
- },
3495
- children: "Confirm the chain and token to use for this transfer."
3496
- }
3497
- )
3498
- ] }),
3499
- /* @__PURE__ */ jsxRuntime.jsxs(
3500
- "div",
3501
- {
3502
- style: {
3503
- fontSize: "0.825rem",
3504
- color: tokens.textSecondary,
3505
- marginBottom: "16px",
3506
- padding: "14px",
3507
- background: tokens.bgInput,
3508
- borderRadius: tokens.radius,
3509
- border: `1px solid ${tokens.border}`
3510
- },
3511
- children: [
3512
- /* @__PURE__ */ jsxRuntime.jsx(
3513
- "label",
3514
- {
3515
- htmlFor: "swype-select-source-chain",
3516
- style: {
3517
- display: "block",
3518
- fontSize: "0.75rem",
3519
- fontWeight: 600,
3520
- marginBottom: "6px",
3521
- color: tokens.textMuted,
3522
- textTransform: "uppercase",
3523
- letterSpacing: "0.04em"
3524
- },
3525
- children: "Chain"
3526
- }
3527
- ),
3528
- /* @__PURE__ */ jsxRuntime.jsx(
3529
- "select",
3530
- {
3531
- id: "swype-select-source-chain",
3532
- value: chainValue,
3533
- onChange: (event) => handleSelectSourceChainChange(event.target.value),
3534
- style: {
3535
- width: "100%",
3536
- marginBottom: "12px",
3537
- padding: "10px 12px",
3538
- borderRadius: tokens.radiusLg,
3539
- border: `1px solid ${tokens.border}`,
3540
- background: tokens.bgInput,
3541
- color: tokens.text,
3542
- fontFamily: "inherit",
3543
- fontSize: "0.875rem",
3544
- outline: "none"
3545
- },
3546
- children: displayedSelectSourceChoices.map((chainChoice) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: chainChoice.chainName, children: [
3547
- chainChoice.chainName,
3548
- " ($",
3549
- chainChoice.balance.toFixed(2),
3550
- ")"
3551
- ] }, chainChoice.chainName))
3552
- }
3553
- ),
3554
- /* @__PURE__ */ jsxRuntime.jsx(
3555
- "label",
3556
- {
3557
- htmlFor: "swype-select-source-token",
3558
- style: {
3559
- display: "block",
3560
- fontSize: "0.75rem",
3561
- fontWeight: 600,
3562
- marginBottom: "6px",
3563
- color: tokens.textMuted,
3564
- textTransform: "uppercase",
3565
- letterSpacing: "0.04em"
3566
- },
3567
- children: "Token"
3568
- }
3569
- ),
3570
- /* @__PURE__ */ jsxRuntime.jsx(
3571
- "select",
3572
- {
3573
- id: "swype-select-source-token",
3574
- value: tokenValue,
3575
- onChange: (event) => setSelectSourceTokenSymbol(event.target.value),
3576
- style: {
3577
- width: "100%",
3578
- padding: "10px 12px",
3579
- borderRadius: tokens.radiusLg,
3580
- border: `1px solid ${tokens.border}`,
3581
- background: tokens.bgInput,
3582
- color: tokens.text,
3583
- fontFamily: "inherit",
3584
- fontSize: "0.875rem",
3585
- outline: "none"
3586
- },
3587
- children: selectSourceTokenChoices.map((tokenChoice) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: tokenChoice.tokenSymbol, children: [
3588
- tokenChoice.tokenSymbol,
3589
- " ($",
3590
- tokenChoice.balance.toFixed(2),
3591
- ")"
3592
- ] }, tokenChoice.tokenSymbol))
3593
- }
3594
- )
3595
- ]
3596
- }
3597
- ),
3598
- /* @__PURE__ */ jsxRuntime.jsx(
3599
- "button",
3600
- {
3601
- style: canConfirmSelectSource ? btnPrimary : btnDisabled,
3602
- disabled: !canConfirmSelectSource,
3603
- onClick: () => {
3604
- if (!canConfirmSelectSource) return;
3605
- authExecutor.resolveSelectSource({
3606
- chainName: resolvedSelectSourceChainName,
3607
- tokenSymbol: resolvedSelectSourceTokenSymbol
3608
- });
3609
- },
3610
- children: "Confirm source"
3611
- }
3612
- )
3613
- ] });
3614
- }
3615
- if (transferSigning.signing && transferSigning.signPayload) {
3616
- const payload = transferSigning.signPayload;
3617
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "16px 0" }, children: [
3618
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "48", height: "48", viewBox: "0 0 48 48", fill: "none", style: { margin: "0 auto 16px" }, children: [
3619
- /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "48", height: "48", rx: "12", fill: tokens.accent + "20" }),
3620
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M24 14v8M20 18h8M24 26v2M24 32v2", stroke: tokens.accent, strokeWidth: "2", strokeLinecap: "round" })
3621
- ] }),
3622
- /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { ...headingStyle, marginBottom: "8px" }, children: "Authorize Transfer" }),
3623
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.85rem", color: tokens.textSecondary, margin: "0 0 16px 0", lineHeight: 1.5 }, children: "Use your passkey to confirm this payment." }),
3624
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: "0.825rem", color: tokens.textSecondary, padding: "12px 14px", background: tokens.bgInput, borderRadius: tokens.radiusLg, border: `1px solid ${tokens.border}`, textAlign: "left", lineHeight: 1.7, marginBottom: "16px" }, children: [
3625
- payload.amount && payload.tokenSymbol && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
3626
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Amount" }),
3627
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontWeight: 600, color: tokens.text }, children: [
3628
- payload.amount,
3629
- " ",
3630
- payload.tokenSymbol
3631
- ] })
3632
- ] }),
3633
- payload.bridgeRelayAddress && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
3634
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Bridge relay" }),
3635
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontFamily: '"SF Mono", "Fira Code", monospace', fontSize: "0.75rem" }, children: [
3636
- payload.bridgeRelayAddress.slice(0, 6),
3637
- "...",
3638
- payload.bridgeRelayAddress.slice(-4)
3639
- ] })
3640
- ] }),
3641
- payload.estimatedFeeUsd && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
3642
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Est. fee" }),
3643
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontWeight: 600 }, children: [
3644
- "$",
3645
- payload.estimatedFeeUsd
3646
- ] })
3647
- ] })
3648
- ] }),
3649
- /* @__PURE__ */ jsxRuntime.jsx(Spinner, { label: "Waiting for passkey..." })
3650
- ] }) });
3651
- }
3652
4058
  const currentActionType = authExecutor.currentAction?.type;
3653
- const getRegistrationMessage = () => {
3654
- switch (currentActionType) {
3655
- case "CREATE_SMART_ACCOUNT":
3656
- return {
3657
- label: "Creating your smart account...",
3658
- description: "Setting up your smart account for gasless payments."
3659
- };
3660
- case "APPROVE_PERMIT2":
3661
- return {
3662
- label: "Approving token access...",
3663
- description: "Approve the prompt in your wallet to allow secure token transfers."
3664
- };
3665
- case "SIGN_PERMIT2":
3666
- return {
3667
- label: "Signing transfer permission...",
3668
- description: "Sign the permit to allow your smart account to transfer tokens on your behalf."
3669
- };
3670
- default:
3671
- return { label: "", description: "" };
3672
- }
3673
- };
3674
- const regMsg = getRegistrationMessage();
3675
- getDisplayTransferStatus(polling.transfer, transfer);
3676
- getTransferIdSuffix(polling.transfer, transfer);
3677
- const statusLabel = creatingTransfer ? "Creating Transfer" : mobileFlow ? "Waiting for Authorization" : authExecutor.executing && regMsg.label ? regMsg.label : authExecutor.executing ? "Authorizing" : transferSigning.signing ? "Sending transfer" : polling.isPolling ? "Transfer Sent" : "Please wait...";
3678
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "16px 0" }, children: [
4059
+ const statusLabel = creatingTransfer ? "Creating Transfer" : mobileFlow ? "Waiting for Authorization" : authExecutor.executing ? currentActionType?.replace(/_/g, " ") ?? "Authorizing" : transferSigning.signing ? "Sending transfer" : polling.isPolling ? "Transfer Sent" : "Please wait...";
4060
+ return /* @__PURE__ */ jsxRuntime.jsx(ScreenLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", padding: "48px 0", flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }, children: [
3679
4061
  /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
3680
- /* @__PURE__ */ jsxRuntime.jsx(
3681
- "h2",
3682
- {
3683
- style: {
3684
- ...headingStyle,
3685
- marginTop: "20px",
3686
- marginBottom: "8px"
3687
- },
3688
- children: statusLabel
3689
- }
3690
- ),
3691
- polling.error && /* @__PURE__ */ jsxRuntime.jsxs(
3692
- "p",
3693
- {
3694
- style: {
3695
- marginTop: "8px",
3696
- marginBottom: 0,
3697
- fontSize: "0.75rem",
3698
- color: tokens.textMuted
3699
- },
3700
- children: [
3701
- "Last polling error: ",
3702
- polling.error
3703
- ]
3704
- }
3705
- ),
3706
- !mobileFlow && authExecutor.results.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "20px", textAlign: "left" }, children: authExecutor.results.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
3707
- "div",
3708
- {
3709
- style: {
3710
- display: "flex",
3711
- alignItems: "center",
3712
- gap: "8px",
3713
- padding: "6px 0",
3714
- fontSize: "0.8rem",
3715
- color: r.status === "success" ? tokens.success : tokens.error
3716
- },
3717
- children: [
3718
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: r.status === "success" ? "\u2713" : "\u2717" }),
3719
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: r.type.replace(/_/g, " ") })
3720
- ]
3721
- },
3722
- r.actionId
3723
- )) }),
3724
- (error || authExecutor.error || transferSigning.error || polling.error) && /* @__PURE__ */ jsxRuntime.jsx(
3725
- "div",
3726
- {
3727
- style: { ...errorStyle, marginTop: "16px", textAlign: "left" },
3728
- children: error || authExecutor.error || transferSigning.error || polling.error
3729
- }
3730
- )
4062
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { fontSize: "1.4rem", fontWeight: 700, color: tokens.text, marginTop: 20, marginBottom: 8 }, children: statusLabel }),
4063
+ (error || authExecutor.error || transferSigning.error || polling.error) && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
4064
+ background: tokens.errorBg,
4065
+ border: `1px solid ${tokens.error}66`,
4066
+ borderRadius: 16,
4067
+ padding: "11px 14px",
4068
+ color: tokens.error,
4069
+ fontSize: "0.84rem",
4070
+ marginTop: 16,
4071
+ lineHeight: 1.5,
4072
+ textAlign: "left",
4073
+ maxWidth: 340
4074
+ }, children: error || authExecutor.error || transferSigning.error || polling.error })
3731
4075
  ] }) });
3732
4076
  }
3733
- if (step === "complete") {
3734
- const succeeded = transfer?.status === "COMPLETED";
3735
- return /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center" }, children: [
3736
- /* @__PURE__ */ jsxRuntime.jsx(
3737
- "div",
3738
- {
3739
- style: {
3740
- width: 56,
3741
- height: 56,
3742
- borderRadius: "50%",
3743
- background: succeeded ? tokens.success + "20" : tokens.error + "20",
3744
- display: "flex",
3745
- alignItems: "center",
3746
- justifyContent: "center",
3747
- margin: "0 auto 16px"
3748
- },
3749
- children: succeeded ? /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
3750
- "path",
3751
- {
3752
- d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
3753
- fill: tokens.success
3754
- }
3755
- ) }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
3756
- "path",
3757
- {
3758
- d: "M18.3 5.71L12 12.01 5.7 5.71 4.29 7.12l6.3 6.3-6.3 6.29 1.41 1.41 6.3-6.29 6.29 6.29 1.41-1.41-6.29-6.29 6.29-6.3-1.41-1.41z",
3759
- fill: tokens.error
3760
- }
3761
- ) })
3762
- }
3763
- ),
3764
- /* @__PURE__ */ jsxRuntime.jsx(
3765
- "h2",
3766
- {
3767
- style: {
3768
- ...headingStyle,
3769
- marginBottom: "8px",
3770
- color: succeeded ? tokens.success : tokens.error
3771
- },
3772
- children: succeeded ? "Payment Complete" : "Payment Failed"
3773
- }
3774
- ),
3775
- transfer && /* @__PURE__ */ jsxRuntime.jsxs(
3776
- "div",
3777
- {
3778
- style: {
3779
- fontSize: "0.825rem",
3780
- color: tokens.textSecondary,
3781
- margin: "0 0 24px 0",
3782
- padding: "14px",
3783
- background: tokens.bgInput,
3784
- borderRadius: tokens.radiusLg,
3785
- border: `1px solid ${tokens.border}`,
3786
- textAlign: "left",
3787
- lineHeight: 1.8
3788
- },
3789
- children: [
3790
- /* @__PURE__ */ jsxRuntime.jsxs(
3791
- "div",
3792
- {
3793
- style: { display: "flex", justifyContent: "space-between" },
3794
- children: [
3795
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Amount" }),
3796
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontWeight: 600, color: tokens.text }, children: [
3797
- "$",
3798
- transfer.amount?.amount?.toFixed(2),
3799
- " ",
3800
- transfer.amount?.currency
3801
- ] })
3802
- ]
3803
- }
3804
- ),
3805
- /* @__PURE__ */ jsxRuntime.jsxs(
3806
- "div",
3807
- {
3808
- style: { display: "flex", justifyContent: "space-between" },
3809
- children: [
3810
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Status" }),
3811
- /* @__PURE__ */ jsxRuntime.jsx(
3812
- "span",
3813
- {
3814
- style: {
3815
- fontWeight: 600,
3816
- color: succeeded ? tokens.success : tokens.error
3817
- },
3818
- children: transfer.status
3819
- }
3820
- )
3821
- ]
3822
- }
3823
- ),
3824
- /* @__PURE__ */ jsxRuntime.jsxs(
3825
- "div",
3826
- {
3827
- style: { display: "flex", justifyContent: "space-between" },
3828
- children: [
3829
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Transfer ID" }),
3830
- /* @__PURE__ */ jsxRuntime.jsxs(
3831
- "span",
3832
- {
3833
- style: {
3834
- fontFamily: '"SF Mono", "Fira Code", monospace',
3835
- fontSize: "0.75rem"
3836
- },
3837
- children: [
3838
- transfer.id.slice(0, 8),
3839
- "..."
3840
- ]
3841
- }
3842
- )
3843
- ]
3844
- }
3845
- )
3846
- ]
3847
- }
3848
- ),
3849
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...errorStyle, textAlign: "left" }, children: error }),
3850
- /* @__PURE__ */ jsxRuntime.jsx("button", { style: btnPrimary, onClick: handleNewPayment, children: succeeded ? "Make Another Payment" : "Try Again" })
3851
- ] }) });
4077
+ if (step === "success") {
4078
+ transfer?.status === "COMPLETED";
4079
+ const displayAmount = transfer?.amount?.amount ?? 0;
4080
+ const displayCurrency = transfer?.amount?.currency ?? "USD";
4081
+ return /* @__PURE__ */ jsxRuntime.jsx(
4082
+ SuccessScreen,
4083
+ {
4084
+ amount: displayAmount,
4085
+ currency: displayCurrency,
4086
+ merchantName,
4087
+ sourceName,
4088
+ remainingLimit: oneTapLimit > displayAmount ? oneTapLimit - displayAmount : 0,
4089
+ onDone: handleNewPayment
4090
+ }
4091
+ );
4092
+ }
4093
+ if (step === "low-balance") {
4094
+ return /* @__PURE__ */ jsxRuntime.jsx(
4095
+ DepositScreen,
4096
+ {
4097
+ merchantName,
4098
+ sourceName,
4099
+ sourceAddress,
4100
+ sourceVerified,
4101
+ availableBalance: 0,
4102
+ remainingLimit: oneTapLimit,
4103
+ tokenCount,
4104
+ initialAmount: depositAmount ?? 5,
4105
+ processing: false,
4106
+ error,
4107
+ onDeposit: handlePay,
4108
+ onChangeSource: () => setStep("wallet-picker"),
4109
+ onSwitchWallet: () => setStep("wallet-picker"),
4110
+ onBack: onBack ?? (() => handleLogout())
4111
+ }
4112
+ );
3852
4113
  }
3853
4114
  return null;
3854
4115
  }