@pollar/react 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { PollarClient, StellarClient, StateStatus, STATE_VAR_CODES, isValidSession, PollarStateVar, WalletType } from '@pollar/core';
3
- import { createContext, useState, useEffect, useMemo, useContext, useRef } from 'react';
3
+ import { createContext, useState, useEffect, useMemo, useContext, useRef, Component } from 'react';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
 
6
6
  // src/context.tsx
@@ -10,6 +10,25 @@ var LOGO_POLLAR = "https://pollar.xyz/assets/logo_pollar.png";
10
10
  var LOGO_GITHUB = "https://pollar.xyz/assets/GitHub_Invertocat_White.png";
11
11
  var LOGO_FREIGHTER = "https://pollar.xyz/assets/logo_freighter.png";
12
12
  var LOGO_ALBEDO = "https://pollar.xyz/assets/logo_albedo.svg";
13
+ var ModalErrorBoundary = class extends Component {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.state = { crashed: false };
17
+ }
18
+ static getDerivedStateFromError() {
19
+ return { crashed: true };
20
+ }
21
+ componentDidCatch(error) {
22
+ console.error("[Pollar] Modal crashed:", error);
23
+ }
24
+ render() {
25
+ if (this.state.crashed) {
26
+ this.props.onClose();
27
+ return null;
28
+ }
29
+ return this.props.children;
30
+ }
31
+ };
13
32
  var PollarModalFooter = () => {
14
33
  return /* @__PURE__ */ jsxs("div", { className: "pollar-footer", children: [
15
34
  /* @__PURE__ */ jsx("span", { className: "pollar-footer-protected", children: "Protected by" }),
@@ -18,11 +37,71 @@ var PollarModalFooter = () => {
18
37
  /* @__PURE__ */ jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
19
38
  /* @__PURE__ */ jsxs("span", { className: "pollar-footer-version", children: [
20
39
  "v",
21
- "0.4.0"
40
+ "0.4.2"
22
41
  ] })
23
42
  ] })
24
43
  ] });
25
44
  };
