@swype-org/react-sdk 0.1.30 → 0.1.32

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,1945 @@ 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", { className: "swype-slider-wrap", 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
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 = {
1853
+ position: "absolute",
1854
+ left: 0,
1855
+ right: 0,
1856
+ width: "100%",
1857
+ height: 28,
1858
+ margin: 0,
1859
+ cursor: "pointer",
1860
+ zIndex: 2,
1861
+ WebkitAppearance: "none",
1862
+ appearance: "none",
1863
+ background: "transparent"
1864
+ };
1865
+ var ticksStyle = {
1866
+ display: "flex",
1867
+ justifyContent: "space-between",
1868
+ marginTop: 6
1869
+ };
1870
+ var tickLabelStyle = (color) => ({
1871
+ fontSize: "0.72rem",
1872
+ fontWeight: 500,
1873
+ color
1874
+ });
1875
+ var sliderThumbCss = (accent) => `
1876
+ .swype-slider-wrap input[type="range"]::-webkit-slider-runnable-track {
1877
+ height: 4px;
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
+ margin-top: -8px;
1890
+ }
1891
+ .swype-slider-wrap input[type="range"]::-moz-range-track {
1892
+ height: 4px;
1893
+ background: transparent;
1894
+ border: none;
1895
+ }
1896
+ .swype-slider-wrap input[type="range"]::-moz-range-thumb {
1897
+ width: 14px;
1898
+ height: 14px;
1899
+ border-radius: 50%;
1900
+ background: ${accent};
1901
+ border: 3px solid #fff;
1902
+ box-shadow: 0 2px 6px rgba(0,0,0,0.15);
1903
+ cursor: pointer;
1904
+ }
1905
+ `;
1906
+ function SourceCard({ name, address, verified, onChangeSource }) {
1907
+ const { tokens } = useSwypeConfig();
1908
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle6(tokens), children: [
1909
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: leftStyle, children: [
1910
+ /* @__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(
1911
+ "path",
1912
+ {
1913
+ 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",
1914
+ fill: "currentColor"
1915
+ }
1916
+ ) }) }),
1917
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1918
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: nameRowStyle, children: [
1919
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: nameStyle(tokens.text), children: name }),
1920
+ 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 }) })
1921
+ ] }),
1922
+ address && /* @__PURE__ */ jsxRuntime.jsx("span", { style: addressStyle(tokens.textMuted), children: address })
1923
+ ] })
1924
+ ] }),
1925
+ onChangeSource && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onChangeSource, style: changeStyle(tokens.accent), children: "Change source" })
1926
+ ] });
1927
+ }
1928
+ var containerStyle6 = (tokens) => ({
1929
+ display: "flex",
1930
+ alignItems: "center",
1931
+ justifyContent: "space-between",
1932
+ padding: "12px 16px",
1933
+ background: tokens.bgInput,
1934
+ border: `1px solid ${tokens.border}`,
1935
+ borderRadius: 16
1936
+ });
1937
+ var leftStyle = {
1938
+ display: "flex",
1939
+ alignItems: "center",
1940
+ gap: 10
1941
+ };
1942
+ var iconStyle3 = (color) => ({
1943
+ color,
1944
+ display: "flex",
1945
+ alignItems: "center"
1946
+ });
1947
+ var nameRowStyle = {
1948
+ display: "flex",
1949
+ alignItems: "center",
1950
+ gap: 4
1951
+ };
1952
+ var nameStyle = (color) => ({
1953
+ fontWeight: 600,
1954
+ fontSize: "0.9rem",
1955
+ color
1956
+ });
1957
+ var addressStyle = (color) => ({
1958
+ fontSize: "0.72rem",
1959
+ color,
1960
+ fontFamily: '"SF Mono", "Fira Code", monospace'
1961
+ });
1962
+ var changeStyle = (color) => ({
1963
+ background: "transparent",
1964
+ border: "none",
1965
+ color,
1966
+ fontWeight: 600,
1967
+ fontSize: "0.82rem",
1968
+ cursor: "pointer",
1969
+ fontFamily: "inherit",
1970
+ padding: 0
1971
+ });
1972
+ function StepList({ steps }) {
1973
+ const { tokens } = useSwypeConfig();
1974
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: listStyle, children: steps.map((step, i) => {
1975
+ const isComplete = step.status === "complete";
1976
+ const isActive = step.status === "active";
1977
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: rowStyle, children: [
1978
+ /* @__PURE__ */ jsxRuntime.jsx(
1979
+ "div",
1980
+ {
1981
+ style: badgeStyle2(
1982
+ isComplete ? tokens.accent : isActive ? tokens.accent : tokens.border,
1983
+ isComplete || isActive
1984
+ ),
1985
+ 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 })
1986
+ }
1987
+ ),
1988
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: labelContainerStyle, children: [
1989
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: labelStyle(isComplete || isActive ? tokens.text : tokens.textMuted), children: step.label }),
1990
+ step.detail && /* @__PURE__ */ jsxRuntime.jsx("span", { style: detailStyle(tokens.textMuted), children: step.detail })
1991
+ ] })
1992
+ ] }, i);
1993
+ }) });
1994
+ }
1995
+ var listStyle = {
1996
+ display: "flex",
1997
+ flexDirection: "column",
1998
+ gap: 12
1999
+ };
2000
+ var rowStyle = {
2001
+ display: "flex",
2002
+ alignItems: "center",
2003
+ gap: 12
2004
+ };
2005
+ var badgeStyle2 = (color, filled) => ({
2006
+ width: 28,
2007
+ height: 28,
2008
+ borderRadius: "50%",
2009
+ background: filled ? color : "transparent",
2010
+ border: filled ? "none" : `1.5px solid ${color}`,
2011
+ display: "flex",
2012
+ alignItems: "center",
2013
+ justifyContent: "center",
2014
+ flexShrink: 0
2015
+ });
2016
+ var badgeNumberStyle = (active) => ({
2017
+ fontSize: "0.75rem",
2018
+ fontWeight: 600,
2019
+ color: active ? "#fff" : "inherit"
2020
+ });
2021
+ var labelContainerStyle = {
2022
+ display: "flex",
2023
+ flexDirection: "column"
2024
+ };
2025
+ var labelStyle = (color) => ({
2026
+ fontSize: "0.9rem",
2027
+ fontWeight: 500,
2028
+ color
2029
+ });
2030
+ var detailStyle = (color) => ({
2031
+ fontSize: "0.75rem",
2032
+ color
2033
+ });
2034
+ function SettingsMenu({ onLogout }) {
2035
+ const { tokens } = useSwypeConfig();
2036
+ const [open, setOpen] = react.useState(false);
2037
+ const menuRef = react.useRef(null);
2038
+ const toggle = react.useCallback(() => setOpen((prev) => !prev), []);
2039
+ react.useEffect(() => {
2040
+ if (!open) return;
2041
+ const handleClickOutside = (e) => {
2042
+ if (menuRef.current && !menuRef.current.contains(e.target)) {
2043
+ setOpen(false);
2044
+ }
2045
+ };
2046
+ document.addEventListener("mousedown", handleClickOutside);
2047
+ return () => document.removeEventListener("mousedown", handleClickOutside);
2048
+ }, [open]);
2049
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: menuRef, style: containerStyle7, children: [
2050
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: toggle, style: triggerStyle(tokens.text), "aria-label": "Settings", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [
2051
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "5", r: "2", fill: "currentColor" }),
2052
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "2", fill: "currentColor" }),
2053
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "19", r: "2", fill: "currentColor" })
2054
+ ] }) }),
2055
+ open && /* @__PURE__ */ jsxRuntime.jsx("div", { style: dropdownStyle(tokens), children: /* @__PURE__ */ jsxRuntime.jsxs(
2056
+ "button",
2057
+ {
2058
+ type: "button",
2059
+ onClick: () => {
2060
+ setOpen(false);
2061
+ onLogout();
2062
+ },
2063
+ style: menuItemStyle(tokens),
2064
+ children: [
2065
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { marginRight: 8, flexShrink: 0 }, children: [
2066
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4", stroke: tokens.error, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
2067
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "16 17 21 12 16 7", stroke: tokens.error, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
2068
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "12", x2: "9", y2: "12", stroke: tokens.error, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
2069
+ ] }),
2070
+ "Log out"
2071
+ ]
2072
+ }
2073
+ ) })
2074
+ ] });
2075
+ }
2076
+ var containerStyle7 = {
2077
+ position: "relative"
2078
+ };
2079
+ var triggerStyle = (color) => ({
2080
+ background: "transparent",
2081
+ border: "none",
2082
+ cursor: "pointer",
2083
+ padding: 4,
2084
+ color,
2085
+ display: "flex",
2086
+ alignItems: "center",
2087
+ justifyContent: "center"
2088
+ });
2089
+ var dropdownStyle = (tokens) => ({
2090
+ position: "absolute",
2091
+ right: 0,
2092
+ top: "100%",
2093
+ marginTop: 4,
2094
+ minWidth: 140,
2095
+ background: tokens.bgCard,
2096
+ border: `1px solid ${tokens.border}`,
2097
+ borderRadius: 12,
2098
+ boxShadow: tokens.shadow,
2099
+ zIndex: 100,
2100
+ overflow: "hidden"
2101
+ });
2102
+ var menuItemStyle = (tokens) => ({
2103
+ width: "100%",
2104
+ display: "flex",
2105
+ alignItems: "center",
2106
+ padding: "12px 16px",
2107
+ background: "transparent",
2108
+ border: "none",
2109
+ cursor: "pointer",
2110
+ fontFamily: "inherit",
2111
+ fontSize: "0.85rem",
2112
+ fontWeight: 500,
2113
+ color: tokens.error
2114
+ });
2115
+ function LoginScreen({
2116
+ authInput,
2117
+ onAuthInputChange,
2118
+ onSubmit,
2119
+ sending,
2120
+ error,
2121
+ onBack
2122
+ }) {
2123
+ const { tokens } = useSwypeConfig();
2124
+ const disabled = authInput.trim().length === 0 || sending;
2125
+ const walletLogos = ["MM", "R", "O", "P", "+"];
2126
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2127
+ ScreenLayout,
2128
+ {
2129
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2130
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onSubmit, disabled, loading: sending, children: "Continue" }),
2131
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: dividerStyle(tokens), children: [
2132
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerLineStyle(tokens.border) }),
2133
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "works with" }),
2134
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: dividerLineStyle(tokens.border) })
2135
+ ] }),
2136
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: logosRowStyle, children: walletLogos.map((label) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: logoCircleStyle(tokens), children: label }, label)) }),
2137
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2138
+ ] }),
2139
+ children: [
2140
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onBack }),
2141
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle, children: [
2142
+ /* @__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(
2143
+ "path",
2144
+ {
2145
+ d: "M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z",
2146
+ fill: tokens.accent
2147
+ }
2148
+ ) }) }),
2149
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle(tokens.text), children: "One-time setup.\nOne-tap deposits after." }),
2150
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle(tokens.textSecondary), children: "Protected by Face ID." }),
2151
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorStyle(tokens), children: error }),
2152
+ /* @__PURE__ */ jsxRuntime.jsx(
2153
+ "input",
2154
+ {
2155
+ id: "swype-login-identifier",
2156
+ type: "text",
2157
+ inputMode: "text",
2158
+ autoComplete: "username",
2159
+ placeholder: "Email or phone number",
2160
+ value: authInput,
2161
+ onChange: (e) => onAuthInputChange(e.target.value),
2162
+ onKeyDown: (e) => {
2163
+ if (e.key === "Enter" && !disabled) onSubmit();
2164
+ },
2165
+ style: inputStyle2(tokens)
2166
+ }
2167
+ )
2168
+ ] })
2169
+ ]
2170
+ }
2171
+ );
2172
+ }
2173
+ var contentStyle = {
2174
+ textAlign: "center",
2175
+ flex: 1,
2176
+ display: "flex",
2177
+ flexDirection: "column",
2178
+ alignItems: "center",
2179
+ paddingTop: 24
2180
+ };
2181
+ var headingStyle = (color) => ({
2182
+ fontSize: "1.65rem",
2183
+ fontWeight: 700,
2184
+ lineHeight: 1.2,
2185
+ letterSpacing: "-0.02em",
2186
+ color,
2187
+ margin: "20px 0 8px",
2188
+ whiteSpace: "pre-line"
2189
+ });
2190
+ var subtitleStyle = (color) => ({
2191
+ fontSize: "0.84rem",
2192
+ color,
2193
+ margin: "0 0 24px",
2194
+ lineHeight: 1.5
2195
+ });
2196
+ var inputStyle2 = (tokens) => ({
2197
+ width: "100%",
2198
+ padding: "15px 16px",
2199
+ borderRadius: 16,
2200
+ border: `1px solid ${tokens.border}`,
2201
+ background: tokens.bgInput,
2202
+ color: tokens.text,
2203
+ fontSize: "0.95rem",
2204
+ fontFamily: "inherit",
2205
+ outline: "none",
2206
+ boxSizing: "border-box"
2207
+ });
2208
+ var errorStyle = (tokens) => ({
2209
+ background: tokens.errorBg,
2210
+ border: `1px solid ${tokens.error}66`,
2211
+ borderRadius: 16,
2212
+ padding: "11px 14px",
2213
+ color: tokens.error,
2214
+ fontSize: "0.84rem",
2215
+ marginBottom: 14,
2216
+ lineHeight: 1.5,
2217
+ width: "100%",
2218
+ textAlign: "left"
2219
+ });
2220
+ var dividerStyle = (tokens) => ({
2221
+ display: "flex",
2222
+ alignItems: "center",
2223
+ gap: 10,
2224
+ margin: "20px 0 14px",
2225
+ color: tokens.textMuted,
2226
+ fontSize: "0.82rem"
2227
+ });
2228
+ var dividerLineStyle = (color) => ({
2229
+ flex: 1,
2230
+ height: 1,
2231
+ background: color
2232
+ });
2233
+ var logosRowStyle = {
2234
+ display: "flex",
2235
+ justifyContent: "center",
2236
+ gap: 12,
2237
+ marginBottom: 8
2238
+ };
2239
+ var logoCircleStyle = (tokens) => ({
2240
+ width: 34,
2241
+ height: 34,
2242
+ borderRadius: 999,
2243
+ border: `1px solid ${tokens.border}`,
2244
+ background: tokens.bgInput,
2245
+ color: tokens.textMuted,
2246
+ display: "flex",
2247
+ alignItems: "center",
2248
+ justifyContent: "center",
2249
+ fontSize: "0.72rem",
2250
+ fontWeight: 600
2251
+ });
2252
+ var RESEND_COOLDOWN_SECONDS = 30;
2253
+ function OtpVerifyScreen({
2254
+ maskedIdentifier,
2255
+ otpCode,
2256
+ onOtpChange,
2257
+ onVerify,
2258
+ onResend,
2259
+ onBack,
2260
+ verifying,
2261
+ error
2262
+ }) {
2263
+ const { tokens } = useSwypeConfig();
2264
+ const disabled = otpCode.trim().length !== 6 || verifying;
2265
+ const [cooldown, setCooldown] = react.useState(RESEND_COOLDOWN_SECONDS);
2266
+ const intervalRef = react.useRef(null);
2267
+ react.useEffect(() => {
2268
+ setCooldown(RESEND_COOLDOWN_SECONDS);
2269
+ intervalRef.current = setInterval(() => {
2270
+ setCooldown((prev) => {
2271
+ if (prev <= 1) {
2272
+ if (intervalRef.current) clearInterval(intervalRef.current);
2273
+ return 0;
2274
+ }
2275
+ return prev - 1;
2276
+ });
2277
+ }, 1e3);
2278
+ return () => {
2279
+ if (intervalRef.current) clearInterval(intervalRef.current);
2280
+ };
2281
+ }, []);
2282
+ const handleResend = react.useCallback(() => {
2283
+ if (cooldown > 0) return;
2284
+ onResend();
2285
+ setCooldown(RESEND_COOLDOWN_SECONDS);
2286
+ intervalRef.current = setInterval(() => {
2287
+ setCooldown((prev) => {
2288
+ if (prev <= 1) {
2289
+ if (intervalRef.current) clearInterval(intervalRef.current);
2290
+ return 0;
2291
+ }
2292
+ return prev - 1;
2293
+ });
2294
+ }, 1e3);
2295
+ }, [cooldown, onResend]);
2296
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2297
+ ScreenLayout,
2298
+ {
2299
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2300
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onVerify, disabled, loading: verifying, children: "Verify" }),
2301
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: hintStyle(tokens.textMuted), children: "Didn't get the code? Check your spam folder" }),
2302
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2303
+ ] }),
2304
+ children: [
2305
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onBack }),
2306
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle2, children: [
2307
+ /* @__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(
2308
+ "path",
2309
+ {
2310
+ d: "M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z",
2311
+ fill: tokens.accent
2312
+ }
2313
+ ) }) }),
2314
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle2(tokens.text), children: "Check your email" }),
2315
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle2(tokens.textSecondary), children: [
2316
+ "We sent a 6-digit code to",
2317
+ "\n",
2318
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: maskedIdentifier })
2319
+ ] }),
2320
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle(tokens), children: error }),
2321
+ /* @__PURE__ */ jsxRuntime.jsx(OtpInput, { value: otpCode, onChange: onOtpChange, disabled: verifying }),
2322
+ /* @__PURE__ */ jsxRuntime.jsx(
2323
+ "button",
2324
+ {
2325
+ type: "button",
2326
+ onClick: handleResend,
2327
+ disabled: cooldown > 0,
2328
+ style: resendStyle(tokens.textMuted, cooldown > 0),
2329
+ children: cooldown > 0 ? `Resend code in ${cooldown}s` : "Resend code"
2330
+ }
2331
+ )
2332
+ ] })
2333
+ ]
2334
+ }
2335
+ );
2336
+ }
2337
+ var contentStyle2 = {
2338
+ textAlign: "center",
2339
+ flex: 1,
2340
+ display: "flex",
2341
+ flexDirection: "column",
2342
+ alignItems: "center",
2343
+ paddingTop: 24
2344
+ };
2345
+ var headingStyle2 = (color) => ({
2346
+ fontSize: "1.5rem",
2347
+ fontWeight: 700,
2348
+ letterSpacing: "-0.02em",
2349
+ color,
2350
+ margin: "20px 0 8px"
2351
+ });
2352
+ var subtitleStyle2 = (color) => ({
2353
+ fontSize: "0.88rem",
2354
+ color,
2355
+ margin: "0 0 28px",
2356
+ lineHeight: 1.5,
2357
+ whiteSpace: "pre-line"
2358
+ });
2359
+ var errorBannerStyle = (tokens) => ({
2360
+ background: tokens.errorBg,
2361
+ border: `1px solid ${tokens.error}66`,
2362
+ borderRadius: 16,
2363
+ padding: "11px 14px",
2364
+ color: tokens.error,
2365
+ fontSize: "0.84rem",
2366
+ marginBottom: 14,
2367
+ lineHeight: 1.5,
2368
+ width: "100%",
2369
+ textAlign: "left"
2370
+ });
2371
+ var resendStyle = (color, disabled) => ({
2372
+ background: "transparent",
2373
+ border: "none",
2374
+ color,
2375
+ cursor: disabled ? "default" : "pointer",
2376
+ fontFamily: "inherit",
2377
+ fontSize: "0.82rem",
2378
+ marginTop: 16,
2379
+ padding: 0,
2380
+ opacity: disabled ? 0.6 : 1
2381
+ });
2382
+ var hintStyle = (color) => ({
2383
+ textAlign: "center",
2384
+ fontSize: "0.78rem",
2385
+ color,
2386
+ margin: "12px 0 0"
2387
+ });
2388
+ function CreatePasskeyScreen({
2389
+ onCreatePasskey,
2390
+ onSkip,
2391
+ onBack,
2392
+ creating,
2393
+ error
2394
+ }) {
2395
+ const { tokens } = useSwypeConfig();
2396
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2397
+ ScreenLayout,
2398
+ {
2399
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2400
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onCreatePasskey, disabled: creating, loading: creating, children: "Create passkey" }),
2401
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onSkip, style: skipStyle(tokens.textMuted), disabled: creating, children: "Skip for now" }),
2402
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2403
+ ] }),
2404
+ children: [
2405
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onBack }),
2406
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle3, children: [
2407
+ /* @__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: [
2408
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "3", stroke: tokens.accent, strokeWidth: "1.5", strokeDasharray: "3 2" }),
2409
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "10", r: "1", fill: tokens.accent }),
2410
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "15", cy: "10", r: "1", fill: tokens.accent }),
2411
+ /* @__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" })
2412
+ ] }) }),
2413
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle3(tokens.text), children: "Create your passkey" }),
2414
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle3(tokens.textSecondary), children: "Use Face ID to sign in instantly \u2014 no passwords, no codes." }),
2415
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle2(tokens), children: error }),
2416
+ /* @__PURE__ */ jsxRuntime.jsx(InfoBanner, { children: "Your passkey is stored securely on your device. Swype never sees your biometric data." })
2417
+ ] })
2418
+ ]
2419
+ }
2420
+ );
2421
+ }
2422
+ var contentStyle3 = {
2423
+ textAlign: "center",
2424
+ flex: 1,
2425
+ display: "flex",
2426
+ flexDirection: "column",
2427
+ alignItems: "center",
2428
+ paddingTop: 32
2429
+ };
2430
+ var headingStyle3 = (color) => ({
2431
+ fontSize: "1.45rem",
2432
+ fontWeight: 700,
2433
+ letterSpacing: "-0.02em",
2434
+ color,
2435
+ margin: "24px 0 8px"
2436
+ });
2437
+ var subtitleStyle3 = (color) => ({
2438
+ fontSize: "0.9rem",
2439
+ color,
2440
+ margin: "0 0 28px",
2441
+ lineHeight: 1.5,
2442
+ maxWidth: 280
2443
+ });
2444
+ var errorBannerStyle2 = (tokens) => ({
2445
+ background: tokens.errorBg,
2446
+ border: `1px solid ${tokens.error}66`,
2447
+ borderRadius: 16,
2448
+ padding: "11px 14px",
2449
+ color: tokens.error,
2450
+ fontSize: "0.84rem",
2451
+ marginBottom: 14,
2452
+ lineHeight: 1.5,
2453
+ width: "100%",
2454
+ textAlign: "left"
2455
+ });
2456
+ var skipStyle = (color) => ({
2457
+ background: "transparent",
2458
+ border: "none",
2459
+ color,
2460
+ cursor: "pointer",
2461
+ fontFamily: "inherit",
2462
+ fontSize: "0.88rem",
2463
+ fontWeight: 500,
2464
+ display: "block",
2465
+ width: "100%",
2466
+ textAlign: "center",
2467
+ padding: "12px 0 0"
2468
+ });
2469
+ var WALLET_EMOJIS = {
2470
+ metamask: "\u{1F98A}",
2471
+ rabby: "\u{1F430}",
2472
+ ora: "\u2666\uFE0F",
2473
+ phantom: "\u{1F47B}"
2474
+ };
2475
+ function WalletPickerScreen({
2476
+ providers,
2477
+ onSelectProvider,
2478
+ onBack
2479
+ }) {
2480
+ const { tokens } = useSwypeConfig();
2481
+ const [hoveredId, setHoveredId] = react.useState(null);
2482
+ const displayProviders = providers.length > 0 ? providers : [
2483
+ { id: "metamask", name: "MetaMask" },
2484
+ { id: "rabby", name: "Rabby" },
2485
+ { id: "ora", name: "Ora" },
2486
+ { id: "phantom", name: "Phantom" }
2487
+ ];
2488
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2489
+ ScreenLayout,
2490
+ {
2491
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2492
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: hintStyle2(tokens.textMuted), children: "You'll set your deposit limit in your wallet app." }),
2493
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2494
+ ] }),
2495
+ children: [
2496
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: "Set up Swype", onBack }),
2497
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle4(tokens.text), children: "Where are your stablecoins?" }),
2498
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle4(tokens.textSecondary), children: "Select the wallet you want to deposit from" }),
2499
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: gridStyle, children: [
2500
+ displayProviders.map((p) => {
2501
+ const emoji = WALLET_EMOJIS[p.name.toLowerCase()] ?? p.name.charAt(0);
2502
+ const isHovered = hoveredId === p.id;
2503
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2504
+ "button",
2505
+ {
2506
+ onClick: () => onSelectProvider(p.id),
2507
+ onMouseEnter: () => setHoveredId(p.id),
2508
+ onMouseLeave: () => setHoveredId(null),
2509
+ style: cardStyle(tokens, isHovered),
2510
+ children: [
2511
+ "logoURI" in p && p.logoURI ? /* @__PURE__ */ jsxRuntime.jsx(
2512
+ "img",
2513
+ {
2514
+ src: p.logoURI,
2515
+ alt: p.name,
2516
+ style: logoImgStyle
2517
+ }
2518
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: emojiStyle, children: emoji }),
2519
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: nameStyle2(tokens.text), children: p.name })
2520
+ ]
2521
+ },
2522
+ p.id
2523
+ );
2524
+ }),
2525
+ /* @__PURE__ */ jsxRuntime.jsxs(
2526
+ "button",
2527
+ {
2528
+ onClick: () => onSelectProvider("other"),
2529
+ onMouseEnter: () => setHoveredId("other"),
2530
+ onMouseLeave: () => setHoveredId(null),
2531
+ style: cardStyle(tokens, hoveredId === "other"),
2532
+ children: [
2533
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { margin: "0 auto" }, children: /* @__PURE__ */ jsxRuntime.jsx(
2534
+ "path",
2535
+ {
2536
+ 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",
2537
+ fill: tokens.textMuted
2538
+ }
2539
+ ) }),
2540
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: nameStyle2(tokens.text), children: "Other" })
2541
+ ]
2542
+ }
2543
+ )
2544
+ ] })
2545
+ ]
2546
+ }
2547
+ );
2548
+ }
2549
+ var headingStyle4 = (color) => ({
2550
+ fontSize: "1.35rem",
2551
+ fontWeight: 700,
2552
+ letterSpacing: "-0.02em",
2553
+ color,
2554
+ margin: "8px 0 4px"
2555
+ });
2556
+ var subtitleStyle4 = (color) => ({
2557
+ fontSize: "0.88rem",
2558
+ color,
2559
+ margin: "0 0 24px"
2560
+ });
2561
+ var gridStyle = {
2562
+ display: "grid",
2563
+ gridTemplateColumns: "1fr 1fr",
2564
+ gap: 12
2565
+ };
2566
+ var cardStyle = (tokens, hovered) => ({
2567
+ display: "flex",
2568
+ flexDirection: "column",
2569
+ alignItems: "center",
2570
+ justifyContent: "center",
2571
+ gap: 8,
2572
+ padding: "20px 12px",
2573
+ background: hovered ? tokens.bgHover : tokens.bgInput,
2574
+ border: `1.5px solid ${tokens.border}`,
2575
+ borderRadius: 16,
2576
+ cursor: "pointer",
2577
+ fontFamily: "inherit",
2578
+ transition: "background 0.15s ease",
2579
+ outline: "none"
2580
+ });
2581
+ var emojiStyle = {
2582
+ fontSize: "1.75rem",
2583
+ lineHeight: 1
2584
+ };
2585
+ var logoImgStyle = {
2586
+ width: 32,
2587
+ height: 32,
2588
+ borderRadius: 8,
2589
+ objectFit: "contain"
2590
+ };
2591
+ var nameStyle2 = (color) => ({
2592
+ fontSize: "0.88rem",
2593
+ fontWeight: 600,
2594
+ color
2595
+ });
2596
+ var hintStyle2 = (color) => ({
2597
+ textAlign: "center",
2598
+ fontSize: "0.82rem",
2599
+ color,
2600
+ margin: "0 0 4px"
2601
+ });
2602
+ var DEFAULT_MAX = 500;
2603
+ var ABSOLUTE_MIN = 1;
2604
+ function buildTicks(min, max) {
2605
+ if (max <= min) return [min];
2606
+ const range = max - min;
2607
+ const candidates = [1, 2, 5, 10, 25, 50, 100, 250];
2608
+ const step = candidates.find((s) => range / s <= 5) ?? Math.ceil(range / 4);
2609
+ const ticks = [];
2610
+ for (let v = min; v <= max; v += step) {
2611
+ ticks.push(Math.round(v * 100) / 100);
2612
+ }
2613
+ if (ticks[ticks.length - 1] !== max) ticks.push(max);
2614
+ return ticks;
2615
+ }
2616
+ function SetupScreen({
2617
+ availableBalance,
2618
+ tokenCount,
2619
+ sourceName,
2620
+ onSetupOneTap,
2621
+ onBack,
2622
+ onLogout,
2623
+ loading,
2624
+ error
2625
+ }) {
2626
+ const { tokens } = useSwypeConfig();
2627
+ const effectiveMax = Math.min(DEFAULT_MAX, availableBalance > 0 ? availableBalance : DEFAULT_MAX);
2628
+ const effectiveMin = Math.min(ABSOLUTE_MIN, effectiveMax);
2629
+ const sliderStep = effectiveMax <= 10 ? 0.5 : effectiveMax <= 50 ? 1 : 5;
2630
+ const ticks = buildTicks(effectiveMin, effectiveMax);
2631
+ const [limit, setLimit] = react.useState(() => Math.min(100, effectiveMax));
2632
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2633
+ ScreenLayout,
2634
+ {
2635
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2636
+ /* @__PURE__ */ jsxRuntime.jsx(
2637
+ PrimaryButton,
2638
+ {
2639
+ onClick: () => onSetupOneTap(limit),
2640
+ disabled: loading,
2641
+ loading,
2642
+ children: "Set up One-Tap"
2643
+ }
2644
+ ),
2645
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2646
+ ] }),
2647
+ children: [
2648
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: "Swype Setup", badge: "Simple", onBack, right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
2649
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle5(tokens.text), children: "Set up One-Tap deposits" }),
2650
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle5(tokens.textSecondary), children: "Set your limit for instant deposits. Like a contactless card \u2014 you choose the max." }),
2651
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle3(tokens), children: error }),
2652
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceRowStyle, children: [
2653
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceLeftStyle, children: [
2654
+ /* @__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: [
2655
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", fill: "currentColor" }),
2656
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: "12", y: "16", textAnchor: "middle", fontSize: "12", fill: "#fff", fontWeight: "700", children: "$" })
2657
+ ] }) }),
2658
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2659
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: balanceLabelStyle(tokens.textMuted), children: "Available" }),
2660
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceValueStyle(tokens.text), children: [
2661
+ "$",
2662
+ availableBalance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
2663
+ ] })
2664
+ ] })
2665
+ ] }),
2666
+ tokenCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenBadgeStyle(tokens), children: [
2667
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDotStyle(tokens.accent) }),
2668
+ tokenCount,
2669
+ " ",
2670
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: chevronStyle, children: ">" })
2671
+ ] })
2672
+ ] }),
2673
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: limitSectionStyle, children: [
2674
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: limitLabelStyle(tokens.textMuted), children: "Your One-Tap limit" }),
2675
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: limitValueStyle(tokens.text), children: [
2676
+ "$",
2677
+ limit
2678
+ ] }),
2679
+ /* @__PURE__ */ jsxRuntime.jsx(
2680
+ LimitSlider,
2681
+ {
2682
+ value: limit,
2683
+ min: effectiveMin,
2684
+ max: effectiveMax,
2685
+ step: sliderStep,
2686
+ ticks,
2687
+ onChange: setLimit
2688
+ }
2689
+ )
2690
+ ] }),
2691
+ /* @__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." }) }),
2692
+ /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", style: linkStyle(tokens.accent), children: [
2693
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", style: { marginRight: 6 }, children: [
2694
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2" }),
2695
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 16v-4M12 8h.01", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
2696
+ ] }),
2697
+ "How does this work?"
2698
+ ] })
2699
+ ]
2700
+ }
2701
+ );
2702
+ }
2703
+ var headingStyle5 = (color) => ({
2704
+ fontSize: "1.3rem",
2705
+ fontWeight: 700,
2706
+ letterSpacing: "-0.02em",
2707
+ color,
2708
+ margin: "8px 0 4px"
2709
+ });
2710
+ var subtitleStyle5 = (color) => ({
2711
+ fontSize: "0.86rem",
2712
+ color,
2713
+ margin: "0 0 24px",
2714
+ lineHeight: 1.5
2715
+ });
2716
+ var errorBannerStyle3 = (tokens) => ({
2717
+ background: tokens.errorBg,
2718
+ border: `1px solid ${tokens.error}66`,
2719
+ borderRadius: 16,
2720
+ padding: "11px 14px",
2721
+ color: tokens.error,
2722
+ fontSize: "0.84rem",
2723
+ marginBottom: 14,
2724
+ lineHeight: 1.5
2725
+ });
2726
+ var balanceRowStyle = {
2727
+ display: "flex",
2728
+ alignItems: "center",
2729
+ justifyContent: "space-between",
2730
+ marginBottom: 24
2731
+ };
2732
+ var balanceLeftStyle = {
2733
+ display: "flex",
2734
+ alignItems: "center",
2735
+ gap: 10
2736
+ };
2737
+ var coinIconStyle = (color) => ({
2738
+ color,
2739
+ display: "flex",
2740
+ alignItems: "center"
2741
+ });
2742
+ var balanceLabelStyle = (color) => ({
2743
+ fontSize: "0.72rem",
2744
+ color,
2745
+ fontWeight: 500
2746
+ });
2747
+ var balanceValueStyle = (color) => ({
2748
+ fontSize: "1.1rem",
2749
+ fontWeight: 700,
2750
+ color
2751
+ });
2752
+ var tokenBadgeStyle = (tokens) => ({
2753
+ display: "flex",
2754
+ alignItems: "center",
2755
+ gap: 4,
2756
+ fontSize: "0.78rem",
2757
+ color: tokens.textMuted,
2758
+ border: `1px solid ${tokens.border}`,
2759
+ borderRadius: 999,
2760
+ padding: "4px 10px"
2761
+ });
2762
+ var tokenDotStyle = (color) => ({
2763
+ width: 8,
2764
+ height: 8,
2765
+ borderRadius: "50%",
2766
+ background: color,
2767
+ display: "inline-block"
2768
+ });
2769
+ var chevronStyle = { fontSize: "0.68rem", marginLeft: 2 };
2770
+ var limitSectionStyle = {
2771
+ textAlign: "center",
2772
+ marginBottom: 24
2773
+ };
2774
+ var limitLabelStyle = (color) => ({
2775
+ fontSize: "0.8rem",
2776
+ color,
2777
+ marginBottom: 4
2778
+ });
2779
+ var limitValueStyle = (color) => ({
2780
+ fontSize: "2.2rem",
2781
+ fontWeight: 700,
2782
+ color,
2783
+ marginBottom: 12
2784
+ });
2785
+ var bannerWrapStyle = { marginBottom: 16 };
2786
+ var linkStyle = (color) => ({
2787
+ background: "transparent",
2788
+ border: "none",
2789
+ color,
2790
+ cursor: "pointer",
2791
+ fontFamily: "inherit",
2792
+ fontSize: "0.82rem",
2793
+ fontWeight: 500,
2794
+ display: "flex",
2795
+ alignItems: "center",
2796
+ padding: 0,
2797
+ marginBottom: 16
2798
+ });
2799
+ function SetupStatusScreen({
2800
+ complete,
2801
+ limit,
2802
+ tokensApproved,
2803
+ currentStepLabel,
2804
+ merchantName,
2805
+ onContinue,
2806
+ onLogout,
2807
+ error
2808
+ }) {
2809
+ const { tokens } = useSwypeConfig();
2810
+ const steps = complete ? [
2811
+ {
2812
+ label: "One-Tap ready",
2813
+ detail: `$${limit} limit \xB7 ${tokensApproved} token${tokensApproved !== 1 ? "s" : ""} approved`,
2814
+ status: "complete"
2815
+ },
2816
+ { label: "Done", status: "complete" }
2817
+ ] : [
2818
+ {
2819
+ label: currentStepLabel ?? "Approving tokens",
2820
+ status: "active"
2821
+ },
2822
+ { label: "Done", status: "pending" }
2823
+ ];
2824
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2825
+ ScreenLayout,
2826
+ {
2827
+ footer: complete ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2828
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onContinue, children: merchantName ? `Return to ${merchantName}` : "Continue" }),
2829
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: swipeHintStyle(tokens.textMuted), children: "Swipe to deposit \u2014 no approvals needed." })
2830
+ ] }) : void 0,
2831
+ children: [
2832
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
2833
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle4, children: [
2834
+ complete ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2835
+ /* @__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 }) }) }),
2836
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "You're all set!" })
2837
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2838
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
2839
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle6(tokens.text), children: "Setting up One-Tap..." })
2840
+ ] }),
2841
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle4(tokens), children: error }),
2842
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: stepsWrapStyle, children: /* @__PURE__ */ jsxRuntime.jsx(StepList, { steps }) }),
2843
+ !complete && /* @__PURE__ */ jsxRuntime.jsx("p", { style: waitHintStyle(tokens.textMuted), children: "Usually takes a few seconds" }),
2844
+ complete && /* @__PURE__ */ jsxRuntime.jsx("p", { style: readyHintStyle(tokens.textSecondary), children: "You can now deposit instantly from any partner app." })
2845
+ ] })
2846
+ ]
2847
+ }
2848
+ );
2849
+ }
2850
+ var contentStyle4 = {
2851
+ flex: 1,
2852
+ display: "flex",
2853
+ flexDirection: "column",
2854
+ alignItems: "center",
2855
+ justifyContent: "center",
2856
+ textAlign: "center",
2857
+ padding: "0 24px"
2858
+ };
2859
+ var headingStyle6 = (color) => ({
2860
+ fontSize: "1.45rem",
2861
+ fontWeight: 700,
2862
+ letterSpacing: "-0.02em",
2863
+ color,
2864
+ margin: "20px 0 16px"
2865
+ });
2866
+ var errorBannerStyle4 = (tokens) => ({
2867
+ background: tokens.errorBg,
2868
+ border: `1px solid ${tokens.error}66`,
2869
+ borderRadius: 16,
2870
+ padding: "11px 14px",
2871
+ color: tokens.error,
2872
+ fontSize: "0.84rem",
2873
+ marginBottom: 14,
2874
+ lineHeight: 1.5,
2875
+ width: "100%",
2876
+ textAlign: "left"
2877
+ });
2878
+ var stepsWrapStyle = {
2879
+ width: "100%",
2880
+ maxWidth: 280,
2881
+ textAlign: "left",
2882
+ marginBottom: 16
2883
+ };
2884
+ var waitHintStyle = (color) => ({
2885
+ fontSize: "0.82rem",
2886
+ color,
2887
+ margin: 0
2888
+ });
2889
+ var readyHintStyle = (color) => ({
2890
+ fontSize: "0.88rem",
2891
+ color,
2892
+ margin: "8px 0 0",
2893
+ lineHeight: 1.5,
2894
+ maxWidth: 280
2895
+ });
2896
+ var swipeHintStyle = (color) => ({
2897
+ textAlign: "center",
2898
+ fontSize: "0.8rem",
2899
+ color,
2900
+ margin: "12px 0 0"
2901
+ });
2902
+ var MIN_DEPOSIT = 1;
2903
+ function DepositScreen({
2904
+ merchantName,
2905
+ sourceName,
2906
+ sourceAddress,
2907
+ sourceVerified,
2908
+ availableBalance,
2909
+ remainingLimit,
2910
+ tokenCount,
2911
+ initialAmount,
2912
+ estimatedFeePct,
2913
+ estimatedFeeUsd,
2914
+ processing,
2915
+ error,
2916
+ onDeposit,
2917
+ onChangeSource,
2918
+ onSwitchWallet,
2919
+ onBack,
2920
+ onLogout
2921
+ }) {
2922
+ const { tokens } = useSwypeConfig();
2923
+ const [amount, setAmount] = react.useState(initialAmount);
2924
+ const sliderMax = Math.min(remainingLimit, availableBalance, 500);
2925
+ const isLowBalance = availableBalance < MIN_DEPOSIT;
2926
+ const canDeposit = amount >= MIN_DEPOSIT && amount <= remainingLimit && !isLowBalance && !processing;
2927
+ const headerTitle = merchantName ? `Deposit to ${merchantName}` : "Deposit";
2928
+ if (isLowBalance) {
2929
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2930
+ ScreenLayout,
2931
+ {
2932
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2933
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onSwitchWallet, children: "Switch wallet" }),
2934
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: switchHintStyle(tokens.textMuted), children: "Use a different wallet with more balance" }),
2935
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: outlineBtnWrapStyle, children: /* @__PURE__ */ jsxRuntime.jsx(OutlineButton, { onClick: onBack, children: "Back to deposit options" }) }),
2936
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2937
+ ] }),
2938
+ children: [
2939
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: headerTitle, onBack, right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
2940
+ /* @__PURE__ */ jsxRuntime.jsx(
2941
+ SourceCard,
2942
+ {
2943
+ name: sourceName,
2944
+ address: sourceAddress,
2945
+ verified: sourceVerified,
2946
+ onChangeSource
2947
+ }
2948
+ ),
2949
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: amountDisplayStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: amountStyle({ ...tokens, dimmed: true }), children: [
2950
+ "$",
2951
+ amount.toFixed(2)
2952
+ ] }) }),
2953
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceRowStyle2, children: [
2954
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceLeftStyle2, children: [
2955
+ /* @__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: [
2956
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", fill: "currentColor" }),
2957
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: "12", y: "16", textAnchor: "middle", fontSize: "12", fill: "#fff", fontWeight: "700", children: "$" })
2958
+ ] }) }),
2959
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2960
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: balanceLabelStyle2(tokens.textMuted), children: "Available" }),
2961
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { ...balanceAmountStyle, color: tokens.warning }, children: [
2962
+ "$",
2963
+ availableBalance.toFixed(2)
2964
+ ] })
2965
+ ] })
2966
+ ] }),
2967
+ /* @__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 }) })
2968
+ ] }),
2969
+ /* @__PURE__ */ jsxRuntime.jsxs(WarningBanner, { title: "Not enough funds", children: [
2970
+ "Your wallet balance is $",
2971
+ availableBalance.toFixed(2),
2972
+ " \u2014 you need at least $",
2973
+ MIN_DEPOSIT.toFixed(2),
2974
+ " to deposit via One-Tap."
2975
+ ] })
2976
+ ]
2977
+ }
2978
+ );
2979
+ }
2980
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2981
+ ScreenLayout,
2982
+ {
2983
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2984
+ /* @__PURE__ */ jsxRuntime.jsxs(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: [
2985
+ "Deposit $",
2986
+ amount.toFixed(2)
2987
+ ] }),
2988
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: noApprovalStyle(tokens.textMuted), children: "No approval needed \xB7 within your One-Tap limit" }),
2989
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: routeStyle(tokens.textMuted), children: [
2990
+ "From ",
2991
+ sourceName,
2992
+ " ",
2993
+ merchantName ? `\u2192 ${merchantName}` : ""
2994
+ ] }),
2995
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
2996
+ ] }),
2997
+ children: [
2998
+ /* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: headerTitle, badge: "Simple", onBack, right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
2999
+ /* @__PURE__ */ jsxRuntime.jsx(
3000
+ SourceCard,
3001
+ {
3002
+ name: sourceName,
3003
+ address: sourceAddress,
3004
+ verified: sourceVerified,
3005
+ onChangeSource
3006
+ }
3007
+ ),
3008
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: amountDisplayStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: amountStyle(tokens), children: [
3009
+ "$",
3010
+ amount.toFixed(2)
3011
+ ] }) }),
3012
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceRowStyle2, children: [
3013
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceLeftStyle2, children: [
3014
+ /* @__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: [
3015
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", fill: "currentColor" }),
3016
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: "12", y: "16", textAnchor: "middle", fontSize: "12", fill: "#fff", fontWeight: "700", children: "$" })
3017
+ ] }) }),
3018
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3019
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceLabelStyle2(tokens.textMuted), children: [
3020
+ "Paying from ",
3021
+ sourceName
3022
+ ] }),
3023
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceAmountStyle, children: [
3024
+ "$",
3025
+ availableBalance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
3026
+ ] })
3027
+ ] })
3028
+ ] }),
3029
+ tokenCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenBadgeStyle2(tokens), children: [
3030
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDotStyle2(tokens.accent) }),
3031
+ tokenCount,
3032
+ " ",
3033
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: chevronStyle2, children: ">" })
3034
+ ] })
3035
+ ] }),
3036
+ /* @__PURE__ */ jsxRuntime.jsx(
3037
+ LimitSlider,
3038
+ {
3039
+ value: amount,
3040
+ min: MIN_DEPOSIT,
3041
+ max: sliderMax > MIN_DEPOSIT ? sliderMax : 20,
3042
+ step: 0.5,
3043
+ ticks: [MIN_DEPOSIT, 5, 10, 20].filter((t) => t <= sliderMax || t <= 20),
3044
+ onChange: setAmount
3045
+ }
3046
+ ),
3047
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: detailsStyle, children: [
3048
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: detailRowStyle(tokens.textMuted), children: [
3049
+ "Remaining limit: ",
3050
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { style: { color: tokens.text }, children: [
3051
+ "$",
3052
+ remainingLimit.toFixed(2)
3053
+ ] })
3054
+ ] }),
3055
+ estimatedFeeUsd != null && estimatedFeePct != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: detailRowStyle(tokens.textMuted), children: [
3056
+ "Fee: ~$",
3057
+ estimatedFeeUsd.toFixed(2),
3058
+ " (",
3059
+ estimatedFeePct.toFixed(1),
3060
+ "%)"
3061
+ ] })
3062
+ ] }),
3063
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle5(tokens), children: error })
3064
+ ]
3065
+ }
3066
+ );
3067
+ }
3068
+ var amountDisplayStyle = {
3069
+ textAlign: "center",
3070
+ padding: "20px 0 8px"
3071
+ };
3072
+ var amountStyle = (opts) => ({
3073
+ fontSize: "2.5rem",
3074
+ fontWeight: 700,
3075
+ color: opts.dimmed ? "#ccc" : opts.text ?? "#12222b",
3076
+ letterSpacing: "-0.02em"
3077
+ });
3078
+ var balanceRowStyle2 = {
3079
+ display: "flex",
3080
+ alignItems: "center",
3081
+ justifyContent: "space-between",
3082
+ marginBottom: 16
3083
+ };
3084
+ var balanceLeftStyle2 = {
3085
+ display: "flex",
3086
+ alignItems: "center",
3087
+ gap: 10
3088
+ };
3089
+ var coinIconStyle2 = (color) => ({
3090
+ color,
3091
+ display: "flex",
3092
+ alignItems: "center"
3093
+ });
3094
+ var balanceLabelStyle2 = (color) => ({
3095
+ fontSize: "0.72rem",
3096
+ color,
3097
+ fontWeight: 500
3098
+ });
3099
+ var balanceAmountStyle = {
3100
+ fontSize: "1rem",
3101
+ fontWeight: 700
3102
+ };
3103
+ var tokenBadgeStyle2 = (tokens) => ({
3104
+ display: "flex",
3105
+ alignItems: "center",
3106
+ gap: 4,
3107
+ fontSize: "0.78rem",
3108
+ color: tokens.textMuted,
3109
+ border: `1px solid ${tokens.border}`,
3110
+ borderRadius: 999,
3111
+ padding: "4px 10px"
3112
+ });
3113
+ var tokenDotStyle2 = (color) => ({
3114
+ width: 8,
3115
+ height: 8,
3116
+ borderRadius: "50%",
3117
+ background: color,
3118
+ display: "inline-block"
3119
+ });
3120
+ var chevronStyle2 = { fontSize: "0.68rem", marginLeft: 2 };
3121
+ var detailsStyle = {
3122
+ textAlign: "center",
3123
+ marginTop: 12,
3124
+ marginBottom: 8
3125
+ };
3126
+ var detailRowStyle = (color) => ({
3127
+ fontSize: "0.8rem",
3128
+ color,
3129
+ marginBottom: 4
3130
+ });
3131
+ var errorBannerStyle5 = (tokens) => ({
3132
+ background: tokens.errorBg,
3133
+ border: `1px solid ${tokens.error}66`,
3134
+ borderRadius: 16,
3135
+ padding: "11px 14px",
3136
+ color: tokens.error,
3137
+ fontSize: "0.84rem",
3138
+ marginTop: 8,
3139
+ lineHeight: 1.5
3140
+ });
3141
+ var noApprovalStyle = (color) => ({
3142
+ textAlign: "center",
3143
+ fontSize: "0.78rem",
3144
+ color,
3145
+ margin: "12px 0 2px"
3146
+ });
3147
+ var routeStyle = (color) => ({
3148
+ textAlign: "center",
3149
+ fontSize: "0.75rem",
3150
+ color,
3151
+ margin: "0 0 4px"
3152
+ });
3153
+ var switchHintStyle = (color) => ({
3154
+ textAlign: "center",
3155
+ fontSize: "0.8rem",
3156
+ color,
3157
+ margin: "10px 0"
3158
+ });
3159
+ var outlineBtnWrapStyle = {
3160
+ marginBottom: 8
3161
+ };
3162
+ function SuccessScreen({
3163
+ amount,
3164
+ currency,
3165
+ merchantName,
3166
+ sourceName,
3167
+ remainingLimit,
3168
+ onDone,
3169
+ onLogout,
3170
+ onIncreaseLimits,
3171
+ onManageAccount
3172
+ }) {
3173
+ const { tokens } = useSwypeConfig();
3174
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3175
+ ScreenLayout,
3176
+ {
3177
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3178
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onDone, children: "Done" }),
3179
+ onManageAccount && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onManageAccount, style: manageStyle(tokens.textMuted), children: "Manage Swype account \u2192" }),
3180
+ /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
3181
+ ] }),
3182
+ children: [
3183
+ /* @__PURE__ */ jsxRuntime.jsx(
3184
+ ScreenHeader,
3185
+ {
3186
+ right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout })
3187
+ }
3188
+ ),
3189
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle5, children: [
3190
+ /* @__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 }) }) }),
3191
+ /* @__PURE__ */ jsxRuntime.jsxs("h2", { style: headingStyle7(tokens.text), children: [
3192
+ "$",
3193
+ amount.toFixed(2),
3194
+ " deposited"
3195
+ ] }),
3196
+ merchantName && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle6(tokens.textSecondary), children: [
3197
+ "to ",
3198
+ merchantName
3199
+ ] }),
3200
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryCardStyle(tokens), children: [
3201
+ sourceName && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3202
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryLabelStyle(tokens.textMuted), children: "From" }),
3203
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryValueStyle(tokens.text), children: sourceName })
3204
+ ] }),
3205
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3206
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryLabelStyle(tokens.textMuted), children: "Time" }),
3207
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryValueStyle(tokens.text), children: "just now" })
3208
+ ] }),
3209
+ remainingLimit != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
3210
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryLabelStyle(tokens.textMuted), children: "Remaining limit" }),
3211
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { ...summaryValueStyle(tokens.text), color: tokens.accent }, children: [
3212
+ "$",
3213
+ remainingLimit.toFixed(2)
3214
+ ] })
3215
+ ] })
3216
+ ] }),
3217
+ onIncreaseLimits && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: upsellCardStyle(tokens), children: [
3218
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: upsellHeaderStyle, children: [
3219
+ /* @__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" }) }),
3220
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Want higher limits?" })
3221
+ ] }),
3222
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: upsellBodyStyle(tokens.textSecondary), children: "Increase your One-Tap limit to deposit more without re-approving." }),
3223
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onIncreaseLimits, style: upsellLinkStyle(tokens.accent), children: "Increase One-Tap limit" })
3224
+ ] })
3225
+ ] })
3226
+ ]
3227
+ }
3228
+ );
3229
+ }
3230
+ var contentStyle5 = {
3231
+ flex: 1,
3232
+ display: "flex",
3233
+ flexDirection: "column",
3234
+ alignItems: "center",
3235
+ paddingTop: 16
3236
+ };
3237
+ var headingStyle7 = (color) => ({
3238
+ fontSize: "1.5rem",
3239
+ fontWeight: 700,
3240
+ letterSpacing: "-0.02em",
3241
+ color,
3242
+ margin: "20px 0 4px"
3243
+ });
3244
+ var subtitleStyle6 = (color) => ({
3245
+ fontSize: "0.9rem",
3246
+ color,
3247
+ margin: "0 0 20px"
3248
+ });
3249
+ var summaryCardStyle = (tokens) => ({
3250
+ width: "100%",
3251
+ padding: "14px 16px",
3252
+ background: tokens.bgInput,
3253
+ border: `1px solid ${tokens.border}`,
3254
+ borderRadius: 20,
3255
+ marginBottom: 16
3256
+ });
3257
+ var summaryRowStyle = {
3258
+ display: "flex",
3259
+ justifyContent: "space-between",
3260
+ alignItems: "center",
3261
+ padding: "6px 0"
3262
+ };
3263
+ var summaryLabelStyle = (color) => ({
3264
+ fontSize: "0.84rem",
3265
+ color
3266
+ });
3267
+ var summaryValueStyle = (color) => ({
3268
+ fontSize: "0.88rem",
3269
+ fontWeight: 600,
3270
+ color
3271
+ });
3272
+ var upsellCardStyle = (tokens) => ({
3273
+ width: "100%",
3274
+ padding: "16px",
3275
+ background: tokens.bgInput,
3276
+ border: `1px solid ${tokens.border}`,
3277
+ borderRadius: 20,
3278
+ marginBottom: 16
3279
+ });
3280
+ var upsellHeaderStyle = {
3281
+ display: "flex",
3282
+ alignItems: "center",
3283
+ fontSize: "0.88rem",
3284
+ marginBottom: 4
3285
+ };
3286
+ var upsellBodyStyle = (color) => ({
3287
+ fontSize: "0.8rem",
3288
+ color,
3289
+ margin: "4px 0 10px",
3290
+ lineHeight: 1.5
3291
+ });
3292
+ var upsellLinkStyle = (color) => ({
3293
+ background: "transparent",
3294
+ border: "none",
3295
+ color,
3296
+ fontWeight: 600,
3297
+ fontSize: "0.84rem",
3298
+ cursor: "pointer",
3299
+ fontFamily: "inherit",
3300
+ padding: 0
3301
+ });
3302
+ var manageStyle = (color) => ({
3303
+ background: "transparent",
3304
+ border: "none",
3305
+ color,
3306
+ cursor: "pointer",
3307
+ fontFamily: "inherit",
3308
+ fontSize: "0.84rem",
3309
+ fontWeight: 500,
3310
+ display: "block",
3311
+ width: "100%",
3312
+ textAlign: "center",
3313
+ padding: "12px 0 0"
3314
+ });
3315
+ var ACTIVE_CREDENTIAL_STORAGE_KEY = "swype_active_credential_id";
3316
+ var MIN_SEND_AMOUNT_USD = 0.25;
3317
+ function computeSmartDefaults(accts, transferAmount) {
3318
+ if (accts.length === 0) return null;
3319
+ for (const acct of accts) {
3320
+ for (const wallet of acct.wallets) {
3321
+ if (wallet.status === "ACTIVE") {
3322
+ const bestSource = wallet.sources.find(
3323
+ (s) => s.balance.available.amount >= transferAmount
3324
+ );
3325
+ if (bestSource) {
3326
+ return { accountId: acct.id, walletId: wallet.id };
3327
+ }
3328
+ }
3329
+ }
3330
+ }
3331
+ let bestAccount = null;
3332
+ let bestWallet = null;
3333
+ let bestBalance = -1;
3334
+ let bestIsActive = false;
3335
+ for (const acct of accts) {
3336
+ for (const wallet of acct.wallets) {
3337
+ const walletBal = wallet.balance.available.amount;
3338
+ const isActive = wallet.status === "ACTIVE";
3339
+ if (walletBal > bestBalance || walletBal === bestBalance && isActive && !bestIsActive) {
3340
+ bestBalance = walletBal;
3341
+ bestAccount = acct;
3342
+ bestWallet = wallet;
3343
+ bestIsActive = isActive;
3344
+ }
3345
+ }
3346
+ }
3347
+ if (bestAccount) {
3348
+ return {
3349
+ accountId: bestAccount.id,
3350
+ walletId: bestWallet?.id ?? null
3351
+ };
3352
+ }
3353
+ return { accountId: accts[0].id, walletId: null };
3354
+ }
3355
+ function parseRawBalance(rawBalance, decimals) {
3356
+ const parsed = Number(rawBalance);
3357
+ if (!Number.isFinite(parsed)) return 0;
3358
+ return parsed / 10 ** decimals;
3359
+ }
3360
+ function buildSelectSourceChoices(options) {
3361
+ const chainChoices = [];
3362
+ const chainIndexByName = /* @__PURE__ */ new Map();
3363
+ for (const option of options) {
3364
+ const { chainName, tokenSymbol } = option;
3365
+ const balance = parseRawBalance(option.rawBalance, option.decimals);
3366
+ let chainChoice;
3367
+ const existingIdx = chainIndexByName.get(chainName);
3368
+ if (existingIdx === void 0) {
3369
+ chainChoice = { chainName, balance: 0, tokens: [] };
3370
+ chainIndexByName.set(chainName, chainChoices.length);
3371
+ chainChoices.push(chainChoice);
3372
+ } else {
3373
+ chainChoice = chainChoices[existingIdx];
3374
+ }
3375
+ chainChoice.balance += balance;
3376
+ const existing = chainChoice.tokens.find((t) => t.tokenSymbol === tokenSymbol);
3377
+ if (existing) {
3378
+ existing.balance += balance;
3379
+ } else {
3380
+ chainChoice.tokens.push({ tokenSymbol, balance });
3381
+ }
3382
+ }
3383
+ return chainChoices;
3384
+ }
3385
+ function SwypePayment({
3386
+ destination,
3387
+ onComplete,
3388
+ onError,
3389
+ useWalletConnector,
3390
+ idempotencyKey,
3391
+ merchantAuthorization,
3392
+ merchantName,
3393
+ onBack
3394
+ }) {
3395
+ const { apiBaseUrl, tokens, depositAmount } = useSwypeConfig();
3396
+ const { ready, authenticated, user, logout, getAccessToken } = reactAuth.usePrivy();
3397
+ const {
3398
+ sendCode: sendEmailCode,
3399
+ loginWithCode: loginWithEmailCode,
3400
+ state: emailLoginState
3401
+ } = reactAuth.useLoginWithEmail();
3402
+ const {
3403
+ sendCode: sendSmsCode,
3404
+ loginWithCode: loginWithSmsCode,
3405
+ state: smsLoginState
3406
+ } = reactAuth.useLoginWithSms();
3407
+ const [step, setStep] = react.useState("login");
2260
3408
  const [error, setError] = react.useState(null);
2261
3409
  const [providers, setProviders] = react.useState([]);
2262
3410
  const [accounts, setAccounts] = react.useState([]);
@@ -2269,10 +3417,6 @@ function SwypePayment({
2269
3417
  const [amount, setAmount] = react.useState(
2270
3418
  depositAmount != null ? depositAmount.toString() : ""
2271
3419
  );
2272
- const [advancedSettings, setAdvancedSettings] = react.useState({
2273
- asset: null,
2274
- chain: null
2275
- });
2276
3420
  const [transfer, setTransfer] = react.useState(null);
2277
3421
  const [creatingTransfer, setCreatingTransfer] = react.useState(false);
2278
3422
  const [registeringPasskey, setRegisteringPasskey] = react.useState(false);
@@ -2281,10 +3425,11 @@ function SwypePayment({
2281
3425
  return window.localStorage.getItem(ACTIVE_CREDENTIAL_STORAGE_KEY);
2282
3426
  });
2283
3427
  const [authInput, setAuthInput] = react.useState("");
2284
- const [verificationTarget, setVerificationTarget] = react.useState(
2285
- null
2286
- );
3428
+ const [verificationTarget, setVerificationTarget] = react.useState(null);
2287
3429
  const [otpCode, setOtpCode] = react.useState("");
3430
+ const [oneTapLimit, setOneTapLimit] = react.useState(100);
3431
+ const [setupComplete, setSetupComplete] = react.useState(false);
3432
+ const [setupStepLabel, setSetupStepLabel] = react.useState(void 0);
2288
3433
  const [mobileFlow, setMobileFlow] = react.useState(false);
2289
3434
  const pollingTransferIdRef = react.useRef(null);
2290
3435
  const mobileSigningTransferIdRef = react.useRef(null);
@@ -2310,9 +3455,7 @@ function SwypePayment({
2310
3455
  const activeOtpStatus = verificationTarget?.kind === "email" ? emailLoginState.status : verificationTarget?.kind === "phone" ? smsLoginState.status : "initial";
2311
3456
  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
3457
  react.useEffect(() => {
2313
- if (activeOtpErrorMessage) {
2314
- setError(activeOtpErrorMessage);
2315
- }
3458
+ if (activeOtpErrorMessage) setError(activeOtpErrorMessage);
2316
3459
  }, [activeOtpErrorMessage]);
2317
3460
  const handleSendLoginCode = react.useCallback(async () => {
2318
3461
  const normalizedIdentifier = normalizeAuthIdentifier(authInput);
@@ -2329,9 +3472,9 @@ function SwypePayment({
2329
3472
  await sendSmsCode({ phoneNumber: normalizedIdentifier.value });
2330
3473
  }
2331
3474
  setVerificationTarget(normalizedIdentifier);
3475
+ setStep("otp-verify");
2332
3476
  } catch (err) {
2333
- const msg = err instanceof Error ? err.message : "Failed to send verification code";
2334
- setError(msg);
3477
+ setError(err instanceof Error ? err.message : "Failed to send verification code");
2335
3478
  }
2336
3479
  }, [authInput, sendEmailCode, sendSmsCode]);
2337
3480
  const handleVerifyLoginCode = react.useCallback(async () => {
@@ -2349,8 +3492,7 @@ function SwypePayment({
2349
3492
  await loginWithSmsCode({ code: trimmedCode });
2350
3493
  }
2351
3494
  } catch (err) {
2352
- const msg = err instanceof Error ? err.message : "Failed to verify code";
2353
- setError(msg);
3495
+ setError(err instanceof Error ? err.message : "Failed to verify code");
2354
3496
  }
2355
3497
  }, [verificationTarget, otpCode, loginWithEmailCode, loginWithSmsCode]);
2356
3498
  const handleResendLoginCode = react.useCallback(async () => {
@@ -2363,17 +3505,12 @@ function SwypePayment({
2363
3505
  await sendSmsCode({ phoneNumber: verificationTarget.value });
2364
3506
  }
2365
3507
  } catch (err) {
2366
- const msg = err instanceof Error ? err.message : "Failed to resend code";
2367
- setError(msg);
3508
+ setError(err instanceof Error ? err.message : "Failed to resend code");
2368
3509
  }
2369
3510
  }, [verificationTarget, sendEmailCode, sendSmsCode]);
2370
- const handleEditIdentifier = react.useCallback(() => {
2371
- setError(null);
2372
- setVerificationTarget(null);
2373
- setOtpCode("");
2374
- }, []);
2375
3511
  react.useEffect(() => {
2376
- if (!ready || !authenticated || step !== "login") return;
3512
+ if (!ready || !authenticated) return;
3513
+ if (step !== "login" && step !== "otp-verify") return;
2377
3514
  let cancelled = false;
2378
3515
  setError(null);
2379
3516
  resetHeadlessLogin();
@@ -2385,15 +3522,11 @@ function SwypePayment({
2385
3522
  if (cancelled) return;
2386
3523
  const allPasskeys = config.passkeys ?? (config.passkey ? [config.passkey] : []);
2387
3524
  if (allPasskeys.length === 0) {
2388
- setStep("register-passkey");
3525
+ setStep("create-passkey");
2389
3526
  return;
2390
3527
  }
2391
3528
  if (activeCredentialId && allPasskeys.some((p) => p.credentialId === activeCredentialId)) {
2392
- if (depositAmount != null && depositAmount > 0) {
2393
- setStep("ready");
2394
- } else {
2395
- setStep("enter-amount");
2396
- }
3529
+ setStep("deposit");
2397
3530
  return;
2398
3531
  }
2399
3532
  if (cancelled) return;
@@ -2403,42 +3536,23 @@ function SwypePayment({
2403
3536
  if (matched) {
2404
3537
  setActiveCredentialId(matched);
2405
3538
  window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, matched);
2406
- if (depositAmount != null && depositAmount > 0) {
2407
- setStep("ready");
2408
- } else {
2409
- setStep("enter-amount");
2410
- }
3539
+ setStep("deposit");
2411
3540
  return;
2412
3541
  }
2413
- setStep("register-passkey");
3542
+ setStep("create-passkey");
2414
3543
  } catch {
2415
- if (!cancelled) {
2416
- if (depositAmount != null && depositAmount > 0) {
2417
- setStep("ready");
2418
- } else {
2419
- setStep("enter-amount");
2420
- }
2421
- }
3544
+ if (!cancelled) setStep("deposit");
2422
3545
  }
2423
3546
  };
2424
3547
  checkPasskey();
2425
3548
  return () => {
2426
3549
  cancelled = true;
2427
3550
  };
2428
- }, [
2429
- ready,
2430
- authenticated,
2431
- step,
2432
- depositAmount,
2433
- apiBaseUrl,
2434
- getAccessToken,
2435
- activeCredentialId,
2436
- resetHeadlessLogin
2437
- ]);
3551
+ }, [ready, authenticated, step, apiBaseUrl, getAccessToken, activeCredentialId, resetHeadlessLogin]);
2438
3552
  const loadingDataRef = react.useRef(false);
2439
3553
  react.useEffect(() => {
2440
3554
  if (!authenticated) return;
2441
- if (step === "login") return;
3555
+ if (step === "login" || step === "otp-verify") return;
2442
3556
  if (accounts.length > 0 || loadingDataRef.current) return;
2443
3557
  if (!activeCredentialId) return;
2444
3558
  let cancelled = false;
@@ -2466,10 +3580,12 @@ function SwypePayment({
2466
3580
  } else if (prov.length > 0) {
2467
3581
  setSelectedProviderId(prov[0].id);
2468
3582
  }
3583
+ if (accts.length === 0 && step === "deposit") {
3584
+ setStep("wallet-picker");
3585
+ }
2469
3586
  } catch (err) {
2470
3587
  if (!cancelled) {
2471
- const msg = err instanceof Error ? err.message : "Failed to load data";
2472
- setError(msg);
3588
+ setError(err instanceof Error ? err.message : "Failed to load data");
2473
3589
  }
2474
3590
  } finally {
2475
3591
  if (!cancelled) {
@@ -2483,15 +3599,15 @@ function SwypePayment({
2483
3599
  cancelled = true;
2484
3600
  loadingDataRef.current = false;
2485
3601
  };
2486
- }, [authenticated, step, accounts.length, apiBaseUrl, getAccessToken, activeCredentialId]);
3602
+ }, [authenticated, step, accounts.length, apiBaseUrl, getAccessToken, activeCredentialId, depositAmount]);
2487
3603
  react.useEffect(() => {
2488
3604
  if (!polling.transfer) return;
2489
3605
  if (polling.transfer.status === "COMPLETED") {
2490
- setStep("complete");
3606
+ setStep("success");
2491
3607
  setTransfer(polling.transfer);
2492
3608
  onComplete?.(polling.transfer);
2493
3609
  } else if (polling.transfer.status === "FAILED") {
2494
- setStep("complete");
3610
+ setStep("success");
2495
3611
  setTransfer(polling.transfer);
2496
3612
  setError("Transfer failed.");
2497
3613
  }
@@ -2507,13 +3623,11 @@ function SwypePayment({
2507
3623
  const elapsedMs = Date.now() - processingStartedAtRef.current;
2508
3624
  const remainingMs = PROCESSING_TIMEOUT_MS - elapsedMs;
2509
3625
  const handleTimeout = () => {
2510
- if (!hasProcessingTimedOut(processingStartedAtRef.current, Date.now())) {
2511
- return;
2512
- }
3626
+ if (!hasProcessingTimedOut(processingStartedAtRef.current, Date.now())) return;
2513
3627
  const status = getTransferStatus(polling.transfer, transfer);
2514
3628
  const msg = buildProcessingTimeoutMessage(status);
2515
3629
  polling.stopPolling();
2516
- setStep("ready");
3630
+ setStep("deposit");
2517
3631
  setError(msg);
2518
3632
  onError?.(msg);
2519
3633
  };
@@ -2522,15 +3636,12 @@ function SwypePayment({
2522
3636
  return;
2523
3637
  }
2524
3638
  const timeoutId = window.setTimeout(handleTimeout, remainingMs);
2525
- return () => {
2526
- window.clearTimeout(timeoutId);
2527
- };
3639
+ return () => window.clearTimeout(timeoutId);
2528
3640
  }, [step, polling.transfer, transfer, polling.stopPolling, onError]);
2529
3641
  react.useEffect(() => {
2530
3642
  if (!mobileFlow) return;
2531
3643
  const polledTransfer = polling.transfer;
2532
- if (!polledTransfer) return;
2533
- if (polledTransfer.status !== "AUTHORIZED") return;
3644
+ if (!polledTransfer || polledTransfer.status !== "AUTHORIZED") return;
2534
3645
  if (transferSigning.signing) return;
2535
3646
  if (mobileSigningTransferIdRef.current === polledTransfer.id) return;
2536
3647
  mobileSigningTransferIdRef.current = polledTransfer.id;
@@ -2551,18 +3662,14 @@ function SwypePayment({
2551
3662
  if (!mobileFlow) return;
2552
3663
  const transferIdToResume = pollingTransferIdRef.current ?? transfer?.id;
2553
3664
  if (!transferIdToResume) return;
2554
- if (!polling.isPolling) {
2555
- polling.startPolling(transferIdToResume);
2556
- }
3665
+ if (!polling.isPolling) polling.startPolling(transferIdToResume);
2557
3666
  const handleVisibility = () => {
2558
3667
  if (document.visibilityState === "visible") {
2559
3668
  polling.startPolling(transferIdToResume);
2560
3669
  }
2561
3670
  };
2562
3671
  document.addEventListener("visibilitychange", handleVisibility);
2563
- return () => {
2564
- document.removeEventListener("visibilitychange", handleVisibility);
2565
- };
3672
+ return () => document.removeEventListener("visibilitychange", handleVisibility);
2566
3673
  }, [mobileFlow, transfer?.id, polling.isPolling, polling.startPolling]);
2567
3674
  const pendingSelectSourceAction = authExecutor.pendingSelectSource;
2568
3675
  const selectSourceChoices = react.useMemo(() => {
@@ -2581,15 +3688,11 @@ function SwypePayment({
2581
3688
  setSelectSourceTokenSymbol("");
2582
3689
  return;
2583
3690
  }
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
- )
3691
+ if (initializedSelectSourceActionRef.current === pendingSelectSourceAction.id) return;
3692
+ const hasRecommended = !!selectSourceRecommended && selectSourceChoices.some(
3693
+ (chain) => chain.chainName === selectSourceRecommended.chainName && chain.tokens.some((t) => t.tokenSymbol === selectSourceRecommended.tokenSymbol)
2591
3694
  );
2592
- if (hasRecommendedOption && selectSourceRecommended) {
3695
+ if (hasRecommended && selectSourceRecommended) {
2593
3696
  setSelectSourceChainName(selectSourceRecommended.chainName);
2594
3697
  setSelectSourceTokenSymbol(selectSourceRecommended.tokenSymbol);
2595
3698
  } else if (selectSourceChoices.length > 0 && selectSourceChoices[0].tokens.length > 0) {
@@ -2601,8 +3704,35 @@ function SwypePayment({
2601
3704
  }
2602
3705
  initializedSelectSourceActionRef.current = pendingSelectSourceAction.id;
2603
3706
  }, [pendingSelectSourceAction, selectSourceChoices, selectSourceRecommended]);
2604
- const handlePay = react.useCallback(async () => {
2605
- const parsedAmount = parseFloat(amount);
3707
+ const selectedAccount = accounts.find((a) => a.id === selectedAccountId);
3708
+ const selectedWallet = selectedAccount?.wallets.find((w) => w.id === selectedWalletId);
3709
+ const sourceName = selectedAccount?.name ?? selectedWallet?.chain.name ?? "Wallet";
3710
+ const sourceAddress = selectedWallet ? `${selectedWallet.name.slice(0, 6)}...${selectedWallet.name.slice(-4)}` : void 0;
3711
+ const sourceVerified = selectedWallet?.status === "ACTIVE";
3712
+ const maxSourceBalance = react.useMemo(() => {
3713
+ let max = 0;
3714
+ for (const acct of accounts) {
3715
+ for (const wallet of acct.wallets) {
3716
+ for (const source of wallet.sources) {
3717
+ if (source.balance.available.amount > max) {
3718
+ max = source.balance.available.amount;
3719
+ }
3720
+ }
3721
+ }
3722
+ }
3723
+ return max;
3724
+ }, [accounts]);
3725
+ const tokenCount = react.useMemo(() => {
3726
+ let count = 0;
3727
+ for (const acct of accounts) {
3728
+ for (const wallet of acct.wallets) {
3729
+ count += wallet.sources.length;
3730
+ }
3731
+ }
3732
+ return count;
3733
+ }, [accounts]);
3734
+ const handlePay = react.useCallback(async (depositAmount2) => {
3735
+ const parsedAmount = depositAmount2;
2606
3736
  if (isNaN(parsedAmount) || parsedAmount < MIN_SEND_AMOUNT_USD) {
2607
3737
  setError(`Minimum amount is $${MIN_SEND_AMOUNT_USD.toFixed(2)}.`);
2608
3738
  return;
@@ -2613,7 +3743,7 @@ function SwypePayment({
2613
3743
  }
2614
3744
  if (!activeCredentialId) {
2615
3745
  setError("Create a passkey on this device before continuing.");
2616
- setStep("register-passkey");
3746
+ setStep("create-passkey");
2617
3747
  return;
2618
3748
  }
2619
3749
  setStep("processing");
@@ -2683,12 +3813,11 @@ function SwypePayment({
2683
3813
  const msg = err instanceof Error ? err.message : "Transfer failed";
2684
3814
  setError(msg);
2685
3815
  onError?.(msg);
2686
- setStep("ready");
3816
+ setStep("deposit");
2687
3817
  } finally {
2688
3818
  setCreatingTransfer(false);
2689
3819
  }
2690
3820
  }, [
2691
- amount,
2692
3821
  sourceId,
2693
3822
  sourceType,
2694
3823
  activeCredentialId,
@@ -2700,10 +3829,103 @@ function SwypePayment({
2700
3829
  transferSigning,
2701
3830
  polling,
2702
3831
  onError,
2703
- useWalletConnector
3832
+ useWalletConnector,
3833
+ idempotencyKey,
3834
+ merchantAuthorization
3835
+ ]);
3836
+ const handleRegisterPasskey = react.useCallback(async () => {
3837
+ setRegisteringPasskey(true);
3838
+ setError(null);
3839
+ try {
3840
+ const token = await getAccessToken();
3841
+ if (!token) throw new Error("Not authenticated");
3842
+ const passkeyDisplayName = user?.email?.address ?? user?.google?.name ?? user?.id ?? "Swype User";
3843
+ const { credentialId, publicKey } = await createPasskeyCredential({
3844
+ userId: user?.id ?? "unknown",
3845
+ displayName: passkeyDisplayName
3846
+ });
3847
+ await registerPasskey(apiBaseUrl, token, credentialId, publicKey);
3848
+ setActiveCredentialId(credentialId);
3849
+ window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
3850
+ if (accounts.length === 0) {
3851
+ setStep("wallet-picker");
3852
+ } else {
3853
+ setStep("deposit");
3854
+ }
3855
+ } catch (err) {
3856
+ setError(err instanceof Error ? err.message : "Failed to register passkey");
3857
+ } finally {
3858
+ setRegisteringPasskey(false);
3859
+ }
3860
+ }, [getAccessToken, user, apiBaseUrl, accounts.length]);
3861
+ const handleSkipPasskey = react.useCallback(() => {
3862
+ if (accounts.length === 0) {
3863
+ setStep("wallet-picker");
3864
+ } else {
3865
+ setStep("deposit");
3866
+ }
3867
+ }, [accounts.length]);
3868
+ const handleSetupOneTap = react.useCallback(async (limit) => {
3869
+ setOneTapLimit(limit);
3870
+ setStep("setup-status");
3871
+ setSetupComplete(false);
3872
+ setSetupStepLabel("Approving tokens");
3873
+ setError(null);
3874
+ try {
3875
+ const token = await getAccessToken();
3876
+ if (!token) throw new Error("Not authenticated");
3877
+ if (!sourceId) {
3878
+ throw new Error("No wallet selected for setup.");
3879
+ }
3880
+ const setupAmount = depositAmount ?? MIN_SEND_AMOUNT_USD;
3881
+ const t = await createTransfer(apiBaseUrl, token, {
3882
+ credentialId: activeCredentialId ?? "",
3883
+ merchantAuthorization,
3884
+ sourceType,
3885
+ sourceId,
3886
+ destination,
3887
+ amount: setupAmount
3888
+ });
3889
+ if (t.authorizationSessions && t.authorizationSessions.length > 0) {
3890
+ const shouldUseConnector = shouldUseWalletConnector({
3891
+ useWalletConnector,
3892
+ userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
3893
+ });
3894
+ if (!shouldUseConnector) {
3895
+ setMobileFlow(true);
3896
+ window.location.href = t.authorizationSessions[0].uri;
3897
+ } else {
3898
+ await authExecutor.executeSession(t);
3899
+ }
3900
+ }
3901
+ setSetupStepLabel(void 0);
3902
+ setSetupComplete(true);
3903
+ } catch (err) {
3904
+ const msg = err instanceof Error ? err.message : "Setup failed";
3905
+ setError(msg);
3906
+ onError?.(msg);
3907
+ }
3908
+ }, [
3909
+ getAccessToken,
3910
+ sourceId,
3911
+ sourceType,
3912
+ activeCredentialId,
3913
+ destination,
3914
+ apiBaseUrl,
3915
+ merchantAuthorization,
3916
+ useWalletConnector,
3917
+ authExecutor,
3918
+ onError,
3919
+ depositAmount
2704
3920
  ]);
2705
- const handleNewPayment = () => {
2706
- setStep("ready");
3921
+ const handleSelectProvider = react.useCallback((providerId) => {
3922
+ setSelectedProviderId(providerId);
3923
+ setSelectedAccountId(null);
3924
+ setConnectingNewAccount(true);
3925
+ setStep("setup");
3926
+ }, []);
3927
+ const handleNewPayment = react.useCallback(() => {
3928
+ setStep("deposit");
2707
3929
  setTransfer(null);
2708
3930
  setError(null);
2709
3931
  setAmount(depositAmount != null ? depositAmount.toString() : "");
@@ -2713,9 +3935,9 @@ function SwypePayment({
2713
3935
  mobileSigningTransferIdRef.current = null;
2714
3936
  setConnectingNewAccount(false);
2715
3937
  setSelectedWalletId(null);
2716
- setAdvancedSettings({ asset: null, chain: null });
3938
+ setSetupComplete(false);
2717
3939
  if (accounts.length > 0) setSelectedAccountId(accounts[0].id);
2718
- };
3940
+ }, [depositAmount, accounts]);
2719
3941
  const handleLogout = react.useCallback(async () => {
2720
3942
  try {
2721
3943
  await logout();
@@ -2730,1134 +3952,196 @@ function SwypePayment({
2730
3952
  setError(null);
2731
3953
  setTransfer(null);
2732
3954
  setCreatingTransfer(false);
2733
- setRegisteringPasskey(false);
2734
- setProviders([]);
2735
- setAccounts([]);
2736
- setChains([]);
2737
- setSelectedAccountId(null);
2738
- setSelectedWalletId(null);
2739
- setSelectedProviderId(null);
2740
- setConnectingNewAccount(false);
2741
- setAmount(depositAmount != null ? depositAmount.toString() : "");
2742
- setAdvancedSettings({ asset: null, chain: null });
2743
- setMobileFlow(false);
2744
- setSelectSourceChainName("");
2745
- setSelectSourceTokenSymbol("");
2746
- initializedSelectSourceActionRef.current = null;
2747
- processingStartedAtRef.current = null;
2748
- pollingTransferIdRef.current = null;
2749
- 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
- };
3955
+ setRegisteringPasskey(false);
3956
+ setProviders([]);
3957
+ setAccounts([]);
3958
+ setChains([]);
3959
+ setSelectedAccountId(null);
3960
+ setSelectedWalletId(null);
3961
+ setSelectedProviderId(null);
3962
+ setConnectingNewAccount(false);
3963
+ setAmount(depositAmount != null ? depositAmount.toString() : "");
3964
+ setMobileFlow(false);
3965
+ setSetupComplete(false);
3966
+ resetHeadlessLogin();
3967
+ }, [logout, polling, depositAmount, resetHeadlessLogin]);
2919
3968
  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..." }) }) });
3969
+ 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..." }) }) });
2921
3970
  }
2922
3971
  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
- ] }) });
3972
+ return /* @__PURE__ */ jsxRuntime.jsx(
3973
+ LoginScreen,
3974
+ {
3975
+ authInput,
3976
+ onAuthInputChange: setAuthInput,
3977
+ onSubmit: handleSendLoginCode,
3978
+ sending: activeOtpStatus === "sending-code",
3979
+ error,
3980
+ onBack
3981
+ }
3982
+ );
3104
3983
  }
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);
3984
+ if (step === "otp-verify" && !authenticated) {
3985
+ return /* @__PURE__ */ jsxRuntime.jsx(
3986
+ OtpVerifyScreen,
3987
+ {
3988
+ maskedIdentifier: verificationTarget ? maskAuthIdentifier(verificationTarget) : "",
3989
+ otpCode,
3990
+ onOtpChange: (code) => {
3991
+ setOtpCode(code);
3992
+ setError(null);
3993
+ },
3994
+ onVerify: handleVerifyLoginCode,
3995
+ onResend: handleResendLoginCode,
3996
+ onBack: () => {
3997
+ setVerificationTarget(null);
3998
+ setOtpCode("");
3999
+ setError(null);
4000
+ setStep("login");
4001
+ },
4002
+ verifying: activeOtpStatus === "submitting-code",
4003
+ error
3130
4004
  }
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
- ] }) });
4005
+ );
3177
4006
  }
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
- }
4007
+ if (step === "create-passkey") {
4008
+ return /* @__PURE__ */ jsxRuntime.jsx(
4009
+ CreatePasskeyScreen,
4010
+ {
4011
+ onCreatePasskey: handleRegisterPasskey,
4012
+ onSkip: handleSkipPasskey,
4013
+ onBack: () => setStep("login"),
4014
+ creating: registeringPasskey,
4015
+ error
4016
+ }
4017
+ );
4018
+ }
4019
+ if (step === "wallet-picker") {
4020
+ return /* @__PURE__ */ jsxRuntime.jsx(
4021
+ WalletPickerScreen,
4022
+ {
4023
+ providers,
4024
+ onSelectProvider: handleSelectProvider,
4025
+ onBack: () => setStep("create-passkey")
4026
+ }
4027
+ );
4028
+ }
4029
+ if (step === "setup") {
4030
+ return /* @__PURE__ */ jsxRuntime.jsx(
4031
+ SetupScreen,
4032
+ {
4033
+ availableBalance: maxSourceBalance,
4034
+ tokenCount,
4035
+ sourceName,
4036
+ onSetupOneTap: handleSetupOneTap,
4037
+ onBack: () => setStep("wallet-picker"),
4038
+ onLogout: handleLogout,
4039
+ loading: loadingData,
4040
+ error
4041
+ }
4042
+ );
4043
+ }
4044
+ if (step === "setup-status") {
4045
+ return /* @__PURE__ */ jsxRuntime.jsx(
4046
+ SetupStatusScreen,
4047
+ {
4048
+ complete: setupComplete,
4049
+ limit: oneTapLimit,
4050
+ tokensApproved: tokenCount,
4051
+ currentStepLabel: setupStepLabel,
4052
+ merchantName,
4053
+ onContinue: () => setStep("deposit"),
4054
+ onLogout: handleLogout,
4055
+ error
3190
4056
  }
4057
+ );
4058
+ }
4059
+ if (step === "deposit") {
4060
+ if (loadingData) {
4061
+ 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
4062
  }
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
- ] });
4063
+ const parsedAmt = depositAmount != null ? depositAmount : 5;
4064
+ return /* @__PURE__ */ jsxRuntime.jsx(
4065
+ DepositScreen,
4066
+ {
4067
+ merchantName,
4068
+ sourceName,
4069
+ sourceAddress,
4070
+ sourceVerified,
4071
+ availableBalance: maxSourceBalance,
4072
+ remainingLimit: oneTapLimit,
4073
+ tokenCount,
4074
+ initialAmount: parsedAmt,
4075
+ estimatedFeePct: 0.6,
4076
+ estimatedFeeUsd: parsedAmt * 6e-3,
4077
+ processing: creatingTransfer,
4078
+ error,
4079
+ onDeposit: handlePay,
4080
+ onChangeSource: () => setStep("wallet-picker"),
4081
+ onSwitchWallet: () => setStep("wallet-picker"),
4082
+ onBack: onBack ?? (() => handleLogout()),
4083
+ onLogout: handleLogout
4084
+ }
4085
+ );
3486
4086
  }
3487
4087
  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
4088
  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: [
4089
+ 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...";
4090
+ 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
4091
  /* @__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
- )
4092
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { fontSize: "1.4rem", fontWeight: 700, color: tokens.text, marginTop: 20, marginBottom: 8 }, children: statusLabel }),
4093
+ (error || authExecutor.error || transferSigning.error || polling.error) && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
4094
+ background: tokens.errorBg,
4095
+ border: `1px solid ${tokens.error}66`,
4096
+ borderRadius: 16,
4097
+ padding: "11px 14px",
4098
+ color: tokens.error,
4099
+ fontSize: "0.84rem",
4100
+ marginTop: 16,
4101
+ lineHeight: 1.5,
4102
+ textAlign: "left",
4103
+ maxWidth: 340
4104
+ }, children: error || authExecutor.error || transferSigning.error || polling.error })
3740
4105
  ] }) });
3741
4106
  }
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
- ] }) });
4107
+ if (step === "success") {
4108
+ transfer?.status === "COMPLETED";
4109
+ const displayAmount = transfer?.amount?.amount ?? 0;
4110
+ const displayCurrency = transfer?.amount?.currency ?? "USD";
4111
+ return /* @__PURE__ */ jsxRuntime.jsx(
4112
+ SuccessScreen,
4113
+ {
4114
+ amount: displayAmount,
4115
+ currency: displayCurrency,
4116
+ merchantName,
4117
+ sourceName,
4118
+ remainingLimit: oneTapLimit > displayAmount ? oneTapLimit - displayAmount : 0,
4119
+ onDone: handleNewPayment,
4120
+ onLogout: handleLogout
4121
+ }
4122
+ );
4123
+ }
4124
+ if (step === "low-balance") {
4125
+ return /* @__PURE__ */ jsxRuntime.jsx(
4126
+ DepositScreen,
4127
+ {
4128
+ merchantName,
4129
+ sourceName,
4130
+ sourceAddress,
4131
+ sourceVerified,
4132
+ availableBalance: 0,
4133
+ remainingLimit: oneTapLimit,
4134
+ tokenCount,
4135
+ initialAmount: depositAmount ?? 5,
4136
+ processing: false,
4137
+ error,
4138
+ onDeposit: handlePay,
4139
+ onChangeSource: () => setStep("wallet-picker"),
4140
+ onSwitchWallet: () => setStep("wallet-picker"),
4141
+ onBack: onBack ?? (() => handleLogout()),
4142
+ onLogout: handleLogout
4143
+ }
4144
+ );
3861
4145
  }
3862
4146
  return null;
3863
4147
  }