@pollar/react 0.10.1-rc.0 → 0.10.1-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/dist/index.mjs CHANGED
@@ -1033,11 +1033,53 @@ var PollarModalFooter = () => {
1033
1033
  /* @__PURE__ */ jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
1034
1034
  /* @__PURE__ */ jsxs("span", { className: "pollar-footer-version", children: [
1035
1035
  "v",
1036
- "0.10.1-rc.0"
1036
+ "0.10.1-rc.10"
1037
1037
  ] })
1038
1038
  ] })
1039
1039
  ] });
1040
1040
  };
1041
+ function CopyButton({ value, label = "Copy", className }) {
1042
+ const [copied, setCopied] = useState(false);
1043
+ const timerRef = useRef(null);
1044
+ useEffect(() => {
1045
+ return () => {
1046
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
1047
+ };
1048
+ }, []);
1049
+ function handleCopy(e) {
1050
+ e.stopPropagation();
1051
+ if (!value || !navigator.clipboard) return;
1052
+ void navigator.clipboard.writeText(value).then(() => {
1053
+ setCopied(true);
1054
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
1055
+ timerRef.current = setTimeout(() => {
1056
+ setCopied(false);
1057
+ timerRef.current = null;
1058
+ }, 1500);
1059
+ });
1060
+ }
1061
+ return /* @__PURE__ */ jsx(
1062
+ "button",
1063
+ {
1064
+ type: "button",
1065
+ className: `pollar-copy-btn${className ? ` ${className}` : ""}`,
1066
+ onClick: handleCopy,
1067
+ "aria-label": copied ? "Copied" : label,
1068
+ children: copied ? /* @__PURE__ */ jsx("svg", { width: "13", height: "13", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M3.5 7l2.5 2.5 4.5-5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) : /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
1069
+ /* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
1070
+ /* @__PURE__ */ jsx(
1071
+ "path",
1072
+ {
1073
+ d: "M3 9H2a1 1 0 01-1-1V2a1 1 0 011-1h6a1 1 0 011 1v1",
1074
+ stroke: "currentColor",
1075
+ strokeWidth: "1.5",
1076
+ strokeLinecap: "round"
1077
+ }
1078
+ )
1079
+ ] })
1080
+ }
1081
+ );
1082
+ }
1041
1083
  function ModalStatusBanner({ message, status, onCancel, onRetry }) {
1042
1084
  if (!message && status === "NONE") {
1043
1085
  return /* @__PURE__ */ jsx("div", { className: "pollar-status" });
@@ -1116,7 +1158,10 @@ function RuleCard({
1116
1158
  validity
1117
1159
  ] })
1118
1160
  ] }),
1119
- /* @__PURE__ */ jsx("div", { className: "pollar-dist-item-action", children: isClaimed ? /* @__PURE__ */ jsx("span", { className: "pollar-dist-item-status", "data-kind": "claimed", children: "Claimed" }) : effectivelyClaimable ? /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary pollar-dist-claim-btn", onClick: onClaim, disabled: isClaiming, children: isClaiming ? "Claiming\u2026" : "Claim" }) : /* @__PURE__ */ jsx("span", { className: "pollar-dist-item-status", "data-kind": "unavailable", children: reasonLabel(rule.reason) }) }),
1161
+ /* @__PURE__ */ jsx("div", { className: "pollar-dist-item-action", children: isClaimed ? /* @__PURE__ */ jsx("span", { className: "pollar-dist-item-status", "data-kind": "claimed", children: "Claimed" }) : effectivelyClaimable ? /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary pollar-dist-claim-btn", onClick: onClaim, disabled: isClaiming, children: isClaiming ? /* @__PURE__ */ jsxs(Fragment, { children: [
1162
+ /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
1163
+ "Claiming\u2026"
1164
+ ] }) : "Claim" }) : /* @__PURE__ */ jsx("span", { className: "pollar-dist-item-status", "data-kind": "unavailable", children: reasonLabel(rule.reason) }) }),
1120
1165
  errorMessage && /* @__PURE__ */ jsx("div", { className: "pollar-dist-item-error", children: errorMessage })
1121
1166
  ] });
1122
1167
  }
@@ -1162,29 +1207,46 @@ function DistributionRulesModalTemplate({
1162
1207
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
1163
1208
  /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Distribution Rules" }),
1164
1209
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
1165
- /* @__PURE__ */ jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading, children: [
1166
- /* @__PURE__ */ jsxs(
1167
- "svg",
1168
- {
1169
- className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
1170
- width: "13",
1171
- height: "13",
1172
- viewBox: "0 0 13 13",
1173
- fill: "none",
1174
- "aria-hidden": true,
1175
- children: [
1176
- /* @__PURE__ */ jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1177
- /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1178
- ]
1179
- }
1180
- ),
1181
- "Refresh"
1182
- ] }),
1210
+ /* @__PURE__ */ jsx(
1211
+ "button",
1212
+ {
1213
+ type: "button",
1214
+ className: "pollar-modal-close",
1215
+ onClick: onRefresh,
1216
+ disabled: isLoading,
1217
+ "aria-label": "Refresh",
1218
+ title: "Refresh",
1219
+ children: /* @__PURE__ */ jsx(
1220
+ "svg",
1221
+ {
1222
+ className: isLoading ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
1223
+ width: "16",
1224
+ height: "16",
1225
+ viewBox: "0 0 16 16",
1226
+ fill: "none",
1227
+ "aria-hidden": true,
1228
+ children: /* @__PURE__ */ jsx(
1229
+ "path",
1230
+ {
1231
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
1232
+ stroke: "currentColor",
1233
+ strokeWidth: "1.6",
1234
+ strokeLinecap: "round",
1235
+ strokeLinejoin: "round"
1236
+ }
1237
+ )
1238
+ }
1239
+ )
1240
+ }
1241
+ ),
1183
1242
  /* @__PURE__ */ jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
1184
1243
  ] })
1185
1244
  ] }),
1186
1245
  /* @__PURE__ */ jsxs("div", { className: "pollar-dist-list", children: [
1187
- isLoading && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
1246
+ isLoading && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
1247
+ /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
1248
+ /* @__PURE__ */ jsx("span", { children: "Loading\u2026" })
1249
+ ] }),
1188
1250
  state.step === "error" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: state.message }),
1189
1251
  state.step === "loaded" && rules.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No distribution rules available." }),
1190
1252
  rules.map((rule) => /* @__PURE__ */ jsx(
@@ -1309,14 +1371,14 @@ function AssetItem({
1309
1371
  !isNative && record.enabledInApp && /* @__PURE__ */ jsx("span", { className: "pollar-asset-sponsor", children: record.sponsored ? "Reserve sponsored by the app" : "You pay the reserve (~0.5 XLM)" })
1310
1372
  ] }),
1311
1373
  /* @__PURE__ */ jsxs("div", { className: "pollar-asset-actions", children: [
1312
- /* @__PURE__ */ jsx("span", { className: `pollar-asset-trustline${established ? " established" : ""}`, children: established ? "Trustline active" : "Needs trustline" }),
1374
+ /* @__PURE__ */ jsx("span", { className: `pollar-asset-trustline${established ? " pollar-established" : ""}`, children: established ? "Trustline active" : "Needs trustline" }),
1313
1375
  !isNative && /* @__PURE__ */ jsx(
1314
1376
  "button",
1315
1377
  {
1316
- className: `pollar-asset-btn${established ? " danger" : ""}`,
1378
+ className: `pollar-asset-btn${established ? " pollar-danger" : ""}`,
1317
1379
  onClick: () => onToggle(record),
1318
1380
  disabled: busy || disabled,
1319
- children: busy ? "\u2026" : established ? "Disable" : "Enable"
1381
+ children: busy ? /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm pollar-spinner-current" }) : established ? "Disable" : "Enable"
1320
1382
  }
1321
1383
  )
1322
1384
  ] })
@@ -1349,29 +1411,46 @@ function EnabledAssetsModalTemplate({
1349
1411
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
1350
1412
  /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Trustlines" }),
1351
1413
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
1352
- /* @__PURE__ */ jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading || busy, children: [
1353
- /* @__PURE__ */ jsxs(
1354
- "svg",
1355
- {
1356
- className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
1357
- width: "13",
1358
- height: "13",
1359
- viewBox: "0 0 13 13",
1360
- fill: "none",
1361
- "aria-hidden": true,
1362
- children: [
1363
- /* @__PURE__ */ jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1364
- /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1365
- ]
1366
- }
1367
- ),
1368
- "Refresh"
1369
- ] }),
1414
+ /* @__PURE__ */ jsx(
1415
+ "button",
1416
+ {
1417
+ type: "button",
1418
+ className: "pollar-modal-close",
1419
+ onClick: onRefresh,
1420
+ disabled: isLoading || busy,
1421
+ "aria-label": "Refresh",
1422
+ title: "Refresh",
1423
+ children: /* @__PURE__ */ jsx(
1424
+ "svg",
1425
+ {
1426
+ className: isLoading ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
1427
+ width: "16",
1428
+ height: "16",
1429
+ viewBox: "0 0 16 16",
1430
+ fill: "none",
1431
+ "aria-hidden": true,
1432
+ children: /* @__PURE__ */ jsx(
1433
+ "path",
1434
+ {
1435
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
1436
+ stroke: "currentColor",
1437
+ strokeWidth: "1.6",
1438
+ strokeLinecap: "round",
1439
+ strokeLinejoin: "round"
1440
+ }
1441
+ )
1442
+ }
1443
+ )
1444
+ }
1445
+ ),
1370
1446
  /* @__PURE__ */ jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
1371
1447
  ] })
1372
1448
  ] }),
1373
1449
  walletAddress && /* @__PURE__ */ jsx("div", { className: "pollar-asset-address", children: cropAddress(walletAddress) }),
1374
- isLoading && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
1450
+ isLoading && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
1451
+ /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
1452
+ /* @__PURE__ */ jsx("span", { children: "Loading\u2026" })
1453
+ ] }),
1375
1454
  enabledAssets.step === "error" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: enabledAssets.message }),
1376
1455
  actionError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-action-error", children: actionError }),
1377
1456
  data && !data.exists && /* @__PURE__ */ jsxs("div", { className: "pollar-modal-empty", children: [
@@ -1430,7 +1509,7 @@ function CustomTrustlineModalTemplate({
1430
1509
  children: [
1431
1510
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
1432
1511
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
1433
- /* @__PURE__ */ jsx("button", { className: "pollar-modal-back", onClick: onBack, disabled: busy, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
1512
+ /* @__PURE__ */ jsx("button", { className: "pollar-modal-close", onClick: onBack, disabled: busy, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
1434
1513
  /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Add custom trustline" })
1435
1514
  ] }),
1436
1515
  /* @__PURE__ */ jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
@@ -1491,7 +1570,10 @@ function CustomTrustlineModalTemplate({
1491
1570
  )
1492
1571
  ] }),
1493
1572
  actionError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-action-error", children: actionError }),
1494
- /* @__PURE__ */ jsx("button", { className: "pollar-asset-submit", onClick: submit, disabled: !canSubmit, children: busy ? "Enabling\u2026" : "Enable trustline" }),
1573
+ /* @__PURE__ */ jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", onClick: submit, disabled: !canSubmit, children: busy ? /* @__PURE__ */ jsxs(Fragment, { children: [
1574
+ /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
1575
+ "Enabling\u2026"
1576
+ ] }) : "Enable trustline" }) }),
1495
1577
  /* @__PURE__ */ jsx(PollarModalFooter, {})
1496
1578
  ]
1497
1579
  }
