@pollar/react 0.10.1-rc.4 → 0.10.1-rc.6

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,7 +1035,7 @@ var PollarModalFooter = () => {
1035
1035
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
1036
1036
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-footer-version", children: [
1037
1037
  "v",
1038
- "0.10.1-rc.4"
1038
+ "0.10.1-rc.6"
1039
1039
  ] })
1040
1040
  ] })
1041
1041
  ] });
@@ -1067,16 +1067,7 @@ function CopyButton({ value, label = "Copy", className }) {
1067
1067
  className: `pollar-copy-btn${className ? ` ${className}` : ""}`,
1068
1068
  onClick: handleCopy,
1069
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(
1071
- "path",
1072
- {
1073
- d: "M3.5 7l2.5 2.5 4.5-5",
1074
- stroke: "currentColor",
1075
- strokeWidth: "1.5",
1076
- strokeLinecap: "round",
1077
- strokeLinejoin: "round"
1078
- }
1079
- ) }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
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: [
1080
1071
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
1081
1072
  /* @__PURE__ */ jsxRuntime.jsx(
1082
1073
  "path",
@@ -2283,12 +2274,38 @@ function PrivyLoginSubmodal({
2283
2274
  fail(error);
2284
2275
  }
2285
2276
  }
2286
- 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" }) }) });
2277
+ const BackButton = ({ onClick }) => /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-back-btn", onClick, "aria-label": "Back", children: /* @__PURE__ */ jsxRuntime.jsx(
2278
+ "svg",
2279
+ {
2280
+ width: "20",
2281
+ height: "20",
2282
+ viewBox: "0 0 24 24",
2283
+ fill: "none",
2284
+ stroke: "currentColor",
2285
+ strokeWidth: "2.5",
2286
+ strokeLinecap: "round",
2287
+ strokeLinejoin: "round",
2288
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 19l-7-7 7-7" })
2289
+ }
2290
+ ) });
2287
2291
  const showEmail = options.includes("email");
2288
2292
  const showGoogle = options.includes("google");
2289
2293
  const showGithub = options.includes("github");
2290
2294
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
2291
- /* @__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" }) }) }),
2295
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-close-btn", onClick: onCancel, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx(
2296
+ "svg",
2297
+ {
2298
+ width: "18",
2299
+ height: "18",
2300
+ viewBox: "0 0 24 24",
2301
+ fill: "none",
2302
+ stroke: "currentColor",
2303
+ strokeWidth: "2.5",
2304
+ strokeLinecap: "round",
2305
+ strokeLinejoin: "round",
2306
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12" })
2307
+ }
2308
+ ) }),
2292
2309
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-header", children: [
2293
2310
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoUrl ?? LOGO_POLLAR, alt: "Logo", className: "pollar-logo" }) }),
2294
2311
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-title", children: appName }),
@@ -2539,13 +2556,23 @@ var INSTRUCTION_LABELS = {
2539
2556
  function flattenInstructions(instr) {
2540
2557
  const out = [];
2541
2558
  for (const [k, v] of Object.entries(instr)) {
2559
+ if (k === "qrBase64") {
2560
+ if (typeof v === "string" && v) out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? "Payment QR", value: v, kind: "qr" });
2561
+ continue;
2562
+ }
2563
+ if ((k === "expiresAt" || k === "expires_at") && (typeof v === "number" || typeof v === "string")) {
2564
+ const ms = Number(v);
2565
+ if (Number.isFinite(ms) && ms > 0) {
2566
+ out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? "Expires", value: new Date(ms).toLocaleString(), kind: "datetime" });
2567
+ }
2568
+ continue;
2569
+ }
2542
2570
  let value = "";
2543
2571
  if (typeof v === "string" || typeof v === "number") value = String(v);
2544
- else if (Array.isArray(v))
2545
- value = v.filter((x) => typeof x === "string" || typeof x === "number").join(", ");
2572
+ else if (Array.isArray(v)) value = v.filter((x) => typeof x === "string" || typeof x === "number").join(", ");
2546
2573
  else continue;
2547
2574
  if (!value) continue;
2548
- out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? k, value });
2575
+ out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? k, value, kind: "text" });
2549
2576
  }
2550
2577
  return out;
2551
2578
  }
@@ -2567,6 +2594,7 @@ function RampWidgetTemplate({
2567
2594
  provider,
2568
2595
  txStatus,
2569
2596
  kycUrl,
2597
+ tosUrl,
2570
2598
  stellarTxHash,
2571
2599
  depositInstructions,
2572
2600
  canComplete,
@@ -2580,6 +2608,7 @@ function RampWidgetTemplate({
2580
2608
  onSelectQuote,
2581
2609
  onContactContinue,
2582
2610
  onOpenKyc,
2611
+ onOpenTos,
2583
2612
  onCompleteWithdraw,
2584
2613
  onRetry,
2585
2614
  onRefresh,
@@ -2769,11 +2798,22 @@ function RampWidgetTemplate({
2769
2798
  stellarTxHash.slice(-8)
2770
2799
  ] }) })
2771
2800
  ] }),
2772
- depositInstructions && txStatus !== "completed" && flattenInstructions(depositInstructions).map(({ key, label, value }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
2801
+ depositInstructions && txStatus !== "completed" && flattenInstructions(depositInstructions).map(({ key, label, value, kind }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
2773
2802
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: label }),
2774
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsxRuntime.jsx("code", { style: { wordBreak: "break-all" }, children: value }) })
2803
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-payment-value", children: kind === "qr" ? /* @__PURE__ */ jsxRuntime.jsx(
2804
+ "img",
2805
+ {
2806
+ src: value.startsWith("data:") ? value : `data:image/png;base64,${value}`,
2807
+ alt: label,
2808
+ style: { width: "100%", maxWidth: 220, height: "auto", display: "block", margin: "0 auto" }
2809
+ }
2810
+ ) : kind === "datetime" ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: value }) : /* @__PURE__ */ jsxRuntime.jsx("code", { style: { wordBreak: "break-all" }, children: value }) })
2775
2811
  ] }, key)),
2776
- kycUrl && txStatus !== "completed" && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenKyc, children: [
2812
+ tosUrl && !depositInstructions && txStatus !== "completed" && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenTos, children: [
2813
+ "Accept terms at ",
2814
+ provider
2815
+ ] }),
2816
+ kycUrl && !depositInstructions && txStatus !== "completed" && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenKyc, children: [
2777
2817
  "Continue at ",
2778
2818
  provider
2779
2819
  ] }),
