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