45
+ var LOGIN_CODE_MESSAGES = {
46
+ NONE: { text: "" },
47
+ LOGOUT: { text: "Logged out" },
48
+ CREATE_SESSION_START: { text: "Starting session\u2026" },
49
+ CREATE_SESSION_ERROR: { text: "Failed to start session" },
50
+ CREATE_SESSION_SUCCESS: { text: "Session ready" },
51
+ EMAIL_AUTH_START: { text: "Sending code\u2026" },
52
+ EMAIL_AUTH_START_ERROR: { text: "Failed to send code" },
53
+ EMAIL_AUTH_START_SUCCESS: { text: "Code sent \u2014 check your inbox" },
54
+ EMAIL_AUTH_CODE_ERROR: { text: "Invalid code \u2014 try again" },
55
+ EMAIL_AUTH_CODE_SUCCESS: { text: "Code verified!" },
56
+ WALLET_AUTH_START: { text: "Connecting wallet\u2026" },
57
+ WALLET_AUTH_FREIGHTER_NOT_INSTALLED: { text: "Freighter is not installed" },
58
+ WALLET_AUTH_ALBEDO_NOT_INSTALLED: { text: "Albedo is not installed" },
59
+ WALLET_AUTH_CONNECTED: { text: "Wallet connected" },
60
+ WALLET_AUTH_LOGIN_START: { text: "Signing in with wallet\u2026" },
61
+ WALLET_AUTH_LOGIN_START_SUCCESS: { text: "Wallet signed in" },
62
+ WALLET_AUTH_LOGIN_START_ERROR: { text: "Failed to sign in with wallet" },
63
+ WALLET_AUTH_ERROR: { text: "Unknow wallet error" },
64
+ STREAM_POLL_START: { text: "Waiting for authentication\u2026" },
65
+ STREAM_POLL_EVENT: { text: "Waiting for authentication\u2026" },
66
+ STREAM_POLL_READY: { text: "Authenticated!" },
67
+ FETCH_SESSION_START: { text: "Loading session\u2026" },
68
+ FETCH_SESSION_SUCCESS: { text: "Welcome back!" },
69
+ FETCH_SESSION_ERROR: { text: "Failed to load session" },
70
+ NO_RESTORED_SESSION: { text: "" },
71
+ RESTORED_SESSION_SUCCESS: { text: "Session restored" },
72
+ RESTORED_SESSION_ERROR: { text: "Failed to restore session" },
73
+ SESSION_STORED: { text: "Session saved" },
74
+ ERROR_UNKNOWN: { text: "Something went wrong" },
75
+ ABORTED: { text: "Login cancelled" },
76
+ // transaction
77
+ BUILD_TRANSACTION_START: { text: "Building transaction\u2026" },
78
+ BUILD_TRANSACTION_SUCCESS: { text: "Transaction built, ready to sign and send" },
79
+ BUILD_TRANSACTION_ERROR: { text: "Failed to build transaction" },
80
+ BUILD_TRANSACTION_ERROR_NO_WALLET: { text: "No wallet connected" },
81
+ SIGN_SEND_TRANSACTION_START: { text: "Signing and sending transaction\u2026" },
82
+ SIGN_SEND_TRANSACTION_SUCCESS: { text: "Transaction signed" },
83
+ SIGN_SEND_TRANSACTION_ERROR: { text: "Signing rejected" }
84
+ };
85
+ function ModalStatusBanner({ code, status, onCancel, onRetry }) {
86
+ if (!code) {
87
+ return /* @__PURE__ */ jsx("div", { className: "pollar-status" });
88
+ }
89
+ const { text } = LOGIN_CODE_MESSAGES[code] || { text: "" };
90
+ const isLoading = status === "LOADING";
91
+ const icon = status === "ERROR" ? /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
92
+ /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
93
+ /* @__PURE__ */ jsx("path", { d: "M4.5 4.5l5 5M9.5 4.5l-5 5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round" })
94
+ ] }) : status === "SUCCESS" ? /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
95
+ /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
96
+ /* @__PURE__ */ jsx("path", { d: "M3.5 7l2.5 2.5 4.5-5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
97
+ ] }) : status === "LOADING" ? /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "5.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeDasharray: "22 10" }) }) : null;
98
+ return /* @__PURE__ */ jsxs("div", { className: "pollar-status", "data-kind": status, children: [
99
+ icon,
100
+ /* @__PURE__ */ jsx("span", { children: text }),
101
+ isLoading && onCancel && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-status-cancel", onClick: onCancel, children: "Cancel" }),
102
+ status === StateStatus.ERROR && onRetry && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-status-cancel", onClick: onRetry, children: "Retry" })
103
+ ] });
104
+ }
26
105
  function EmailCodeInput({ email, onSubmit }) {
27
106
  const [digits, setDigits] = useState(["", "", "", "", "", ""]);
28
107
  const inputRefs = useRef([]);
@@ -129,52 +208,6 @@ var GoogleButton = ({ disabled, onClick }) => {
129
208
  ] })
130
209
  ] });
131
210
  };
