@pollar/react 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { AUTH_ERROR_CODES, WalletType, PollarClient } from '@pollar/core';
3
- import { forwardRef, createContext, useState, useEffect, useRef, useCallback, useMemo, useContext, Component } from 'react';
3
+ import { forwardRef, createContext, useState, useCallback, useEffect, useRef, useMemo, useContext, Component } from 'react';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
 
6
6
  var __create = Object.create;
@@ -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.0"
1031
+ "0.8.0"
1032
1032
  ] })
1033
1033
  ] })
1034
1034
  ] });
@@ -1052,6 +1052,212 @@ function ModalStatusBanner({ message, status, onCancel, onRetry }) {
1052
1052
  status === "ERROR" && onRetry && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-status-cancel", onClick: onRetry, children: "Retry" })
1053
1053
  ] });
1054
1054
  }
1055
+ var PERIOD_LABEL = {
1056
+ DAY: "every 24h",
1057
+ DAY_CALENDAR: "daily",
1058
+ WEEK: "every 7 days",
1059
+ MONTH: "every 30 days",
1060
+ MONTH_CALENDAR: "monthly",
1061
+ LIFETIME: "one-time"
1062
+ };
1063
+ var REASON_LABEL = {
1064
+ DISTRIBUTION_RULE_DISABLED: "Disabled",
1065
+ DISTRIBUTION_RULE_NOT_STARTED: "Not started yet",
1066
+ DISTRIBUTION_RULE_EXPIRED: "Expired",
1067
+ DISTRIBUTION_RULE_EXHAUSTED: "Fully claimed",
1068
+ DISTRIBUTION_RATE_LIMIT_EXCEEDED: "Already claimed"
1069
+ };
1070
+ function reasonLabel(reason) {
1071
+ if (!reason) return "Not available";
1072
+ return REASON_LABEL[reason] ?? "Not available";
1073
+ }
1074
+ function formatAmount(amount) {
1075
+ const n = parseFloat(amount);
1076
+ return isNaN(n) ? amount : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
1077
+ }
1078
+ function formatValidity(rule) {
1079
+ const from = rule.validFrom ? new Date(rule.validFrom) : null;
1080
+ const until = rule.validUntil ? new Date(rule.validUntil) : null;
1081
+ if (!from && !until) return null;
1082
+ const fmt = (d) => d.toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" });
1083
+ if (from && until) return `${fmt(from)} \u2192 ${fmt(until)}`;
1084
+ if (until) return `Until ${fmt(until)}`;
1085
+ if (from) return `From ${fmt(from)}`;
1086
+ return null;
1087
+ }
1088
+ function RuleCard({
1089
+ rule,
1090
+ isClaiming,
1091
+ isClaimed,
1092
+ errorMessage,
1093
+ onClaim
1094
+ }) {
1095
+ const validity = formatValidity(rule);
1096
+ const effectivelyClaimable = rule.claimable && !isClaimed;
1097
+ return /* @__PURE__ */ jsxs("div", { className: "pollar-dist-item", "data-claimable": effectivelyClaimable ? "true" : "false", children: [
1098
+ /* @__PURE__ */ jsxs("div", { className: "pollar-dist-item-row", children: [
1099
+ /* @__PURE__ */ jsx("span", { className: "pollar-dist-item-name", children: rule.name }),
1100
+ /* @__PURE__ */ jsxs("span", { className: "pollar-dist-item-amount", children: [
1101
+ formatAmount(rule.amount),
1102
+ " ",
1103
+ /* @__PURE__ */ jsx("span", { className: "pollar-dist-item-asset", children: rule.assetCode })
1104
+ ] })
1105
+ ] }),
1106
+ /* @__PURE__ */ jsxs("div", { className: "pollar-dist-item-meta", children: [
1107
+ /* @__PURE__ */ jsx("span", { children: PERIOD_LABEL[rule.period] }),
1108
+ validity && /* @__PURE__ */ jsxs("span", { children: [
1109
+ "\xB7 ",
1110
+ validity
1111
+ ] })
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("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) }) }),
1114
+ errorMessage && /* @__PURE__ */ jsx("div", { className: "pollar-dist-item-error", children: errorMessage })
1115
+ ] });
1116
+ }
1117
+ function DistributionRulesModalTemplate({
1118
+ theme,
1119
+ accentColor,
1120
+ state,
1121
+ claimingId,
1122
+ claimErrors,
1123
+ claimedIds,
1124
+ onRefresh,
1125
+ onClaim,
1126
+ onClose
1127
+ }) {
1128
+ const isDark = theme === "dark";
1129
+ const cssVars = {
1130
+ "--pollar-accent": accentColor,
1131
+ "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
1132
+ "--pollar-border": isDark ? "#374151" : "#e5e7eb",
1133
+ "--pollar-text": isDark ? "#ffffff" : "#111827",
1134
+ "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
1135
+ "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
1136
+ "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
1137
+ "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
1138
+ "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
1139
+ "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
1140
+ "--pollar-buttons-border-radius": "6px",
1141
+ "--pollar-buttons-height": "44px",
1142
+ "--pollar-input-height": "44px",
1143
+ "--pollar-input-border-radius": "0.5rem",
1144
+ "--pollar-card-border-radius": "10px"
1145
+ };
1146
+ const isLoading = state.step === "loading";
1147
+ const rules = state.step === "loaded" ? state.rules : [];
1148
+ return /* @__PURE__ */ jsxs(
1149
+ "div",
1150
+ {
1151
+ className: "pollar-modal-card pollar-dist-modal",
1152
+ "data-theme": theme,
1153
+ style: cssVars,
1154
+ onClick: (e) => e.stopPropagation(),
1155
+ children: [
1156
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
1157
+ /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Distribution Rules" }),
1158
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
1159
+ /* @__PURE__ */ jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading, children: [
1160
+ /* @__PURE__ */ jsxs(
1161
+ "svg",
1162
+ {
1163
+ className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
1164
+ width: "13",
1165
+ height: "13",
1166
+ viewBox: "0 0 13 13",
1167
+ fill: "none",
1168
+ "aria-hidden": true,
1169
+ children: [
1170
+ /* @__PURE__ */ jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1171
+ /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1172
+ ]
1173
+ }
1174
+ ),
1175
+ "Refresh"
1176
+ ] }),
1177
+ /* @__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" }) }) })
1178
+ ] })
1179
+ ] }),
1180
+ /* @__PURE__ */ jsxs("div", { className: "pollar-dist-list", children: [
1181
+ isLoading && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
1182
+ state.step === "error" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: state.message }),
1183
+ state.step === "loaded" && rules.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No distribution rules available." }),
1184
+ rules.map((rule) => /* @__PURE__ */ jsx(
1185
+ RuleCard,
1186
+ {
1187
+ rule,
1188
+ isClaiming: claimingId === rule.id,
1189
+ isClaimed: claimedIds.has(rule.id),
1190
+ ...claimErrors[rule.id] && { errorMessage: claimErrors[rule.id] },
1191
+ onClaim: () => onClaim(rule)
1192
+ },
1193
+ rule.id
1194
+ ))
1195
+ ] }),
1196
+ /* @__PURE__ */ jsx(PollarModalFooter, {})
1197
+ ]
1198
+ }
1199
+ );
1200
+ }
1201
+ function DistributionRulesModal({ onClose }) {
1202
+ const { getClient, styles } = usePollar();
1203
+ const { theme = "light", accentColor = "#005DB4" } = styles;
1204
+ const [state, setState] = useState({ step: "idle" });
1205
+ const [claimingId, setClaimingId] = useState(null);
1206
+ const [claimErrors, setClaimErrors] = useState({});
1207
+ const [claimedIds, setClaimedIds] = useState(() => /* @__PURE__ */ new Set());
1208
+ const load = useCallback(async () => {
1209
+ setState({ step: "loading" });
1210
+ try {
1211
+ const rules = await getClient().listDistributionRules();
1212
+ setState({ step: "loaded", rules });
1213
+ } catch (err) {
1214
+ const message = err instanceof Error ? err.message : "Failed to load distribution rules";
1215
+ setState({ step: "error", message });
1216
+ }
1217
+ }, [getClient]);
1218
+ useEffect(() => {
1219
+ void load();
1220
+ }, [load]);
1221
+ const handleClaim = useCallback(
1222
+ async (rule) => {
1223
+ setClaimingId(rule.id);
1224
+ setClaimErrors((prev) => {
1225
+ if (!prev[rule.id]) return prev;
1226
+ const next = { ...prev };
1227
+ delete next[rule.id];
1228
+ return next;
1229
+ });
1230
+ try {
1231
+ await getClient().claimDistributionRule({ ruleId: rule.id });
1232
+ setClaimedIds((prev) => {
1233
+ const next = new Set(prev);
1234
+ next.add(rule.id);
1235
+ return next;
1236
+ });
1237
+ } catch (err) {
1238
+ const message = err instanceof Error ? err.message : "Claim failed";
1239
+ setClaimErrors((prev) => ({ ...prev, [rule.id]: message }));
1240
+ } finally {
1241
+ setClaimingId(null);
1242
+ }
1243
+ },
1244
+ [getClient]
1245
+ );
1246
+ return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsx(
1247
+ DistributionRulesModalTemplate,
1248
+ {
1249
+ theme,
1250
+ accentColor,
1251
+ state,
1252
+ claimingId,
1253
+ claimErrors,
1254
+ claimedIds,
1255
+ onRefresh: () => void load(),
1256
+ onClaim: handleClaim,
1257
+ onClose
1258
+ }
1259
+ ) });
1260
+ }
1055
1261
  var STATUS_CONFIG = {
1056
1262
  none: { label: "Not started", color: "#6b7280", dot: false },
1057
1263
  pending: { label: "Pending review", color: "#f59e0b", dot: true },
@@ -1118,10 +1324,20 @@ function KycModalTemplate({
1118
1324
  ] }),
1119
1325
  step === "select_provider" && /* @__PURE__ */ jsxs("div", { className: "pollar-kyc-providers", children: [
1120
1326
  providers.length === 0 && /* @__PURE__ */ jsx("p", { style: { color: "var(--pollar-muted)", textAlign: "center" }, children: "No providers available for your country." }),
1121
- providers.map((p) => /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-kyc-provider-btn", disabled: isLoading, onClick: () => onSelectProvider(p), children: [
1122
- /* @__PURE__ */ jsx("span", { className: "pollar-kyc-provider-name", children: p.name }),
1123
- /* @__PURE__ */ jsx("span", { className: "pollar-kyc-provider-flow", children: p.flow })
1124
- ] }, 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
+ ))
1125
1341
  ] }),
