stellar-wallet-kit 2.0.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.js ADDED
@@ -0,0 +1,840 @@
1
+ 'use strict';
2
+
3
+ var React3 = require('react');
4
+ var freighterApi = require('@stellar/freighter-api');
5
+
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var React3__default = /*#__PURE__*/_interopDefault(React3);
9
+
10
+ // src/context/WalletContext.tsx
11
+
12
+ // src/types/index.ts
13
+ var WalletType = /* @__PURE__ */ ((WalletType2) => {
14
+ WalletType2["FREIGHTER"] = "freighter";
15
+ return WalletType2;
16
+ })(WalletType || {});
17
+ var NetworkType = /* @__PURE__ */ ((NetworkType2) => {
18
+ NetworkType2["PUBLIC"] = "PUBLIC";
19
+ NetworkType2["TESTNET"] = "TESTNET";
20
+ NetworkType2["FUTURENET"] = "FUTURENET";
21
+ NetworkType2["STANDALONE"] = "STANDALONE";
22
+ return NetworkType2;
23
+ })(NetworkType || {});
24
+ var FreighterAdapter = class {
25
+ constructor() {
26
+ this.type = "freighter" /* FREIGHTER */;
27
+ }
28
+ async isAvailable() {
29
+ try {
30
+ return await freighterApi.isConnected();
31
+ } catch (error) {
32
+ console.error("Error checking Freighter availability:", error);
33
+ return false;
34
+ }
35
+ }
36
+ async connect() {
37
+ try {
38
+ const connected = await freighterApi.isConnected();
39
+ if (!connected) {
40
+ throw new Error("Freighter wallet is not installed");
41
+ }
42
+ const allowed = await freighterApi.isAllowed();
43
+ if (!allowed) {
44
+ await freighterApi.setAllowed();
45
+ }
46
+ const userInfo = await freighterApi.getUserInfo();
47
+ if (!userInfo || !userInfo.publicKey) {
48
+ throw new Error("Failed to get user information from Freighter");
49
+ }
50
+ return {
51
+ address: userInfo.publicKey,
52
+ publicKey: userInfo.publicKey
53
+ };
54
+ } catch (error) {
55
+ console.error("Error connecting to Freighter:", error);
56
+ throw new Error(`Failed to connect to Freighter: ${error instanceof Error ? error.message : "Unknown error"}`);
57
+ }
58
+ }
59
+ async disconnect() {
60
+ console.log("Freighter disconnect requested - user must disconnect from extension");
61
+ }
62
+ async getPublicKey() {
63
+ try {
64
+ const allowed = await freighterApi.isAllowed();
65
+ if (!allowed) {
66
+ return null;
67
+ }
68
+ const userInfo = await freighterApi.getUserInfo();
69
+ return userInfo?.publicKey || null;
70
+ } catch (error) {
71
+ console.error("Error getting public key:", error);
72
+ return null;
73
+ }
74
+ }
75
+ async getNetwork() {
76
+ try {
77
+ const network = await freighterApi.getNetwork();
78
+ return network;
79
+ } catch (error) {
80
+ console.error("Error getting network:", error);
81
+ throw error;
82
+ }
83
+ }
84
+ async signTransaction(xdr, options) {
85
+ try {
86
+ const result = await freighterApi.signTransaction(xdr, {
87
+ network: options?.network,
88
+ networkPassphrase: options?.networkPassphrase,
89
+ accountToSign: options?.accountToSign
90
+ });
91
+ if (!result || typeof result !== "string") {
92
+ throw new Error("Invalid response from Freighter");
93
+ }
94
+ return {
95
+ signedTxXdr: result
96
+ };
97
+ } catch (error) {
98
+ console.error("Error signing transaction:", error);
99
+ throw new Error(`Failed to sign transaction: ${error instanceof Error ? error.message : "Unknown error"}`);
100
+ }
101
+ }
102
+ async signAuthEntry(entryXdr, options) {
103
+ try {
104
+ const result = await freighterApi.signAuthEntry(entryXdr, {
105
+ accountToSign: options?.accountToSign
106
+ });
107
+ if (!result || typeof result !== "string") {
108
+ throw new Error("Invalid response from Freighter");
109
+ }
110
+ return {
111
+ signedAuthEntry: result
112
+ };
113
+ } catch (error) {
114
+ console.error("Error signing auth entry:", error);
115
+ throw new Error(`Failed to sign auth entry: ${error instanceof Error ? error.message : "Unknown error"}`);
116
+ }
117
+ }
118
+ };
119
+
120
+ // src/utils/balanceUtils.ts
121
+ var HORIZON_URLS = {
122
+ PUBLIC: "https://horizon.stellar.org",
123
+ TESTNET: "https://horizon-testnet.stellar.org",
124
+ FUTURENET: "https://horizon-futurenet.stellar.org",
125
+ STANDALONE: "http://localhost:8000"
126
+ };
127
+ async function fetchAccountBalances(publicKey, network) {
128
+ const horizonUrl = HORIZON_URLS[network];
129
+ try {
130
+ const response = await fetch(`${horizonUrl}/accounts/${publicKey}`);
131
+ if (!response.ok) {
132
+ if (response.status === 404) {
133
+ throw new Error("Account not found. Make sure the account is funded.");
134
+ }
135
+ throw new Error(`Failed to fetch account: ${response.statusText}`);
136
+ }
137
+ const data = await response.json();
138
+ return data.balances;
139
+ } catch (error) {
140
+ console.error("Error fetching balances:", error);
141
+ throw error;
142
+ }
143
+ }
144
+ function getNativeBalance(balances) {
145
+ const nativeBalance = balances.find((b) => b.asset_type === "native");
146
+ return nativeBalance?.balance || "0";
147
+ }
148
+ function formatBalance(balance, decimals = 7) {
149
+ const num = parseFloat(balance);
150
+ if (isNaN(num)) return "0";
151
+ return num.toFixed(decimals).replace(/\.?0+$/, "");
152
+ }
153
+ function getAssetBalance(balances, assetCode, assetIssuer) {
154
+ if (!assetCode) {
155
+ return getNativeBalance(balances);
156
+ }
157
+ const asset = balances.find(
158
+ (b) => b.asset_code === assetCode && (!assetIssuer || b.asset_issuer === assetIssuer)
159
+ );
160
+ return asset?.balance || "0";
161
+ }
162
+ function hasSufficientBalance(balances, requiredAmount, assetCode, assetIssuer) {
163
+ const balance = getAssetBalance(balances, assetCode, assetIssuer);
164
+ return parseFloat(balance) >= parseFloat(requiredAmount);
165
+ }
166
+ function getTotalValueXLM(balances) {
167
+ return getNativeBalance(balances);
168
+ }
169
+ function groupBalancesByType(balances) {
170
+ return balances.reduce((acc, balance) => {
171
+ const type = balance.asset_type;
172
+ if (!acc[type]) {
173
+ acc[type] = [];
174
+ }
175
+ acc[type].push(balance);
176
+ return acc;
177
+ }, {});
178
+ }
179
+
180
+ // src/context/WalletContext.tsx
181
+ var WalletContext = React3.createContext(void 0);
182
+ var STORAGE_KEY = "stellar_wallet_kit";
183
+ var getStorageData = () => {
184
+ if (typeof window === "undefined") {
185
+ return { selectedWallet: null, autoConnect: false };
186
+ }
187
+ try {
188
+ const data = localStorage.getItem(STORAGE_KEY);
189
+ return data ? JSON.parse(data) : { selectedWallet: null, autoConnect: false };
190
+ } catch {
191
+ return { selectedWallet: null, autoConnect: false };
192
+ }
193
+ };
194
+ var setStorageData = (data) => {
195
+ if (typeof window === "undefined") return;
196
+ try {
197
+ const existing = getStorageData();
198
+ localStorage.setItem(STORAGE_KEY, JSON.stringify({ ...existing, ...data }));
199
+ } catch (error) {
200
+ console.error("Failed to save to localStorage:", error);
201
+ }
202
+ };
203
+ var isBrowser = typeof window !== "undefined";
204
+ var walletAdapters = {
205
+ ["freighter" /* FREIGHTER */]: new FreighterAdapter()
206
+ };
207
+ var walletMetadata = {
208
+ ["freighter" /* FREIGHTER */]: {
209
+ id: "freighter" /* FREIGHTER */,
210
+ name: "Freighter",
211
+ icon: "https://stellar.creit.tech/wallet-icons/freighter.svg",
212
+ description: "Freighter browser extension wallet",
213
+ downloadUrl: "https://chrome.google.com/webstore/detail/freighter/bcacfldlkkdogcmkkibnjlakofdplcbk"
214
+ }
215
+ };
216
+ function WalletProvider({ config = {}, children }) {
217
+ const [account, setAccount] = React3.useState(null);
218
+ const [isConnecting, setIsConnecting] = React3.useState(false);
219
+ const [error, setError] = React3.useState(null);
220
+ const [network, setNetwork] = React3.useState(config.network || "TESTNET" /* TESTNET */);
221
+ const [selectedWallet, setSelectedWallet] = React3.useState(null);
222
+ const [availableWallets, setAvailableWallets] = React3.useState([]);
223
+ const [isLoadingBalances, setIsLoadingBalances] = React3.useState(false);
224
+ const isConnected2 = !!account;
225
+ React3.useEffect(() => {
226
+ if (!isBrowser) return;
227
+ const checkWallets = async () => {
228
+ const wallets = [];
229
+ for (const [type, adapter] of Object.entries(walletAdapters)) {
230
+ const installed = await adapter.isAvailable();
231
+ wallets.push({
232
+ ...walletMetadata[type],
233
+ installed
234
+ });
235
+ }
236
+ setAvailableWallets(wallets);
237
+ };
238
+ checkWallets();
239
+ }, []);
240
+ React3.useEffect(() => {
241
+ if (!isBrowser) return;
242
+ const autoConnectWallet = async () => {
243
+ const storage = getStorageData();
244
+ if (config.autoConnect && storage.selectedWallet) {
245
+ try {
246
+ await connect(storage.selectedWallet);
247
+ } catch (err) {
248
+ console.error("Auto-connect failed:", err);
249
+ }
250
+ }
251
+ };
252
+ autoConnectWallet();
253
+ }, [config.autoConnect]);
254
+ const refreshBalances = React3.useCallback(async () => {
255
+ if (!account?.publicKey) {
256
+ return;
257
+ }
258
+ setIsLoadingBalances(true);
259
+ try {
260
+ const balances = await fetchAccountBalances(account.publicKey, network);
261
+ setAccount((prev) => prev ? { ...prev, balances } : null);
262
+ } catch (err) {
263
+ console.error("Failed to fetch balances:", err);
264
+ } finally {
265
+ setIsLoadingBalances(false);
266
+ }
267
+ }, [account?.publicKey, network]);
268
+ const connect = React3.useCallback(async (walletType) => {
269
+ setIsConnecting(true);
270
+ setError(null);
271
+ try {
272
+ const typeToConnect = walletType || config.defaultWallet || "freighter" /* FREIGHTER */;
273
+ const adapter = walletAdapters[typeToConnect];
274
+ if (!adapter) {
275
+ throw new Error(`Wallet adapter not found for ${typeToConnect}`);
276
+ }
277
+ const available = await adapter.isAvailable();
278
+ if (!available) {
279
+ throw new Error(`${walletMetadata[typeToConnect].name} is not installed`);
280
+ }
281
+ const response = await adapter.connect();
282
+ const newAccount = {
283
+ address: response.address,
284
+ publicKey: response.publicKey,
285
+ displayName: `${response.address.slice(0, 4)}...${response.address.slice(-4)}`
286
+ };
287
+ setAccount(newAccount);
288
+ setSelectedWallet(typeToConnect);
289
+ setStorageData({ selectedWallet: typeToConnect, autoConnect: true });
290
+ try {
291
+ const balances = await fetchAccountBalances(response.publicKey, network);
292
+ setAccount((prev) => prev ? { ...prev, balances } : null);
293
+ } catch (balanceError) {
294
+ console.error("Failed to fetch initial balances:", balanceError);
295
+ }
296
+ } catch (err) {
297
+ const error2 = err instanceof Error ? err : new Error("Failed to connect wallet");
298
+ setError(error2);
299
+ throw error2;
300
+ } finally {
301
+ setIsConnecting(false);
302
+ }
303
+ }, [config.defaultWallet]);
304
+ const disconnect = React3.useCallback(async () => {
305
+ try {
306
+ if (selectedWallet) {
307
+ const adapter = walletAdapters[selectedWallet];
308
+ await adapter.disconnect();
309
+ }
310
+ setAccount(null);
311
+ setSelectedWallet(null);
312
+ setError(null);
313
+ setStorageData({ selectedWallet: null, autoConnect: false });
314
+ } catch (err) {
315
+ const error2 = err instanceof Error ? err : new Error("Failed to disconnect wallet");
316
+ setError(error2);
317
+ throw error2;
318
+ }
319
+ }, [selectedWallet]);
320
+ const signTransaction2 = React3.useCallback(async (xdr, options) => {
321
+ if (!selectedWallet) {
322
+ throw new Error("No wallet connected");
323
+ }
324
+ const adapter = walletAdapters[selectedWallet];
325
+ return adapter.signTransaction(xdr, options);
326
+ }, [selectedWallet]);
327
+ const signAuthEntry2 = React3.useCallback(async (entryXdr, options) => {
328
+ if (!selectedWallet) {
329
+ throw new Error("No wallet connected");
330
+ }
331
+ const adapter = walletAdapters[selectedWallet];
332
+ return adapter.signAuthEntry(entryXdr, options);
333
+ }, [selectedWallet]);
334
+ const switchNetwork = React3.useCallback(async (newNetwork) => {
335
+ setNetwork(newNetwork);
336
+ if (account?.publicKey) {
337
+ await refreshBalances();
338
+ }
339
+ }, [account?.publicKey, refreshBalances]);
340
+ React3.useEffect(() => {
341
+ if (!account?.publicKey || !isBrowser) return;
342
+ refreshBalances();
343
+ const interval = setInterval(() => {
344
+ refreshBalances();
345
+ }, 3e4);
346
+ return () => clearInterval(interval);
347
+ }, [account?.publicKey, refreshBalances]);
348
+ const value = React3.useMemo(
349
+ () => ({
350
+ account,
351
+ isConnected: isConnected2,
352
+ isConnecting,
353
+ error,
354
+ network,
355
+ selectedWallet,
356
+ connect,
357
+ disconnect,
358
+ signTransaction: signTransaction2,
359
+ signAuthEntry: signAuthEntry2,
360
+ switchNetwork,
361
+ availableWallets,
362
+ refreshBalances,
363
+ isLoadingBalances
364
+ }),
365
+ [
366
+ account,
367
+ isConnected2,
368
+ isConnecting,
369
+ error,
370
+ network,
371
+ selectedWallet,
372
+ connect,
373
+ disconnect,
374
+ signTransaction2,
375
+ signAuthEntry2,
376
+ switchNetwork,
377
+ availableWallets,
378
+ refreshBalances,
379
+ isLoadingBalances
380
+ ]
381
+ );
382
+ return /* @__PURE__ */ React3__default.default.createElement(WalletContext.Provider, { value }, children);
383
+ }
384
+ function useWallet() {
385
+ const context = React3.useContext(WalletContext);
386
+ if (context === void 0) {
387
+ throw new Error("useWallet must be used within a WalletProvider");
388
+ }
389
+ return context;
390
+ }
391
+ function WalletModal({
392
+ isOpen,
393
+ onClose,
394
+ wallets,
395
+ onSelectWallet,
396
+ theme,
397
+ appName = "Your App",
398
+ appIcon
399
+ }) {
400
+ React3.useEffect(() => {
401
+ const handleEsc = (e) => {
402
+ if (e.key === "Escape") onClose();
403
+ };
404
+ if (isOpen) {
405
+ document.addEventListener("keydown", handleEsc);
406
+ document.body.style.overflow = "hidden";
407
+ }
408
+ return () => {
409
+ document.removeEventListener("keydown", handleEsc);
410
+ document.body.style.overflow = "unset";
411
+ };
412
+ }, [isOpen, onClose]);
413
+ if (!isOpen) return null;
414
+ const themeMode = theme?.mode || "light";
415
+ const isDark = themeMode === "dark" || themeMode === "auto" && window.matchMedia("(prefers-color-scheme: dark)").matches;
416
+ const styles = {
417
+ overlay: {
418
+ position: "fixed",
419
+ top: 0,
420
+ left: 0,
421
+ right: 0,
422
+ bottom: 0,
423
+ backgroundColor: theme?.overlayBackground || (isDark ? "rgba(0, 0, 0, 0.8)" : "rgba(0, 0, 0, 0.5)"),
424
+ display: "flex",
425
+ alignItems: "center",
426
+ justifyContent: "center",
427
+ zIndex: 9999,
428
+ animation: "swk-fade-in 0.2s ease-out"
429
+ },
430
+ modal: {
431
+ backgroundColor: theme?.modalBackground || (isDark ? "#1a1a1a" : "#ffffff"),
432
+ borderRadius: theme?.borderRadius || "16px",
433
+ padding: "24px",
434
+ maxWidth: "420px",
435
+ width: "90%",
436
+ maxHeight: "80vh",
437
+ overflowY: "auto",
438
+ boxShadow: isDark ? "0 8px 32px rgba(0, 0, 0, 0.4)" : "0 8px 32px rgba(0, 0, 0, 0.1)",
439
+ animation: "swk-slide-up 0.3s ease-out",
440
+ fontFamily: theme?.fontFamily || '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
441
+ },
442
+ header: {
443
+ display: "flex",
444
+ alignItems: "center",
445
+ justifyContent: "space-between",
446
+ marginBottom: "24px"
447
+ },
448
+ title: {
449
+ fontSize: "20px",
450
+ fontWeight: 600,
451
+ color: theme?.textColor || (isDark ? "#ffffff" : "#000000"),
452
+ margin: 0,
453
+ display: "flex",
454
+ alignItems: "center",
455
+ gap: "12px"
456
+ },
457
+ closeButton: {
458
+ background: "none",
459
+ border: "none",
460
+ fontSize: "24px",
461
+ cursor: "pointer",
462
+ padding: "4px",
463
+ color: theme?.textColor || (isDark ? "#888888" : "#666666"),
464
+ transition: "color 0.2s",
465
+ lineHeight: 1
466
+ },
467
+ walletList: {
468
+ display: "flex",
469
+ flexDirection: "column",
470
+ gap: "12px"
471
+ },
472
+ walletButton: {
473
+ display: "flex",
474
+ alignItems: "center",
475
+ gap: "16px",
476
+ padding: "16px",
477
+ border: `1px solid ${isDark ? "#333333" : "#e5e5e5"}`,
478
+ borderRadius: theme?.borderRadius || "12px",
479
+ background: "none",
480
+ cursor: "pointer",
481
+ transition: "all 0.2s",
482
+ width: "100%",
483
+ textAlign: "left",
484
+ fontFamily: "inherit"
485
+ },
486
+ walletIcon: {
487
+ width: "40px",
488
+ height: "40px",
489
+ borderRadius: "8px",
490
+ flexShrink: 0
491
+ },
492
+ walletInfo: {
493
+ flex: 1
494
+ },
495
+ walletName: {
496
+ fontSize: "16px",
497
+ fontWeight: 500,
498
+ color: theme?.textColor || (isDark ? "#ffffff" : "#000000"),
499
+ margin: 0,
500
+ marginBottom: "4px"
501
+ },
502
+ walletDescription: {
503
+ fontSize: "13px",
504
+ color: theme?.textColor || (isDark ? "#888888" : "#666666"),
505
+ margin: 0
506
+ },
507
+ badge: {
508
+ padding: "4px 8px",
509
+ borderRadius: "6px",
510
+ fontSize: "12px",
511
+ fontWeight: 500,
512
+ flexShrink: 0
513
+ },
514
+ installedBadge: {
515
+ backgroundColor: theme?.primaryColor || (isDark ? "#4CAF50" : "#4CAF50"),
516
+ color: "#ffffff"
517
+ },
518
+ notInstalledBadge: {
519
+ backgroundColor: isDark ? "#333333" : "#f0f0f0",
520
+ color: isDark ? "#888888" : "#666666"
521
+ },
522
+ footer: {
523
+ marginTop: "24px",
524
+ paddingTop: "16px",
525
+ borderTop: `1px solid ${isDark ? "#333333" : "#e5e5e5"}`,
526
+ fontSize: "13px",
527
+ color: isDark ? "#888888" : "#666666",
528
+ textAlign: "center"
529
+ },
530
+ link: {
531
+ color: theme?.primaryColor || "#8b5cf6",
532
+ textDecoration: "none"
533
+ }
534
+ };
535
+ const handleWalletClick = (wallet) => {
536
+ if (wallet.installed) {
537
+ onSelectWallet(wallet.id);
538
+ } else if (wallet.downloadUrl) {
539
+ window.open(wallet.downloadUrl, "_blank");
540
+ }
541
+ };
542
+ return /* @__PURE__ */ React3__default.default.createElement(React3__default.default.Fragment, null, /* @__PURE__ */ React3__default.default.createElement("style", null, `
543
+ @keyframes swk-fade-in {
544
+ from { opacity: 0; }
545
+ to { opacity: 1; }
546
+ }
547
+ @keyframes swk-slide-up {
548
+ from {
549
+ opacity: 0;
550
+ transform: translateY(20px);
551
+ }
552
+ to {
553
+ opacity: 1;
554
+ transform: translateY(0);
555
+ }
556
+ }
557
+ .swk-wallet-button:hover {
558
+ background-color: ${theme?.buttonHoverColor || (isDark ? "#252525" : "#f5f5f5")} !important;
559
+ border-color: ${theme?.primaryColor || "#8b5cf6"} !important;
560
+ }
561
+ .swk-close-button:hover {
562
+ color: ${theme?.primaryColor || "#8b5cf6"} !important;
563
+ }
564
+ `), /* @__PURE__ */ React3__default.default.createElement("div", { style: styles.overlay, onClick: onClose }, /* @__PURE__ */ React3__default.default.createElement("div", { style: styles.modal, onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React3__default.default.createElement("div", { style: styles.header }, /* @__PURE__ */ React3__default.default.createElement("h2", { style: styles.title }, appIcon && /* @__PURE__ */ React3__default.default.createElement("img", { src: appIcon, alt: "", style: { width: "32px", height: "32px", borderRadius: "8px" } }), "Connect Wallet"), /* @__PURE__ */ React3__default.default.createElement(
565
+ "button",
566
+ {
567
+ className: "swk-close-button",
568
+ style: styles.closeButton,
569
+ onClick: onClose,
570
+ "aria-label": "Close modal"
571
+ },
572
+ "\xD7"
573
+ )), /* @__PURE__ */ React3__default.default.createElement("div", { style: styles.walletList }, wallets.map((wallet) => /* @__PURE__ */ React3__default.default.createElement(
574
+ "button",
575
+ {
576
+ key: wallet.id,
577
+ className: "swk-wallet-button",
578
+ style: styles.walletButton,
579
+ onClick: () => handleWalletClick(wallet),
580
+ disabled: !wallet.installed && !wallet.downloadUrl
581
+ },
582
+ /* @__PURE__ */ React3__default.default.createElement(
583
+ "img",
584
+ {
585
+ src: wallet.icon,
586
+ alt: `${wallet.name} icon`,
587
+ style: styles.walletIcon
588
+ }
589
+ ),
590
+ /* @__PURE__ */ React3__default.default.createElement("div", { style: styles.walletInfo }, /* @__PURE__ */ React3__default.default.createElement("p", { style: styles.walletName }, wallet.name), wallet.description && /* @__PURE__ */ React3__default.default.createElement("p", { style: styles.walletDescription }, wallet.description)),
591
+ /* @__PURE__ */ React3__default.default.createElement(
592
+ "div",
593
+ {
594
+ style: {
595
+ ...styles.badge,
596
+ ...wallet.installed ? styles.installedBadge : styles.notInstalledBadge
597
+ }
598
+ },
599
+ wallet.installed ? "Installed" : "Get"
600
+ )
601
+ ))), /* @__PURE__ */ React3__default.default.createElement("div", { style: styles.footer }, /* @__PURE__ */ React3__default.default.createElement("p", { style: { margin: 0 } }, "Don't have a wallet?", " ", /* @__PURE__ */ React3__default.default.createElement(
602
+ "a",
603
+ {
604
+ href: "https://www.stellar.org/ecosystem/projects#wallets",
605
+ target: "_blank",
606
+ rel: "noopener noreferrer",
607
+ style: styles.link
608
+ },
609
+ "Learn more"
610
+ ))))));
611
+ }
612
+
613
+ // src/components/ConnectButton.tsx
614
+ function ConnectButton({
615
+ label = "Connect Wallet",
616
+ theme,
617
+ className,
618
+ style,
619
+ showBalance = false,
620
+ onConnect,
621
+ onDisconnect
622
+ }) {
623
+ const {
624
+ account,
625
+ isConnected: isConnected2,
626
+ isConnecting,
627
+ connect,
628
+ disconnect,
629
+ availableWallets,
630
+ selectedWallet,
631
+ refreshBalances,
632
+ isLoadingBalances
633
+ } = useWallet();
634
+ const [isModalOpen, setIsModalOpen] = React3.useState(false);
635
+ const [showDropdown, setShowDropdown] = React3.useState(false);
636
+ const themeMode = theme?.mode || "light";
637
+ const isDark = themeMode === "dark" || themeMode === "auto" && window.matchMedia("(prefers-color-scheme: dark)").matches;
638
+ const defaultButtonStyles = {
639
+ padding: "12px 24px",
640
+ borderRadius: theme?.borderRadius || "12px",
641
+ border: "none",
642
+ fontSize: "15px",
643
+ fontWeight: 500,
644
+ cursor: "pointer",
645
+ transition: "all 0.2s",
646
+ fontFamily: theme?.fontFamily || '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
647
+ ...style
648
+ };
649
+ const connectButtonStyles = {
650
+ ...defaultButtonStyles,
651
+ backgroundColor: theme?.primaryColor || "#8b5cf6",
652
+ color: "#ffffff"
653
+ };
654
+ const accountButtonStyles = {
655
+ ...defaultButtonStyles,
656
+ backgroundColor: isDark ? "#252525" : "#f5f5f5",
657
+ color: theme?.textColor || (isDark ? "#ffffff" : "#000000"),
658
+ border: `1px solid ${isDark ? "#333333" : "#e5e5e5"}`,
659
+ position: "relative",
660
+ display: "flex",
661
+ alignItems: "center",
662
+ gap: "8px"
663
+ };
664
+ const dropdownStyles = {
665
+ position: "absolute",
666
+ top: "calc(100% + 8px)",
667
+ right: 0,
668
+ backgroundColor: theme?.modalBackground || (isDark ? "#1a1a1a" : "#ffffff"),
669
+ border: `1px solid ${isDark ? "#333333" : "#e5e5e5"}`,
670
+ borderRadius: theme?.borderRadius || "12px",
671
+ padding: "8px",
672
+ minWidth: "200px",
673
+ boxShadow: isDark ? "0 4px 16px rgba(0, 0, 0, 0.4)" : "0 4px 16px rgba(0, 0, 0, 0.1)",
674
+ zIndex: 1e3
675
+ };
676
+ const dropdownItemStyles = {
677
+ padding: "12px 16px",
678
+ border: "none",
679
+ background: "none",
680
+ cursor: "pointer",
681
+ width: "100%",
682
+ textAlign: "left",
683
+ fontSize: "14px",
684
+ color: theme?.textColor || (isDark ? "#ffffff" : "#000000"),
685
+ borderRadius: "8px",
686
+ transition: "background-color 0.2s",
687
+ fontFamily: "inherit"
688
+ };
689
+ const handleConnect = async (walletType) => {
690
+ try {
691
+ await connect(walletType);
692
+ setIsModalOpen(false);
693
+ onConnect?.();
694
+ } catch (error) {
695
+ console.error("Connection error:", error);
696
+ }
697
+ };
698
+ const handleDisconnect = async () => {
699
+ try {
700
+ await disconnect();
701
+ setShowDropdown(false);
702
+ onDisconnect?.();
703
+ } catch (error) {
704
+ console.error("Disconnect error:", error);
705
+ }
706
+ };
707
+ const copyAddress = () => {
708
+ if (account?.address) {
709
+ navigator.clipboard.writeText(account.address);
710
+ setShowDropdown(false);
711
+ }
712
+ };
713
+ if (isConnecting) {
714
+ return /* @__PURE__ */ React3__default.default.createElement(
715
+ "button",
716
+ {
717
+ className,
718
+ style: connectButtonStyles,
719
+ disabled: true
720
+ },
721
+ "Connecting..."
722
+ );
723
+ }
724
+ if (!isConnected2 || !account) {
725
+ return /* @__PURE__ */ React3__default.default.createElement(React3__default.default.Fragment, null, /* @__PURE__ */ React3__default.default.createElement(
726
+ "button",
727
+ {
728
+ className,
729
+ style: connectButtonStyles,
730
+ onClick: () => setIsModalOpen(true)
731
+ },
732
+ label
733
+ ), /* @__PURE__ */ React3__default.default.createElement(
734
+ WalletModal,
735
+ {
736
+ isOpen: isModalOpen,
737
+ onClose: () => setIsModalOpen(false),
738
+ wallets: availableWallets,
739
+ onSelectWallet: handleConnect,
740
+ theme
741
+ }
742
+ ));
743
+ }
744
+ const walletIcon = availableWallets.find((w) => w.id === selectedWallet)?.icon;
745
+ const nativeBalance = account?.balances ? getNativeBalance(account.balances) : null;
746
+ const formattedBalance = nativeBalance ? formatBalance(nativeBalance, 2) : null;
747
+ return /* @__PURE__ */ React3__default.default.createElement(React3__default.default.Fragment, null, /* @__PURE__ */ React3__default.default.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React3__default.default.createElement(
748
+ "button",
749
+ {
750
+ className,
751
+ style: accountButtonStyles,
752
+ onClick: () => setShowDropdown(!showDropdown)
753
+ },
754
+ walletIcon && /* @__PURE__ */ React3__default.default.createElement(
755
+ "img",
756
+ {
757
+ src: walletIcon,
758
+ alt: "Wallet",
759
+ style: { width: "20px", height: "20px", borderRadius: "4px" }
760
+ }
761
+ ),
762
+ /* @__PURE__ */ React3__default.default.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "2px" } }, /* @__PURE__ */ React3__default.default.createElement("span", null, account.displayName), showBalance && formattedBalance && /* @__PURE__ */ React3__default.default.createElement("span", { style: { fontSize: "12px", opacity: 0.7, fontWeight: 400 } }, isLoadingBalances ? "..." : `${formattedBalance} XLM`)),
763
+ /* @__PURE__ */ React3__default.default.createElement("span", { style: { fontSize: "12px", opacity: 0.7 } }, "\u25BC")
764
+ ), showDropdown && /* @__PURE__ */ React3__default.default.createElement(React3__default.default.Fragment, null, /* @__PURE__ */ React3__default.default.createElement(
765
+ "div",
766
+ {
767
+ style: {
768
+ position: "fixed",
769
+ top: 0,
770
+ left: 0,
771
+ right: 0,
772
+ bottom: 0,
773
+ zIndex: 999
774
+ },
775
+ onClick: () => setShowDropdown(false)
776
+ }
777
+ ), /* @__PURE__ */ React3__default.default.createElement("div", { style: dropdownStyles }, /* @__PURE__ */ React3__default.default.createElement(
778
+ "button",
779
+ {
780
+ style: dropdownItemStyles,
781
+ onClick: () => {
782
+ refreshBalances();
783
+ setShowDropdown(false);
784
+ },
785
+ onMouseEnter: (e) => {
786
+ e.currentTarget.style.backgroundColor = theme?.buttonHoverColor || (isDark ? "#333333" : "#f0f0f0");
787
+ },
788
+ onMouseLeave: (e) => {
789
+ e.currentTarget.style.backgroundColor = "transparent";
790
+ }
791
+ },
792
+ "\u{1F504} Refresh Balances"
793
+ ), /* @__PURE__ */ React3__default.default.createElement(
794
+ "button",
795
+ {
796
+ style: dropdownItemStyles,
797
+ onClick: copyAddress,
798
+ onMouseEnter: (e) => {
799
+ e.currentTarget.style.backgroundColor = theme?.buttonHoverColor || (isDark ? "#333333" : "#f0f0f0");
800
+ },
801
+ onMouseLeave: (e) => {
802
+ e.currentTarget.style.backgroundColor = "transparent";
803
+ }
804
+ },
805
+ "\u{1F4CB} Copy Address"
806
+ ), /* @__PURE__ */ React3__default.default.createElement(
807
+ "button",
808
+ {
809
+ style: {
810
+ ...dropdownItemStyles,
811
+ color: "#ef4444"
812
+ },
813
+ onClick: handleDisconnect,
814
+ onMouseEnter: (e) => {
815
+ e.currentTarget.style.backgroundColor = theme?.buttonHoverColor || (isDark ? "#333333" : "#f0f0f0");
816
+ },
817
+ onMouseLeave: (e) => {
818
+ e.currentTarget.style.backgroundColor = "transparent";
819
+ }
820
+ },
821
+ "\u{1F6AA} Disconnect"
822
+ )))));
823
+ }
824
+
825
+ exports.ConnectButton = ConnectButton;
826
+ exports.FreighterAdapter = FreighterAdapter;
827
+ exports.NetworkType = NetworkType;
828
+ exports.WalletModal = WalletModal;
829
+ exports.WalletProvider = WalletProvider;
830
+ exports.WalletType = WalletType;
831
+ exports.fetchAccountBalances = fetchAccountBalances;
832
+ exports.formatBalance = formatBalance;
833
+ exports.getAssetBalance = getAssetBalance;
834
+ exports.getNativeBalance = getNativeBalance;
835
+ exports.getTotalValueXLM = getTotalValueXLM;
836
+ exports.groupBalancesByType = groupBalancesByType;
837
+ exports.hasSufficientBalance = hasSufficientBalance;
838
+ exports.useWallet = useWallet;
839
+ //# sourceMappingURL=index.js.map
840
+ //# sourceMappingURL=index.js.map