@@ -2815,6 +2855,7 @@ function RampWidget({ onClose }) {
2815
2855
  const [txId, setTxId] = react.useState(null);
2816
2856
  const [provider, setProvider] = react.useState("");
2817
2857
  const [kycUrl, setKycUrl] = react.useState(null);
2858
+ const [tosUrl, setTosUrl] = react.useState(null);
2818
2859
  const [txStatus, setTxStatus] = react.useState(null);
2819
2860
  const [stellarTxHash, setStellarTxHash] = react.useState(null);
2820
2861
  const [depositInstructions, setDepositInstructions] = react.useState(null);
@@ -2833,8 +2874,7 @@ function RampWidget({ onClose }) {
2833
2874
  setTxStatus(tx.status);
2834
2875
  if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
2835
2876
  if (tx.kycUrl) setKycUrl(tx.kycUrl);
2836
- const di = tx.depositInstructions;
2837
- if (di) setDepositInstructions(di);
2877
+ if (tx.depositInstructions) setDepositInstructions(tx.depositInstructions);
2838
2878
  if (TERMINAL.includes(tx.status)) clearInterval(id);
2839
2879
  } catch {
2840
2880
  }
@@ -2882,8 +2922,7 @@ function RampWidget({ onClose }) {
2882
2922
  setTxStatus(tx.status);
2883
2923
  if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
2884
2924
  if (tx.kycUrl) setKycUrl(tx.kycUrl);
2885
- const di = tx.depositInstructions;
2886
- if (di) setDepositInstructions(di);
2925
+ if (tx.depositInstructions) setDepositInstructions(tx.depositInstructions);
2887
2926
  }
2888
2927
  } catch {
2889
2928
  } finally {
@@ -2897,6 +2936,7 @@ function RampWidget({ onClose }) {
2897
2936
  setTxId(null);
2898
2937
  setProvider("");
2899
2938
  setKycUrl(null);
2939
+ setTosUrl(null);
2900
2940
  setTxStatus(null);
2901
2941
  setStellarTxHash(null);
2902
2942
  setDepositInstructions(null);
@@ -2923,6 +2963,7 @@ function RampWidget({ onClose }) {
2923
2963
  return;
2924
2964
  }
2925
2965
  setKycUrl(result.kycUrl ?? null);
2966
+ setTosUrl(result.tosUrl ?? null);
2926
2967
  setTxStatus(result.status);
2927
2968
  setStellarTxHash(result.stellarTxHash ?? null);
2928
2969
  setDepositInstructions(result.depositInstructions ?? null);
@@ -2987,6 +3028,9 @@ function RampWidget({ onClose }) {
2987
3028
  function handleOpenKyc() {
2988
3029
  if (kycUrl) window.open(kycUrl, "_blank", "noopener,noreferrer");
2989
3030
  }
3031
+ function handleOpenTos() {
3032
+ if (tosUrl) window.open(tosUrl, "_blank", "noopener,noreferrer");
3033
+ }
2990
3034
  async function handleCompleteWithdraw() {
2991
3035
  if (!txId) return;
2992
3036
  setCompleting(true);
@@ -3029,6 +3073,7 @@ function RampWidget({ onClose }) {
3029
3073
  provider,
3030
3074
  txStatus,
3031
3075
  kycUrl,
3076
+ tosUrl,
3032
3077
  stellarTxHash,
3033
3078
  depositInstructions,
3034
3079
  canComplete,
@@ -3042,6 +3087,7 @@ function RampWidget({ onClose }) {
3042
3087
  onSelectQuote: handleSelectQuote,
3043
3088
  onContactContinue: handleContactContinue,
3044
3089
  onOpenKyc: handleOpenKyc,
3090
+ onOpenTos: handleOpenTos,
3045
3091
  onCompleteWithdraw: handleCompleteWithdraw,
3046
3092
  onRetry: resetToInput,
3047
3093
  onRefresh: handleRefresh,
@@ -3207,6 +3253,43 @@ function ReceiveModal({ onClose }) {
3207
3253
  }
3208
3254
  ) });
3209
3255
  }
3256
+ function formatAmount2(value) {
3257
+ const n = parseFloat(value);
3258
+ return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
3259
+ }
3260
+ var optionLabel = (o) => o.available !== void 0 ? `${o.code} \u2014 ${formatAmount2(o.available)} available` : o.code;
3261
+ function AssetSelect({
3262
+ label,
3263
+ value,
3264
+ options,
3265
+ onChange,
3266
+ loading = false,
3267
+ disabled = false,
3268
+ appGroupLabel = "App assets",
3269
+ otherGroupLabel = "Other assets",
3270
+ children
3271
+ }) {
3272
+ const appAssets = options.filter((o) => o.enabledInApp);
3273
+ const otherAssets = options.filter((o) => !o.enabledInApp);
3274
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
3275
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: label }),
3276
+ loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxRuntime.jsxs(
3277
+ "select",
3278
+ {
3279
+ className: "pollar-input pollar-send-select",
3280
+ value,
3281
+ disabled,
3282
+ onChange: (e) => onChange(e.target.value),
3283
+ children: [
3284
+ value === "" && /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, hidden: true }),
3285
+ 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)) }),
3286
+ 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)) })
3287
+ ]
3288
+ }
3289
+ ),
3290
+ !loading && children
3291
+ ] });
3292
+ }
3210
3293
  var STATUS_MESSAGES = {
3211
3294
  idle: "",
3212
3295
  building: "Building transaction\u2026",
@@ -3459,8 +3542,6 @@ function SendModalTemplate({
3459
3542
  "--pollar-input-border-radius": "0.5rem",
3460
3543
  "--pollar-card-border-radius": "10px"
3461
3544
  };
3462
- const enabledAssets = assets.filter((a) => a.enabledInApp);
3463
- const otherAssets = assets.filter((a) => !a.enabledInApp);
3464
3545
  const selectedKey = selectedAsset ? assetKey3(selectedAsset) : "";
3465
3546
  const canSubmit = !!selectedAsset && !!amount && !!destination.trim() && !isLoadingBalance;
3466
3547
  const title = step === "form" ? "Send" : txTitle;
@@ -3480,36 +3561,24 @@ function SendModalTemplate({
3480
3561
  !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" }) }) }) })
3481
3562
  ] }),
3482
3563
  step === "form" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3483
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
3484
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Asset" }),
3485
- isLoadingBalance ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxRuntime.jsxs(
3486
- "select",
3487
- {
3488
- className: "pollar-input pollar-send-select",
3489
- value: selectedKey,
3490
- onChange: (e) => {
3491
- const all = [...enabledAssets, ...otherAssets];
3492
- const found = all.find((a) => assetKey3(a) === e.target.value);
3493
- if (found) onSelectAsset(found);
3494
- },
3495
- children: [
3496
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Select asset" }),
3497
- enabledAssets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("optgroup", { label: "App assets", children: enabledAssets.map((a) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: assetKey3(a), children: [
3498
- a.code,
3499
- " \u2014 ",
3500
- formatBalance(a.available),
3501
- " available"
3502
- ] }, assetKey3(a))) }),
3503
- otherAssets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("optgroup", { label: "Other assets", children: otherAssets.map((a) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: assetKey3(a), children: [
3504
- a.code,
3505
- " \u2014 ",
3506
- formatBalance(a.available),
3507
- " available"
3508
- ] }, assetKey3(a))) })
3509
- ]
3564
+ /* @__PURE__ */ jsxRuntime.jsx(
3565
+ AssetSelect,
3566
+ {
3567
+ label: "Asset",
3568
+ value: selectedKey,
3569
+ loading: isLoadingBalance,
3570
+ options: assets.map((a) => ({
3571
+ key: assetKey3(a),
3572
+ code: a.code,
3573
+ available: a.available,
3574
+ enabledInApp: a.enabledInApp
3575
+ })),
3576
+ onChange: (key) => {
3577
+ const found = assets.find((a) => assetKey3(a) === key);
3578
+ if (found) onSelectAsset(found);
3510
3579
  }
3511
- )
3512
- ] }),
3580
+ }
3581
+ ),
3513
3582
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
3514
3583
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-label-row", children: [
3515
3584
  /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Amount" }),