@@ -1612,6 +1694,7 @@ function KycModalTemplate({
1612
1694
  isLoading,
1613
1695
  onSelectProvider,
1614
1696
  onDoneVerifying,
1697
+ onRefresh,
1615
1698
  onClose
1616
1699
  }) {
1617
1700
  const isDark = theme === "dark";
@@ -1636,16 +1719,56 @@ function KycModalTemplate({
1636
1719
  "--pollar-modal-subtitle-size": "0.9rem"
1637
1720
  };
1638
1721
  return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-kyc-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
1639
- /* @__PURE__ */ jsxs("div", { className: "pollar-kyc-header", children: [
1640
- /* @__PURE__ */ jsx("h2", { className: "pollar-kyc-title", children: "Identity verification" }),
1641
- /* @__PURE__ */ jsxs("p", { className: "pollar-kyc-subtitle", children: [
1642
- step === "select_provider" && "Choose your verification provider",
1643
- step === "verifying" && `Verifying with ${selectedProvider?.name}`,
1644
- step === "polling" && "Waiting for verification result",
1645
- step === "done" && "Verification complete"
1722
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
1723
+ /* @__PURE__ */ jsxs("div", { className: "pollar-kyc-header-text", children: [
1724
+ /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Identity verification" }),
1725
+ /* @__PURE__ */ jsxs("p", { className: "pollar-kyc-subtitle", children: [
1726
+ step === "select_provider" && "Choose your verification provider",
1727
+ step === "verifying" && `Verifying with ${selectedProvider?.name}`,
1728
+ step === "polling" && "Waiting for verification result",
1729
+ step === "done" && "Verification complete"
1730
+ ] })
1731
+ ] }),
1732
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
1733
+ step === "select_provider" && /* @__PURE__ */ jsx(
1734
+ "button",
1735
+ {
1736
+ type: "button",
1737
+ className: "pollar-modal-close",
1738
+ onClick: onRefresh,
1739
+ disabled: isLoading,
1740
+ "aria-label": "Refresh",
1741
+ title: "Refresh providers",
1742
+ children: /* @__PURE__ */ jsx(
1743
+ "svg",
1744
+ {
1745
+ className: isLoading ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
1746
+ width: "16",
1747
+ height: "16",
1748
+ viewBox: "0 0 16 16",
1749
+ fill: "none",
1750
+ "aria-hidden": true,
1751
+ children: /* @__PURE__ */ jsx(
1752
+ "path",
1753
+ {
1754
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
1755
+ stroke: "currentColor",
1756
+ strokeWidth: "1.6",
1757
+ strokeLinecap: "round",
1758
+ strokeLinejoin: "round"
1759
+ }
1760
+ )
1761
+ }
1762
+ )
1763
+ }
1764
+ ),
1765
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
1646
1766
  ] })
1647
1767
  ] }),
1648
- step === "select_provider" && /* @__PURE__ */ jsxs("div", { className: "pollar-kyc-providers", children: [
1768
+ step === "select_provider" && (isLoading && providers.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
1769
+ /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
1770
+ /* @__PURE__ */ jsx("span", { children: "Loading providers\u2026" })
1771
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "pollar-kyc-providers", children: [
1649
1772
  providers.length === 0 && /* @__PURE__ */ jsx("p", { style: { color: "var(--pollar-muted)", textAlign: "center" }, children: "No providers available for your country." }),
1650
1773
  providers.map((p) => /* @__PURE__ */ jsxs(
1651
1774
  "button",
@@ -1661,7 +1784,7 @@ function KycModalTemplate({
1661
1784
  },
1662
1785
  p.id
1663
1786
  ))
1664
- ] }),
1787
+ ] })),
1665
1788
  step === "verifying" && selectedProvider && /* @__PURE__ */ jsxs(Fragment, { children: [
1666
1789
  /* @__PURE__ */ jsx("div", { className: "pollar-kyc-iframe-wrap", children: session?.kycUrl ? /* @__PURE__ */ jsx("iframe", { className: "pollar-kyc-iframe", src: session.kycUrl, title: "KYC verification", allow: "camera; microphone" }) : /* @__PURE__ */ jsxs("div", { className: "pollar-kyc-iframe-mock", children: [
1667
1790
  /* @__PURE__ */ jsx("span", { children: "\u{1F512}" }),
@@ -1694,10 +1817,13 @@ function KycModal({ onClose, country = "MX", level = "basic", onApproved }) {
1694
1817
  const [isLoading, setIsLoading] = useState(false);
1695
1818
  const client = getClient();
1696
1819
  const { theme = "light", accentColor = "#005DB4" } = styles;
1697
- useEffect(() => {
1820
+ const loadProviders = useCallback(() => {
1698
1821
  setIsLoading(true);
1699
- getClient().getKycProviders(country).then((result) => setProviders(result.providers)).catch(() => setProviders([])).finally(() => setIsLoading(false));
1822
+ return getClient().getKycProviders(country).then((result) => setProviders(result.providers)).catch(() => setProviders([])).finally(() => setIsLoading(false));
1700
1823
  }, [getClient, country]);
1824
+ useEffect(() => {
1825
+ void loadProviders();
1826
+ }, [loadProviders]);
1701
1827
  async function handleSelectProvider(provider) {
1702
1828
  setSelectedProvider(provider);
1703
1829
  setIsLoading(true);
@@ -1743,6 +1869,7 @@ function KycModal({ onClose, country = "MX", level = "basic", onApproved }) {
1743
1869
  isLoading,
1744
1870
  onSelectProvider: handleSelectProvider,
1745
1871
  onDoneVerifying: handleDoneVerifying,
1872
+ onRefresh: () => void loadProviders(),
1746
1873
  onClose
1747
1874
  }
1748
1875
  ) });
@@ -1798,8 +1925,8 @@ function EmailCodeInput({ email, onSubmit }) {
1798
1925
  ] });
1799
1926
  }
1800
1927
  var GithubButton = ({ disabled, onClick }) => {
1801
- return /* @__PURE__ */ jsxs("button", { className: "github-button", disabled, onClick, children: [
1802
- /* @__PURE__ */ jsx("svg", { className: "github-button-icon", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx(
1928
+ return /* @__PURE__ */ jsxs("button", { className: "pollar-github-button", disabled, onClick, children: [
1929
+ /* @__PURE__ */ jsx("svg", { className: "pollar-github-button-icon", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx(
1803
1930
  "path",
1804
1931
  {
1805
1932
  fillRule: "evenodd",
@@ -1807,14 +1934,14 @@ var GithubButton = ({ disabled, onClick }) => {
1807
1934
  clipRule: "evenodd"
1808
1935
  }
1809
1936
  ) }),
1810
- /* @__PURE__ */ jsx("span", { className: "github-button-contents", children: "GitHub" })
1937
+ /* @__PURE__ */ jsx("span", { className: "pollar-github-button-contents", children: "GitHub" })
1811
1938
  ] });
1812
1939
  };
1813
1940
  var GoogleButton = ({ disabled, onClick }) => {
1814
- return /* @__PURE__ */ jsxs("button", { className: "gsi-material-button", disabled, onClick, children: [
1815
- /* @__PURE__ */ jsx("div", { className: "gsi-material-button-state" }),
1816
- /* @__PURE__ */ jsxs("div", { className: "gsi-material-button-content-wrapper", children: [
1817
- /* @__PURE__ */ jsx("div", { className: "gsi-material-button-icon", children: /* @__PURE__ */ jsxs("svg", { version: "1.1", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 48 48", style: { display: "block" }, children: [
1941
+ return /* @__PURE__ */ jsxs("button", { className: "pollar-gsi-material-button", disabled, onClick, children: [
1942
+ /* @__PURE__ */ jsx("div", { className: "pollar-gsi-material-button-state" }),
1943
+ /* @__PURE__ */ jsxs("div", { className: "pollar-gsi-material-button-content-wrapper", children: [
1944
+ /* @__PURE__ */ jsx("div", { className: "pollar-gsi-material-button-icon", children: /* @__PURE__ */ jsxs("svg", { version: "1.1", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 48 48", style: { display: "block" }, children: [
1818
1945
  /* @__PURE__ */ jsx(
1819
1946
  "path",
1820
1947
  {
@@ -1845,7 +1972,7 @@ var GoogleButton = ({ disabled, onClick }) => {
1845
1972
  ),
1846
1973
  /* @__PURE__ */ jsx("path", { fill: "none", d: "M0 0h48v48H0z" })
1847
1974
  ] }) }),
1848
- /* @__PURE__ */ jsx("span", { className: "gsi-material-button-contents", children: "Google" }),
1975
+ /* @__PURE__ */ jsx("span", { className: "pollar-gsi-material-button-contents", children: "Google" }),
1849
1976
  /* @__PURE__ */ jsx("span", { style: { display: "none" }, children: "Google" })
1850
1977
  ] })
1851
1978
  ] });
@@ -2051,7 +2178,7 @@ function LoginModalTemplate({
2051
2178
  placeholder: "you@email.com",
2052
2179
  value: email,
2053
2180
  disabled: isLoading,
2054
- className: "pollar-email-input",
2181
+ className: "pollar-input",
2055
2182
  onChange: (e) => onEmailChange?.(e.target.value),
2056
2183
  onKeyDown: (e) => e.key === "Enter" && onEmailSubmit?.()
2057
2184
  }
@@ -2230,12 +2357,38 @@ function PrivyLoginSubmodal({
2230
2357
  fail(error);
2231
2358
  }
2232
2359
  }
2233
- const BackButton = ({ onClick }) => /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-back-btn", onClick, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M15 19l-7-7 7-7" }) }) });
2360
+ const BackButton = ({ onClick }) => /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-back-btn", onClick, "aria-label": "Back", children: /* @__PURE__ */ jsx(
2361
+ "svg",
2362
+ {
2363
+ width: "20",
2364
+ height: "20",
2365
+ viewBox: "0 0 24 24",
2366
+ fill: "none",
2367
+ stroke: "currentColor",
2368
+ strokeWidth: "2.5",
2369
+ strokeLinecap: "round",
2370
+ strokeLinejoin: "round",
2371
+ children: /* @__PURE__ */ jsx("path", { d: "M15 19l-7-7 7-7" })
2372
+ }
2373
+ ) });
2234
2374
  const showEmail = options.includes("email");
2235
2375
  const showGoogle = options.includes("google");
2236
2376
  const showGithub = options.includes("github");
2237
2377
  return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
2238
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-close-btn", onClick: onCancel, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) }),
2378
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-close-btn", onClick: onCancel, "aria-label": "Close", children: /* @__PURE__ */ jsx(
2379
+ "svg",
2380
+ {
2381
+ width: "18",
2382
+ height: "18",
2383
+ viewBox: "0 0 24 24",
2384
+ fill: "none",
2385
+ stroke: "currentColor",
2386
+ strokeWidth: "2.5",
2387
+ strokeLinecap: "round",
2388
+ strokeLinejoin: "round",
2389
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
2390
+ }
2391
+ ) }),
2239
2392
  /* @__PURE__ */ jsxs("div", { className: "pollar-header", children: [
2240
2393
  /* @__PURE__ */ jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsx("img", { src: logoUrl ?? LOGO_POLLAR, alt: "Logo", className: "pollar-logo" }) }),
2241
2394
  /* @__PURE__ */ jsx("h2", { className: "pollar-title", children: appName }),
@@ -2254,7 +2407,7 @@ function PrivyLoginSubmodal({
2254
2407
  placeholder: "you@email.com",
2255
2408
  value: email,
2256
2409
  disabled: isLoading,
2257
- className: "pollar-email-input",
2410
+ className: "pollar-input",
2258
2411
  onChange: (e) => setEmail(e.target.value),
2259
2412
  onKeyDown: (e) => e.key === "Enter" && handleEmailSubmit()
2260
2413
  }
@@ -2456,21 +2609,63 @@ function RouteDisplay({ quote, onSelect }) {
2456
2609
  }
2457
2610
  );
2458
2611
  }
2612
+ var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2613
+ function isFieldValid(spec, raw) {
2614
+ const value = (raw ?? "").trim();
2615
+ if (!value) return false;
2616
+ if (spec.type === "email") return EMAIL_RE.test(value);
2617
+ return true;
2618
+ }
2459
2619
  var LOADING_STEPS = ["Detecting your country\u2026", "Consulting providers\u2026", "Route found!"];
2460
- var COUNTRY_CURRENCIES = {
2461
- MX: "MXN",
2462
- BR: "BRL",
2463
- CO: "COP",
2464
- CL: "CLP",
2465
- PE: "PEN",
2466
- AR: "ARS"
2467
- };
2620
+ function flagEmoji(code) {
2621
+ const cc = code.trim().toUpperCase();
2622
+ if (!/^[A-Z]{2}$/.test(cc)) return "";
2623
+ const base = 127462;
2624
+ return String.fromCodePoint(base + (cc.charCodeAt(0) - 65), base + (cc.charCodeAt(1) - 65));
2625
+ }
2468
2626
  var STATUS_LABEL = {
2469
2627
  pending: "Pending",
2470
2628
  processing: "Processing",
2471
2629
  completed: "Completed",
2472
2630
  failed: "Failed"
2473
2631
  };
2632
+ var INSTRUCTION_LABELS = {
2633
+ br_code: "Pix code",
2634
+ account_holder_name: "Account holder",
2635
+ bank_name: "Bank",
2636
+ bank_address: "Bank address",
2637
+ bank_account_number: "Account number",
2638
+ bank_routing_number: "Routing number",
2639
+ iban: "IBAN",
2640
+ bic: "BIC",
2641
+ clabe: "CLABE",
2642
+ amount: "Amount",
2643
+ currency: "Currency",
2644
+ payment_rails: "Rails"
2645
+ };
2646
+ function flattenInstructions(instr) {
2647
+ const out = [];
2648
+ for (const [k, v] of Object.entries(instr)) {
2649
+ if (k === "qrBase64") {
2650
+ if (typeof v === "string" && v) out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? "Payment QR", value: v, kind: "qr" });
2651
+ continue;
2652
+ }
2653
+ if ((k === "expiresAt" || k === "expires_at") && (typeof v === "number" || typeof v === "string")) {
2654
+ const ms = Number(v);
2655
+ if (Number.isFinite(ms) && ms > 0) {
2656
+ out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? "Expires", value: new Date(ms).toLocaleString(), kind: "datetime" });
2657
+ }
2658
+ continue;
2659
+ }
2660
+ let value;
2661
+ if (typeof v === "string" || typeof v === "number") value = String(v);
2662
+ else if (Array.isArray(v)) value = v.filter((x) => typeof x === "string" || typeof x === "number").join(", ");
2663
+ else continue;
2664
+ if (!value) continue;
2665
+ out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? k, value, kind: "text" });
2666
+ }
2667
+ return out;
2668
+ }
2474
2669
  function RampWidgetTemplate({
2475
2670
  theme,
2476
2671
  accentColor,
@@ -2479,24 +2674,35 @@ function RampWidgetTemplate({
2479
2674
  amount,
2480
2675
  currency,
2481
2676
  country,
2677
+ requiredFields,
2678
+ fieldValues,
2679
+ countries,
2680
+ countriesLoading,
2681
+ refreshing,
2482
2682
  quotes,
2483
2683
  isLoading,
2484
2684
  provider,
2485
2685
  txStatus,
2486
2686
  kycUrl,
2687
+ tosUrl,
2487
2688
  stellarTxHash,
2689
+ explorerUrl,
2690
+ depositInstructions,
2488
2691
  canComplete,
2489
2692
  completing,
2490
2693
  errorMsg,
2491
2694
  onDirectionChange,
2492
2695
  onAmountChange,
2493
- onCurrencyChange,
2696
+ onFieldChange,
2494
2697
  onCountryChange,
2495
2698
  onFindRoute,
2496
2699
  onSelectQuote,
2700
+ onContactContinue,
2497
2701
  onOpenKyc,
2702
+ onOpenTos,
2498
2703
  onCompleteWithdraw,
2499
2704
  onRetry,
2705
+ onRefresh,
2500
2706
  onClose
2501
2707
  }) {
2502
2708
  const isDark = theme === "dark";
@@ -2524,6 +2730,7 @@ function RampWidgetTemplate({
2524
2730
  input: direction === "onramp" ? "Buy crypto" : "Sell crypto",
2525
2731
  loading_quote: "Finding best route",
2526
2732
  select_route: "Select provider",
2733
+ contact: "Your details",
2527
2734
  status: direction === "onramp" ? "Complete your deposit" : "Complete your withdrawal",
2528
2735
  error: "Something went wrong"
2529
2736
  };
@@ -2531,21 +2738,48 @@ function RampWidgetTemplate({
2531
2738
  input: direction === "onramp" ? "Enter the amount you want to deposit" : "Enter the amount you want to withdraw",
2532
2739
  loading_quote: "Comparing providers in real time\u2026",
2533
2740
  select_route: "All prices include fees",
2741
+ contact: `${provider || "This provider"} needs your name and email to verify you`,
2534
2742
  status: `Finish the flow at ${provider || "the provider"} to continue`,
2535
2743
  error: "Please try again"
2536
2744
  };
2537
2745
  return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-ramp-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
2538
- /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-header", children: [
2539
- /* @__PURE__ */ jsx("h2", { className: "pollar-ramp-title", children: stepTitle[step] }),
2540
- /* @__PURE__ */ jsx("p", { className: "pollar-ramp-subtitle", children: stepSubtitle[step] })
2746
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
2747
+ /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-header-text", children: [
2748
+ /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: stepTitle[step] }),
2749
+ /* @__PURE__ */ jsx("p", { className: "pollar-ramp-subtitle", children: stepSubtitle[step] })
2750
+ ] }),
2751
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
2752
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onRefresh, disabled: refreshing, "aria-label": "Refresh", children: /* @__PURE__ */ jsx(
2753
+ "svg",
2754
+ {
2755
+ className: refreshing ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
2756
+ width: "16",
2757
+ height: "16",
2758
+ viewBox: "0 0 16 16",
2759
+ fill: "none",
2760
+ "aria-hidden": true,
2761
+ children: /* @__PURE__ */ jsx(
2762
+ "path",
2763
+ {
2764
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
2765
+ stroke: "currentColor",
2766
+ strokeWidth: "1.6",
2767
+ strokeLinecap: "round",
2768
+ strokeLinejoin: "round"
2769
+ }
2770
+ )
2771
+ }
2772
+ ) }),
2773
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
2774
+ ] })
2541
2775
  ] }),
2542
2776
  step === "input" && /* @__PURE__ */ jsxs(Fragment, { children: [
2543
- /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-tabs", children: [
2777
+ /* @__PURE__ */ jsxs("div", { className: "pollar-tabs", children: [
2544
2778
  /* @__PURE__ */ jsx(
2545
2779
  "button",
2546
2780
  {
2547
2781
  type: "button",
2548
- className: "pollar-ramp-tab",
2782
+ className: "pollar-tab",
2549
2783
  "data-active": direction === "onramp",
2550
2784
  onClick: () => onDirectionChange("onramp"),
2551
2785
  children: "Buy"
@@ -2555,79 +2789,110 @@ function RampWidgetTemplate({
2555
2789
  "button",
2556
2790
  {
2557
2791
  type: "button",
2558
- className: "pollar-ramp-tab",
2792
+ className: "pollar-tab",
2559
2793
  "data-active": direction === "offramp",
2560
2794
  onClick: () => onDirectionChange("offramp"),
2561
2795
  children: "Sell"
2562
2796
  }
2563
2797
  )
2564
2798
  ] }),
2565
- /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-input-row", children: [
2566
- /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
2567
- /* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", children: "Amount" }),
2568
- /* @__PURE__ */ jsx(
2569
- "input",
2570
- {
2571
- type: "number",
2572
- className: "pollar-ramp-input",
2573
- placeholder: "0.00",
2574
- value: amount,
2575
- min: "0",
2576
- onChange: (e) => onAmountChange(e.target.value)
2577
- }
2578
- )
2579
- ] }),
2580
- /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", style: { maxWidth: 90 }, children: [
2581
- /* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", children: "Currency" }),
2582
- /* @__PURE__ */ jsx(
2583
- "input",
2584
- {
2585
- type: "text",
2586
- className: "pollar-ramp-input",
2587
- placeholder: "MXN",
2588
- value: currency,
2589
- maxLength: 5,
2590
- onChange: (e) => onCurrencyChange(e.target.value.toUpperCase())
2591
- }
2592
- )
2593
- ] })
2594
- ] }),
2595
2799
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
2596
2800
  /* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", children: "Country" }),
2597
- /* @__PURE__ */ jsxs(
2598
- "select",
2801
+ countriesLoading ? /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-input pollar-ramp-input-loading", children: [
2802
+ /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
2803
+ /* @__PURE__ */ jsx("span", { children: "Loading countries\u2026" })
2804
+ ] }) : countries.length === 0 ? /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: "No ramp providers available on this network yet." }) : /* @__PURE__ */ jsx("select", { className: "pollar-ramp-input", value: country, onChange: (e) => onCountryChange(e.target.value), children: countries.map((c) => /* @__PURE__ */ jsxs("option", { value: c.code, children: [
2805
+ flagEmoji(c.code),
2806
+ " ",
2807
+ c.code,
2808
+ c.currency ? ` \u2014 ${c.currency}` : ""
2809
+ ] }, c.code)) })
2810
+ ] }),
2811
+ /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
2812
+ /* @__PURE__ */ jsxs("label", { className: "pollar-ramp-label", children: [
2813
+ "Amount",
2814
+ currency ? ` (${currency})` : ""
2815
+ ] }),
2816
+ /* @__PURE__ */ jsx(
2817
+ "input",
2599
2818
  {
2819
+ type: "number",
2600
2820
  className: "pollar-ramp-input",
2601
- value: country,
2602
- onChange: (e) => {
2603
- const c = e.target.value;
2604
- onCountryChange(c);
2605
- if (COUNTRY_CURRENCIES[c]) onCurrencyChange(COUNTRY_CURRENCIES[c]);
2606
- },
2607
- children: [
2608
- /* @__PURE__ */ jsx("option", { value: "MX", children: "\u{1F1F2}\u{1F1FD} Mexico" }),
2609
- /* @__PURE__ */ jsx("option", { value: "BR", children: "\u{1F1E7}\u{1F1F7} Brazil" }),
2610
- /* @__PURE__ */ jsx("option", { value: "CO", children: "\u{1F1E8}\u{1F1F4} Colombia" }),
2611
- /* @__PURE__ */ jsx("option", { value: "CL", children: "\u{1F1E8}\u{1F1F1} Chile" }),
2612
- /* @__PURE__ */ jsx("option", { value: "PE", children: "\u{1F1F5}\u{1F1EA} Peru" }),
2613
- /* @__PURE__ */ jsx("option", { value: "AR", children: "\u{1F1E6}\u{1F1F7} Argentina" })
2614
- ]
2821
+ placeholder: "0.00",
2822
+ value: amount,
2823
+ min: "0",
2824
+ onChange: (e) => onAmountChange(e.target.value)
2615
2825
  }
2616
2826
  )
2617
2827
  ] }),
2618
2828
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-actions", children: [
2619
2829
  /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" }),
2620
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", disabled: !amount || isLoading, onClick: onFindRoute, children: "Find best route" })
2830
+ /* @__PURE__ */ jsx(
2831
+ "button",
2832
+ {
2833
+ type: "button",
2834
+ className: "pollar-btn-primary",
2835
+ disabled: !amount || isLoading || countriesLoading || countries.length === 0,
2836
+ onClick: onFindRoute,
2837
+ children: "Find best route"
2838
+ }
2839
+ )
2621
2840
  ] })
2622
2841
  ] }),