1126
1342
  step === "verifying" && selectedProvider && /* @__PURE__ */ jsxs(Fragment, { children: [
1127
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: [
@@ -1240,8 +1456,7 @@ function EmailCodeInput({ email, onSubmit }) {
1240
1456
  }
1241
1457
  return /* @__PURE__ */ jsxs("div", { className: "pollar-code-section", children: [
1242
1458
  /* @__PURE__ */ jsxs("p", { className: "pollar-code-label", children: [
1243
- "Enter the 6-digit code sent to",
1244
- " ",
1459
+ "Enter the 6-digit code sent to ",
1245
1460
  email ? /* @__PURE__ */ jsx("strong", { children: email }) : "your email"
1246
1461
  ] }),
1247
1462
  /* @__PURE__ */ jsx("div", { className: "pollar-code-inputs", children: digits.map((digit, i) => /* @__PURE__ */ jsx(
@@ -1265,7 +1480,14 @@ function EmailCodeInput({ email, onSubmit }) {
1265
1480
  }
1266
1481
  var GithubButton = ({ disabled, onClick }) => {
1267
1482
  return /* @__PURE__ */ jsxs("button", { className: "github-button", disabled, onClick, children: [
1268
- /* @__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
+ ) }),
1269
1491
  /* @__PURE__ */ jsx("span", { className: "github-button-contents", children: "GitHub" })
1270
1492
  ] });
1271
1493
  };
@@ -1318,6 +1540,36 @@ var GoogleButton = ({ disabled, onClick }) => {
1318
1540
  ] })
1319
1541
  ] });
1320
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
+ }
1321
1573
  var AUTH_STATE_MESSAGES = {
1322
1574
  idle: "",
1323
1575
  creating_session: "Initializing\u2026",
@@ -1362,8 +1614,8 @@ function LoginModalTemplate({
1362
1614
  onEmailChange,
1363
1615
  onEmailSubmit,
1364
1616
  onSocialLogin,
1365
- onFreighterConnect,
1366
- onAlbedoConnect,
1617
+ onWalletConnect,
1618
+ renderWallets,
1367
1619
  authState,
1368
1620
  codeInputKey,
1369
1621
  onCodeSubmit,
@@ -1399,9 +1651,35 @@ function LoginModalTemplate({
1399
1651
  const isEmailCodeError = authState.step === "error" && (authState.errorCode === AUTH_ERROR_CODES.EMAIL_CODE_EXPIRED || authState.errorCode === AUTH_ERROR_CODES.EMAIL_CODE_INVALID);
1400
1652
  const awaitingEmailCode = authState.step === "entering_code" || authState.step === "verifying_email_code" || isEmailCodeError;
1401
1653
  const statusMessage = authState.step === "error" ? authState.message : AUTH_STATE_MESSAGES[authState.step];
1402
- 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
+ ) });
1403
1668
  return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
1404
- /* @__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
+ ) }),
1405
1683
  /* @__PURE__ */ jsxs("div", { className: "pollar-header", children: [
1406
1684
  /* @__PURE__ */ jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsx("img", { src: logoUrl ?? LOGO_POLLAR, alt: "Logo", className: "pollar-logo" }) }),
1407
1685
  /* @__PURE__ */ jsx("h2", { className: "pollar-title", children: appName }),
@@ -1413,34 +1691,7 @@ function LoginModalTemplate({
1413
1691
  }) }, codeInputKey)
1414
1692
  ] }) : showWalletPicker ? /* @__PURE__ */ jsxs(Fragment, { children: [
1415
1693
  /* @__PURE__ */ jsx(BackButton, { onClick: () => setShowWalletPicker(false) }),
1416
- /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-list", children: [
1417
- /* @__PURE__ */ jsxs(
1418
- "button",
1419
- {
1420
- type: "button",
1421
- disabled: isLoading,
1422
- className: "pollar-wallet-list-btn",
1423
- onClick: onFreighterConnect,
1424
- children: [
1425
- /* @__PURE__ */ jsx("img", { src: LOGO_FREIGHTER, alt: "Freighter", className: "pollar-wallet-list-icon" }),
1426
- /* @__PURE__ */ jsx("span", { className: "pollar-wallet-list-name", children: "Freighter" })
1427
- ]
1428
- }
1429
- ),
1430
- /* @__PURE__ */ jsxs(
1431
- "button",
1432
- {
1433
- type: "button",
1434
- disabled: isLoading,
1435
- className: "pollar-wallet-list-btn",
1436
- onClick: onAlbedoConnect,
1437
- children: [
1438
- /* @__PURE__ */ jsx("img", { src: LOGO_ALBEDO, alt: "Albedo", className: "pollar-wallet-list-icon" }),
1439
- /* @__PURE__ */ jsx("span", { className: "pollar-wallet-list-name", children: "Albedo" })
1440
- ]
1441
- }
1442
- )
1443
- ] })
1694
+ renderWallets ? renderWallets({ onConnect: onWalletConnect, authState }) : /* @__PURE__ */ jsx(DefaultFreighterAlbedoButtons, { onConnect: onWalletConnect, isLoading })
1444
1695
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1445
1696
  emailEnabled && /* @__PURE__ */ jsxs("div", { className: "pollar-email-section", children: [
1446
1697
  /* @__PURE__ */ jsx(
@@ -1455,7 +1706,17 @@ function LoginModalTemplate({
1455
1706
  onKeyDown: (e) => e.key === "Enter" && onEmailSubmit?.()
1456
1707
  }
1457
1708
  ),
1458
- /* @__PURE__ */ jsx("button", { type: "button", disabled: isLoading || !email, className: "pollar-btn-primary", style: { marginTop: "0.75rem", width: "100%" }, onClick: onEmailSubmit, children: "Submit" })
1709
+ /* @__PURE__ */ jsx(
1710
+ "button",
1711
+ {
1712
+ type: "button",
1713
+ disabled: isLoading || !email,
1714
+ className: "pollar-btn-primary",
1715
+ style: { marginTop: "0.75rem", width: "100%" },
1716
+ onClick: onEmailSubmit,
1717
+ children: "Submit"
1718
+ }
1719
+ )
1459
1720
  ] }),
1460
1721
  emailEnabled && enabledSocial.length > 0 && /* @__PURE__ */ jsxs("div", { className: "pollar-divider", children: [
1461
1722
  /* @__PURE__ */ jsx("div", { className: "pollar-divider-line" }),
@@ -1473,7 +1734,20 @@ function LoginModalTemplate({
1473
1734
  className: "pollar-wallet-entry-btn",
1474
1735
  onClick: () => setShowWalletPicker(true),
1475
1736
  children: [
1476
- /* @__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" }) }),
1737
+ /* @__PURE__ */ jsx(
1738
+ "svg",
1739
+ {
1740
+ width: "18",
1741
+ height: "20",
1742
+ viewBox: "0 0 24 24",
1743
+ fill: "none",
1744
+ stroke: "currentColor",
1745
+ strokeWidth: "2",
1746
+ strokeLinecap: "round",
1747
+ strokeLinejoin: "round",
1748
+ 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" })
1749
+ }
1750
+ ),
1477
1751
  "Wallet"
1478
1752
  ]
1479
1753
  }
@@ -1493,14 +1767,15 @@ function LoginModalTemplate({
1493
1767
  }
1494
1768
  function LoginModal({ onClose }) {
1495
1769
  const [email, setEmail] = useState("");
1496
- const { getClient, styles, appConfig: config } = usePollar();
1770
+ const { getClient, styles, appConfig: config, renderWallets } = usePollar();
1497
1771
  const [authState, setAuthState] = useState(() => getClient().getAuthState());
1498
1772
  const [codeInputKey, setCodeInputKey] = useState(0);
1499
1773
  const pendingEmail = useRef(null);
1500
1774
  const onCloseRef = useRef(onClose);
1501
1775
  onCloseRef.current = onClose;
1776
+ const autoCloseTimer = useRef(null);
1502
1777
  useEffect(() => {
1503
- return getClient().onAuthStateChange((next) => {
1778
+ const unsubscribe = getClient().onAuthStateChange((next) => {
1504
1779
  setAuthState(next);
1505
1780
  if (next.step === "entering_email" && pendingEmail.current) {
1506
1781
  getClient().sendEmailCode(pendingEmail.current);
@@ -1510,9 +1785,19 @@ function LoginModal({ onClose }) {
1510
1785
  setCodeInputKey((k) => k + 1);
1511
1786
  }
1512
1787
  if (next.step === "authenticated") {
1513
- setTimeout(onCloseRef.current, 1e3);
1788
+ autoCloseTimer.current = setTimeout(() => {
1789
+ autoCloseTimer.current = null;
1790
+ onCloseRef.current();
1791
+ }, 1e3);
1514
1792
  }
1515
1793
  });
1794
+ return () => {
1795
+ unsubscribe();
1796
+ if (autoCloseTimer.current !== null) {
1797
+ clearTimeout(autoCloseTimer.current);
1798
+ autoCloseTimer.current = null;
1799
+ }
1800
+ };
1516
1801
  }, [getClient]);
1517
1802
  const { theme = "light", accentColor = "#005DB4", logoUrl, emailEnabled, embeddedWallets, providers } = styles;
1518
1803
  function handleClose() {
@@ -1564,8 +1849,8 @@ function LoginModal({ onClose }) {
1564
1849
  onEmailChange: setEmail,
1565
1850
  onEmailSubmit: handleEmailSubmit,
1566
1851
  onSocialLogin: handleSocialLogin,
1567
- onFreighterConnect: () => handleWalletConnect(WalletType.FREIGHTER),
1568
- onAlbedoConnect: () => handleWalletConnect(WalletType.ALBEDO),
1852
+ onWalletConnect: handleWalletConnect,
1853
+ ...renderWallets !== void 0 && { renderWallets },
1569
1854
  authState,
1570
1855
  codeInputKey,
1571
1856
  onCodeSubmit: handleVerifyCode,
@@ -1575,166 +1860,6 @@ function LoginModal({ onClose }) {
1575
1860
  }
1576
1861
  ) });
1577
1862
  }
1578
-
1579
- // src/lib/qr-code/index.tsx
1580
- var import_ErrorCorrectLevel = __toESM(require_ErrorCorrectLevel());
1581
- var import_QRCode = __toESM(require_QRCode());
1582
- var QRCodeSvg = forwardRef(function QRCodeSvg2({
1583
- bgColor,
1584
- bgD,
1585
- fgD,
1586
- fgColor,
1587
- size,
1588
- title,
1589
- viewBoxSize,
1590
- xmlns = "http://www.w3.org/2000/svg",
1591
- ...props
1592
- }, ref) {
1593
- return /* @__PURE__ */ jsxs("svg", { ...props, height: size, ref, viewBox: `0 0 ${viewBoxSize} ${viewBoxSize}`, width: size, xmlns, children: [
1594
- title ? /* @__PURE__ */ jsx("title", { children: title }) : null,
1595
- /* @__PURE__ */ jsx("path", { d: bgD, fill: bgColor }),
1596
- /* @__PURE__ */ jsx("path", { d: fgD, fill: fgColor })
1597
- ] });
1598
- });
1599
- QRCodeSvg.displayName = "QRCodeSvg";
1600
- function bytesToBinaryString(bytes) {
1601
- return bytes.map((b) => String.fromCharCode(b & 255)).join("");
1602
- }
1603
- function encodeStringToUtf8Bytes(input) {
1604
- return Array.from(new TextEncoder().encode(input));
1605
- }
1606
- var QRCode = forwardRef(function QRCode2({ bgColor = "#FFFFFF", fgColor = "#000000", level = "L", size = 256, value, ...props }, ref) {
1607
- const qrcode = new import_QRCode.default(-1, import_ErrorCorrectLevel.default[level]);
1608
- const utf8Bytes = encodeStringToUtf8Bytes(value);
1609
- const binaryString = bytesToBinaryString(utf8Bytes);
1610
- qrcode.addData(binaryString, "Byte");
1611
- qrcode.make();
1612
- const cells = qrcode.modules;
1613
- return /* @__PURE__ */ jsx(
1614
- QRCodeSvg,
1615
- {
1616
- ...props,
1617
- bgColor,
1618
- bgD: cells.map((row, rowIndex) => row.map((cell, cellIndex) => !cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")).join(" "),
1619
- fgColor,
1620
- fgD: cells.map((row, rowIndex) => row.map((cell, cellIndex) => cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")).join(" "),
1621
- ref,
1622
- size,
1623
- viewBoxSize: cells.length
1624
- }
1625
- );
1626
- });
1627
- function ReceiveModalTemplate({
1628
- theme,
1629
- accentColor,
1630
- walletAddress,
1631
- copied,
1632
- onCopy,
1633
- onClose
1634
- }) {
1635
- const isDark = theme === "dark";
1636
- const cssVars = {
1637
- "--pollar-accent": accentColor,
1638
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
1639
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
1640
- "--pollar-text": isDark ? "#ffffff" : "#111827",
1641
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
1642
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
1643
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
1644
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
1645
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
1646
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
1647
- "--pollar-buttons-border-radius": "6px",
1648
- "--pollar-buttons-height": "44px",
1649
- "--pollar-input-height": "44px",
1650
- "--pollar-input-border-radius": "0.5rem",
1651
- "--pollar-card-border-radius": "10px"
1652
- };
1653
- return /* @__PURE__ */ jsxs(
1654
- "div",
1655
- {
1656
- className: "pollar-modal-card pollar-receive-modal",
1657
- "data-theme": theme,
1658
- style: cssVars,
1659
- onClick: (e) => e.stopPropagation(),
1660
- children: [
1661
- /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
1662
- /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Receive" }),
1663
- /* @__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" }) }) }) })
1664
- ] }),
1665
- walletAddress ? /* @__PURE__ */ jsxs(Fragment, { children: [
1666
- /* @__PURE__ */ jsx("div", { className: "pollar-receive-qr", children: /* @__PURE__ */ jsx(
1667
- QRCode,
1668
- {
1669
- value: walletAddress,
1670
- size: 180,
1671
- fgColor: isDark ? "#ffffff" : "#111827",
1672
- bgColor: "transparent"
1673
- }
1674
- ) }),
1675
- /* @__PURE__ */ jsx("p", { className: "pollar-receive-instructions", children: "Share your Stellar address to receive any asset. Only send Stellar assets to this address." }),
1676
- /* @__PURE__ */ jsxs("div", { className: "pollar-receive-address-row", children: [
1677
- /* @__PURE__ */ jsx("span", { className: "pollar-receive-address", children: walletAddress }),
1678
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-receive-copy-btn", onClick: onCopy, "aria-label": "Copy address", children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
1679
- /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
1680
- /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
1681
- /* @__PURE__ */ jsx(
1682
- "path",
1683
- {
1684
- d: "M3.5 7l2.5 2.5 4.5-5",
1685
- stroke: "white",
1686
- strokeWidth: "1.5",
1687
- strokeLinecap: "round",
1688
- strokeLinejoin: "round"
1689
- }
1690
- )
1691
- ] }),
1692
- "Copied!"
1693
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1694
- /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
1695
- /* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
1696
- /* @__PURE__ */ jsx(
1697
- "path",
1698
- {
1699
- d: "M3 9H2a1 1 0 01-1-1V2a1 1 0 011-1h6a1 1 0 011 1v1",
1700
- stroke: "currentColor",
1701
- strokeWidth: "1.5",
1702
- strokeLinecap: "round"
1703
- }
1704
- )
1705
- ] }),
1706
- "Copy address"
1707
- ] }) })
1708
- ] })
1709
- ] }) : /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No wallet connected." }),
1710
- /* @__PURE__ */ jsx(PollarModalFooter, {})
1711
- ]
1712
- }
1713
- );
1714
- }
1715
- function ReceiveModal({ onClose }) {
1716
- const { walletAddress, styles } = usePollar();
1717
- const { theme = "light", accentColor = "#005DB4" } = styles;
1718
- const [copied, setCopied] = useState(false);
1719
- function handleCopy() {
1720
- if (!walletAddress) return;
1721
- navigator.clipboard.writeText(walletAddress).then(() => {
1722
- setCopied(true);
1723
- setTimeout(() => setCopied(false), 2e3);
1724
- });
1725
- }
1726
- return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsx(
1727
- ReceiveModalTemplate,
1728
- {
1729
- theme,
1730
- accentColor,
1731
- walletAddress,
1732
- copied,
1733
- onCopy: handleCopy,
1734
- onClose
1735
- }
1736
- ) });
1737
- }
1738
1863
  var RAIL_LABELS = {
1739
1864
  SPEI: "SPEI (Mexico)",
1740
1865
  PIX: "PIX (Brazil)",
@@ -1842,8 +1967,26 @@ function RampWidgetTemplate({
1842
1967
  ] }),
1843
1968
  step === "input" && /* @__PURE__ */ jsxs(Fragment, { children: [
1844
1969
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-tabs", children: [
1845
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-ramp-tab", "data-active": direction === "onramp", onClick: () => onDirectionChange("onramp"), children: "Buy" }),
1846
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-ramp-tab", "data-active": direction === "offramp", onClick: () => onDirectionChange("offramp"), children: "Sell" })
1970
+ /* @__PURE__ */ jsx(
1971
+ "button",
1972
+ {
1973
+ type: "button",
1974
+ className: "pollar-ramp-tab",
1975
+ "data-active": direction === "onramp",
1976
+ onClick: () => onDirectionChange("onramp"),
1977
+ children: "Buy"
1978
+ }
1979
+ ),
1980
+ /* @__PURE__ */ jsx(
1981
+ "button",
1982
+ {
1983
+ type: "button",
1984
+ className: "pollar-ramp-tab",
1985
+ "data-active": direction === "offramp",
1986
+ onClick: () => onDirectionChange("offramp"),
1987
+ children: "Sell"
1988
+ }
1989
+ )
1847
1990
  ] }),
1848
1991
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-input-row", children: [
1849
1992
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
@@ -1948,17 +2091,79 @@ function RampWidgetTemplate({
1948
2091
  ] });
1949
2092
  }
