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