132
- var LOGIN_CODE_MESSAGES = {
133
- NONE: { text: "" },
134
- LOGOUT: { text: "Logged out" },
135
- CREATE_SESSION_START: { text: "Starting session\u2026" },
136
- CREATE_SESSION_ERROR: { text: "Failed to start session" },
137
- CREATE_SESSION_SUCCESS: { text: "Session ready" },
138
- EMAIL_AUTH_START: { text: "Sending code\u2026" },
139
- EMAIL_AUTH_START_ERROR: { text: "Failed to send code" },
140
- EMAIL_AUTH_START_SUCCESS: { text: "Code sent \u2014 check your inbox" },
141
- EMAIL_AUTH_CODE_ERROR: { text: "Invalid code \u2014 try again" },
142
- EMAIL_AUTH_CODE_SUCCESS: { text: "Code verified!" },
143
- WALLET_AUTH_START: { text: "Connecting wallet\u2026" },
144
- WALLET_AUTH_FREIGHTER_NOT_INSTALLED: { text: "Freighter is not installed" },
145
- WALLET_AUTH_ALBEDO_NOT_INSTALLED: { text: "Albedo is not installed" },
146
- WALLET_AUTH_CONNECTED: { text: "Wallet connected" },
147
- WALLET_AUTH_LOGIN_START: { text: "Signing in with wallet\u2026" },
148
- WALLET_AUTH_LOGIN_START_SUCCESS: { text: "Wallet signed in" },
149
- WALLET_AUTH_LOGIN_START_ERROR: { text: "Failed to sign in with wallet" },
150
- WALLET_AUTH_ERROR: { text: "Unknow wallet error" },
151
- STREAM_POLL_START: { text: "Waiting for authentication\u2026" },
152
- STREAM_POLL_EVENT: { text: "Waiting for authentication\u2026" },
153
- STREAM_POLL_READY: { text: "Authenticated!" },
154
- FETCH_SESSION_START: { text: "Loading session\u2026" },
155
- FETCH_SESSION_SUCCESS: { text: "Welcome back!" },
156
- FETCH_SESSION_ERROR: { text: "Failed to load session" },
157
- ERROR_UNKNOWN: { text: "Something went wrong" },
158
- ABORTED: { text: "Login cancelled" }
159
- };
160
- function LoginStatusBanner({ code, status, onCancel, onRetry }) {
161
- if (!code) return /* @__PURE__ */ jsx("div", { className: "pollar-status" });
162
- const { text } = LOGIN_CODE_MESSAGES[code] || { text: "" };
163
- const isLoading = status === StateStatus.LOADING;
164
- const icon = status === StateStatus.ERROR ? /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
165
- /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
166
- /* @__PURE__ */ jsx("path", { d: "M4.5 4.5l5 5M9.5 4.5l-5 5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round" })
167
- ] }) : status === StateStatus.SUCCESS ? /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
168
- /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
169
- /* @__PURE__ */ jsx("path", { d: "M3.5 7l2.5 2.5 4.5-5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
170
- ] }) : status === StateStatus.LOADING ? /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "5.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeDasharray: "22 10" }) }) : null;
171
- return /* @__PURE__ */ jsxs("div", { className: "pollar-status", "data-kind": status, children: [
172
- icon,
173
- /* @__PURE__ */ jsx("span", { children: text }),
174
- isLoading && onCancel && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-status-cancel", onClick: onCancel, children: "Cancel" }),
175
- status === StateStatus.ERROR && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-status-cancel", onClick: onRetry, children: "Retry" })
176
- ] });
177
- }
178
211
  function LoginModalTemplate({
179
212
  theme,
180
213
  accentColor,
@@ -257,7 +290,7 @@ function LoginModalTemplate({
257
290
  ] })
258
291
  ] })
259
292
  ] }),
260
- /* @__PURE__ */ jsx(LoginStatusBanner, { code: loginStateCode, status, onCancel: () => cancelLoginRef.current?.(), onRetry }),
293
+ /* @__PURE__ */ jsx(ModalStatusBanner, { code: loginStateCode, status, onCancel: () => cancelLoginRef.current?.(), onRetry }),
261
294
  /* @__PURE__ */ jsx(PollarModalFooter, {})
262
295
  ] });
263
296
  }
@@ -357,37 +390,16 @@ function LoginModal({ onClose }) {
357
390
  }
358
391
  ) });
359
392
  }
