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