2623
- step === "loading_quote" && /* @__PURE__ */ jsx("div", { className: "pollar-ramp-loading", children: LOADING_STEPS.map((text, i) => /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-loading-row", children: [
2624
- /* @__PURE__ */ jsx("div", { className: "pollar-ramp-loading-dot" }),
2625
- /* @__PURE__ */ jsx("span", { children: text })
2626
- ] }, i)) }),
2842
+ step === "loading_quote" && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-loading", children: [
2843
+ /* @__PURE__ */ jsx("div", { className: "pollar-spinner pollar-ramp-loading-spinner" }),
2844
+ LOADING_STEPS.map((text, i) => /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-loading-row", children: [
2845
+ /* @__PURE__ */ jsx("div", { className: "pollar-ramp-loading-dot" }),
2846
+ /* @__PURE__ */ jsx("span", { children: text })
2847
+ ] }, i))
2848
+ ] }),
2627
2849
  step === "select_route" && /* @__PURE__ */ jsxs(Fragment, { children: [
2628
2850
  /* @__PURE__ */ jsx("div", { className: "pollar-ramp-route-list", children: quotes.map((q, i) => /* @__PURE__ */ jsx(RouteDisplay, { quote: q, onSelect: onSelectQuote }, i)) }),
2629
2851
  /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" })
2630
2852
  ] }),
2853
+ step === "contact" && /* @__PURE__ */ jsxs(Fragment, { children: [
2854
+ requiredFields.map((f) => /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
2855
+ /* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", children: f.label }),
2856
+ f.type === "select" ? /* @__PURE__ */ jsxs(
2857
+ "select",
2858
+ {
2859
+ className: "pollar-ramp-input",
2860
+ value: fieldValues[f.key] ?? "",
2861
+ onChange: (e) => onFieldChange(f.key, e.target.value),
2862
+ children: [
2863
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select\u2026" }),
2864
+ (f.options ?? []).map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
2865
+ ]
2866
+ }
2867
+ ) : /* @__PURE__ */ jsx(
2868
+ "input",
2869
+ {
2870
+ type: f.type,
2871
+ className: "pollar-ramp-input",
2872
+ value: fieldValues[f.key] ?? "",
2873
+ autoComplete: f.type === "email" ? "email" : "off",
2874
+ onChange: (e) => onFieldChange(f.key, e.target.value)
2875
+ }
2876
+ ),
2877
+ f.type === "email" && (fieldValues[f.key] ?? "").trim() !== "" && !isFieldValid(f, fieldValues[f.key]) && /* @__PURE__ */ jsx("span", { className: "pollar-ramp-field-error", children: "Enter a valid email address." })
2878
+ ] }, f.key)),
2879
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-actions", children: [
2880
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onRetry, children: "Back" }),
2881
+ /* @__PURE__ */ jsx(
2882
+ "button",
2883
+ {
2884
+ type: "button",
2885
+ className: "pollar-btn-primary",
2886
+ disabled: requiredFields.some((f) => !isFieldValid(f, fieldValues[f.key])) || isLoading,
2887
+ onClick: onContactContinue,
2888
+ children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
2889
+ /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
2890
+ "Starting\u2026"
2891
+ ] }) : "Continue"
2892
+ }
2893
+ )
2894
+ ] })
2895
+ ] }),
2631
2896
  step === "status" && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment", children: [
2632
2897
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
2633
2898
  /* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Provider" }),
@@ -2635,27 +2900,81 @@ function RampWidgetTemplate({
2635
2900
  ] }),
2636
2901
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
2637
2902
  /* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Status" }),
2638
- /* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsx(
2639
- "code",
2640
- {
2641
- style: { color: txStatus === "completed" ? "var(--pollar-success-text)" : void 0 },
2642
- children: txStatus ? STATUS_LABEL[txStatus] : "Processing"
2643
- }
2644
- ) })
2903
+ /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-value", children: [
2904
+ /* @__PURE__ */ jsx("code", { style: { color: txStatus === "completed" ? "var(--pollar-success-text)" : void 0 }, children: txStatus ? STATUS_LABEL[txStatus] : "Processing" }),
2905
+ txStatus !== "completed" && txStatus !== "failed" && /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm", "aria-label": "Checking status" })
2906
+ ] })
2645
2907
  ] }),
2646
2908
  stellarTxHash && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
2647
2909
  /* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Stellar tx" }),
2648
- /* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsxs("code", { children: [
2649
- stellarTxHash.slice(0, 8),
2650
- "\u2026",
2651
- stellarTxHash.slice(-8)
2910
+ /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-value", style: { display: "flex", alignItems: "center", gap: 6 }, children: [
2911
+ /* @__PURE__ */ jsxs("code", { style: { flex: 1, wordBreak: "break-all" }, children: [
2912
+ stellarTxHash.slice(0, 8),
2913
+ "\u2026",
2914
+ stellarTxHash.slice(-8)
2915
+ ] }),
2916
+ /* @__PURE__ */ jsx(CopyButton, { value: stellarTxHash, label: "Copy transaction hash" }),
2917
+ explorerUrl && /* @__PURE__ */ jsx(
2918
+ "a",
2919
+ {
2920
+ href: explorerUrl,
2921
+ target: "_blank",
2922
+ rel: "noopener noreferrer",
2923
+ className: "pollar-copy-btn",
2924
+ "aria-label": "View on Stellar Expert",
2925
+ title: "View on Stellar Expert",
2926
+ children: /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
2927
+ /* @__PURE__ */ jsx(
2928
+ "path",
2929
+ {
2930
+ d: "M6 3H3v8h8V8",
2931
+ stroke: "currentColor",
2932
+ strokeWidth: "1.5",
2933
+ strokeLinecap: "round",
2934
+ strokeLinejoin: "round"
2935
+ }
2936
+ ),
2937
+ /* @__PURE__ */ jsx(
2938
+ "path",
2939
+ {
2940
+ d: "M8.5 2.5h3v3M11 3L6.5 7.5",
2941
+ stroke: "currentColor",
2942
+ strokeWidth: "1.5",
2943
+ strokeLinecap: "round",
2944
+ strokeLinejoin: "round"
2945
+ }
2946
+ )
2947
+ ] })
2948
+ }
2949
+ )
2950
+ ] })
2951
+ ] }),
2952
+ depositInstructions && txStatus !== "completed" && flattenInstructions(depositInstructions).map(({ key, label, value, kind }) => /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
2953
+ /* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: label }),
2954
+ /* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: kind === "qr" ? /* @__PURE__ */ jsx(
2955
+ "img",
2956
+ {
2957
+ src: value.startsWith("data:") ? value : `data:image/png;base64,${value}`,
2958
+ alt: label,
2959
+ style: { width: "100%", maxWidth: 220, height: "auto", display: "block", margin: "0 auto" }
2960
+ }
2961
+ ) : kind === "datetime" ? /* @__PURE__ */ jsx("span", { children: value }) : /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
2962
+ /* @__PURE__ */ jsx("code", { style: { flex: 1, wordBreak: "break-all" }, children: value }),
2963
+ /* @__PURE__ */ jsx(CopyButton, { value, label: `Copy ${label}` })
2652
2964
  ] }) })
2965
+ ] }, key)),
2966
+ tosUrl && !depositInstructions && txStatus !== "completed" && /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenTos, children: [
2967
+ "Accept terms at ",
2968
+ provider
2653
2969
  ] }),
2654
- kycUrl && txStatus !== "completed" && /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenKyc, children: [
2970
+ kycUrl && !depositInstructions && txStatus !== "completed" && /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenKyc, children: [
2655
2971
  "Continue at ",
2656
2972
  provider
2657
2973
  ] }),
2658
- canComplete && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", disabled: completing, onClick: onCompleteWithdraw, children: completing ? "Submitting\u2026" : "I've completed KYC \u2014 withdraw" }),
2974
+ canComplete && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", disabled: completing, onClick: onCompleteWithdraw, children: completing ? /* @__PURE__ */ jsxs(Fragment, { children: [
2975
+ /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
2976
+ "Submitting\u2026"
2977
+ ] }) : "I've completed KYC \u2014 withdraw" }),
2659
2978
  errorMsg && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", style: { color: "var(--pollar-error-text)" }, children: errorMsg }),
2660
2979
  /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: txStatus === "completed" ? "Done" : "Close" })
2661
2980
  ] }),
@@ -2669,23 +2988,34 @@ function RampWidgetTemplate({
2669
2988
  ] });
2670
2989
  }
2671
2990
  var TERMINAL = ["completed", "failed"];
2991
+ function requiredFieldsOf(quote) {
2992
+ return quote.requiredFields ?? [];
2993
+ }
2672
2994
  function RampWidget({ onClose }) {
2673
- const { getClient, signTx, wallet, styles } = usePollar();
2995
+ const { getClient, signTx, wallet, styles, network } = usePollar();
2674
2996
  const walletAddress = wallet?.address ?? "";
2675
2997
  const client = getClient();
2676
2998
  const { theme = "light", accentColor = "#005DB4" } = styles;
2677
2999
  const [step, setStep] = useState("input");
2678
3000
  const [direction, setDirection] = useState("onramp");
2679
3001
  const [amount, setAmount] = useState("");
2680
- const [currency, setCurrency] = useState("ARS");
2681
- const [country, setCountry] = useState("AR");
3002
+ const [currency, setCurrency] = useState("");
3003
+ const [country, setCountry] = useState("");
3004
+ const [fieldValues, setFieldValues] = useState({});
3005
+ const setFieldValue = (key, value) => setFieldValues((v) => ({ ...v, [key]: value }));
3006
+ const [countries, setCountries] = useState([]);
3007
+ const [countriesLoading, setCountriesLoading] = useState(true);
3008
+ const [refreshing, setRefreshing] = useState(false);
2682
3009
  const [quotes, setQuotes] = useState([]);
3010
+ const [selectedQuote, setSelectedQuote] = useState(null);
2683
3011
  const [isLoading, setIsLoading] = useState(false);
2684
3012
  const [txId, setTxId] = useState(null);
2685
3013
  const [provider, setProvider] = useState("");
2686
3014
  const [kycUrl, setKycUrl] = useState(null);
3015
+ const [tosUrl, setTosUrl] = useState(null);
2687
3016
  const [txStatus, setTxStatus] = useState(null);
2688
3017
  const [stellarTxHash, setStellarTxHash] = useState(null);
3018
+ const [depositInstructions, setDepositInstructions] = useState(null);
2689
3019
  const [completing, setCompleting] = useState(false);
2690
3020
  const [errorMsg, setErrorMsg] = useState(null);
2691
3021
  const directionRef = useRef(direction);
@@ -2701,6 +3031,7 @@ function RampWidget({ onClose }) {
2701
3031
  setTxStatus(tx.status);
2702
3032
  if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
2703
3033
  if (tx.kycUrl) setKycUrl(tx.kycUrl);
3034
+ if (tx.depositInstructions) setDepositInstructions(tx.depositInstructions);
2704
3035
  if (TERMINAL.includes(tx.status)) clearInterval(id);
2705
3036
  } catch {
2706
3037
  }
@@ -2710,14 +3041,63 @@ function RampWidget({ onClose }) {
2710
3041
  clearInterval(id);
2711
3042
  };
2712
3043
  }, [step, txId, txStatus, client]);
3044
+ async function loadCountries(resetSelection) {
3045
+ setCountriesLoading(true);
3046
+ try {
3047
+ const { countries: list } = await client.getRampCountries();
3048
+ setCountries(list);
3049
+ const first = list[0];
3050
+ const stillValid = list.some((c) => c.code === country);
3051
+ if (first && (resetSelection || !stillValid)) {
3052
+ setCountry(first.code);
3053
+ if (first.currency) setCurrency(first.currency);
3054
+ }
3055
+ } catch {
3056
+ setCountries([]);
3057
+ } finally {
3058
+ setCountriesLoading(false);
3059
+ }
3060
+ }
3061
+ useEffect(() => {
3062
+ loadCountries(true);
3063
+ }, []);
3064
+ function handleCountryChange(code) {
3065
+ setCountry(code);
3066
+ const match = countries.find((c) => c.code === code);
3067
+ if (match?.currency) setCurrency(match.currency);
3068
+ }
3069
+ async function handleRefresh() {
3070
+ if (refreshing) return;
3071
+ setRefreshing(true);
3072
+ try {
3073
+ await loadCountries(false);
3074
+ if (step === "select_route") {
3075
+ const result = await client.getRampsQuote({ country, amount: Number(amount), currency, direction });
3076
+ setQuotes(result.quotes ?? []);
3077
+ } else if (step === "status" && txId) {
3078
+ const tx = await client.getRampTransaction(txId);
3079
+ setTxStatus(tx.status);
3080
+ if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
3081
+ if (tx.kycUrl) setKycUrl(tx.kycUrl);
3082
+ if (tx.depositInstructions) setDepositInstructions(tx.depositInstructions);
3083
+ }
3084
+ } catch {
3085
+ } finally {
3086
+ setRefreshing(false);
3087
+ }
3088
+ }
2713
3089
  function resetToInput() {
2714
3090
  setStep("input");
2715
3091
  setQuotes([]);
3092
+ setSelectedQuote(null);
3093
+ setFieldValues({});
2716
3094
  setTxId(null);
2717
3095
  setProvider("");
2718
3096
  setKycUrl(null);
3097
+ setTosUrl(null);
2719
3098
  setTxStatus(null);
2720
3099
  setStellarTxHash(null);
3100
+ setDepositInstructions(null);
2721
3101
  setErrorMsg(null);
2722
3102
  }
2723
3103
  async function resumeWithSignature(id, ps) {
@@ -2741,8 +3121,10 @@ function RampWidget({ onClose }) {
2741
3121
  return;
2742
3122
  }
2743
3123
  setKycUrl(result.kycUrl ?? null);
3124
+ setTosUrl(result.tosUrl ?? null);
2744
3125
  setTxStatus(result.status);
2745
3126
  setStellarTxHash(result.stellarTxHash ?? null);
3127
+ setDepositInstructions(result.depositInstructions ?? null);
2746
3128
  setStep("status");
2747
3129
  }
2748
3130
  async function handleFindRoute() {
@@ -2766,12 +3148,37 @@ function RampWidget({ onClose }) {
2766
3148
  setIsLoading(false);
2767
3149
  }
2768
3150
  }
2769
- async function handleSelectQuote(quote) {
3151
+ function handleSelectQuote(quote) {
3152
+ setSelectedQuote(quote);
3153
+ setErrorMsg(null);
3154
+ const fields = requiredFieldsOf(quote);
3155
+ const missing = fields.some((f) => !(fieldValues[f.key] ?? "").trim());
3156
+ if (fields.length > 0 && missing) {
3157
+ setStep("contact");
3158
+ return;
3159
+ }
3160
+ void startRamp(quote);
3161
+ }
3162
+ function handleContactContinue() {
3163
+ if (selectedQuote) void startRamp(selectedQuote);
3164
+ }
3165
+ async function startRamp(quote) {
2770
3166
  setIsLoading(true);
2771
3167
  setErrorMsg(null);
2772
3168
  try {
2773
3169
  const base = { quoteId: quote.quoteId, amount: Number(amount), currency, country };
2774
- const result = direction === "onramp" ? await client.createOnRamp({ ...base, ...walletAddress ? { walletAddress } : {} }) : await client.createOffRamp({ ...base, ...walletAddress ? { walletAddress } : {} });
3170
+ if (walletAddress) base.walletAddress = walletAddress;
3171
+ const STANDARD_BODY_KEYS = /* @__PURE__ */ new Set(["email", "fullName", "taxId", "qrCode"]);
3172
+ const extraFields = {};
3173
+ for (const f of requiredFieldsOf(quote)) {
3174
+ const val = (fieldValues[f.key] ?? "").trim();
3175
+ if (!val) continue;
3176
+ if (f.bankType) base.bankDetails = { type: f.bankType, value: val };
3177
+ else if (STANDARD_BODY_KEYS.has(f.key)) base[f.key] = val;
3178
+ else extraFields[f.key] = val;
3179
+ }
3180
+ if (Object.keys(extraFields).length > 0) base.fields = extraFields;
3181
+ const result = direction === "onramp" ? await client.createOnRamp(base) : await client.createOffRamp(base);
2775
3182
  await applyResult(result);
2776
3183
  } catch (e) {
2777
3184
  setErrorMsg(e instanceof Error ? e.message : "Failed to start the ramp.");
@@ -2783,6 +3190,9 @@ function RampWidget({ onClose }) {
2783
3190
  function handleOpenKyc() {
2784
3191
  if (kycUrl) window.open(kycUrl, "_blank", "noopener,noreferrer");
2785
3192
  }
3193
+ function handleOpenTos() {
3194
+ if (tosUrl) window.open(tosUrl, "_blank", "noopener,noreferrer");
3195
+ }
2786
3196
  async function handleCompleteWithdraw() {
2787
3197
  if (!txId) return;
2788
3198
  setCompleting(true);
@@ -2815,24 +3225,35 @@ function RampWidget({ onClose }) {
2815
3225
  amount,
2816
3226
  currency,
2817
3227
  country,
3228
+ requiredFields: selectedQuote ? requiredFieldsOf(selectedQuote) : [],
3229
+ fieldValues,
3230
+ countries,
3231
+ countriesLoading,
3232
+ refreshing,
2818
3233
  quotes,
2819
3234
  isLoading,
2820
3235
  provider,
2821
3236
  txStatus,
2822
3237
  kycUrl,
3238
+ tosUrl,
2823
3239
  stellarTxHash,
3240
+ explorerUrl: stellarTxHash ? `https://stellar.expert/explorer/${network === "mainnet" ? "public" : "testnet"}/tx/${stellarTxHash}` : null,
3241
+ depositInstructions,
2824
3242
  canComplete,
2825
3243
  completing,
2826
3244
  errorMsg,
2827
3245
  onDirectionChange: setDirection,
2828
3246
  onAmountChange: setAmount,
2829
- onCurrencyChange: setCurrency,
2830
- onCountryChange: setCountry,
3247
+ onFieldChange: setFieldValue,
3248
+ onCountryChange: handleCountryChange,
2831
3249
  onFindRoute: handleFindRoute,
2832
3250
  onSelectQuote: handleSelectQuote,
3251
+ onContactContinue: handleContactContinue,
2833
3252
  onOpenKyc: handleOpenKyc,
3253
+ onOpenTos: handleOpenTos,
2834
3254
  onCompleteWithdraw: handleCompleteWithdraw,
2835
3255
  onRetry: resetToInput,
3256
+ onRefresh: handleRefresh,
2836
3257
  onClose
2837
3258
  }
2838
3259
  ) });
@@ -2995,6 +3416,43 @@ function ReceiveModal({ onClose }) {
2995
3416
  }
2996
3417
  ) });
