@pollar/react 0.7.1 → 0.8.1

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
@@ -31,7 +31,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
 
32
32
  // ../../node_modules/qr.js/lib/ErrorCorrectLevel.js
33
33
  var require_ErrorCorrectLevel = __commonJS({
34
- "../../node_modules/qr.js/lib/ErrorCorrectLevel.js"(exports$1, module) {
34
+ "../../node_modules/qr.js/lib/ErrorCorrectLevel.js"(exports, module) {
35
35
  module.exports = {
36
36
  L: 1,
37
37
  M: 0,
@@ -43,7 +43,7 @@ var require_ErrorCorrectLevel = __commonJS({
43
43
 
44
44
  // ../../node_modules/qr.js/lib/mode.js
45
45
  var require_mode = __commonJS({
46
- "../../node_modules/qr.js/lib/mode.js"(exports$1, module) {
46
+ "../../node_modules/qr.js/lib/mode.js"(exports, module) {
47
47
  module.exports = {
48
48
  MODE_NUMBER: 1 << 0,
49
49
  MODE_ALPHA_NUM: 1 << 1,
@@ -55,7 +55,7 @@ var require_mode = __commonJS({
55
55
 
56
56
  // ../../node_modules/qr.js/lib/8BitByte.js
57
57
  var require_BitByte = __commonJS({
58
- "../../node_modules/qr.js/lib/8BitByte.js"(exports$1, module) {
58
+ "../../node_modules/qr.js/lib/8BitByte.js"(exports, module) {
59
59
  var mode = require_mode();
60
60
  function QR8bitByte(data) {
61
61
  this.mode = mode.MODE_8BIT_BYTE;
@@ -77,7 +77,7 @@ var require_BitByte = __commonJS({
77
77
 
78
78
  // ../../node_modules/qr.js/lib/RSBlock.js
79
79
  var require_RSBlock = __commonJS({
80
- "../../node_modules/qr.js/lib/RSBlock.js"(exports$1, module) {
80
+ "../../node_modules/qr.js/lib/RSBlock.js"(exports, module) {
81
81
  var ECL = require_ErrorCorrectLevel();
82
82
  function QRRSBlock(totalCount, dataCount) {
83
83
  this.totalCount = totalCount;
@@ -326,7 +326,7 @@ var require_RSBlock = __commonJS({
326
326
 
327
327
  // ../../node_modules/qr.js/lib/BitBuffer.js
328
328
  var require_BitBuffer = __commonJS({
329
- "../../node_modules/qr.js/lib/BitBuffer.js"(exports$1, module) {
329
+ "../../node_modules/qr.js/lib/BitBuffer.js"(exports, module) {
330
330
  function QRBitBuffer() {
331
331
  this.buffer = new Array();
332
332
  this.length = 0;
@@ -361,7 +361,7 @@ var require_BitBuffer = __commonJS({
361
361
 
362
362
  // ../../node_modules/qr.js/lib/math.js
363
363
  var require_math = __commonJS({
364
- "../../node_modules/qr.js/lib/math.js"(exports$1, module) {
364
+ "../../node_modules/qr.js/lib/math.js"(exports, module) {
365
365
  var QRMath = {
366
366
  glog: function(n) {
367
367
  if (n < 1) {
@@ -399,7 +399,7 @@ var require_math = __commonJS({
399
399
 
400
400
  // ../../node_modules/qr.js/lib/Polynomial.js
401
401
  var require_Polynomial = __commonJS({
402
- "../../node_modules/qr.js/lib/Polynomial.js"(exports$1, module) {
402
+ "../../node_modules/qr.js/lib/Polynomial.js"(exports, module) {
403
403
  var math = require_math();
404
404
  function QRPolynomial(num, shift) {
405
405
  if (num.length == void 0) {
@@ -451,7 +451,7 @@ var require_Polynomial = __commonJS({
451
451
 
452
452
  // ../../node_modules/qr.js/lib/util.js
453
453
  var require_util = __commonJS({
454
- "../../node_modules/qr.js/lib/util.js"(exports$1, module) {
454
+ "../../node_modules/qr.js/lib/util.js"(exports, module) {
455
455
  var Mode = require_mode();
456
456
  var Polynomial = require_Polynomial();
457
457
  var math = require_math();
@@ -682,7 +682,7 @@ var require_util = __commonJS({
682
682
 
683
683
  // ../../node_modules/qr.js/lib/QRCode.js
684
684
  var require_QRCode = __commonJS({
685
- "../../node_modules/qr.js/lib/QRCode.js"(exports$1, module) {
685
+ "../../node_modules/qr.js/lib/QRCode.js"(exports, module) {
686
686
  var BitByte = require_BitByte();
687
687
  var RSBlock = require_RSBlock();
688
688
  var BitBuffer = require_BitBuffer();
@@ -1028,7 +1028,7 @@ var PollarModalFooter = () => {
1028
1028
  /* @__PURE__ */ jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
1029
1029
  /* @__PURE__ */ jsxs("span", { className: "pollar-footer-version", children: [
1030
1030
  "v",
1031
- "0.7.1"
1031
+ "0.8.1"
1032
1032
  ] })
1033
1033
  ] })
1034
1034
  ] });
@@ -1110,16 +1110,7 @@ function RuleCard({
1110
1110
  validity
1111
1111
  ] })
1112
1112
  ] }),
1113
- /* @__PURE__ */ jsx("div", { className: "pollar-dist-item-action", children: isClaimed ? /* @__PURE__ */ jsx("span", { className: "pollar-dist-item-status", "data-kind": "claimed", children: "Claimed" }) : effectivelyClaimable ? /* @__PURE__ */ jsx(
1114
- "button",
1115
- {
1116
- type: "button",
1117
- className: "pollar-btn-primary pollar-dist-claim-btn",
1118
- onClick: onClaim,
1119
- disabled: isClaiming,
1120
- children: isClaiming ? "Claiming\u2026" : "Claim"
1121
- }
1122
- ) : /* @__PURE__ */ jsx("span", { className: "pollar-dist-item-status", "data-kind": "unavailable", children: reasonLabel(rule.reason) }) }),
1113
+ /* @__PURE__ */ jsx("div", { className: "pollar-dist-item-action", children: isClaimed ? /* @__PURE__ */ jsx("span", { className: "pollar-dist-item-status", "data-kind": "claimed", children: "Claimed" }) : effectivelyClaimable ? /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary pollar-dist-claim-btn", onClick: onClaim, disabled: isClaiming, children: isClaiming ? "Claiming\u2026" : "Claim" }) : /* @__PURE__ */ jsx("span", { className: "pollar-dist-item-status", "data-kind": "unavailable", children: reasonLabel(rule.reason) }) }),
1123
1114
  errorMessage && /* @__PURE__ */ jsx("div", { className: "pollar-dist-item-error", children: errorMessage })
1124
1115
  ] });
1125
1116
  }
@@ -1333,10 +1324,20 @@ function KycModalTemplate({
1333
1324
  ] }),
1334
1325
  step === "select_provider" && /* @__PURE__ */ jsxs("div", { className: "pollar-kyc-providers", children: [
1335
1326
  providers.length === 0 && /* @__PURE__ */ jsx("p", { style: { color: "var(--pollar-muted)", textAlign: "center" }, children: "No providers available for your country." }),
1336
- providers.map((p) => /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-kyc-provider-btn", disabled: isLoading, onClick: () => onSelectProvider(p), children: [
1337
- /* @__PURE__ */ jsx("span", { className: "pollar-kyc-provider-name", children: p.name }),
1338
- /* @__PURE__ */ jsx("span", { className: "pollar-kyc-provider-flow", children: p.flow })
1339
- ] }, p.id))
1327
+ providers.map((p) => /* @__PURE__ */ jsxs(
1328
+ "button",
1329
+ {
1330
+ type: "button",
1331
+ className: "pollar-kyc-provider-btn",
1332
+ disabled: isLoading,
1333
+ onClick: () => onSelectProvider(p),
1334
+ children: [
1335
+ /* @__PURE__ */ jsx("span", { className: "pollar-kyc-provider-name", children: p.name }),
1336
+ /* @__PURE__ */ jsx("span", { className: "pollar-kyc-provider-flow", children: p.flow })
1337
+ ]
1338
+ },
1339
+ p.id
1340
+ ))
1340
1341
  ] }),
1341
1342
  step === "verifying" && selectedProvider && /* @__PURE__ */ jsxs(Fragment, { children: [
1342
1343
  /* @__PURE__ */ jsx("div", { className: "pollar-kyc-iframe-wrap", children: session?.kycUrl ? /* @__PURE__ */ jsx("iframe", { className: "pollar-kyc-iframe", src: session.kycUrl, title: "KYC verification", allow: "camera; microphone" }) : /* @__PURE__ */ jsxs("div", { className: "pollar-kyc-iframe-mock", children: [
@@ -1455,8 +1456,7 @@ function EmailCodeInput({ email, onSubmit }) {
1455
1456
  }
1456
1457
  return /* @__PURE__ */ jsxs("div", { className: "pollar-code-section", children: [
1457
1458
  /* @__PURE__ */ jsxs("p", { className: "pollar-code-label", children: [
1458
- "Enter the 6-digit code sent to",
1459
- " ",
1459
+ "Enter the 6-digit code sent to ",
1460
1460
  email ? /* @__PURE__ */ jsx("strong", { children: email }) : "your email"
1461
1461
  ] }),
1462
1462
  /* @__PURE__ */ jsx("div", { className: "pollar-code-inputs", children: digits.map((digit, i) => /* @__PURE__ */ jsx(
@@ -1480,7 +1480,14 @@ function EmailCodeInput({ email, onSubmit }) {
1480
1480
  }
1481
1481
  var GithubButton = ({ disabled, onClick }) => {
1482
1482
  return /* @__PURE__ */ jsxs("button", { className: "github-button", disabled, onClick, children: [
1483
- /* @__PURE__ */ jsx("svg", { className: "github-button-icon", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z", clipRule: "evenodd" }) }),
1483
+ /* @__PURE__ */ jsx("svg", { className: "github-button-icon", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx(
1484
+ "path",
1485
+ {
1486
+ fillRule: "evenodd",
1487
+ d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z",
1488
+ clipRule: "evenodd"
1489
+ }
1490
+ ) }),
1484
1491
  /* @__PURE__ */ jsx("span", { className: "github-button-contents", children: "GitHub" })
1485
1492
  ] });
1486
1493
  };
@@ -1533,6 +1540,36 @@ var GoogleButton = ({ disabled, onClick }) => {
1533
1540
  ] })
1534
1541
  ] });
1535
1542
  };
1543
+ function DefaultFreighterAlbedoButtons({ onConnect, isLoading }) {
1544
+ return /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-list", children: [
1545
+ /* @__PURE__ */ jsxs(
1546
+ "button",
1547
+ {
1548
+ type: "button",
1549
+ disabled: isLoading,
1550
+ className: "pollar-wallet-list-btn",
1551
+ onClick: () => onConnect(WalletType.FREIGHTER),
1552
+ children: [
1553
+ /* @__PURE__ */ jsx("img", { src: LOGO_FREIGHTER, alt: "Freighter", className: "pollar-wallet-list-icon" }),
1554
+ /* @__PURE__ */ jsx("span", { className: "pollar-wallet-list-name", children: "Freighter" })
1555
+ ]
1556
+ }
1557
+ ),
1558
+ /* @__PURE__ */ jsxs(
1559
+ "button",
1560
+ {
1561
+ type: "button",
1562
+ disabled: isLoading,
1563
+ className: "pollar-wallet-list-btn",
1564
+ onClick: () => onConnect(WalletType.ALBEDO),
1565
+ children: [
1566
+ /* @__PURE__ */ jsx("img", { src: LOGO_ALBEDO, alt: "Albedo", className: "pollar-wallet-list-icon" }),
1567
+ /* @__PURE__ */ jsx("span", { className: "pollar-wallet-list-name", children: "Albedo" })
1568
+ ]
1569
+ }
1570
+ )
1571
+ ] });
1572
+ }
1536
1573
  var AUTH_STATE_MESSAGES = {
1537
1574
  idle: "",
1538
1575
  creating_session: "Initializing\u2026",
@@ -1577,8 +1614,8 @@ function LoginModalTemplate({
1577
1614
  onEmailChange,
1578
1615
  onEmailSubmit,
1579
1616
  onSocialLogin,
1580
- onFreighterConnect,
1581
- onAlbedoConnect,
1617
+ onWalletConnect,
1618
+ renderWallets,
1582
1619
  authState,
1583
1620
  codeInputKey,
1584
1621
  onCodeSubmit,
@@ -1614,9 +1651,35 @@ function LoginModalTemplate({
1614
1651
  const isEmailCodeError = authState.step === "error" && (authState.errorCode === AUTH_ERROR_CODES.EMAIL_CODE_EXPIRED || authState.errorCode === AUTH_ERROR_CODES.EMAIL_CODE_INVALID);
1615
1652
  const awaitingEmailCode = authState.step === "entering_code" || authState.step === "verifying_email_code" || isEmailCodeError;
1616
1653
  const statusMessage = authState.step === "error" ? authState.message : AUTH_STATE_MESSAGES[authState.step];
1617
- const BackButton = ({ onClick }) => /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-back-btn", onClick, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M15 19l-7-7 7-7" }) }) });
1654
+ const BackButton = ({ onClick }) => /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-back-btn", onClick, "aria-label": "Back", children: /* @__PURE__ */ jsx(
1655
+ "svg",
1656
+ {
1657
+ width: "20",
1658
+ height: "20",
1659
+ viewBox: "0 0 24 24",
1660
+ fill: "none",
1661
+ stroke: "currentColor",
1662
+ strokeWidth: "2.5",
1663
+ strokeLinecap: "round",
1664
+ strokeLinejoin: "round",
1665
+ children: /* @__PURE__ */ jsx("path", { d: "M15 19l-7-7 7-7" })
1666
+ }
1667
+ ) });
1618
1668
  return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
1619
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-close-btn", onClick: onCancel, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) }),
1669
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-close-btn", onClick: onCancel, "aria-label": "Close", children: /* @__PURE__ */ jsx(
1670
+ "svg",
1671
+ {
1672
+ width: "18",
1673
+ height: "18",
1674
+ viewBox: "0 0 24 24",
1675
+ fill: "none",
1676
+ stroke: "currentColor",
1677
+ strokeWidth: "2.5",
1678
+ strokeLinecap: "round",
1679
+ strokeLinejoin: "round",
1680
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
1681
+ }
1682
+ ) }),
1620
1683
  /* @__PURE__ */ jsxs("div", { className: "pollar-header", children: [
1621
1684
  /* @__PURE__ */ jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsx("img", { src: logoUrl ?? LOGO_POLLAR, alt: "Logo", className: "pollar-logo" }) }),
1622
1685
  /* @__PURE__ */ jsx("h2", { className: "pollar-title", children: appName }),
@@ -1628,34 +1691,9 @@ function LoginModalTemplate({
1628
1691
  }) }, codeInputKey)
1629
1692
  ] }) : showWalletPicker ? /* @__PURE__ */ jsxs(Fragment, { children: [
1630
1693
  /* @__PURE__ */ jsx(BackButton, { onClick: () => setShowWalletPicker(false) }),
1631
- /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-list", children: [
1632
- /* @__PURE__ */ jsxs(
1633
- "button",
1634
- {
1635
- type: "button",
1636
- disabled: isLoading,
1637
- className: "pollar-wallet-list-btn",
1638
- onClick: onFreighterConnect,
1639
- children: [
1640
- /* @__PURE__ */ jsx("img", { src: LOGO_FREIGHTER, alt: "Freighter", className: "pollar-wallet-list-icon" }),
1641
- /* @__PURE__ */ jsx("span", { className: "pollar-wallet-list-name", children: "Freighter" })
1642
- ]
1643
- }
1644
- ),
1645
- /* @__PURE__ */ jsxs(
1646
- "button",
1647
- {
1648
- type: "button",
1649
- disabled: isLoading,
1650
- className: "pollar-wallet-list-btn",
1651
- onClick: onAlbedoConnect,
1652
- children: [
1653
- /* @__PURE__ */ jsx("img", { src: LOGO_ALBEDO, alt: "Albedo", className: "pollar-wallet-list-icon" }),
1654
- /* @__PURE__ */ jsx("span", { className: "pollar-wallet-list-name", children: "Albedo" })
1655
- ]
1656
- }
1657
- )
1658
- ] })
1694
+ renderWallets ? renderWallets({ onConnect: onWalletConnect ?? (() => {
1695
+ }), authState }) : /* @__PURE__ */ jsx(DefaultFreighterAlbedoButtons, { onConnect: onWalletConnect ?? (() => {
1696
+ }), isLoading })
1659
1697
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1660
1698
  emailEnabled && /* @__PURE__ */ jsxs("div", { className: "pollar-email-section", children: [
1661
1699
  /* @__PURE__ */ jsx(
@@ -1670,7 +1708,17 @@ function LoginModalTemplate({
1670
1708
  onKeyDown: (e) => e.key === "Enter" && onEmailSubmit?.()
1671
1709
  }
1672
1710
  ),
1673
- /* @__PURE__ */ jsx("button", { type: "button", disabled: isLoading || !email, className: "pollar-btn-primary", style: { marginTop: "0.75rem", width: "100%" }, onClick: onEmailSubmit, children: "Submit" })
1711
+ /* @__PURE__ */ jsx(
1712
+ "button",
1713
+ {
1714
+ type: "button",
1715
+ disabled: isLoading || !email,
1716
+ className: "pollar-btn-primary",
1717
+ style: { marginTop: "0.75rem", width: "100%" },
1718
+ onClick: onEmailSubmit,
1719
+ children: "Submit"
1720
+ }
1721
+ )
1674
1722
  ] }),
1675
1723
  emailEnabled && enabledSocial.length > 0 && /* @__PURE__ */ jsxs("div", { className: "pollar-divider", children: [
1676
1724
  /* @__PURE__ */ jsx("div", { className: "pollar-divider-line" }),
@@ -1688,7 +1736,20 @@ function LoginModalTemplate({
1688
1736
  className: "pollar-wallet-entry-btn",
1689
1737
  onClick: () => setShowWalletPicker(true),
1690
1738
  children: [
1691
- /* @__PURE__ */ jsx("svg", { width: "18", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" }) }),
1739
+ /* @__PURE__ */ jsx(
1740
+ "svg",
1741
+ {
1742
+ width: "18",
1743
+ height: "20",
1744
+ viewBox: "0 0 24 24",
1745
+ fill: "none",
1746
+ stroke: "currentColor",
1747
+ strokeWidth: "2",
1748
+ strokeLinecap: "round",
1749
+ strokeLinejoin: "round",
1750
+ children: /* @__PURE__ */ jsx("path", { d: "M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" })
1751
+ }
1752
+ ),
1692
1753
  "Wallet"
1693
1754
  ]
1694
1755
  }
@@ -1708,14 +1769,15 @@ function LoginModalTemplate({
1708
1769
  }
1709
1770
  function LoginModal({ onClose }) {
1710
1771
  const [email, setEmail] = useState("");
1711
- const { getClient, styles, appConfig: config } = usePollar();
1772
+ const { getClient, styles, appConfig: config, renderWallets } = usePollar();
1712
1773
  const [authState, setAuthState] = useState(() => getClient().getAuthState());
1713
1774
  const [codeInputKey, setCodeInputKey] = useState(0);
1714
1775
  const pendingEmail = useRef(null);
1715
1776
  const onCloseRef = useRef(onClose);
1716
1777
  onCloseRef.current = onClose;
1778
+ const autoCloseTimer = useRef(null);
1717
1779
  useEffect(() => {
1718
- return getClient().onAuthStateChange((next) => {
1780
+ const unsubscribe = getClient().onAuthStateChange((next) => {
1719
1781
  setAuthState(next);
1720
1782
  if (next.step === "entering_email" && pendingEmail.current) {
1721
1783
  getClient().sendEmailCode(pendingEmail.current);
@@ -1725,9 +1787,19 @@ function LoginModal({ onClose }) {
1725
1787
  setCodeInputKey((k) => k + 1);
1726
1788
  }
1727
1789
  if (next.step === "authenticated") {
1728
- setTimeout(onCloseRef.current, 1e3);
1790
+ autoCloseTimer.current = setTimeout(() => {
1791
+ autoCloseTimer.current = null;
1792
+ onCloseRef.current();
1793
+ }, 1e3);
1729
1794
  }
1730
1795
  });
1796
+ return () => {
1797
+ unsubscribe();
1798
+ if (autoCloseTimer.current !== null) {
1799
+ clearTimeout(autoCloseTimer.current);
1800
+ autoCloseTimer.current = null;
1801
+ }
1802
+ };
1731
1803
  }, [getClient]);
1732
1804
  const { theme = "light", accentColor = "#005DB4", logoUrl, emailEnabled, embeddedWallets, providers } = styles;
1733
1805
  function handleClose() {
@@ -1779,8 +1851,8 @@ function LoginModal({ onClose }) {
1779
1851
  onEmailChange: setEmail,
1780
1852
  onEmailSubmit: handleEmailSubmit,
1781
1853
  onSocialLogin: handleSocialLogin,
1782
- onFreighterConnect: () => handleWalletConnect(WalletType.FREIGHTER),
1783
- onAlbedoConnect: () => handleWalletConnect(WalletType.ALBEDO),
1854
+ onWalletConnect: handleWalletConnect,
1855
+ ...renderWallets !== void 0 && { renderWallets },
1784
1856
  authState,
1785
1857
  codeInputKey,
1786
1858
  onCodeSubmit: handleVerifyCode,
@@ -1897,8 +1969,26 @@ function RampWidgetTemplate({
1897
1969
  ] }),
1898
1970
  step === "input" && /* @__PURE__ */ jsxs(Fragment, { children: [
1899
1971
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-tabs", children: [
1900
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-ramp-tab", "data-active": direction === "onramp", onClick: () => onDirectionChange("onramp"), children: "Buy" }),
1901
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-ramp-tab", "data-active": direction === "offramp", onClick: () => onDirectionChange("offramp"), children: "Sell" })
1972
+ /* @__PURE__ */ jsx(
1973
+ "button",
1974
+ {
1975
+ type: "button",
1976
+ className: "pollar-ramp-tab",
1977
+ "data-active": direction === "onramp",
1978
+ onClick: () => onDirectionChange("onramp"),
1979
+ children: "Buy"
1980
+ }
1981
+ ),
1982
+ /* @__PURE__ */ jsx(
1983
+ "button",
1984
+ {
1985
+ type: "button",
1986
+ className: "pollar-ramp-tab",
1987
+ "data-active": direction === "offramp",
1988
+ onClick: () => onDirectionChange("offramp"),
1989
+ children: "Sell"
1990
+ }
1991
+ )
1902
1992
  ] }),
1903
1993
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-input-row", children: [
1904
1994
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
@@ -2003,17 +2093,79 @@ function RampWidgetTemplate({
2003
2093
  ] });
2004
2094
  }
2005
2095
  var MOCK_DEFAULT_QUOTES = [
2006
- { quoteId: "meld-default", provider: "Meld", fee: 1.2, feeCurrency: "USD", rate: 1, rail: "ACH", protocol: "REST", estimatedTime: "~20 min", recommended: true }
2096
+ {
2097
+ quoteId: "meld-default",
2098
+ provider: "Meld",
2099
+ fee: 1.2,
2100
+ feeCurrency: "USD",
2101
+ rate: 1,
2102
+ rail: "ACH",
2103
+ protocol: "REST",
2104
+ estimatedTime: "~20 min",
2105
+ recommended: true
2106
+ }
2007
2107
  ];
2008
2108
  var MOCK_QUOTES = {
2009
2109
  MX: [
2010
- { quoteId: "etherfuse-mx", provider: "Etherfuse", fee: 0.5, feeCurrency: "MXN", rate: 17.2, rail: "SPEI", protocol: "SEP-24", estimatedTime: "~10 min", recommended: true },
2011
- { quoteId: "alfredpay-mx", provider: "AlfredPay", fee: 0.8, feeCurrency: "MXN", rate: 17.1, rail: "SPEI", protocol: "REST", estimatedTime: "~15 min", recommended: false }
2110
+ {
2111
+ quoteId: "etherfuse-mx",
2112
+ provider: "Etherfuse",
2113
+ fee: 0.5,
2114
+ feeCurrency: "MXN",
2115
+ rate: 17.2,
2116
+ rail: "SPEI",
2117
+ protocol: "SEP-24",
2118
+ estimatedTime: "~10 min",
2119
+ recommended: true
2120
+ },
2121
+ {
2122
+ quoteId: "alfredpay-mx",
2123
+ provider: "AlfredPay",
2124
+ fee: 0.8,
2125
+ feeCurrency: "MXN",
2126
+ rate: 17.1,
2127
+ rail: "SPEI",
2128
+ protocol: "REST",
2129
+ estimatedTime: "~15 min",
2130
+ recommended: false
2131
+ }
2132
+ ],
2133
+ BR: [
2134
+ {
2135
+ quoteId: "abroad-br",
2136
+ provider: "Abroad",
2137
+ fee: 0.6,
2138
+ feeCurrency: "BRL",
2139
+ rate: 5.1,
2140
+ rail: "PIX",
2141
+ protocol: "REST",
2142
+ estimatedTime: "~5 min",
2143
+ recommended: true
2144
+ }
2012
2145
  ],
2013
- BR: [{ quoteId: "abroad-br", provider: "Abroad", fee: 0.6, feeCurrency: "BRL", rate: 5.1, rail: "PIX", protocol: "REST", estimatedTime: "~5 min", recommended: true }],
2014
2146
  CO: [
2015
- { quoteId: "abroad-co", provider: "Abroad", fee: 0.7, feeCurrency: "COP", rate: 4100, rail: "PSE", protocol: "REST", estimatedTime: "~10 min", recommended: true },
2016
- { quoteId: "koywe-co", provider: "Koywe", fee: 0.9, feeCurrency: "COP", rate: 4095, rail: "PSE", protocol: "REST", estimatedTime: "~15 min", recommended: false }
2147
+ {
2148
+ quoteId: "abroad-co",
2149
+ provider: "Abroad",
2150
+ fee: 0.7,
2151
+ feeCurrency: "COP",
2152
+ rate: 4100,
2153
+ rail: "PSE",
2154
+ protocol: "REST",
2155
+ estimatedTime: "~10 min",
2156
+ recommended: true
2157
+ },
2158
+ {
2159
+ quoteId: "koywe-co",
2160
+ provider: "Koywe",
2161
+ fee: 0.9,
2162
+ feeCurrency: "COP",
2163
+ rate: 4095,
2164
+ rail: "PSE",
2165
+ protocol: "REST",
2166
+ estimatedTime: "~15 min",
2167
+ recommended: false
2168
+ }
2017
2169
  ],
2018
2170
  DEFAULT: MOCK_DEFAULT_QUOTES
2019
2171
  };
@@ -2108,17 +2260,7 @@ function RampWidget({ onClose }) {
2108
2260
  // src/lib/qr-code/index.tsx
2109
2261
  var import_ErrorCorrectLevel = __toESM(require_ErrorCorrectLevel());
2110
2262
  var import_QRCode = __toESM(require_QRCode());
2111
- var QRCodeSvg = forwardRef(function QRCodeSvg2({
2112
- bgColor,
2113
- bgD,
2114
- fgD,
2115
- fgColor,
2116
- size,
2117
- title,
2118
- viewBoxSize,
2119
- xmlns = "http://www.w3.org/2000/svg",
2120
- ...props
2121
- }, ref) {
2263
+ var QRCodeSvg = forwardRef(function QRCodeSvg2({ bgColor, bgD, fgD, fgColor, size, title, viewBoxSize, xmlns = "http://www.w3.org/2000/svg", ...props }, ref) {
2122
2264
  return /* @__PURE__ */ jsxs("svg", { ...props, height: size, ref, viewBox: `0 0 ${viewBoxSize} ${viewBoxSize}`, width: size, xmlns, children: [
2123
2265
  title ? /* @__PURE__ */ jsx("title", { children: title }) : null,
2124
2266
  /* @__PURE__ */ jsx("path", { d: bgD, fill: bgColor }),
@@ -2144,9 +2286,13 @@ var QRCode = forwardRef(function QRCode2({ bgColor = "#FFFFFF", fgColor = "#0000
2144
2286
  {
2145
2287
  ...props,
2146
2288
  bgColor,
2147
- bgD: cells.map((row, rowIndex) => row.map((cell, cellIndex) => !cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")).join(" "),
2289
+ bgD: cells.map(
2290
+ (row, rowIndex) => row.map((cell, cellIndex) => !cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")
2291
+ ).join(" "),
2148
2292
  fgColor,
2149
- fgD: cells.map((row, rowIndex) => row.map((cell, cellIndex) => cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")).join(" "),
2293
+ fgD: cells.map(
2294
+ (row, rowIndex) => row.map((cell, cellIndex) => cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")
2295
+ ).join(" "),
2150
2296
  ref,
2151
2297
  size,
2152
2298
  viewBoxSize: cells.length
@@ -2192,15 +2338,7 @@ function ReceiveModalTemplate({
2192
2338
  /* @__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" }) }) }) })
2193
2339
  ] }),
2194
2340
  walletAddress ? /* @__PURE__ */ jsxs(Fragment, { children: [
2195
- /* @__PURE__ */ jsx("div", { className: "pollar-receive-qr", children: /* @__PURE__ */ jsx(
2196
- QRCode,
2197
- {
2198
- value: walletAddress,
2199
- size: 180,
2200
- fgColor: isDark ? "#ffffff" : "#111827",
2201
- bgColor: "transparent"
2202
- }
2203
- ) }),
2341
+ /* @__PURE__ */ jsx("div", { className: "pollar-receive-qr", children: /* @__PURE__ */ jsx(QRCode, { value: walletAddress, size: 180, fgColor: isDark ? "#ffffff" : "#111827", bgColor: "transparent" }) }),
2204
2342
  /* @__PURE__ */ jsx("p", { className: "pollar-receive-instructions", children: "Share your Stellar address to receive any asset. Only send Stellar assets to this address." }),
2205
2343
  /* @__PURE__ */ jsxs("div", { className: "pollar-receive-address-row", children: [
2206
2344
  /* @__PURE__ */ jsx("span", { className: "pollar-receive-address", children: walletAddress }),
@@ -2245,11 +2383,22 @@ function ReceiveModal({ onClose }) {
2245
2383
  const { walletAddress, styles } = usePollar();
2246
2384
  const { theme = "light", accentColor = "#005DB4" } = styles;
2247
2385
  const [copied, setCopied] = useState(false);
2386
+ const copyTimerRef = useRef(null);
2387
+ useEffect(
2388
+ () => () => {
2389
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
2390
+ },
2391
+ []
2392
+ );
2248
2393
  function handleCopy() {
2249
2394
  if (!walletAddress) return;
2250
2395
  navigator.clipboard.writeText(walletAddress).then(() => {
2251
2396
  setCopied(true);
2252
- setTimeout(() => setCopied(false), 2e3);
2397
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
2398
+ copyTimerRef.current = setTimeout(() => {
2399
+ copyTimerRef.current = null;
2400
+ setCopied(false);
2401
+ }, 2e3);
2253
2402
  });
2254
2403
  }
2255
2404
  return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsx(
@@ -2268,10 +2417,32 @@ var STATUS_MESSAGES = {
2268
2417
  idle: "",
2269
2418
  building: "Building transaction\u2026",
2270
2419
  built: "Ready to sign and send",
2271
- signing: "Signing and sending transaction\u2026",
2420
+ signing: "Signing transaction\u2026",
2421
+ signed: "Signed \u2014 ready to submit",
2422
+ submitting: "Submitting transaction\u2026",
2423
+ submitted: "Submitted \u2014 waiting for confirmation\u2026",
2424
+ "signing-submitting": "Signing and submitting transaction\u2026",
2425
+ "building-signing-submitting": "Processing transaction\u2026",
2272
2426
  success: "Transaction sent successfully",
2273
2427
  error: "Transaction failed"
2274
2428
  };
2429
+ var IN_FLIGHT_STEPS = /* @__PURE__ */ new Set([
2430
+ "building",
2431
+ "signing",
2432
+ "submitting",
2433
+ "submitted",
2434
+ "signing-submitting",
2435
+ "building-signing-submitting"
2436
+ ]);
2437
+ var SHOW_DETAILS_STEPS = /* @__PURE__ */ new Set([
2438
+ "built",
2439
+ "signing",
2440
+ "signed",
2441
+ "submitting",
2442
+ "submitted",
2443
+ "signing-submitting",
2444
+ "success"
2445
+ ]);
2275
2446
  function TxStatusView({
2276
2447
  transaction,
2277
2448
  showXdr,
@@ -2288,10 +2459,10 @@ function TxStatusView({
2288
2459
  const hash = transaction.step === "success" ? transaction.hash : null;
2289
2460
  const errorDetails = transaction.step === "error" ? transaction.details ?? null : null;
2290
2461
  const isBuilt = transaction.step === "built";
2291
- const isSigning = transaction.step === "signing";
2462
+ const isInFlight = IN_FLIGHT_STEPS.has(transaction.step);
2292
2463
  const isSuccess = transaction.step === "success";
2293
2464
  const isError = transaction.step === "error";
2294
- const showDetails = buildData !== null && (isBuilt || isSigning || isSuccess);
2465
+ const showDetails = buildData !== null && SHOW_DETAILS_STEPS.has(transaction.step);
2295
2466
  const walletImg = walletType === WalletType.FREIGHTER ? LOGO_FREIGHTER : walletType === WalletType.ALBEDO ? LOGO_ALBEDO : LOGO_POLLAR;
2296
2467
  const walletAlt = walletType === WalletType.FREIGHTER ? "Freighter" : walletType === WalletType.ALBEDO ? "Albedo" : "Pollar";
2297
2468
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -2334,7 +2505,7 @@ function TxStatusView({
2334
2505
  /* @__PURE__ */ jsx("pre", { className: "pollar-tx-error-details-content", children: errorDetails })
2335
2506
  ] }),
2336
2507
  isBuilt && /* @__PURE__ */ jsx("button", { className: "pollar-btn-primary pollar-tx-sign-btn", onClick: onSignAndSend, children: "Sign & Send" }),
2337
- (isSigning || isSuccess || isError) && /* @__PURE__ */ jsxs("div", { className: "pollar-tx-wallet-spinner", children: [
2508
+ (isInFlight || isSuccess || isError) && /* @__PURE__ */ jsxs("div", { className: "pollar-tx-wallet-spinner", children: [
2338
2509
  /* @__PURE__ */ jsxs("div", { className: "pollar-tx-spinner-ring", children: [
2339
2510
  /* @__PURE__ */ jsxs(
2340
2511
  "svg",
@@ -2342,7 +2513,7 @@ function TxStatusView({
2342
2513
  viewBox: "0 0 88 88",
2343
2514
  width: "88",
2344
2515
  height: "88",
2345
- className: `pollar-tx-spinner-svg${isSigning ? " pollar-tx-spinner-rotating" : ""}`,
2516
+ className: `pollar-tx-spinner-svg${isInFlight ? " pollar-tx-spinner-rotating" : ""}`,
2346
2517
  "aria-hidden": true,
2347
2518
  children: [
2348
2519
  /* @__PURE__ */ jsx("circle", { cx: "44", cy: "44", r: "36", fill: "none", stroke: "var(--pollar-border)", strokeWidth: "3" }),
@@ -2356,9 +2527,9 @@ function TxStatusView({
2356
2527
  stroke: isSuccess ? "var(--pollar-success-text)" : isError ? "var(--pollar-error-text)" : "var(--pollar-accent)",
2357
2528
  strokeWidth: "3",
2358
2529
  strokeLinecap: "round",
2359
- strokeDasharray: isSigning ? "169.6 56.6" : "999 0",
2530
+ strokeDasharray: isInFlight ? "169.6 56.6" : "999 0",
2360
2531
  transform: "rotate(-90 44 44)",
2361
- style: { transition: isSigning ? "none" : "stroke 400ms, stroke-dasharray 400ms" }
2532
+ style: { transition: isInFlight ? "none" : "stroke 400ms, stroke-dasharray 400ms" }
2362
2533
  }
2363
2534
  )
2364
2535
  ]
@@ -2366,7 +2537,7 @@ function TxStatusView({
2366
2537
  ),
2367
2538
  /* @__PURE__ */ jsx("div", { className: "pollar-tx-wallet-icon", children: /* @__PURE__ */ jsx("img", { src: walletImg, alt: walletAlt, className: "pollar-tx-wallet-img" }) })
2368
2539
  ] }),
2369
- isSigning && /* @__PURE__ */ jsx("p", { className: "pollar-tx-spinner-label", children: walletType === WalletType.FREIGHTER ? "Waiting for Freighter\u2026" : walletType === WalletType.ALBEDO ? "Waiting for Albedo\u2026" : "Signing and sending\u2026" }),
2540
+ isInFlight && /* @__PURE__ */ jsx("p", { className: "pollar-tx-spinner-label", children: walletType === WalletType.FREIGHTER ? "Waiting for Freighter\u2026" : walletType === WalletType.ALBEDO ? "Waiting for Albedo\u2026" : "Signing and sending\u2026" }),
2370
2541
  isError && onRetry && "buildData" in transaction && transaction.buildData && /* @__PURE__ */ jsx("button", { className: "pollar-btn-secondary pollar-tx-retry-btn", onClick: onRetry, children: "Try again" })
2371
2542
  ] }),
2372
2543
  isSuccess && hash && /* @__PURE__ */ jsxs("div", { className: "pollar-tx-result", children: [
@@ -2434,7 +2605,7 @@ function TxStatusView({
2434
2605
  ModalStatusBanner,
2435
2606
  {
2436
2607
  message: STATUS_MESSAGES[transaction.step],
2437
- status: isError ? "ERROR" : isSigning || transaction.step === "building" ? "LOADING" : isSuccess ? "SUCCESS" : "NONE"
2608
+ status: isError ? "ERROR" : isInFlight ? "LOADING" : isSuccess ? "SUCCESS" : "NONE"
2438
2609
  }
2439
2610
  )
2440
2611
  ] });
@@ -2611,7 +2782,16 @@ function assetParam(record) {
2611
2782
  return { type: "credit_alphanum12", code: record.code, issuer: record.issuer };
2612
2783
  }
2613
2784
  function SendModal({ onClose }) {
2614
- const { walletBalance, refreshWalletBalance, buildTx, signAndSubmitTx, tx: transaction, walletType, network, styles } = usePollar();
2785
+ const {
2786
+ walletBalance,
2787
+ refreshWalletBalance,
2788
+ buildTx,
2789
+ signAndSubmitTx,
2790
+ tx: transaction,
2791
+ walletType,
2792
+ network,
2793
+ styles
2794
+ } = usePollar();
2615
2795
  const { theme = "light", accentColor = "#005DB4" } = styles;
2616
2796
  const [step, setStep] = useState("form");
2617
2797
  const [amount, setAmount] = useState("");
@@ -2620,9 +2800,16 @@ function SendModal({ onClose }) {
2620
2800
  const [showXdr, setShowXdr] = useState(false);
2621
2801
  const [copied, setCopied] = useState(false);
2622
2802
  const [formError, setFormError] = useState("");
2803
+ const copyTimerRef = useRef(null);
2623
2804
  useEffect(() => {
2624
2805
  void refreshWalletBalance();
2625
2806
  }, [refreshWalletBalance]);
2807
+ useEffect(
2808
+ () => () => {
2809
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
2810
+ },
2811
+ []
2812
+ );
2626
2813
  const balanceData = walletBalance.step === "loaded" ? walletBalance.data : null;
2627
2814
  const allAssets = balanceData?.balances ?? [];
2628
2815
  const sortedAssets = [
@@ -2633,9 +2820,17 @@ function SendModal({ onClose }) {
2633
2820
  const buildData = "buildData" in transaction ? transaction.buildData : null;
2634
2821
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
2635
2822
  const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
2636
- const isInProgress = transaction.step === "building" || transaction.step === "signing";
2823
+ const IN_FLIGHT_STEPS2 = [
2824
+ "building",
2825
+ "signing",
2826
+ "submitting",
2827
+ "submitted",
2828
+ "signing-submitting",
2829
+ "building-signing-submitting"
2830
+ ];
2831
+ const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
2637
2832
  const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
2638
- const txTitle = transaction.step === "signing" ? "Sending\u2026" : transaction.step === "success" ? "Sent!" : transaction.step === "error" ? "Send failed" : "Confirm Send";
2833
+ const txTitle = isInProgress ? "Sending\u2026" : transaction.step === "success" ? "Sent!" : transaction.step === "error" ? "Send failed" : "Confirm Send";
2639
2834
  async function handleSubmit() {
2640
2835
  setFormError("");
2641
2836
  if (!selectedAsset) {
@@ -2667,7 +2862,11 @@ function SendModal({ onClose }) {
2667
2862
  if (!hash) return;
2668
2863
  navigator.clipboard.writeText(hash).then(() => {
2669
2864
  setCopied(true);
2670
- setTimeout(() => setCopied(false), 2e3);
2865
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
2866
+ copyTimerRef.current = setTimeout(() => {
2867
+ copyTimerRef.current = null;
2868
+ setCopied(false);
2869
+ }, 2e3);
2671
2870
  });
2672
2871
  }
2673
2872
  async function handleRetry() {
@@ -2817,16 +3016,7 @@ function SessionsModalTemplate({
2817
3016
  "aria-hidden": true,
2818
3017
  children: [
2819
3018
  /* @__PURE__ */ jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
2820
- /* @__PURE__ */ jsx(
2821
- "path",
2822
- {
2823
- d: "M10 1v3h-3",
2824
- stroke: "currentColor",
2825
- strokeWidth: "1.5",
2826
- strokeLinecap: "round",
2827
- strokeLinejoin: "round"
2828
- }
2829
- )
3019
+ /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
2830
3020
  ]
2831
3021
  }
2832
3022
  ),
@@ -2894,9 +3084,12 @@ function SessionsModal({ onClose }) {
2894
3084
  const [revokingFamilyId, setRevokingFamilyId] = useState(null);
2895
3085
  const [signingOutEverywhere, setSigningOutEverywhere] = useState(false);
2896
3086
  const mountedRef = useRef(true);
2897
- useEffect(() => () => {
2898
- mountedRef.current = false;
2899
- }, []);
3087
+ useEffect(
3088
+ () => () => {
3089
+ mountedRef.current = false;
3090
+ },
3091
+ []
3092
+ );
2900
3093
  const onCloseRef = useRef(onClose);
2901
3094
  onCloseRef.current = onClose;
2902
3095
  useEffect(() => {
@@ -2928,9 +3121,7 @@ function SessionsModal({ onClose }) {
2928
3121
  await load();
2929
3122
  } catch {
2930
3123
  if (!mountedRef.current) return;
2931
- setState(
2932
- (prev) => prev.step === "loaded" ? { step: "error", message: "Failed to revoke session" } : prev
2933
- );
3124
+ setState((prev) => prev.step === "loaded" ? { step: "error", message: "Failed to revoke session" } : prev);
2934
3125
  } finally {
2935
3126
  if (mountedRef.current) setRevokingFamilyId(null);
2936
3127
  }
@@ -2994,55 +3185,53 @@ function TransactionModalTemplate({
2994
3185
  "--pollar-input-border-radius": "0.5rem",
2995
3186
  "--pollar-card-border-radius": "10px"
2996
3187
  };
2997
- return /* @__PURE__ */ jsxs(
2998
- "div",
2999
- {
3000
- className: "pollar-modal-card pollar-tx-modal",
3001
- "data-theme": theme,
3002
- style: cssVars,
3003
- onClick: (e) => e.stopPropagation(),
3004
- children: [
3005
- /* @__PURE__ */ jsx("div", { className: "pollar-modal-header", children: /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Transaction" }) }),
3006
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-close-btn", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(
3007
- "svg",
3008
- {
3009
- width: "18",
3010
- height: "18",
3011
- viewBox: "0 0 24 24",
3012
- fill: "none",
3013
- stroke: "currentColor",
3014
- strokeWidth: "2.5",
3015
- strokeLinecap: "round",
3016
- strokeLinejoin: "round",
3017
- "aria-hidden": true,
3018
- children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
3019
- }
3020
- ) }),
3021
- /* @__PURE__ */ jsx(
3022
- TxStatusView,
3023
- {
3024
- transaction,
3025
- showXdr,
3026
- copied,
3027
- explorerUrl,
3028
- walletType,
3029
- onSignAndSend,
3030
- onToggleXdr,
3031
- onCopyHash,
3032
- onRetry,
3033
- onDone: onClose
3034
- }
3035
- ),
3036
- /* @__PURE__ */ jsx(PollarModalFooter, {})
3037
- ]
3038
- }
3039
- );
3188
+ return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-tx-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
3189
+ /* @__PURE__ */ jsx("div", { className: "pollar-modal-header", children: /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Transaction" }) }),
3190
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-close-btn", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(
3191
+ "svg",
3192
+ {
3193
+ width: "18",
3194
+ height: "18",
3195
+ viewBox: "0 0 24 24",
3196
+ fill: "none",
3197
+ stroke: "currentColor",
3198
+ strokeWidth: "2.5",
3199
+ strokeLinecap: "round",
3200
+ strokeLinejoin: "round",
3201
+ "aria-hidden": true,
3202
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
3203
+ }
3204
+ ) }),
3205
+ /* @__PURE__ */ jsx(
3206
+ TxStatusView,
3207
+ {
3208
+ transaction,
3209
+ showXdr,
3210
+ copied,
3211
+ explorerUrl,
3212
+ walletType,
3213
+ onSignAndSend,
3214
+ onToggleXdr,
3215
+ onCopyHash,
3216
+ onRetry,
3217
+ onDone: onClose
3218
+ }
3219
+ ),
3220
+ /* @__PURE__ */ jsx(PollarModalFooter, {})
3221
+ ] });
3040
3222
  }
3041
3223
  function TransactionModal({ onClose }) {
3042
3224
  const { getClient, styles, tx: transaction, network, walletType } = usePollar();
3043
3225
  const { theme = "light", accentColor = "#005DB4" } = styles;
3044
3226
  const [showXdr, setShowXdr] = useState(false);
3045
3227
  const [copied, setCopied] = useState(false);
3228
+ const copyTimerRef = useRef(null);
3229
+ useEffect(
3230
+ () => () => {
3231
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
3232
+ },
3233
+ []
3234
+ );
3046
3235
  const hash = transaction.step === "success" ? transaction.hash : null;
3047
3236
  const buildData = "buildData" in transaction ? transaction.buildData : null;
3048
3237
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
@@ -3056,7 +3245,11 @@ function TransactionModal({ onClose }) {
3056
3245
  if (!hash) return;
3057
3246
  navigator.clipboard.writeText(hash).then(() => {
3058
3247
  setCopied(true);
3059
- setTimeout(() => setCopied(false), 2e3);
3248
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
3249
+ copyTimerRef.current = setTimeout(() => {
3250
+ copyTimerRef.current = null;
3251
+ setCopied(false);
3252
+ }, 2e3);
3060
3253
  });
3061
3254
  }
3062
3255
  async function handleRetry() {
@@ -3123,97 +3316,128 @@ function TxHistoryModalTemplate({
3123
3316
  const hasPrev = offset > 0;
3124
3317
  const hasNext = offset + PAGE_SIZE < total;
3125
3318
  const showPagination = txHistory.step === "loaded" && total > PAGE_SIZE;
3126
- return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-hist-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
3127
- /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
3128
- /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Transaction History" }),
3129
- /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
3130
- /* @__PURE__ */ jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading, children: [
3131
- /* @__PURE__ */ jsxs(
3132
- "svg",
3133
- {
3134
- className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
3135
- width: "13",
3136
- height: "13",
3137
- viewBox: "0 0 13 13",
3138
- fill: "none",
3139
- "aria-hidden": true,
3140
- children: [
3141
- /* @__PURE__ */ jsx(
3142
- "path",
3319
+ return /* @__PURE__ */ jsxs(
3320
+ "div",
3321
+ {
3322
+ className: "pollar-modal-card pollar-hist-modal",
3323
+ "data-theme": theme,
3324
+ style: cssVars,
3325
+ onClick: (e) => e.stopPropagation(),
3326
+ children: [
3327
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
3328
+ /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Transaction History" }),
3329
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
3330
+ /* @__PURE__ */ jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading, children: [
3331
+ /* @__PURE__ */ jsxs(
3332
+ "svg",
3333
+ {
3334
+ className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
3335
+ width: "13",
3336
+ height: "13",
3337
+ viewBox: "0 0 13 13",
3338
+ fill: "none",
3339
+ "aria-hidden": true,
3340
+ children: [
3341
+ /* @__PURE__ */ jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
3342
+ /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
3343
+ ]
3344
+ }
3345
+ ),
3346
+ "Refresh"
3347
+ ] }),
3348
+ /* @__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" }) }) })
3349
+ ] })
3350
+ ] }),
3351
+ /* @__PURE__ */ jsxs("div", { className: "pollar-hist-list", children: [
3352
+ txHistory.step === "idle" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Click Refresh to load transactions." }),
3353
+ isLoading && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
3354
+ txHistory.step === "error" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: txHistory.message }),
3355
+ txHistory.step === "loaded" && records.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No transactions yet." }),
3356
+ records.map((record) => {
3357
+ const explorerUrl = `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${record.hash}`;
3358
+ return /* @__PURE__ */ jsxs("div", { className: "pollar-hist-item", children: [
3359
+ /* @__PURE__ */ jsx("span", { className: "pollar-hist-item-summary", children: record.summary }),
3360
+ /* @__PURE__ */ jsx(StatusBadge, { status: record.status }),
3361
+ /* @__PURE__ */ jsxs("span", { className: "pollar-hist-item-meta", children: [
3362
+ /* @__PURE__ */ jsx("span", { children: record.operation }),
3363
+ record.feeXlm && /* @__PURE__ */ jsxs("span", { children: [
3364
+ "\xB7 ",
3365
+ record.feeXlm,
3366
+ " XLM"
3367
+ ] }),
3368
+ /* @__PURE__ */ jsxs("span", { children: [
3369
+ "\xB7 ",
3370
+ formatDate(record.createdAt)
3371
+ ] }),
3372
+ /* @__PURE__ */ jsx("span", { children: "\xB7" }),
3373
+ /* @__PURE__ */ jsxs(
3374
+ "a",
3143
3375
  {
3144
- d: "M11.5 6.5a5 5 0 11-1.5-3.536",
3145
- stroke: "currentColor",
3146
- strokeWidth: "1.5",
3147
- strokeLinecap: "round"
3376
+ className: "pollar-hist-item-explorer",
3377
+ href: explorerUrl,
3378
+ target: "_blank",
3379
+ rel: "noopener noreferrer",
3380
+ "aria-label": "View on Stellar Explorer",
3381
+ children: [
3382
+ /* @__PURE__ */ jsxs("svg", { width: "11", height: "11", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
3383
+ /* @__PURE__ */ jsx(
3384
+ "path",
3385
+ {
3386
+ d: "M5 2H2a1 1 0 00-1 1v8a1 1 0 001 1h8a1 1 0 001-1V8",
3387
+ stroke: "currentColor",
3388
+ strokeWidth: "1.5",
3389
+ strokeLinecap: "round"
3390
+ }
3391
+ ),
3392
+ /* @__PURE__ */ jsx(
3393
+ "path",
3394
+ {
3395
+ d: "M8 1h4m0 0v4m0-4L6 7",
3396
+ stroke: "currentColor",
3397
+ strokeWidth: "1.5",
3398
+ strokeLinecap: "round",
3399
+ strokeLinejoin: "round"
3400
+ }
3401
+ )
3402
+ ] }),
3403
+ "Explorer"
3404
+ ]
3148
3405
  }
3149
- ),
3150
- /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
3151
- ]
3152
- }
3153
- ),
3154
- "Refresh"
3406
+ )
3407
+ ] })
3408
+ ] }, record.id);
3409
+ })
3155
3410
  ] }),
3156
- /* @__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" }) }) })
3157
- ] })
3158
- ] }),
3159
- /* @__PURE__ */ jsxs("div", { className: "pollar-hist-list", children: [
3160
- txHistory.step === "idle" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Click Refresh to load transactions." }),
3161
- isLoading && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
3162
- txHistory.step === "error" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: txHistory.message }),
3163
- txHistory.step === "loaded" && records.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No transactions yet." }),
3164
- records.map((record) => {
3165
- const explorerUrl = `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${record.hash}`;
3166
- return /* @__PURE__ */ jsxs("div", { className: "pollar-hist-item", children: [
3167
- /* @__PURE__ */ jsx("span", { className: "pollar-hist-item-summary", children: record.summary }),
3168
- /* @__PURE__ */ jsx(StatusBadge, { status: record.status }),
3169
- /* @__PURE__ */ jsxs("span", { className: "pollar-hist-item-meta", children: [
3170
- /* @__PURE__ */ jsx("span", { children: record.operation }),
3171
- record.feeXlm && /* @__PURE__ */ jsxs("span", { children: [
3172
- "\xB7 ",
3173
- record.feeXlm,
3174
- " XLM"
3175
- ] }),
3176
- /* @__PURE__ */ jsxs("span", { children: [
3177
- "\xB7 ",
3178
- formatDate(record.createdAt)
3179
- ] }),
3180
- /* @__PURE__ */ jsx("span", { children: "\xB7" }),
3181
- /* @__PURE__ */ jsxs("a", { className: "pollar-hist-item-explorer", href: explorerUrl, target: "_blank", rel: "noopener noreferrer", "aria-label": "View on Stellar Explorer", children: [
3182
- /* @__PURE__ */ jsxs("svg", { width: "11", height: "11", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
3183
- /* @__PURE__ */ jsx("path", { d: "M5 2H2a1 1 0 00-1 1v8a1 1 0 001 1h8a1 1 0 001-1V8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
3184
- /* @__PURE__ */ jsx("path", { d: "M8 1h4m0 0v4m0-4L6 7", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
3185
- ] }),
3186
- "Explorer"
3187
- ] })
3411
+ showPagination && /* @__PURE__ */ jsxs("div", { className: "pollar-hist-pagination", children: [
3412
+ /* @__PURE__ */ jsxs("span", { className: "pollar-hist-pagination-info", children: [
3413
+ offset + 1,
3414
+ "\u2013",
3415
+ Math.min(offset + PAGE_SIZE, total),
3416
+ " of ",
3417
+ total
3418
+ ] }),
3419
+ /* @__PURE__ */ jsxs("div", { className: "pollar-hist-pagination-btns", children: [
3420
+ /* @__PURE__ */ jsx("button", { className: "pollar-hist-page-btn", onClick: onPrev, disabled: !hasPrev, children: "\u2190 Prev" }),
3421
+ /* @__PURE__ */ jsx("button", { className: "pollar-hist-page-btn", onClick: onNext, disabled: !hasNext, children: "Next \u2192" })
3188
3422
  ] })
3189
- ] }, record.id);
3190
- })
3191
- ] }),
3192
- showPagination && /* @__PURE__ */ jsxs("div", { className: "pollar-hist-pagination", children: [
3193
- /* @__PURE__ */ jsxs("span", { className: "pollar-hist-pagination-info", children: [
3194
- offset + 1,
3195
- "\u2013",
3196
- Math.min(offset + PAGE_SIZE, total),
3197
- " of ",
3198
- total
3199
- ] }),
3200
- /* @__PURE__ */ jsxs("div", { className: "pollar-hist-pagination-btns", children: [
3201
- /* @__PURE__ */ jsx("button", { className: "pollar-hist-page-btn", onClick: onPrev, disabled: !hasPrev, children: "\u2190 Prev" }),
3202
- /* @__PURE__ */ jsx("button", { className: "pollar-hist-page-btn", onClick: onNext, disabled: !hasNext, children: "Next \u2192" })
3203
- ] })
3204
- ] }),
3205
- /* @__PURE__ */ jsx(PollarModalFooter, {})
3206
- ] });
3423
+ ] }),
3424
+ /* @__PURE__ */ jsx(PollarModalFooter, {})
3425
+ ]
3426
+ }
3427
+ );
3207
3428
  }
3208
3429
  var PAGE_SIZE2 = 10;
3209
3430
  function TxHistoryModal({ onClose }) {
3210
3431
  const { getClient, styles, txHistory } = usePollar();
3211
3432
  const { theme = "light", accentColor = "#005DB4" } = styles;
3212
3433
  const [offset, setOffset] = useState(0);
3213
- const load = useCallback((nextOffset) => {
3214
- setOffset(nextOffset);
3215
- void getClient().fetchTxHistory({ limit: PAGE_SIZE2, offset: nextOffset });
3216
- }, [getClient]);
3434
+ const load = useCallback(
3435
+ (nextOffset) => {
3436
+ setOffset(nextOffset);
3437
+ void getClient().fetchTxHistory({ limit: PAGE_SIZE2, offset: nextOffset });
3438
+ },
3439
+ [getClient]
3440
+ );
3217
3441
  useEffect(() => {
3218
3442
  load(0);
3219
3443
  }, [load]);
@@ -3336,28 +3560,31 @@ function WalletBalanceModal({ onClose }) {
3336
3560
  }
3337
3561
  ) });
3338
3562
  }
3339
- var emptyResponse = {
3340
- application: {
3341
- name: ""
3342
- },
3563
+ var DEFAULT_APP_CONFIG = {
3564
+ application: { name: "" },
3343
3565
  styles: {}
3344
3566
  };
3345
- async function fetchRemoteConfig(client) {
3346
- const content = await client.getAppConfig();
3347
- return content ?? emptyResponse;
3567
+ function sessionsEqual(a, b) {
3568
+ if (a === b) return true;
3569
+ if (!a || !b) return false;
3570
+ return a.clientSessionId === b.clientSessionId && a.userId === b.userId && a.status === b.status && a.token?.accessToken === b.token?.accessToken && a.token?.refreshToken === b.token?.refreshToken && a.token?.expiresAt === b.token?.expiresAt && a.wallet?.publicKey === b.wallet?.publicKey;
3348
3571
  }
3349
3572
  var PollarContext = createContext(null);
3350
- function PollarProvider({ config, styles: propStyles, adapters, children }) {
3351
- const [pollarClient] = useState(() => new PollarClient(config));
3573
+ function PollarProvider({
3574
+ client,
3575
+ appConfig: appConfigProp,
3576
+ ui,
3577
+ adapters,
3578
+ onStorageDegrade,
3579
+ children
3580
+ }) {
3581
+ const [pollarClient] = useState(() => client instanceof PollarClient ? client : new PollarClient(client));
3352
3582
  const [networkState, setNetworkState] = useState(() => pollarClient.getNetworkState());
3353
3583
  const [sessionState, setSessionState] = useState(null);
3354
3584
  const [transaction, setTransaction] = useState({ step: "idle" });
3355
3585
  const [txHistory, setTxHistory] = useState({ step: "idle" });
3356
3586
  const [walletBalance, setWalletBalance] = useState({ step: "idle" });
3357
- const [remoteConfig, setRemoteConfig] = useState(emptyResponse);
3358
- const [styles, setStyles] = useState(propStyles ?? {});
3359
- const propStylesRef = useRef(propStyles);
3360
- propStylesRef.current = propStyles;
3587
+ const [resolvedConfig, setResolvedConfig] = useState(() => appConfigProp ?? DEFAULT_APP_CONFIG);
3361
3588
  useEffect(() => {
3362
3589
  return pollarClient.onTransactionStateChange(setTransaction);
3363
3590
  }, [pollarClient]);
@@ -3372,28 +3599,32 @@ function PollarProvider({ config, styles: propStyles, adapters, children }) {
3372
3599
  setNetworkState(state);
3373
3600
  });
3374
3601
  }, [pollarClient]);
3602
+ useEffect(() => {
3603
+ if (!onStorageDegrade) return;
3604
+ return pollarClient.onStorageDegrade(onStorageDegrade);
3605
+ }, [pollarClient, onStorageDegrade]);
3375
3606
  useEffect(() => {
3376
3607
  return pollarClient.onAuthStateChange((authState) => {
3377
3608
  if (authState.step === "authenticated") {
3378
- setSessionState((prev) => JSON.stringify(prev) !== JSON.stringify(authState.session) ? authState.session : prev);
3609
+ setSessionState((prev) => sessionsEqual(prev, authState.session) ? prev : authState.session);
3379
3610
  } else if (authState.step === "idle") {
3380
3611
  setSessionState(null);
3381
3612
  }
3382
3613
  });
3383
3614
  }, [pollarClient]);
3384
3615
  useEffect(() => {
3385
- const propStyles2 = propStylesRef.current;
3386
- fetchRemoteConfig(pollarClient).then((fetched) => {
3387
- setRemoteConfig(fetched);
3388
- setStyles({
3389
- ...fetched.styles,
3390
- ...propStyles2,
3391
- providers: { ...fetched.styles?.providers, ...propStyles2?.providers }
3392
- });
3393
- }).catch(() => {
3394
- setStyles(propStyles2 ?? {});
3616
+ if (appConfigProp !== void 0) return;
3617
+ let cancelled = false;
3618
+ pollarClient.getAppConfig().then((fetched) => {
3619
+ if (cancelled || !fetched) return;
3620
+ setResolvedConfig(fetched);
3621
+ }).catch((err) => {
3622
+ console.error("[PollarProvider] getAppConfig failed", err);
3395
3623
  });
3396
- }, [pollarClient]);
3624
+ return () => {
3625
+ cancelled = true;
3626
+ };
3627
+ }, [pollarClient, appConfigProp]);
3397
3628
  const [loginModalOpen, setLoginModalOpen] = useState(false);
3398
3629
  const [transactionModalOpen, setTransactionModalOpen] = useState(false);
3399
3630
  const [kycModalOpen, setKycModalOpen] = useState(false);
@@ -3405,13 +3636,13 @@ function PollarProvider({ config, styles: propStyles, adapters, children }) {
3405
3636
  const [receiveModalOpen, setReceiveModalOpen] = useState(false);
3406
3637
  const [sessionsModalOpen, setSessionsModalOpen] = useState(false);
3407
3638
  const [distributionRulesModalOpen, setDistributionRulesModalOpen] = useState(false);
3408
- const adaptersRef = useRef(adapters);
3409
- adaptersRef.current = adapters;
3410
3639
  const walletAddress = sessionState?.wallet?.publicKey || "";
3411
3640
  const getClient = useCallback(() => pollarClient, [pollarClient]);
3412
3641
  const refreshWalletBalance = useCallback(() => pollarClient.refreshBalance(walletAddress), [pollarClient, walletAddress]);
3413
- const contextValue = useMemo(
3414
- () => ({
3642
+ const renderWallets = ui?.renderWallets;
3643
+ const contextValue = useMemo(() => {
3644
+ const styles = resolvedConfig.styles ?? {};
3645
+ return {
3415
3646
  // session
3416
3647
  walletAddress,
3417
3648
  isAuthenticated: !!walletAddress,
@@ -3426,6 +3657,10 @@ function PollarProvider({ config, styles: propStyles, adapters, children }) {
3426
3657
  tx: transaction,
3427
3658
  buildTx: (operation, params, options) => pollarClient.buildTx(operation, params, options),
3428
3659
  signAndSubmitTx: (unsignedXdr) => pollarClient.signAndSubmitTx(unsignedXdr),
3660
+ signTx: (unsignedXdr) => pollarClient.signTx(unsignedXdr),
3661
+ submitTx: (signedXdr) => pollarClient.submitTx(signedXdr),
3662
+ buildAndSignAndSubmitTx: (operation, params, options) => pollarClient.buildAndSignAndSubmitTx(operation, params, options),
3663
+ runTx: (operation, params, options) => pollarClient.runTx(operation, params, options),
3429
3664
  openTxModal: () => setTransactionModalOpen(true),
3430
3665
  // tx history
3431
3666
  txHistory,
@@ -3452,23 +3687,24 @@ function PollarProvider({ config, styles: propStyles, adapters, children }) {
3452
3687
  // ramp
3453
3688
  openRampModal: () => setRampModalOpen(true),
3454
3689
  // config
3455
- appConfig: remoteConfig,
3690
+ appConfig: resolvedConfig,
3456
3691
  styles,
3457
- adapters: adaptersRef.current
3458
- }),
3459
- [
3460
- walletAddress,
3461
- pollarClient,
3462
- getClient,
3463
- transaction,
3464
- txHistory,
3465
- walletBalance,
3466
- refreshWalletBalance,
3467
- networkState,
3468
- remoteConfig,
3469
- styles
3470
- ]
3471
- );
3692
+ renderWallets,
3693
+ adapters
3694
+ };
3695
+ }, [
3696
+ walletAddress,
3697
+ pollarClient,
3698
+ getClient,
3699
+ transaction,
3700
+ txHistory,
3701
+ walletBalance,
3702
+ refreshWalletBalance,
3703
+ networkState,
3704
+ resolvedConfig,
3705
+ adapters,
3706
+ renderWallets
3707
+ ]);
3472
3708
  return /* @__PURE__ */ jsxs(PollarContext.Provider, { value: contextValue, children: [
3473
3709
  children,
3474
3710
  loginModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setLoginModalOpen(false), children: /* @__PURE__ */ jsx(LoginModal, { onClose: () => setLoginModalOpen(false) }) }),
@@ -3512,7 +3748,7 @@ function createPollarAdapterHook(key) {
3512
3748
  name,
3513
3749
  async (params) => {
3514
3750
  const { unsignedTransaction } = await fn(params);
3515
- await signAndSubmitTx(unsignedTransaction);
3751
+ return signAndSubmitTx(unsignedTransaction);
3516
3752
  }
3517
3753
  ])
3518
3754
  );
@@ -3561,33 +3797,22 @@ function WalletButtonTemplate({
3561
3797
  "aria-busy": isInProgress,
3562
3798
  children: [
3563
3799
  /* @__PURE__ */ jsx("span", { className: "wallet-btn-label", children: cropWallet(walletAddress) }),
3564
- isInProgress ? /* @__PURE__ */ jsxs(
3565
- "svg",
3566
- {
3567
- className: "wallet-btn-spinner",
3568
- viewBox: "0 0 12 12",
3569
- width: "12",
3570
- height: "12",
3571
- fill: "none",
3572
- "aria-hidden": true,
3573
- children: [
3574
- /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "4.5", stroke: "rgba(255,255,255,0.35)", strokeWidth: "1.5" }),
3575
- /* @__PURE__ */ jsx(
3576
- "circle",
3577
- {
3578
- cx: "6",
3579
- cy: "6",
3580
- r: "4.5",
3581
- stroke: "white",
3582
- strokeWidth: "1.5",
3583
- strokeLinecap: "round",
3584
- strokeDasharray: "14 9",
3585
- transform: "rotate(-90 6 6)"
3586
- }
3587
- )
3588
- ]
3589
- }
3590
- ) : /* @__PURE__ */ jsx(
3800
+ isInProgress ? /* @__PURE__ */ jsxs("svg", { className: "wallet-btn-spinner", viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", "aria-hidden": true, children: [
3801
+ /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "4.5", stroke: "rgba(255,255,255,0.35)", strokeWidth: "1.5" }),
3802
+ /* @__PURE__ */ jsx(
3803
+ "circle",
3804
+ {
3805
+ cx: "6",
3806
+ cy: "6",
3807
+ r: "4.5",
3808
+ stroke: "white",
3809
+ strokeWidth: "1.5",
3810
+ strokeLinecap: "round",
3811
+ strokeDasharray: "14 9",
3812
+ transform: "rotate(-90 6 6)"
3813
+ }
3814
+ )
3815
+ ] }) : /* @__PURE__ */ jsx(
3591
3816
  "svg",
3592
3817
  {
3593
3818
  className: `wallet-chevron${open ? " open" : ""}`,
@@ -3605,53 +3830,131 @@ function WalletButtonTemplate({
3605
3830
  ),
3606
3831
  open && /* @__PURE__ */ jsxs("div", { className: "wallet-dropdown", style: { backgroundColor: dropdownBg, borderColor: dropdownBorder }, children: [
3607
3832
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onSend, children: [
3608
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3609
- /* @__PURE__ */ jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
3610
- /* @__PURE__ */ jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
3611
- ] }),
3833
+ /* @__PURE__ */ jsxs(
3834
+ "svg",
3835
+ {
3836
+ width: "14",
3837
+ height: "14",
3838
+ viewBox: "0 0 24 24",
3839
+ fill: "none",
3840
+ stroke: "currentColor",
3841
+ strokeWidth: "2",
3842
+ strokeLinecap: "round",
3843
+ strokeLinejoin: "round",
3844
+ children: [
3845
+ /* @__PURE__ */ jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
3846
+ /* @__PURE__ */ jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
3847
+ ]
3848
+ }
3849
+ ),
3612
3850
  "Send"
3613
3851
  ] }),
3614
3852
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onReceive, children: [
3615
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3616
- /* @__PURE__ */ jsx("polyline", { points: "8 17 12 21 16 17" }),
3617
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "12", x2: "12", y2: "21" }),
3618
- /* @__PURE__ */ jsx("path", { d: "M20.88 18.09A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.29" })
3619
- ] }),
3853
+ /* @__PURE__ */ jsxs(
3854
+ "svg",
3855
+ {
3856
+ width: "14",
3857
+ height: "14",
3858
+ viewBox: "0 0 24 24",
3859
+ fill: "none",
3860
+ stroke: "currentColor",
3861
+ strokeWidth: "2",
3862
+ strokeLinecap: "round",
3863
+ strokeLinejoin: "round",
3864
+ children: [
3865
+ /* @__PURE__ */ jsx("polyline", { points: "8 17 12 21 16 17" }),
3866
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "12", x2: "12", y2: "21" }),
3867
+ /* @__PURE__ */ jsx("path", { d: "M20.88 18.09A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.29" })
3868
+ ]
3869
+ }
3870
+ ),
3620
3871
  "Receive"
3621
3872
  ] }),
3622
3873
  /* @__PURE__ */ jsx("div", { className: "wallet-dropdown-divider" }),
3623
3874
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onCopy, children: [
3624
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3625
- /* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
3626
- /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
3627
- ] }),
3875
+ /* @__PURE__ */ jsxs(
3876
+ "svg",
3877
+ {
3878
+ width: "14",
3879
+ height: "14",
3880
+ viewBox: "0 0 24 24",
3881
+ fill: "none",
3882
+ stroke: "currentColor",
3883
+ strokeWidth: "2",
3884
+ strokeLinecap: "round",
3885
+ strokeLinejoin: "round",
3886
+ children: [
3887
+ /* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
3888
+ /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
3889
+ ]
3890
+ }
3891
+ ),
3628
3892
  copied ? "Copied!" : "Copy address"
3629
3893
  ] }),
3630
3894
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onWalletBalance, children: [
3631
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3632
- /* @__PURE__ */ jsx("rect", { x: "1", y: "4", width: "22", height: "16", rx: "2", ry: "2" }),
3633
- /* @__PURE__ */ jsx("circle", { cx: "16", cy: "12", r: "2" }),
3634
- /* @__PURE__ */ jsx("path", { d: "M22 8H12" })
3635
- ] }),
3895
+ /* @__PURE__ */ jsxs(
3896
+ "svg",
3897
+ {
3898
+ width: "14",
3899
+ height: "14",
3900
+ viewBox: "0 0 24 24",
3901
+ fill: "none",
3902
+ stroke: "currentColor",
3903
+ strokeWidth: "2",
3904
+ strokeLinecap: "round",
3905
+ strokeLinejoin: "round",
3906
+ children: [
3907
+ /* @__PURE__ */ jsx("rect", { x: "1", y: "4", width: "22", height: "16", rx: "2", ry: "2" }),
3908
+ /* @__PURE__ */ jsx("circle", { cx: "16", cy: "12", r: "2" }),
3909
+ /* @__PURE__ */ jsx("path", { d: "M22 8H12" })
3910
+ ]
3911
+ }
3912
+ ),
3636
3913
  "Wallet balance"
3637
3914
  ] }),
3638
3915
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onTxHistory, children: [
3639
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3640
- /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
3641
- /* @__PURE__ */ jsx("polyline", { points: "14,2 14,8 20,8" }),
3642
- /* @__PURE__ */ jsx("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
3643
- /* @__PURE__ */ jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
3644
- /* @__PURE__ */ jsx("polyline", { points: "10,9 9,9 8,9" })
3645
- ] }),
3916
+ /* @__PURE__ */ jsxs(
3917
+ "svg",
3918
+ {
3919
+ width: "14",
3920
+ height: "14",
3921
+ viewBox: "0 0 24 24",
3922
+ fill: "none",
3923
+ stroke: "currentColor",
3924
+ strokeWidth: "2",
3925
+ strokeLinecap: "round",
3926
+ strokeLinejoin: "round",
3927
+ children: [
3928
+ /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
3929
+ /* @__PURE__ */ jsx("polyline", { points: "14,2 14,8 20,8" }),
3930
+ /* @__PURE__ */ jsx("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
3931
+ /* @__PURE__ */ jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
3932
+ /* @__PURE__ */ jsx("polyline", { points: "10,9 9,9 8,9" })
3933
+ ]
3934
+ }
3935
+ ),
3646
3936
  "Transaction history"
3647
3937
  ] }),
3648
3938
  /* @__PURE__ */ jsx("div", { className: "wallet-dropdown-divider" }),
3649
3939
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item danger", onClick: onLogout, children: [
3650
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3651
- /* @__PURE__ */ jsx("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
3652
- /* @__PURE__ */ jsx("polyline", { points: "16,17 21,12 16,7" }),
3653
- /* @__PURE__ */ jsx("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
3654
- ] }),
3940
+ /* @__PURE__ */ jsxs(
3941
+ "svg",
3942
+ {
3943
+ width: "14",
3944
+ height: "14",
3945
+ viewBox: "0 0 24 24",
3946
+ fill: "none",
3947
+ stroke: "currentColor",
3948
+ strokeWidth: "2",
3949
+ strokeLinecap: "round",
3950
+ strokeLinejoin: "round",
3951
+ children: [
3952
+ /* @__PURE__ */ jsx("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
3953
+ /* @__PURE__ */ jsx("polyline", { points: "16,17 21,12 16,7" }),
3954
+ /* @__PURE__ */ jsx("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
3955
+ ]
3956
+ }
3957
+ ),
3655
3958
  "Log out"
3656
3959
  ] })
3657
3960
  ] })
@@ -3673,6 +3976,7 @@ function WalletButton() {
3673
3976
  const [open, setOpen] = useState(false);
3674
3977
  const [copied, setCopied] = useState(false);
3675
3978
  const wrapperRef = useRef(null);
3979
+ const copyTimerRef = useRef(null);
3676
3980
  const isInProgress = transaction.step === "building" || transaction.step === "signing";
3677
3981
  const { theme = "light", accentColor = "#005DB4" } = styles;
3678
3982
  const isDark = theme === "dark";
@@ -3688,11 +3992,21 @@ function WalletButton() {
3688
3992
  document.addEventListener("mousedown", handleClickOutside);
3689
3993
  return () => document.removeEventListener("mousedown", handleClickOutside);
3690
3994
  }, []);
3995
+ useEffect(
3996
+ () => () => {
3997
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
3998
+ },
3999
+ []
4000
+ );
3691
4001
  async function handleCopy() {
3692
4002
  if (!walletAddress) return;
3693
4003
  await navigator.clipboard.writeText(walletAddress);
3694
4004
  setCopied(true);
3695
- setTimeout(() => setCopied(false), 1500);
4005
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
4006
+ copyTimerRef.current = setTimeout(() => {
4007
+ copyTimerRef.current = null;
4008
+ setCopied(false);
4009
+ }, 1500);
3696
4010
  }
3697
4011
  function handleLogout() {
3698
4012
  setOpen(false);