@pollar/react 0.10.1-rc.5 → 0.10.1-rc.7

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.5"
1038
+ "0.10.1-rc.7"
1039
1039
  ] })
1040
1040
  ] })
1041
1041
  ] });
@@ -2556,12 +2556,23 @@ var INSTRUCTION_LABELS = {
2556
2556
  function flattenInstructions(instr) {
2557
2557
  const out = [];
2558
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
+ }
2559
2570
  let value = "";
2560
2571
  if (typeof v === "string" || typeof v === "number") value = String(v);
2561
2572
  else if (Array.isArray(v)) value = v.filter((x) => typeof x === "string" || typeof x === "number").join(", ");
2562
2573
  else continue;
2563
2574
  if (!value) continue;
2564
- out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? k, value });
2575
+ out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? k, value, kind: "text" });
2565
2576
  }
2566
2577
  return out;
2567
2578
  }
@@ -2787,9 +2798,16 @@ function RampWidgetTemplate({
2787
2798
  stellarTxHash.slice(-8)
2788
2799
  ] }) })
2789
2800
  ] }),
2790
- 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: [
2791
2802
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: label }),
2792
- /* @__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 }) })
2793
2811
  ] }, key)),
2794
2812
  tosUrl && !depositInstructions && txStatus !== "completed" && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenTos, children: [
2795
2813
  "Accept terms at ",
@@ -3669,7 +3687,7 @@ function SendModal({ onClose }) {
3669
3687
  const buildData = "buildData" in transaction ? transaction.buildData : null;
3670
3688
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
3671
3689
  const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
3672
- const IN_FLIGHT_STEPS2 = [
3690
+ const IN_FLIGHT_STEPS3 = [
3673
3691
  "building",
3674
3692
  "signing",
3675
3693
  "submitting",
@@ -3677,7 +3695,7 @@ function SendModal({ onClose }) {
3677
3695
  "signing-submitting",
3678
3696
  "building-signing-submitting"
3679
3697
  ];
3680
- const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
3698
+ const isInProgress = IN_FLIGHT_STEPS3.includes(transaction.step);
3681
3699
  const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
3682
3700
  const txTitle = isInProgress ? "Sending\u2026" : transaction.step === "success" ? "Sent!" : transaction.step === "error" ? "Send failed" : "Confirm Send";
3683
3701
  async function handleSubmit() {
@@ -4243,7 +4261,7 @@ function SwapModal({ onClose }) {
4243
4261
  const buildData = "buildData" in transaction ? transaction.buildData : null;
4244
4262
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
4245
4263
  const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
4246
- const IN_FLIGHT_STEPS2 = [
4264
+ const IN_FLIGHT_STEPS3 = [
4247
4265
  "building",
4248
4266
  "signing",
4249
4267
  "submitting",
@@ -4251,7 +4269,7 @@ function SwapModal({ onClose }) {
4251
4269
  "signing-submitting",
4252
4270
  "building-signing-submitting"
4253
4271
  ];
4254
- const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
4272
+ const isInProgress = IN_FLIGHT_STEPS3.includes(transaction.step);
4255
4273
  const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
4256
4274
  const txTitle = isInProgress ? "Swapping\u2026" : transaction.step === "success" ? "Swapped!" : transaction.step === "error" ? "Swap failed" : "Confirm Swap";
4257
4275
  async function handleSwap() {
@@ -4345,6 +4363,314 @@ function SwapModal({ onClose }) {
4345
4363
  }
4346
4364
  ) });
4347
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
+ }
4348
4674
  function describeDevice(s) {
4349
4675
  if (s.deviceLabel) return s.deviceLabel;
4350
4676
  if (!s.userAgent) return "Unknown device";
@@ -4697,6 +5023,30 @@ function formatDate(iso) {
4697
5023
  function truncateMiddle(value, head = 4, tail = 4) {
4698
5024
  return value.length <= head + tail + 1 ? value : `${value.slice(0, head)}\u2026${value.slice(-tail)}`;
4699
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
+ }
4700
5050
  function TxHistoryModalTemplate({
4701
5051
  theme,
4702
5052
  accentColor,
@@ -4771,7 +5121,6 @@ function TxHistoryModalTemplate({
4771
5121
  records.map((record) => {
4772
5122
  const hash = typeof record.hash === "string" && record.hash.length > 0 ? record.hash : void 0;
4773
5123
  const explorerUrl = hash ? `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${hash}` : void 0;
4774
- const destination = typeof record.details?.destination === "string" ? record.details.destination : void 0;
4775
5124
  const asset = typeof record.details?.asset === "string" ? record.details.asset : void 0;
4776
5125
  const colon = asset ? asset.indexOf(":") : -1;
4777
5126
  const trustline = record.operation === "change_trust" && asset && colon > 0 ? {
@@ -4779,6 +5128,7 @@ function TxHistoryModalTemplate({
4779
5128
  code: asset.slice(0, colon),
4780
5129
  issuer: asset.slice(colon + 1)
4781
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;
4782
5132
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-hist-item", children: [
4783
5133
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-hist-item-top", children: [
4784
5134
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-hist-item-summary", children: trustline ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -4787,11 +5137,15 @@ function TxHistoryModalTemplate({
4787
5137
  ": ",
4788
5138
  trustline.code
4789
5139
  ] }),
4790
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-hist-item-issuer", children: [
4791
- truncateMiddle(trustline.issuer),
4792
- /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: trustline.issuer, label: "Copy issuer", className: "pollar-copy-btn-sm" })
4793
- ] })
4794
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-hist-item-title", children: record.summary }) }),
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) }),
4795
5149
  /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: record.status })
4796
5150
  ] }),
4797
5151
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-hist-item-meta", children: [
@@ -4804,13 +5158,6 @@ function TxHistoryModalTemplate({
4804
5158
  "\xB7 ",
4805
5159
  record.feeXlm,
4806
5160
  " XLM"
4807
- ] }),
4808
- destination && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4809
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\xB7" }),
4810
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-hist-item-issuer", children: [
4811
- truncateMiddle(destination),
4812
- /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: destination, label: "Copy wallet address", className: "pollar-copy-btn-sm" })
4813
- ] })
4814
5161
  ] })
4815
5162
  ] }),
4816
5163
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-hist-item-footer", children: [
@@ -5196,6 +5543,7 @@ function PollarProvider({
5196
5543
  const [enabledAssetsModalOpen, setEnabledAssetsModalOpen] = react.useState(false);
5197
5544
  const [sendModalOpen, setSendModalOpen] = react.useState(false);
5198
5545
  const [swapModalOpen, setSwapModalOpen] = react.useState(false);
5546
+ const [earnModalOpen, setEarnModalOpen] = react.useState(false);
5199
5547
  const [receiveModalOpen, setReceiveModalOpen] = react.useState(false);
5200
5548
  const [sessionsModalOpen, setSessionsModalOpen] = react.useState(false);
5201
5549
  const [distributionRulesModalOpen, setDistributionRulesModalOpen] = react.useState(false);
@@ -5246,6 +5594,13 @@ function PollarProvider({
5246
5594
  getSwapQuote: (params) => pollarClient.getSwapQuote(params),
5247
5595
  swap: (quote, opts) => pollarClient.swap(quote, opts),
5248
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),
5249
5604
  // sessions
5250
5605
  sessions,
5251
5606
  openSessionsModal: () => setSessionsModalOpen(true),
@@ -5301,6 +5656,7 @@ function PollarProvider({
5301
5656
  enabledAssetsModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setEnabledAssetsModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(EnabledAssetsModal, { onClose: () => setEnabledAssetsModalOpen(false) }) }),
5302
5657
  sendModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSendModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SendModal, { onClose: () => setSendModalOpen(false) }) }),
5303
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) }) }),
5304
5660
  receiveModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setReceiveModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(ReceiveModal, { onClose: () => setReceiveModalOpen(false) }) }),
5305
5661
  sessionsModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSessionsModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SessionsModal, { onClose: () => setSessionsModalOpen(false) }) }),
5306
5662
  distributionRulesModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setDistributionRulesModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(DistributionRulesModal, { onClose: () => setDistributionRulesModalOpen(false) }) })
@@ -5350,7 +5706,10 @@ function WalletButtonTemplate({
5350
5706
  itemColor,
5351
5707
  wrapperRef,
5352
5708
  isInProgress,
5709
+ showCreateAccount,
5710
+ creatingAccount,
5353
5711
  onToggleOpen,
5712
+ onCreateAccount,
5354
5713
  onCopy,
5355
5714
  onWalletBalance,
5356
5715
  onTxHistory,
@@ -5412,6 +5771,40 @@ function WalletButtonTemplate({
5412
5771
  }
5413
5772
  ),
5414
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
+ ] }),
5415
5808
  /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onSend, children: [
5416
5809
  /* @__PURE__ */ jsxRuntime.jsxs(
5417
5810
  "svg",
@@ -5651,9 +6044,12 @@ function WalletButton() {
5651
6044
  const walletType = wallet?.custody === "external" ? wallet.provider : null;
5652
6045
  const [open, setOpen] = react.useState(false);
5653
6046
  const [copied, setCopied] = react.useState(false);
6047
+ const [creating, setCreating] = react.useState(false);
6048
+ const [created, setCreated] = react.useState(false);
5654
6049
  const wrapperRef = react.useRef(null);
5655
6050
  const copyTimerRef = react.useRef(null);
5656
6051
  const isInProgress = transaction.step === "building" || transaction.step === "signing";
6052
+ const canCreateAccount = !created && wallet?.custody === "external" && wallet.existsOnStellar === false && wallet.fundingMode === "IMMEDIATE";
5657
6053
  const { theme = "light", accentColor = "#005DB4" } = styles;
5658
6054
  const isDark = theme === "dark";
5659
6055
  const dropdownBg = isDark ? "#18181b" : "#fff";
@@ -5688,6 +6084,20 @@ function WalletButton() {
5688
6084
  setOpen(false);
5689
6085
  getClient().logout();
5690
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
+ }
5691
6101
  function handleWalletBalance() {
5692
6102
  setOpen(false);
5693
6103
  openWalletBalanceModal();
@@ -5733,7 +6143,10 @@ function WalletButton() {
5733
6143
  wrapperRef,
5734
6144
  isInProgress,
5735
6145
  walletType,
6146
+ showCreateAccount: canCreateAccount,
6147
+ creatingAccount: creating,
5736
6148
  onToggleOpen: () => setOpen((v) => !v),
6149
+ onCreateAccount: handleCreateAccount,
5737
6150
  onCopy: handleCopy,
5738
6151
  onWalletBalance: handleWalletBalance,
5739
6152
  onTxHistory: handleTxHistory,
@@ -5751,6 +6164,7 @@ function WalletButton() {
5751
6164
 
5752
6165
  exports.DistributionRulesModal = DistributionRulesModal;
5753
6166
  exports.DistributionRulesModalTemplate = DistributionRulesModalTemplate;
6167
+ exports.EarnModal = EarnModal;
5754
6168
  exports.EnabledAssetsModal = EnabledAssetsModal;
5755
6169
  exports.EnabledAssetsModalTemplate = EnabledAssetsModalTemplate;
5756
6170
  exports.KycModal = KycModal;