2997
3418
  }
3419
+ function formatAmount2(value) {
3420
+ const n = parseFloat(value);
3421
+ return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
3422
+ }
3423
+ var optionLabel = (o) => o.available !== void 0 ? `${o.code} \u2014 ${formatAmount2(o.available)} available` : o.code;
3424
+ function AssetSelect({
3425
+ label,
3426
+ value,
3427
+ options,
3428
+ onChange,
3429
+ loading = false,
3430
+ disabled = false,
3431
+ appGroupLabel = "App assets",
3432
+ otherGroupLabel = "Other assets",
3433
+ children
3434
+ }) {
3435
+ const appAssets = options.filter((o) => o.enabledInApp);
3436
+ const otherAssets = options.filter((o) => !o.enabledInApp);
3437
+ return /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
3438
+ /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: label }),
3439
+ loading ? /* @__PURE__ */ jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxs(
3440
+ "select",
3441
+ {
3442
+ className: "pollar-input pollar-send-select",
3443
+ value,
3444
+ disabled,
3445
+ onChange: (e) => onChange(e.target.value),
3446
+ children: [
3447
+ value === "" && /* @__PURE__ */ jsx("option", { value: "", disabled: true, hidden: true }),
3448
+ appAssets.length > 0 && /* @__PURE__ */ jsx("optgroup", { label: appGroupLabel, children: appAssets.map((o) => /* @__PURE__ */ jsx("option", { value: o.key, children: optionLabel(o) }, o.key)) }),
3449
+ otherAssets.length > 0 && /* @__PURE__ */ jsx("optgroup", { label: otherGroupLabel, children: otherAssets.map((o) => /* @__PURE__ */ jsx("option", { value: o.key, children: optionLabel(o) }, o.key)) })
3450
+ ]
3451
+ }
3452
+ ),
3453
+ !loading && children
3454
+ ] });
3455
+ }
2998
3456
  var STATUS_MESSAGES = {
2999
3457
  idle: "",
3000
3458
  building: "Building transaction\u2026",
@@ -3219,6 +3677,7 @@ function SendModalTemplate({
3219
3677
  isInProgress,
3220
3678
  onClose,
3221
3679
  onBack,
3680
+ onRefresh,
3222
3681
  onSelectAsset,
3223
3682
  onAmountChange,
3224
3683
  onDestinationChange,
@@ -3247,8 +3706,6 @@ function SendModalTemplate({
3247
3706
  "--pollar-input-border-radius": "0.5rem",
3248
3707
  "--pollar-card-border-radius": "10px"
3249
3708
  };
3250
- const enabledAssets = assets.filter((a) => a.enabledInApp);
3251
- const otherAssets = assets.filter((a) => !a.enabledInApp);
3252
3709
  const selectedKey = selectedAsset ? assetKey3(selectedAsset) : "";
3253
3710
  const canSubmit = !!selectedAsset && !!amount && !!destination.trim() && !isLoadingBalance;
3254
3711
  const title = step === "form" ? "Send" : txTitle;
@@ -3265,39 +3722,61 @@ function SendModalTemplate({
3265
3722
  showBack && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onBack, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
3266
3723
  /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: title })
3267
3724
  ] }),
3268
- !isInProgress && /* @__PURE__ */ jsx("div", { className: "pollar-modal-header-actions", children: /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) }) })
3725
+ !isInProgress && /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
3726
+ step === "form" && /* @__PURE__ */ jsx(
3727
+ "button",
3728
+ {
3729
+ type: "button",
3730
+ className: "pollar-modal-close",
3731
+ onClick: onRefresh,
3732
+ disabled: isLoadingBalance,
3733
+ "aria-label": "Refresh",
3734
+ title: "Refresh balances",
3735
+ children: /* @__PURE__ */ jsx(
3736
+ "svg",
3737
+ {
3738
+ className: isLoadingBalance ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
3739
+ width: "16",
3740
+ height: "16",
3741
+ viewBox: "0 0 16 16",
3742
+ fill: "none",
3743
+ "aria-hidden": true,
3744
+ children: /* @__PURE__ */ jsx(
3745
+ "path",
3746
+ {
3747
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
3748
+ stroke: "currentColor",
3749
+ strokeWidth: "1.6",
3750
+ strokeLinecap: "round",
3751
+ strokeLinejoin: "round"
3752
+ }
3753
+ )
3754
+ }
3755
+ )
3756
+ }
3757
+ ),
3758
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
3759
+ ] })
3269
3760
  ] }),
3270
3761
  step === "form" && /* @__PURE__ */ jsxs(Fragment, { children: [
3271
- /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
3272
- /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Asset" }),
3273
- isLoadingBalance ? /* @__PURE__ */ jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxs(
3274
- "select",
3275
- {
3276
- className: "pollar-input pollar-send-select",
3277
- value: selectedKey,
3278
- onChange: (e) => {
3279
- const all = [...enabledAssets, ...otherAssets];
3280
- const found = all.find((a) => assetKey3(a) === e.target.value);
3281
- if (found) onSelectAsset(found);
3282
- },
3283
- children: [
3284
- /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select asset" }),
3285
- enabledAssets.length > 0 && /* @__PURE__ */ jsx("optgroup", { label: "App assets", children: enabledAssets.map((a) => /* @__PURE__ */ jsxs("option", { value: assetKey3(a), children: [
3286
- a.code,
3287
- " \u2014 ",
3288
- formatBalance(a.available),
3289
- " available"
3290
- ] }, assetKey3(a))) }),
3291
- otherAssets.length > 0 && /* @__PURE__ */ jsx("optgroup", { label: "Other assets", children: otherAssets.map((a) => /* @__PURE__ */ jsxs("option", { value: assetKey3(a), children: [
3292
- a.code,
3293
- " \u2014 ",
3294
- formatBalance(a.available),
3295
- " available"
3296
- ] }, assetKey3(a))) })
3297
- ]
3762
+ /* @__PURE__ */ jsx(
3763
+ AssetSelect,
3764
+ {
3765
+ label: "Asset",
3766
+ value: selectedKey,
3767
+ loading: isLoadingBalance,
3768
+ options: assets.map((a) => ({
3769
+ key: assetKey3(a),
3770
+ code: a.code,
3771
+ available: a.available,
3772
+ enabledInApp: a.enabledInApp
3773
+ })),
3774
+ onChange: (key) => {
3775
+ const found = assets.find((a) => assetKey3(a) === key);
3776
+ if (found) onSelectAsset(found);
3298
3777
  }
3299
- )
3300
- ] }),
3778
+ }
3779
+ ),
3301
3780
  /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
3302
3781
  /* @__PURE__ */ jsxs("div", { className: "pollar-send-label-row", children: [
3303
3782
  /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Amount" }),
@@ -3397,13 +3876,16 @@ function SendModal({ onClose }) {
3397
3876
  const allAssets = balanceData?.balances ?? [];
3398
3877
  const sortedAssets = [
3399
3878
  ...allAssets.filter((b) => b.enabledInApp),
3400
- ...allAssets.filter((b) => !b.enabledInApp && parseFloat(b.balance) > 0)
3879
+ ...allAssets.filter((b) => !b.enabledInApp && (b.type === "native" || parseFloat(b.balance) > 0))
3401
3880
  ];
3881
+ useEffect(() => {
3882
+ if (!selectedAsset && sortedAssets.length > 0) setSelectedAsset(sortedAssets[0]);
3883
+ }, [sortedAssets, selectedAsset]);
3402
3884
  const hash = transaction.step === "success" ? transaction.hash : null;
3403
3885
  const buildData = "buildData" in transaction ? transaction.buildData : null;
3404
3886
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
3405
3887
  const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
3406
- const IN_FLIGHT_STEPS2 = [
3888
+ const IN_FLIGHT_STEPS3 = [
3407
3889
  "building",
3408
3890
  "signing",
3409
3891
  "submitting",
@@ -3411,7 +3893,7 @@ function SendModal({ onClose }) {
3411
3893
  "signing-submitting",
3412
3894
  "building-signing-submitting"
3413
3895
  ];
3414
- const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
3896
+ const isInProgress = IN_FLIGHT_STEPS3.includes(transaction.step);
3415
3897
  const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
3416
3898
  const txTitle = isInProgress ? "Sending\u2026" : transaction.step === "success" ? "Sent!" : transaction.step === "error" ? "Send failed" : "Confirm Send";
3417
3899
  async function handleSubmit() {
@@ -3484,6 +3966,7 @@ function SendModal({ onClose }) {
3484
3966
  isInProgress,
3485
3967
  onClose,
3486
3968
  onBack: handleBack,
3969
+ onRefresh: () => void refreshWalletBalance(),
3487
3970
  onSelectAsset: setSelectedAsset,
3488
3971
  onAmountChange: setAmount,
3489
3972
  onDestinationChange: setDestination,
@@ -3505,7 +3988,7 @@ var PROVIDER_LABELS = {
3505
3988
  soroswap: "Soroswap",
3506
3989
  sdex: "Stellar DEX"
3507
3990
  };
3508
- function formatAmount2(value) {
3991
+ function formatAmount3(value) {
3509
3992
  const n = parseFloat(value);
3510
3993
  return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
3511
3994
  }
@@ -3542,6 +4025,7 @@ function SwapModalTemplate({
3542
4025
  onRefresh,
3543
4026
  onSelectSell,
3544
4027
  onSelectBuy,
4028
+ onAddCustomToken,
3545
4029
  onAmountChange,
3546
4030
  onProviderChange,
3547
4031
  onSwap,
@@ -3551,6 +4035,21 @@ function SwapModalTemplate({
3551
4035
  onDone
3552
4036
  }) {
3553
4037
  const isDark = theme === "dark";
4038
+ const [customOpen, setCustomOpen] = useState(false);
4039
+ const [customCode, setCustomCode] = useState("");
4040
+ const [customIssuer, setCustomIssuer] = useState("");
4041
+ const [customError, setCustomError] = useState("");
4042
+ const submitCustomToken = () => {
4043
+ const err = onAddCustomToken(customCode, customIssuer);
4044
+ if (err) {
4045
+ setCustomError(err);
4046
+ return;
4047
+ }
4048
+ setCustomCode("");
4049
+ setCustomIssuer("");
4050
+ setCustomError("");
4051
+ setCustomOpen(false);
4052
+ };
3554
4053
  const cssVars = {
3555
4054
  "--pollar-accent": accentColor,
3556
4055
  "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
@@ -3572,176 +4071,235 @@ function SwapModalTemplate({
3572
4071
  const buyKey = selectedBuy ? assetOptionKey(selectedBuy) : "";
3573
4072
  const canSwap = !smartUnsupported && !!selectedSell && !!selectedBuy && !!amount && !!quote && !quoteLoading && !isLoadingData;
3574
4073
  const title = step === "form" ? "Swap" : txTitle;
3575
- return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-send-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
3576
- /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
3577
- /* @__PURE__ */ jsxs("div", { className: "pollar-send-header-left", children: [
3578
- showBack && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onBack, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
3579
- /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: title })
3580
- ] }),
3581
- !isInProgress && /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
3582
- step === "form" && /* @__PURE__ */ jsx(
3583
- "button",
3584
- {
3585
- type: "button",
3586
- className: "pollar-modal-close",
3587
- onClick: onRefresh,
3588
- disabled: configLoading || isLoadingData,
3589
- "aria-label": "Refresh",
3590
- title: "Refresh balances and options",
3591
- children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx(
3592
- "path",
4074
+ return /* @__PURE__ */ jsxs(
4075
+ "div",
4076
+ {
4077
+ className: "pollar-modal-card pollar-send-modal",
4078
+ "data-theme": theme,
4079
+ style: cssVars,
4080
+ onClick: (e) => e.stopPropagation(),
4081
+ children: [
4082
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
4083
+ /* @__PURE__ */ jsxs("div", { className: "pollar-send-header-left", children: [
4084
+ showBack && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onBack, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
4085
+ /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: title })
4086
+ ] }),
4087
+ !isInProgress && /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
4088
+ step === "form" && /* @__PURE__ */ jsx(
4089
+ "button",
3593
4090
  {
3594
- d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2.5v3h-3",
3595
- stroke: "currentColor",
3596
- strokeWidth: "1.6",
3597
- strokeLinecap: "round",
3598
- strokeLinejoin: "round"
4091
+ type: "button",
4092
+ className: "pollar-modal-close",
4093
+ onClick: onRefresh,
4094
+ disabled: configLoading || isLoadingData,
4095
+ "aria-label": "Refresh",
4096
+ title: "Refresh balances and options",
4097
+ children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx(
4098
+ "path",
4099
+ {
4100
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2.5v3h-3",
4101
+ stroke: "currentColor",
4102
+ strokeWidth: "1.6",
4103
+ strokeLinecap: "round",
4104
+ strokeLinejoin: "round"
4105
+ }
4106
+ ) })
3599
4107
  }
3600
- ) })
3601
- }
3602
- ),
3603
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
3604
- ] })
3605
- ] }),
3606
- step === "form" && configLoading && /* @__PURE__ */ jsx("div", { className: "pollar-send-hint", children: "Loading swap options\u2026" }),
3607
- step === "form" && !configLoading && swapUnavailable && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: "Swap is not available for this app." }),
3608
- step === "form" && !configLoading && !swapUnavailable && /* @__PURE__ */ jsxs(Fragment, { children: [
3609
- smartUnsupported && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: "Swaps are not yet available for smart (passkey) wallets." }),
3610
- /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
3611
- /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "You pay" }),
3612
- isLoadingData ? /* @__PURE__ */ jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxs(
3613
- "select",
3614
- {
3615
- className: "pollar-input pollar-send-select",
3616
- value: sellKey,
3617
- onChange: (e) => {
3618
- const found = sellOptions.find((o) => assetOptionKey(o) === e.target.value);
3619
- if (found) onSelectSell(found);
3620
- },
3621
- children: [
3622
- /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select asset to sell" }),
3623
- sellOptions.map((o) => /* @__PURE__ */ jsxs("option", { value: assetOptionKey(o), children: [
3624
- o.code,
3625
- o.available !== void 0 ? ` \u2014 ${formatAmount2(o.available)} available` : ""
3626
- ] }, assetOptionKey(o)))
3627
- ]
3628
- }
3629
- )
3630
- ] }),
3631
- /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
3632
- /* @__PURE__ */ jsxs("div", { className: "pollar-send-label-row", children: [
3633
- /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Amount" }),
3634
- selectedSell?.available !== void 0 && /* @__PURE__ */ jsxs("span", { className: "pollar-send-hint", children: [
3635
- "Available: ",
3636
- formatAmount2(selectedSell.available),
3637
- " ",
3638
- selectedSell.code
4108
+ ),
4109
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
3639
4110
  ] })
3640
4111
  ] }),