@@ -3609,13 +3678,16 @@ function SendModal({ onClose }) {
3609
3678
  const allAssets = balanceData?.balances ?? [];
3610
3679
  const sortedAssets = [
3611
3680
  ...allAssets.filter((b) => b.enabledInApp),
3612
- ...allAssets.filter((b) => !b.enabledInApp && parseFloat(b.balance) > 0)
3681
+ ...allAssets.filter((b) => !b.enabledInApp && (b.type === "native" || parseFloat(b.balance) > 0))
3613
3682
  ];
3683
+ react.useEffect(() => {
3684
+ if (!selectedAsset && sortedAssets.length > 0) setSelectedAsset(sortedAssets[0]);
3685
+ }, [sortedAssets, selectedAsset]);
3614
3686
  const hash = transaction.step === "success" ? transaction.hash : null;
3615
3687
  const buildData = "buildData" in transaction ? transaction.buildData : null;
3616
3688
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
3617
3689
  const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
3618
- const IN_FLIGHT_STEPS2 = [
3690
+ const IN_FLIGHT_STEPS3 = [
3619
3691
  "building",
3620
3692
  "signing",
3621
3693
  "submitting",
@@ -3623,7 +3695,7 @@ function SendModal({ onClose }) {
3623
3695
  "signing-submitting",
3624
3696
  "building-signing-submitting"
3625
3697
  ];
3626
- const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
3698
+ const isInProgress = IN_FLIGHT_STEPS3.includes(transaction.step);
3627
3699
  const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
3628
3700
  const txTitle = isInProgress ? "Sending\u2026" : transaction.step === "success" ? "Sent!" : transaction.step === "error" ? "Send failed" : "Confirm Send";
3629
3701
  async function handleSubmit() {
@@ -3717,7 +3789,7 @@ var PROVIDER_LABELS = {
3717
3789
  soroswap: "Soroswap",
3718
3790
  sdex: "Stellar DEX"
3719
3791
  };
3720
- function formatAmount2(value) {
3792
+ function formatAmount3(value) {
3721
3793
  const n = parseFloat(value);
3722
3794
  return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
3723
3795
  }
@@ -3800,214 +3872,229 @@ function SwapModalTemplate({
3800
3872
  const buyKey = selectedBuy ? assetOptionKey(selectedBuy) : "";
3801
3873
  const canSwap = !smartUnsupported && !!selectedSell && !!selectedBuy && !!amount && !!quote && !quoteLoading && !isLoadingData;
3802
3874
  const title = step === "form" ? "Swap" : txTitle;
3803
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-send-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
3804
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
3805
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-header-left", children: [
3806
- 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" }) }) }),
3807
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: title })
3808
- ] }),
3809
- !isInProgress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
3810
- step === "form" && /* @__PURE__ */ jsxRuntime.jsx(
3811
- "button",
3812
- {
3813
- type: "button",
3814
- className: "pollar-modal-close",
3815
- onClick: onRefresh,
3816
- disabled: configLoading || isLoadingData,
3817
- "aria-label": "Refresh",
3818
- title: "Refresh balances and options",
3819
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
3820
- "path",
3875
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3876
+ "div",
3877
+ {
3878
+ className: "pollar-modal-card pollar-send-modal",
3879
+ "data-theme": theme,
3880
+ style: cssVars,
3881
+ onClick: (e) => e.stopPropagation(),
3882
+ children: [
3883
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
3884
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-header-left", children: [
3885
+ 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" }) }) }),
3886
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: title })
3887
+ ] }),
3888
+ !isInProgress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
3889
+ step === "form" && /* @__PURE__ */ jsxRuntime.jsx(
3890
+ "button",
3821
3891
  {
3822
- d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2.5v3h-3",
3823
- stroke: "currentColor",
3824
- strokeWidth: "1.6",
3825
- strokeLinecap: "round",
3826
- strokeLinejoin: "round"
3892
+ type: "button",
3893
+ className: "pollar-modal-close",
3894
+ onClick: onRefresh,
3895
+ disabled: configLoading || isLoadingData,
3896
+ "aria-label": "Refresh",
3897
+ title: "Refresh balances and options",
3898
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
3899
+ "path",
3900
+ {
3901
+ d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2.5v3h-3",
3902
+ stroke: "currentColor",
3903
+ strokeWidth: "1.6",
3904
+ strokeLinecap: "round",
3905
+ strokeLinejoin: "round"
3906
+ }
3907
+ ) })
3827
3908
  }
3828
- ) })
3829
- }
3830
- ),
3831
- /* @__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" }) }) })
3832
- ] })
3833
- ] }),
3834
- step === "form" && configLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "Loading swap options\u2026" }),
3835
- step === "form" && !configLoading && swapUnavailable && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Swap is not available for this app." }),
3836
- step === "form" && !configLoading && !swapUnavailable && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3837
- smartUnsupported && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Swaps are not yet available for smart (passkey) wallets." }),
3838
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
3839
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "You pay" }),
3840
- isLoadingData ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxRuntime.jsxs(
3841
- "select",
3842
- {
3843
- className: "pollar-input pollar-send-select",
3844
- value: sellKey,
3845
- onChange: (e) => {
3846
- const found = sellOptions.find((o) => assetOptionKey(o) === e.target.value);
3847
- if (found) onSelectSell(found);
3848
- },
3849
- children: [
3850
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Select asset to sell" }),
3851
- sellOptions.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: assetOptionKey(o), children: [
3852
- o.code,
3853
- o.available !== void 0 ? ` \u2014 ${formatAmount2(o.available)} available` : ""
3854
- ] }, assetOptionKey(o)))
3855
- ]
3856
- }
3857
- )
3858
- ] }),
3859
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
3860
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-label-row", children: [
3861
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Amount" }),
3862
- selectedSell?.available !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-send-hint", children: [
3863
- "Available: ",
3864
- formatAmount2(selectedSell.available),
3865
- " ",
3866
- selectedSell.code
3909
+ ),
3910
+ /* @__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" }) }) })
3867
3911
  ] })
3868
3912
  ] }),
3869
- /* @__PURE__ */ jsxRuntime.jsx(
3870
- "input",
3871
- {
3872
- className: "pollar-input",
3873
- type: "text",
3874
- inputMode: "decimal",
3875
- placeholder: "0.00",
3876
- value: amount,
3877
- onChange: (e) => onAmountChange(e.target.value)
3878
- }
3879
- )
3880
- ] }),
3881
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
3882
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "You receive" }),
3883
- isLoadingData ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxRuntime.jsxs(
3884
- "select",
3885
- {
3886
- className: "pollar-input pollar-send-select",
3887
- value: buyKey,
3888
- onChange: (e) => {
3889
- const found = buyOptions.find((o) => assetOptionKey(o) === e.target.value);
3890
- if (found) onSelectBuy(found);
3891
- },
3892
- children: [
3893
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Select asset to buy" }),
3894
- buyOptions.map((o) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: assetOptionKey(o), children: [
3895
- o.code,
3896
- o.enabledInApp ? "" : " (external)"
3897
- ] }, assetOptionKey(o)))
3898
- ]
3899
- }
3900
- ),
3901
- !isLoadingData && (customOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-custom", children: [
3913
+ step === "form" && configLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "Loading swap options\u2026" }),
3914
+ step === "form" && !configLoading && swapUnavailable && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Swap is not available for this app." }),
3915
+ step === "form" && !swapUnavailable && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3916
+ smartUnsupported && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Swaps are not yet available for smart (passkey) wallets." }),
3902
3917
  /* @__PURE__ */ jsxRuntime.jsx(
3903
- "input",
3918
+ AssetSelect,
3904
3919
  {
3905
- className: "pollar-input",
3906
- type: "text",
3907
- placeholder: "Code (e.g. USDC)",
3908
- value: customCode,
3909
- onChange: (e) => setCustomCode(e.target.value)
3920
+ label: "You pay",
3921
+ value: sellKey,
3922
+ loading: isLoadingData,
3923
+ disabled: configLoading,
3924
+ options: sellOptions.map((o) => ({
3925
+ key: assetOptionKey(o),
3926
+ code: o.code,
3927
+ available: o.available,
3928
+ enabledInApp: o.enabledInApp
3929
+ })),
3930
+ onChange: (key) => {
3931
+ const found = sellOptions.find((o) => assetOptionKey(o) === key);
3932
+ if (found) onSelectSell(found);
3933
+ }
3910
3934
  }
3911
3935
  ),