1950
2093
  var MOCK_DEFAULT_QUOTES = [
1951
- { quoteId: "meld-default", provider: "Meld", fee: 1.2, feeCurrency: "USD", rate: 1, rail: "ACH", protocol: "REST", estimatedTime: "~20 min", recommended: true }
2094
+ {
2095
+ quoteId: "meld-default",
2096
+ provider: "Meld",
2097
+ fee: 1.2,
2098
+ feeCurrency: "USD",
2099
+ rate: 1,
2100
+ rail: "ACH",
2101
+ protocol: "REST",
2102
+ estimatedTime: "~20 min",
2103
+ recommended: true
2104
+ }
1952
2105
  ];
1953
2106
  var MOCK_QUOTES = {
1954
2107
  MX: [
1955
- { quoteId: "etherfuse-mx", provider: "Etherfuse", fee: 0.5, feeCurrency: "MXN", rate: 17.2, rail: "SPEI", protocol: "SEP-24", estimatedTime: "~10 min", recommended: true },
1956
- { quoteId: "alfredpay-mx", provider: "AlfredPay", fee: 0.8, feeCurrency: "MXN", rate: 17.1, rail: "SPEI", protocol: "REST", estimatedTime: "~15 min", recommended: false }
2108
+ {
2109
+ quoteId: "etherfuse-mx",
2110
+ provider: "Etherfuse",
2111
+ fee: 0.5,
2112
+ feeCurrency: "MXN",
2113
+ rate: 17.2,
2114
+ rail: "SPEI",
2115
+ protocol: "SEP-24",
2116
+ estimatedTime: "~10 min",
2117
+ recommended: true
2118
+ },
2119
+ {
2120
+ quoteId: "alfredpay-mx",
2121
+ provider: "AlfredPay",
2122
+ fee: 0.8,
2123
+ feeCurrency: "MXN",
2124
+ rate: 17.1,
2125
+ rail: "SPEI",
2126
+ protocol: "REST",
2127
+ estimatedTime: "~15 min",
2128
+ recommended: false
2129
+ }
2130
+ ],
2131
+ BR: [
2132
+ {
2133
+ quoteId: "abroad-br",
2134
+ provider: "Abroad",
2135
+ fee: 0.6,
2136
+ feeCurrency: "BRL",
2137
+ rate: 5.1,
2138
+ rail: "PIX",
2139
+ protocol: "REST",
2140
+ estimatedTime: "~5 min",
2141
+ recommended: true
2142
+ }
1957
2143
  ],
1958
- BR: [{ quoteId: "abroad-br", provider: "Abroad", fee: 0.6, feeCurrency: "BRL", rate: 5.1, rail: "PIX", protocol: "REST", estimatedTime: "~5 min", recommended: true }],
1959
2144
  CO: [
1960
- { quoteId: "abroad-co", provider: "Abroad", fee: 0.7, feeCurrency: "COP", rate: 4100, rail: "PSE", protocol: "REST", estimatedTime: "~10 min", recommended: true },
1961
- { quoteId: "koywe-co", provider: "Koywe", fee: 0.9, feeCurrency: "COP", rate: 4095, rail: "PSE", protocol: "REST", estimatedTime: "~15 min", recommended: false }
2145
+ {
2146
+ quoteId: "abroad-co",
2147
+ provider: "Abroad",
2148
+ fee: 0.7,
2149
+ feeCurrency: "COP",
2150
+ rate: 4100,
2151
+ rail: "PSE",
2152
+ protocol: "REST",
2153
+ estimatedTime: "~10 min",
2154
+ recommended: true
2155
+ },
2156
+ {
2157
+ quoteId: "koywe-co",
2158
+ provider: "Koywe",
2159
+ fee: 0.9,
2160
+ feeCurrency: "COP",
2161
+ rate: 4095,
2162
+ rail: "PSE",
2163
+ protocol: "REST",
2164
+ estimatedTime: "~15 min",
2165
+ recommended: false
2166
+ }
1962
2167
  ],
1963
2168
  DEFAULT: MOCK_DEFAULT_QUOTES
1964
2169
  };
@@ -2049,14 +2254,193 @@ function RampWidget({ onClose }) {
2049
2254
  }
