@pollar/react 0.3.9 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +245 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +333 -81
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +335 -83
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { PollarClient, StellarClient, StateStatus, STATE_VAR_CODES,
|
|
3
|
-
import { createContext, useState, useEffect, useMemo, useContext, useRef } from 'react';
|
|
2
|
+
import { PollarClient, StellarClient, StateStatus, STATE_VAR_CODES, isValidSession, PollarStateVar, WalletType } from '@pollar/core';
|
|
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,97 @@ 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
|
+
};
|
|
32
|
+
var PollarModalFooter = () => {
|
|
33
|
+
return /* @__PURE__ */ jsxs("div", { className: "pollar-footer", children: [
|
|
34
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-footer-protected", children: "Protected by" }),
|
|
35
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-footer-brand", children: [
|
|
36
|
+
/* @__PURE__ */ jsx("img", { src: LOGO_POLLAR, alt: "Pollar", className: "pollar-footer-logo" }),
|
|
37
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
|
|
38
|
+
/* @__PURE__ */ jsxs("span", { className: "pollar-footer-version", children: [
|
|
39
|
+
"v",
|
|
40
|
+
"0.4.1"
|
|
41
|
+
] })
|
|
42
|
+
] })
|
|
43
|
+
] });
|
|
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
|
+
RESTORED_SESSION_SUCCESS: { text: "Session restored" },
|
|
71
|
+
RESTORED_SESSION_ERROR: { text: "Failed to restore session" },
|
|
72
|
+
SESSION_STORED: { text: "Session saved" },
|
|
73
|
+
ERROR_UNKNOWN: { text: "Something went wrong" },
|
|
74
|
+
ABORTED: { text: "Login cancelled" },
|
|
75
|
+
// transaction
|
|
76
|
+
BUILD_TRANSACTION_START: { text: "Building transaction\u2026" },
|
|
77
|
+
BUILD_TRANSACTION_SUCCESS: { text: "Transaction built, ready to sign and send" },
|
|
78
|
+
BUILD_TRANSACTION_ERROR: { text: "Failed to build transaction" },
|
|
79
|
+
BUILD_TRANSACTION_ERROR_NO_WALLET: { text: "No wallet connected" },
|
|
80
|
+
SIGN_SEND_TRANSACTION_START: { text: "Signing and sending transaction\u2026" },
|
|
81
|
+
SIGN_SEND_TRANSACTION_SUCCESS: { text: "Transaction signed" },
|
|
82
|
+
SIGN_SEND_TRANSACTION_ERROR: { text: "Signing rejected" }
|
|
83
|
+
};
|
|
84
|
+
function ModalStatusBanner({ code, status, onCancel, onRetry }) {
|
|
85
|
+
if (!code) {
|
|
86
|
+
return /* @__PURE__ */ jsx("div", { className: "pollar-status" });
|
|
87
|
+
}
|
|
88
|
+
const { text } = LOGIN_CODE_MESSAGES[code] || { text: "" };
|
|
89
|
+
const isLoading = status === "LOADING";
|
|
90
|
+
const icon = status === "ERROR" ? /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
|
|
91
|
+
/* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
|
|
92
|
+
/* @__PURE__ */ jsx("path", { d: "M4.5 4.5l5 5M9.5 4.5l-5 5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
93
|
+
] }) : status === "SUCCESS" ? /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
|
|
94
|
+
/* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
|
|
95
|
+
/* @__PURE__ */ jsx("path", { d: "M3.5 7l2.5 2.5 4.5-5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
96
|
+
] }) : 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;
|
|
97
|
+
return /* @__PURE__ */ jsxs("div", { className: "pollar-status", "data-kind": status, children: [
|
|
98
|
+
icon,
|
|
99
|
+
/* @__PURE__ */ jsx("span", { children: text }),
|
|
100
|
+
isLoading && onCancel && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-status-cancel", onClick: onCancel, children: "Cancel" }),
|
|
101
|
+
status === StateStatus.ERROR && onRetry && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-status-cancel", onClick: onRetry, children: "Retry" })
|
|
102
|
+
] });
|
|
103
|
+
}
|
|
13
104
|
function EmailCodeInput({ email, onSubmit }) {
|
|
14
105
|
const [digits, setDigits] = useState(["", "", "", "", "", ""]);
|
|
15
106
|
const inputRefs = useRef([]);
|
|
@@ -116,51 +207,6 @@ var GoogleButton = ({ disabled, onClick }) => {
|
|
|
116
207
|
] })
|
|
117
208
|
] });
|
|
118
209
|
};
|
|
119
|
-
var LOGIN_CODE_MESSAGES = {
|
|
120
|
-
LOGOUT: { text: "Logged out" },
|
|
121
|
-
CREATE_SESSION_START: { text: "Starting session\u2026" },
|
|
122
|
-
CREATE_SESSION_ERROR: { text: "Failed to start session" },
|
|
123
|
-
CREATE_SESSION_SUCCESS: { text: "Session ready" },
|
|
124
|
-
EMAIL_AUTH_START: { text: "Sending code\u2026" },
|
|
125
|
-
EMAIL_AUTH_START_ERROR: { text: "Failed to send code" },
|
|
126
|
-
EMAIL_AUTH_START_SUCCESS: { text: "Code sent \u2014 check your inbox" },
|
|
127
|
-
EMAIL_AUTH_CODE_ERROR: { text: "Invalid code \u2014 try again" },
|
|
128
|
-
EMAIL_AUTH_CODE_SUCCESS: { text: "Code verified!" },
|
|
129
|
-
WALLET_AUTH_START: { text: "Connecting wallet\u2026" },
|
|
130
|
-
WALLET_AUTH_FREIGHTER_NOT_INSTALLED: { text: "Freighter is not installed" },
|
|
131
|
-
WALLET_AUTH_ALBEDO_NOT_INSTALLED: { text: "Albedo is not installed" },
|
|
132
|
-
WALLET_AUTH_CONNECTED: { text: "Wallet connected" },
|
|
133
|
-
WALLET_AUTH_LOGIN_START: { text: "Signing in with wallet\u2026" },
|
|
134
|
-
WALLET_AUTH_LOGIN_START_SUCCESS: { text: "Wallet signed in" },
|
|
135
|
-
WALLET_AUTH_LOGIN_START_ERROR: { text: "Failed to sign in with wallet" },
|
|
136
|
-
WALLET_AUTH_ERROR: { text: "Unknow wallet error" },
|
|
137
|
-
STREAM_POLL_START: { text: "Waiting for authentication\u2026" },
|
|
138
|
-
STREAM_POLL_EVENT: { text: "Waiting for authentication\u2026" },
|
|
139
|
-
STREAM_POLL_READY: { text: "Authenticated!" },
|
|
140
|
-
FETCH_SESSION_START: { text: "Loading session\u2026" },
|
|
141
|
-
FETCH_SESSION_SUCCESS: { text: "Welcome back!" },
|
|
142
|
-
FETCH_SESSION_ERROR: { text: "Failed to load session" },
|
|
143
|
-
ERROR_UNKNOWN: { text: "Something went wrong" },
|
|
144
|
-
ABORTED: { text: "Login cancelled" }
|
|
145
|
-
};
|
|
146
|
-
function LoginStatusBanner({ code, status, onCancel, onRetry }) {
|
|
147
|
-
if (!code) return /* @__PURE__ */ jsx("div", { className: "pollar-status" });
|
|
148
|
-
const { text } = LOGIN_CODE_MESSAGES[code] || { text: "" };
|
|
149
|
-
const isLoading = status === StateStatus.LOADING;
|
|
150
|
-
const icon = status === StateStatus.ERROR ? /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
|
|
151
|
-
/* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
|
|
152
|
-
/* @__PURE__ */ jsx("path", { d: "M4.5 4.5l5 5M9.5 4.5l-5 5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
153
|
-
] }) : status === StateStatus.SUCCESS ? /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
|
|
154
|
-
/* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
|
|
155
|
-
/* @__PURE__ */ jsx("path", { d: "M3.5 7l2.5 2.5 4.5-5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
156
|
-
] }) : 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;
|
|
157
|
-
return /* @__PURE__ */ jsxs("div", { className: "pollar-status", "data-kind": status, children: [
|
|
158
|
-
icon,
|
|
159
|
-
/* @__PURE__ */ jsx("span", { children: text }),
|
|
160
|
-
isLoading && onCancel && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-status-cancel", onClick: onCancel, children: "Cancel" }),
|
|
161
|
-
status === StateStatus.ERROR && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-status-cancel", onClick: onRetry, children: "Retry" })
|
|
162
|
-
] });
|
|
163
|
-
}
|
|
164
210
|
function LoginModalTemplate({
|
|
165
211
|
theme,
|
|
166
212
|
accentColor,
|
|
@@ -243,22 +289,12 @@ function LoginModalTemplate({
|
|
|
243
289
|
] })
|
|
244
290
|
] })
|
|
245
291
|
] }),
|
|
246
|
-
/* @__PURE__ */ jsx(
|
|
247
|
-
/* @__PURE__ */
|
|
248
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-footer-protected", children: "Protected by" }),
|
|
249
|
-
/* @__PURE__ */ jsxs("div", { className: "pollar-footer-brand", children: [
|
|
250
|
-
/* @__PURE__ */ jsx("img", { src: LOGO_POLLAR, alt: "Pollar", className: "pollar-footer-logo" }),
|
|
251
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
|
|
252
|
-
/* @__PURE__ */ jsxs("span", { className: "pollar-footer-version", children: [
|
|
253
|
-
"v",
|
|
254
|
-
"0.3.9"
|
|
255
|
-
] })
|
|
256
|
-
] })
|
|
257
|
-
] })
|
|
292
|
+
/* @__PURE__ */ jsx(ModalStatusBanner, { code: loginStateCode, status, onCancel: () => cancelLoginRef.current?.(), onRetry }),
|
|
293
|
+
/* @__PURE__ */ jsx(PollarModalFooter, {})
|
|
258
294
|
] });
|
|
259
295
|
}
|
|
260
296
|
function isLoginCode(code) {
|
|
261
|
-
return Object.values(STATE_VAR_CODES[PollarStateVar.
|
|
297
|
+
return Object.values(STATE_VAR_CODES[PollarStateVar.AUTHENTICATION]).includes(code);
|
|
262
298
|
}
|
|
263
299
|
function LoginModal({ onClose }) {
|
|
264
300
|
const [email, setEmail] = useState("");
|
|
@@ -270,20 +306,20 @@ function LoginModal({ onClose }) {
|
|
|
270
306
|
const [clientSessionId, setClientSessionId] = useState(null);
|
|
271
307
|
useEffect(() => {
|
|
272
308
|
return getClient().onStateChange((stateEntry) => {
|
|
273
|
-
if (stateEntry.var === PollarStateVar.
|
|
309
|
+
if (stateEntry.var === PollarStateVar.AUTHENTICATION && isLoginCode(stateEntry.code)) {
|
|
274
310
|
setLoginStateCode(stateEntry.code);
|
|
275
311
|
setStatus(stateEntry.status);
|
|
276
|
-
if (stateEntry.code === STATE_VAR_CODES[PollarStateVar.
|
|
312
|
+
if (stateEntry.code === STATE_VAR_CODES[PollarStateVar.AUTHENTICATION].STREAM_POLL_START) {
|
|
277
313
|
const data = stateEntry.data;
|
|
278
314
|
setClientSessionId(data.clientSessionId);
|
|
279
315
|
}
|
|
280
|
-
if (stateEntry.code === STATE_VAR_CODES[PollarStateVar.
|
|
316
|
+
if (stateEntry.code === STATE_VAR_CODES[PollarStateVar.AUTHENTICATION].STREAM_POLL_EVENT) {
|
|
281
317
|
const data = stateEntry.data;
|
|
282
318
|
if (data?.status === "AWAITING_EMAIL") {
|
|
283
319
|
setAwaitingEmailCode(true);
|
|
284
320
|
}
|
|
285
321
|
}
|
|
286
|
-
if (stateEntry.code === STATE_VAR_CODES[PollarStateVar.
|
|
322
|
+
if (stateEntry.code === STATE_VAR_CODES[PollarStateVar.AUTHENTICATION].FETCH_SESSION_SUCCESS) {
|
|
287
323
|
setAwaitingEmailCode(false);
|
|
288
324
|
setTimeout(onClose, 1e3);
|
|
289
325
|
}
|
|
@@ -353,6 +389,203 @@ function LoginModal({ onClose }) {
|
|
|
353
389
|
}
|
|
354
390
|
) });
|
|
355
391
|
}
|
|
392
|
+
function TransactionModalTemplate({
|
|
393
|
+
theme,
|
|
394
|
+
accentColor,
|
|
395
|
+
transactionStateCode,
|
|
396
|
+
status,
|
|
397
|
+
buildResult,
|
|
398
|
+
submitResult,
|
|
399
|
+
onClose,
|
|
400
|
+
onSignAndSend,
|
|
401
|
+
onRetrySignAndSend
|
|
402
|
+
}) {
|
|
403
|
+
const isDark = theme === "dark";
|
|
404
|
+
const cssVars = {
|
|
405
|
+
"--pollar-accent": accentColor,
|
|
406
|
+
"--pollar-buttons-border-radius": "8px",
|
|
407
|
+
"--pollar-buttons-height": "44px",
|
|
408
|
+
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
409
|
+
"--pollar-border": isDark ? "#374151" : "#e5e7eb",
|
|
410
|
+
"--pollar-text": isDark ? "#ffffff" : "#111827",
|
|
411
|
+
"--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
|
|
412
|
+
"--pollar-input-bg": isDark ? "#374151" : "rgba(0,0,0,0.04)",
|
|
413
|
+
"--pollar-error-text": isDark ? "#f87171" : "#dc2626",
|
|
414
|
+
"--pollar-success-text": isDark ? "#4ade80" : "#16a34a"
|
|
415
|
+
};
|
|
416
|
+
const [showXdr, setShowXdr] = useState(false);
|
|
417
|
+
const [copied, setCopied] = useState(false);
|
|
418
|
+
function handleCopyHash() {
|
|
419
|
+
if (!submitResult) return;
|
|
420
|
+
navigator.clipboard.writeText(submitResult.hash).then(() => {
|
|
421
|
+
setCopied(true);
|
|
422
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
const explorerNetwork = buildResult?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : "public";
|
|
426
|
+
const explorerUrl = submitResult ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${submitResult.hash}` : null;
|
|
427
|
+
transactionStateCode.includes("ERROR");
|
|
428
|
+
transactionStateCode.includes("SUCCESS");
|
|
429
|
+
const isBuilt = buildResult && transactionStateCode === "BUILD_TRANSACTION_SUCCESS";
|
|
430
|
+
const isDone = submitResult && transactionStateCode === "SIGN_SEND_TRANSACTION_START";
|
|
431
|
+
return /* @__PURE__ */ jsxs("div", { className: "pollar-tx-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
|
|
432
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-tx-header", children: [
|
|
433
|
+
/* @__PURE__ */ jsx("h2", { className: "pollar-tx-title", children: "Transaction" }),
|
|
434
|
+
/* @__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" }) }) })
|
|
435
|
+
] }),
|
|
436
|
+
isBuilt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
437
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-tx-summary", children: [
|
|
438
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-tx-summary-title", children: "Details" }),
|
|
439
|
+
/* @__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)) })
|
|
440
|
+
] }),
|
|
441
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-tx-meta", children: [
|
|
442
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-tx-meta-item", children: [
|
|
443
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-tx-meta-label", children: "Network" }),
|
|
444
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-tx-meta-value", children: buildResult.summary.network })
|
|
445
|
+
] }),
|
|
446
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-tx-meta-item", children: [
|
|
447
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-tx-meta-label", children: "Fee" }),
|
|
448
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-tx-meta-value", children: buildResult.summary.fee })
|
|
449
|
+
] })
|
|
450
|
+
] }),
|
|
451
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-tx-xdr", children: [
|
|
452
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-tx-xdr-toggle", onClick: () => setShowXdr((v) => !v), children: [
|
|
453
|
+
/* @__PURE__ */ jsx(
|
|
454
|
+
"svg",
|
|
455
|
+
{
|
|
456
|
+
width: "12",
|
|
457
|
+
height: "12",
|
|
458
|
+
viewBox: "0 0 12 12",
|
|
459
|
+
fill: "none",
|
|
460
|
+
"aria-hidden": true,
|
|
461
|
+
style: { transform: showXdr ? "rotate(90deg)" : "rotate(0deg)", transition: "transform 150ms" },
|
|
462
|
+
children: /* @__PURE__ */ jsx("path", { d: "M4 2l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
463
|
+
}
|
|
464
|
+
),
|
|
465
|
+
"Raw transaction (XDR)"
|
|
466
|
+
] }),
|
|
467
|
+
showXdr && /* @__PURE__ */ jsx("pre", { className: "pollar-tx-xdr-content", children: buildResult.unsignedXdr })
|
|
468
|
+
] })
|
|
469
|
+
] }),
|
|
470
|
+
submitResult && transactionStateCode === "SIGN_SEND_TRANSACTION_SUCCESS" && /* @__PURE__ */ jsxs("div", { className: "pollar-tx-result", children: [
|
|
471
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-tx-result-label", children: "Transaction hash" }),
|
|
472
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-tx-result-hash", children: submitResult.hash }),
|
|
473
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-tx-result-actions", children: [
|
|
474
|
+
/* @__PURE__ */ jsx("button", { className: "pollar-tx-result-btn", onClick: handleCopyHash, children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
475
|
+
/* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
|
|
476
|
+
/* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
|
|
477
|
+
/* @__PURE__ */ jsx(
|
|
478
|
+
"path",
|
|
479
|
+
{
|
|
480
|
+
d: "M3.5 7l2.5 2.5 4.5-5",
|
|
481
|
+
stroke: "white",
|
|
482
|
+
strokeWidth: "1.5",
|
|
483
|
+
strokeLinecap: "round",
|
|
484
|
+
strokeLinejoin: "round"
|
|
485
|
+
}
|
|
486
|
+
)
|
|
487
|
+
] }),
|
|
488
|
+
"Copied!"
|
|
489
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
490
|
+
/* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
|
|
491
|
+
/* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
492
|
+
/* @__PURE__ */ jsx(
|
|
493
|
+
"path",
|
|
494
|
+
{
|
|
495
|
+
d: "M3 9H2a1 1 0 01-1-1V2a1 1 0 011-1h6a1 1 0 011 1v1",
|
|
496
|
+
stroke: "currentColor",
|
|
497
|
+
strokeWidth: "1.5",
|
|
498
|
+
strokeLinecap: "round"
|
|
499
|
+
}
|
|
500
|
+
)
|
|
501
|
+
] }),
|
|
502
|
+
"Copy hash"
|
|
503
|
+
] }) }),
|
|
504
|
+
explorerUrl && /* @__PURE__ */ jsxs("a", { className: "pollar-tx-result-btn", href: explorerUrl, target: "_blank", rel: "noopener noreferrer", children: [
|
|
505
|
+
/* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
|
|
506
|
+
/* @__PURE__ */ jsx(
|
|
507
|
+
"path",
|
|
508
|
+
{
|
|
509
|
+
d: "M5 2H2a1 1 0 00-1 1v8a1 1 0 001 1h8a1 1 0 001-1V8",
|
|
510
|
+
stroke: "currentColor",
|
|
511
|
+
strokeWidth: "1.5",
|
|
512
|
+
strokeLinecap: "round"
|
|
513
|
+
}
|
|
514
|
+
),
|
|
515
|
+
/* @__PURE__ */ jsx(
|
|
516
|
+
"path",
|
|
517
|
+
{
|
|
518
|
+
d: "M8 1h4m0 0v4m0-4L6 7",
|
|
519
|
+
stroke: "currentColor",
|
|
520
|
+
strokeWidth: "1.5",
|
|
521
|
+
strokeLinecap: "round",
|
|
522
|
+
strokeLinejoin: "round"
|
|
523
|
+
}
|
|
524
|
+
)
|
|
525
|
+
] }),
|
|
526
|
+
"View on Explorer"
|
|
527
|
+
] })
|
|
528
|
+
] })
|
|
529
|
+
] }),
|
|
530
|
+
isBuilt && /* @__PURE__ */ jsx("button", { className: "pollar-tx-sign-btn", onClick: onSignAndSend, children: "Sign & Send" }),
|
|
531
|
+
isDone && /* @__PURE__ */ jsx("button", { className: "pollar-tx-sign-btn", onClick: onClose, children: "Done" }),
|
|
532
|
+
/* @__PURE__ */ jsx(
|
|
533
|
+
ModalStatusBanner,
|
|
534
|
+
{
|
|
535
|
+
code: transactionStateCode,
|
|
536
|
+
status
|
|
537
|
+
}
|
|
538
|
+
),
|
|
539
|
+
/* @__PURE__ */ jsx(PollarModalFooter, {})
|
|
540
|
+
] });
|
|
541
|
+
}
|
|
542
|
+
var isTxBuildResponseContent = (data) => {
|
|
543
|
+
if (!data || typeof data !== "object") return false;
|
|
544
|
+
const d = data;
|
|
545
|
+
return typeof d.unsignedXdr === "string" && typeof d.networkPassphrase === "string" && typeof d.estimatedFee === "string" && d.summary !== null && typeof d.summary === "object";
|
|
546
|
+
};
|
|
547
|
+
var isTxSignSendResponseContent = (data) => {
|
|
548
|
+
if (!data || typeof data !== "object") return false;
|
|
549
|
+
const d = data;
|
|
550
|
+
return typeof d.hash === "string" && (d.status === "PENDING" || d.status === "SUCCESS" || d.status === "FAILED");
|
|
551
|
+
};
|
|
552
|
+
function TransactionModal({ onClose }) {
|
|
553
|
+
const {
|
|
554
|
+
getClient,
|
|
555
|
+
styles,
|
|
556
|
+
state: { transaction }
|
|
557
|
+
} = usePollar();
|
|
558
|
+
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
559
|
+
let buildResult = null;
|
|
560
|
+
const transactionStateCode = transaction.code;
|
|
561
|
+
const content = transaction.data?.content;
|
|
562
|
+
if (isTxBuildResponseContent(content)) {
|
|
563
|
+
buildResult = content;
|
|
564
|
+
}
|
|
565
|
+
let submitResult = null;
|
|
566
|
+
if (isTxSignSendResponseContent(content)) {
|
|
567
|
+
submitResult = content;
|
|
568
|
+
}
|
|
569
|
+
async function handleSignAndSend() {
|
|
570
|
+
if (buildResult) {
|
|
571
|
+
await getClient().submitTx(buildResult.unsignedXdr);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsx(
|
|
575
|
+
TransactionModalTemplate,
|
|
576
|
+
{
|
|
577
|
+
theme,
|
|
578
|
+
accentColor,
|
|
579
|
+
transactionStateCode,
|
|
580
|
+
status: transaction.status,
|
|
581
|
+
buildResult,
|
|
582
|
+
submitResult,
|
|
583
|
+
onClose,
|
|
584
|
+
onSignAndSend: handleSignAndSend,
|
|
585
|
+
onRetrySignAndSend: handleSignAndSend
|
|
586
|
+
}
|
|
587
|
+
) });
|
|
588
|
+
}
|
|
356
589
|
var emptyResponse = {
|
|
357
590
|
application: {
|
|
358
591
|
name: ""
|
|
@@ -361,7 +594,7 @@ var emptyResponse = {
|
|
|
361
594
|
};
|
|
362
595
|
async function fetchRemoteConfig(api) {
|
|
363
596
|
try {
|
|
364
|
-
const { data, error } = await api.GET(`/config`);
|
|
597
|
+
const { data, error } = await api.GET(`/applications/config`);
|
|
365
598
|
if (!data || error) {
|
|
366
599
|
return emptyResponse;
|
|
367
600
|
}
|
|
@@ -376,16 +609,23 @@ function PollarProvider({ config, styles: propStyles, children }) {
|
|
|
376
609
|
const [stellarClient] = useState(() => new StellarClient(config.stellarNetwork || "testnet"));
|
|
377
610
|
const [sessionState, setSessionState] = useState(null);
|
|
378
611
|
const [state, setState] = useState({
|
|
379
|
-
|
|
380
|
-
var:
|
|
381
|
-
code: STATE_VAR_CODES
|
|
612
|
+
network: {
|
|
613
|
+
var: "network",
|
|
614
|
+
code: STATE_VAR_CODES.network.NONE,
|
|
615
|
+
status: StateStatus.NONE,
|
|
616
|
+
level: "info",
|
|
617
|
+
ts: 0
|
|
618
|
+
},
|
|
619
|
+
authentication: {
|
|
620
|
+
var: "authentication",
|
|
621
|
+
code: STATE_VAR_CODES.authentication.NONE,
|
|
382
622
|
status: StateStatus.NONE,
|
|
383
623
|
level: "info",
|
|
384
624
|
ts: 0
|
|
385
625
|
},
|
|
386
|
-
|
|
387
|
-
var:
|
|
388
|
-
code: STATE_VAR_CODES
|
|
626
|
+
transaction: {
|
|
627
|
+
var: "transaction",
|
|
628
|
+
code: STATE_VAR_CODES.transaction.NONE,
|
|
389
629
|
status: StateStatus.NONE,
|
|
390
630
|
level: "info",
|
|
391
631
|
ts: 0
|
|
@@ -404,8 +644,8 @@ function PollarProvider({ config, styles: propStyles, children }) {
|
|
|
404
644
|
}
|
|
405
645
|
return prevState;
|
|
406
646
|
});
|
|
407
|
-
if (stateEntry.var ===
|
|
408
|
-
if (stateEntry.code === STATE_VAR_CODES
|
|
647
|
+
if (stateEntry.var === "authentication") {
|
|
648
|
+
if ((stateEntry.code === STATE_VAR_CODES.authentication.SESSION_STORED || STATE_VAR_CODES.authentication.RESTORED_SESSION_SUCCESS) && isValidSession(stateEntry.data)) {
|
|
409
649
|
setSessionState((prevState) => {
|
|
410
650
|
if (JSON.stringify(prevState) !== JSON.stringify(stateEntry.data)) {
|
|
411
651
|
return stateEntry.data;
|
|
@@ -413,9 +653,9 @@ function PollarProvider({ config, styles: propStyles, children }) {
|
|
|
413
653
|
return prevState;
|
|
414
654
|
});
|
|
415
655
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
656
|
+
if (stateEntry.code === STATE_VAR_CODES.authentication.LOGOUT) {
|
|
657
|
+
setSessionState(null);
|
|
658
|
+
}
|
|
419
659
|
}
|
|
420
660
|
});
|
|
421
661
|
}, [pollarClient]);
|
|
@@ -431,31 +671,43 @@ function PollarProvider({ config, styles: propStyles, children }) {
|
|
|
431
671
|
setStyles(propStyles ?? {});
|
|
432
672
|
});
|
|
433
673
|
}, [pollarClient]);
|
|
434
|
-
const [
|
|
674
|
+
const [loginModalOpen, setLoginModalOpen] = useState(false);
|
|
675
|
+
const [transactionModalOpen, setTransactionModalOpen] = useState(false);
|
|
435
676
|
const contextValue = useMemo(
|
|
436
677
|
() => ({
|
|
437
678
|
walletAddress: sessionState?.wallet?.publicKey || "",
|
|
438
679
|
getClient: () => pollarClient,
|
|
439
|
-
|
|
440
|
-
|
|
680
|
+
// client
|
|
681
|
+
state,
|
|
441
682
|
login: (options) => pollarClient.login(options),
|
|
442
683
|
logout: () => pollarClient.logout(),
|
|
684
|
+
isAuthenticated: pollarClient.isAuthenticated(),
|
|
685
|
+
buildTx: (operation, params, options) => pollarClient.buildTx(operation, params, options),
|
|
686
|
+
submitTx: (signedXdr) => pollarClient.submitTx(signedXdr),
|
|
687
|
+
// react
|
|
688
|
+
sendTransaction: (operation, params, options) => {
|
|
689
|
+
void pollarClient.buildTx(operation, params, options);
|
|
690
|
+
setTransactionModalOpen(true);
|
|
691
|
+
},
|
|
692
|
+
openTransactionModal: () => setTransactionModalOpen(true),
|
|
693
|
+
openLoginModal: () => setLoginModalOpen(true),
|
|
443
694
|
config: remoteConfig,
|
|
444
|
-
state,
|
|
445
695
|
styles,
|
|
696
|
+
// stellar
|
|
446
697
|
async getBalance(publicKey) {
|
|
447
698
|
const pk = publicKey || sessionState?.wallet?.publicKey;
|
|
448
699
|
if (pk) {
|
|
449
|
-
return stellarClient.getBalances(pk);
|
|
700
|
+
return await stellarClient.getBalances(pk);
|
|
450
701
|
}
|
|
451
|
-
return
|
|
702
|
+
return { success: false, errorCode: "NO_WALLET_FOUND", balances: [] };
|
|
452
703
|
}
|
|
453
704
|
}),
|
|
454
705
|
[sessionState, remoteConfig, styles, pollarClient, state]
|
|
455
706
|
);
|
|
456
707
|
return /* @__PURE__ */ jsxs(PollarContext.Provider, { value: contextValue, children: [
|
|
457
708
|
children,
|
|
458
|
-
|
|
709
|
+
loginModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setLoginModalOpen(false), children: /* @__PURE__ */ jsx(LoginModal, { onClose: () => setLoginModalOpen(false) }) }),
|
|
710
|
+
transactionModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setTransactionModalOpen(false), children: /* @__PURE__ */ jsx(TransactionModal, { onClose: () => setTransactionModalOpen(false) }) })
|
|
459
711
|
] });
|
|
460
712
|
}
|
|
461
713
|
function usePollar() {
|