3936
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
3937
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-label-row", children: [
3938
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Amount" }),
3939
+ selectedSell?.available !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-send-hint", children: [
3940
+ "Available: ",
3941
+ formatAmount3(selectedSell.available),
3942
+ " ",
3943
+ selectedSell.code
3944
+ ] })
3945
+ ] }),
3946
+ /* @__PURE__ */ jsxRuntime.jsx(
3947
+ "input",
3948
+ {
3949
+ className: "pollar-input",
3950
+ type: "text",
3951
+ inputMode: "decimal",
3952
+ placeholder: "0.00",
3953
+ value: amount,
3954
+ disabled: configLoading,
3955
+ onChange: (e) => onAmountChange(e.target.value)
3956
+ }
3957
+ )
3958
+ ] }),
3912
3959
  /* @__PURE__ */ jsxRuntime.jsx(
3913
- "input",
3960
+ AssetSelect,
3914
3961
  {
3915
- className: "pollar-input",
3916
- type: "text",
3917
- placeholder: "Issuer (G...)",
3918
- value: customIssuer,
3919
- onChange: (e) => setCustomIssuer(e.target.value)
3962
+ label: "You receive",
3963
+ value: buyKey,
3964
+ loading: isLoadingData,
3965
+ disabled: configLoading,
3966
+ options: buyOptions.map((o) => ({
3967
+ key: assetOptionKey(o),
3968
+ code: o.code,
3969
+ enabledInApp: o.enabledInApp
3970
+ })),
3971
+ onChange: (key) => {
3972
+ const found = buyOptions.find((o) => assetOptionKey(o) === key);
3973
+ if (found) onSelectBuy(found);
3974
+ },
3975
+ children: customOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-custom", children: [
3976
+ /* @__PURE__ */ jsxRuntime.jsx(
3977
+ "input",
3978
+ {
3979
+ className: "pollar-input",
3980
+ type: "text",
3981
+ placeholder: "Code (e.g. USDC)",
3982
+ value: customCode,
3983
+ onChange: (e) => setCustomCode(e.target.value)
3984
+ }
3985
+ ),
3986
+ /* @__PURE__ */ jsxRuntime.jsx(
3987
+ "input",
3988
+ {
3989
+ className: "pollar-input",
3990
+ type: "text",
3991
+ placeholder: "Issuer (G...)",
3992
+ value: customIssuer,
3993
+ onChange: (e) => setCustomIssuer(e.target.value)
3994
+ }
3995
+ ),
3996
+ customError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: customError }),
3997
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-custom-actions", children: [
3998
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: submitCustomToken, children: "Add token" }),
3999
+ /* @__PURE__ */ jsxRuntime.jsx(
4000
+ "button",
4001
+ {
4002
+ type: "button",
4003
+ className: "pollar-swap-custom-cancel",
4004
+ onClick: () => {
4005
+ setCustomOpen(false);
4006
+ setCustomError("");
4007
+ },
4008
+ children: "Cancel"
4009
+ }
4010
+ )
4011
+ ] })
4012
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
4013
+ "button",
4014
+ {
4015
+ type: "button",
4016
+ className: "pollar-swap-custom-toggle",
4017
+ disabled: configLoading,
4018
+ onClick: () => setCustomOpen(true),
4019
+ children: "+ Add a token by code / issuer"
4020
+ }
4021
+ )
3920
4022
  }
3921
4023
  ),
3922
- customError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: customError }),
3923
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-custom-actions", children: [
3924
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: submitCustomToken, children: "Add token" }),
4024
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
4025
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Route" }),
3925
4026
  /* @__PURE__ */ jsxRuntime.jsx(
3926
- "button",
4027
+ "select",
3927
4028
  {
3928
- type: "button",
3929
- className: "pollar-swap-custom-cancel",
3930
- onClick: () => {
3931
- setCustomOpen(false);
3932
- setCustomError("");
3933
- },
3934
- children: "Cancel"
4029
+ className: "pollar-input pollar-send-select",
4030
+ value: provider,
4031
+ disabled: configLoading || providers.length === 0,
4032
+ onChange: (e) => onProviderChange(e.target.value),
4033
+ 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))
3935
4034
  }
3936
4035
  )
3937
- ] })
3938
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-swap-custom-toggle", onClick: () => setCustomOpen(true), children: "+ Add a token by code / issuer" }))
3939
- ] }),
3940
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
3941
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Route" }),
3942
- /* @__PURE__ */ jsxRuntime.jsx(
3943
- "select",
4036
+ ] }),
4037
+ quoteLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "Fetching best price\u2026" }),
4038
+ !quoteLoading && quoteError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: quoteError }),
4039
+ !quoteLoading && !quoteError && quote && selectedBuy && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote", children: [
4040
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
4041
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "You receive" }),
4042
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
4043
+ "~ ",
4044
+ formatAmount3(quote.amountOut),
4045
+ " ",
4046
+ selectedBuy.code
4047
+ ] })
4048
+ ] }),
4049
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
4050
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Minimum received" }),
4051
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
4052
+ formatAmount3(quote.minReceived),
4053
+ " ",
4054
+ selectedBuy.code
4055
+ ] })
4056
+ ] }),
4057
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
4058
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Price impact" }),
4059
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
4060
+ quote.priceImpactPct,
4061
+ "%"
4062
+ ] })
4063
+ ] }),
4064
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
4065
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Route" }),
4066
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: PROVIDER_LABELS[quote.provider] })
4067
+ ] })
4068
+ ] }),
4069
+ !quoteLoading && !quoteError && !quote && selectedSell && selectedBuy && !!amount && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "No route found for this pair." }),
4070
+ buyNeedsTrustline && selectedBuy && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-trustline-notice", children: [
4071
+ "To receive ",
4072
+ selectedBuy.code,
4073
+ " your wallet needs a trustline. Swapping will create it first (~0.5 XLM reserve, refundable if you later remove it)."
4074
+ ] }),
4075
+ formError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: formError }),
4076
+ /* @__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" }) })
4077
+ ] }),
4078
+ step === "tx" && /* @__PURE__ */ jsxRuntime.jsx(
4079
+ TxStatusView,
3944
4080
  {
3945
- className: "pollar-input pollar-send-select",
3946
- value: provider,
3947
- onChange: (e) => onProviderChange(e.target.value),
3948
- children: providers.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p, children: PROVIDER_LABELS[p] }, p))
4081
+ transaction,
4082
+ showXdr,
4083
+ copied,
4084
+ explorerUrl,
4085
+ walletType,
4086
+ onSignAndSend: () => {
4087
+ },
4088
+ onToggleXdr,
4089
+ onCopyHash,
4090
+ onRetry,
4091
+ onDone
3949
4092
  }