2050
2255
  ) });
2051
2256
  }
2257
+
2258
+ // src/lib/qr-code/index.tsx
2259
+ var import_ErrorCorrectLevel = __toESM(require_ErrorCorrectLevel());
2260
+ var import_QRCode = __toESM(require_QRCode());
2261
+ var QRCodeSvg = forwardRef(function QRCodeSvg2({ bgColor, bgD, fgD, fgColor, size, title, viewBoxSize, xmlns = "http://www.w3.org/2000/svg", ...props }, ref) {
2262
+ return /* @__PURE__ */ jsxs("svg", { ...props, height: size, ref, viewBox: `0 0 ${viewBoxSize} ${viewBoxSize}`, width: size, xmlns, children: [
2263
+ title ? /* @__PURE__ */ jsx("title", { children: title }) : null,
2264
+ /* @__PURE__ */ jsx("path", { d: bgD, fill: bgColor }),
2265
+ /* @__PURE__ */ jsx("path", { d: fgD, fill: fgColor })
2266
+ ] });
2267
+ });
2268
+ QRCodeSvg.displayName = "QRCodeSvg";
2269
+ function bytesToBinaryString(bytes) {
2270
+ return bytes.map((b) => String.fromCharCode(b & 255)).join("");
2271
+ }
2272
+ function encodeStringToUtf8Bytes(input) {
2273
+ return Array.from(new TextEncoder().encode(input));
2274
+ }
2275
+ var QRCode = forwardRef(function QRCode2({ bgColor = "#FFFFFF", fgColor = "#000000", level = "L", size = 256, value, ...props }, ref) {
2276
+ const qrcode = new import_QRCode.default(-1, import_ErrorCorrectLevel.default[level]);
2277
+ const utf8Bytes = encodeStringToUtf8Bytes(value);
2278
+ const binaryString = bytesToBinaryString(utf8Bytes);
2279
+ qrcode.addData(binaryString, "Byte");
2280
+ qrcode.make();
2281
+ const cells = qrcode.modules;
2282
+ return /* @__PURE__ */ jsx(
2283
+ QRCodeSvg,
2284
+ {
2285
+ ...props,
2286
+ bgColor,
2287
+ bgD: cells.map(
2288
+ (row, rowIndex) => row.map((cell, cellIndex) => !cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")
2289
+ ).join(" "),
2290
+ fgColor,
2291
+ fgD: cells.map(
2292
+ (row, rowIndex) => row.map((cell, cellIndex) => cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")
2293
+ ).join(" "),
2294
+ ref,
2295
+ size,
2296
+ viewBoxSize: cells.length
2297
+ }
2298
+ );
2299
+ });
2300
+ function ReceiveModalTemplate({
2301
+ theme,
2302
+ accentColor,
2303
+ walletAddress,
2304
+ copied,
2305
+ onCopy,
2306
+ onClose
2307
+ }) {
2308
+ const isDark = theme === "dark";
2309
+ const cssVars = {
2310
+ "--pollar-accent": accentColor,
2311
+ "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
2312
+ "--pollar-border": isDark ? "#374151" : "#e5e7eb",
2313
+ "--pollar-text": isDark ? "#ffffff" : "#111827",
2314
+ "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
2315
+ "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
2316
+ "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
2317
+ "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
2318
+ "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
2319
+ "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
2320
+ "--pollar-buttons-border-radius": "6px",
2321
+ "--pollar-buttons-height": "44px",
2322
+ "--pollar-input-height": "44px",
2323
+ "--pollar-input-border-radius": "0.5rem",
2324
+ "--pollar-card-border-radius": "10px"
2325
+ };
2326
+ return /* @__PURE__ */ jsxs(
2327
+ "div",
2328
+ {
2329
+ className: "pollar-modal-card pollar-receive-modal",
2330
+ "data-theme": theme,
2331
+ style: cssVars,
2332
+ onClick: (e) => e.stopPropagation(),
2333
+ children: [
2334
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
2335
+ /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Receive" }),
2336
+ /* @__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" }) }) }) })
2337
+ ] }),
2338
+ walletAddress ? /* @__PURE__ */ jsxs(Fragment, { children: [
2339
+ /* @__PURE__ */ jsx("div", { className: "pollar-receive-qr", children: /* @__PURE__ */ jsx(QRCode, { value: walletAddress, size: 180, fgColor: isDark ? "#ffffff" : "#111827", bgColor: "transparent" }) }),
2340
+ /* @__PURE__ */ jsx("p", { className: "pollar-receive-instructions", children: "Share your Stellar address to receive any asset. Only send Stellar assets to this address." }),
2341
+ /* @__PURE__ */ jsxs("div", { className: "pollar-receive-address-row", children: [
2342
+ /* @__PURE__ */ jsx("span", { className: "pollar-receive-address", children: walletAddress }),
2343
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-receive-copy-btn", onClick: onCopy, "aria-label": "Copy address", children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
2344
+ /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
2345
+ /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
2346
+ /* @__PURE__ */ jsx(
2347
+ "path",
2348
+ {
2349
+ d: "M3.5 7l2.5 2.5 4.5-5",
2350
+ stroke: "white",
2351
+ strokeWidth: "1.5",
2352
+ strokeLinecap: "round",
2353
+ strokeLinejoin: "round"
2354
+ }
2355
+ )
2356
+ ] }),
2357
+ "Copied!"
2358
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2359
+ /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
2360
+ /* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
2361
+ /* @__PURE__ */ jsx(
2362
+ "path",
2363
+ {
2364
+ d: "M3 9H2a1 1 0 01-1-1V2a1 1 0 011-1h6a1 1 0 011 1v1",
2365
+ stroke: "currentColor",
2366
+ strokeWidth: "1.5",
2367
+ strokeLinecap: "round"
2368
+ }
2369
+ )
2370
+ ] }),
2371
+ "Copy address"
2372
+ ] }) })
2373
+ ] })
2374
+ ] }) : /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No wallet connected." }),
2375
+ /* @__PURE__ */ jsx(PollarModalFooter, {})
2376
+ ]
2377
+ }
2378
+ );
2379
+ }
2380
+ function ReceiveModal({ onClose }) {
2381
+ const { walletAddress, styles } = usePollar();
2382
+ const { theme = "light", accentColor = "#005DB4" } = styles;
2383
+ const [copied, setCopied] = useState(false);
2384
+ const copyTimerRef = useRef(null);
2385
+ useEffect(
2386
+ () => () => {
2387
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
2388
+ },
2389
+ []
2390
+ );
2391
+ function handleCopy() {
2392
+ if (!walletAddress) return;
2393
+ navigator.clipboard.writeText(walletAddress).then(() => {
2394
+ setCopied(true);
2395
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
2396
+ copyTimerRef.current = setTimeout(() => {
2397
+ copyTimerRef.current = null;
2398
+ setCopied(false);
2399
+ }, 2e3);
2400
+ });
2401
+ }
2402
+ return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsx(
2403
+ ReceiveModalTemplate,
2404
+ {
2405
+ theme,
2406
+ accentColor,
2407
+ walletAddress,
2408
+ copied,
2409
+ onCopy: handleCopy,
2410
+ onClose
2411
+ }
2412
+ ) });
2413
+ }
2052
2414
  var STATUS_MESSAGES = {
2053
2415
  idle: "",
2054
2416
  building: "Building transaction\u2026",
2055
2417
  built: "Ready to sign and send",
2056
- signing: "Signing and sending transaction\u2026",
2418
+ signing: "Signing transaction\u2026",
2419
+ signed: "Signed \u2014 ready to submit",
2420
+ submitting: "Submitting transaction\u2026",
2421
+ submitted: "Submitted \u2014 waiting for confirmation\u2026",
2422
+ "signing-submitting": "Signing and submitting transaction\u2026",
2423
+ "building-signing-submitting": "Processing transaction\u2026",
2057
2424
  success: "Transaction sent successfully",
2058
2425
  error: "Transaction failed"
2059
2426
  };
