@pollar/react 0.11.1-rc.3 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client';
2
- import { AUTH_ERROR_CODES, WalletType, PollarClient, isInteractiveAuthAdapter } from '@pollar/core';
3
- import { forwardRef, createContext, useState, useCallback, useEffect, useRef, useMemo, useContext, Component } from 'react';
2
+ import { AUTH_ERROR_CODES, WalletType, PollarClient, isInteractiveAuthAdapter, toBaseUnits } from '@pollar/core';
3
+ import { forwardRef, createContext, useState, useCallback, useEffect, useMemo, useRef, useContext, Component } from 'react';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
  import { startAuthentication, startRegistration } from '@simplewebauthn/browser';
6
6
 
@@ -1033,7 +1033,7 @@ var PollarModalFooter = () => {
1033
1033
  /* @__PURE__ */ jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
1034
1034
  /* @__PURE__ */ jsxs("span", { className: "pollar-footer-version", children: [
1035
1035
  "v",
1036
- "0.11.1-rc.3"
1036
+ "0.11.2"
1037
1037
  ] })
1038
1038
  ] })
1039
1039
  ] });
@@ -1099,6 +1099,36 @@ function ModalStatusBanner({ message, status, onCancel, onRetry }) {
1099
1099
  status === "ERROR" && onRetry && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-status-cancel", onClick: onRetry, children: "Retry" })
1100
1100
  ] });
1101
1101
  }
1102
+ function cropAddress(address) {
1103
+ if (address.length <= 16) return address;
1104
+ return `${address.slice(0, 8)}...${address.slice(-8)}`;
1105
+ }
1106
+ function useStickyData(data) {
1107
+ const lastRef = useRef(null);
1108
+ if (data !== null) lastRef.current = data;
1109
+ return data ?? lastRef.current;
1110
+ }
1111
+ function BusyOverlay({ label = "Loading\u2026" }) {
1112
+ return /* @__PURE__ */ jsx("div", { className: "pollar-busy-overlay", "aria-busy": "true", "aria-live": "polite", children: /* @__PURE__ */ jsxs("div", { className: "pollar-busy-overlay-inner", children: [
1113
+ /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
1114
+ /* @__PURE__ */ jsx("span", { children: label })
1115
+ ] }) });
1116
+ }
1117
+ function Toggle({ checked, onChange, disabled = false, busy = false, label }) {
1118
+ return /* @__PURE__ */ jsx(
1119
+ "button",
1120
+ {
1121
+ type: "button",
1122
+ role: "switch",
1123
+ "aria-checked": checked,
1124
+ "aria-label": label,
1125
+ className: `pollar-switch${checked ? " pollar-switch-on" : ""}${busy ? " pollar-switch-busy" : ""}`,
1126
+ onClick: onChange,
1127
+ disabled: disabled || busy,
1128
+ children: /* @__PURE__ */ jsx("span", { className: "pollar-switch-knob", children: busy && /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm pollar-spinner-current" }) })
1129
+ }
1130
+ );
1131
+ }
1102
1132
  var PERIOD_LABEL = {
1103
1133
  DAY: "every 24h",
1104
1134
  DAY_CALENDAR: "daily",
@@ -1326,9 +1356,66 @@ function DistributionRulesModal({ onClose }) {
1326
1356
  }
1327
1357
  ) });
1328
1358
  }