3641
- /* @__PURE__ */ jsx(
3642
- "input",
3643
- {
3644
- className: "pollar-input",
3645
- type: "text",
3646
- inputMode: "decimal",
3647
- placeholder: "0.00",
3648
- value: amount,
3649
- onChange: (e) => onAmountChange(e.target.value)
3650
- }
3651
- )
3652
- ] }),
3653
- /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
3654
- /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "You receive" }),
3655
- isLoadingData ? /* @__PURE__ */ jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxs(
3656
- "select",
4112
+ step === "form" && configLoading && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
4113
+ /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
4114
+ /* @__PURE__ */ jsx("span", { children: "Loading swap options\u2026" })
4115
+ ] }),
4116
+ step === "form" && !configLoading && swapUnavailable && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: "Swap is not available for this app." }),
4117
+ step === "form" && !swapUnavailable && /* @__PURE__ */ jsxs(Fragment, { children: [
4118
+ smartUnsupported && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: "Swaps are not yet available for smart (passkey) wallets." }),
4119
+ /* @__PURE__ */ jsx(
4120
+ AssetSelect,
4121
+ {
4122
+ label: "You pay",
4123
+ value: sellKey,
4124
+ loading: isLoadingData,
4125
+ disabled: configLoading,
4126
+ options: sellOptions.map((o) => ({
4127
+ key: assetOptionKey(o),
4128
+ code: o.code,
4129
+ available: o.available,
4130
+ enabledInApp: o.enabledInApp
4131
+ })),
4132
+ onChange: (key) => {
4133
+ const found = sellOptions.find((o) => assetOptionKey(o) === key);
4134
+ if (found) onSelectSell(found);
4135
+ }
4136
+ }
4137
+ ),
4138
+ /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
4139
+ /* @__PURE__ */ jsxs("div", { className: "pollar-send-label-row", children: [
4140
+ /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Amount" }),
4141
+ selectedSell?.available !== void 0 && /* @__PURE__ */ jsxs("span", { className: "pollar-send-hint", children: [
4142
+ "Available: ",
4143
+ formatAmount3(selectedSell.available),
4144
+ " ",
4145
+ selectedSell.code
4146
+ ] })
4147
+ ] }),
4148
+ /* @__PURE__ */ jsx(
4149
+ "input",
4150
+ {
4151
+ className: "pollar-input",
4152
+ type: "text",
4153
+ inputMode: "decimal",
4154
+ placeholder: "0.00",
4155
+ value: amount,
4156
+ disabled: configLoading,
4157
+ onChange: (e) => onAmountChange(e.target.value)
4158
+ }
4159
+ )
4160
+ ] }),
4161
+ /* @__PURE__ */ jsx(
4162
+ AssetSelect,
4163
+ {
4164
+ label: "You receive",
4165
+ value: buyKey,
4166
+ loading: isLoadingData,
4167
+ disabled: configLoading,
4168
+ options: buyOptions.map((o) => ({
4169
+ key: assetOptionKey(o),
4170
+ code: o.code,
4171
+ enabledInApp: o.enabledInApp
4172
+ })),
4173
+ onChange: (key) => {
4174
+ const found = buyOptions.find((o) => assetOptionKey(o) === key);
4175
+ if (found) onSelectBuy(found);
4176
+ },
4177
+ children: customOpen ? /* @__PURE__ */ jsxs("div", { className: "pollar-swap-custom", children: [
4178
+ /* @__PURE__ */ jsx(
4179
+ "input",
4180
+ {
4181
+ className: "pollar-input",
4182
+ type: "text",
4183
+ placeholder: "Code (e.g. USDC)",
4184
+ value: customCode,
4185
+ onChange: (e) => setCustomCode(e.target.value)
4186
+ }
4187
+ ),
4188
+ /* @__PURE__ */ jsx(
4189
+ "input",
4190
+ {
4191
+ className: "pollar-input",
4192
+ type: "text",
4193
+ placeholder: "Issuer (G...)",
4194
+ value: customIssuer,
4195
+ onChange: (e) => setCustomIssuer(e.target.value)
4196
+ }
4197
+ ),
4198
+ customError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: customError }),
4199
+ /* @__PURE__ */ jsxs("div", { className: "pollar-swap-custom-actions", children: [
4200
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", onClick: submitCustomToken, children: "Add token" }),
4201
+ /* @__PURE__ */ jsx(
4202
+ "button",
4203
+ {
4204
+ type: "button",
4205
+ className: "pollar-swap-custom-cancel",
4206
+ onClick: () => {
4207
+ setCustomOpen(false);
4208
+ setCustomError("");
4209
+ },
4210
+ children: "Cancel"
4211
+ }
4212
+ )
4213
+ ] })
4214
+ ] }) : /* @__PURE__ */ jsx(
4215
+ "button",
4216
+ {
4217
+ type: "button",
4218
+ className: "pollar-swap-custom-toggle",
4219
+ disabled: configLoading,
4220
+ onClick: () => setCustomOpen(true),
4221
+ children: "+ Add a token by code / issuer"
4222
+ }
4223
+ )
4224
+ }
4225
+ ),
4226
+ /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
4227
+ /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Route" }),
4228
+ /* @__PURE__ */ jsx(
4229
+ "select",
4230
+ {
4231
+ className: "pollar-input pollar-send-select",
4232
+ value: provider,
4233
+ disabled: configLoading || providers.length === 0,
4234
+ onChange: (e) => onProviderChange(e.target.value),
4235
+ children: providers.length === 0 ? /* @__PURE__ */ jsx("option", { value: provider, children: configLoading ? "Loading\u2026" : PROVIDER_LABELS[provider] }) : providers.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: PROVIDER_LABELS[p] }, p))
4236
+ }
4237
+ )
4238
+ ] }),
4239
+ quoteLoading && /* @__PURE__ */ jsxs("div", { className: "pollar-send-hint pollar-inline-loading", children: [
4240
+ /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
4241
+ "Fetching best price\u2026"
4242
+ ] }),
4243
+ !quoteLoading && quoteError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: quoteError }),
4244
+ !quoteLoading && !quoteError && quote && selectedBuy && /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote", children: [
4245
+ /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
4246
+ /* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "You receive" }),
4247
+ /* @__PURE__ */ jsxs("span", { children: [
4248
+ "~ ",
4249
+ formatAmount3(quote.amountOut),
4250
+ " ",
4251
+ selectedBuy.code
4252
+ ] })
4253
+ ] }),
4254
+ /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
4255
+ /* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "Minimum received" }),
4256
+ /* @__PURE__ */ jsxs("span", { children: [
4257
+ formatAmount3(quote.minReceived),
4258
+ " ",
4259
+ selectedBuy.code
4260
+ ] })
4261
+ ] }),
4262
+ /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
4263
+ /* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "Price impact" }),
4264
+ /* @__PURE__ */ jsxs("span", { children: [
4265
+ quote.priceImpactPct,
4266
+ "%"
4267
+ ] })
4268
+ ] }),
4269
+ /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
4270
+ /* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "Route" }),
4271
+ /* @__PURE__ */ jsx("span", { children: PROVIDER_LABELS[quote.provider] })
4272
+ ] })
4273
+ ] }),
4274
+ !quoteLoading && !quoteError && !quote && selectedSell && selectedBuy && !!amount && /* @__PURE__ */ jsx("div", { className: "pollar-send-hint", children: "No route found for this pair." }),
4275
+ buyNeedsTrustline && selectedBuy && /* @__PURE__ */ jsxs("div", { className: "pollar-swap-trustline-notice", children: [
4276
+ "To receive ",
4277
+ selectedBuy.code,
4278
+ " your wallet needs a trustline. Swapping will create it first (~0.5 XLM reserve, refundable if you later remove it)."
4279
+ ] }),
4280
+ formError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: formError }),
4281
+ /* @__PURE__ */ jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsx("button", { className: "pollar-btn-primary", onClick: onSwap, disabled: !canSwap, children: buyNeedsTrustline ? "Create trustline & swap" : "Swap" }) })
4282
+ ] }),
4283
+ step === "tx" && /* @__PURE__ */ jsx(
4284
+ TxStatusView,
3657
4285
  {
3658
- className: "pollar-input pollar-send-select",
3659
- value: buyKey,
3660
- onChange: (e) => {
3661
- const found = buyOptions.find((o) => assetOptionKey(o) === e.target.value);
3662
- if (found) onSelectBuy(found);
4286
+ transaction,
4287
+ showXdr,
4288
+ copied,
4289
+ explorerUrl,
4290
+ walletType,
4291
+ onSignAndSend: () => {
3663
4292
  },
3664
- children: [
3665
- /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select asset to buy" }),
3666
- buyOptions.map((o) => /* @__PURE__ */ jsxs("option", { value: assetOptionKey(o), children: [
3667
- o.code,
3668
- o.enabledInApp ? "" : " (external)"
3669
- ] }, assetOptionKey(o)))
3670
- ]
3671
- }
3672
- )
3673
- ] }),
3674
- /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
3675
- /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Route" }),
3676
- /* @__PURE__ */ jsx(
3677
- "select",
3678
- {
3679
- className: "pollar-input pollar-send-select",
3680
- value: provider,
3681
- onChange: (e) => onProviderChange(e.target.value),
3682
- children: providers.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: PROVIDER_LABELS[p] }, p))
4293
+ onToggleXdr,
4294
+ onCopyHash,
4295
+ onRetry,
4296
+ onDone
3683
4297
  }
3684
- )
3685
- ] }),
3686
- quoteLoading && /* @__PURE__ */ jsx("div", { className: "pollar-send-hint", children: "Fetching best price\u2026" }),
3687
- !quoteLoading && quoteError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: quoteError }),
3688
- !quoteLoading && !quoteError && quote && selectedBuy && /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote", children: [
3689
- /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
3690
- /* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "You receive" }),
3691
- /* @__PURE__ */ jsxs("span", { children: [
3692
- "~ ",
3693
- formatAmount2(quote.amountOut),
3694
- " ",
3695
- selectedBuy.code
3696
- ] })
3697
- ] }),
3698
- /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
3699
- /* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "Minimum received" }),
3700
- /* @__PURE__ */ jsxs("span", { children: [
3701
- formatAmount2(quote.minReceived),
3702
- " ",
3703
- selectedBuy.code
3704
- ] })
3705
- ] }),
3706
- /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
3707
- /* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "Price impact" }),
3708
- /* @__PURE__ */ jsxs("span", { children: [
3709
- quote.priceImpactPct,
3710
- "%"
3711
- ] })
3712
- ] }),
3713
- /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
3714
- /* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "Route" }),
3715
- /* @__PURE__ */ jsx("span", { children: PROVIDER_LABELS[quote.provider] })
3716
- ] })
3717
- ] }),
3718
- !quoteLoading && !quoteError && !quote && selectedSell && selectedBuy && !!amount && /* @__PURE__ */ jsx("div", { className: "pollar-send-hint", children: "No route found for this pair." }),
3719
- buyNeedsTrustline && selectedBuy && /* @__PURE__ */ jsxs("div", { className: "pollar-swap-trustline-notice", children: [
3720
- "To receive ",
3721
- selectedBuy.code,
3722
- " your wallet needs a trustline. Swapping will create it first (~0.5 XLM reserve, refundable if you later remove it)."
3723
- ] }),
3724
- formError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: formError }),
3725
- /* @__PURE__ */ jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsx("button", { className: "pollar-btn-primary", onClick: onSwap, disabled: !canSwap, children: buyNeedsTrustline ? "Create trustline & swap" : "Swap" }) })
3726
- ] }),
3727
- step === "tx" && /* @__PURE__ */ jsx(
3728
- TxStatusView,
3729
- {
3730
- transaction,
3731
- showXdr,
3732
- copied,
3733
- explorerUrl,
3734
- walletType,
3735
- onSignAndSend: () => {
3736
- },
3737
- onToggleXdr,
3738
- onCopyHash,
3739
- onRetry,
3740
- onDone
3741
- }
3742
- ),
3743
- /* @__PURE__ */ jsx(PollarModalFooter, {})
3744
- ] });
4298
+ ),
4299
+ /* @__PURE__ */ jsx(PollarModalFooter, {})
4300
+ ]
4301
+ }
4302
+ );
3745
4303
  }
3746
4304
  var QUOTE_DEBOUNCE_MS = 400;
3747
4305
  function toRef(a) {
@@ -3777,6 +4335,7 @@ function SwapModal({ onClose }) {
3777
4335
  const [provider, setProvider] = useState("auto");
3778
4336
  const [venues, setVenues] = useState(null);
3779
4337
  const [catalogTokens, setCatalogTokens] = useState([]);
4338
+ const [customTokens, setCustomTokens] = useState([]);
3780
4339
  const [quotes, setQuotes] = useState([]);
3781
4340
  const [quoteLoading, setQuoteLoading] = useState(false);
3782
4341
  const [quoteError, setQuoteError] = useState("");
@@ -3818,7 +4377,7 @@ function SwapModal({ onClose }) {
3818
4377
  const balances = walletBalance.step === "loaded" ? walletBalance.data.balances : [];
3819
4378
  const assetRecords = enabledAssets.step === "loaded" ? enabledAssets.data.assets : [];
3820
4379
  const isLoadingData = walletBalance.step === "loading" || enabledAssets.step === "loading";
3821
- 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 }));
4380
+ const sellOptions = balances.filter((b) => b.type === "native" || !b.trustlineRemoved).map((b) => ({ ref: toRef(b), code: b.code, issuer: b.issuer, available: b.available, enabledInApp: b.enabledInApp }));
3822
4381
  const buyKeyOfSell = selectedSell ? `${selectedSell.code}:${selectedSell.issuer ?? "native"}` : "";
3823
4382
  const optKey = (o) => `${o.code}:${o.issuer ?? "native"}`;