2427
+ var IN_FLIGHT_STEPS = /* @__PURE__ */ new Set([
2428
+ "building",
2429
+ "signing",
2430
+ "submitting",
2431
+ "submitted",
2432
+ "signing-submitting",
2433
+ "building-signing-submitting"
2434
+ ]);
2435
+ var SHOW_DETAILS_STEPS = /* @__PURE__ */ new Set([
2436
+ "built",
2437
+ "signing",
2438
+ "signed",
2439
+ "submitting",
2440
+ "submitted",
2441
+ "signing-submitting",
2442
+ "success"
2443
+ ]);
2060
2444
  function TxStatusView({
2061
2445
  transaction,
2062
2446
  showXdr,
@@ -2073,10 +2457,10 @@ function TxStatusView({
2073
2457
  const hash = transaction.step === "success" ? transaction.hash : null;
2074
2458
  const errorDetails = transaction.step === "error" ? transaction.details ?? null : null;
2075
2459
  const isBuilt = transaction.step === "built";
2076
- const isSigning = transaction.step === "signing";
2460
+ const isInFlight = IN_FLIGHT_STEPS.has(transaction.step);
2077
2461
  const isSuccess = transaction.step === "success";
2078
2462
  const isError = transaction.step === "error";
2079
- const showDetails = buildData !== null && (isBuilt || isSigning || isSuccess);
2463
+ const showDetails = buildData !== null && SHOW_DETAILS_STEPS.has(transaction.step);
2080
2464
  const walletImg = walletType === WalletType.FREIGHTER ? LOGO_FREIGHTER : walletType === WalletType.ALBEDO ? LOGO_ALBEDO : LOGO_POLLAR;
2081
2465
  const walletAlt = walletType === WalletType.FREIGHTER ? "Freighter" : walletType === WalletType.ALBEDO ? "Albedo" : "Pollar";
2082
2466
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -2119,7 +2503,7 @@ function TxStatusView({
2119
2503
  /* @__PURE__ */ jsx("pre", { className: "pollar-tx-error-details-content", children: errorDetails })
2120
2504
  ] }),
2121
2505
  isBuilt && /* @__PURE__ */ jsx("button", { className: "pollar-btn-primary pollar-tx-sign-btn", onClick: onSignAndSend, children: "Sign & Send" }),
2122
- (isSigning || isSuccess || isError) && /* @__PURE__ */ jsxs("div", { className: "pollar-tx-wallet-spinner", children: [
2506
+ (isInFlight || isSuccess || isError) && /* @__PURE__ */ jsxs("div", { className: "pollar-tx-wallet-spinner", children: [
2123
2507
  /* @__PURE__ */ jsxs("div", { className: "pollar-tx-spinner-ring", children: [
2124
2508
  /* @__PURE__ */ jsxs(
2125
2509
  "svg",
@@ -2127,7 +2511,7 @@ function TxStatusView({
2127
2511
  viewBox: "0 0 88 88",
2128
2512
  width: "88",
2129
2513
  height: "88",
2130
- className: `pollar-tx-spinner-svg${isSigning ? " pollar-tx-spinner-rotating" : ""}`,
2514
+ className: `pollar-tx-spinner-svg${isInFlight ? " pollar-tx-spinner-rotating" : ""}`,
2131
2515
  "aria-hidden": true,
2132
2516
  children: [
2133
2517
  /* @__PURE__ */ jsx("circle", { cx: "44", cy: "44", r: "36", fill: "none", stroke: "var(--pollar-border)", strokeWidth: "3" }),
@@ -2141,9 +2525,9 @@ function TxStatusView({
2141
2525
  stroke: isSuccess ? "var(--pollar-success-text)" : isError ? "var(--pollar-error-text)" : "var(--pollar-accent)",
2142
2526
  strokeWidth: "3",
2143
2527
  strokeLinecap: "round",
2144
- strokeDasharray: isSigning ? "169.6 56.6" : "999 0",
2528
+ strokeDasharray: isInFlight ? "169.6 56.6" : "999 0",
2145
2529
  transform: "rotate(-90 44 44)",
2146
- style: { transition: isSigning ? "none" : "stroke 400ms, stroke-dasharray 400ms" }
2530
+ style: { transition: isInFlight ? "none" : "stroke 400ms, stroke-dasharray 400ms" }
2147
2531
  }
2148
2532
  )
2149
2533
  ]
@@ -2151,7 +2535,7 @@ function TxStatusView({
2151
2535
  ),
2152
2536
  /* @__PURE__ */ jsx("div", { className: "pollar-tx-wallet-icon", children: /* @__PURE__ */ jsx("img", { src: walletImg, alt: walletAlt, className: "pollar-tx-wallet-img" }) })
2153
2537
  ] }),
2154
- 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" }),
2538
+ 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" }),
2155
2539
  isError && onRetry && "buildData" in transaction && transaction.buildData && /* @__PURE__ */ jsx("button", { className: "pollar-btn-secondary pollar-tx-retry-btn", onClick: onRetry, children: "Try again" })
2156
2540
  ] }),
2157
2541
  isSuccess && hash && /* @__PURE__ */ jsxs("div", { className: "pollar-tx-result", children: [
@@ -2219,7 +2603,7 @@ function TxStatusView({
2219
2603
  ModalStatusBanner,
2220
2604
  {
2221
2605
  message: STATUS_MESSAGES[transaction.step],
2222
- status: isError ? "ERROR" : isSigning || transaction.step === "building" ? "LOADING" : isSuccess ? "SUCCESS" : "NONE"
2606
+ status: isError ? "ERROR" : isInFlight ? "LOADING" : isSuccess ? "SUCCESS" : "NONE"
2223
2607
  }
2224
2608
  )
2225
2609
  ] });
@@ -2396,7 +2780,16 @@ function assetParam(record) {
2396
2780
  return { type: "credit_alphanum12", code: record.code, issuer: record.issuer };
2397
2781
  }
2398
2782
  function SendModal({ onClose }) {
2399
- const { walletBalance, refreshWalletBalance, buildTx, signAndSubmitTx, tx: transaction, walletType, network, styles } = usePollar();
2783
+ const {
2784
+ walletBalance,
2785
+ refreshWalletBalance,
2786
+ buildTx,
2787
+ signAndSubmitTx,
2788
+ tx: transaction,
2789
+ walletType,
2790
+ network,
2791
+ styles
2792
+ } = usePollar();
2400
2793
  const { theme = "light", accentColor = "#005DB4" } = styles;
2401
2794
  const [step, setStep] = useState("form");
2402
2795
  const [amount, setAmount] = useState("");
@@ -2405,9 +2798,16 @@ function SendModal({ onClose }) {
2405
2798
  const [showXdr, setShowXdr] = useState(false);
2406
2799
  const [copied, setCopied] = useState(false);
2407
2800
  const [formError, setFormError] = useState("");
2801
+ const copyTimerRef = useRef(null);
2408
2802
  useEffect(() => {
2409
2803
  void refreshWalletBalance();
2410
2804
  }, [refreshWalletBalance]);
2805
+ useEffect(
2806
+ () => () => {
2807
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
2808
+ },
2809
+ []
2810
+ );
2411
2811
  const balanceData = walletBalance.step === "loaded" ? walletBalance.data : null;
2412
2812
  const allAssets = balanceData?.balances ?? [];
2413
2813
  const sortedAssets = [
@@ -2418,9 +2818,17 @@ function SendModal({ onClose }) {
2418
2818
  const buildData = "buildData" in transaction ? transaction.buildData : null;
2419
2819
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
2420
2820
  const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
2421
- const isInProgress = transaction.step === "building" || transaction.step === "signing";
2821
+ const IN_FLIGHT_STEPS2 = [
2822
+ "building",
2823
+ "signing",
2824
+ "submitting",
2825
+ "submitted",
2826
+ "signing-submitting",
2827
+ "building-signing-submitting"
2828
+ ];
2829
+ const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
2422
2830
  const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
2423
- const txTitle = transaction.step === "signing" ? "Sending\u2026" : transaction.step === "success" ? "Sent!" : transaction.step === "error" ? "Send failed" : "Confirm Send";
2831
+ const txTitle = isInProgress ? "Sending\u2026" : transaction.step === "success" ? "Sent!" : transaction.step === "error" ? "Send failed" : "Confirm Send";
2424
2832
  async function handleSubmit() {
2425
2833
  setFormError("");
2426
2834
  if (!selectedAsset) {
@@ -2452,7 +2860,11 @@ function SendModal({ onClose }) {
2452
2860
  if (!hash) return;
2453
2861
  navigator.clipboard.writeText(hash).then(() => {
2454
2862
  setCopied(true);
2455
- setTimeout(() => setCopied(false), 2e3);
2863
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
2864
+ copyTimerRef.current = setTimeout(() => {
2865
+ copyTimerRef.current = null;
2866
+ setCopied(false);
2867
+ }, 2e3);
2456
2868
  });
2457
2869
  }
2458
2870
  async function handleRetry() {
@@ -2602,16 +3014,7 @@ function SessionsModalTemplate({
2602
3014
  "aria-hidden": true,
2603
3015
  children: [
2604
3016
  /* @__PURE__ */ jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
2605
- /* @__PURE__ */ jsx(
2606
- "path",
2607
- {
2608
- d: "M10 1v3h-3",
2609
- stroke: "currentColor",
2610
- strokeWidth: "1.5",
2611
- strokeLinecap: "round",
2612
- strokeLinejoin: "round"
2613
- }
2614
- )
3017
+ /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
2615
3018
  ]
2616
3019
  }
2617
3020
  ),
@@ -2679,9 +3082,12 @@ function SessionsModal({ onClose }) {
2679
3082
  const [revokingFamilyId, setRevokingFamilyId] = useState(null);
2680
3083
  const [signingOutEverywhere, setSigningOutEverywhere] = useState(false);
2681
3084
  const mountedRef = useRef(true);
2682
- useEffect(() => () => {
2683
- mountedRef.current = false;
2684
- }, []);
3085
+ useEffect(
3086
+ () => () => {
3087
+ mountedRef.current = false;
3088
+ },
3089
+ []
3090
+ );
2685
3091
  const onCloseRef = useRef(onClose);
2686
3092
  onCloseRef.current = onClose;
2687
3093
  useEffect(() => {
@@ -2713,9 +3119,7 @@ function SessionsModal({ onClose }) {
2713
3119
  await load();
2714
3120
  } catch {
2715
3121
  if (!mountedRef.current) return;
2716
- setState(
2717
- (prev) => prev.step === "loaded" ? { step: "error", message: "Failed to revoke session" } : prev
2718
- );
3122
+ setState((prev) => prev.step === "loaded" ? { step: "error", message: "Failed to revoke session" } : prev);
2719
3123
  } finally {
2720
3124
  if (mountedRef.current) setRevokingFamilyId(null);
2721
3125
  }
@@ -2779,55 +3183,53 @@ function TransactionModalTemplate({
2779
3183
  "--pollar-input-border-radius": "0.5rem",
2780
3184
  "--pollar-card-border-radius": "10px"
2781
3185
  };
2782
- return /* @__PURE__ */ jsxs(
2783
- "div",
2784
- {
2785
- className: "pollar-modal-card pollar-tx-modal",
2786
- "data-theme": theme,
2787
- style: cssVars,
2788
- onClick: (e) => e.stopPropagation(),
2789
- children: [
2790
- /* @__PURE__ */ jsx("div", { className: "pollar-modal-header", children: /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Transaction" }) }),
2791
- /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-close-btn", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(
2792
- "svg",
2793
- {
2794
- width: "18",
2795
- height: "18",
2796
- viewBox: "0 0 24 24",
2797
- fill: "none",
2798
- stroke: "currentColor",
2799
- strokeWidth: "2.5",
2800
- strokeLinecap: "round",
2801
- strokeLinejoin: "round",
2802
- "aria-hidden": true,
2803
- children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
2804
- }
2805
- ) }),
2806
- /* @__PURE__ */ jsx(
2807
- TxStatusView,
2808
- {
2809
- transaction,
2810
- showXdr,
2811
- copied,
2812
- explorerUrl,
2813
- walletType,
2814
- onSignAndSend,
2815
- onToggleXdr,
2816
- onCopyHash,
2817
- onRetry,
2818
- onDone: onClose
2819
- }
2820
- ),
2821
- /* @__PURE__ */ jsx(PollarModalFooter, {})
2822
- ]
2823
- }
2824
- );
3186
+ return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-tx-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
3187
+ /* @__PURE__ */ jsx("div", { className: "pollar-modal-header", children: /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Transaction" }) }),
3188
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-close-btn", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(
3189
+ "svg",
3190
+ {
3191
+ width: "18",
3192
+ height: "18",
3193
+ viewBox: "0 0 24 24",
3194
+ fill: "none",
3195
+ stroke: "currentColor",
3196
+ strokeWidth: "2.5",
3197
+ strokeLinecap: "round",
3198
+ strokeLinejoin: "round",
3199
+ "aria-hidden": true,
3200
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
3201
+ }
3202
+ ) }),
3203
+ /* @__PURE__ */ jsx(
3204
+ TxStatusView,
3205
+ {
3206
+ transaction,
3207
+ showXdr,
3208
+ copied,
3209
+ explorerUrl,
3210
+ walletType,
3211
+ onSignAndSend,
3212
+ onToggleXdr,
3213
+ onCopyHash,
3214
+ onRetry,
3215
+ onDone: onClose
3216
+ }
3217
+ ),
3218
+ /* @__PURE__ */ jsx(PollarModalFooter, {})
3219
+ ] });
2825
3220
  }
2826
3221
  function TransactionModal({ onClose }) {
2827
3222
  const { getClient, styles, tx: transaction, network, walletType } = usePollar();
2828
3223
  const { theme = "light", accentColor = "#005DB4" } = styles;
2829
3224
  const [showXdr, setShowXdr] = useState(false);
2830
3225
  const [copied, setCopied] = useState(false);
3226
+ const copyTimerRef = useRef(null);
3227
+ useEffect(
3228
+ () => () => {
3229
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
3230
+ },
3231
+ []
3232
+ );
2831
3233
  const hash = transaction.step === "success" ? transaction.hash : null;
2832
3234
  const buildData = "buildData" in transaction ? transaction.buildData : null;
2833
3235
  const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
@@ -2841,7 +3243,11 @@ function TransactionModal({ onClose }) {
2841
3243
  if (!hash) return;
2842
3244
  navigator.clipboard.writeText(hash).then(() => {
2843
3245
  setCopied(true);
2844
- setTimeout(() => setCopied(false), 2e3);
3246
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
3247
+ copyTimerRef.current = setTimeout(() => {
3248
+ copyTimerRef.current = null;
3249
+ setCopied(false);
3250
+ }, 2e3);
2845
3251
  });
2846
3252
  }
2847
3253
  async function handleRetry() {
@@ -2908,97 +3314,128 @@ function TxHistoryModalTemplate({
2908
3314
  const hasPrev = offset > 0;
2909
3315
  const hasNext = offset + PAGE_SIZE < total;
2910
3316
  const showPagination = txHistory.step === "loaded" && total > PAGE_SIZE;
2911
- return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-hist-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
2912
- /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
2913
- /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Transaction History" }),
2914
- /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
2915
- /* @__PURE__ */ jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading, children: [
2916
- /* @__PURE__ */ jsxs(
2917
- "svg",
2918
- {
2919
- className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
2920
- width: "13",
2921
- height: "13",
2922
- viewBox: "0 0 13 13",
2923
- fill: "none",
2924
- "aria-hidden": true,
2925
- children: [
2926
- /* @__PURE__ */ jsx(
2927
- "path",
3317
+ return /* @__PURE__ */ jsxs(
3318
+ "div",
3319
+ {
3320
+ className: "pollar-modal-card pollar-hist-modal",
3321
+ "data-theme": theme,
3322
+ style: cssVars,
3323
+ onClick: (e) => e.stopPropagation(),
3324
+ children: [
3325
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
3326
+ /* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Transaction History" }),
3327
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
3328
+ /* @__PURE__ */ jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading, children: [
3329
+ /* @__PURE__ */ jsxs(
3330
+ "svg",
3331
+ {
3332
+ className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
3333
+ width: "13",
3334
+ height: "13",
3335
+ viewBox: "0 0 13 13",
3336
+ fill: "none",
3337
+ "aria-hidden": true,
3338
+ children: [
3339
+ /* @__PURE__ */ jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
3340
+ /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
3341
+ ]
3342
+ }
3343
+ ),
3344
+ "Refresh"
3345
+ ] }),
3346
+ /* @__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" }) }) })
3347
+ ] })
3348
+ ] }),
3349
+ /* @__PURE__ */ jsxs("div", { className: "pollar-hist-list", children: [
3350
+ txHistory.step === "idle" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Click Refresh to load transactions." }),
3351
+ isLoading && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
3352
+ txHistory.step === "error" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: txHistory.message }),
3353
+ txHistory.step === "loaded" && records.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No transactions yet." }),
3354
+ records.map((record) => {
3355
+ const explorerUrl = `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${record.hash}`;
3356
+ return /* @__PURE__ */ jsxs("div", { className: "pollar-hist-item", children: [
3357
+ /* @__PURE__ */ jsx("span", { className: "pollar-hist-item-summary", children: record.summary }),
3358
+ /* @__PURE__ */ jsx(StatusBadge, { status: record.status }),
3359
+ /* @__PURE__ */ jsxs("span", { className: "pollar-hist-item-meta", children: [
3360
+ /* @__PURE__ */ jsx("span", { children: record.operation }),
3361
+ record.feeXlm && /* @__PURE__ */ jsxs("span", { children: [
3362
+ "\xB7 ",
3363
+ record.feeXlm,
3364
+ " XLM"
3365
+ ] }),
3366
+ /* @__PURE__ */ jsxs("span", { children: [
3367
+ "\xB7 ",
3368
+ formatDate(record.createdAt)
3369
+ ] }),
3370
+ /* @__PURE__ */ jsx("span", { children: "\xB7" }),
3371
+ /* @__PURE__ */ jsxs(
3372
+ "a",
2928
3373
  {
2929
- d: "M11.5 6.5a5 5 0 11-1.5-3.536",
2930
- stroke: "currentColor",
2931
- strokeWidth: "1.5",
2932
- strokeLinecap: "round"
3374
+ className: "pollar-hist-item-explorer",
3375
+ href: explorerUrl,
3376
+ target: "_blank",
3377
+ rel: "noopener noreferrer",
3378
+ "aria-label": "View on Stellar Explorer",
3379
+ children: [
3380
+ /* @__PURE__ */ jsxs("svg", { width: "11", height: "11", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
3381
+ /* @__PURE__ */ jsx(
3382
+ "path",
3383
+ {
3384
+ d: "M5 2H2a1 1 0 00-1 1v8a1 1 0 001 1h8a1 1 0 001-1V8",
3385
+ stroke: "currentColor",
3386
+ strokeWidth: "1.5",
3387
+ strokeLinecap: "round"
3388
+ }
3389
+ ),
3390
+ /* @__PURE__ */ jsx(
3391
+ "path",
3392
+ {
3393
+ d: "M8 1h4m0 0v4m0-4L6 7",
3394
+ stroke: "currentColor",
3395
+ strokeWidth: "1.5",
3396
+ strokeLinecap: "round",
3397
+ strokeLinejoin: "round"
3398
+ }
3399
+ )
3400
+ ] }),
3401
+ "Explorer"
3402
+ ]
2933
3403
  }
2934
- ),
2935
- /* @__PURE__ */ jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
2936
- ]
2937
- }
2938
- ),
2939
- "Refresh"
3404
+ )
3405
+ ] })
3406
+ ] }, record.id);
3407
+ })
2940
3408
  ] }),
2941
- /* @__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" }) }) })
2942
- ] })
2943
- ] }),
2944
- /* @__PURE__ */ jsxs("div", { className: "pollar-hist-list", children: [
2945
- txHistory.step === "idle" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Click Refresh to load transactions." }),
2946
- isLoading && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
2947
- txHistory.step === "error" && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: txHistory.message }),
2948
- txHistory.step === "loaded" && records.length === 0 && /* @__PURE__ */ jsx("div", { className: "pollar-modal-empty", children: "No transactions yet." }),
2949
- records.map((record) => {
2950
- const explorerUrl = `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${record.hash}`;
2951
- return /* @__PURE__ */ jsxs("div", { className: "pollar-hist-item", children: [
2952
- /* @__PURE__ */ jsx("span", { className: "pollar-hist-item-summary", children: record.summary }),
2953
- /* @__PURE__ */ jsx(StatusBadge, { status: record.status }),
2954
- /* @__PURE__ */ jsxs("span", { className: "pollar-hist-item-meta", children: [
2955
- /* @__PURE__ */ jsx("span", { children: record.operation }),
2956
- record.feeXlm && /* @__PURE__ */ jsxs("span", { children: [
2957
- "\xB7 ",
2958
- record.feeXlm,
2959
- " XLM"
2960
- ] }),
2961
- /* @__PURE__ */ jsxs("span", { children: [
2962
- "\xB7 ",
2963
- formatDate(record.createdAt)
2964
- ] }),
2965
- /* @__PURE__ */ jsx("span", { children: "\xB7" }),
2966
- /* @__PURE__ */ jsxs("a", { className: "pollar-hist-item-explorer", href: explorerUrl, target: "_blank", rel: "noopener noreferrer", "aria-label": "View on Stellar Explorer", children: [
2967
- /* @__PURE__ */ jsxs("svg", { width: "11", height: "11", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
2968
- /* @__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" }),
2969
- /* @__PURE__ */ jsx("path", { d: "M8 1h4m0 0v4m0-4L6 7", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
2970
- ] }),
2971
- "Explorer"
2972
- ] })
3409
+ showPagination && /* @__PURE__ */ jsxs("div", { className: "pollar-hist-pagination", children: [
3410
+ /* @__PURE__ */ jsxs("span", { className: "pollar-hist-pagination-info", children: [
3411
+ offset + 1,
3412
+ "\u2013",
3413
+ Math.min(offset + PAGE_SIZE, total),
3414
+ " of ",
3415
+ total
3416
+ ] }),
3417
+ /* @__PURE__ */ jsxs("div", { className: "pollar-hist-pagination-btns", children: [
3418
+ /* @__PURE__ */ jsx("button", { className: "pollar-hist-page-btn", onClick: onPrev, disabled: !hasPrev, children: "\u2190 Prev" }),
3419
+ /* @__PURE__ */ jsx("button", { className: "pollar-hist-page-btn", onClick: onNext, disabled: !hasNext, children: "Next \u2192" })
2973
3420
  ] })
2974
- ] }, record.id);
2975
- })
2976
- ] }),
2977
- showPagination && /* @__PURE__ */ jsxs("div", { className: "pollar-hist-pagination", children: [
2978
- /* @__PURE__ */ jsxs("span", { className: "pollar-hist-pagination-info", children: [
2979
- offset + 1,
2980
- "\u2013",
2981
- Math.min(offset + PAGE_SIZE, total),
2982
- " of ",
2983
- total
2984
- ] }),
2985
- /* @__PURE__ */ jsxs("div", { className: "pollar-hist-pagination-btns", children: [
2986
- /* @__PURE__ */ jsx("button", { className: "pollar-hist-page-btn", onClick: onPrev, disabled: !hasPrev, children: "\u2190 Prev" }),
2987
- /* @__PURE__ */ jsx("button", { className: "pollar-hist-page-btn", onClick: onNext, disabled: !hasNext, children: "Next \u2192" })
2988
- ] })
2989
- ] }),
2990
- /* @__PURE__ */ jsx(PollarModalFooter, {})
2991
- ] });
3421
+ ] }),
3422
+ /* @__PURE__ */ jsx(PollarModalFooter, {})
3423
+ ]
3424
+ }
3425
+ );
2992
3426
  }
2993
3427
  var PAGE_SIZE2 = 10;
2994
3428
  function TxHistoryModal({ onClose }) {
2995
3429
  const { getClient, styles, txHistory } = usePollar();
2996
3430
  const { theme = "light", accentColor = "#005DB4" } = styles;
2997
3431
  const [offset, setOffset] = useState(0);
2998
- const load = useCallback((nextOffset) => {
2999
- setOffset(nextOffset);
3000
- void getClient().fetchTxHistory({ limit: PAGE_SIZE2, offset: nextOffset });
3001
- }, [getClient]);
3432
+ const load = useCallback(
3433
+ (nextOffset) => {
3434
+ setOffset(nextOffset);
3435
+ void getClient().fetchTxHistory({ limit: PAGE_SIZE2, offset: nextOffset });
3436
+ },
3437
+ [getClient]
3438
+ );
3002
3439
  useEffect(() => {
3003
3440
  load(0);
3004
3441
  }, [load]);
@@ -3121,28 +3558,31 @@ function WalletBalanceModal({ onClose }) {
3121
3558
  }
3122
3559
  ) });
3123
3560
  }
3124
- var emptyResponse = {
3125
- application: {
3126
- name: ""
3127
- },
3561
+ var DEFAULT_APP_CONFIG = {
3562
+ application: { name: "" },
3128
3563
  styles: {}
3129
3564
  };
3130
- async function fetchRemoteConfig(client) {
3131
- const content = await client.getAppConfig();
3132
- return content ?? emptyResponse;
3565
+ function sessionsEqual(a, b) {
3566
+ if (a === b) return true;
3567
+ if (!a || !b) return false;
3568
+ 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;
3133
3569
  }
3134
3570
  var PollarContext = createContext(null);
3135
- function PollarProvider({ config, styles: propStyles, adapters, children }) {
3136
- const [pollarClient] = useState(() => new PollarClient(config));
3571
+ function PollarProvider({
3572
+ client,
3573
+ appConfig: appConfigProp,
3574
+ ui,
3575
+ adapters,
3576
+ onStorageDegrade,
3577
+ children
3578
+ }) {
3579
+ const [pollarClient] = useState(() => client instanceof PollarClient ? client : new PollarClient(client));
3137
3580
  const [networkState, setNetworkState] = useState(() => pollarClient.getNetworkState());
3138
3581
  const [sessionState, setSessionState] = useState(null);
3139
3582
  const [transaction, setTransaction] = useState({ step: "idle" });
3140
3583
  const [txHistory, setTxHistory] = useState({ step: "idle" });
3141
3584
  const [walletBalance, setWalletBalance] = useState({ step: "idle" });
3142
- const [remoteConfig, setRemoteConfig] = useState(emptyResponse);
3143
- const [styles, setStyles] = useState(propStyles ?? {});
3144
- const propStylesRef = useRef(propStyles);
3145
- propStylesRef.current = propStyles;
3585
+ const [resolvedConfig, setResolvedConfig] = useState(() => appConfigProp ?? DEFAULT_APP_CONFIG);
3146
3586
  useEffect(() => {
3147
3587
  return pollarClient.onTransactionStateChange(setTransaction);
3148
3588
  }, [pollarClient]);
@@ -3157,28 +3597,32 @@ function PollarProvider({ config, styles: propStyles, adapters, children }) {
3157
3597
  setNetworkState(state);
3158
3598
  });
3159
3599
  }, [pollarClient]);
3600
+ useEffect(() => {
3601
+ if (!onStorageDegrade) return;
3602
+ return pollarClient.onStorageDegrade(onStorageDegrade);
3603
+ }, [pollarClient, onStorageDegrade]);
3160
3604
  useEffect(() => {
3161
3605
  return pollarClient.onAuthStateChange((authState) => {
3162
3606
  if (authState.step === "authenticated") {
3163
- setSessionState((prev) => JSON.stringify(prev) !== JSON.stringify(authState.session) ? authState.session : prev);
3607
+ setSessionState((prev) => sessionsEqual(prev, authState.session) ? prev : authState.session);
3164
3608
  } else if (authState.step === "idle") {
3165
3609
  setSessionState(null);
3166
3610
  }
3167
3611
  });
3168
3612
  }, [pollarClient]);
3169
3613
  useEffect(() => {
3170
- const propStyles2 = propStylesRef.current;
3171
- fetchRemoteConfig(pollarClient).then((fetched) => {
3172
- setRemoteConfig(fetched);
3173
- setStyles({
3174
- ...fetched.styles,
3175
- ...propStyles2,
3176
- providers: { ...fetched.styles?.providers, ...propStyles2?.providers }
3177
- });
3178
- }).catch(() => {
3179
- setStyles(propStyles2 ?? {});
3614
+ if (appConfigProp !== void 0) return;
3615
+ let cancelled = false;
3616
+ pollarClient.getAppConfig().then((fetched) => {
3617
+ if (cancelled || !fetched) return;
3618
+ setResolvedConfig(fetched);
3619
+ }).catch((err) => {
3620
+ console.error("[PollarProvider] getAppConfig failed", err);
3180
3621
  });
3181
- }, [pollarClient]);
3622
+ return () => {
3623
+ cancelled = true;
3624
+ };
3625
+ }, [pollarClient, appConfigProp]);
3182
3626
  const [loginModalOpen, setLoginModalOpen] = useState(false);
3183
3627
  const [transactionModalOpen, setTransactionModalOpen] = useState(false);
3184
3628
  const [kycModalOpen, setKycModalOpen] = useState(false);
@@ -3189,13 +3633,14 @@ function PollarProvider({ config, styles: propStyles, adapters, children }) {
3189
3633
  const [sendModalOpen, setSendModalOpen] = useState(false);
3190
3634
  const [receiveModalOpen, setReceiveModalOpen] = useState(false);
3191
3635
  const [sessionsModalOpen, setSessionsModalOpen] = useState(false);
3192
- const adaptersRef = useRef(adapters);
3193
- adaptersRef.current = adapters;
3636
+ const [distributionRulesModalOpen, setDistributionRulesModalOpen] = useState(false);
3194
3637
  const walletAddress = sessionState?.wallet?.publicKey || "";
3195
3638
  const getClient = useCallback(() => pollarClient, [pollarClient]);
3196
3639
  const refreshWalletBalance = useCallback(() => pollarClient.refreshBalance(walletAddress), [pollarClient, walletAddress]);
3197
- const contextValue = useMemo(
3198
- () => ({
3640
+ const renderWallets = ui?.renderWallets;
3641
+ const contextValue = useMemo(() => {
3642
+ const styles = resolvedConfig.styles ?? {};
3643
+ return {
3199
3644
  // session
3200
3645
  walletAddress,
3201
3646
  isAuthenticated: !!walletAddress,
@@ -3210,6 +3655,10 @@ function PollarProvider({ config, styles: propStyles, adapters, children }) {
3210
3655
  tx: transaction,
3211
3656
  buildTx: (operation, params, options) => pollarClient.buildTx(operation, params, options),
3212
3657
  signAndSubmitTx: (unsignedXdr) => pollarClient.signAndSubmitTx(unsignedXdr),
3658
+ signTx: (unsignedXdr) => pollarClient.signTx(unsignedXdr),
3659
+ submitTx: (signedXdr) => pollarClient.submitTx(signedXdr),
3660
+ buildAndSignAndSubmitTx: (operation, params, options) => pollarClient.buildAndSignAndSubmitTx(operation, params, options),
3661
+ runTx: (operation, params, options) => pollarClient.runTx(operation, params, options),
3213
3662
  openTxModal: () => setTransactionModalOpen(true),
3214
3663
  // tx history
3215
3664
  txHistory,
@@ -3223,6 +3672,8 @@ function PollarProvider({ config, styles: propStyles, adapters, children }) {
3223
3672
  openReceiveModal: () => setReceiveModalOpen(true),
3224
3673
  // sessions
3225
3674
  openSessionsModal: () => setSessionsModalOpen(true),
3675
+ // distribution
3676
+ openDistributionRulesModal: () => setDistributionRulesModalOpen(true),
3226
3677
  // network
3227
3678
  network: networkState.step === "connected" ? networkState.network : "testnet",
3228
3679
  setNetwork: (network) => pollarClient.setNetwork(network),
@@ -3234,12 +3685,24 @@ function PollarProvider({ config, styles: propStyles, adapters, children }) {
3234
3685
  // ramp
3235
3686
  openRampModal: () => setRampModalOpen(true),
3236
3687
  // config
3237
- appConfig: remoteConfig,
3688
+ appConfig: resolvedConfig,
3238
3689
  styles,
3239
- adapters: adaptersRef.current
3240
- }),
3241
- [walletAddress, pollarClient, getClient, transaction, txHistory, walletBalance, refreshWalletBalance, networkState, remoteConfig, styles]
3242
- );
3690
+ renderWallets,
3691
+ adapters
3692
+ };
3693
+ }, [
3694
+ walletAddress,
3695
+ pollarClient,
3696
+ getClient,
3697
+ transaction,
3698
+ txHistory,
3699
+ walletBalance,
3700
+ refreshWalletBalance,
3701
+ networkState,
3702
+ resolvedConfig,
3703
+ adapters,
3704
+ renderWallets
3705
+ ]);
3243
3706
  return /* @__PURE__ */ jsxs(PollarContext.Provider, { value: contextValue, children: [
3244
3707
  children,
3245
3708
  loginModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setLoginModalOpen(false), children: /* @__PURE__ */ jsx(LoginModal, { onClose: () => setLoginModalOpen(false) }) }),
@@ -3258,7 +3721,8 @@ function PollarProvider({ config, styles: propStyles, adapters, children }) {
3258
3721
  walletBalanceModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setWalletBalanceModalOpen(false), children: /* @__PURE__ */ jsx(WalletBalanceModal, { onClose: () => setWalletBalanceModalOpen(false) }) }),
3259
3722
  sendModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSendModalOpen(false), children: /* @__PURE__ */ jsx(SendModal, { onClose: () => setSendModalOpen(false) }) }),
3260
3723
  receiveModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setReceiveModalOpen(false), children: /* @__PURE__ */ jsx(ReceiveModal, { onClose: () => setReceiveModalOpen(false) }) }),
3261
- sessionsModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSessionsModalOpen(false), children: /* @__PURE__ */ jsx(SessionsModal, { onClose: () => setSessionsModalOpen(false) }) })
3724
+ sessionsModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSessionsModalOpen(false), children: /* @__PURE__ */ jsx(SessionsModal, { onClose: () => setSessionsModalOpen(false) }) }),
3725
+ distributionRulesModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setDistributionRulesModalOpen(false), children: /* @__PURE__ */ jsx(DistributionRulesModal, { onClose: () => setDistributionRulesModalOpen(false) }) })
3262
3726
  ] });
3263
3727
  }
3264
3728
  function usePollar() {
@@ -3282,7 +3746,7 @@ function createPollarAdapterHook(key) {
3282
3746
  name,
3283
3747
  async (params) => {
3284
3748
  const { unsignedTransaction } = await fn(params);
3285
- await signAndSubmitTx(unsignedTransaction);
3749
+ return signAndSubmitTx(unsignedTransaction);
3286
3750
  }
3287
3751
  ])
3288
3752
  );
@@ -3331,33 +3795,22 @@ function WalletButtonTemplate({
3331
3795
  "aria-busy": isInProgress,
3332
3796
  children: [
3333
3797
  /* @__PURE__ */ jsx("span", { className: "wallet-btn-label", children: cropWallet(walletAddress) }),
3334
- isInProgress ? /* @__PURE__ */ jsxs(
3335
- "svg",
3336
- {
3337
- className: "wallet-btn-spinner",
3338
- viewBox: "0 0 12 12",
3339
- width: "12",
3340
- height: "12",
3341
- fill: "none",
3342
- "aria-hidden": true,
3343
- children: [
3344
- /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "4.5", stroke: "rgba(255,255,255,0.35)", strokeWidth: "1.5" }),
3345
- /* @__PURE__ */ jsx(
3346
- "circle",
3347
- {
3348
- cx: "6",
3349
- cy: "6",
3350
- r: "4.5",
3351
- stroke: "white",
3352
- strokeWidth: "1.5",
3353
- strokeLinecap: "round",
3354
- strokeDasharray: "14 9",
3355
- transform: "rotate(-90 6 6)"
3356
- }
3357
- )
3358
- ]
3359
- }
3360
- ) : /* @__PURE__ */ jsx(
3798
+ isInProgress ? /* @__PURE__ */ jsxs("svg", { className: "wallet-btn-spinner", viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", "aria-hidden": true, children: [
3799
+ /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "4.5", stroke: "rgba(255,255,255,0.35)", strokeWidth: "1.5" }),
3800
+ /* @__PURE__ */ jsx(
3801
+ "circle",
3802
+ {
3803
+ cx: "6",
3804
+ cy: "6",
3805
+ r: "4.5",
3806
+ stroke: "white",
3807
+ strokeWidth: "1.5",
3808
+ strokeLinecap: "round",
3809
+ strokeDasharray: "14 9",
3810
+ transform: "rotate(-90 6 6)"
3811
+ }
3812
+ )
3813
+ ] }) : /* @__PURE__ */ jsx(
3361
3814
  "svg",
3362
3815
  {
3363
3816
  className: `wallet-chevron${open ? " open" : ""}`,
@@ -3375,53 +3828,131 @@ function WalletButtonTemplate({
3375
3828
  ),
3376
3829
  open && /* @__PURE__ */ jsxs("div", { className: "wallet-dropdown", style: { backgroundColor: dropdownBg, borderColor: dropdownBorder }, children: [
3377
3830
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onSend, children: [
3378
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3379
- /* @__PURE__ */ jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
3380
- /* @__PURE__ */ jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
3381
- ] }),
3831
+ /* @__PURE__ */ jsxs(
3832
+ "svg",
3833
+ {
3834
+ width: "14",
3835
+ height: "14",
3836
+ viewBox: "0 0 24 24",
3837
+ fill: "none",
3838
+ stroke: "currentColor",
3839
+ strokeWidth: "2",
3840
+ strokeLinecap: "round",
3841
+ strokeLinejoin: "round",
3842
+ children: [
3843
+ /* @__PURE__ */ jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
3844
+ /* @__PURE__ */ jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
3845
+ ]
3846
+ }
3847
+ ),
3382
3848
  "Send"
3383
3849
  ] }),
3384
3850
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onReceive, children: [
3385
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3386
- /* @__PURE__ */ jsx("polyline", { points: "8 17 12 21 16 17" }),
3387
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "12", x2: "12", y2: "21" }),
3388
- /* @__PURE__ */ jsx("path", { d: "M20.88 18.09A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.29" })
3389
- ] }),
3851
+ /* @__PURE__ */ jsxs(
3852
+ "svg",
3853
+ {
3854
+ width: "14",
3855
+ height: "14",
3856
+ viewBox: "0 0 24 24",
3857
+ fill: "none",
3858
+ stroke: "currentColor",
3859
+ strokeWidth: "2",
3860
+ strokeLinecap: "round",
3861
+ strokeLinejoin: "round",
3862
+ children: [
3863
+ /* @__PURE__ */ jsx("polyline", { points: "8 17 12 21 16 17" }),
3864
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "12", x2: "12", y2: "21" }),
3865
+ /* @__PURE__ */ jsx("path", { d: "M20.88 18.09A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.29" })
3866
+ ]
3867
+ }
3868
+ ),
3390
3869
  "Receive"
