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