3824
4383
  const enabledBuy = assetRecords.map((a) => ({
@@ -3834,7 +4393,31 @@ function SwapModal({ onClose }) {
3834
4393
  issuer: tk.issuer,
3835
4394
  enabledInApp: false
3836
4395
  })).filter((o) => !enabledKeys.has(optKey(o)));
3837
- const buyOptions = [...enabledBuy, ...catalogBuy].filter((o) => optKey(o) !== buyKeyOfSell);
4396
+ const knownKeys = /* @__PURE__ */ new Set([...enabledKeys, ...catalogBuy.map(optKey)]);
4397
+ const customBuy = customTokens.filter((o) => !knownKeys.has(optKey(o)));
4398
+ const buyOptions = [...enabledBuy, ...catalogBuy, ...customBuy].filter((o) => optKey(o) !== buyKeyOfSell);
4399
+ useEffect(() => {
4400
+ if (sellOptions.length === 0) return;
4401
+ if (!selectedSell || !sellOptions.some((o) => optKey(o) === optKey(selectedSell))) {
4402
+ setSelectedSell(sellOptions[0]);
4403
+ }
4404
+ }, [sellOptions, selectedSell]);
4405
+ useEffect(() => {
4406
+ if (buyOptions.length === 0) return;
4407
+ if (!selectedBuy || !buyOptions.some((o) => optKey(o) === optKey(selectedBuy))) {
4408
+ setSelectedBuy(buyOptions[0]);
4409
+ }
4410
+ }, [buyOptions, selectedBuy]);
4411
+ function addCustomToken(code, issuer) {
4412
+ const c = code.trim().toUpperCase();
4413
+ const i = issuer.trim();
4414
+ if (c.length < 1 || c.length > 12) return "Code must be 1-12 characters";
4415
+ if (i.length !== 56 || !i.startsWith("G")) return "Issuer must be a Stellar address (G..., 56 chars)";
4416
+ const opt = { ref: catalogRef(c, i), code: c, issuer: i, enabledInApp: false };
4417
+ setCustomTokens((prev) => prev.some((o) => optKey(o) === optKey(opt)) ? prev : [...prev, opt]);
4418
+ setSelectedBuy(opt);
4419
+ return null;
4420
+ }
3838
4421
  const buyNeedsTrustline = (() => {
3839
4422
  if (!selectedBuy || smartUnsupported) return false;
3840
4423
  if (selectedBuy.ref.type === "native") return false;
@@ -3883,7 +4466,7 @@ function SwapModal({ onClose }) {
3883
4466
  const buildData = "buildData" in transaction ? transaction.buildData : null;
3884
4467
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
3885
4468
  const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
3886
- const IN_FLIGHT_STEPS2 = [
4469
+ const IN_FLIGHT_STEPS3 = [
3887
4470
  "building",
3888
4471
  "signing",
3889
4472
  "submitting",
@@ -3891,7 +4474,7 @@ function SwapModal({ onClose }) {
3891
4474
  "signing-submitting",
3892
4475
  "building-signing-submitting"
3893
4476
  ];
3894
- const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
4477
+ const isInProgress = IN_FLIGHT_STEPS3.includes(transaction.step);
3895
4478
  const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
3896
4479
  const txTitle = isInProgress ? "Swapping\u2026" : transaction.step === "success" ? "Swapped!" : transaction.step === "error" ? "Swap failed" : "Confirm Swap";
3897
4480
  async function handleSwap() {
@@ -3900,8 +4483,224 @@ function SwapModal({ onClose }) {
3900
4483
  setFormError("Swaps are not yet supported for smart (passkey) wallets");
3901
4484
  return;
3902
4485
  }
3903
- if (!selectedSell || !selectedBuy) {
3904
- setFormError("Select both assets");
4486
+ if (!selectedSell || !selectedBuy) {
4487
+ setFormError("Select both assets");
4488
+ return;
4489
+ }
4490
+ const parsed = parseFloat(amount);
4491
+ if (!amount || isNaN(parsed) || parsed <= 0) {
4492
+ setFormError("Enter a valid amount");
4493
+ return;
4494
+ }
4495
+ if (selectedSell.available !== void 0 && parsed > parseFloat(selectedSell.available)) {
4496
+ setFormError("Insufficient balance");
4497
+ return;
4498
+ }
4499
+ if (!quote) {
4500
+ setFormError("No route available for this pair");
4501
+ return;
4502
+ }
4503
+ setStep("tx");
4504
+ await swap(quote);
4505
+ }
4506
+ async function handleRetry() {
4507
+ if (transaction.step === "error" && quote) await swap(quote);
4508
+ }
4509
+ function handleCopyHash() {
4510
+ if (!hash) return;
4511
+ navigator.clipboard.writeText(hash).then(() => {
4512
+ setCopied(true);
4513
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
4514
+ copyTimerRef.current = setTimeout(() => {
4515
+ copyTimerRef.current = null;
4516
+ setCopied(false);
4517
+ }, 2e3);
4518
+ });
4519
+ }
4520
+ function handleBack() {
4521
+ setStep("form");
4522
+ setShowXdr(false);
4523
+ setCopied(false);
4524
+ }
4525
+ return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsx(
4526
+ SwapModalTemplate,
4527
+ {
4528
+ theme,
4529
+ accentColor,
4530
+ step,
4531
+ txTitle,
4532
+ sellOptions,
4533
+ buyOptions,
4534
+ selectedSell,
4535
+ selectedBuy,
4536
+ amount,
4537
+ provider,
4538
+ providers,
4539
+ quote,
4540
+ quoteLoading,
4541
+ quoteError,
4542
+ formError,
4543
+ isLoadingData,
4544
+ smartUnsupported,
4545
+ configLoading,
4546
+ swapUnavailable,
4547
+ buyNeedsTrustline,
4548
+ transaction,
4549
+ showXdr,
4550
+ copied,
4551
+ explorerUrl,
4552
+ walletType,
4553
+ showBack,
4554
+ isInProgress,
4555
+ onClose,
4556
+ onBack: handleBack,
4557
+ onRefresh: handleRefresh,
4558
+ onSelectSell: setSelectedSell,
4559
+ onSelectBuy: setSelectedBuy,
4560
+ onAddCustomToken: addCustomToken,
4561
+ onAmountChange: setAmount,
4562
+ onProviderChange: setProvider,
4563
+ onSwap: () => void handleSwap(),
4564
+ onToggleXdr: () => setShowXdr((v) => !v),
4565
+ onCopyHash: handleCopyHash,
4566
+ onRetry: () => void handleRetry(),
4567
+ onDone: onClose
4568
+ }
4569
+ ) });
4570
+ }
4571
+ var POSITION_POLL_MS = 1e4;
4572
+ var PROVIDER_LABELS2 = {
4573
+ blend: "Blend",
4574
+ defindex: "DeFindex"
4575
+ };
4576
+ var IN_FLIGHT_STEPS2 = [
4577
+ "building",
4578
+ "signing",
4579
+ "submitting",
4580
+ "submitted",
4581
+ "signing-submitting",
4582
+ "building-signing-submitting"
4583
+ ];
4584
+ function formatAmount4(value) {
4585
+ const n = parseFloat(value);
4586
+ return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
4587
+ }
4588
+ function EarnModal({ onClose }) {
4589
+ const {
4590
+ getEarnProviders,
4591
+ getEarnOpportunities,
4592
+ getEarnPosition,
4593
+ earnDeposit,
4594
+ earnWithdraw,
4595
+ tx: transaction,
4596
+ wallet,
4597
+ network,
4598
+ styles
4599
+ } = usePollar();
4600
+ const walletType = wallet?.custody === "external" ? wallet.provider : null;
4601
+ const smartUnsupported = wallet?.custody === "smart";
4602
+ const { theme = "light", accentColor = "#005DB4" } = styles;
4603
+ const isDark = theme === "dark";
4604
+ const [step, setStep] = useState("form");
4605
+ const [tab, setTab] = useState("deposit");
4606
+ const [providers, setProviders] = useState(null);
4607
+ const [provider, setProvider] = useState(null);
4608
+ const [opportunities, setOpportunities] = useState([]);
4609
+ const [opportunityId, setOpportunityId] = useState("");
4610
+ const [position, setPosition] = useState(null);
4611
+ const [amount, setAmount] = useState("");
4612
+ const [loadingOpps, setLoadingOpps] = useState(false);
4613
+ const [formError, setFormError] = useState("");
4614
+ const [refreshing, setRefreshing] = useState(false);
4615
+ const [showXdr, setShowXdr] = useState(false);
4616
+ const [copied, setCopied] = useState(false);
4617
+ const copyTimerRef = useRef(null);
4618
+ const loadProviders = useCallback(() => {
4619
+ setProviders(null);
4620
+ return getEarnProviders().then((ps) => {
4621
+ setProviders(ps);
4622
+ setProvider((cur) => cur ?? ps[0] ?? null);
4623
+ }).catch(() => setProviders([]));
4624
+ }, [getEarnProviders]);
4625
+ useEffect(() => {
4626
+ void loadProviders();
4627
+ }, [loadProviders]);
4628
+ useEffect(() => {
4629
+ if (!provider) return;
4630
+ let cancelled = false;
4631
+ setLoadingOpps(true);
4632
+ getEarnOpportunities(provider).then((opps) => {
4633
+ if (cancelled) return;
4634
+ setOpportunities(opps);
4635
+ setOpportunityId((cur) => opps.some((o) => o.id === cur) ? cur : opps[0]?.id ?? "");
4636
+ }).catch(() => {
4637
+ if (!cancelled) setOpportunities([]);
4638
+ }).finally(() => {
4639
+ if (!cancelled) setLoadingOpps(false);
4640
+ });
4641
+ return () => {
4642
+ cancelled = true;
4643
+ };
4644
+ }, [provider, getEarnOpportunities]);
4645
+ const selectedOpportunity = opportunities.find((o) => o.id === opportunityId) ?? null;
4646
+ const refreshPosition = useCallback(() => {
4647
+ if (!provider || !opportunityId || !wallet) return;
4648
+ getEarnPosition({ provider, opportunity: opportunityId }).then(setPosition).catch(() => {
4649
+ });
4650
+ }, [provider, opportunityId, wallet, getEarnPosition]);
4651
+ useEffect(() => {
4652
+ setPosition(null);
4653
+ refreshPosition();
4654
+ }, [refreshPosition]);
4655
+ useEffect(() => {
4656
+ if (step !== "form" || !provider || !opportunityId) return;
4657
+ const id = setInterval(refreshPosition, POSITION_POLL_MS);
4658
+ return () => clearInterval(id);
4659
+ }, [step, provider, opportunityId, refreshPosition]);
4660
+ useEffect(
4661
+ () => () => {
4662
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
4663
+ },
4664
+ []
4665
+ );
4666
+ const providersLoading = providers === null;
4667
+ const earnUnavailable = providers !== null && providers.length === 0;
4668
+ const withdrawUnit = position?.withdrawUnit ?? "asset";
4669
+ const assetCode = selectedOpportunity?.asset.code ?? "";
4670
+ const amountUnitLabel = tab === "deposit" ? assetCode : withdrawUnit === "shares" ? "shares" : assetCode;
4671
+ const hash = transaction.step === "success" ? transaction.hash : null;
4672
+ const buildData = "buildData" in transaction ? transaction.buildData : null;
4673
+ const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
4674
+ const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
4675
+ const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
4676
+ const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
4677
+ const txTitle = isInProgress ? tab === "deposit" ? "Depositing\u2026" : "Withdrawing\u2026" : transaction.step === "success" ? "Done!" : transaction.step === "error" ? tab === "deposit" ? "Deposit failed" : "Withdraw failed" : "Confirm";
4678
+ const canSubmit = !smartUnsupported && !!provider && !!opportunityId && !!amount && parseFloat(amount) > 0 && !providersLoading && !loadingOpps;
4679
+ const cssVars = {
4680
+ "--pollar-accent": accentColor,
4681
+ "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
4682
+ "--pollar-border": isDark ? "#374151" : "#e5e7eb",
4683
+ "--pollar-text": isDark ? "#ffffff" : "#111827",
4684
+ "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
4685
+ "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
4686
+ "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
4687
+ "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
4688
+ "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
4689
+ "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
4690
+ "--pollar-buttons-border-radius": "6px",
4691
+ "--pollar-buttons-height": "44px",
4692
+ "--pollar-input-height": "44px",
4693
+ "--pollar-input-border-radius": "0.5rem",
4694
+ "--pollar-card-border-radius": "10px"
4695
+ };
4696
+ async function handleSubmit() {
4697
+ setFormError("");
4698
+ if (smartUnsupported) {
4699
+ setFormError("Earn is not yet supported for smart (passkey) wallets");
4700
+ return;
4701
+ }
4702
+ if (!provider || !opportunityId) {
4703
+ setFormError("Select a vault or pool");
3905
4704
  return;
3906
4705
  }
3907
4706
  const parsed = parseFloat(amount);
@@ -3909,19 +4708,23 @@ function SwapModal({ onClose }) {
3909
4708
  setFormError("Enter a valid amount");
3910
4709
  return;
3911
4710
  }
3912
- if (selectedSell.available !== void 0 && parsed > parseFloat(selectedSell.available)) {
3913
- setFormError("Insufficient balance");
3914
- return;
3915
- }
3916
- if (!quote) {
3917
- setFormError("No route available for this pair");
4711
+ if (tab === "withdraw" && position && parsed > parseFloat(position.withdrawable)) {
4712
+ setFormError("Amount exceeds your position");
3918
4713
  return;
3919
4714
  }
3920
4715
  setStep("tx");
3921
- await swap(quote);
4716
+ const params = { provider, opportunity: opportunityId, amount };
4717
+ const outcome = tab === "deposit" ? await earnDeposit(params) : await earnWithdraw(params);
4718
+ if (outcome.status === "success" || outcome.status === "pending") {
4719
+ setAmount("");
4720
+ refreshPosition();
4721
+ }
3922
4722
  }
3923
4723
  async function handleRetry() {
3924
- if (transaction.step === "error" && quote) await swap(quote);
4724
+ if (transaction.step !== "error" || !provider || !opportunityId) return;
4725
+ const params = { provider, opportunity: opportunityId, amount };
4726
+ if (tab === "deposit") await earnDeposit(params);
4727
+ else await earnWithdraw(params);
3925
4728
  }
3926
4729
  function handleCopyHash() {
3927
4730
  if (!hash) return;
@@ -3938,49 +4741,201 @@ function SwapModal({ onClose }) {
3938
4741
  setStep("form");
3939
4742
  setShowXdr(false);
3940
4743
  setCopied(false);
4744
+ refreshPosition();
3941
4745
  }
3942
- return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsx(
3943
- SwapModalTemplate,
4746
+ async function handleRefresh() {
4747
+ if (refreshing || !provider) return;
4748
+ setRefreshing(true);
4749
+ try {
4750
+ const opps = await getEarnOpportunities(provider);
4751
+ setOpportunities(opps);
4752
+ setOpportunityId((cur) => opps.some((o) => o.id === cur) ? cur : opps[0]?.id ?? "");
4753
+ refreshPosition();
4754
+ } catch {
4755
+ } finally {
4756
+ setRefreshing(false);
4757
+ }
4758
+ }
4759
+ const title = step === "form" ? "Earn" : txTitle;
4760
+ return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsxs(
4761
+ "div",
3944
4762
  {
3945
- theme,
3946
- accentColor,
3947
- step,
3948
- txTitle,
3949
- sellOptions,
3950
- buyOptions,
3951
- selectedSell,
3952
- selectedBuy,
3953
- amount,
3954
- provider,
3955
- providers,
3956
- quote,
3957
- quoteLoading,
3958
- quoteError,
3959
- formError,
3960
- isLoadingData,
3961
- smartUnsupported,
3962
- configLoading,
3963
- swapUnavailable,
3964
- buyNeedsTrustline,
3965
- transaction,
3966
- showXdr,
3967
- copied,
3968
- explorerUrl,
3969
- walletType,
3970
- showBack,
3971
- isInProgress,
3972
- onClose,
3973
- onBack: handleBack,
3974
- onRefresh: handleRefresh,
3975
- onSelectSell: setSelectedSell,
3976
- onSelectBuy: setSelectedBuy,
3977
- onAmountChange: setAmount,
3978
- onProviderChange: setProvider,
3979
- onSwap: () => void handleSwap(),
3980
- onToggleXdr: () => setShowXdr((v) => !v),
3981
- onCopyHash: handleCopyHash,
3982
- onRetry: () => void handleRetry(),
3983
- onDone: onClose
4763
+ className: "pollar-modal-card pollar-send-modal",
4764
+ "data-theme": theme,
4765
+ style: cssVars,
4766
+ onClick: (e) => e.stopPropagation(),
4767
+ children: [
4768
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
4769
+ /* @__PURE__ */ jsxs("div", { className: "pollar-send-header-left", children: [
4770
+ showBack && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: handleBack, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
4771
+ /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: title })
4772
+ ] }),
4773
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
4774
+ step === "form" && !earnUnavailable && !smartUnsupported && /* @__PURE__ */ jsx(
4775
+ "button",
4776
+ {
4777
+ type: "button",
4778
+ className: "pollar-modal-close",
4779
+ onClick: () => void handleRefresh(),
4780
+ disabled: refreshing || providersLoading,
4781
+ "aria-label": "Refresh",
4782
+ children: /* @__PURE__ */ jsx(
4783
+ "svg",
4784
+ {
4785
+ className: refreshing ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
4786
+ width: "16",
4787
+ height: "16",
4788
+ viewBox: "0 0 16 16",
4789
+ fill: "none",
4790
+ "aria-hidden": true,
4791
+ children: /* @__PURE__ */ jsx(
4792
+ "path",
4793
+ {
4794
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
4795
+ stroke: "currentColor",
4796
+ strokeWidth: "1.6",
4797
+ strokeLinecap: "round",
4798
+ strokeLinejoin: "round"
4799
+ }
4800
+ )
4801
+ }
4802
+ )
4803
+ }
4804
+ ),
4805
+ !isInProgress && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
4806
+ ] })
4807
+ ] }),
4808
+ step === "form" && providersLoading && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
4809
+ /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
4810
+ /* @__PURE__ */ jsx("span", { children: "Loading Earn options\u2026" })
4811
+ ] }),
4812
+ step === "form" && earnUnavailable && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: "Earn is not available for this app." }),
4813
+ step === "form" && !earnUnavailable && /* @__PURE__ */ jsxs(Fragment, { children: [
4814
+ smartUnsupported && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: "Earn is not yet available for smart (passkey) wallets." }),
4815
+ /* @__PURE__ */ jsxs("div", { className: "pollar-tabs", children: [
4816
+ /* @__PURE__ */ jsx(
4817
+ "button",
4818
+ {
4819
+ type: "button",
4820
+ className: "pollar-tab",
4821
+ "data-active": tab === "deposit",
4822
+ onClick: () => {
4823
+ setTab("deposit");
4824
+ setFormError("");
4825
+ },
4826
+ children: "Deposit"
4827
+ }
4828
+ ),
4829
+ /* @__PURE__ */ jsx(
4830
+ "button",
4831
+ {
4832
+ type: "button",
4833
+ className: "pollar-tab",
4834
+ "data-active": tab === "withdraw",
4835
+ onClick: () => {
4836
+ setTab("withdraw");
4837
+ setFormError("");
4838
+ },
4839
+ children: "Withdraw"
4840
+ }
4841
+ )
4842
+ ] }),
4843
+ providers && providers.length > 1 && /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
4844
+ /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Provider" }),
4845
+ /* @__PURE__ */ jsx(
4846
+ "select",
4847
+ {
4848
+ className: "pollar-input pollar-send-select",
4849
+ value: provider ?? "",
4850
+ onChange: (e) => setProvider(e.target.value),
4851
+ children: providers.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: PROVIDER_LABELS2[p] }, p))
4852
+ }
4853
+ )
4854
+ ] }),
4855
+ /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
4856
+ /* @__PURE__ */ jsxs("div", { className: "pollar-send-label-row", children: [
4857
+ /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: provider === "defindex" ? "Vault" : "Pool" }),
4858
+ loadingOpps && /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm", "aria-label": "Loading options" })
4859
+ ] }),
4860
+ /* @__PURE__ */ jsx(
4861
+ "select",
4862
+ {
4863
+ className: "pollar-input pollar-send-select",
4864
+ value: opportunityId,
4865
+ disabled: loadingOpps || opportunities.length === 0,
4866
+ onChange: (e) => setOpportunityId(e.target.value),
4867
+ children: opportunities.length === 0 ? /* @__PURE__ */ jsx("option", { value: "", children: loadingOpps ? "Loading\u2026" : "None available" }) : opportunities.map((o) => /* @__PURE__ */ jsxs("option", { value: o.id, children: [
4868
+ o.name,
4869
+ " \xB7 ",
4870
+ o.apy.toFixed(2),
4871
+ "% APY"
4872
+ ] }, o.id))
4873
+ }
4874
+ )
4875
+ ] }),
4876
+ selectedOpportunity && /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote", children: [
4877
+ /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
4878
+ /* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "Your position" }),
4879
+ /* @__PURE__ */ jsxs("span", { children: [
4880
+ position ? formatAmount4(position.balance) : "\u2026",
4881
+ " ",
4882
+ assetCode
4883
+ ] })
4884
+ ] }),
4885
+ /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
4886
+ /* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "APY" }),
4887
+ /* @__PURE__ */ jsxs("span", { className: "pollar-earn-live", children: [
4888
+ selectedOpportunity.apy.toFixed(2),
4889
+ "%"
4890
+ ] })
4891
+ ] })
4892
+ ] }),
4893
+ /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
4894
+ /* @__PURE__ */ jsxs("div", { className: "pollar-send-label-row", children: [
4895
+ /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: tab === "deposit" ? "Amount" : "Withdraw amount" }),
4896
+ tab === "withdraw" && position && /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-swap-custom-toggle", onClick: () => setAmount(position.withdrawable), children: [
4897
+ "Max: ",
4898
+ formatAmount4(position.withdrawable),
4899
+ " ",
4900
+ amountUnitLabel
4901
+ ] })
4902
+ ] }),
4903
+ /* @__PURE__ */ jsxs("div", { className: "pollar-earn-amount", children: [
4904
+ /* @__PURE__ */ jsx(
4905
+ "input",
4906
+ {
4907
+ className: "pollar-input",
4908
+ type: "text",
4909
+ inputMode: "decimal",
4910
+ placeholder: "0.00",
4911
+ value: amount,
4912
+ onChange: (e) => setAmount(e.target.value)
4913
+ }
4914
+ ),
4915
+ amountUnitLabel && /* @__PURE__ */ jsx("span", { className: "pollar-earn-amount-unit", children: amountUnitLabel })
4916
+ ] })
4917
+ ] }),
4918
+ formError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: formError }),
4919
+ /* @__PURE__ */ jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsx("button", { className: "pollar-btn-primary", onClick: () => void handleSubmit(), disabled: !canSubmit, children: tab === "deposit" ? "Deposit" : "Withdraw" }) })
4920
+ ] }),
4921
+ step === "tx" && /* @__PURE__ */ jsx(
4922
+ TxStatusView,
4923
+ {
4924
+ transaction,
4925
+ showXdr,
4926
+ copied,
4927
+ explorerUrl,
4928
+ walletType,
4929
+ onSignAndSend: () => {
4930
+ },
4931
+ onToggleXdr: () => setShowXdr((v) => !v),
4932
+ onCopyHash: handleCopyHash,
4933
+ onRetry: () => void handleRetry(),
4934
+ onDone: onClose
4935
+ }
4936
+ ),
4937
+ /* @__PURE__ */ jsx(PollarModalFooter, {})
4938
+ ]
3984
4939
  }