1329
- function cropAddress(address) {
1330
- if (address.length <= 16) return address;
1331
- return `${address.slice(0, 8)}...${address.slice(-8)}`;
1359
+ var CHAIN_LABEL = {
1360
+ STELLAR: "Stellar",
1361
+ POLYGON: "Polygon",
1362
+ SOLANA: "Solana"
1363
+ };
1364
+ function resolveChain(chain) {
1365
+ return chain ?? "STELLAR";
1366
+ }
1367
+ function chainsOf(wallets, order) {
1368
+ const held = [];
1369
+ for (const w of wallets) {
1370
+ const chain = resolveChain(w.chain);
1371
+ if (!held.includes(chain)) held.push(chain);
1372
+ }
1373
+ if (!order || order.length === 0) return held;
1374
+ return order.filter((c) => held.includes(c));
1375
+ }
1376
+ function addressForChain(wallets, chain) {
1377
+ if (!chain) return "";
1378
+ return wallets.find((w) => resolveChain(w.chain) === chain)?.address ?? "";
1379
+ }
1380
+ function ChainSelect({ label = "Network", value, options, onChange, disabled = false }) {
1381
+ if (options.length < 2) return null;
1382
+ return /* @__PURE__ */ jsxs("div", { className: "pollar-send-field pollar-chain-field", children: [
1383
+ /* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: label }),
1384
+ /* @__PURE__ */ jsxs(
1385
+ "select",
1386
+ {
1387
+ className: "pollar-input pollar-send-select",
1388
+ value: value ?? "",
1389
+ disabled,
1390
+ onChange: (e) => onChange(e.target.value),
1391
+ children: [
1392
+ value === null && /* @__PURE__ */ jsx("option", { value: "", disabled: true, hidden: true }),
1393
+ options.map((chain) => /* @__PURE__ */ jsx("option", { value: chain, children: CHAIN_LABEL[chain] ?? chain }, chain))
1394
+ ]
1395
+ }
1396
+ )
1397
+ ] });
1398
+ }
1399
+
1400
+ // src/useChains.ts
1401
+ function useChains() {
1402
+ const { wallets, appConfig, configStatus } = usePollar();
1403
+ const configured = appConfig?.application?.chains;
1404
+ const ready = configStatus === "ready";
1405
+ return useMemo(() => {
1406
+ if (!ready) {
1407
+ const fallback = chainsOf(wallets);
1408
+ return {
1409
+ chains: [],
1410
+ primaryChain: null,
1411
+ primaryAddress: addressForChain(wallets, fallback[0] ?? null),
1412
+ ready: false
1413
+ };
1414
+ }
1415
+ const chains = chainsOf(wallets, configured);
1416
+ const primaryChain = chains[0] ?? null;
1417
+ return { chains, primaryChain, primaryAddress: addressForChain(wallets, primaryChain), ready: true };
1418
+ }, [wallets, configured, ready]);
1332
1419
  }
1333
1420
  function cssVarsFor(theme, accentColor) {
1334
1421
  const isDark = theme === "dark";
@@ -1353,14 +1440,18 @@ function cssVarsFor(theme, accentColor) {
1353
1440
  function assetKey(record) {
1354
1441
  return record.code + (record.issuer ?? "");
1355
1442
  }
1443
+ function rowKey(record) {
1444
+ return (record.chain ?? "") + assetKey(record);
1445
+ }
1356
1446
  function AssetItem({
1357
1447
  record,
1358
1448
  busy,
1359
1449
  disabled,
1360
1450
  onToggle
1361
1451
  }) {
1362
- const established = record.trustlineEstablished;
1452
+ const established = record.trustlineEstablished ?? false;
1363
1453
  const isNative = record.type === "native";
1454
+ const isStellar = resolveChain(record.chain) === "STELLAR";
1364
1455
  return /* @__PURE__ */ jsxs("div", { className: "pollar-asset-item", children: [
1365
1456
  /* @__PURE__ */ jsxs("div", { className: "pollar-asset-info", children: [
1366
1457
  /* @__PURE__ */ jsxs("div", { className: "pollar-asset-code-row", children: [
@@ -1368,17 +1459,22 @@ function AssetItem({
1368
1459
  record.enabledInApp && /* @__PURE__ */ jsx("span", { className: "pollar-asset-tag", children: "App" })
1369
1460
  ] }),
1370
1461
  record.name && /* @__PURE__ */ jsx("span", { className: "pollar-asset-name", children: record.name }),
1371
- !isNative && record.enabledInApp && /* @__PURE__ */ jsx("span", { className: "pollar-asset-sponsor", children: record.sponsored ? "Reserve sponsored by the app" : "You pay the reserve (~0.5 XLM)" })
1462
+ record.issuer && /* @__PURE__ */ jsxs("span", { className: "pollar-issuer", children: [
1463
+ /* @__PURE__ */ jsx("span", { className: "pollar-issuer-addr", children: cropAddress(record.issuer) }),
1464
+ /* @__PURE__ */ jsx(CopyButton, { value: record.issuer, label: "Copy issuer address", className: "pollar-copy-btn-sm" })
1465
+ ] }),
1466
+ isStellar && !isNative && record.enabledInApp && /* @__PURE__ */ jsx("span", { className: "pollar-asset-sponsor", children: record.sponsored ? "Reserve sponsored by the app" : "You pay the reserve (~0.5 XLM)" })
1372
1467
  ] }),
1373
- /* @__PURE__ */ jsxs("div", { className: "pollar-asset-actions", children: [
1374
- /* @__PURE__ */ jsx("span", { className: `pollar-asset-trustline${established ? " pollar-established" : ""}`, children: established ? "Trustline active" : "Needs trustline" }),
1375
- !isNative && /* @__PURE__ */ jsx(
1376
- "button",
1468
+ isStellar && /* @__PURE__ */ jsxs("div", { className: "pollar-asset-actions", children: [
1469
+ /* @__PURE__ */ jsx("span", { className: "pollar-asset-trustline-label", children: "Trustline" }),
1470
+ /* @__PURE__ */ jsx(
1471
+ Toggle,
1377
1472
  {
1378
- className: `pollar-asset-btn${established ? " pollar-danger" : ""}`,
1379
- onClick: () => onToggle(record),
1380
- disabled: busy || disabled,
1381
- children: busy ? /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm pollar-spinner-current" }) : established ? "Disable" : "Enable"
1473
+ checked: established,
1474
+ busy,
1475
+ disabled: isNative || disabled,
1476
+ onChange: () => onToggle(record),
1477
+ label: `${established ? "Disable" : "Enable"} ${record.code} trustline`
1382
1478
  }
1383
1479
  )
1384
1480
  ] })
@@ -1389,6 +1485,9 @@ function EnabledAssetsModalTemplate({
1389
1485
  accentColor,
1390
1486
  enabledAssets,
1391
1487
  walletAddress,
1488
+ chains,
1489
+ selectedChain,
1490
+ onSelectChain,
1392
1491
  busyKey,
1393
1492
  actionError,
1394
1493
  onRefresh,
@@ -1398,8 +1497,10 @@ function EnabledAssetsModalTemplate({
1398
1497
  }) {
1399
1498
  const cssVars = cssVarsFor(theme, accentColor);
1400
1499
  const isLoading = enabledAssets.step === "loading";
1401
- const data = enabledAssets.step === "loaded" ? enabledAssets.data : null;
1500
+ const data = useStickyData(enabledAssets.step === "loaded" ? enabledAssets.data : null);
1402
1501
  const busy = busyKey !== null;
1502
+ const assets = (data?.assets ?? []).filter((a) => resolveChain(a.chain) === selectedChain);
1503
+ const isStellarSelected = selectedChain === "STELLAR";
1403
1504
  return /* @__PURE__ */ jsxs(
1404
1505
  "div",
1405
1506
  {
@@ -1408,8 +1509,9 @@ function EnabledAssetsModalTemplate({
1408
1509
  style: cssVars,
1409
1510
  onClick: (e) => e.stopPropagation(),
1410
1511
  children: [
1512
+ isLoading && data && /* @__PURE__ */ jsx(BusyOverlay, { label: "Refreshing assets\u2026" }),
1411
1513
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
1412
- /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Trustlines" }),
1514
+ /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Assets" }),
1413
1515
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
1414
1516
  /* @__PURE__ */ jsx(
1415
1517
  "button",
@@ -1446,8 +1548,12 @@ function EnabledAssetsModalTemplate({
1446
1548
  /* @__PURE__ */ jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
1447
1549
  ] })
1448
1550
  ] }),
1449
- walletAddress && /* @__PURE__ */ jsx("div", { className: "pollar-asset-address", children: cropAddress(walletAddress) }),
1450
- isLoading && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
1551
+ /* @__PURE__ */ jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain, disabled: isLoading || busy }),
1552
+ walletAddress && /* @__PURE__ */ jsxs("div", { className: "pollar-address-row", children: [
1553
+ /* @__PURE__ */ jsx("span", { className: "pollar-address", children: cropAddress(walletAddress) }),
1554
+ /* @__PURE__ */ jsx(CopyButton, { value: walletAddress, label: "Copy wallet address" })
1555
+ ] }),
1556
+ isLoading && !data && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
1451
1557
  /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
1452
1558
  /* @__PURE__ */ jsx("span", { children: "Loading\u2026" })
1453
1559
  ] }),
@@ -1458,8 +1564,8 @@ function EnabledAssetsModalTemplate({
1458
1564
  data.network,
1459
1565
  "."
1460
1566
  ] }),
1461
- data && data.assets.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No trustlines found." }),
1462
- data && data.assets.length > 0 && /* @__PURE__ */ jsx("div", { className: "pollar-asset-list", children: data.assets.map((a) => /* @__PURE__ */ jsx(
1567
+ data && assets.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No assets found on this network." }),
1568
+ data && assets.length > 0 && /* @__PURE__ */ jsx("div", { className: "pollar-asset-list", children: assets.map((a) => /* @__PURE__ */ jsx(
1463
1569
  AssetItem,
1464
1570
  {
1465
1571
  record: a,
@@ -1467,9 +1573,9 @@ function EnabledAssetsModalTemplate({
1467
1573
  disabled: busy && busyKey !== assetKey(a),
1468
1574
  onToggle: onToggleTrustline
1469
1575
  },
1470
- assetKey(a)
1576
+ rowKey(a)
1471
1577
  )) }),
1472
- /* @__PURE__ */ jsx("button", { className: "pollar-asset-add-custom", onClick: onAddCustom, disabled: busy, children: "+ Add custom trustline" }),
1578
+ isStellarSelected && /* @__PURE__ */ jsx("button", { className: "pollar-asset-add-custom", onClick: onAddCustom, disabled: busy, children: "+ Add custom trustline" }),
1473
1579
  /* @__PURE__ */ jsx(PollarModalFooter, {})
1474
1580
  ]
1475
1581
  }
@@ -1583,9 +1689,14 @@ function assetKey2(record) {
1583
1689
  return record.code + (record.issuer ?? "");
1584
1690
  }
1585
1691
  function EnabledAssetsModal({ onClose }) {
1586
- const { enabledAssets, refreshAssets, setTrustline, wallet, styles } = usePollar();
1587
- const walletAddress = wallet?.address ?? "";
1692
+ const { enabledAssets, refreshAssets, setTrustline, wallets, styles } = usePollar();
1588
1693
  const { theme = "light", accentColor = "#005DB4" } = styles;
1694
+ const { chains } = useChains();
1695
+ const [selectedChain, setSelectedChain] = useState(null);
1696
+ useEffect(() => {
1697
+ if (selectedChain === null && chains.length > 0) setSelectedChain(chains[0]);
1698
+ }, [chains, selectedChain]);
1699
+ const walletAddress = addressForChain(wallets, selectedChain);
1589
1700
  const [view, setView] = useState("list");
1590
1701
  const [busyKey, setBusyKey] = useState(null);
1591
1702
  const [actionError, setActionError] = useState(null);
@@ -1614,7 +1725,7 @@ function EnabledAssetsModal({ onClose }) {
1614
1725
  void runAction(
1615
1726
  assetKey2(record),
1616
1727
  { code: record.code, issuer: record.issuer ?? "" },
1617
- { ...removing ? { limit: "0" } : {}, sponsored: record.sponsored ?? false }
1728
+ { ...removing ? { limit: "0" } : {} }
1618
1729
  );
1619
1730
  },
1620
1731
  [runAction]
@@ -1624,7 +1735,7 @@ function EnabledAssetsModal({ onClose }) {
1624
1735
  const ok = await runAction(
1625
1736
  "custom",
1626
1737
  { code: input.code, issuer: input.issuer },
1627
- { ...input.limit ? { limit: input.limit } : {}, sponsored: false }
1738
+ { ...input.limit ? { limit: input.limit } : {}, skipSponsorship: true }
1628
1739
  );
1629
1740
  if (ok) setView("list");
1630
1741
  },
@@ -1637,6 +1748,9 @@ function EnabledAssetsModal({ onClose }) {
1637
1748
  accentColor,
1638
1749
  enabledAssets,
1639
1750
  walletAddress,
1751
+ chains,
1752
+ selectedChain,
1753
+ onSelectChain: setSelectedChain,
1640
1754
  busyKey,
1641
1755
  actionError,
1642
1756
  onRefresh: () => refreshAssets(),
@@ -3355,10 +3469,18 @@ var QRCode = forwardRef(function QRCode2({ bgColor = "#FFFFFF", fgColor = "#0000
3355
3469
  }
3356
3470
  );
3357
3471
  });
3472
+ var CHAIN_NAME = {
3473
+ STELLAR: "Stellar",
3474
+ POLYGON: "Polygon",
3475
+ SOLANA: "Solana"
3476
+ };
3358
3477
  function ReceiveModalTemplate({
3359
3478
  theme,
3360
3479
  accentColor,
3361
3480
  walletAddress,
3481
+ chains,
3482
+ selectedChain,
3483
+ onSelectChain,
3362
3484
  copied,
3363
3485
  onCopy,
3364
3486
  onClose
@@ -3381,6 +3503,7 @@ function ReceiveModalTemplate({
3381
3503
  "--pollar-input-border-radius": "0.5rem",
3382
3504
  "--pollar-card-border-radius": "10px"
3383
3505
  };
3506
+ const chainName = selectedChain ? CHAIN_NAME[selectedChain] ?? selectedChain : "wallet";
3384
3507
  return /* @__PURE__ */ jsxs(
3385
3508
  "div",
3386
3509
  {
@@ -3393,9 +3516,16 @@ function ReceiveModalTemplate({
3393
3516
  /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Receive" }),
3394
3517
  /* @__PURE__ */ jsx("div", { className: "pollar-modal-header-actions", children: /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) }) })
3395
3518
  ] }),
3519
+ /* @__PURE__ */ jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain }),
3396
3520
  walletAddress ? /* @__PURE__ */ jsxs(Fragment, { children: [
3397
3521
  /* @__PURE__ */ jsx("div", { className: "pollar-receive-qr", children: /* @__PURE__ */ jsx(QRCode, { value: walletAddress, size: 180, fgColor: isDark ? "#ffffff" : "#111827", bgColor: "transparent" }) }),
3398
- /* @__PURE__ */ jsx("p", { className: "pollar-receive-instructions", children: "Share your Stellar address to receive any asset. Only send Stellar assets to this address." }),
3522
+ /* @__PURE__ */ jsxs("p", { className: "pollar-receive-instructions", children: [
3523
+ "Share your ",
3524
+ chainName,
3525
+ " address to receive any asset. Only send ",
3526
+ chainName,
3527
+ " assets to this address. Funds sent from another network are lost."
3528
+ ] }),
3399
3529
  /* @__PURE__ */ jsxs("div", { className: "pollar-receive-address-row", children: [
3400
3530
  /* @__PURE__ */ jsx("span", { className: "pollar-receive-address", children: walletAddress }),
3401
3531
  /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-receive-copy-btn", onClick: onCopy, "aria-label": "Copy address", children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -3436,11 +3566,16 @@ function ReceiveModalTemplate({
3436
3566
  );
3437
3567
  }
3438
3568
  function ReceiveModal({ onClose }) {
3439
- const { wallet, styles } = usePollar();
3440
- const walletAddress = wallet?.address ?? "";
3569
+ const { wallets, styles } = usePollar();
3441
3570
  const { theme = "light", accentColor = "#005DB4" } = styles;
3442
3571
  const [copied, setCopied] = useState(false);
3443
3572
  const copyTimerRef = useRef(null);
3573
+ const { chains } = useChains();
3574
+ const [selectedChain, setSelectedChain] = useState(null);
3575
+ useEffect(() => {
3576
+ if (selectedChain === null && chains.length > 0) setSelectedChain(chains[0]);
3577
+ }, [chains, selectedChain]);
3578
+ const walletAddress = addressForChain(wallets, selectedChain);
3444
3579
  useEffect(
3445
3580
  () => () => {
3446
3581
  if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
@@ -3464,6 +3599,12 @@ function ReceiveModal({ onClose }) {
3464
3599
  theme,
3465
3600
  accentColor,
3466
3601
  walletAddress,
3602
+ chains,
3603
+ selectedChain,
3604
+ onSelectChain: (chain) => {
3605
+ setCopied(false);
3606
+ setSelectedChain(chain);
3607
+ },
3467
3608
  copied,
3468
3609
  onCopy: handleCopy,
3469
3610
  onClose
@@ -3709,6 +3850,7 @@ function TxStatusView({
3709
3850
  ] });
3710
3851
  }
3711
3852
  function formatBalance(balance) {
3853
+ if (balance === null) return "\u2014";
3712
3854
  const n = parseFloat(balance);
3713
3855
  return isNaN(n) ? balance : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
3714
3856
  }
@@ -3722,6 +3864,11 @@ function SendModalTemplate({
3722
3864
  txTitle,
3723
3865
  assets,
3724
3866
  selectedAsset,
3867
+ chains,
3868
+ selectedChain,
3869
+ walletAddress,
3870
+ canSendOnChain,
3871
+ onSelectChain,
3725
3872
  amount,
3726
3873
  destination,
3727
3874
  formError,
@@ -3765,7 +3912,7 @@ function SendModalTemplate({
3765
3912
  "--pollar-card-border-radius": "10px"
3766
3913
  };
3767
3914
  const selectedKey = selectedAsset ? assetKey3(selectedAsset) : "";
3768
- const canSubmit = !!selectedAsset && !!amount && !!destination.trim() && !isLoadingBalance;
3915
+ const canSubmit = canSendOnChain && !!selectedAsset && !!amount && !!destination.trim() && !isLoadingBalance;
3769
3916
  const title = step === "form" ? "Send" : txTitle;
3770
3917
  return /* @__PURE__ */ jsxs(
3771
3918
  "div",
@@ -3817,6 +3964,12 @@ function SendModalTemplate({
3817
3964
  ] })
3818
3965
  ] }),
3819
3966
  step === "form" && /* @__PURE__ */ jsxs(Fragment, { children: [
3967
+ /* @__PURE__ */ jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain, disabled: isLoadingBalance }),
3968
+ walletAddress && /* @__PURE__ */ jsxs("div", { className: "pollar-address-row", children: [
3969
+ /* @__PURE__ */ jsx("span", { className: "pollar-address", children: cropAddress(walletAddress) }),
3970
+ /* @__PURE__ */ jsx(CopyButton, { value: walletAddress, label: "Copy wallet address" })
3971
+ ] }),
3972
+ !canSendOnChain && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Sending is not available on this network yet." }),
3820
3973
  /* @__PURE__ */ jsx(
3821
3974
  AssetSelect,
3822
3975
  {
@@ -3827,7 +3980,9 @@ function SendModalTemplate({
3827
3980
  options: assets.map((a) => ({
3828
3981
  key: assetKey3(a),
3829
3982
  code: a.code,
3830
- available: a.available,
3983
+ // Unreadable (null) drops the "— X available" suffix instead of
3984
+ // claiming a zero balance.
3985
+ available: a.available ?? void 0,
3831
3986
  enabledInApp: a.enabledInApp
3832
3987
  })),
3833
3988
  onChange: (key) => {
@@ -3906,9 +4061,11 @@ function SendModal({ onClose }) {
3906
4061
  walletBalance,
3907
4062
  refreshWalletBalance,
3908
4063
  buildTx,
4064
+ sendPayment,
3909
4065
  signAndSubmitTx,
3910
4066
  tx: transaction,
3911
4067
  wallet,
4068
+ wallets,
3912
4069
  network,
3913
4070
  styles
3914
4071
  } = usePollar();
@@ -3922,6 +4079,14 @@ function SendModal({ onClose }) {
3922
4079
  const [copied, setCopied] = useState(false);
3923
4080
  const [formError, setFormError] = useState("");
3924
4081
  const copyTimerRef = useRef(null);
4082
+ const { chains } = useChains();
4083
+ const [selectedChain, setSelectedChain] = useState(null);
4084
+ useEffect(() => {
4085
+ if (selectedChain === null && chains.length > 0) setSelectedChain(chains[0]);
4086
+ }, [chains, selectedChain]);
4087
+ const walletAddress = addressForChain(wallets, selectedChain);
4088
+ const canSendOnChain = selectedChain === "STELLAR" || selectedChain === "SOLANA";
4089
+ const isBaseUnitChain = selectedChain === "SOLANA";
3925
4090
  useEffect(() => {
3926
4091
  void refreshWalletBalance();
3927
4092
  }, [refreshWalletBalance]);
@@ -3932,18 +4097,24 @@ function SendModal({ onClose }) {
3932
4097
  []
3933
4098
  );
3934
4099
  const balanceData = walletBalance.step === "loaded" ? walletBalance.data : null;
3935
- const allAssets = (balanceData?.balances ?? []).filter((b) => b.chain === void 0 || b.chain === "STELLAR");
4100
+ const allAssets = (balanceData?.balances ?? []).filter((b) => resolveChain(b.chain) === selectedChain);
3936
4101
  const sortedAssets = [
3937
4102
  ...allAssets.filter((b) => b.enabledInApp),
3938
- ...allAssets.filter((b) => !b.enabledInApp && (b.type === "native" || parseFloat(b.balance) > 0))
4103
+ // An unreadable balance (null) is not a positive one, so it stays out.
4104
+ ...allAssets.filter((b) => !b.enabledInApp && (b.type === "native" || parseFloat(b.balance ?? "0") > 0))
3939
4105
  ];
3940
4106
  useEffect(() => {
4107
+ const stranded = selectedAsset !== null && resolveChain(selectedAsset.chain) !== selectedChain;
4108
+ if (stranded) {
4109
+ setSelectedAsset(sortedAssets[0] ?? null);
4110
+ return;
4111
+ }
3941
4112
  if (!selectedAsset && sortedAssets.length > 0) setSelectedAsset(sortedAssets[0]);
3942
- }, [sortedAssets, selectedAsset]);
4113
+ }, [sortedAssets, selectedAsset, selectedChain]);
3943
4114
  const hash = transaction.step === "success" ? transaction.hash : null;
3944
4115
  const buildData = "buildData" in transaction ? transaction.buildData : null;
3945
4116
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
3946
- const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
4117
+ const explorerUrl = !hash ? null : selectedChain === "SOLANA" ? `https://explorer.solana.com/tx/${hash}${explorerNetwork === "testnet" ? "?cluster=devnet" : ""}` : `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}`;
3947
4118
  const IN_FLIGHT_STEPS3 = [
3948
4119
  "building",
3949
4120
  "signing",
@@ -3957,6 +4128,10 @@ function SendModal({ onClose }) {
3957
4128
  const txTitle = isInProgress ? "Sending\u2026" : transaction.step === "success" ? "Sent!" : transaction.step === "error" ? "Send failed" : "Confirm Send";
3958
4129
  async function handleSubmit() {
3959
4130
  setFormError("");
4131
+ if (!canSendOnChain) {
4132
+ setFormError("Sending is not available on this network yet.");
4133
+ return;
4134
+ }
3960
4135
  if (!selectedAsset) {
3961
4136
  setFormError("Select an asset");
3962
4137
  return;
@@ -3966,7 +4141,7 @@ function SendModal({ onClose }) {
3966
4141
  setFormError("Enter a valid amount");
3967
4142
  return;
3968
4143
  }
3969
- if (parsed > parseFloat(selectedAsset.available)) {
4144
+ if (parsed > parseFloat(selectedAsset.available ?? "0")) {
3970
4145
  setFormError("Insufficient balance");
3971
4146
  return;
3972
4147
  }
@@ -3974,7 +4149,32 @@ function SendModal({ onClose }) {
3974
4149
  setFormError("Enter a destination address");
3975
4150
  return;
3976
4151
  }
4152
+ const isNativeAsset = selectedAsset.type === "native";
4153
+ if (isBaseUnitChain && !isNativeAsset && (!selectedAsset.issuer || selectedAsset.decimals === void 0)) {
4154
+ setFormError("This token is missing its mint or decimals and cannot be sent.");
4155
+ return;
4156
+ }
4157
+ let sendAmount = amount;
4158
+ if (isBaseUnitChain) {
4159
+ try {
4160
+ sendAmount = toBaseUnits(amount, selectedAsset.decimals ?? 9);
4161
+ } catch (e) {
4162
+ setFormError(e instanceof Error ? e.message : "Invalid amount");
4163
+ return;
4164
+ }
4165
+ }
3977
4166
  setStep("tx");
4167
+ if (selectedChain === "SOLANA") {
4168
+ await sendPayment({
4169
+ chain: "SOLANA",
4170
+ destination: destination.trim(),
4171
+ amount: sendAmount,
4172
+ // Native SOL carries no mint; an SPL token's mint rides in `issuer`,
4173
+ // which the guard above proved is present.
4174
+ ...isNativeAsset ? {} : { mint: selectedAsset.issuer }
4175
+ });
4176
+ return;
4177
+ }
3978
4178
  await buildTx("payment", { destination: destination.trim(), amount, asset: assetParam(selectedAsset) });
3979
4179
  }
3980
4180
  function handleSignAndSend() {
@@ -4012,6 +4212,11 @@ function SendModal({ onClose }) {
4012
4212
  txTitle,
4013
4213
  assets: sortedAssets,
4014
4214
  selectedAsset,
4215
+ chains,
4216
+ selectedChain,
4217
+ walletAddress,
4218
+ canSendOnChain,
4219
+ onSelectChain: setSelectedChain,
4015
4220
  amount,
4016
4221
  destination,
4017
4222
  formError,
@@ -4438,11 +4643,19 @@ function SwapModal({ onClose }) {
4438
4643
  const assetRecords = enabledAssets.step === "loaded" ? enabledAssets.data.assets : [];
4439
4644
  const isLoadingData = walletBalance.step === "loading" || enabledAssets.step === "loading";
4440
4645
  const sellOptions = balances.filter(
4441
- (b) => b.type != null && (b.type === "native" || !b.trustlineRemoved)
4442
- ).map((b) => ({ ref: toRef(b), code: b.code, issuer: b.issuer, available: b.available, enabledInApp: b.enabledInApp }));
4646
+ (b) => (b.chain === void 0 || b.chain === "STELLAR") && (b.type === "native" || (b.type === "credit_alphanum4" || b.type === "credit_alphanum12") && !b.trustlineRemoved)
4647
+ ).map((b) => ({
4648
+ ref: toRef(b),
4649
+ code: b.code,
4650
+ issuer: b.issuer,
4651
+ available: b.available ?? void 0,
4652
+ enabledInApp: b.enabledInApp
4653
+ }));
4443
4654
  const buyKeyOfSell = selectedSell ? `${selectedSell.code}:${selectedSell.issuer ?? "native"}` : "";
4444
4655
  const optKey = (o) => `${o.code}:${o.issuer ?? "native"}`;
4445
- const enabledBuy = assetRecords.map((a) => ({
4656
+ const enabledBuy = assetRecords.filter(
4657
+ (a) => (a.chain === void 0 || a.chain === "STELLAR") && (a.type === "native" || a.type === "credit_alphanum4" || a.type === "credit_alphanum12")
4658
+ ).map((a) => ({
4446
4659
  ref: toRef(a),
4447
4660
  code: a.code,
4448
4661
  issuer: a.issuer,
@@ -4743,15 +4956,13 @@ function EarnModal({ onClose }) {
4743
4956
  if (!selectedOpportunity) return null;
4744
4957
  const balances = walletBalance.step === "loaded" ? walletBalance.data.balances : [];
4745
4958
  const issuer = selectedOpportunity.asset.issuer;
4746
- const rec = balances.find(
4747
- (b) => issuer === null ? b.type === "native" : b.code === assetCode && b.issuer === issuer
4748
- );
4959
+ const rec = balances.find((b) => issuer === null ? b.type === "native" : b.code === assetCode && b.issuer === issuer);
4749
4960
  return rec ? rec.available : null;
4750
4961
  })();
4751
4962
  const depositAssetRecord = (() => {
4752
4963
  if (!selectedOpportunity?.asset.issuer || enabledAssets.step !== "loaded") return void 0;
4753
4964
  return enabledAssets.data.assets.find(
4754
- (a) => a.code === assetCode && a.issuer === selectedOpportunity.asset.issuer
4965
+ (a) => (a.chain === void 0 || a.chain === "STELLAR") && a.code === assetCode && a.issuer === selectedOpportunity.asset.issuer
4755
4966
  );
4756
4967
  })();
4757
4968
  const depositNeedsTrustline = tab === "deposit" && !smartUnsupported && !!selectedOpportunity?.asset.issuer && !depositAssetRecord?.trustlineEstablished;
@@ -4807,10 +5018,7 @@ function EarnModal({ onClose }) {
4807
5018
  }
4808
5019
  setStep("tx");
4809
5020
  if (tab === "deposit" && depositNeedsTrustline && selectedOpportunity?.asset.issuer) {
4810
- const tl = await setTrustline(
4811
- { code: assetCode, issuer: selectedOpportunity.asset.issuer },
4812
- depositAssetRecord?.sponsored ? { sponsored: true } : void 0
4813
- );
5021
+ const tl = await setTrustline({ code: assetCode, issuer: selectedOpportunity.asset.issuer });
4814
5022
  if (tl.status === "error") {
4815
5023
  setFormError(`Trustline for ${assetCode} failed: ${tl.details ?? "unknown error"}`);
4816
5024
  setStep("form");
@@ -5425,6 +5633,12 @@ function TransactionModal({ onClose }) {
5425
5633
  ) });
5426
5634
  }
5427
5635
  var PAGE_SIZE = 10;
5636
+ function explorerUrlFor(chain, hash, network) {
5637
+ if (chain === "SOLANA") {
5638
+ return `https://explorer.solana.com/tx/${hash}${network === "testnet" ? "?cluster=devnet" : ""}`;
5639
+ }
5640
+ return `https://stellar.expert/explorer/${network === "testnet" ? "testnet" : "public"}/tx/${hash}`;
5641
+ }
5428
5642
  function StatusBadge({ status }) {
5429
5643
  return /* @__PURE__ */ jsx("span", { className: "pollar-hist-item-badge", "data-status": status, children: status });
5430
5644
  }
@@ -5463,6 +5677,10 @@ function TxHistoryModalTemplate({
5463
5677
  accentColor,
5464
5678
  txHistory,
5465
5679
  offset,
5680
+ chains,
5681
+ selectedChain,
5682
+ walletAddress,
5683
+ onSelectChain,
5466
5684
  onRefresh,
5467
5685
  onPrev,
5468
5686
  onNext,
@@ -5538,6 +5756,11 @@ function TxHistoryModalTemplate({
5538
5756
  /* @__PURE__ */ jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
5539
5757
  ] })
5540
5758
  ] }),
5759
+ /* @__PURE__ */ jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain, disabled: isLoading }),
5760
+ walletAddress && /* @__PURE__ */ jsxs("div", { className: "pollar-address-row", children: [
5761
+ /* @__PURE__ */ jsx("span", { className: "pollar-address", children: cropAddress(walletAddress) }),
5762
+ /* @__PURE__ */ jsx(CopyButton, { value: walletAddress, label: "Copy wallet address" })
5763
+ ] }),
5541
5764
  /* @__PURE__ */ jsxs("div", { className: "pollar-hist-list", children: [
5542
5765
  txHistory.step === "idle" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Click Refresh to load transactions." }),
5543
5766
  isLoading && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
@@ -5548,7 +5771,7 @@ function TxHistoryModalTemplate({
5548
5771
  txHistory.step === "loaded" && records.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No transactions yet." }),
5549
5772
  records.map((record) => {
5550
5773
  const hash = typeof record.hash === "string" && record.hash.length > 0 ? record.hash : void 0;
5551
- const explorerUrl = hash ? `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${hash}` : void 0;
5774
+ const explorerUrl = hash ? explorerUrlFor(record.chain, hash, record.network) : void 0;
5552
5775
  const asset = typeof record.details?.asset === "string" ? record.details.asset : void 0;
5553
5776
  const colon = asset ? asset.indexOf(":") : -1;
5554
5777
  const trustline = record.operation === "change_trust" && asset && colon > 0 ? {
@@ -5582,10 +5805,11 @@ function TxHistoryModalTemplate({
5582
5805
  "\xB7 ",
5583
5806
  record.details.sponsored ? "Sponsored" : "Self-paid"
5584
5807
  ] }),
5585
- record.feeXlm && /* @__PURE__ */ jsxs("span", { children: [
5808
+ record.fee && /* @__PURE__ */ jsxs("span", { children: [
5586
5809
  "\xB7 ",
5587
- record.feeXlm,
5588
- " XLM"
5810
+ record.fee.amount,
5811
+ " ",
5812
+ record.fee.unit
5589
5813
  ] })
5590
5814
  ] }),
5591
5815
  /* @__PURE__ */ jsxs("div", { className: "pollar-hist-item-footer", children: [
@@ -5601,7 +5825,7 @@ function TxHistoryModalTemplate({
5601
5825
  href: explorerUrl,
5602
5826
  target: "_blank",
5603
5827
  rel: "noopener noreferrer",
5604
- "aria-label": "View on Stellar Explorer",
5828
+ "aria-label": "View on block explorer",
5605
5829
  children: /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
5606
5830
  /* @__PURE__ */ jsx(
5607
5831
  "path",
@@ -5650,19 +5874,29 @@ function TxHistoryModalTemplate({
5650
5874
  }
5651
5875
  var PAGE_SIZE2 = 10;
5652
5876
  function TxHistoryModal({ onClose }) {
5653
- const { getClient, styles, txHistory } = usePollar();
5877
+ const { getClient, styles, txHistory, wallets } = usePollar();
5654
5878
  const { theme = "light", accentColor = "#005DB4" } = styles;
5655
5879
  const [offset, setOffset] = useState(0);
5880
+ const { chains } = useChains();
5881
+ const [selectedChain, setSelectedChain] = useState(null);
5882
+ useEffect(() => {
5883
+ if (selectedChain === null && chains.length > 0) setSelectedChain(chains[0]);
5884
+ }, [chains, selectedChain]);
5885
+ const walletAddress = addressForChain(wallets, selectedChain);
5656
5886
  const load = useCallback(
5657
- (nextOffset) => {
5887
+ (nextOffset, chain) => {
5658
5888
  setOffset(nextOffset);
5659
- void getClient().fetchTxHistory({ limit: PAGE_SIZE2, offset: nextOffset });
5889
+ void getClient().fetchTxHistory({ limit: PAGE_SIZE2, offset: nextOffset, chain });
5660
5890
  },
5661
5891
  [getClient]
5662
5892
  );
5663
5893
  useEffect(() => {
5664
- load(0);
5665
- }, [load]);
5894
+ if (selectedChain) load(0, selectedChain);
5895
+ }, [selectedChain, load]);
5896
+ const onSelectChain = (chain) => setSelectedChain(chain);
5897
+ const paged = (nextOffset) => {
5898
+ if (selectedChain) load(nextOffset, selectedChain);
5899
+ };
5666
5900
  return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsx(
5667
5901
  TxHistoryModalTemplate,
5668
5902
  {
@@ -5670,47 +5904,48 @@ function TxHistoryModal({ onClose }) {
5670
5904
  accentColor,
5671
5905
  txHistory,
5672
5906
  offset,
5673
- onRefresh: () => load(offset),
5674
- onPrev: () => load(Math.max(0, offset - PAGE_SIZE2)),
5675
- onNext: () => load(offset + PAGE_SIZE2),
5907
+ chains,
5908
+ selectedChain,
5909
+ walletAddress,
5910
+ onSelectChain,
5911
+ onRefresh: () => paged(offset),
5912
+ onPrev: () => paged(Math.max(0, offset - PAGE_SIZE2)),
5913
+ onNext: () => paged(offset + PAGE_SIZE2),
5676
5914
  onClose
5677
5915
  }
5678
5916
  ) });
5679
5917
  }
5680
- function formatBalance2(balance) {
5918
+ function formatBalance2(balance, decimals = 7) {
5919
+ if (balance === null) return "\u2014";
5920
+ const digits = Math.min(decimals, 7);
5681
5921
  const n = parseFloat(balance);
5682
- return isNaN(n) ? balance : n.toLocaleString(void 0, { minimumFractionDigits: 7, maximumFractionDigits: 7 });
5922
+ return isNaN(n) ? balance : n.toLocaleString(void 0, { minimumFractionDigits: digits, maximumFractionDigits: digits });
5683
5923
  }
5684
- function cropAddress2(address) {
5685
- if (address.length <= 16) return address;
5686
- return `${address.slice(0, 8)}...${address.slice(-8)}`;
5687
- }
5688
- var CHAIN_TAG = {
5689
- STELLAR: { label: "Stellar", color: "#7d00ff" },
5690
- POLYGON: { label: "Polygon", color: "#8247e5" },
5691
- SOLANA: { label: "Solana", color: "#14f195" }
5692
- };
5693
- function ChainTag({ chain }) {
5694
- const tag = CHAIN_TAG[chain] ?? { label: chain, color: "#6b7280" };
5695
- return /* @__PURE__ */ jsx("span", { className: "pollar-bal-chain-tag", style: { "--pollar-chain-color": tag.color }, children: tag.label });
5924
+ function faucetFor(record) {
5925
+ if (record.type === "native") return { url: "https://faucet.solana.com/", label: "Get test SOL" };
5926
+ if (record.code === "USDC") return { url: "https://faucet.circle.com/", label: "Get test USDC" };
5927
+ return null;
5696
5928
  }
5697
- function BalanceItem({ record, showChain }) {
5929
+ function BalanceItem({ record, faucet }) {
5698
5930
  const balanceDiffers = record.balance !== record.available;
5699
5931
  return /* @__PURE__ */ jsxs("div", { className: "pollar-bal-item", children: [
5700
5932
  /* @__PURE__ */ jsxs("div", { className: "pollar-bal-asset-info", children: [
5701
- /* @__PURE__ */ jsxs("span", { className: "pollar-bal-asset-code-row", children: [
5702
- /* @__PURE__ */ jsx("span", { className: "pollar-bal-asset", children: record.code }),
5703
- showChain && record.chain && /* @__PURE__ */ jsx(ChainTag, { chain: record.chain })
5704
- ] }),
5705
- record.issuer && /* @__PURE__ */ jsxs("span", { className: "pollar-bal-issuer", children: [
5706
- /* @__PURE__ */ jsx("span", { className: "pollar-bal-issuer-addr", children: cropAddress2(record.issuer) }),
5933
+ /* @__PURE__ */ jsx("span", { className: "pollar-bal-asset-code-row", children: /* @__PURE__ */ jsx("span", { className: "pollar-bal-asset", children: record.code }) }),
5934
+ record.issuer && /* @__PURE__ */ jsxs("span", { className: "pollar-issuer", children: [
5935
+ /* @__PURE__ */ jsx("span", { className: "pollar-issuer-addr", children: cropAddress(record.issuer) }),
5707
5936
  /* @__PURE__ */ jsx(CopyButton, { value: record.issuer, label: "Copy issuer address", className: "pollar-copy-btn-sm" })
5937
+ ] }),
5938
+ faucet && /* @__PURE__ */ jsxs("span", { className: "pollar-bal-faucet-hint", children: [
5939
+ "Need more?",
5940
+ " ",
5941
+ /* @__PURE__ */ jsx("a", { href: faucet.url, target: "_blank", rel: "noopener noreferrer", children: faucet.label }),
5942
+ /* @__PURE__ */ jsx("span", { className: "pollar-bal-faucet-net", children: " (devnet)" })
5708
5943
  ] })
5709
5944
  ] }),
5710
5945
  /* @__PURE__ */ jsxs("div", { className: "pollar-bal-amounts", children: [
5711
- /* @__PURE__ */ jsx("span", { className: "pollar-bal-amount", children: formatBalance2(record.balance) }),
5946
+ /* @__PURE__ */ jsx("span", { className: "pollar-bal-amount", children: formatBalance2(record.balance, record.decimals) }),
5712
5947
  balanceDiffers && /* @__PURE__ */ jsxs("span", { className: "pollar-bal-available", children: [
5713
- formatBalance2(record.available),
5948
+ formatBalance2(record.available, record.decimals),
5714
5949
  " available"
5715
5950
  ] })
5716
5951
  ] })
@@ -5721,6 +5956,10 @@ function WalletBalanceModalTemplate({
5721
5956
  accentColor,
5722
5957
  walletBalance,
5723
5958
  walletAddress,
5959
+ chains,
5960
+ selectedChain,
5961
+ network,
5962
+ onSelectChain,
5724
5963
  onRefresh,
5725
5964
  onClose
5726
5965
  }) {
@@ -5743,8 +5982,11 @@ function WalletBalanceModalTemplate({
5743
5982
  "--pollar-card-border-radius": "10px"
5744
5983
  };
5745
5984
  const isLoading = walletBalance.step === "loading";
5746
- const data = walletBalance.step === "loaded" ? walletBalance.data : null;
5985
+ const data = useStickyData(walletBalance.step === "loaded" ? walletBalance.data : null);
5986
+ const balances = (data?.balances ?? []).filter((b) => resolveChain(b.chain) === selectedChain);
5987
+ const showFaucets = selectedChain === "SOLANA" && network === "testnet";
5747
5988
  return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-bal-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
5989
+ isLoading && data && /* @__PURE__ */ jsx(BusyOverlay, { label: "Refreshing balances\u2026" }),
5748
5990
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
5749
5991
  /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Wallet Balance" }),
5750
5992
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
@@ -5783,11 +6025,12 @@ function WalletBalanceModalTemplate({
5783
6025
  /* @__PURE__ */ jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
5784
6026
  ] })
5785
6027
  ] }),
5786
- walletAddress && /* @__PURE__ */ jsxs("div", { className: "pollar-bal-address-row", children: [
5787
- /* @__PURE__ */ jsx("span", { className: "pollar-bal-address", children: cropAddress2(walletAddress) }),
6028
+ /* @__PURE__ */ jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain, disabled: isLoading }),
6029
+ walletAddress && /* @__PURE__ */ jsxs("div", { className: "pollar-address-row", children: [
6030
+ /* @__PURE__ */ jsx("span", { className: "pollar-address", children: cropAddress(walletAddress) }),
5788
6031
  /* @__PURE__ */ jsx(CopyButton, { value: walletAddress, label: "Copy wallet address" })
5789
6032
  ] }),
5790
- isLoading && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
6033
+ isLoading && !data && /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
5791
6034
  /* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
5792
6035
  /* @__PURE__ */ jsx("span", { children: "Loading\u2026" })
5793
6036
  ] }),
@@ -5797,15 +6040,27 @@ function WalletBalanceModalTemplate({
5797
6040
  data.network,
5798
6041
  "."
5799
6042
  ] }),
5800
- data?.exists && data.balances.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No balances found." }),
5801
- data?.exists && data.balances.length > 0 && /* @__PURE__ */ jsx("div", { className: "pollar-bal-list", children: data.balances.map((b) => /* @__PURE__ */ jsx(BalanceItem, { record: b, showChain: data.multichain === true }, (b.chain ?? "") + b.code + (b.issuer ?? ""))) }),
6043
+ data?.exists && balances.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No balances found on this network." }),
6044
+ data?.exists && balances.length > 0 && /* @__PURE__ */ jsx("div", { className: "pollar-bal-list", children: balances.map((b) => /* @__PURE__ */ jsx(
6045
+ BalanceItem,
6046
+ {
6047
+ record: b,
6048
+ faucet: showFaucets ? faucetFor(b) : null
6049
+ },
6050
+ (b.chain ?? "") + b.code + (b.issuer ?? "")
6051
+ )) }),
5802
6052
  /* @__PURE__ */ jsx(PollarModalFooter, {})
5803
6053
  ] });
5804
6054
  }
5805
6055
  function WalletBalanceModal({ onClose }) {
5806
- const { walletBalance, refreshWalletBalance, wallet, styles } = usePollar();
5807
- const walletAddress = wallet?.address ?? "";
6056
+ const { walletBalance, refreshWalletBalance, wallets, network, styles } = usePollar();
5808
6057
  const { theme = "light", accentColor = "#005DB4" } = styles;
6058
+ const { chains } = useChains();
6059
+ const [selectedChain, setSelectedChain] = useState(null);
6060
+ useEffect(() => {
6061
+ if (selectedChain === null && chains.length > 0) setSelectedChain(chains[0]);
6062
+ }, [chains, selectedChain]);
6063
+ const walletAddress = addressForChain(wallets, selectedChain);
5809
6064
  useEffect(() => {
5810
6065
  void refreshWalletBalance();
5811
6066
  }, [refreshWalletBalance]);
@@ -5816,6 +6071,10 @@ function WalletBalanceModal({ onClose }) {
5816
6071
  accentColor,
5817
6072
  walletBalance,
5818
6073
  walletAddress,
6074
+ chains,
6075
+ selectedChain,
6076
+ network,
6077
+ onSelectChain: setSelectedChain,
5819
6078
  onRefresh: () => refreshWalletBalance(),
5820
6079
  onClose
5821
6080
  }
@@ -5920,6 +6179,9 @@ function PollarProvider({
5920
6179
  );
5921
6180
  const [configRetry, setConfigRetry] = useState(0);
5922
6181
  const retryConfig = useCallback(() => setConfigRetry((n) => n + 1), []);
6182
+ const appConfigKey = appConfigProp === void 0 ? "" : JSON.stringify(appConfigProp);
6183
+ const appConfigPropRef = useRef(appConfigProp);
6184
+ appConfigPropRef.current = appConfigProp;
5923
6185
  useEffect(() => {
5924
6186
  return pollarClient.onTransactionStateChange(setTransaction);
5925
6187
  }, [pollarClient]);
@@ -5983,7 +6245,9 @@ function PollarProvider({
5983
6245
  setModalErrorLogger(pollarClient.getLogger());
5984
6246
  }, [pollarClient]);
5985
6247
  useEffect(() => {
5986
- if (appConfigProp !== void 0) {
6248
+ const localConfig = appConfigPropRef.current;
6249
+ if (localConfig !== void 0) {
6250
+ setResolvedConfig(localConfig ?? DEFAULT_APP_CONFIG);
5987
6251
  setConfigStatus("ready");
5988
6252
  return;
5989
6253
  }
@@ -6005,7 +6269,7 @@ function PollarProvider({
6005
6269
  return () => {
6006
6270
  cancelled = true;
6007
6271
  };
6008
- }, [pollarClient, appConfigProp, configRetry]);
6272
+ }, [pollarClient, appConfigKey, configRetry]);
6009
6273
  const [loginModalOpen, setLoginModalOpen] = useState(false);
6010
6274
  const [transactionModalOpen, setTransactionModalOpen] = useState(false);
6011
6275
  const [kycModalOpen, setKycModalOpen] = useState(false);
@@ -6032,6 +6296,7 @@ function PollarProvider({
6032
6296
  return {
6033
6297
  // session
6034
6298
  wallet: pollarClient.getWallet(),
6299
+ wallets: pollarClient.getWallets(),
6035
6300
  isAuthenticated: !!walletAddress,
6036
6301
  verified,
6037
6302
  // client
@@ -6048,6 +6313,7 @@ function PollarProvider({
6048
6313
  submitTx: (signedXdr) => pollarClient.submitTx(signedXdr),
6049
6314
  buildAndSignAndSubmitTx: (operation, params, options) => pollarClient.buildAndSignAndSubmitTx(operation, params, options),
6050
6315
  runTx: (operation, params, options) => pollarClient.runTx(operation, params, options),
6316
+ sendPayment: (params) => pollarClient.sendPayment(params),
6051
6317
  openTxModal: () => setTransactionModalOpen(true),
6052
6318
  // tx history
6053
6319
  txHistory,
@@ -6532,7 +6798,8 @@ function WalletButton() {
6532
6798
  openDistributionRulesModal,
6533
6799
  tx: transaction
6534
6800
  } = usePollar();
6535
- const walletAddress = wallet?.address ?? "";
6801
+ const { primaryAddress } = useChains();
6802
+ const walletAddress = primaryAddress || (wallet?.address ?? "");
6536
6803
  const walletType = wallet?.custody === "external" ? wallet.provider : null;
6537
6804
  const [open, setOpen] = useState(false);
6538
6805
  const [copied, setCopied] = useState(false);
@@ -6654,6 +6921,6 @@ function WalletButton() {
6654
6921
  );
6655
6922
  }
6656
6923
 
6657
- export { DistributionRulesModal, DistributionRulesModalTemplate, EarnModal, EnabledAssetsModal, EnabledAssetsModalTemplate, KycModal, KycModalTemplate, KycStatus, LoginModalTemplate, PollarProvider, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, RouteDisplay, SendModal, SendModalTemplate, SessionsModal, SessionsModalTemplate, SwapModal, SwapModalTemplate, TransactionModalTemplate, TxHistoryModalTemplate, TxStatusView, WalletBalanceModal, WalletBalanceModalTemplate, WalletButton, WalletButtonTemplate, createPollarAdapterHook, usePollar };
6924
+ export { ChainSelect, DistributionRulesModal, DistributionRulesModalTemplate, EarnModal, EnabledAssetsModal, EnabledAssetsModalTemplate, KycModal, KycModalTemplate, KycStatus, LoginModalTemplate, PollarProvider, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, RouteDisplay, SendModal, SendModalTemplate, SessionsModal, SessionsModalTemplate, SwapModal, SwapModalTemplate, TransactionModalTemplate, TxHistoryModalTemplate, TxStatusView, WalletBalanceModal, WalletBalanceModalTemplate, WalletButton, WalletButtonTemplate, addressForChain, chainsOf, createPollarAdapterHook, resolveChain, useChains, usePollar };
6658
6925
  //# sourceMappingURL=index.mjs.map
6659
6926
  //# sourceMappingURL=index.mjs.map