3391
3870
  ] }),
3392
3871
  /* @__PURE__ */ jsx("div", { className: "wallet-dropdown-divider" }),
3393
3872
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onCopy, children: [
3394
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3395
- /* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
3396
- /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
3397
- ] }),
3873
+ /* @__PURE__ */ jsxs(
3874
+ "svg",
3875
+ {
3876
+ width: "14",
3877
+ height: "14",
3878
+ viewBox: "0 0 24 24",
3879
+ fill: "none",
3880
+ stroke: "currentColor",
3881
+ strokeWidth: "2",
3882
+ strokeLinecap: "round",
3883
+ strokeLinejoin: "round",
3884
+ children: [
3885
+ /* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
3886
+ /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
3887
+ ]
3888
+ }
3889
+ ),
3398
3890
  copied ? "Copied!" : "Copy address"
3399
3891
  ] }),
3400
3892
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onWalletBalance, children: [
3401
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3402
- /* @__PURE__ */ jsx("rect", { x: "1", y: "4", width: "22", height: "16", rx: "2", ry: "2" }),
3403
- /* @__PURE__ */ jsx("circle", { cx: "16", cy: "12", r: "2" }),
3404
- /* @__PURE__ */ jsx("path", { d: "M22 8H12" })
3405
- ] }),
3893
+ /* @__PURE__ */ jsxs(
3894
+ "svg",
3895
+ {
3896
+ width: "14",
3897
+ height: "14",
3898
+ viewBox: "0 0 24 24",
3899
+ fill: "none",
3900
+ stroke: "currentColor",
3901
+ strokeWidth: "2",
3902
+ strokeLinecap: "round",
3903
+ strokeLinejoin: "round",
3904
+ children: [
3905
+ /* @__PURE__ */ jsx("rect", { x: "1", y: "4", width: "22", height: "16", rx: "2", ry: "2" }),
3906
+ /* @__PURE__ */ jsx("circle", { cx: "16", cy: "12", r: "2" }),
3907
+ /* @__PURE__ */ jsx("path", { d: "M22 8H12" })
3908
+ ]
3909
+ }
3910
+ ),
3406
3911
  "Wallet balance"
3407
3912
  ] }),