3950
- )
3951
- ] }),
3952
- quoteLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "Fetching best price\u2026" }),
3953
- !quoteLoading && quoteError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: quoteError }),
3954
- !quoteLoading && !quoteError && quote && selectedBuy && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote", children: [
3955
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
3956
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "You receive" }),
3957
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
3958
- "~ ",
3959
- formatAmount2(quote.amountOut),
3960
- " ",
3961
- selectedBuy.code
3962
- ] })
3963
- ] }),
3964
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
3965
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Minimum received" }),
3966
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
3967
- formatAmount2(quote.minReceived),
3968
- " ",
3969
- selectedBuy.code
3970
- ] })
3971
- ] }),
3972
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
3973
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Price impact" }),
3974
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
3975
- quote.priceImpactPct,
3976
- "%"
3977
- ] })
3978
- ] }),
3979
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
3980
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Route" }),
3981
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: PROVIDER_LABELS[quote.provider] })
3982
- ] })
3983
- ] }),
3984
- !quoteLoading && !quoteError && !quote && selectedSell && selectedBuy && !!amount && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "No route found for this pair." }),
3985
- buyNeedsTrustline && selectedBuy && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-trustline-notice", children: [
3986
- "To receive ",
3987
- selectedBuy.code,
3988
- " your wallet needs a trustline. Swapping will create it first (~0.5 XLM reserve, refundable if you later remove it)."
3989
- ] }),
3990
- formError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: formError }),
3991
- /* @__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" }) })
3992
- ] }),
3993
- step === "tx" && /* @__PURE__ */ jsxRuntime.jsx(
3994
- TxStatusView,
3995
- {
3996
- transaction,
3997
- showXdr,
3998
- copied,
3999
- explorerUrl,
4000
- walletType,
4001
- onSignAndSend: () => {
4002
- },
4003
- onToggleXdr,
4004
- onCopyHash,
4005
- onRetry,
4006
- onDone
4007
- }
4008
- ),
4009
- /* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
4010
- ] });
4093
+ ),
4094
+ /* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
4095
+ ]
4096
+ }
4097
+ );
4011
4098
  }
4012
4099
  var QUOTE_DEBOUNCE_MS = 400;
4013
4100
  function toRef(a) {
@@ -4085,7 +4172,7 @@ function SwapModal({ onClose }) {
4085
4172
  const balances = walletBalance.step === "loaded" ? walletBalance.data.balances : [];
4086
4173
  const assetRecords = enabledAssets.step === "loaded" ? enabledAssets.data.assets : [];
4087
4174
  const isLoadingData = walletBalance.step === "loading" || enabledAssets.step === "loading";
4088
- 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 }));
4175
+ 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 }));
4089
4176
  const buyKeyOfSell = selectedSell ? `${selectedSell.code}:${selectedSell.issuer ?? "native"}` : "";
4090
4177
  const optKey = (o) => `${o.code}:${o.issuer ?? "native"}`;
4091
4178
  const enabledBuy = assetRecords.map((a) => ({
@@ -4103,9 +4190,19 @@ function SwapModal({ onClose }) {
4103
4190
  })).filter((o) => !enabledKeys.has(optKey(o)));
4104
4191
  const knownKeys = /* @__PURE__ */ new Set([...enabledKeys, ...catalogBuy.map(optKey)]);
4105
4192
  const customBuy = customTokens.filter((o) => !knownKeys.has(optKey(o)));