3985
4940
  ) });
3986
4941
  }
@@ -4075,30 +5030,46 @@ function SessionsModalTemplate({
4075
5030
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
4076
5031
  /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Active sessions" }),
4077
5032
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
4078
- /* @__PURE__ */ jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading, children: [
4079
- /* @__PURE__ */ jsxs(
4080
- "svg",
4081
- {
4082
- className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
4083
- width: "13",
4084
- height: "13",
4085
- viewBox: "0 0 13 13",
4086
- fill: "none",
4087
- "aria-hidden": true,
4088
- children: [
4089
- /* @__PURE__ */ jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
4090
- /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
4091
- ]
4092
- }
4093
- ),
4094
- "Refresh"
4095
- ] }),
5033
+ /* @__PURE__ */ jsx(
5034
+ "button",
5035
+ {
5036
+ type: "button",
5037
+ className: "pollar-modal-close",
5038
+ onClick: onRefresh,
5039
+ disabled: isLoading,
5040
+ "aria-label": "Refresh",
5041
+ title: "Refresh",
5042
+ children: /* @__PURE__ */ jsx(
5043
+ "svg",
5044
+ {
5045
+ className: isLoading ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
5046
+ width: "16",
5047
+ height: "16",
5048
+ viewBox: "0 0 16 16",
5049
+ fill: "none",
5050
+ "aria-hidden": true,
5051
+ children: /* @__PURE__ */ jsx(
5052
+ "path",
5053
+ {
5054
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
5055
+ stroke: "currentColor",
5056
+ strokeWidth: "1.6",
5057
+ strokeLinecap: "round",
5058
+ strokeLinejoin: "round"
5059
+ }
5060
+ )
5061
+ }
5062
+ )
5063
+ }
5064
+ ),
4096
5065
  /* @__PURE__ */ jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
4097
5066
  ] })
4098
5067
  ] }),
4099
5068
  /* @__PURE__ */ jsxs("div", { className: "pollar-sessions-list", children: [
4100
- state.step === "idle" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
4101
- isLoading && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
5069
+ (state.step === "idle" || isLoading) && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
5070
+ /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
5071
+ /* @__PURE__ */ jsx("span", { children: "Loading\u2026" })
5072
+ ] }),
4102
5073
  state.step === "error" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: state.message }),
4103
5074
  state.step === "loaded" && sessions.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No active sessions." }),
4104
5075
  sessions.map((s) => {
@@ -4127,7 +5098,10 @@ function SessionsModalTemplate({
4127
5098
  className: "pollar-sessions-item-revoke",
4128
5099
  onClick: () => onRevoke(s.familyId),
4129
5100
  disabled: isRevoking || signingOutEverywhere,
4130
- children: isRevoking ? "Revoking\u2026" : "Revoke"
5101
+ children: isRevoking ? /* @__PURE__ */ jsxs(Fragment, { children: [
5102
+ /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm pollar-spinner-current" }),
5103
+ "Revoking\u2026"
5104
+ ] }) : "Revoke"
4131
5105
  }
4132
5106
  )
4133
5107
  ] }, s.familyId);
@@ -4140,7 +5114,10 @@ function SessionsModalTemplate({
4140
5114
  onClick: onLogoutEverywhere,
4141
5115
  disabled: signingOutEverywhere || otherCount === 0,
4142
5116
  title: otherCount === 0 ? "No other devices to sign out" : void 0,
4143
- children: signingOutEverywhere ? "Signing out\u2026" : "Sign out everywhere"
5117
+ children: signingOutEverywhere ? /* @__PURE__ */ jsxs(Fragment, { children: [
5118
+ /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm pollar-spinner-current" }),
5119
+ "Signing out\u2026"
5120
+ ] }) : "Sign out everywhere"
4144
5121
  }
4145
5122
  ) }),
4146
5123
  /* @__PURE__ */ jsx(PollarModalFooter, {})
@@ -4333,6 +5310,33 @@ function StatusBadge({ status }) {
4333
5310
  function formatDate(iso) {
4334
5311
  return new Date(iso).toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" });
4335
5312
  }
5313
+ function truncateMiddle(value, head = 4, tail = 4) {
5314
+ return value.length <= head + tail + 1 ? value : `${value.slice(0, head)}\u2026${value.slice(-tail)}`;
5315
+ }
5316
+ var STELLAR_ADDRESS = /\b[GC][A-Z2-7]{55}\b/g;
5317
+ function AddressChip({ value, label }) {
5318
+ return /* @__PURE__ */ jsxs("span", { className: "pollar-hist-item-issuer", children: [
5319
+ truncateMiddle(value),
5320
+ /* @__PURE__ */ jsx(CopyButton, { value, label, className: "pollar-copy-btn-sm" })
5321
+ ] });
5322
+ }
5323
+ function renderSummary(summary) {
5324
+ const parts = [];
5325
+ let last = 0;
5326
+ let key = 0;
5327
+ STELLAR_ADDRESS.lastIndex = 0;
5328
+ for (let m = STELLAR_ADDRESS.exec(summary); m !== null; m = STELLAR_ADDRESS.exec(summary)) {
5329
+ if (m.index > last) parts.push(/* @__PURE__ */ jsx("span", { children: summary.slice(last, m.index) }, key++));
5330
+ const address = m[0];
5331
+ parts.push(
5332
+ /* @__PURE__ */ jsx(AddressChip, { value: address, label: address[0] === "C" ? "Copy contract address" : "Copy wallet address" }, key++)
5333
+ );
5334
+ last = m.index + address.length;
5335
+ }
5336
+ if (parts.length === 0) return /* @__PURE__ */ jsx("span", { className: "pollar-hist-item-title", children: summary });
5337
+ if (last < summary.length) parts.push(/* @__PURE__ */ jsx("span", { children: summary.slice(last) }, key));
5338
+ return parts;
5339
+ }
4336
5340
  function TxHistoryModalTemplate({
4337
5341
  theme,
4338
5342
  accentColor,
@@ -4378,59 +5382,106 @@ function TxHistoryModalTemplate({
4378
5382
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
4379
5383
  /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Transaction History" }),
4380
5384
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
4381
- /* @__PURE__ */ jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading, children: [
4382
- /* @__PURE__ */ jsxs(
4383
- "svg",
4384
- {
4385
- className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
4386
- width: "13",
4387
- height: "13",
4388
- viewBox: "0 0 13 13",
4389
- fill: "none",
4390
- "aria-hidden": true,
4391
- children: [
4392
- /* @__PURE__ */ jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
4393
- /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
4394
- ]
4395
- }
4396
- ),
4397
- "Refresh"
4398
- ] }),
5385
+ /* @__PURE__ */ jsx(
5386
+ "button",
5387
+ {
5388
+ type: "button",
5389
+ className: "pollar-modal-close",
5390
+ onClick: onRefresh,
5391
+ disabled: isLoading,
5392
+ "aria-label": "Refresh",
5393
+ title: "Refresh",
5394
+ children: /* @__PURE__ */ jsx(
5395
+ "svg",
5396
+ {
5397
+ className: isLoading ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
5398
+ width: "16",
5399
+ height: "16",
5400
+ viewBox: "0 0 16 16",
5401
+ fill: "none",
5402
+ "aria-hidden": true,
5403
+ children: /* @__PURE__ */ jsx(
5404
+ "path",
5405
+ {
5406
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
5407
+ stroke: "currentColor",
5408
+ strokeWidth: "1.6",
5409
+ strokeLinecap: "round",
5410
+ strokeLinejoin: "round"
5411
+ }
5412
+ )
5413
+ }
5414
+ )
5415
+ }
5416
+ ),
4399
5417
  /* @__PURE__ */ jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
4400
5418
  ] })
4401
5419
  ] }),
4402
5420
  /* @__PURE__ */ jsxs("div", { className: "pollar-hist-list", children: [
4403
5421
  txHistory.step === "idle" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Click Refresh to load transactions." }),
4404
- isLoading && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
5422
+ isLoading && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
5423
+ /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
5424
+ /* @__PURE__ */ jsx("span", { children: "Loading\u2026" })
5425
+ ] }),
4405
5426
  txHistory.step === "error" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: txHistory.message }),
4406
5427
  txHistory.step === "loaded" && records.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No transactions yet." }),
4407
5428
  records.map((record) => {
4408
- const explorerUrl = `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${record.hash}`;
5429
+ const hash = typeof record.hash === "string" && record.hash.length > 0 ? record.hash : void 0;
5430
+ const explorerUrl = hash ? `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${hash}` : void 0;
5431
+ const asset = typeof record.details?.asset === "string" ? record.details.asset : void 0;
5432
+ const colon = asset ? asset.indexOf(":") : -1;
5433
+ const trustline = record.operation === "change_trust" && asset && colon > 0 ? {
5434
+ prefix: record.summary.split(":")[0],
5435
+ code: asset.slice(0, colon),
5436
+ issuer: asset.slice(colon + 1)
5437
+ } : void 0;
5438
+ const contract = record.operation === "invoke_contract" && typeof record.details?.contractId === "string" && typeof record.details?.method === "string" ? { method: record.details.method, contractId: record.details.contractId } : void 0;
4409
5439
  return /* @__PURE__ */ jsxs("div", { className: "pollar-hist-item", children: [
4410
- /* @__PURE__ */ jsx("span", { className: "pollar-hist-item-summary", children: record.summary }),
4411
- /* @__PURE__ */ jsx(StatusBadge, { status: record.status }),
5440
+ /* @__PURE__ */ jsxs("div", { className: "pollar-hist-item-top", children: [
5441
+ /* @__PURE__ */ jsx("span", { className: "pollar-hist-item-summary", children: trustline ? /* @__PURE__ */ jsxs(Fragment, { children: [
5442
+ /* @__PURE__ */ jsxs("span", { className: "pollar-hist-item-title", children: [
5443
+ trustline.prefix,
5444
+ ": ",
5445
+ trustline.code
5446
+ ] }),
5447
+ /* @__PURE__ */ jsx(AddressChip, { value: trustline.issuer, label: "Copy issuer" })
5448
+ ] }) : contract ? /* @__PURE__ */ jsxs(Fragment, { children: [
5449
+ /* @__PURE__ */ jsxs("span", { className: "pollar-hist-item-title", children: [
5450
+ "Invoke ",
5451
+ contract.method,
5452
+ "() on"
5453
+ ] }),
5454
+ /* @__PURE__ */ jsx(AddressChip, { value: contract.contractId, label: "Copy contract address" })
5455
+ ] }) : renderSummary(record.summary) }),
5456
+ /* @__PURE__ */ jsx(StatusBadge, { status: record.status })
5457
+ ] }),
4412
5458
  /* @__PURE__ */ jsxs("span", { className: "pollar-hist-item-meta", children: [
4413
5459
  /* @__PURE__ */ jsx("span", { children: record.operation }),
5460
+ typeof record.details?.sponsored === "boolean" && /* @__PURE__ */ jsxs("span", { children: [
5461
+ "\xB7 ",
5462
+ record.details.sponsored ? "Sponsored" : "Self-paid"
5463
+ ] }),
4414
5464
  record.feeXlm && /* @__PURE__ */ jsxs("span", { children: [
4415
5465
  "\xB7 ",
4416
5466
  record.feeXlm,
4417
5467
  " XLM"
4418
- ] }),
4419
- /* @__PURE__ */ jsxs("span", { children: [
4420
- "\xB7 ",
4421
- formatDate(record.createdAt)
4422
- ] }),
4423
- /* @__PURE__ */ jsx("span", { children: "\xB7" }),
4424
- /* @__PURE__ */ jsxs(
4425
- "a",
4426
- {
4427
- className: "pollar-hist-item-explorer",
4428
- href: explorerUrl,
4429
- target: "_blank",
4430
- rel: "noopener noreferrer",
4431
- "aria-label": "View on Stellar Explorer",
4432
- children: [
4433
- /* @__PURE__ */ jsxs("svg", { width: "11", height: "11", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
5468
+ ] })
5469
+ ] }),
5470
+ /* @__PURE__ */ jsxs("div", { className: "pollar-hist-item-footer", children: [
5471
+ /* @__PURE__ */ jsx("span", { children: formatDate(record.createdAt) }),
5472
+ hash && /* @__PURE__ */ jsxs(Fragment, { children: [
5473
+ /* @__PURE__ */ jsx("span", { className: "pollar-hist-item-dot", children: "\xB7" }),
5474
+ /* @__PURE__ */ jsx("span", { className: "pollar-hist-item-hash", children: truncateMiddle(hash, 6, 6) }),
5475
+ /* @__PURE__ */ jsx(CopyButton, { value: hash, label: "Copy transaction hash", className: "pollar-copy-btn-sm" }),
5476
+ /* @__PURE__ */ jsx(
5477
+ "a",
5478
+ {
5479
+ className: "pollar-hist-item-explorer",
5480
+ href: explorerUrl,
5481
+ target: "_blank",
5482
+ rel: "noopener noreferrer",
5483
+ "aria-label": "View on Stellar Explorer",
5484
+ children: /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
4434
5485
  /* @__PURE__ */ jsx(
4435
5486
  "path",
4436
5487
  {
@@ -4450,11 +5501,10 @@ function TxHistoryModalTemplate({
4450
5501
  strokeLinejoin: "round"
4451
5502
  }
4452
5503
  )
4453
- ] }),
4454
- "Explorer"
4455
- ]
4456
- }
4457
- )
5504
+ ] })
5505
+ }
5506
+ )
5507
+ ] })
4458
5508
  ] })
4459
5509
  ] }, record.id);
4460
5510
  })
@@ -4508,7 +5558,7 @@ function TxHistoryModal({ onClose }) {
4508
5558
  }
4509
5559
  function formatBalance2(balance) {
4510
5560
  const n = parseFloat(balance);
4511
- return isNaN(n) ? balance : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
5561
+ return isNaN(n) ? balance : n.toLocaleString(void 0, { minimumFractionDigits: 7, maximumFractionDigits: 7 });
4512
5562
  }