360
- function phaseFromStateCode(stateCode, submitResult) {
361
- if (stateCode === STATE_VAR_CODES.transaction.BUILD_TRANSACTION_ERROR || stateCode === STATE_VAR_CODES.transaction.BUILD_TRANSACTION_ERROR_NO_WALLET || stateCode === STATE_VAR_CODES.transaction.SIGN_TRANSACTION_ERROR || stateCode === STATE_VAR_CODES.transaction.SEND_TRANSACTION_ERROR)
362
- return "error";
363
- if (stateCode === STATE_VAR_CODES.transaction.SEND_TRANSACTION_SUCCESS || submitResult) return "success";
364
- if (stateCode === STATE_VAR_CODES.transaction.BUILD_TRANSACTION_SUCCESS || stateCode === STATE_VAR_CODES.transaction.SIGN_TRANSACTION_START || stateCode === STATE_VAR_CODES.transaction.SIGN_TRANSACTION_SUCCESS || stateCode === STATE_VAR_CODES.transaction.SEND_TRANSACTION_START)
365
- return "ready";
366
- return "building";
367
- }
368
- var TX_TITLES = {
369
- NONE: "Preparing transaction\u2026",
370
- BUILD_TRANSACTION_START: "Building transaction\u2026",
371
- BUILD_TRANSACTION_SUCCESS: "Confirm Transaction",
372
- BUILD_TRANSACTION_ERROR: "Transaction failed",
373
- BUILD_TRANSACTION_ERROR_NO_WALLET: "No wallet connected",
374
- SIGN_TRANSACTION_START: "Waiting for wallet\u2026",
375
- SIGN_TRANSACTION_SUCCESS: "Signed \u2014 submitting\u2026",
376
- SIGN_TRANSACTION_ERROR: "Signing failed",
377
- SEND_TRANSACTION_START: "Submitting transaction\u2026",
378
- SEND_TRANSACTION_SUCCESS: "Transaction sent",
379
- SEND_TRANSACTION_ERROR: "Transaction failed"
380
- };
381
393
  function TransactionModalTemplate({
382
394
  theme,
383
395
  accentColor,
384
- stateCode,
396
+ transactionStateCode,
397
+ status,
385
398
  buildResult,
386
399
  submitResult,
387
- isLoading,
388
400
  onClose,
389
401
  onSignAndSend,
390
- onRetry
402
+ onRetrySignAndSend
391
403
  }) {
392
404
  const isDark = theme === "dark";
393
405
  const cssVars = {
@@ -403,14 +415,26 @@ function TransactionModalTemplate({
403
415
  "--pollar-success-text": isDark ? "#4ade80" : "#16a34a"
404
416
  };
405
417
  const [showXdr, setShowXdr] = useState(false);
406
- const phase = phaseFromStateCode(stateCode, submitResult);
407
- const title = TX_TITLES[stateCode] || "";
418
+ const [copied, setCopied] = useState(false);
419
+ function handleCopyHash() {
420
+ if (!submitResult) return;
421
+ navigator.clipboard.writeText(submitResult.hash).then(() => {
422
+ setCopied(true);
423
+ setTimeout(() => setCopied(false), 2e3);
424
+ });
425
+ }
426
+ const explorerNetwork = buildResult?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : "public";
427
+ const explorerUrl = submitResult ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${submitResult.hash}` : null;
428
+ transactionStateCode.includes("ERROR");
429
+ transactionStateCode.includes("SUCCESS");
430
+ const isBuilt = buildResult && transactionStateCode === "BUILD_TRANSACTION_SUCCESS";
431
+ const isDone = submitResult && transactionStateCode === "SIGN_SEND_TRANSACTION_START";
408
432
  return /* @__PURE__ */ jsxs("div", { className: "pollar-tx-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
409
433
  /* @__PURE__ */ jsxs("div", { className: "pollar-tx-header", children: [
410
- /* @__PURE__ */ jsx("h2", { className: "pollar-tx-title", children: title }),
411
- /* @__PURE__ */ jsx("button", { className: "pollar-tx-close", onClick: onClose, disabled: isLoading, "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" }) }) })
434
+ /* @__PURE__ */ jsx("h2", { className: "pollar-tx-title", children: "Transaction" }),
435
+ /* @__PURE__ */ jsx("button", { className: "pollar-tx-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" }) }) })
412
436
  ] }),
413
- buildResult && phase !== "building" && /* @__PURE__ */ jsxs(Fragment, { children: [
437
+ isBuilt && /* @__PURE__ */ jsxs(Fragment, { children: [
414
438
  /* @__PURE__ */ jsxs("div", { className: "pollar-tx-summary", children: [
415
439
  /* @__PURE__ */ jsx("p", { className: "pollar-tx-summary-title", children: "Details" }),
416
440
  /* @__PURE__ */ jsx("ul", { className: "pollar-tx-summary-lines", children: buildResult.summary.lines.map((line, i) => /* @__PURE__ */ jsx("li", { className: "pollar-tx-summary-line", children: line }, i)) })
@@ -444,73 +468,122 @@ function TransactionModalTemplate({
444
468
  showXdr && /* @__PURE__ */ jsx("pre", { className: "pollar-tx-xdr-content", children: buildResult.unsignedXdr })
445
469
  ] })
446
470
  ] }),
447
- phase === "success" && submitResult && /* @__PURE__ */ jsxs("div", { className: "pollar-tx-result", children: [
471
+ submitResult && transactionStateCode === "SIGN_SEND_TRANSACTION_SUCCESS" && /* @__PURE__ */ jsxs("div", { className: "pollar-tx-result", children: [
448
472
  /* @__PURE__ */ jsx("span", { className: "pollar-tx-result-label", children: "Transaction hash" }),
449
- /* @__PURE__ */ jsx("span", { className: "pollar-tx-result-hash", children: submitResult.hash })
450
- ] }),
451
- /* @__PURE__ */ jsxs("div", { className: "pollar-tx-status", "data-kind": phase === "error" ? "ERROR" : phase === "success" ? "SUCCESS" : "LOADING", children: [
452
- isLoading && /* @__PURE__ */ jsx("svg", { className: "pollar-tx-spinner", width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx(
453
- "circle",
454
- {
455
- cx: "7",
456
- cy: "7",
457
- r: "5.5",
458
- stroke: "currentColor",
459
- strokeWidth: "1.5",
460
- strokeLinecap: "round",
461
- strokeDasharray: "22 10"
462
- }
463
- ) }),
464
- phase === "error" && /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
465
- /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
466
- /* @__PURE__ */ jsx("path", { d: "M4.5 4.5l5 5M9.5 4.5l-5 5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round" })
467
- ] }),
468
- phase === "success" && /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
469
- /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
470
- /* @__PURE__ */ jsx("path", { d: "M3.5 7l2.5 2.5 4.5-5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
473
+ /* @__PURE__ */ jsx("span", { className: "pollar-tx-result-hash", children: submitResult.hash }),
474
+ /* @__PURE__ */ jsxs("div", { className: "pollar-tx-result-actions", children: [
475
+ /* @__PURE__ */ jsx("button", { className: "pollar-tx-result-btn", onClick: handleCopyHash, children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
476
+ /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
477
+ /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
478
+ /* @__PURE__ */ jsx(
479
+ "path",
480
+ {
481
+ d: "M3.5 7l2.5 2.5 4.5-5",
482
+ stroke: "white",
483
+ strokeWidth: "1.5",
484
+ strokeLinecap: "round",
485
+ strokeLinejoin: "round"
486
+ }
487
+ )
488
+ ] }),
489
+ "Copied!"
490
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
491
+ /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
492
+ /* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
493
+ /* @__PURE__ */ jsx(
494
+ "path",
495
+ {
496
+ d: "M3 9H2a1 1 0 01-1-1V2a1 1 0 011-1h6a1 1 0 011 1v1",
497
+ stroke: "currentColor",
498
+ strokeWidth: "1.5",
499
+ strokeLinecap: "round"
500
+ }
501
+ )
502
+ ] }),
503
+ "Copy hash"
504
+ ] }) }),
505
+ explorerUrl && /* @__PURE__ */ jsxs("a", { className: "pollar-tx-result-btn", href: explorerUrl, target: "_blank", rel: "noopener noreferrer", children: [
506
+ /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
507
+ /* @__PURE__ */ jsx(
508
+ "path",
509
+ {
510
+ d: "M5 2H2a1 1 0 00-1 1v8a1 1 0 001 1h8a1 1 0 001-1V8",
511
+ stroke: "currentColor",
512
+ strokeWidth: "1.5",
513
+ strokeLinecap: "round"
514
+ }
515
+ ),
516
+ /* @__PURE__ */ jsx(
517
+ "path",
518
+ {
519
+ d: "M8 1h4m0 0v4m0-4L6 7",
520
+ stroke: "currentColor",
521
+ strokeWidth: "1.5",
522
+ strokeLinecap: "round",
523
+ strokeLinejoin: "round"
524
+ }
525
+ )
526
+ ] }),
527
+ "View on Explorer"
528
+ ] })
471
529
  ] })
472
530
  ] }),
473
- phase === "ready" && /* @__PURE__ */ jsx("button", { className: "pollar-tx-sign-btn", onClick: onSignAndSend, children: "Sign & Send" }),
474
- phase === "error" && /* @__PURE__ */ jsx("button", { className: "pollar-tx-sign-btn", onClick: onRetry, children: "Retry" }),
475
- phase === "success" && /* @__PURE__ */ jsx("button", { className: "pollar-tx-sign-btn", onClick: onClose, children: "Done" }),
531
+ isBuilt && /* @__PURE__ */ jsx("button", { className: "pollar-tx-sign-btn", onClick: onSignAndSend, children: "Sign & Send" }),
532
+ isDone && /* @__PURE__ */ jsx("button", { className: "pollar-tx-sign-btn", onClick: onClose, children: "Done" }),
533
+ /* @__PURE__ */ jsx(
534
+ ModalStatusBanner,
535
+ {
536
+ code: transactionStateCode,
537
+ status
538
+ }
539
+ ),
476
540
  /* @__PURE__ */ jsx(PollarModalFooter, {})
477
541
  ] });
478
542
  }
479
- var isTxBuildResponse = (data) => {
543
+ var isTxBuildResponseContent = (data) => {
480
544
  if (!data || typeof data !== "object") return false;
481
545
  const d = data;
482
546
  return typeof d.unsignedXdr === "string" && typeof d.networkPassphrase === "string" && typeof d.estimatedFee === "string" && d.summary !== null && typeof d.summary === "object";
483
547
  };
548
+ var isTxSignSendResponseContent = (data) => {
549
+ if (!data || typeof data !== "object") return false;
550
+ const d = data;
551
+ return typeof d.hash === "string" && (d.status === "PENDING" || d.status === "SUCCESS" || d.status === "FAILED");
552
+ };
484
553
  function TransactionModal({ onClose }) {
485
554
  const {
555
+ getClient,
486
556
  styles,
487
557
  state: { transaction }
488
558
  } = usePollar();
489
559
  const { theme = "light", accentColor = "#005DB4" } = styles;
490
- const [submitResult, setSubmitResult] = useState(null);
491
- console.log({ transaction });
492
- async function handleSignAndSend() {
493
- }
494
- const isLoading = transaction.status === "LOADING";
495
560
  let buildResult = null;
496
- const stateCode = transaction.code;
497
- if (isTxBuildResponse(transaction.data)) {
498
- buildResult = transaction.data;
561
+ const transactionStateCode = transaction.code;
562
+ const content = transaction.data?.content;
563
+ if (isTxBuildResponseContent(content)) {
564
+ buildResult = content;
565
+ }
566
+ let submitResult = null;
567
+ if (isTxSignSendResponseContent(content)) {
568
+ submitResult = content;
569
+ }
570
+ async function handleSignAndSend() {
571
+ if (buildResult) {
572
+ await getClient().submitTx(buildResult.unsignedXdr);
573
+ }
499
574
  }
500
- console.log({ transaction, buildResult });
501
575
  return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsx(
502
576
  TransactionModalTemplate,
503
577
  {
504
578
  theme,
505
579
  accentColor,
506
- stateCode,
580
+ transactionStateCode,
581
+ status: transaction.status,
507
582
  buildResult,
508
583
  submitResult,
509
- isLoading,
510
584
  onClose,
511
585
  onSignAndSend: handleSignAndSend,
512
- onRetry: () => {
513
- }
586
+ onRetrySignAndSend: handleSignAndSend
514
587
  }
515
588
  ) });
516
589
  }
@@ -537,6 +610,13 @@ function PollarProvider({ config, styles: propStyles, children }) {
537
610
  const [stellarClient] = useState(() => new StellarClient(config.stellarNetwork || "testnet"));
538
611
  const [sessionState, setSessionState] = useState(null);
539
612
  const [state, setState] = useState({
613
+ network: {
614
+ var: "network",
615
+ code: STATE_VAR_CODES.network.NONE,
616
+ status: StateStatus.NONE,
617
+ level: "info",
618
+ ts: 0
619
+ },
540
620
  authentication: {
541
621
  var: "authentication",
542
622
  code: STATE_VAR_CODES.authentication.NONE,
@@ -627,8 +707,8 @@ function PollarProvider({ config, styles: propStyles, children }) {
627
707
  );
628
708
  return /* @__PURE__ */ jsxs(PollarContext.Provider, { value: contextValue, children: [
629
709
  children,
630
- loginModalOpen && /* @__PURE__ */ jsx(LoginModal, { onClose: () => setLoginModalOpen(false) }),
631
- transactionModalOpen && /* @__PURE__ */ jsx(TransactionModal, { onClose: () => setTransactionModalOpen(false) })
710
+ loginModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setLoginModalOpen(false), children: /* @__PURE__ */ jsx(LoginModal, { onClose: () => setLoginModalOpen(false) }) }),
711
+ transactionModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setTransactionModalOpen(false), children: /* @__PURE__ */ jsx(TransactionModal, { onClose: () => setTransactionModalOpen(false) }) })
632
712
  ] });
633
713
  }
634
714
  function usePollar() {