4106
- const buyOptions = [...enabledBuy, ...catalogBuy, ...customBuy].filter(
4107
- (o) => optKey(o) !== buyKeyOfSell
4108
- );
4193
+ const buyOptions = [...enabledBuy, ...catalogBuy, ...customBuy].filter((o) => optKey(o) !== buyKeyOfSell);
4194
+ react.useEffect(() => {
4195
+ if (sellOptions.length === 0) return;
4196
+ if (!selectedSell || !sellOptions.some((o) => optKey(o) === optKey(selectedSell))) {
4197
+ setSelectedSell(sellOptions[0]);
4198
+ }
4199
+ }, [sellOptions, selectedSell]);
4200
+ react.useEffect(() => {
4201
+ if (buyOptions.length === 0) return;
4202
+ if (!selectedBuy || !buyOptions.some((o) => optKey(o) === optKey(selectedBuy))) {
4203
+ setSelectedBuy(buyOptions[0]);
4204
+ }
4205
+ }, [buyOptions, selectedBuy]);
4109
4206
  function addCustomToken(code, issuer) {
4110
4207
  const c = code.trim().toUpperCase();
4111
4208
  const i = issuer.trim();
@@ -4164,7 +4261,7 @@ function SwapModal({ onClose }) {
4164
4261
  const buildData = "buildData" in transaction ? transaction.buildData : null;
4165
4262
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
4166
4263
  const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
4167
- const IN_FLIGHT_STEPS2 = [
4264
+ const IN_FLIGHT_STEPS3 = [
4168
4265
  "building",
4169
4266
  "signing",
4170
4267
  "submitting",
@@ -4172,7 +4269,7 @@ function SwapModal({ onClose }) {
4172
4269
  "signing-submitting",
4173
4270
  "building-signing-submitting"
4174
4271
  ];
4175
- const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
4272
+ const isInProgress = IN_FLIGHT_STEPS3.includes(transaction.step);
4176
4273
  const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
4177
4274
  const txTitle = isInProgress ? "Swapping\u2026" : transaction.step === "success" ? "Swapped!" : transaction.step === "error" ? "Swap failed" : "Confirm Swap";
4178
4275
  async function handleSwap() {
@@ -4266,6 +4363,314 @@ function SwapModal({ onClose }) {
4266
4363
  }
4267
4364
  ) });
4268
4365
  }
4366
+ var POSITION_POLL_MS = 1e4;
4367
+ var PROVIDER_LABELS2 = {
4368
+ blend: "Blend",
4369
+ defindex: "DeFindex"
4370
+ };
4371
+ var IN_FLIGHT_STEPS2 = ["building", "signing", "submitting", "submitted", "signing-submitting", "building-signing-submitting"];
4372
+ function formatAmount4(value) {
4373
+ const n = parseFloat(value);
4374
+ return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
4375
+ }
4376
+ function EarnModal({ onClose }) {
4377
+ const {
4378
+ getEarnProviders,
4379
+ getEarnOpportunities,
4380
+ getEarnPosition,
4381
+ earnDeposit,
4382
+ earnWithdraw,
4383
+ tx: transaction,
4384
+ wallet,
4385
+ network,
4386
+ styles
4387
+ } = usePollar();
4388
+ const walletType = wallet?.custody === "external" ? wallet.provider : null;
4389
+ const smartUnsupported = wallet?.custody === "smart";
4390
+ const { theme = "light", accentColor = "#005DB4" } = styles;
4391
+ const isDark = theme === "dark";
4392
+ const [step, setStep] = react.useState("form");
4393
+ const [tab, setTab] = react.useState("deposit");
4394
+ const [providers, setProviders] = react.useState(null);
4395
+ const [provider, setProvider] = react.useState(null);
4396
+ const [opportunities, setOpportunities] = react.useState([]);
4397
+ const [opportunityId, setOpportunityId] = react.useState("");
4398
+ const [position, setPosition] = react.useState(null);
4399
+ const [amount, setAmount] = react.useState("");
4400
+ const [loadingOpps, setLoadingOpps] = react.useState(false);
4401
+ const [formError, setFormError] = react.useState("");
4402
+ const [showXdr, setShowXdr] = react.useState(false);
4403
+ const [copied, setCopied] = react.useState(false);
4404
+ const copyTimerRef = react.useRef(null);
4405
+ const loadProviders = react.useCallback(() => {
4406
+ setProviders(null);
4407
+ return getEarnProviders().then((ps) => {
4408
+ setProviders(ps);
4409
+ setProvider((cur) => cur ?? ps[0] ?? null);
4410
+ }).catch(() => setProviders([]));
4411
+ }, [getEarnProviders]);
4412
+ react.useEffect(() => {
4413
+ void loadProviders();
4414
+ }, [loadProviders]);
4415
+ react.useEffect(() => {
4416
+ if (!provider) return;
4417
+ let cancelled = false;
4418
+ setLoadingOpps(true);
4419
+ getEarnOpportunities(provider).then((opps) => {
4420
+ if (cancelled) return;
4421
+ setOpportunities(opps);
4422
+ setOpportunityId((cur) => opps.some((o) => o.id === cur) ? cur : opps[0]?.id ?? "");
4423
+ }).catch(() => {
4424
+ if (!cancelled) setOpportunities([]);
4425
+ }).finally(() => {
4426
+ if (!cancelled) setLoadingOpps(false);
4427
+ });
4428
+ return () => {
4429
+ cancelled = true;
4430
+ };
4431
+ }, [provider, getEarnOpportunities]);
4432
+ const selectedOpportunity = opportunities.find((o) => o.id === opportunityId) ?? null;
4433
+ const refreshPosition = react.useCallback(() => {
4434
+ if (!provider || !opportunityId || !wallet) return;
4435
+ getEarnPosition({ provider, opportunity: opportunityId }).then(setPosition).catch(() => {
4436
+ });
4437
+ }, [provider, opportunityId, wallet, getEarnPosition]);
4438
+ react.useEffect(() => {
4439
+ setPosition(null);
4440
+ refreshPosition();
4441
+ }, [refreshPosition]);
4442
+ react.useEffect(() => {
4443
+ if (step !== "form" || !provider || !opportunityId) return;
4444
+ const id = setInterval(refreshPosition, POSITION_POLL_MS);
4445
+ return () => clearInterval(id);
4446
+ }, [step, provider, opportunityId, refreshPosition]);
4447
+ react.useEffect(
4448
+ () => () => {
4449
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
4450
+ },
4451
+ []
4452
+ );
4453
+ const providersLoading = providers === null;
4454
+ const earnUnavailable = providers !== null && providers.length === 0;
4455
+ const withdrawUnit = position?.withdrawUnit ?? "asset";
4456
+ const assetCode = selectedOpportunity?.asset.code ?? "";
4457
+ const amountUnitLabel = tab === "deposit" ? assetCode : withdrawUnit === "shares" ? "shares" : assetCode;
4458
+ const hash = transaction.step === "success" ? transaction.hash : null;
4459
+ const buildData = "buildData" in transaction ? transaction.buildData : null;
4460
+ const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
4461
+ const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
4462
+ const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
4463
+ const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
4464
+ const txTitle = isInProgress ? tab === "deposit" ? "Depositing\u2026" : "Withdrawing\u2026" : transaction.step === "success" ? "Done!" : transaction.step === "error" ? tab === "deposit" ? "Deposit failed" : "Withdraw failed" : "Confirm";
4465
+ const canSubmit = !smartUnsupported && !!provider && !!opportunityId && !!amount && parseFloat(amount) > 0 && !providersLoading && !loadingOpps;
4466
+ const cssVars = {
4467
+ "--pollar-accent": accentColor,
4468
+ "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
4469
+ "--pollar-border": isDark ? "#374151" : "#e5e7eb",
4470
+ "--pollar-text": isDark ? "#ffffff" : "#111827",
4471
+ "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
4472
+ "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
4473
+ "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
4474
+ "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
4475
+ "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
4476
+ "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
4477
+ "--pollar-buttons-border-radius": "6px",
4478
+ "--pollar-buttons-height": "44px",
4479
+ "--pollar-input-height": "44px",
4480
+ "--pollar-input-border-radius": "0.5rem",
4481
+ "--pollar-card-border-radius": "10px"
4482
+ };
4483
+ async function handleSubmit() {
4484
+ setFormError("");
4485
+ if (smartUnsupported) {
4486
+ setFormError("Earn is not yet supported for smart (passkey) wallets");
4487
+ return;
4488
+ }
4489
+ if (!provider || !opportunityId) {
4490
+ setFormError("Select a vault or pool");
4491
+ return;
4492
+ }
4493
+ const parsed = parseFloat(amount);
4494
+ if (!amount || isNaN(parsed) || parsed <= 0) {
4495
+ setFormError("Enter a valid amount");
4496
+ return;
4497
+ }
4498
+ if (tab === "withdraw" && position && parsed > parseFloat(position.withdrawable)) {
4499
+ setFormError("Amount exceeds your position");
4500
+ return;
4501
+ }
4502
+ setStep("tx");
4503
+ const params = { provider, opportunity: opportunityId, amount };
4504
+ const outcome = tab === "deposit" ? await earnDeposit(params) : await earnWithdraw(params);
4505
+ if (outcome.status === "success" || outcome.status === "pending") {
4506
+ setAmount("");
4507
+ refreshPosition();
4508
+ }
4509
+ }
4510
+ async function handleRetry() {
4511
+ if (transaction.step !== "error" || !provider || !opportunityId) return;
4512
+ const params = { provider, opportunity: opportunityId, amount };
4513
+ if (tab === "deposit") await earnDeposit(params);
4514
+ else await earnWithdraw(params);
4515
+ }
4516
+ function handleCopyHash() {
4517
+ if (!hash) return;
4518
+ navigator.clipboard.writeText(hash).then(() => {
4519
+ setCopied(true);
4520
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
4521
+ copyTimerRef.current = setTimeout(() => {
4522
+ copyTimerRef.current = null;
4523
+ setCopied(false);
4524
+ }, 2e3);
4525
+ });
4526
+ }
4527
+ function handleBack() {
4528
+ setStep("form");
4529
+ setShowXdr(false);
4530
+ setCopied(false);
4531
+ refreshPosition();
4532
+ }
4533
+ const title = step === "form" ? "Earn" : txTitle;
4534
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-send-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
4535
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
4536
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-header-left", children: [
4537
+ 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" }) }) }),
4538
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: title })
4539
+ ] }),
4540
+ !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" }) }) })
4541
+ ] }),
4542
+ step === "form" && providersLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "Loading Earn options\u2026" }),
4543
+ step === "form" && earnUnavailable && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Earn is not available for this app." }),
4544
+ step === "form" && !earnUnavailable && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4545
+ smartUnsupported && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Earn is not yet available for smart (passkey) wallets." }),
4546
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-earn-tabs", children: [
4547
+ /* @__PURE__ */ jsxRuntime.jsx(
4548
+ "button",
4549
+ {
4550
+ type: "button",
4551
+ className: `pollar-earn-tab${tab === "deposit" ? " pollar-earn-tab-active" : ""}`,
4552
+ onClick: () => {
4553
+ setTab("deposit");
4554
+ setFormError("");
4555
+ },
4556
+ children: "Deposit"
4557
+ }
4558
+ ),
4559
+ /* @__PURE__ */ jsxRuntime.jsx(
4560
+ "button",
4561
+ {
4562
+ type: "button",
4563
+ className: `pollar-earn-tab${tab === "withdraw" ? " pollar-earn-tab-active" : ""}`,
4564
+ onClick: () => {
4565
+ setTab("withdraw");
4566
+ setFormError("");
4567
+ },
4568
+ children: "Withdraw"
4569
+ }
4570
+ )
4571
+ ] }),
4572
+ providers && providers.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
4573
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Provider" }),
4574
+ /* @__PURE__ */ jsxRuntime.jsx(
4575
+ "select",
4576
+ {
4577
+ className: "pollar-input pollar-send-select",
4578
+ value: provider ?? "",
4579
+ onChange: (e) => setProvider(e.target.value),
4580
+ children: providers.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p, children: PROVIDER_LABELS2[p] }, p))
4581
+ }
4582
+ )
4583
+ ] }),
4584
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
4585
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: provider === "defindex" ? "Vault" : "Pool" }),
4586
+ /* @__PURE__ */ jsxRuntime.jsx(
4587
+ "select",
4588
+ {
4589
+ className: "pollar-input pollar-send-select",
4590
+ value: opportunityId,
4591
+ disabled: loadingOpps || opportunities.length === 0,
4592
+ onChange: (e) => setOpportunityId(e.target.value),
4593
+ 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: [
4594
+ o.name,
4595
+ " \xB7 ",
4596
+ o.apy.toFixed(2),
4597
+ "% APY"
4598
+ ] }, o.id))
4599
+ }
4600
+ )
4601
+ ] }),
4602
+ selectedOpportunity && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote", children: [
4603
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
4604
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Your position" }),
4605
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
4606
+ position ? formatAmount4(position.balance) : "\u2026",
4607
+ " ",
4608
+ assetCode
4609
+ ] })
4610
+ ] }),
4611
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
4612
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "APY" }),
4613
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-earn-live", children: [
4614
+ selectedOpportunity.apy.toFixed(2),
4615
+ "%"
4616
+ ] })
4617
+ ] })
4618
+ ] }),
4619
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
4620
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-label-row", children: [
4621
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: tab === "deposit" ? "Amount" : "Withdraw amount" }),
4622
+ tab === "withdraw" && position && /* @__PURE__ */ jsxRuntime.jsxs(
4623
+ "button",
4624
+ {
4625
+ type: "button",
4626
+ className: "pollar-swap-custom-toggle",
4627
+ onClick: () => setAmount(position.withdrawable),
4628
+ children: [
4629
+ "Max: ",
4630
+ formatAmount4(position.withdrawable),
4631
+ " ",
4632
+ amountUnitLabel
4633
+ ]
4634
+ }
4635
+ )
4636
+ ] }),
4637
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-earn-amount", children: [
4638
+ /* @__PURE__ */ jsxRuntime.jsx(
4639
+ "input",
4640
+ {
4641
+ className: "pollar-input",
4642
+ type: "text",
4643
+ inputMode: "decimal",
4644
+ placeholder: "0.00",
4645
+ value: amount,
4646
+ onChange: (e) => setAmount(e.target.value)
4647
+ }
4648
+ ),
4649
+ amountUnitLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-earn-amount-unit", children: amountUnitLabel })
4650
+ ] })
4651
+ ] }),
4652
+ formError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: formError }),
4653
+ /* @__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" }) })
4654
+ ] }),
4655
+ step === "tx" && /* @__PURE__ */ jsxRuntime.jsx(
4656
+ TxStatusView,
4657
+ {
4658
+ transaction,
4659
+ showXdr,
4660
+ copied,
4661
+ explorerUrl,
4662
+ walletType,
4663
+ onSignAndSend: () => {
4664
+ },
4665
+ onToggleXdr: () => setShowXdr((v) => !v),
4666
+ onCopyHash: handleCopyHash,
4667
+ onRetry: () => void handleRetry(),
4668
+ onDone: onClose
4669
+ }
4670
+ ),
4671
+ /* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
4672
+ ] }) });
4673
+ }
4269
4674
  function describeDevice(s) {
4270
4675
  if (s.deviceLabel) return s.deviceLabel;
4271
4676
  if (!s.userAgent) return "Unknown device";
@@ -4615,6 +5020,33 @@ function StatusBadge({ status }) {
4615
5020
  function formatDate(iso) {
4616
5021
  return new Date(iso).toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" });
4617
5022
  }
5023
+ function truncateMiddle(value, head = 4, tail = 4) {
5024
+ return value.length <= head + tail + 1 ? value : `${value.slice(0, head)}\u2026${value.slice(-tail)}`;
5025
+ }
5026
+ var STELLAR_ADDRESS = /\b[GC][A-Z2-7]{55}\b/g;
5027
+ function AddressChip({ value, label }) {
5028
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-hist-item-issuer", children: [
5029
+ truncateMiddle(value),
5030
+ /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value, label, className: "pollar-copy-btn-sm" })
5031
+ ] });
5032
+ }
5033
+ function renderSummary(summary) {
5034
+ const parts = [];
5035
+ let last = 0;
5036
+ let key = 0;
5037
+ STELLAR_ADDRESS.lastIndex = 0;
5038
+ for (let m = STELLAR_ADDRESS.exec(summary); m !== null; m = STELLAR_ADDRESS.exec(summary)) {
5039
+ if (m.index > last) parts.push(/* @__PURE__ */ jsxRuntime.jsx("span", { children: summary.slice(last, m.index) }, key++));
5040
+ const address = m[0];
5041
+ parts.push(
5042
+ /* @__PURE__ */ jsxRuntime.jsx(AddressChip, { value: address, label: address[0] === "C" ? "Copy contract address" : "Copy wallet address" }, key++)
5043
+ );
5044
+ last = m.index + address.length;
5045
+ }
5046
+ if (parts.length === 0) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-hist-item-title", children: summary });
5047
+ if (last < summary.length) parts.push(/* @__PURE__ */ jsxRuntime.jsx("span", { children: summary.slice(last) }, key++));
5048
+ return parts;
5049
+ }
4618
5050
  function TxHistoryModalTemplate({
4619
5051
  theme,
4620
5052
  accentColor,
@@ -4687,11 +5119,35 @@ function TxHistoryModalTemplate({
4687
5119
  txHistory.step === "error" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: txHistory.message }),
4688
5120
  txHistory.step === "loaded" && records.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "No transactions yet." }),