4513
5563
  function cropAddress2(address) {
4514
5564
  if (address.length <= 16) return address;
@@ -4517,7 +5567,13 @@ function cropAddress2(address) {
4517
5567
  function BalanceItem({ record }) {
4518
5568
  const balanceDiffers = record.balance !== record.available;
4519
5569
  return /* @__PURE__ */ jsxs("div", { className: "pollar-bal-item", children: [
4520
- /* @__PURE__ */ jsx("span", { className: "pollar-bal-asset", children: record.code }),
5570
+ /* @__PURE__ */ jsxs("div", { className: "pollar-bal-asset-info", children: [
5571
+ /* @__PURE__ */ jsx("span", { className: "pollar-bal-asset", children: record.code }),
5572
+ record.issuer && /* @__PURE__ */ jsxs("span", { className: "pollar-bal-issuer", children: [
5573
+ /* @__PURE__ */ jsx("span", { className: "pollar-bal-issuer-addr", children: cropAddress2(record.issuer) }),
5574
+ /* @__PURE__ */ jsx(CopyButton, { value: record.issuer, label: "Copy issuer address", className: "pollar-copy-btn-sm" })
5575
+ ] })
5576
+ ] }),
4521
5577
  /* @__PURE__ */ jsxs("div", { className: "pollar-bal-amounts", children: [
4522
5578
  /* @__PURE__ */ jsx("span", { className: "pollar-bal-amount", children: formatBalance2(record.balance) }),
4523
5579
  balanceDiffers && /* @__PURE__ */ jsxs("span", { className: "pollar-bal-available", children: [
@@ -4559,29 +5615,49 @@ function WalletBalanceModalTemplate({
4559
5615
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
4560
5616
  /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Wallet Balance" }),
4561
5617
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
4562
- /* @__PURE__ */ jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading, children: [
4563
- /* @__PURE__ */ jsxs(
4564
- "svg",
4565
- {
4566
- className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
4567
- width: "13",
4568
- height: "13",
4569
- viewBox: "0 0 13 13",
4570
- fill: "none",
4571
- "aria-hidden": true,
4572
- children: [
4573
- /* @__PURE__ */ jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
4574
- /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
4575
- ]
4576
- }
4577
- ),
4578
- "Refresh"
4579
- ] }),
5618
+ /* @__PURE__ */ jsx(
5619
+ "button",
5620
+ {
5621
+ type: "button",
5622
+ className: "pollar-modal-close",
5623
+ onClick: onRefresh,
5624
+ disabled: isLoading,
5625
+ "aria-label": "Refresh",
5626
+ title: "Refresh",
5627
+ children: /* @__PURE__ */ jsx(
5628
+ "svg",
5629
+ {
5630
+ className: isLoading ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
5631
+ width: "16",
5632
+ height: "16",
5633
+ viewBox: "0 0 16 16",
5634
+ fill: "none",
5635
+ "aria-hidden": true,
5636
+ children: /* @__PURE__ */ jsx(
5637
+ "path",
5638
+ {
5639
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
5640
+ stroke: "currentColor",
5641
+ strokeWidth: "1.6",
5642
+ strokeLinecap: "round",
5643
+ strokeLinejoin: "round"
5644
+ }
5645
+ )
5646
+ }
5647
+ )
5648
+ }
5649
+ ),
4580
5650
  /* @__PURE__ */ jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
4581
5651
  ] })
4582
5652
  ] }),
4583
- walletAddress && /* @__PURE__ */ jsx("div", { className: "pollar-bal-address", children: cropAddress2(walletAddress) }),
4584
- isLoading && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
5653
+ walletAddress && /* @__PURE__ */ jsxs("div", { className: "pollar-bal-address-row", children: [
5654
+ /* @__PURE__ */ jsx("span", { className: "pollar-bal-address", children: cropAddress2(walletAddress) }),
5655
+ /* @__PURE__ */ jsx(CopyButton, { value: walletAddress, label: "Copy wallet address" })
5656
+ ] }),
5657
+ isLoading && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
5658
+ /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
5659
+ /* @__PURE__ */ jsx("span", { children: "Loading\u2026" })
5660
+ ] }),
4585
5661
  walletBalance.step === "error" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: walletBalance.message }),
4586
5662
  data && !data.exists && /* @__PURE__ */ jsxs("div", { className: "pollar-modal-empty", children: [
4587
5663
  "Account not found on ",
@@ -4791,6 +5867,7 @@ function PollarProvider({
4791
5867
  const [enabledAssetsModalOpen, setEnabledAssetsModalOpen] = useState(false);
4792
5868
  const [sendModalOpen, setSendModalOpen] = useState(false);
4793
5869
  const [swapModalOpen, setSwapModalOpen] = useState(false);
5870
+ const [earnModalOpen, setEarnModalOpen] = useState(false);
4794
5871
  const [receiveModalOpen, setReceiveModalOpen] = useState(false);
4795
5872
  const [sessionsModalOpen, setSessionsModalOpen] = useState(false);
4796
5873
  const [distributionRulesModalOpen, setDistributionRulesModalOpen] = useState(false);
@@ -4841,6 +5918,13 @@ function PollarProvider({
4841
5918
  getSwapQuote: (params) => pollarClient.getSwapQuote(params),
4842
5919
  swap: (quote, opts) => pollarClient.swap(quote, opts),
4843
5920
  openSwapModal: () => setSwapModalOpen(true),
5921
+ // earn
5922
+ getEarnProviders: () => pollarClient.getEarnProviders(),
5923
+ getEarnOpportunities: (provider) => pollarClient.getEarnOpportunities(provider),
5924
+ getEarnPosition: (params) => pollarClient.getEarnPosition(params),
5925
+ earnDeposit: (params) => pollarClient.earnDeposit(params),
5926
+ earnWithdraw: (params) => pollarClient.earnWithdraw(params),
5927
+ openEarnModal: () => setEarnModalOpen(true),
4844
5928
  // sessions
4845
5929
  sessions,
4846
5930
  openSessionsModal: () => setSessionsModalOpen(true),
@@ -4896,6 +5980,7 @@ function PollarProvider({
4896
5980
  enabledAssetsModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setEnabledAssetsModalOpen(false), children: /* @__PURE__ */ jsx(EnabledAssetsModal, { onClose: () => setEnabledAssetsModalOpen(false) }) }),
4897
5981
  sendModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSendModalOpen(false), children: /* @__PURE__ */ jsx(SendModal, { onClose: () => setSendModalOpen(false) }) }),
4898
5982
  swapModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSwapModalOpen(false), children: /* @__PURE__ */ jsx(SwapModal, { onClose: () => setSwapModalOpen(false) }) }),
5983
+ earnModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setEarnModalOpen(false), children: /* @__PURE__ */ jsx(EarnModal, { onClose: () => setEarnModalOpen(false) }) }),
4899
5984
  receiveModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setReceiveModalOpen(false), children: /* @__PURE__ */ jsx(ReceiveModal, { onClose: () => setReceiveModalOpen(false) }) }),
4900
5985
  sessionsModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSessionsModalOpen(false), children: /* @__PURE__ */ jsx(SessionsModal, { onClose: () => setSessionsModalOpen(false) }) }),
4901
5986
  distributionRulesModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setDistributionRulesModalOpen(false), children: /* @__PURE__ */ jsx(DistributionRulesModal, { onClose: () => setDistributionRulesModalOpen(false) }) })
@@ -4929,7 +6014,7 @@ function createPollarAdapterHook(key) {
4929
6014
  };
4930
6015
  }
4931
6016
  function ButtonLogo() {
4932
- return /* @__PURE__ */ jsx("img", { src: LOGO_POLLAR, alt: "Pollar", width: 22, height: 22, className: "wallet-btn-logo" });
6017
+ return /* @__PURE__ */ jsx("img", { src: LOGO_POLLAR, alt: "Pollar", width: 22, height: 22, className: "pollar-wallet-btn-logo" });
4933
6018
  }
4934
6019
  function cropWallet(address) {
4935
6020
  if (address.length <= 12) return address;
@@ -4945,7 +6030,10 @@ function WalletButtonTemplate({
4945
6030
  itemColor,
4946
6031
  wrapperRef,
4947
6032
  isInProgress,
6033
+ showCreateAccount,
6034
+ creatingAccount,
4948
6035
  onToggleOpen,
6036
+ onCreateAccount,
4949
6037
  onCopy,
4950
6038
  onWalletBalance,
4951
6039
  onTxHistory,
@@ -4959,23 +6047,23 @@ function WalletButtonTemplate({
4959
6047
  onLogin
4960
6048
  }) {
4961
6049
  if (!walletAddress) {
4962
- return /* @__PURE__ */ jsxs("button", { type: "button", className: "wallet-login-btn", style: { backgroundColor: accentColor }, onClick: onLogin, children: [
6050
+ return /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-wallet-login-btn", style: { backgroundColor: accentColor }, onClick: onLogin, children: [
4963
6051
  /* @__PURE__ */ jsx(ButtonLogo, {}),
4964
6052
  "Login with Pollar"
4965
6053
  ] });
4966
6054
  }
4967
- return /* @__PURE__ */ jsxs("div", { className: "wallet-wrapper", ref: wrapperRef, children: [
6055
+ return /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-wrapper", ref: wrapperRef, children: [
4968
6056
  /* @__PURE__ */ jsxs(
4969
6057
  "button",
4970
6058
  {
4971
- className: "wallet-btn",
6059
+ className: "pollar-wallet-btn",
4972
6060
  style: { backgroundColor: accentColor },
4973
6061
  onClick: isInProgress ? void 0 : onToggleOpen,
4974
6062
  disabled: isInProgress,
4975
6063
  "aria-busy": isInProgress,
4976
6064
  children: [
4977
- /* @__PURE__ */ jsx("span", { className: "wallet-btn-label", children: cropWallet(walletAddress) }),
4978
- isInProgress ? /* @__PURE__ */ jsxs("svg", { className: "wallet-btn-spinner", viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", "aria-hidden": true, children: [
6065
+ /* @__PURE__ */ jsx("span", { className: "pollar-wallet-btn-label", children: cropWallet(walletAddress) }),
6066
+ isInProgress ? /* @__PURE__ */ jsxs("svg", { className: "pollar-wallet-btn-spinner", viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", "aria-hidden": true, children: [
4979
6067
  /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "4.5", stroke: "rgba(255,255,255,0.35)", strokeWidth: "1.5" }),
4980
6068
  /* @__PURE__ */ jsx(
4981
6069
  "circle",
@@ -4993,7 +6081,7 @@ function WalletButtonTemplate({
4993
6081
  ] }) : /* @__PURE__ */ jsx(
4994
6082
  "svg",
4995
6083
  {
4996
- className: `wallet-chevron${open ? " open" : ""}`,
6084
+ className: `pollar-wallet-chevron${open ? " pollar-open" : ""}`,
4997
6085
  viewBox: "0 0 12 12",
4998
6086
  fill: "none",
4999
6087
  stroke: "currentColor",
@@ -5006,8 +6094,42 @@ function WalletButtonTemplate({
5006
6094
  ]
5007
6095
  }
5008
6096
  ),
5009
- open && /* @__PURE__ */ jsxs("div", { className: "wallet-dropdown", style: { backgroundColor: dropdownBg, borderColor: dropdownBorder }, children: [
5010
- /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onSend, children: [
6097
+ open && /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-dropdown", style: { backgroundColor: dropdownBg, borderColor: dropdownBorder }, children: [
6098
+ showCreateAccount && /* @__PURE__ */ jsxs(Fragment, { children: [
6099
+ /* @__PURE__ */ jsxs(
6100
+ "button",
6101
+ {
6102
+ className: "pollar-wallet-dropdown-item",
6103
+ style: { color: itemColor },
6104
+ onClick: onCreateAccount,
6105
+ disabled: creatingAccount,
6106
+ children: [
6107
+ /* @__PURE__ */ jsxs(
6108
+ "svg",
6109
+ {
6110
+ width: "14",
6111
+ height: "14",
6112
+ viewBox: "0 0 24 24",
6113
+ fill: "none",
6114
+ stroke: "currentColor",
6115
+ strokeWidth: "2",
6116
+ strokeLinecap: "round",
6117
+ strokeLinejoin: "round",
6118
+ children: [
6119
+ /* @__PURE__ */ jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
6120
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "7", r: "4" }),
6121
+ /* @__PURE__ */ jsx("line", { x1: "19", y1: "8", x2: "19", y2: "14" }),
6122
+ /* @__PURE__ */ jsx("line", { x1: "22", y1: "11", x2: "16", y2: "11" })
6123
+ ]
6124
+ }
6125
+ ),
6126
+ creatingAccount ? "Creating account\u2026" : "Create account"
6127
+ ]
6128
+ }
6129
+ ),
6130
+ /* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" })
6131
+ ] }),
6132
+ /* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", style: { color: itemColor }, onClick: onSend, children: [
5011
6133
  /* @__PURE__ */ jsxs(
5012
6134
  "svg",
5013
6135
  {
@@ -5027,7 +6149,7 @@ function WalletButtonTemplate({
5027
6149
  ),
5028
6150
  "Send"
5029
6151
  ] }),
5030
- /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onReceive, children: [
6152
+ /* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", style: { color: itemColor }, onClick: onReceive, children: [
5031
6153
  /* @__PURE__ */ jsxs(
5032
6154
  "svg",
5033
6155
  {
@@ -5048,8 +6170,8 @@ function WalletButtonTemplate({
5048
6170
  ),
5049
6171
  "Receive"
5050
6172
  ] }),
5051
- /* @__PURE__ */ jsx("div", { className: "wallet-dropdown-divider" }),
5052
- /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onCopy, children: [
6173
+ /* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" }),
6174
+ /* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", style: { color: itemColor }, onClick: onCopy, children: [
5053
6175
  /* @__PURE__ */ jsxs(
5054
6176
  "svg",
5055
6177
  {
@@ -5069,7 +6191,7 @@ function WalletButtonTemplate({
5069
6191
  ),
5070
6192
  copied ? "Copied!" : "Copy address"
5071
6193
  ] }),
5072
- /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onWalletBalance, children: [
6194
+ /* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", style: { color: itemColor }, onClick: onWalletBalance, children: [
5073
6195
  /* @__PURE__ */ jsxs(
5074
6196
  "svg",
5075
6197
  {
@@ -5090,7 +6212,7 @@ function WalletButtonTemplate({
5090
6212
  ),
5091
6213
  "Wallet balance"
5092
6214
  ] }),
5093
- /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onTxHistory, children: [
6215
+ /* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", style: { color: itemColor }, onClick: onTxHistory, children: [
5094
6216
  /* @__PURE__ */ jsxs(
5095
6217
  "svg",
5096
6218
  {
@@ -5113,8 +6235,8 @@ function WalletButtonTemplate({
5113
6235
  ),
5114
6236
  "Transaction history"
5115
6237
  ] }),
5116
- /* @__PURE__ */ jsx("div", { className: "wallet-dropdown-divider" }),
5117
- /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onRamp, children: [
6238
+ /* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" }),
6239
+ /* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", style: { color: itemColor }, onClick: onRamp, children: [
5118
6240
  /* @__PURE__ */ jsxs(
5119
6241
  "svg",
5120
6242
  {
@@ -5136,7 +6258,7 @@ function WalletButtonTemplate({
5136
6258
  ),
5137
6259
  "Buy / Sell"
5138
6260
  ] }),
5139
- /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onKyc, children: [
6261
+ /* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", style: { color: itemColor }, onClick: onKyc, children: [
5140
6262
  /* @__PURE__ */ jsxs(
5141
6263
  "svg",
5142
6264
  {
@@ -5157,7 +6279,7 @@ function WalletButtonTemplate({
5157
6279
  ),
5158
6280
  "Identity verification"
5159
6281
  ] }),
5160
- /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onDistributionRules, children: [
6282
+ /* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", style: { color: itemColor }, onClick: onDistributionRules, children: [
5161
6283
  /* @__PURE__ */ jsxs(
5162
6284
  "svg",
5163
6285
  {
@@ -5180,7 +6302,7 @@ function WalletButtonTemplate({
5180
6302
  ),
5181
6303
  "Distribution rules"
5182
6304
  ] }),
5183
- /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onSessions, children: [
6305
+ /* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", style: { color: itemColor }, onClick: onSessions, children: [
5184
6306
  /* @__PURE__ */ jsxs(
5185
6307
  "svg",
5186
6308
  {
@@ -5201,8 +6323,8 @@ function WalletButtonTemplate({
5201
6323
  ),
5202
6324
  "Active sessions"
5203
6325
  ] }),
5204
- /* @__PURE__ */ jsx("div", { className: "wallet-dropdown-divider" }),
5205
- /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item danger", onClick: onLogout, children: [
6326
+ /* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" }),
6327
+ /* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item pollar-danger", onClick: onLogout, children: [
5206
6328
  /* @__PURE__ */ jsxs(
5207
6329
  "svg",
5208
6330
  {
@@ -5246,9 +6368,12 @@ function WalletButton() {
5246
6368
  const walletType = wallet?.custody === "external" ? wallet.provider : null;
5247
6369
  const [open, setOpen] = useState(false);
5248
6370
  const [copied, setCopied] = useState(false);
6371
+ const [creating, setCreating] = useState(false);
6372
+ const [created, setCreated] = useState(false);
5249
6373
  const wrapperRef = useRef(null);
5250
6374
  const copyTimerRef = useRef(null);
5251
6375
  const isInProgress = transaction.step === "building" || transaction.step === "signing";
6376
+ const canCreateAccount = !created && wallet?.custody === "external" && wallet.existsOnStellar === false && wallet.fundingMode === "IMMEDIATE";
5252
6377
  const { theme = "light", accentColor = "#005DB4" } = styles;
5253
6378
  const isDark = theme === "dark";
5254
6379
  const dropdownBg = isDark ? "#18181b" : "#fff";
@@ -5283,6 +6408,20 @@ function WalletButton() {
5283
6408
  setOpen(false);
5284
6409
  getClient().logout();
5285
6410
  }
6411
+ async function handleCreateAccount() {
6412
+ if (creating) return;
6413
+ setCreating(true);
6414
+ try {
6415
+ const res = await getClient().createAccount();
6416
+ if (res.status === "success" || res.status === "pending") {
6417
+ setCreated(true);
6418
+ setOpen(false);
6419
+ await getClient().refreshBalance();
6420
+ }
6421
+ } finally {
6422
+ setCreating(false);
6423
+ }
6424
+ }
5286
6425
  function handleWalletBalance() {
5287
6426
  setOpen(false);
5288
6427
  openWalletBalanceModal();
@@ -5328,7 +6467,10 @@ function WalletButton() {
5328
6467
  wrapperRef,
5329
6468
  isInProgress,
5330
6469
  walletType,
6470
+ showCreateAccount: canCreateAccount,
6471
+ creatingAccount: creating,
5331
6472
  onToggleOpen: () => setOpen((v) => !v),
6473
+ onCreateAccount: handleCreateAccount,
5332
6474
  onCopy: handleCopy,
5333
6475
  onWalletBalance: handleWalletBalance,
5334
6476
  onTxHistory: handleTxHistory,
@@ -5344,6 +6486,6 @@ function WalletButton() {
5344
6486
  );
5345
6487
  }
5346
6488
 
5347
- export { DistributionRulesModal, DistributionRulesModalTemplate, EnabledAssetsModal, EnabledAssetsModalTemplate, KycModal, KycModalTemplate, KycStatus, LoginModalTemplate, PollarProvider, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, RouteDisplay, SendModal, SendModalTemplate, SessionsModal, SessionsModalTemplate, SwapModal, SwapModalTemplate, TransactionModalTemplate, TxHistoryModalTemplate, TxStatusView, WalletBalanceModal, WalletBalanceModalTemplate, WalletButton, WalletButtonTemplate, createPollarAdapterHook, usePollar };
6489
+ export { DistributionRulesModal, DistributionRulesModalTemplate, EarnModal, EnabledAssetsModal, EnabledAssetsModalTemplate, KycModal, KycModalTemplate, KycStatus, LoginModalTemplate, PollarProvider, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, RouteDisplay, SendModal, SendModalTemplate, SessionsModal, SessionsModalTemplate, SwapModal, SwapModalTemplate, TransactionModalTemplate, TxHistoryModalTemplate, TxStatusView, WalletBalanceModal, WalletBalanceModalTemplate, WalletButton, WalletButtonTemplate, createPollarAdapterHook, usePollar };
5348
6490
  //# sourceMappingURL=index.mjs.map
5349
6491
  //# sourceMappingURL=index.mjs.map