@pollar/react 0.9.0 → 0.10.0-rc.10
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/README.md +23 -47
- package/dist/index.css +43 -12
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +101 -37
- package/dist/index.d.ts +101 -37
- package/dist/index.js +1021 -364
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1021 -366
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -1035,7 +1035,7 @@ var PollarModalFooter = () => {
|
|
|
1035
1035
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
|
|
1036
1036
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-footer-version", children: [
|
|
1037
1037
|
"v",
|
|
1038
|
-
"0.
|
|
1038
|
+
"0.10.0-rc.10"
|
|
1039
1039
|
] })
|
|
1040
1040
|
] })
|
|
1041
1041
|
] });
|
|
@@ -1340,54 +1340,63 @@ function EnabledAssetsModalTemplate({
|
|
|
1340
1340
|
const isLoading = enabledAssets.step === "loading";
|
|
1341
1341
|
const data = enabledAssets.step === "loaded" ? enabledAssets.data : null;
|
|
1342
1342
|
const busy = busyKey !== null;
|
|
1343
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1343
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1344
|
+
"div",
|
|
1345
|
+
{
|
|
1346
|
+
className: "pollar-modal-card pollar-asset-modal",
|
|
1347
|
+
"data-theme": theme,
|
|
1348
|
+
style: cssVars,
|
|
1349
|
+
onClick: (e) => e.stopPropagation(),
|
|
1350
|
+
children: [
|
|
1351
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
1352
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: "Trustlines" }),
|
|
1353
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
|
|
1354
|
+
/* @__PURE__ */ jsxRuntime.jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading || busy, children: [
|
|
1355
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1356
|
+
"svg",
|
|
1357
|
+
{
|
|
1358
|
+
className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
|
|
1359
|
+
width: "13",
|
|
1360
|
+
height: "13",
|
|
1361
|
+
viewBox: "0 0 13 13",
|
|
1362
|
+
fill: "none",
|
|
1363
|
+
"aria-hidden": true,
|
|
1364
|
+
children: [
|
|
1365
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
1366
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
1367
|
+
]
|
|
1368
|
+
}
|
|
1369
|
+
),
|
|
1370
|
+
"Refresh"
|
|
1371
|
+
] }),
|
|
1372
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
|
|
1373
|
+
] })
|
|
1364
1374
|
] }),
|
|
1365
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
] });
|
|
1375
|
+
walletAddress && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-asset-address", children: cropAddress(walletAddress) }),
|
|
1376
|
+
isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
|
|
1377
|
+
enabledAssets.step === "error" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: enabledAssets.message }),
|
|
1378
|
+
actionError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-action-error", children: actionError }),
|
|
1379
|
+
data && !data.exists && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-empty", children: [
|
|
1380
|
+
"Account not found on ",
|
|
1381
|
+
data.network,
|
|
1382
|
+
"."
|
|
1383
|
+
] }),
|
|
1384
|
+
data && data.assets.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "No trustlines found." }),
|
|
1385
|
+
data && data.assets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-asset-list", children: data.assets.map((a) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1386
|
+
AssetItem,
|
|
1387
|
+
{
|
|
1388
|
+
record: a,
|
|
1389
|
+
busy: busyKey === assetKey(a),
|
|
1390
|
+
disabled: busy && busyKey !== assetKey(a),
|
|
1391
|
+
onToggle: onToggleTrustline
|
|
1392
|
+
},
|
|
1393
|
+
assetKey(a)
|
|
1394
|
+
)) }),
|
|
1395
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-asset-add-custom", onClick: onAddCustom, disabled: busy, children: "+ Add custom trustline" }),
|
|
1396
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
1397
|
+
]
|
|
1398
|
+
}
|
|
1399
|
+
);
|
|
1391
1400
|
}
|
|
1392
1401
|
function isValidIssuer(issuer) {
|
|
1393
1402
|
return issuer.length === 56 && issuer.startsWith("G");
|
|
@@ -1413,79 +1422,89 @@ function CustomTrustlineModalTemplate({
|
|
|
1413
1422
|
const trimmedLimit = limit.trim();
|
|
1414
1423
|
onSubmit({ code: code.trim(), issuer: issuer.trim(), ...trimmedLimit ? { limit: trimmedLimit } : {} });
|
|
1415
1424
|
};
|
|
1416
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
{
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1425
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1426
|
+
"div",
|
|
1427
|
+
{
|
|
1428
|
+
className: "pollar-modal-card pollar-asset-modal",
|
|
1429
|
+
"data-theme": theme,
|
|
1430
|
+
style: cssVars,
|
|
1431
|
+
onClick: (e) => e.stopPropagation(),
|
|
1432
|
+
children: [
|
|
1433
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
1434
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
|
|
1435
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-back", onClick: onBack, disabled: busy, "aria-label": "Back", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
|
|
1436
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: "Add custom trustline" })
|
|
1437
|
+
] }),
|
|
1438
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
|
|
1439
|
+
] }),
|
|
1440
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-asset-custom-hint", children: "Custom trustlines aren't sponsored \u2014 your wallet pays the 0.5 XLM reserve and the transaction fee." }),
|
|
1441
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-field", children: [
|
|
1442
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-label", htmlFor: "pollar-trustline-code", children: "Asset code" }),
|
|
1443
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1444
|
+
"input",
|
|
1445
|
+
{
|
|
1446
|
+
id: "pollar-trustline-code",
|
|
1447
|
+
className: "pollar-input",
|
|
1448
|
+
value: code,
|
|
1449
|
+
onChange: (e) => setCode(e.target.value),
|
|
1450
|
+
placeholder: "USDC",
|
|
1451
|
+
maxLength: 12,
|
|
1452
|
+
autoComplete: "off",
|
|
1453
|
+
spellCheck: false,
|
|
1454
|
+
disabled: busy
|
|
1455
|
+
}
|
|
1456
|
+
)
|
|
1457
|
+
] }),
|
|
1458
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-field", children: [
|
|
1459
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-label", htmlFor: "pollar-trustline-issuer", children: "Issuer" }),
|
|
1460
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1461
|
+
"input",
|
|
1462
|
+
{
|
|
1463
|
+
id: "pollar-trustline-issuer",
|
|
1464
|
+
className: "pollar-input",
|
|
1465
|
+
value: issuer,
|
|
1466
|
+
onChange: (e) => setIssuer(e.target.value),
|
|
1467
|
+
placeholder: "G\u2026",
|
|
1468
|
+
autoComplete: "off",
|
|
1469
|
+
spellCheck: false,
|
|
1470
|
+
disabled: busy
|
|
1471
|
+
}
|
|
1472
|
+
),
|
|
1473
|
+
issuer.trim().length > 0 && !issuerOk && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-field-error", children: "Issuer must be a 56-character Stellar address starting with G." })
|
|
1474
|
+
] }),
|
|
1475
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-field", children: [
|
|
1476
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-label", htmlFor: "pollar-trustline-limit", children: [
|
|
1477
|
+
"Limit ",
|
|
1478
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-label-optional", children: "(optional)" })
|
|
1479
|
+
] }),
|
|
1480
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1481
|
+
"input",
|
|
1482
|
+
{
|
|
1483
|
+
id: "pollar-trustline-limit",
|
|
1484
|
+
className: "pollar-input",
|
|
1485
|
+
value: limit,
|
|
1486
|
+
onChange: (e) => setLimit(e.target.value),
|
|
1487
|
+
placeholder: "Maximum",
|
|
1488
|
+
inputMode: "decimal",
|
|
1489
|
+
autoComplete: "off",
|
|
1490
|
+
spellCheck: false,
|
|
1491
|
+
disabled: busy
|
|
1492
|
+
}
|
|
1493
|
+
)
|
|
1494
|
+
] }),
|
|
1495
|
+
actionError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-action-error", children: actionError }),
|
|
1496
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-asset-submit", onClick: submit, disabled: !canSubmit, children: busy ? "Enabling\u2026" : "Enable trustline" }),
|
|
1497
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
1498
|
+
]
|
|
1499
|
+
}
|
|
1500
|
+
);
|
|
1483
1501
|
}
|
|
1484
1502
|
function assetKey2(record) {
|
|
1485
1503
|
return record.code + (record.issuer ?? "");
|
|
1486
1504
|
}
|
|
1487
1505
|
function EnabledAssetsModal({ onClose }) {
|
|
1488
|
-
const { enabledAssets, refreshAssets, setTrustline,
|
|
1506
|
+
const { enabledAssets, refreshAssets, setTrustline, wallet, styles } = usePollar();
|
|
1507
|
+
const walletAddress = wallet?.address ?? "";
|
|
1489
1508
|
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
1490
1509
|
const [view, setView] = react.useState("list");
|
|
1491
1510
|
const [busyKey, setBusyKey] = react.useState(null);
|
|
@@ -1833,35 +1852,42 @@ var GoogleButton = ({ disabled, onClick }) => {
|
|
|
1833
1852
|
] })
|
|
1834
1853
|
] });
|
|
1835
1854
|
};
|
|
1836
|
-
function
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
onClick: () => onConnect(core.WalletType.FREIGHTER),
|
|
1845
|
-
children: [
|
|
1846
|
-
/* @__PURE__ */ jsxRuntime.jsx("img", { src: LOGO_FREIGHTER, alt: "Freighter", className: "pollar-wallet-list-icon" }),
|
|
1847
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-wallet-list-name", children: "Freighter" })
|
|
1848
|
-
]
|
|
1849
|
-
}
|
|
1850
|
-
),
|
|
1851
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1855
|
+
function WalletAdapterButtons({
|
|
1856
|
+
walletAdapters,
|
|
1857
|
+
onConnect,
|
|
1858
|
+
isLoading,
|
|
1859
|
+
variant = "list"
|
|
1860
|
+
}) {
|
|
1861
|
+
if (variant === "entry") {
|
|
1862
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: walletAdapters.map((a) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1852
1863
|
"button",
|
|
1853
1864
|
{
|
|
1854
1865
|
type: "button",
|
|
1855
1866
|
disabled: isLoading,
|
|
1856
|
-
className: "pollar-wallet-
|
|
1857
|
-
onClick: () => onConnect(
|
|
1867
|
+
className: "pollar-wallet-entry-btn",
|
|
1868
|
+
onClick: () => onConnect(a.id),
|
|
1858
1869
|
children: [
|
|
1859
|
-
/* @__PURE__ */ jsxRuntime.jsx("img", { src:
|
|
1860
|
-
|
|
1870
|
+
a.meta.iconUrl && /* @__PURE__ */ jsxRuntime.jsx("img", { src: a.meta.iconUrl, alt: a.meta.label, className: "pollar-wallet-icon" }),
|
|
1871
|
+
a.meta.label
|
|
1861
1872
|
]
|
|
1862
|
-
}
|
|
1863
|
-
|
|
1864
|
-
|
|
1873
|
+
},
|
|
1874
|
+
a.id
|
|
1875
|
+
)) });
|
|
1876
|
+
}
|
|
1877
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-wallet-list", children: walletAdapters.map((a) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1878
|
+
"button",
|
|
1879
|
+
{
|
|
1880
|
+
type: "button",
|
|
1881
|
+
disabled: isLoading,
|
|
1882
|
+
className: "pollar-wallet-list-btn",
|
|
1883
|
+
onClick: () => onConnect(a.id),
|
|
1884
|
+
children: [
|
|
1885
|
+
a.meta.iconUrl && /* @__PURE__ */ jsxRuntime.jsx("img", { src: a.meta.iconUrl, alt: a.meta.label, className: "pollar-wallet-list-icon" }),
|
|
1886
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-wallet-list-name", children: a.meta.label })
|
|
1887
|
+
]
|
|
1888
|
+
},
|
|
1889
|
+
a.id
|
|
1890
|
+
)) });
|
|
1865
1891
|
}
|
|
1866
1892
|
var AUTH_STATE_MESSAGES = {
|
|
1867
1893
|
idle: "",
|
|
@@ -1872,6 +1898,7 @@ var AUTH_STATE_MESSAGES = {
|
|
|
1872
1898
|
verifying_email_code: "Verifying\u2026",
|
|
1873
1899
|
opening_oauth: "Redirecting\u2026",
|
|
1874
1900
|
connecting_wallet: "Connecting wallet\u2026",
|
|
1901
|
+
signing_wallet_challenge: "Confirm in your wallet\u2026",
|
|
1875
1902
|
wallet_not_installed: "Wallet not installed",
|
|
1876
1903
|
authenticating_wallet: "Signing in with wallet\u2026",
|
|
1877
1904
|
creating_passkey: "Waiting for passkey\u2026",
|
|
@@ -1887,6 +1914,7 @@ function authStateToStatus(step) {
|
|
|
1887
1914
|
"verifying_email_code",
|
|
1888
1915
|
"opening_oauth",
|
|
1889
1916
|
"connecting_wallet",
|
|
1917
|
+
"signing_wallet_challenge",
|
|
1890
1918
|
"authenticating_wallet",
|
|
1891
1919
|
"creating_passkey",
|
|
1892
1920
|
"deploying_smart_account",
|
|
@@ -1907,6 +1935,7 @@ function LoginModalTemplate({
|
|
|
1907
1935
|
embeddedWallets,
|
|
1908
1936
|
smartWallet = false,
|
|
1909
1937
|
providers,
|
|
1938
|
+
walletAdapters,
|
|
1910
1939
|
appName,
|
|
1911
1940
|
email = "",
|
|
1912
1941
|
onEmailChange,
|
|
@@ -1915,7 +1944,6 @@ function LoginModalTemplate({
|
|
|
1915
1944
|
onWalletConnect,
|
|
1916
1945
|
onLoginSmartWallet,
|
|
1917
1946
|
onCreateSmartWallet,
|
|
1918
|
-
renderWallets,
|
|
1919
1947
|
authState,
|
|
1920
1948
|
codeInputKey,
|
|
1921
1949
|
onCodeSubmit,
|
|
@@ -1923,10 +1951,19 @@ function LoginModalTemplate({
|
|
|
1923
1951
|
onCancel,
|
|
1924
1952
|
onRetry
|
|
1925
1953
|
}) {
|
|
1926
|
-
const [showWalletPicker, setShowWalletPicker] = react.useState(false);
|
|
1927
1954
|
const [showPasskeyChooser, setShowPasskeyChooser] = react.useState(false);
|
|
1955
|
+
const [activeGroup, setActiveGroup] = react.useState(null);
|
|
1928
1956
|
const isDark = theme === "dark";
|
|
1929
1957
|
const enabledSocial = Object.entries(providers).filter(([, enabled]) => enabled);
|
|
1958
|
+
const rootAdapters = walletAdapters.filter((a) => !a.meta.group);
|
|
1959
|
+
const walletGroups = walletAdapters.filter((a) => a.meta.group).reduce((acc, a) => {
|
|
1960
|
+
const label = a.meta.group;
|
|
1961
|
+
const existing = acc.find((g) => g.label === label);
|
|
1962
|
+
if (existing) existing.adapters.push(a);
|
|
1963
|
+
else acc.push({ label, adapters: [a] });
|
|
1964
|
+
return acc;
|
|
1965
|
+
}, []);
|
|
1966
|
+
const activeGroupAdapters = walletGroups.find((g) => g.label === activeGroup)?.adapters ?? [];
|
|
1930
1967
|
const cssVars = {
|
|
1931
1968
|
"--pollar-accent": accentColor,
|
|
1932
1969
|
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
@@ -1990,35 +2027,22 @@ function LoginModalTemplate({
|
|
|
1990
2027
|
/* @__PURE__ */ jsxRuntime.jsx(BackButton, { onClick: onBack }),
|
|
1991
2028
|
/* @__PURE__ */ jsxRuntime.jsx(EmailCodeInput, { email, onSubmit: onCodeSubmit ?? (() => {
|
|
1992
2029
|
}) }, codeInputKey)
|
|
1993
|
-
] }) :
|
|
1994
|
-
/* @__PURE__ */ jsxRuntime.jsx(BackButton, { onClick: () =>
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
2030
|
+
] }) : activeGroup ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2031
|
+
/* @__PURE__ */ jsxRuntime.jsx(BackButton, { onClick: () => setActiveGroup(null) }),
|
|
2032
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2033
|
+
WalletAdapterButtons,
|
|
2034
|
+
{
|
|
2035
|
+
walletAdapters: activeGroupAdapters,
|
|
2036
|
+
onConnect: onWalletConnect ?? (() => {
|
|
2037
|
+
}),
|
|
2038
|
+
isLoading
|
|
2039
|
+
}
|
|
2040
|
+
)
|
|
1998
2041
|
] }) : showPasskeyChooser ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1999
2042
|
/* @__PURE__ */ jsxRuntime.jsx(BackButton, { onClick: () => setShowPasskeyChooser(false) }),
|
|
2000
2043
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-wallet-section", children: [
|
|
2001
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2002
|
-
|
|
2003
|
-
{
|
|
2004
|
-
type: "button",
|
|
2005
|
-
disabled: isLoading,
|
|
2006
|
-
className: "pollar-btn-primary",
|
|
2007
|
-
style: { width: "100%" },
|
|
2008
|
-
onClick: onCreateSmartWallet,
|
|
2009
|
-
children: "Create a new wallet"
|
|
2010
|
-
}
|
|
2011
|
-
),
|
|
2012
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2013
|
-
"button",
|
|
2014
|
-
{
|
|
2015
|
-
type: "button",
|
|
2016
|
-
disabled: isLoading,
|
|
2017
|
-
className: "pollar-wallet-entry-btn",
|
|
2018
|
-
onClick: onLoginSmartWallet,
|
|
2019
|
-
children: "Log in with an existing wallet"
|
|
2020
|
-
}
|
|
2021
|
-
)
|
|
2044
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", disabled: isLoading, className: "pollar-btn-primary", onClick: onCreateSmartWallet, children: "Create a new wallet" }),
|
|
2045
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", disabled: isLoading, className: "pollar-wallet-entry-btn", onClick: onLoginSmartWallet, children: "Log in with an existing wallet" })
|
|
2022
2046
|
] })
|
|
2023
2047
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2024
2048
|
emailEnabled && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-email-section", children: [
|
|
@@ -2040,7 +2064,7 @@ function LoginModalTemplate({
|
|
|
2040
2064
|
type: "button",
|
|
2041
2065
|
disabled: isLoading || !email,
|
|
2042
2066
|
className: "pollar-btn-primary",
|
|
2043
|
-
style: { marginTop: "0.75rem"
|
|
2067
|
+
style: { marginTop: "0.75rem" },
|
|
2044
2068
|
onClick: onEmailSubmit,
|
|
2045
2069
|
children: "Submit"
|
|
2046
2070
|
}
|
|
@@ -2055,32 +2079,45 @@ function LoginModalTemplate({
|
|
|
2055
2079
|
enabledSocial.some(([key]) => key === "github") && /* @__PURE__ */ jsxRuntime.jsx(GithubButton, { disabled: isLoading, onClick: () => onSocialLogin?.("github") })
|
|
2056
2080
|
] }),
|
|
2057
2081
|
(embeddedWallets || smartWallet) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-wallet-section", children: [
|
|
2058
|
-
embeddedWallets && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2082
|
+
embeddedWallets && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2083
|
+
walletGroups.map((g) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2084
|
+
"button",
|
|
2085
|
+
{
|
|
2086
|
+
type: "button",
|
|
2087
|
+
disabled: isLoading,
|
|
2088
|
+
className: "pollar-wallet-entry-btn",
|
|
2089
|
+
onClick: () => setActiveGroup(g.label),
|
|
2090
|
+
children: [
|
|
2091
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2092
|
+
"svg",
|
|
2093
|
+
{
|
|
2094
|
+
width: "18",
|
|
2095
|
+
height: "20",
|
|
2096
|
+
viewBox: "0 0 24 24",
|
|
2097
|
+
fill: "none",
|
|
2098
|
+
stroke: "currentColor",
|
|
2099
|
+
strokeWidth: "2",
|
|
2100
|
+
strokeLinecap: "round",
|
|
2101
|
+
strokeLinejoin: "round",
|
|
2102
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" })
|
|
2103
|
+
}
|
|
2104
|
+
),
|
|
2105
|
+
g.label
|
|
2106
|
+
]
|
|
2107
|
+
},
|
|
2108
|
+
g.label
|
|
2109
|
+
)),
|
|
2110
|
+
rootAdapters.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2111
|
+
WalletAdapterButtons,
|
|
2112
|
+
{
|
|
2113
|
+
walletAdapters: rootAdapters,
|
|
2114
|
+
onConnect: onWalletConnect ?? (() => {
|
|
2115
|
+
}),
|
|
2116
|
+
isLoading,
|
|
2117
|
+
variant: "entry"
|
|
2118
|
+
}
|
|
2119
|
+
)
|
|
2120
|
+
] }),
|
|
2084
2121
|
smartWallet && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2085
2122
|
"button",
|
|
2086
2123
|
{
|
|
@@ -2121,12 +2158,142 @@ function LoginModalTemplate({
|
|
|
2121
2158
|
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
2122
2159
|
] });
|
|
2123
2160
|
}
|
|
2161
|
+
function PrivyLoginSubmodal({
|
|
2162
|
+
adapter,
|
|
2163
|
+
theme,
|
|
2164
|
+
accentColor,
|
|
2165
|
+
logoUrl,
|
|
2166
|
+
appName,
|
|
2167
|
+
onBack,
|
|
2168
|
+
onCancel,
|
|
2169
|
+
onAuthenticated
|
|
2170
|
+
}) {
|
|
2171
|
+
const options = react.useMemo(() => adapter.getAuthOptions(), [adapter]);
|
|
2172
|
+
const [email, setEmail] = react.useState("");
|
|
2173
|
+
const [view, setView] = react.useState("root");
|
|
2174
|
+
const [status, setStatus] = react.useState("NONE");
|
|
2175
|
+
const [message, setMessage] = react.useState("");
|
|
2176
|
+
const isDark = theme === "dark";
|
|
2177
|
+
const isLoading = status === "LOADING";
|
|
2178
|
+
const cssVars = {
|
|
2179
|
+
"--pollar-accent": accentColor,
|
|
2180
|
+
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
2181
|
+
"--pollar-border": isDark ? "#374151" : "#e5e7eb",
|
|
2182
|
+
"--pollar-text": isDark ? "#ffffff" : "#111827",
|
|
2183
|
+
"--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
|
|
2184
|
+
"--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
|
|
2185
|
+
"--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
|
|
2186
|
+
"--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
|
|
2187
|
+
"--pollar-error-text": isDark ? "#f87171" : "#dc2626",
|
|
2188
|
+
"--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
|
|
2189
|
+
"--pollar-buttons-border-radius": "6px",
|
|
2190
|
+
"--pollar-buttons-height": "44px",
|
|
2191
|
+
"--pollar-input-height": "44px",
|
|
2192
|
+
"--pollar-input-border-radius": "0.5rem",
|
|
2193
|
+
"--pollar-card-border-radius": "10px",
|
|
2194
|
+
"--pollar-modal-padding": "2rem",
|
|
2195
|
+
"--pollar-modal-heading-size": "1.375rem",
|
|
2196
|
+
"--pollar-modal-subtitle-size": "0.9rem"
|
|
2197
|
+
};
|
|
2198
|
+
function fail(error) {
|
|
2199
|
+
setStatus("ERROR");
|
|
2200
|
+
setMessage(error instanceof Error ? error.message : "Something went wrong. Please try again.");
|
|
2201
|
+
}
|
|
2202
|
+
async function handleEmailSubmit() {
|
|
2203
|
+
if (!email) return;
|
|
2204
|
+
setStatus("LOADING");
|
|
2205
|
+
setMessage("");
|
|
2206
|
+
try {
|
|
2207
|
+
await adapter.sendEmailCode(email);
|
|
2208
|
+
setStatus("SUCCESS");
|
|
2209
|
+
setMessage("Code sent \u2014 check your inbox");
|
|
2210
|
+
setView("email-code");
|
|
2211
|
+
} catch (error) {
|
|
2212
|
+
fail(error);
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
async function handleCodeSubmit(code) {
|
|
2216
|
+
setStatus("LOADING");
|
|
2217
|
+
setMessage("Verifying\u2026");
|
|
2218
|
+
try {
|
|
2219
|
+
await adapter.verifyEmailCode(code);
|
|
2220
|
+
onAuthenticated();
|
|
2221
|
+
} catch (error) {
|
|
2222
|
+
fail(error);
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
async function handleOAuth(provider) {
|
|
2226
|
+
setStatus("LOADING");
|
|
2227
|
+
setMessage("");
|
|
2228
|
+
try {
|
|
2229
|
+
await adapter.loginWithOAuth(provider);
|
|
2230
|
+
onAuthenticated();
|
|
2231
|
+
} catch (error) {
|
|
2232
|
+
fail(error);
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
const BackButton = ({ onClick }) => /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-back-btn", onClick, "aria-label": "Back", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 19l-7-7 7-7" }) }) });
|
|
2236
|
+
const showEmail = options.includes("email");
|
|
2237
|
+
const showGoogle = options.includes("google");
|
|
2238
|
+
const showGithub = options.includes("github");
|
|
2239
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
|
|
2240
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-close-btn", onClick: onCancel, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) }),
|
|
2241
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-header", children: [
|
|
2242
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoUrl ?? LOGO_POLLAR, alt: "Logo", className: "pollar-logo" }) }),
|
|
2243
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-title", children: appName }),
|
|
2244
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-subtitle", children: adapter.meta.label })
|
|
2245
|
+
] }),
|
|
2246
|
+
view === "email-code" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2247
|
+
/* @__PURE__ */ jsxRuntime.jsx(BackButton, { onClick: () => setView("root") }),
|
|
2248
|
+
/* @__PURE__ */ jsxRuntime.jsx(EmailCodeInput, { email, onSubmit: handleCodeSubmit })
|
|
2249
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2250
|
+
/* @__PURE__ */ jsxRuntime.jsx(BackButton, { onClick: onBack }),
|
|
2251
|
+
showEmail && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-email-section", children: [
|
|
2252
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2253
|
+
"input",
|
|
2254
|
+
{
|
|
2255
|
+
type: "email",
|
|
2256
|
+
placeholder: "you@email.com",
|
|
2257
|
+
value: email,
|
|
2258
|
+
disabled: isLoading,
|
|
2259
|
+
className: "pollar-email-input",
|
|
2260
|
+
onChange: (e) => setEmail(e.target.value),
|
|
2261
|
+
onKeyDown: (e) => e.key === "Enter" && handleEmailSubmit()
|
|
2262
|
+
}
|
|
2263
|
+
),
|
|
2264
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2265
|
+
"button",
|
|
2266
|
+
{
|
|
2267
|
+
type: "button",
|
|
2268
|
+
disabled: isLoading || !email,
|
|
2269
|
+
className: "pollar-btn-primary",
|
|
2270
|
+
style: { marginTop: "0.75rem" },
|
|
2271
|
+
onClick: handleEmailSubmit,
|
|
2272
|
+
children: "Submit"
|
|
2273
|
+
}
|
|
2274
|
+
)
|
|
2275
|
+
] }),
|
|
2276
|
+
showEmail && (showGoogle || showGithub) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-divider", children: [
|
|
2277
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-divider-line" }),
|
|
2278
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-divider-label", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-divider-text", children: "or continue with" }) })
|
|
2279
|
+
] }),
|
|
2280
|
+
(showGoogle || showGithub) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-social-list", children: [
|
|
2281
|
+
showGoogle && /* @__PURE__ */ jsxRuntime.jsx(GoogleButton, { disabled: isLoading, onClick: () => handleOAuth("google") }),
|
|
2282
|
+
showGithub && /* @__PURE__ */ jsxRuntime.jsx(GithubButton, { disabled: isLoading, onClick: () => handleOAuth("github") })
|
|
2283
|
+
] })
|
|
2284
|
+
] }),
|
|
2285
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalStatusBanner, { message, status, onCancel, onRetry: void 0 }),
|
|
2286
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
2287
|
+
] });
|
|
2288
|
+
}
|
|
2124
2289
|
function LoginModal({ onClose }) {
|
|
2125
2290
|
const [email, setEmail] = react.useState("");
|
|
2126
|
-
const { getClient, styles, appConfig: config
|
|
2291
|
+
const { getClient, styles, appConfig: config } = usePollar();
|
|
2127
2292
|
const [authState, setAuthState] = react.useState(() => getClient().getAuthState());
|
|
2293
|
+
const walletAdapters = react.useMemo(() => getClient().listWalletAdapters(), [getClient]);
|
|
2128
2294
|
const [codeInputKey, setCodeInputKey] = react.useState(0);
|
|
2129
2295
|
const pendingEmail = react.useRef(null);
|
|
2296
|
+
const [interactiveAdapter, setInteractiveAdapter] = react.useState(null);
|
|
2130
2297
|
const onCloseRef = react.useRef(onClose);
|
|
2131
2298
|
onCloseRef.current = onClose;
|
|
2132
2299
|
const autoCloseTimer = react.useRef(null);
|
|
@@ -2174,7 +2341,12 @@ function LoginModal({ onClose }) {
|
|
|
2174
2341
|
getClient().login({ provider });
|
|
2175
2342
|
}
|
|
2176
2343
|
function handleWalletConnect(type) {
|
|
2177
|
-
getClient().
|
|
2344
|
+
const adapter = getClient().getWalletAdapter(type);
|
|
2345
|
+
if (core.isInteractiveAuthAdapter(adapter)) {
|
|
2346
|
+
setInteractiveAdapter(adapter);
|
|
2347
|
+
return;
|
|
2348
|
+
}
|
|
2349
|
+
getClient().login({ provider: type });
|
|
2178
2350
|
}
|
|
2179
2351
|
function handleLoginSmartWallet() {
|
|
2180
2352
|
getClient().loginSmartWallet();
|
|
@@ -2195,7 +2367,26 @@ function LoginModal({ onClose }) {
|
|
|
2195
2367
|
getClient().beginEmailLogin();
|
|
2196
2368
|
}
|
|
2197
2369
|
}
|
|
2198
|
-
|
|
2370
|
+
function handleInteractiveAuthenticated() {
|
|
2371
|
+
const provider = interactiveAdapter?.type;
|
|
2372
|
+
setInteractiveAdapter(null);
|
|
2373
|
+
if (provider) {
|
|
2374
|
+
getClient().login({ provider });
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: handleClose, children: interactiveAdapter ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2378
|
+
PrivyLoginSubmodal,
|
|
2379
|
+
{
|
|
2380
|
+
adapter: interactiveAdapter,
|
|
2381
|
+
theme,
|
|
2382
|
+
accentColor,
|
|
2383
|
+
logoUrl: logoUrl ?? null,
|
|
2384
|
+
appName: config.application?.name ?? "Pollar",
|
|
2385
|
+
onBack: () => setInteractiveAdapter(null),
|
|
2386
|
+
onCancel: handleClose,
|
|
2387
|
+
onAuthenticated: handleInteractiveAuthenticated
|
|
2388
|
+
}
|
|
2389
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2199
2390
|
LoginModalTemplate,
|
|
2200
2391
|
{
|
|
2201
2392
|
theme,
|
|
@@ -2211,6 +2402,7 @@ function LoginModal({ onClose }) {
|
|
|
2211
2402
|
github: !!providers?.github,
|
|
2212
2403
|
apple: !!providers?.apple
|
|
2213
2404
|
},
|
|
2405
|
+
walletAdapters,
|
|
2214
2406
|
appName: config.application?.name ?? "Pollar",
|
|
2215
2407
|
email,
|
|
2216
2408
|
onEmailChange: setEmail,
|
|
@@ -2219,7 +2411,6 @@ function LoginModal({ onClose }) {
|
|
|
2219
2411
|
onWalletConnect: handleWalletConnect,
|
|
2220
2412
|
onLoginSmartWallet: handleLoginSmartWallet,
|
|
2221
2413
|
onCreateSmartWallet: handleCreateSmartWallet,
|
|
2222
|
-
...renderWallets !== void 0 && { renderWallets },
|
|
2223
2414
|
authState,
|
|
2224
2415
|
codeInputKey,
|
|
2225
2416
|
onCodeSubmit: handleVerifyCode,
|
|
@@ -2276,6 +2467,12 @@ var COUNTRY_CURRENCIES = {
|
|
|
2276
2467
|
PE: "PEN",
|
|
2277
2468
|
AR: "ARS"
|
|
2278
2469
|
};
|
|
2470
|
+
var STATUS_LABEL = {
|
|
2471
|
+
pending: "Pending",
|
|
2472
|
+
processing: "Processing",
|
|
2473
|
+
completed: "Completed",
|
|
2474
|
+
failed: "Failed"
|
|
2475
|
+
};
|
|
2279
2476
|
function RampWidgetTemplate({
|
|
2280
2477
|
theme,
|
|
2281
2478
|
accentColor,
|
|
@@ -2285,15 +2482,23 @@ function RampWidgetTemplate({
|
|
|
2285
2482
|
currency,
|
|
2286
2483
|
country,
|
|
2287
2484
|
quotes,
|
|
2288
|
-
paymentInstructions,
|
|
2289
2485
|
isLoading,
|
|
2486
|
+
provider,
|
|
2487
|
+
txStatus,
|
|
2488
|
+
kycUrl,
|
|
2489
|
+
stellarTxHash,
|
|
2490
|
+
canComplete,
|
|
2491
|
+
completing,
|
|
2492
|
+
errorMsg,
|
|
2290
2493
|
onDirectionChange,
|
|
2291
2494
|
onAmountChange,
|
|
2292
2495
|
onCurrencyChange,
|
|
2293
2496
|
onCountryChange,
|
|
2294
2497
|
onFindRoute,
|
|
2295
2498
|
onSelectQuote,
|
|
2296
|
-
|
|
2499
|
+
onOpenKyc,
|
|
2500
|
+
onCompleteWithdraw,
|
|
2501
|
+
onRetry,
|
|
2297
2502
|
onClose
|
|
2298
2503
|
}) {
|
|
2299
2504
|
const isDark = theme === "dark";
|
|
@@ -2321,13 +2526,15 @@ function RampWidgetTemplate({
|
|
|
2321
2526
|
input: direction === "onramp" ? "Buy crypto" : "Sell crypto",
|
|
2322
2527
|
loading_quote: "Finding best route",
|
|
2323
2528
|
select_route: "Select provider",
|
|
2324
|
-
|
|
2529
|
+
status: direction === "onramp" ? "Complete your deposit" : "Complete your withdrawal",
|
|
2530
|
+
error: "Something went wrong"
|
|
2325
2531
|
};
|
|
2326
2532
|
const stepSubtitle = {
|
|
2327
2533
|
input: direction === "onramp" ? "Enter the amount you want to deposit" : "Enter the amount you want to withdraw",
|
|
2328
2534
|
loading_quote: "Comparing providers in real time\u2026",
|
|
2329
2535
|
select_route: "All prices include fees",
|
|
2330
|
-
|
|
2536
|
+
status: `Finish the flow at ${provider || "the provider"} to continue`,
|
|
2537
|
+
error: "Please try again"
|
|
2331
2538
|
};
|
|
2332
2539
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-ramp-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
|
|
2333
2540
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-header", children: [
|
|
@@ -2423,182 +2630,183 @@ function RampWidgetTemplate({
|
|
|
2423
2630
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-route-list", children: quotes.map((q, i) => /* @__PURE__ */ jsxRuntime.jsx(RouteDisplay, { quote: q, onSelect: onSelectQuote }, i)) }),
|
|
2424
2631
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" })
|
|
2425
2632
|
] }),
|
|
2426
|
-
step === "
|
|
2427
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-ramp-payment-title", children: paymentInstructions.type }),
|
|
2633
|
+
step === "status" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment", children: [
|
|
2428
2634
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2429
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children:
|
|
2430
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2431
|
-
/* @__PURE__ */ jsxRuntime.jsx("code", { children: paymentInstructions.value }),
|
|
2432
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-ramp-copy-btn", onClick: () => onCopy(paymentInstructions.value), children: "Copy" })
|
|
2433
|
-
] })
|
|
2635
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: "Provider" }),
|
|
2636
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: provider }) })
|
|
2434
2637
|
] }),
|
|
2435
2638
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2436
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: "
|
|
2437
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
" ",
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
] })
|
|
2639
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: "Status" }),
|
|
2640
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2641
|
+
"code",
|
|
2642
|
+
{
|
|
2643
|
+
style: { color: txStatus === "completed" ? "var(--pollar-success-text)" : void 0 },
|
|
2644
|
+
children: txStatus ? STATUS_LABEL[txStatus] : "Processing"
|
|
2645
|
+
}
|
|
2646
|
+
) })
|
|
2647
|
+
] }),
|
|
2648
|
+
stellarTxHash && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2649
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: "Stellar tx" }),
|
|
2650
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsxRuntime.jsxs("code", { children: [
|
|
2651
|
+
stellarTxHash.slice(0, 8),
|
|
2652
|
+
"\u2026",
|
|
2653
|
+
stellarTxHash.slice(-8)
|
|
2654
|
+
] }) })
|
|
2453
2655
|
] }),
|
|
2454
|
-
|
|
2455
|
-
"
|
|
2456
|
-
|
|
2656
|
+
kycUrl && txStatus !== "completed" && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenKyc, children: [
|
|
2657
|
+
"Continue at ",
|
|
2658
|
+
provider
|
|
2457
2659
|
] }),
|
|
2458
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick:
|
|
2660
|
+
canComplete && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", disabled: completing, onClick: onCompleteWithdraw, children: completing ? "Submitting\u2026" : "I've completed KYC \u2014 withdraw" }),
|
|
2661
|
+
errorMsg && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-ramp-payment-note", style: { color: "var(--pollar-error-text)" }, children: errorMsg }),
|
|
2662
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: txStatus === "completed" ? "Done" : "Close" })
|
|
2663
|
+
] }),
|
|
2664
|
+
step === "error" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment", children: [
|
|
2665
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-ramp-payment-note", style: { color: "var(--pollar-error-text)" }, children: errorMsg ?? "Unexpected error." }),
|
|
2666
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
|
|
2667
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Close" }),
|
|
2668
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onRetry, children: "Try again" })
|
|
2669
|
+
] })
|
|
2459
2670
|
] })
|
|
2460
2671
|
] });
|
|
2461
2672
|
}
|
|
2462
|
-
var
|
|
2463
|
-
{
|
|
2464
|
-
quoteId: "meld-default",
|
|
2465
|
-
provider: "Meld",
|
|
2466
|
-
fee: 1.2,
|
|
2467
|
-
feeCurrency: "USD",
|
|
2468
|
-
rate: 1,
|
|
2469
|
-
rail: "ACH",
|
|
2470
|
-
protocol: "REST",
|
|
2471
|
-
estimatedTime: "~20 min",
|
|
2472
|
-
recommended: true
|
|
2473
|
-
}
|
|
2474
|
-
];
|
|
2475
|
-
var MOCK_QUOTES = {
|
|
2476
|
-
MX: [
|
|
2477
|
-
{
|
|
2478
|
-
quoteId: "etherfuse-mx",
|
|
2479
|
-
provider: "Etherfuse",
|
|
2480
|
-
fee: 0.5,
|
|
2481
|
-
feeCurrency: "MXN",
|
|
2482
|
-
rate: 17.2,
|
|
2483
|
-
rail: "SPEI",
|
|
2484
|
-
protocol: "SEP-24",
|
|
2485
|
-
estimatedTime: "~10 min",
|
|
2486
|
-
recommended: true
|
|
2487
|
-
},
|
|
2488
|
-
{
|
|
2489
|
-
quoteId: "alfredpay-mx",
|
|
2490
|
-
provider: "AlfredPay",
|
|
2491
|
-
fee: 0.8,
|
|
2492
|
-
feeCurrency: "MXN",
|
|
2493
|
-
rate: 17.1,
|
|
2494
|
-
rail: "SPEI",
|
|
2495
|
-
protocol: "REST",
|
|
2496
|
-
estimatedTime: "~15 min",
|
|
2497
|
-
recommended: false
|
|
2498
|
-
}
|
|
2499
|
-
],
|
|
2500
|
-
BR: [
|
|
2501
|
-
{
|
|
2502
|
-
quoteId: "abroad-br",
|
|
2503
|
-
provider: "Abroad",
|
|
2504
|
-
fee: 0.6,
|
|
2505
|
-
feeCurrency: "BRL",
|
|
2506
|
-
rate: 5.1,
|
|
2507
|
-
rail: "PIX",
|
|
2508
|
-
protocol: "REST",
|
|
2509
|
-
estimatedTime: "~5 min",
|
|
2510
|
-
recommended: true
|
|
2511
|
-
}
|
|
2512
|
-
],
|
|
2513
|
-
CO: [
|
|
2514
|
-
{
|
|
2515
|
-
quoteId: "abroad-co",
|
|
2516
|
-
provider: "Abroad",
|
|
2517
|
-
fee: 0.7,
|
|
2518
|
-
feeCurrency: "COP",
|
|
2519
|
-
rate: 4100,
|
|
2520
|
-
rail: "PSE",
|
|
2521
|
-
protocol: "REST",
|
|
2522
|
-
estimatedTime: "~10 min",
|
|
2523
|
-
recommended: true
|
|
2524
|
-
},
|
|
2525
|
-
{
|
|
2526
|
-
quoteId: "koywe-co",
|
|
2527
|
-
provider: "Koywe",
|
|
2528
|
-
fee: 0.9,
|
|
2529
|
-
feeCurrency: "COP",
|
|
2530
|
-
rate: 4095,
|
|
2531
|
-
rail: "PSE",
|
|
2532
|
-
protocol: "REST",
|
|
2533
|
-
estimatedTime: "~15 min",
|
|
2534
|
-
recommended: false
|
|
2535
|
-
}
|
|
2536
|
-
],
|
|
2537
|
-
DEFAULT: MOCK_DEFAULT_QUOTES
|
|
2538
|
-
};
|
|
2539
|
-
var MOCK_PAYMENT = {
|
|
2540
|
-
type: "CLABE",
|
|
2541
|
-
value: "646180157088723456",
|
|
2542
|
-
amount: 1e3,
|
|
2543
|
-
currency: "MXN",
|
|
2544
|
-
expiresAt: new Date(Date.now() + 30 * 60 * 1e3).toISOString()
|
|
2545
|
-
};
|
|
2673
|
+
var TERMINAL = ["completed", "failed"];
|
|
2546
2674
|
function RampWidget({ onClose }) {
|
|
2547
|
-
const { getClient,
|
|
2675
|
+
const { getClient, signTx, wallet, styles } = usePollar();
|
|
2676
|
+
const walletAddress = wallet?.address ?? "";
|
|
2677
|
+
const client = getClient();
|
|
2678
|
+
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
2548
2679
|
const [step, setStep] = react.useState("input");
|
|
2549
2680
|
const [direction, setDirection] = react.useState("onramp");
|
|
2550
2681
|
const [amount, setAmount] = react.useState("");
|
|
2551
|
-
const [currency, setCurrency] = react.useState("
|
|
2552
|
-
const [country, setCountry] = react.useState("
|
|
2682
|
+
const [currency, setCurrency] = react.useState("ARS");
|
|
2683
|
+
const [country, setCountry] = react.useState("AR");
|
|
2553
2684
|
const [quotes, setQuotes] = react.useState([]);
|
|
2554
|
-
const [paymentInstructions, setPaymentInstructions] = react.useState(null);
|
|
2555
2685
|
const [isLoading, setIsLoading] = react.useState(false);
|
|
2556
|
-
const
|
|
2557
|
-
const
|
|
2686
|
+
const [txId, setTxId] = react.useState(null);
|
|
2687
|
+
const [provider, setProvider] = react.useState("");
|
|
2688
|
+
const [kycUrl, setKycUrl] = react.useState(null);
|
|
2689
|
+
const [txStatus, setTxStatus] = react.useState(null);
|
|
2690
|
+
const [stellarTxHash, setStellarTxHash] = react.useState(null);
|
|
2691
|
+
const [completing, setCompleting] = react.useState(false);
|
|
2692
|
+
const [errorMsg, setErrorMsg] = react.useState(null);
|
|
2693
|
+
const directionRef = react.useRef(direction);
|
|
2694
|
+
directionRef.current = direction;
|
|
2695
|
+
react.useEffect(() => {
|
|
2696
|
+
if (step !== "status" || !txId) return;
|
|
2697
|
+
if (txStatus && TERMINAL.includes(txStatus)) return;
|
|
2698
|
+
let active = true;
|
|
2699
|
+
const id = setInterval(async () => {
|
|
2700
|
+
try {
|
|
2701
|
+
const tx = await client.getRampTransaction(txId);
|
|
2702
|
+
if (!active) return;
|
|
2703
|
+
setTxStatus(tx.status);
|
|
2704
|
+
if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
|
|
2705
|
+
if (tx.kycUrl) setKycUrl(tx.kycUrl);
|
|
2706
|
+
if (TERMINAL.includes(tx.status)) clearInterval(id);
|
|
2707
|
+
} catch {
|
|
2708
|
+
}
|
|
2709
|
+
}, 5e3);
|
|
2710
|
+
return () => {
|
|
2711
|
+
active = false;
|
|
2712
|
+
clearInterval(id);
|
|
2713
|
+
};
|
|
2714
|
+
}, [step, txId, txStatus, client]);
|
|
2715
|
+
function resetToInput() {
|
|
2716
|
+
setStep("input");
|
|
2717
|
+
setQuotes([]);
|
|
2718
|
+
setTxId(null);
|
|
2719
|
+
setProvider("");
|
|
2720
|
+
setKycUrl(null);
|
|
2721
|
+
setTxStatus(null);
|
|
2722
|
+
setStellarTxHash(null);
|
|
2723
|
+
setErrorMsg(null);
|
|
2724
|
+
}
|
|
2725
|
+
async function resumeWithSignature(id, ps) {
|
|
2726
|
+
const outcome = await signTx(ps.unsignedXdr);
|
|
2727
|
+
if (outcome.status !== "signed") {
|
|
2728
|
+
setErrorMsg(outcome.message ?? outcome.details ?? "Signing was cancelled.");
|
|
2729
|
+
setStep("error");
|
|
2730
|
+
return;
|
|
2731
|
+
}
|
|
2732
|
+
const result = await client.submitRampSignature(id, {
|
|
2733
|
+
signedXdr: outcome.signedXdr,
|
|
2734
|
+
action: ps.action
|
|
2735
|
+
});
|
|
2736
|
+
await applyResult(result);
|
|
2737
|
+
}
|
|
2738
|
+
async function applyResult(result) {
|
|
2739
|
+
setTxId(result.txId);
|
|
2740
|
+
setProvider(result.provider);
|
|
2741
|
+
if (result.pendingSignature) {
|
|
2742
|
+
await resumeWithSignature(result.txId, result.pendingSignature);
|
|
2743
|
+
return;
|
|
2744
|
+
}
|
|
2745
|
+
setKycUrl(result.kycUrl ?? null);
|
|
2746
|
+
setTxStatus(result.status);
|
|
2747
|
+
setStellarTxHash(result.stellarTxHash ?? null);
|
|
2748
|
+
setStep("status");
|
|
2749
|
+
}
|
|
2558
2750
|
async function handleFindRoute() {
|
|
2559
2751
|
setStep("loading_quote");
|
|
2560
2752
|
setIsLoading(true);
|
|
2753
|
+
setErrorMsg(null);
|
|
2561
2754
|
try {
|
|
2562
|
-
const result = await client.getRampsQuote({
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2755
|
+
const result = await client.getRampsQuote({ country, amount: Number(amount), currency, direction });
|
|
2756
|
+
const list = result.quotes ?? [];
|
|
2757
|
+
if (list.length === 0) {
|
|
2758
|
+
setErrorMsg(`No ramp providers available for ${country} yet.`);
|
|
2759
|
+
setStep("error");
|
|
2760
|
+
return;
|
|
2761
|
+
}
|
|
2762
|
+
setQuotes(list);
|
|
2763
|
+
setStep("select_route");
|
|
2764
|
+
} catch (e) {
|
|
2765
|
+
setErrorMsg(e instanceof Error ? e.message : "Failed to fetch quotes.");
|
|
2766
|
+
setStep("error");
|
|
2572
2767
|
} finally {
|
|
2573
2768
|
setIsLoading(false);
|
|
2574
|
-
setStep("select_route");
|
|
2575
2769
|
}
|
|
2576
2770
|
}
|
|
2577
2771
|
async function handleSelectQuote(quote) {
|
|
2578
|
-
if (!walletAddress) return;
|
|
2579
2772
|
setIsLoading(true);
|
|
2580
|
-
|
|
2581
|
-
quoteId: `${quote.provider}-${Date.now()}`,
|
|
2582
|
-
amount: Number(amount),
|
|
2583
|
-
currency,
|
|
2584
|
-
country,
|
|
2585
|
-
walletAddress
|
|
2586
|
-
};
|
|
2773
|
+
setErrorMsg(null);
|
|
2587
2774
|
try {
|
|
2588
|
-
const
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2775
|
+
const base = { quoteId: quote.quoteId, amount: Number(amount), currency, country };
|
|
2776
|
+
const result = direction === "onramp" ? await client.createOnRamp({ ...base, ...walletAddress ? { walletAddress } : {} }) : await client.createOffRamp({ ...base, ...walletAddress ? { walletAddress } : {} });
|
|
2777
|
+
await applyResult(result);
|
|
2778
|
+
} catch (e) {
|
|
2779
|
+
setErrorMsg(e instanceof Error ? e.message : "Failed to start the ramp.");
|
|
2780
|
+
setStep("error");
|
|
2593
2781
|
} finally {
|
|
2594
2782
|
setIsLoading(false);
|
|
2595
|
-
setStep("payment_instructions");
|
|
2596
2783
|
}
|
|
2597
2784
|
}
|
|
2598
|
-
function
|
|
2599
|
-
|
|
2600
|
-
|
|
2785
|
+
function handleOpenKyc() {
|
|
2786
|
+
if (kycUrl) window.open(kycUrl, "_blank", "noopener,noreferrer");
|
|
2787
|
+
}
|
|
2788
|
+
async function handleCompleteWithdraw() {
|
|
2789
|
+
if (!txId) return;
|
|
2790
|
+
setCompleting(true);
|
|
2791
|
+
setErrorMsg(null);
|
|
2792
|
+
try {
|
|
2793
|
+
const result = await client.completeWithdraw(txId);
|
|
2794
|
+
if (result.pendingSignature) {
|
|
2795
|
+
await resumeWithSignature(txId, result.pendingSignature);
|
|
2796
|
+
return;
|
|
2797
|
+
}
|
|
2798
|
+
setTxStatus(result.status);
|
|
2799
|
+
setStellarTxHash(result.stellarTxHash ?? null);
|
|
2800
|
+
} catch (e) {
|
|
2801
|
+
const msg = e instanceof Error ? e.message : "";
|
|
2802
|
+
setErrorMsg(
|
|
2803
|
+
msg.includes("KYC") ? "Finish KYC at the provider first, then try again." : msg || "Failed to complete the withdrawal."
|
|
2804
|
+
);
|
|
2805
|
+
} finally {
|
|
2806
|
+
setCompleting(false);
|
|
2807
|
+
}
|
|
2601
2808
|
}
|
|
2809
|
+
const canComplete = direction === "offramp" && step === "status" && txStatus !== "completed" && !stellarTxHash;
|
|
2602
2810
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2603
2811
|
RampWidgetTemplate,
|
|
2604
2812
|
{
|
|
@@ -2610,15 +2818,23 @@ function RampWidget({ onClose }) {
|
|
|
2610
2818
|
currency,
|
|
2611
2819
|
country,
|
|
2612
2820
|
quotes,
|
|
2613
|
-
paymentInstructions,
|
|
2614
2821
|
isLoading,
|
|
2822
|
+
provider,
|
|
2823
|
+
txStatus,
|
|
2824
|
+
kycUrl,
|
|
2825
|
+
stellarTxHash,
|
|
2826
|
+
canComplete,
|
|
2827
|
+
completing,
|
|
2828
|
+
errorMsg,
|
|
2615
2829
|
onDirectionChange: setDirection,
|
|
2616
2830
|
onAmountChange: setAmount,
|
|
2617
2831
|
onCurrencyChange: setCurrency,
|
|
2618
2832
|
onCountryChange: setCountry,
|
|
2619
2833
|
onFindRoute: handleFindRoute,
|
|
2620
2834
|
onSelectQuote: handleSelectQuote,
|
|
2621
|
-
|
|
2835
|
+
onOpenKyc: handleOpenKyc,
|
|
2836
|
+
onCompleteWithdraw: handleCompleteWithdraw,
|
|
2837
|
+
onRetry: resetToInput,
|
|
2622
2838
|
onClose
|
|
2623
2839
|
}
|
|
2624
2840
|
) });
|
|
@@ -2747,7 +2963,8 @@ function ReceiveModalTemplate({
|
|
|
2747
2963
|
);
|
|
2748
2964
|
}
|
|
2749
2965
|
function ReceiveModal({ onClose }) {
|
|
2750
|
-
const {
|
|
2966
|
+
const { wallet, styles } = usePollar();
|
|
2967
|
+
const walletAddress = wallet?.address ?? "";
|
|
2751
2968
|
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
2752
2969
|
const [copied, setCopied] = react.useState(false);
|
|
2753
2970
|
const copyTimerRef = react.useRef(null);
|
|
@@ -3155,10 +3372,11 @@ function SendModal({ onClose }) {
|
|
|
3155
3372
|
buildTx,
|
|
3156
3373
|
signAndSubmitTx,
|
|
3157
3374
|
tx: transaction,
|
|
3158
|
-
|
|
3375
|
+
wallet,
|
|
3159
3376
|
network,
|
|
3160
3377
|
styles
|
|
3161
3378
|
} = usePollar();
|
|
3379
|
+
const walletType = wallet?.custody === "external" ? wallet.provider : null;
|
|
3162
3380
|
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
3163
3381
|
const [step, setStep] = react.useState("form");
|
|
3164
3382
|
const [amount, setAmount] = react.useState("");
|
|
@@ -3280,6 +3498,415 @@ function SendModal({ onClose }) {
|
|
|
3280
3498
|
}
|
|
3281
3499
|
) });
|
|
3282
3500
|
}
|
|
3501
|
+
function assetOptionKey(o) {
|
|
3502
|
+
return `${o.code}:${o.issuer ?? "native"}`;
|
|
3503
|
+
}
|
|
3504
|
+
var PROVIDER_LABELS = {
|
|
3505
|
+
auto: "Best price (auto)",
|
|
3506
|
+
aquarius: "Aquarius",
|
|
3507
|
+
soroswap: "Soroswap",
|
|
3508
|
+
sdex: "Stellar DEX"
|
|
3509
|
+
};
|
|
3510
|
+
var IMPLEMENTED_PROVIDERS = ["auto", "aquarius"];
|
|
3511
|
+
function formatAmount2(value) {
|
|
3512
|
+
const n = parseFloat(value);
|
|
3513
|
+
return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
|
|
3514
|
+
}
|
|
3515
|
+
function SwapModalTemplate({
|
|
3516
|
+
theme,
|
|
3517
|
+
accentColor,
|
|
3518
|
+
step,
|
|
3519
|
+
txTitle,
|
|
3520
|
+
sellOptions,
|
|
3521
|
+
buyOptions,
|
|
3522
|
+
selectedSell,
|
|
3523
|
+
selectedBuy,
|
|
3524
|
+
amount,
|
|
3525
|
+
provider,
|
|
3526
|
+
providers,
|
|
3527
|
+
quote,
|
|
3528
|
+
quoteLoading,
|
|
3529
|
+
quoteError,
|
|
3530
|
+
formError,
|
|
3531
|
+
isLoadingData,
|
|
3532
|
+
smartUnsupported,
|
|
3533
|
+
transaction,
|
|
3534
|
+
showXdr,
|
|
3535
|
+
copied,
|
|
3536
|
+
explorerUrl,
|
|
3537
|
+
walletType,
|
|
3538
|
+
showBack,
|
|
3539
|
+
isInProgress,
|
|
3540
|
+
onClose,
|
|
3541
|
+
onBack,
|
|
3542
|
+
onSelectSell,
|
|
3543
|
+
onSelectBuy,
|
|
3544
|
+
onAmountChange,
|
|
3545
|
+
onProviderChange,
|
|
3546
|
+
onSwap,
|
|
3547
|
+
onToggleXdr,
|
|
3548
|
+
onCopyHash,
|
|
3549
|
+
onRetry,
|
|
3550
|
+
onDone
|
|
3551
|
+
}) {
|
|
3552
|
+
const isDark = theme === "dark";
|
|
3553
|
+
const cssVars = {
|
|
3554
|
+
"--pollar-accent": accentColor,
|
|
3555
|
+
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
3556
|
+
"--pollar-border": isDark ? "#374151" : "#e5e7eb",
|
|
3557
|
+
"--pollar-text": isDark ? "#ffffff" : "#111827",
|
|
3558
|
+
"--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
|
|
3559
|
+
"--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
|
|
3560
|
+
"--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
|
|
3561
|
+
"--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
|
|
3562
|
+
"--pollar-error-text": isDark ? "#f87171" : "#dc2626",
|
|
3563
|
+
"--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
|
|
3564
|
+
"--pollar-buttons-border-radius": "6px",
|
|
3565
|
+
"--pollar-buttons-height": "44px",
|
|
3566
|
+
"--pollar-input-height": "44px",
|
|
3567
|
+
"--pollar-input-border-radius": "0.5rem",
|
|
3568
|
+
"--pollar-card-border-radius": "10px"
|
|
3569
|
+
};
|
|
3570
|
+
const sellKey = selectedSell ? assetOptionKey(selectedSell) : "";
|
|
3571
|
+
const buyKey = selectedBuy ? assetOptionKey(selectedBuy) : "";
|
|
3572
|
+
const canSwap = !smartUnsupported && !!selectedSell && !!selectedBuy && !!amount && !!quote && !quoteLoading && !isLoadingData;
|
|
3573
|
+
const title = step === "form" ? "Swap" : txTitle;
|
|
3574
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-send-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
|
|
3575
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
3576
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-header-left", children: [
|
|
3577
|
+
showBack && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onBack, "aria-label": "Back", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
|
|
3578
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: title })
|
|
3579
|
+
] }),
|
|
3580
|
+
!isInProgress && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-header-actions", children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) }) })
|
|
3581
|
+
] }),
|
|
3582
|
+
step === "form" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3583
|
+
smartUnsupported && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Swaps are not yet available for smart (passkey) wallets." }),
|
|
3584
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
3585
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "You pay" }),
|
|
3586
|
+
isLoadingData ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3587
|
+
"select",
|
|
3588
|
+
{
|
|
3589
|
+
className: "pollar-input pollar-send-select",
|
|
3590
|
+
value: sellKey,
|
|
3591
|
+
onChange: (e) => {
|
|
3592
|
+
const found = sellOptions.find((o) => assetOptionKey(o) === e.target.value);
|
|
3593
|
+
if (found) onSelectSell(found);
|
|
3594
|
+
},
|
|
3595
|
+
children: [
|
|
3596
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Select asset to sell" }),
|
|
3597
|
+
sellOptions.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: assetOptionKey(o), children: [
|
|
3598
|
+
o.code,
|
|
3599
|
+
o.available !== void 0 ? ` \u2014 ${formatAmount2(o.available)} available` : ""
|
|
3600
|
+
] }, assetOptionKey(o)))
|
|
3601
|
+
]
|
|
3602
|
+
}
|
|
3603
|
+
)
|
|
3604
|
+
] }),
|
|
3605
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
3606
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-label-row", children: [
|
|
3607
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Amount" }),
|
|
3608
|
+
selectedSell?.available !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-send-hint", children: [
|
|
3609
|
+
"Available: ",
|
|
3610
|
+
formatAmount2(selectedSell.available),
|
|
3611
|
+
" ",
|
|
3612
|
+
selectedSell.code
|
|
3613
|
+
] })
|
|
3614
|
+
] }),
|
|
3615
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3616
|
+
"input",
|
|
3617
|
+
{
|
|
3618
|
+
className: "pollar-input",
|
|
3619
|
+
type: "text",
|
|
3620
|
+
inputMode: "decimal",
|
|
3621
|
+
placeholder: "0.00",
|
|
3622
|
+
value: amount,
|
|
3623
|
+
onChange: (e) => onAmountChange(e.target.value)
|
|
3624
|
+
}
|
|
3625
|
+
)
|
|
3626
|
+
] }),
|
|
3627
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
3628
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "You receive" }),
|
|
3629
|
+
isLoadingData ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3630
|
+
"select",
|
|
3631
|
+
{
|
|
3632
|
+
className: "pollar-input pollar-send-select",
|
|
3633
|
+
value: buyKey,
|
|
3634
|
+
onChange: (e) => {
|
|
3635
|
+
const found = buyOptions.find((o) => assetOptionKey(o) === e.target.value);
|
|
3636
|
+
if (found) onSelectBuy(found);
|
|
3637
|
+
},
|
|
3638
|
+
children: [
|
|
3639
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Select asset to buy" }),
|
|
3640
|
+
buyOptions.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: assetOptionKey(o), children: [
|
|
3641
|
+
o.code,
|
|
3642
|
+
o.enabledInApp ? "" : " (external)"
|
|
3643
|
+
] }, assetOptionKey(o)))
|
|
3644
|
+
]
|
|
3645
|
+
}
|
|
3646
|
+
)
|
|
3647
|
+
] }),
|
|
3648
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
3649
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Route" }),
|
|
3650
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3651
|
+
"select",
|
|
3652
|
+
{
|
|
3653
|
+
className: "pollar-input pollar-send-select",
|
|
3654
|
+
value: provider,
|
|
3655
|
+
onChange: (e) => onProviderChange(e.target.value),
|
|
3656
|
+
children: providers.map((p) => {
|
|
3657
|
+
const implemented = IMPLEMENTED_PROVIDERS.includes(p);
|
|
3658
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("option", { value: p, disabled: !implemented, children: [
|
|
3659
|
+
PROVIDER_LABELS[p],
|
|
3660
|
+
implemented ? "" : " (coming soon)"
|
|
3661
|
+
] }, p);
|
|
3662
|
+
})
|
|
3663
|
+
}
|
|
3664
|
+
)
|
|
3665
|
+
] }),
|
|
3666
|
+
quoteLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "Fetching best price\u2026" }),
|
|
3667
|
+
!quoteLoading && quoteError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: quoteError }),
|
|
3668
|
+
!quoteLoading && !quoteError && quote && selectedBuy && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote", children: [
|
|
3669
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
3670
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "You receive" }),
|
|
3671
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3672
|
+
"~ ",
|
|
3673
|
+
formatAmount2(quote.amountOut),
|
|
3674
|
+
" ",
|
|
3675
|
+
selectedBuy.code
|
|
3676
|
+
] })
|
|
3677
|
+
] }),
|
|
3678
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
3679
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Minimum received" }),
|
|
3680
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3681
|
+
formatAmount2(quote.minReceived),
|
|
3682
|
+
" ",
|
|
3683
|
+
selectedBuy.code
|
|
3684
|
+
] })
|
|
3685
|
+
] }),
|
|
3686
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
3687
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Price impact" }),
|
|
3688
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3689
|
+
quote.priceImpactPct,
|
|
3690
|
+
"%"
|
|
3691
|
+
] })
|
|
3692
|
+
] }),
|
|
3693
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
3694
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Route" }),
|
|
3695
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: PROVIDER_LABELS[quote.provider] })
|
|
3696
|
+
] })
|
|
3697
|
+
] }),
|
|
3698
|
+
!quoteLoading && !quoteError && !quote && selectedSell && selectedBuy && !!amount && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "No route found for this pair." }),
|
|
3699
|
+
formError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: formError }),
|
|
3700
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-btn-primary", onClick: onSwap, disabled: !canSwap, children: "Swap" }) })
|
|
3701
|
+
] }),
|
|
3702
|
+
step === "tx" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3703
|
+
TxStatusView,
|
|
3704
|
+
{
|
|
3705
|
+
transaction,
|
|
3706
|
+
showXdr,
|
|
3707
|
+
copied,
|
|
3708
|
+
explorerUrl,
|
|
3709
|
+
walletType,
|
|
3710
|
+
onSignAndSend: () => {
|
|
3711
|
+
},
|
|
3712
|
+
onToggleXdr,
|
|
3713
|
+
onCopyHash,
|
|
3714
|
+
onRetry,
|
|
3715
|
+
onDone
|
|
3716
|
+
}
|
|
3717
|
+
),
|
|
3718
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
3719
|
+
] });
|
|
3720
|
+
}
|
|
3721
|
+
var QUOTE_DEBOUNCE_MS = 400;
|
|
3722
|
+
var ALL_PROVIDERS = ["auto", "aquarius", "soroswap", "sdex"];
|
|
3723
|
+
function toRef(a) {
|
|
3724
|
+
if (a.type === "native") return { type: "native" };
|
|
3725
|
+
if (a.type === "credit_alphanum4") return { type: "credit_alphanum4", code: a.code, issuer: a.issuer };
|
|
3726
|
+
return { type: "credit_alphanum12", code: a.code, issuer: a.issuer };
|
|
3727
|
+
}
|
|
3728
|
+
function SwapModal({ onClose }) {
|
|
3729
|
+
const {
|
|
3730
|
+
getSwapQuote,
|
|
3731
|
+
swap,
|
|
3732
|
+
walletBalance,
|
|
3733
|
+
refreshWalletBalance,
|
|
3734
|
+
enabledAssets,
|
|
3735
|
+
refreshAssets,
|
|
3736
|
+
tx: transaction,
|
|
3737
|
+
wallet,
|
|
3738
|
+
network,
|
|
3739
|
+
styles
|
|
3740
|
+
} = usePollar();
|
|
3741
|
+
const walletType = wallet?.custody === "external" ? wallet.provider : null;
|
|
3742
|
+
const smartUnsupported = wallet?.custody === "smart";
|
|
3743
|
+
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
3744
|
+
const [step, setStep] = react.useState("form");
|
|
3745
|
+
const [selectedSell, setSelectedSell] = react.useState(null);
|
|
3746
|
+
const [selectedBuy, setSelectedBuy] = react.useState(null);
|
|
3747
|
+
const [amount, setAmount] = react.useState("");
|
|
3748
|
+
const [provider, setProvider] = react.useState("auto");
|
|
3749
|
+
const [quotes, setQuotes] = react.useState([]);
|
|
3750
|
+
const [quoteLoading, setQuoteLoading] = react.useState(false);
|
|
3751
|
+
const [quoteError, setQuoteError] = react.useState("");
|
|
3752
|
+
const [formError, setFormError] = react.useState("");
|
|
3753
|
+
const [showXdr, setShowXdr] = react.useState(false);
|
|
3754
|
+
const [copied, setCopied] = react.useState(false);
|
|
3755
|
+
const copyTimerRef = react.useRef(null);
|
|
3756
|
+
const slippageBps = 50;
|
|
3757
|
+
react.useEffect(() => {
|
|
3758
|
+
void refreshWalletBalance();
|
|
3759
|
+
void refreshAssets();
|
|
3760
|
+
}, [refreshWalletBalance, refreshAssets]);
|
|
3761
|
+
react.useEffect(
|
|
3762
|
+
() => () => {
|
|
3763
|
+
if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
|
|
3764
|
+
},
|
|
3765
|
+
[]
|
|
3766
|
+
);
|
|
3767
|
+
const balances = walletBalance.step === "loaded" ? walletBalance.data.balances : [];
|
|
3768
|
+
const assetRecords = enabledAssets.step === "loaded" ? enabledAssets.data.assets : [];
|
|
3769
|
+
const isLoadingData = walletBalance.step === "loading" || enabledAssets.step === "loading";
|
|
3770
|
+
const sellOptions = balances.filter((b) => parseFloat(b.available) > 0).map((b) => ({ ref: toRef(b), code: b.code, issuer: b.issuer, available: b.available, enabledInApp: b.enabledInApp }));
|
|
3771
|
+
const buyKeyOfSell = selectedSell ? `${selectedSell.code}:${selectedSell.issuer ?? "native"}` : "";
|
|
3772
|
+
const buyOptions = assetRecords.map((a) => ({ ref: toRef(a), code: a.code, issuer: a.issuer, enabledInApp: a.enabledInApp })).filter((o) => `${o.code}:${o.issuer ?? "native"}` !== buyKeyOfSell);
|
|
3773
|
+
const providers = smartUnsupported ? ALL_PROVIDERS.filter((p) => p !== "sdex") : ALL_PROVIDERS;
|
|
3774
|
+
const quote = quotes[0] ?? null;
|
|
3775
|
+
react.useEffect(() => {
|
|
3776
|
+
if (step !== "form" || !selectedSell || !selectedBuy || !amount || parseFloat(amount) <= 0) {
|
|
3777
|
+
setQuotes([]);
|
|
3778
|
+
setQuoteError("");
|
|
3779
|
+
setQuoteLoading(false);
|
|
3780
|
+
return;
|
|
3781
|
+
}
|
|
3782
|
+
let cancelled = false;
|
|
3783
|
+
setQuoteLoading(true);
|
|
3784
|
+
setQuoteError("");
|
|
3785
|
+
const t = setTimeout(async () => {
|
|
3786
|
+
try {
|
|
3787
|
+
const qs = await getSwapQuote({
|
|
3788
|
+
sellAsset: selectedSell.ref,
|
|
3789
|
+
buyAsset: selectedBuy.ref,
|
|
3790
|
+
amount,
|
|
3791
|
+
provider,
|
|
3792
|
+
slippageBps
|
|
3793
|
+
});
|
|
3794
|
+
if (!cancelled) setQuotes(qs);
|
|
3795
|
+
} catch (e) {
|
|
3796
|
+
if (!cancelled) {
|
|
3797
|
+
setQuotes([]);
|
|
3798
|
+
setQuoteError(e instanceof Error ? e.message : "Failed to fetch quote");
|
|
3799
|
+
}
|
|
3800
|
+
} finally {
|
|
3801
|
+
if (!cancelled) setQuoteLoading(false);
|
|
3802
|
+
}
|
|
3803
|
+
}, QUOTE_DEBOUNCE_MS);
|
|
3804
|
+
return () => {
|
|
3805
|
+
cancelled = true;
|
|
3806
|
+
clearTimeout(t);
|
|
3807
|
+
};
|
|
3808
|
+
}, [step, selectedSell, selectedBuy, amount, provider, getSwapQuote]);
|
|
3809
|
+
const hash = transaction.step === "success" ? transaction.hash : null;
|
|
3810
|
+
const buildData = "buildData" in transaction ? transaction.buildData : null;
|
|
3811
|
+
const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
|
|
3812
|
+
const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
|
|
3813
|
+
const IN_FLIGHT_STEPS2 = [
|
|
3814
|
+
"building",
|
|
3815
|
+
"signing",
|
|
3816
|
+
"submitting",
|
|
3817
|
+
"submitted",
|
|
3818
|
+
"signing-submitting",
|
|
3819
|
+
"building-signing-submitting"
|
|
3820
|
+
];
|
|
3821
|
+
const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
|
|
3822
|
+
const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
|
|
3823
|
+
const txTitle = isInProgress ? "Swapping\u2026" : transaction.step === "success" ? "Swapped!" : transaction.step === "error" ? "Swap failed" : "Confirm Swap";
|
|
3824
|
+
async function handleSwap() {
|
|
3825
|
+
setFormError("");
|
|
3826
|
+
if (smartUnsupported) {
|
|
3827
|
+
setFormError("Swaps are not yet supported for smart (passkey) wallets");
|
|
3828
|
+
return;
|
|
3829
|
+
}
|
|
3830
|
+
if (!selectedSell || !selectedBuy) {
|
|
3831
|
+
setFormError("Select both assets");
|
|
3832
|
+
return;
|
|
3833
|
+
}
|
|
3834
|
+
const parsed = parseFloat(amount);
|
|
3835
|
+
if (!amount || isNaN(parsed) || parsed <= 0) {
|
|
3836
|
+
setFormError("Enter a valid amount");
|
|
3837
|
+
return;
|
|
3838
|
+
}
|
|
3839
|
+
if (selectedSell.available !== void 0 && parsed > parseFloat(selectedSell.available)) {
|
|
3840
|
+
setFormError("Insufficient balance");
|
|
3841
|
+
return;
|
|
3842
|
+
}
|
|
3843
|
+
if (!quote) {
|
|
3844
|
+
setFormError("No route available for this pair");
|
|
3845
|
+
return;
|
|
3846
|
+
}
|
|
3847
|
+
setStep("tx");
|
|
3848
|
+
await swap(quote);
|
|
3849
|
+
}
|
|
3850
|
+
async function handleRetry() {
|
|
3851
|
+
if (transaction.step === "error" && quote) await swap(quote);
|
|
3852
|
+
}
|
|
3853
|
+
function handleCopyHash() {
|
|
3854
|
+
if (!hash) return;
|
|
3855
|
+
navigator.clipboard.writeText(hash).then(() => {
|
|
3856
|
+
setCopied(true);
|
|
3857
|
+
if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
|
|
3858
|
+
copyTimerRef.current = setTimeout(() => {
|
|
3859
|
+
copyTimerRef.current = null;
|
|
3860
|
+
setCopied(false);
|
|
3861
|
+
}, 2e3);
|
|
3862
|
+
});
|
|
3863
|
+
}
|
|
3864
|
+
function handleBack() {
|
|
3865
|
+
setStep("form");
|
|
3866
|
+
setShowXdr(false);
|
|
3867
|
+
setCopied(false);
|
|
3868
|
+
}
|
|
3869
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3870
|
+
SwapModalTemplate,
|
|
3871
|
+
{
|
|
3872
|
+
theme,
|
|
3873
|
+
accentColor,
|
|
3874
|
+
step,
|
|
3875
|
+
txTitle,
|
|
3876
|
+
sellOptions,
|
|
3877
|
+
buyOptions,
|
|
3878
|
+
selectedSell,
|
|
3879
|
+
selectedBuy,
|
|
3880
|
+
amount,
|
|
3881
|
+
provider,
|
|
3882
|
+
providers,
|
|
3883
|
+
quote,
|
|
3884
|
+
quoteLoading,
|
|
3885
|
+
quoteError,
|
|
3886
|
+
formError,
|
|
3887
|
+
isLoadingData,
|
|
3888
|
+
smartUnsupported,
|
|
3889
|
+
transaction,
|
|
3890
|
+
showXdr,
|
|
3891
|
+
copied,
|
|
3892
|
+
explorerUrl,
|
|
3893
|
+
walletType,
|
|
3894
|
+
showBack,
|
|
3895
|
+
isInProgress,
|
|
3896
|
+
onClose,
|
|
3897
|
+
onBack: handleBack,
|
|
3898
|
+
onSelectSell: setSelectedSell,
|
|
3899
|
+
onSelectBuy: setSelectedBuy,
|
|
3900
|
+
onAmountChange: setAmount,
|
|
3901
|
+
onProviderChange: setProvider,
|
|
3902
|
+
onSwap: () => void handleSwap(),
|
|
3903
|
+
onToggleXdr: () => setShowXdr((v) => !v),
|
|
3904
|
+
onCopyHash: handleCopyHash,
|
|
3905
|
+
onRetry: () => void handleRetry(),
|
|
3906
|
+
onDone: onClose
|
|
3907
|
+
}
|
|
3908
|
+
) });
|
|
3909
|
+
}
|
|
3283
3910
|
function describeDevice(s) {
|
|
3284
3911
|
if (s.deviceLabel) return s.deviceLabel;
|
|
3285
3912
|
if (!s.userAgent) return "Unknown device";
|
|
@@ -3567,7 +4194,8 @@ function TransactionModalTemplate({
|
|
|
3567
4194
|
] });
|
|
3568
4195
|
}
|
|
3569
4196
|
function TransactionModal({ onClose }) {
|
|
3570
|
-
const { getClient, styles, tx: transaction, network,
|
|
4197
|
+
const { getClient, styles, tx: transaction, network, wallet } = usePollar();
|
|
4198
|
+
const walletType = wallet?.custody === "external" ? wallet.provider : null;
|
|
3571
4199
|
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
3572
4200
|
const [showXdr, setShowXdr] = react.useState(false);
|
|
3573
4201
|
const [copied, setCopied] = react.useState(false);
|
|
@@ -3889,7 +4517,8 @@ function WalletBalanceModalTemplate({
|
|
|
3889
4517
|
] });
|
|
3890
4518
|
}
|
|
3891
4519
|
function WalletBalanceModal({ onClose }) {
|
|
3892
|
-
const { walletBalance, refreshWalletBalance,
|
|
4520
|
+
const { walletBalance, refreshWalletBalance, wallet, styles } = usePollar();
|
|
4521
|
+
const walletAddress = wallet?.address ?? "";
|
|
3893
4522
|
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
3894
4523
|
react.useEffect(() => {
|
|
3895
4524
|
void refreshWalletBalance();
|
|
@@ -3972,7 +4601,6 @@ var PollarContext = react.createContext(null);
|
|
|
3972
4601
|
function PollarProvider({
|
|
3973
4602
|
client,
|
|
3974
4603
|
appConfig: appConfigProp,
|
|
3975
|
-
ui,
|
|
3976
4604
|
adapters,
|
|
3977
4605
|
onStorageDegrade,
|
|
3978
4606
|
children
|
|
@@ -4024,6 +4652,30 @@ function PollarProvider({
|
|
|
4024
4652
|
}
|
|
4025
4653
|
});
|
|
4026
4654
|
}, [pollarClient]);
|
|
4655
|
+
const sessionRef = react.useRef(sessionState);
|
|
4656
|
+
sessionRef.current = sessionState;
|
|
4657
|
+
react.useEffect(() => {
|
|
4658
|
+
const unsubscribes = [];
|
|
4659
|
+
for (const { id } of pollarClient.listWalletAdapters()) {
|
|
4660
|
+
const adapter = pollarClient.getWalletAdapter(id);
|
|
4661
|
+
if (!core.isInteractiveAuthAdapter(adapter) || !adapter.onProviderAuthChange) continue;
|
|
4662
|
+
let triggered = false;
|
|
4663
|
+
unsubscribes.push(
|
|
4664
|
+
adapter.onProviderAuthChange((state) => {
|
|
4665
|
+
if (!state.authenticated || !state.address) {
|
|
4666
|
+
triggered = false;
|
|
4667
|
+
return;
|
|
4668
|
+
}
|
|
4669
|
+
if (triggered || sessionRef.current?.wallet?.address) return;
|
|
4670
|
+
triggered = true;
|
|
4671
|
+
pollarClient.login({ provider: id });
|
|
4672
|
+
})
|
|
4673
|
+
);
|
|
4674
|
+
}
|
|
4675
|
+
return () => {
|
|
4676
|
+
for (const unsubscribe of unsubscribes) unsubscribe();
|
|
4677
|
+
};
|
|
4678
|
+
}, [pollarClient]);
|
|
4027
4679
|
react.useEffect(() => {
|
|
4028
4680
|
setModalErrorLogger(pollarClient.getLogger());
|
|
4029
4681
|
}, [pollarClient]);
|
|
@@ -4049,6 +4701,7 @@ function PollarProvider({
|
|
|
4049
4701
|
const [walletBalanceModalOpen, setWalletBalanceModalOpen] = react.useState(false);
|
|
4050
4702
|
const [enabledAssetsModalOpen, setEnabledAssetsModalOpen] = react.useState(false);
|
|
4051
4703
|
const [sendModalOpen, setSendModalOpen] = react.useState(false);
|
|
4704
|
+
const [swapModalOpen, setSwapModalOpen] = react.useState(false);
|
|
4052
4705
|
const [receiveModalOpen, setReceiveModalOpen] = react.useState(false);
|
|
4053
4706
|
const [sessionsModalOpen, setSessionsModalOpen] = react.useState(false);
|
|
4054
4707
|
const [distributionRulesModalOpen, setDistributionRulesModalOpen] = react.useState(false);
|
|
@@ -4056,15 +4709,13 @@ function PollarProvider({
|
|
|
4056
4709
|
const getClient = react.useCallback(() => pollarClient, [pollarClient]);
|
|
4057
4710
|
const refreshWalletBalance = react.useCallback(() => pollarClient.refreshBalance(), [pollarClient, walletAddress]);
|
|
4058
4711
|
const refreshAssets = react.useCallback(() => pollarClient.refreshAssets(), [pollarClient, walletAddress]);
|
|
4059
|
-
const renderWallets = ui?.renderWallets;
|
|
4060
4712
|
const contextValue = react.useMemo(() => {
|
|
4061
4713
|
const styles = resolvedConfig.styles ?? {};
|
|
4062
4714
|
return {
|
|
4063
4715
|
// session
|
|
4064
|
-
|
|
4716
|
+
wallet: pollarClient.getWallet(),
|
|
4065
4717
|
isAuthenticated: !!walletAddress,
|
|
4066
4718
|
verified,
|
|
4067
|
-
walletType: pollarClient.getWalletType(),
|
|
4068
4719
|
// client
|
|
4069
4720
|
getClient,
|
|
4070
4721
|
// auth
|
|
@@ -4095,6 +4746,10 @@ function PollarProvider({
|
|
|
4095
4746
|
// send / receive
|
|
4096
4747
|
openSendModal: () => setSendModalOpen(true),
|
|
4097
4748
|
openReceiveModal: () => setReceiveModalOpen(true),
|
|
4749
|
+
// swap
|
|
4750
|
+
getSwapQuote: (params) => pollarClient.getSwapQuote(params),
|
|
4751
|
+
swap: (quote, opts) => pollarClient.swap(quote, opts),
|
|
4752
|
+
openSwapModal: () => setSwapModalOpen(true),
|
|
4098
4753
|
// sessions
|
|
4099
4754
|
sessions,
|
|
4100
4755
|
openSessionsModal: () => setSessionsModalOpen(true),
|
|
@@ -4113,7 +4768,6 @@ function PollarProvider({
|
|
|
4113
4768
|
// config
|
|
4114
4769
|
appConfig: resolvedConfig,
|
|
4115
4770
|
styles,
|
|
4116
|
-
renderWallets,
|
|
4117
4771
|
adapters
|
|
4118
4772
|
};
|
|
4119
4773
|
}, [
|
|
@@ -4130,8 +4784,7 @@ function PollarProvider({
|
|
|
4130
4784
|
refreshAssets,
|
|
4131
4785
|
networkState,
|
|
4132
4786
|
resolvedConfig,
|
|
4133
|
-
adapters
|
|
4134
|
-
renderWallets
|
|
4787
|
+
adapters
|
|
4135
4788
|
]);
|
|
4136
4789
|
return /* @__PURE__ */ jsxRuntime.jsxs(PollarContext.Provider, { value: contextValue, children: [
|
|
4137
4790
|
children,
|
|
@@ -4151,6 +4804,7 @@ function PollarProvider({
|
|
|
4151
4804
|
walletBalanceModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setWalletBalanceModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(WalletBalanceModal, { onClose: () => setWalletBalanceModalOpen(false) }) }),
|
|
4152
4805
|
enabledAssetsModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setEnabledAssetsModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(EnabledAssetsModal, { onClose: () => setEnabledAssetsModalOpen(false) }) }),
|
|
4153
4806
|
sendModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSendModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SendModal, { onClose: () => setSendModalOpen(false) }) }),
|
|
4807
|
+
swapModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSwapModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SwapModal, { onClose: () => setSwapModalOpen(false) }) }),
|
|
4154
4808
|
receiveModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setReceiveModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(ReceiveModal, { onClose: () => setReceiveModalOpen(false) }) }),
|
|
4155
4809
|
sessionsModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSessionsModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SessionsModal, { onClose: () => setSessionsModalOpen(false) }) }),
|
|
4156
4810
|
distributionRulesModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setDistributionRulesModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(DistributionRulesModal, { onClose: () => setDistributionRulesModalOpen(false) }) })
|
|
@@ -4484,7 +5138,7 @@ function WalletButtonTemplate({
|
|
|
4484
5138
|
function WalletButton() {
|
|
4485
5139
|
const {
|
|
4486
5140
|
getClient,
|
|
4487
|
-
|
|
5141
|
+
wallet,
|
|
4488
5142
|
styles,
|
|
4489
5143
|
openLoginModal,
|
|
4490
5144
|
openTxHistoryModal,
|
|
@@ -4495,9 +5149,10 @@ function WalletButton() {
|
|
|
4495
5149
|
openKycModal,
|
|
4496
5150
|
openRampModal,
|
|
4497
5151
|
openDistributionRulesModal,
|
|
4498
|
-
tx: transaction
|
|
4499
|
-
walletType
|
|
5152
|
+
tx: transaction
|
|
4500
5153
|
} = usePollar();
|
|
5154
|
+
const walletAddress = wallet?.address ?? "";
|
|
5155
|
+
const walletType = wallet?.custody === "external" ? wallet.provider : null;
|
|
4501
5156
|
const [open, setOpen] = react.useState(false);
|
|
4502
5157
|
const [copied, setCopied] = react.useState(false);
|
|
4503
5158
|
const wrapperRef = react.useRef(null);
|
|
@@ -4616,6 +5271,8 @@ exports.SendModal = SendModal;
|
|
|
4616
5271
|
exports.SendModalTemplate = SendModalTemplate;
|
|
4617
5272
|
exports.SessionsModal = SessionsModal;
|
|
4618
5273
|
exports.SessionsModalTemplate = SessionsModalTemplate;
|
|
5274
|
+
exports.SwapModal = SwapModal;
|
|
5275
|
+
exports.SwapModalTemplate = SwapModalTemplate;
|
|
4619
5276
|
exports.TransactionModalTemplate = TransactionModalTemplate;
|
|
4620
5277
|
exports.TxHistoryModalTemplate = TxHistoryModalTemplate;
|
|
4621
5278
|
exports.TxStatusView = TxStatusView;
|