4689
5121
  records.map((record) => {
4690
- const explorerUrl = `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${record.hash}`;
4691
- const destination = typeof record.details?.destination === "string" ? record.details.destination : void 0;
5122
+ const hash = typeof record.hash === "string" && record.hash.length > 0 ? record.hash : void 0;
5123
+ const explorerUrl = hash ? `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${hash}` : void 0;
5124
+ const asset = typeof record.details?.asset === "string" ? record.details.asset : void 0;
5125
+ const colon = asset ? asset.indexOf(":") : -1;
5126
+ const trustline = record.operation === "change_trust" && asset && colon > 0 ? {
5127
+ prefix: record.summary.split(":")[0],
5128
+ code: asset.slice(0, colon),
5129
+ issuer: asset.slice(colon + 1)
5130
+ } : void 0;
5131
+ 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;
4692
5132
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-hist-item", children: [
4693
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-hist-item-summary", children: record.summary }),
4694
- /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: record.status }),
5133
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-hist-item-top", children: [
5134
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-hist-item-summary", children: trustline ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5135
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-hist-item-title", children: [
5136
+ trustline.prefix,
5137
+ ": ",
5138
+ trustline.code
5139
+ ] }),
5140
+ /* @__PURE__ */ jsxRuntime.jsx(AddressChip, { value: trustline.issuer, label: "Copy issuer" })
5141
+ ] }) : contract ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5142
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-hist-item-title", children: [
5143
+ "Invoke ",
5144
+ contract.method,
5145
+ "() on"
5146
+ ] }),
5147
+ /* @__PURE__ */ jsxRuntime.jsx(AddressChip, { value: contract.contractId, label: "Copy contract address" })
5148
+ ] }) : renderSummary(record.summary) }),
5149
+ /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: record.status })
5150
+ ] }),
4695
5151
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-hist-item-meta", children: [
4696
5152
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: record.operation }),
4697
5153
  typeof record.details?.sponsored === "boolean" && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
@@ -4702,26 +5158,23 @@ function TxHistoryModalTemplate({
4702
5158
  "\xB7 ",
4703
5159
  record.feeXlm,
4704
5160
  " XLM"
4705
- ] }),
4706
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
4707
- "\xB7 ",
4708
- formatDate(record.createdAt)
4709
- ] }),
4710
- destination && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4711
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\xB7" }),
4712
- /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: destination, label: "Copy wallet address", className: "pollar-copy-btn-sm" })
4713
- ] }),
4714
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\xB7" }),
4715
- /* @__PURE__ */ jsxRuntime.jsxs(
4716
- "a",
4717
- {
4718
- className: "pollar-hist-item-explorer",
4719
- href: explorerUrl,
4720
- target: "_blank",
4721
- rel: "noopener noreferrer",
4722
- "aria-label": "View on Stellar Explorer",
4723
- children: [
4724
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "11", height: "11", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
5161
+ ] })
5162
+ ] }),
5163
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-hist-item-footer", children: [
5164
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatDate(record.createdAt) }),
5165
+ hash && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5166
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-hist-item-dot", children: "\xB7" }),
5167
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-hist-item-hash", children: truncateMiddle(hash, 6, 6) }),
5168
+ /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: hash, label: "Copy transaction hash", className: "pollar-copy-btn-sm" }),
5169
+ /* @__PURE__ */ jsxRuntime.jsx(
5170
+ "a",
5171
+ {
5172
+ className: "pollar-hist-item-explorer",
5173
+ href: explorerUrl,
5174
+ target: "_blank",
5175
+ rel: "noopener noreferrer",
5176
+ "aria-label": "View on Stellar Explorer",
5177
+ children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "12", height: "12", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
4725
5178
  /* @__PURE__ */ jsxRuntime.jsx(
4726
5179
  "path",
4727
5180
  {
@@ -4741,11 +5194,10 @@ function TxHistoryModalTemplate({
4741
5194
  strokeLinejoin: "round"
4742
5195
  }
4743
5196
  )
4744
- ] }),
4745
- "Explorer"
4746
- ]
4747
- }
4748
- )
5197
+ ] })
5198
+ }
5199
+ )
5200
+ ] })
4749
5201
  ] })