3408
3913
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item", style: { color: itemColor }, onClick: onTxHistory, children: [
3409
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3410
- /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
3411
- /* @__PURE__ */ jsx("polyline", { points: "14,2 14,8 20,8" }),
3412
- /* @__PURE__ */ jsx("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
3413
- /* @__PURE__ */ jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
3414
- /* @__PURE__ */ jsx("polyline", { points: "10,9 9,9 8,9" })
3415
- ] }),
3914
+ /* @__PURE__ */ jsxs(
3915
+ "svg",
3916
+ {
3917
+ width: "14",
3918
+ height: "14",
3919
+ viewBox: "0 0 24 24",
3920
+ fill: "none",
3921
+ stroke: "currentColor",
3922
+ strokeWidth: "2",
3923
+ strokeLinecap: "round",
3924
+ strokeLinejoin: "round",
3925
+ children: [
3926
+ /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
3927
+ /* @__PURE__ */ jsx("polyline", { points: "14,2 14,8 20,8" }),
3928
+ /* @__PURE__ */ jsx("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
3929
+ /* @__PURE__ */ jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
3930
+ /* @__PURE__ */ jsx("polyline", { points: "10,9 9,9 8,9" })
3931
+ ]
3932
+ }
3933
+ ),
3416
3934
  "Transaction history"
3417
3935
  ] }),