4750
5202
  ] }, record.id);
4751
5203
  })
@@ -5091,6 +5543,7 @@ function PollarProvider({
5091
5543
  const [enabledAssetsModalOpen, setEnabledAssetsModalOpen] = react.useState(false);
5092
5544
  const [sendModalOpen, setSendModalOpen] = react.useState(false);
5093
5545
  const [swapModalOpen, setSwapModalOpen] = react.useState(false);
5546
+ const [earnModalOpen, setEarnModalOpen] = react.useState(false);
5094
5547
  const [receiveModalOpen, setReceiveModalOpen] = react.useState(false);
5095
5548
  const [sessionsModalOpen, setSessionsModalOpen] = react.useState(false);
5096
5549
  const [distributionRulesModalOpen, setDistributionRulesModalOpen] = react.useState(false);
@@ -5141,6 +5594,13 @@ function PollarProvider({
5141
5594
  getSwapQuote: (params) => pollarClient.getSwapQuote(params),
5142
5595
  swap: (quote, opts) => pollarClient.swap(quote, opts),
5143
5596
  openSwapModal: () => setSwapModalOpen(true),
5597
+ // earn
5598
+ getEarnProviders: () => pollarClient.getEarnProviders(),
5599
+ getEarnOpportunities: (provider) => pollarClient.getEarnOpportunities(provider),
5600
+ getEarnPosition: (params) => pollarClient.getEarnPosition(params),
5601
+ earnDeposit: (params) => pollarClient.earnDeposit(params),
5602
+ earnWithdraw: (params) => pollarClient.earnWithdraw(params),
5603
+ openEarnModal: () => setEarnModalOpen(true),
5144
5604
  // sessions
5145
5605
  sessions,
5146
5606
  openSessionsModal: () => setSessionsModalOpen(true),
@@ -5196,6 +5656,7 @@ function PollarProvider({
5196
5656
  enabledAssetsModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setEnabledAssetsModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(EnabledAssetsModal, { onClose: () => setEnabledAssetsModalOpen(false) }) }),
5197
5657
  sendModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSendModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SendModal, { onClose: () => setSendModalOpen(false) }) }),
5198
5658
  swapModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSwapModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SwapModal, { onClose: () => setSwapModalOpen(false) }) }),
5659
+ earnModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setEarnModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(EarnModal, { onClose: () => setEarnModalOpen(false) }) }),
5199
5660
  receiveModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setReceiveModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(ReceiveModal, { onClose: () => setReceiveModalOpen(false) }) }),
5200
5661
  sessionsModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSessionsModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SessionsModal, { onClose: () => setSessionsModalOpen(false) }) }),
5201
5662
  distributionRulesModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setDistributionRulesModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(DistributionRulesModal, { onClose: () => setDistributionRulesModalOpen(false) }) })
@@ -5245,7 +5706,10 @@ function WalletButtonTemplate({
5245
5706
  itemColor,
5246
5707
  wrapperRef,
5247
5708
  isInProgress,
5709
+ showCreateAccount,
5710
+ creatingAccount,
5248
5711
  onToggleOpen,
5712
+ onCreateAccount,
5249
5713
  onCopy,
5250
5714
  onWalletBalance,
5251
5715
  onTxHistory,
@@ -5307,6 +5771,40 @@ function WalletButtonTemplate({
5307
5771
  }
5308
5772
  ),
5309
5773
  open && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "wallet-dropdown", style: { backgroundColor: dropdownBg, borderColor: dropdownBorder }, children: [
5774
+ showCreateAccount && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5775
+ /* @__PURE__ */ jsxRuntime.jsxs(
5776
+ "button",
5777
+ {
5778
+ className: "wallet-dropdown-item",
5779
+ style: { color: itemColor },
5780
+ onClick: onCreateAccount,
5781
+ disabled: creatingAccount,
5782
+ children: [
5783
+ /* @__PURE__ */ jsxRuntime.jsxs(
5784
+ "svg",
5785
+ {
5786
+ width: "14",
5787
+ height: "14",
5788
+ viewBox: "0 0 24 24",
5789
+ fill: "none",
5790
+ stroke: "currentColor",
5791
+ strokeWidth: "2",
5792
+ strokeLinecap: "round",
5793
+ strokeLinejoin: "round",
5794
+ children: [
5795
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
5796
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "7", r: "4" }),
5797
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "19", y1: "8", x2: "19", y2: "14" }),
5798
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "22", y1: "11", x2: "16", y2: "11" })
5799
+ ]
5800
+ }
5801
+ ),
5802
+ creatingAccount ? "Creating account\u2026" : "Create account"
5803
+ ]
5804
+ }
5805
+ ),
5806
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "wallet-dropdown-divider" })
5807
+ ] }),
5310
5808
  /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onSend, children: [
5311
5809
  /* @__PURE__ */ jsxRuntime.jsxs(
5312
5810
  "svg",
@@ -5546,9 +6044,12 @@ function WalletButton() {
5546
6044
  const walletType = wallet?.custody === "external" ? wallet.provider : null;
5547
6045
  const [open, setOpen] = react.useState(false);
5548
6046
  const [copied, setCopied] = react.useState(false);
6047
+ const [creating, setCreating] = react.useState(false);
6048
+ const [created, setCreated] = react.useState(false);
5549
6049
  const wrapperRef = react.useRef(null);
5550
6050
  const copyTimerRef = react.useRef(null);
5551
6051
  const isInProgress = transaction.step === "building" || transaction.step === "signing";
6052
+ const canCreateAccount = !created && wallet?.custody === "external" && wallet.existsOnStellar === false && wallet.fundingMode === "IMMEDIATE";
5552
6053
  const { theme = "light", accentColor = "#005DB4" } = styles;
5553
6054
  const isDark = theme === "dark";
5554
6055
  const dropdownBg = isDark ? "#18181b" : "#fff";
@@ -5583,6 +6084,20 @@ function WalletButton() {
5583
6084
  setOpen(false);
5584
6085
  getClient().logout();
5585
6086
  }
6087
+ async function handleCreateAccount() {
6088
+ if (creating) return;
6089
+ setCreating(true);
6090
+ try {
6091
+ const res = await getClient().createAccount();
6092
+ if (res.status === "success" || res.status === "pending") {
6093
+ setCreated(true);
6094
+ setOpen(false);
6095
+ await getClient().refreshBalance();
6096
+ }
6097
+ } finally {
6098
+ setCreating(false);
6099
+ }
6100
+ }
5586
6101
  function handleWalletBalance() {
5587
6102
  setOpen(false);
5588
6103
  openWalletBalanceModal();
@@ -5628,7 +6143,10 @@ function WalletButton() {
5628
6143
  wrapperRef,
5629
6144
  isInProgress,
5630
6145
  walletType,
6146
+ showCreateAccount: canCreateAccount,
6147
+ creatingAccount: creating,
5631
6148
  onToggleOpen: () => setOpen((v) => !v),
6149
+ onCreateAccount: handleCreateAccount,
5632
6150
  onCopy: handleCopy,
5633
6151
  onWalletBalance: handleWalletBalance,
5634
6152
  onTxHistory: handleTxHistory,
@@ -5646,6 +6164,7 @@ function WalletButton() {
5646
6164
 
5647
6165
  exports.DistributionRulesModal = DistributionRulesModal;
5648
6166
  exports.DistributionRulesModalTemplate = DistributionRulesModalTemplate;
6167
+ exports.EarnModal = EarnModal;
5649
6168
  exports.EnabledAssetsModal = EnabledAssetsModal;
5650
6169
  exports.EnabledAssetsModalTemplate = EnabledAssetsModalTemplate;
5651
6170
  exports.KycModal = KycModal;