3418
3936
  /* @__PURE__ */ jsx("div", { className: "wallet-dropdown-divider" }),
3419
3937
  /* @__PURE__ */ jsxs("button", { className: "wallet-dropdown-item danger", onClick: onLogout, children: [
3420
- /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3421
- /* @__PURE__ */ jsx("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
3422
- /* @__PURE__ */ jsx("polyline", { points: "16,17 21,12 16,7" }),
3423
- /* @__PURE__ */ jsx("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
3424
- ] }),
3938
+ /* @__PURE__ */ jsxs(
3939
+ "svg",
3940
+ {
3941
+ width: "14",
3942
+ height: "14",
3943
+ viewBox: "0 0 24 24",
3944
+ fill: "none",
3945
+ stroke: "currentColor",
3946
+ strokeWidth: "2",
3947
+ strokeLinecap: "round",
3948
+ strokeLinejoin: "round",
3949
+ children: [
3950
+ /* @__PURE__ */ jsx("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
3951
+ /* @__PURE__ */ jsx("polyline", { points: "16,17 21,12 16,7" }),
3952
+ /* @__PURE__ */ jsx("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
3953
+ ]
3954
+ }
3955
+ ),
3425
3956
  "Log out"
3426
3957
  ] })
3427
3958
  ] })
@@ -3443,6 +3974,7 @@ function WalletButton() {
3443
3974
  const [open, setOpen] = useState(false);
3444
3975
  const [copied, setCopied] = useState(false);
3445
3976
  const wrapperRef = useRef(null);
3977
+ const copyTimerRef = useRef(null);
3446
3978
  const isInProgress = transaction.step === "building" || transaction.step === "signing";
3447
3979
  const { theme = "light", accentColor = "#005DB4" } = styles;
3448
3980
  const isDark = theme === "dark";
@@ -3458,11 +3990,21 @@ function WalletButton() {
3458
3990
  document.addEventListener("mousedown", handleClickOutside);
3459
3991
  return () => document.removeEventListener("mousedown", handleClickOutside);
3460
3992
  }, []);
3993
+ useEffect(
3994
+ () => () => {
3995
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
3996
+ },
3997
+ []
3998
+ );
3461
3999
  async function handleCopy() {
3462
4000
  if (!walletAddress) return;
3463
4001
  await navigator.clipboard.writeText(walletAddress);
3464
4002
  setCopied(true);
3465
- setTimeout(() => setCopied(false), 1500);
4003
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
4004
+ copyTimerRef.current = setTimeout(() => {
4005
+ copyTimerRef.current = null;
4006
+ setCopied(false);
4007
+ }, 1500);
3466
4008
  }
3467
4009
  function handleLogout() {
3468
4010
  setOpen(false);
@@ -3509,6 +4051,6 @@ function WalletButton() {
3509
4051
  );
3510
4052
  }
3511
4053
 
3512
- export { KycModal, KycModalTemplate, KycStatus, LoginModalTemplate, PollarProvider, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, RouteDisplay, SendModal, SendModalTemplate, SessionsModal, SessionsModalTemplate, TransactionModalTemplate, TxHistoryModalTemplate, TxStatusView, WalletBalanceModal, WalletBalanceModalTemplate, WalletButton, createPollarAdapterHook, usePollar };
4054
+ export { DistributionRulesModal, DistributionRulesModalTemplate, KycModal, KycModalTemplate, KycStatus, LoginModalTemplate, PollarProvider, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, RouteDisplay, SendModal, SendModalTemplate, SessionsModal, SessionsModalTemplate, TransactionModalTemplate, TxHistoryModalTemplate, TxStatusView, WalletBalanceModal, WalletBalanceModalTemplate, WalletButton, createPollarAdapterHook, usePollar };
3513
4055
  //# sourceMappingURL=index.mjs.map
3514
4056
  //# sourceMappingURL=index.mjs.map