@algobright/solana-connector 0.1.0 → 0.1.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/{Avatar.module-P7KEBP7R.module.css → Avatar.module-AACAT34D.module.css} +42 -42
- package/dist/{Button.module-7TPMDOJN.module.css → Button.module-HQNNX6IB.module.css} +145 -145
- package/dist/{Collapsible.module-NXSN3MGI.module.css → Collapsible.module-F4VIL5FH.module.css} +24 -24
- package/dist/ConnectButton.d.mts +4 -0
- package/dist/ConnectButton.d.ts +4 -0
- package/dist/ConnectButton.js +145 -39
- package/dist/ConnectButton.js.map +1 -1
- package/dist/ConnectButton.mjs +140 -34
- package/dist/ConnectButton.mjs.map +1 -1
- package/dist/{ConnectButton.module-UWQKSVTP.module.css → ConnectButton.module-O3M32YJK.module.css} +8 -8
- package/dist/{CustomQRCode.module-FOXENMZG.module.css → CustomQRCode.module-JW3JU3FX.module.css} +176 -176
- package/dist/{Dialog.module-HCRT743N.module.css → Dialog.module-AYJTMDAD.module.css} +136 -136
- package/dist/{Menu.module-GV627ZLI.module.css → Menu.module-6ATSLATI.module.css} +79 -79
- package/dist/{Spinner.module-G7GUQJZJ.module.css → Spinner.module-BLSWZSIL.module.css} +16 -16
- package/dist/WalletDropdown.d.mts +4 -0
- package/dist/WalletDropdown.d.ts +4 -0
- package/dist/WalletDropdown.js +132 -28
- package/dist/WalletDropdown.js.map +1 -1
- package/dist/WalletDropdown.mjs +129 -25
- package/dist/WalletDropdown.mjs.map +1 -1
- package/dist/{WalletDropdown.module-342MM7XM.module.css → WalletDropdown.module-DOK7CUOQ.module.css} +223 -220
- package/dist/WalletModal.js +7 -7
- package/dist/WalletModal.js.map +1 -1
- package/dist/WalletModal.mjs +7 -7
- package/dist/WalletModal.mjs.map +1 -1
- package/dist/{WalletModal.module-PVV5PRXU.module.css → WalletModal.module-ZRTJGOQY.module.css} +341 -341
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -9
package/dist/WalletDropdown.mjs
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
// src/components/WalletDropdown/WalletDropdown.tsx
|
|
4
4
|
import { useEffect, useRef, useState as useState2 } from "react";
|
|
5
|
-
import
|
|
5
|
+
import { isAddress } from "@solana/kit";
|
|
6
|
+
import styles3 from "./WalletDropdown.module-DOK7CUOQ.module.css";
|
|
6
7
|
import { motion } from "motion/react";
|
|
7
8
|
|
|
8
9
|
// src/components/shared/Avatar/Avatar.tsx
|
|
9
10
|
import { useState } from "react";
|
|
10
|
-
import styles from "./Avatar.module-
|
|
11
|
+
import styles from "./Avatar.module-AACAT34D.module.css";
|
|
11
12
|
import { Wallet } from "lucide-react";
|
|
12
13
|
import { jsx } from "react/jsx-runtime";
|
|
13
14
|
function Avatar({
|
|
@@ -39,7 +40,7 @@ import { Check, ChevronLeft, Copy, Globe, LogOut, RefreshCw } from "lucide-react
|
|
|
39
40
|
// src/components/shared/Button/Button.tsx
|
|
40
41
|
import * as React from "react";
|
|
41
42
|
import { Button as BaseButton } from "@base-ui/react/button";
|
|
42
|
-
import styles2 from "./Button.module-
|
|
43
|
+
import styles2 from "./Button.module-HQNNX6IB.module.css";
|
|
43
44
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
44
45
|
var Button = React.forwardRef(
|
|
45
46
|
({ className, variant = "default", size = "default", ...props }, ref) => {
|
|
@@ -62,9 +63,66 @@ var Button_default = Button;
|
|
|
62
63
|
var Button_default2 = Button_default;
|
|
63
64
|
|
|
64
65
|
// src/components/WalletDropdown/WalletDropdown.tsx
|
|
65
|
-
import {
|
|
66
|
-
import { createSolanaRpc } from "@solana/kit";
|
|
66
|
+
import { ClusterElement, DisconnectElement, useConnectorClient } from "@solana/connector";
|
|
67
67
|
import { clsx } from "clsx";
|
|
68
|
+
|
|
69
|
+
// src/utils/fetchBalance.tsx
|
|
70
|
+
import { findAssociatedTokenPda } from "@solana-program/token";
|
|
71
|
+
import { address, lamportsToSol } from "@solana/connector";
|
|
72
|
+
import { createSolanaRpc } from "@solana/kit";
|
|
73
|
+
async function getSolBalance(client, pubkey) {
|
|
74
|
+
let balance = 0;
|
|
75
|
+
try {
|
|
76
|
+
const rpcUrl = client.getRpcUrl();
|
|
77
|
+
if (!rpcUrl) {
|
|
78
|
+
console.error("RPC URL is not available from the ConnectorClient.");
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
const pubkeyAddress = address(pubkey);
|
|
82
|
+
const rpc = createSolanaRpc(rpcUrl);
|
|
83
|
+
const balanceResponse = await rpc.getBalance(pubkeyAddress).send();
|
|
84
|
+
balance = lamportsToSol(balanceResponse.value);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error("Error fetching SOL balance:", error);
|
|
87
|
+
} finally {
|
|
88
|
+
return balance;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async function getTokenBalance(client, pubkey, mintAddress) {
|
|
92
|
+
var _a;
|
|
93
|
+
let balance = 0;
|
|
94
|
+
try {
|
|
95
|
+
const rpcUrl = client.getRpcUrl();
|
|
96
|
+
if (!rpcUrl) {
|
|
97
|
+
console.error("RPC URL is not available from the ConnectorClient.");
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
const pubkeyAddress = address(pubkey);
|
|
101
|
+
const mintPubkey = address(mintAddress);
|
|
102
|
+
const rpc = createSolanaRpc(rpcUrl);
|
|
103
|
+
const mintInfo = await rpc.getAccountInfo(mintPubkey).send();
|
|
104
|
+
const ownerProgram = (_a = mintInfo.value) == null ? void 0 : _a.owner;
|
|
105
|
+
if (!ownerProgram) {
|
|
106
|
+
throw new Error("Failed to fetch mint account info");
|
|
107
|
+
}
|
|
108
|
+
const tokenProgram = address(ownerProgram);
|
|
109
|
+
const [tokenPDA] = await findAssociatedTokenPda({
|
|
110
|
+
mint: mintPubkey,
|
|
111
|
+
owner: pubkeyAddress,
|
|
112
|
+
tokenProgram
|
|
113
|
+
});
|
|
114
|
+
const tokenBalance = await rpc.getTokenAccountBalance(tokenPDA).send();
|
|
115
|
+
if (tokenBalance.value) {
|
|
116
|
+
balance = parseFloat(tokenBalance.value.uiAmountString);
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error("Error fetching token balance:", error);
|
|
120
|
+
} finally {
|
|
121
|
+
return balance;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/components/WalletDropdown/WalletDropdown.tsx
|
|
68
126
|
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
69
127
|
var networkColor = {
|
|
70
128
|
"solana:mainnet": "#00c950",
|
|
@@ -74,12 +132,24 @@ var networkColor = {
|
|
|
74
132
|
};
|
|
75
133
|
function WalletDropdown(props) {
|
|
76
134
|
const client = useConnectorClient();
|
|
77
|
-
const {
|
|
135
|
+
const {
|
|
136
|
+
CN_ConnectButton,
|
|
137
|
+
selectedAccount,
|
|
138
|
+
walletIcon,
|
|
139
|
+
walletName,
|
|
140
|
+
theme,
|
|
141
|
+
allowNetworkSwitch,
|
|
142
|
+
showSolBalance,
|
|
143
|
+
showDefaultToken
|
|
144
|
+
} = props;
|
|
78
145
|
const [view, setView] = useState2("wallet");
|
|
79
146
|
const [copied, setCopied] = useState2(false);
|
|
80
|
-
const
|
|
147
|
+
const fetchingSolBalance = useRef(false);
|
|
81
148
|
const [isFetchingBalance, setIsFetchingBalance] = useState2(false);
|
|
149
|
+
const fetchingDefaultToken = useRef(false);
|
|
150
|
+
const [isFetchingDefaultTokenBalance, setIsFetchingDefaultTokenBalance] = useState2(false);
|
|
82
151
|
const [solBalance, setSolBalance] = useState2(null);
|
|
152
|
+
const [defaultTokenBalance, setDefaultTokenBalance] = useState2(null);
|
|
83
153
|
const shortAddress = `${selectedAccount.slice(0, 4)}...${selectedAccount.slice(-4)}`;
|
|
84
154
|
async function handleCopy() {
|
|
85
155
|
try {
|
|
@@ -92,29 +162,36 @@ function WalletDropdown(props) {
|
|
|
92
162
|
}
|
|
93
163
|
}
|
|
94
164
|
async function fetchSolBalance() {
|
|
95
|
-
if (!client ||
|
|
165
|
+
if (!client || fetchingSolBalance.current) return;
|
|
96
166
|
setIsFetchingBalance(true);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
setIsFetchingBalance(false);
|
|
110
|
-
fetching.current = false;
|
|
167
|
+
fetchingSolBalance.current = true;
|
|
168
|
+
const solBalance2 = await getSolBalance(client, selectedAccount);
|
|
169
|
+
setSolBalance(solBalance2);
|
|
170
|
+
setIsFetchingBalance(false);
|
|
171
|
+
fetchingSolBalance.current = false;
|
|
172
|
+
}
|
|
173
|
+
async function fetchDefaultTokenBalance() {
|
|
174
|
+
if (!showDefaultToken || !showDefaultToken.address || !client || fetchingDefaultToken.current) return;
|
|
175
|
+
const isValidAddress = isAddress(showDefaultToken.address);
|
|
176
|
+
if (!isValidAddress) {
|
|
177
|
+
console.error("Invalid default token address:", showDefaultToken);
|
|
178
|
+
return;
|
|
111
179
|
}
|
|
180
|
+
setIsFetchingDefaultTokenBalance(true);
|
|
181
|
+
fetchingDefaultToken.current = true;
|
|
182
|
+
const tokenBalance = await getTokenBalance(client, selectedAccount, showDefaultToken.address);
|
|
183
|
+
setDefaultTokenBalance(tokenBalance);
|
|
184
|
+
setIsFetchingDefaultTokenBalance(false);
|
|
185
|
+
fetchingDefaultToken.current = false;
|
|
112
186
|
}
|
|
113
187
|
useEffect(() => {
|
|
114
188
|
if (showSolBalance && selectedAccount && client) {
|
|
115
189
|
fetchSolBalance();
|
|
116
190
|
}
|
|
117
|
-
|
|
191
|
+
if (showDefaultToken && selectedAccount && client) {
|
|
192
|
+
fetchDefaultTokenBalance();
|
|
193
|
+
}
|
|
194
|
+
}, [selectedAccount, client, showSolBalance, showDefaultToken]);
|
|
118
195
|
if (view === "wallet") {
|
|
119
196
|
return /* @__PURE__ */ jsxs(
|
|
120
197
|
motion.div,
|
|
@@ -208,7 +285,35 @@ function WalletDropdown(props) {
|
|
|
208
285
|
]
|
|
209
286
|
}
|
|
210
287
|
),
|
|
211
|
-
/* @__PURE__ */ jsx3("div", { className: styles3.balanceValue, children: isFetchingBalance ? /* @__PURE__ */ jsx3("div", { className: styles3.balanceLoading }) : solBalance !== null ? `${solBalance.toFixed(4)} SOL` : "-- SOL" })
|
|
288
|
+
/* @__PURE__ */ jsx3("div", { className: styles3.balanceValue, title: String(solBalance) || "0", children: isFetchingBalance ? /* @__PURE__ */ jsx3("div", { className: styles3.balanceLoading }) : solBalance !== null ? `${solBalance.toFixed(4)} SOL` : "-- SOL" })
|
|
289
|
+
] }),
|
|
290
|
+
showDefaultToken && /* @__PURE__ */ jsxs("div", { className: styles3.balanceSection, children: [
|
|
291
|
+
/* @__PURE__ */ jsxs(
|
|
292
|
+
"div",
|
|
293
|
+
{
|
|
294
|
+
className: styles3.balanceHeader,
|
|
295
|
+
children: [
|
|
296
|
+
/* @__PURE__ */ jsx3("span", { className: styles3.balanceLabel, children: "Balance" }),
|
|
297
|
+
/* @__PURE__ */ jsx3(
|
|
298
|
+
"button",
|
|
299
|
+
{
|
|
300
|
+
onClick: () => fetchDefaultTokenBalance(),
|
|
301
|
+
disabled: isFetchingDefaultTokenBalance,
|
|
302
|
+
title: "Refresh balance",
|
|
303
|
+
className: styles3.refreshButton,
|
|
304
|
+
"data-loading": isFetchingDefaultTokenBalance,
|
|
305
|
+
children: /* @__PURE__ */ jsx3(
|
|
306
|
+
RefreshCw,
|
|
307
|
+
{
|
|
308
|
+
className: styles3.refreshIcon
|
|
309
|
+
}
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
)
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
),
|
|
316
|
+
/* @__PURE__ */ jsx3("div", { className: styles3.balanceValue, title: String(defaultTokenBalance) || "0", children: isFetchingDefaultTokenBalance ? /* @__PURE__ */ jsx3("div", { className: styles3.balanceLoading }) : defaultTokenBalance !== null ? `${defaultTokenBalance.toFixed(4)} ${(showDefaultToken == null ? void 0 : showDefaultToken.symbol) || ""}` : `-- ${(showDefaultToken == null ? void 0 : showDefaultToken.symbol) || ""}` })
|
|
212
317
|
] }),
|
|
213
318
|
/* @__PURE__ */ jsx3(
|
|
214
319
|
DisconnectElement,
|
|
@@ -233,7 +338,6 @@ function WalletDropdown(props) {
|
|
|
233
338
|
);
|
|
234
339
|
}
|
|
235
340
|
if (view === "network") {
|
|
236
|
-
console.count("Network view rendered");
|
|
237
341
|
return /* @__PURE__ */ jsxs(
|
|
238
342
|
motion.div,
|
|
239
343
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/WalletDropdown/WalletDropdown.tsx","../src/components/shared/Avatar/Avatar.tsx","../src/components/shared/Avatar/index.ts","../src/components/shared/Button/Button.tsx","../src/components/shared/Button/index.ts","../src/components/WalletDropdown/index.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\r\nimport styles from './WalletDropdown.module.css'\r\nimport { motion } from 'motion/react';\r\nimport Avatar from '@shared/Avatar';\r\nimport { Check, ChevronLeft, Copy, Globe, LogOut, RefreshCw } from 'lucide-react';\r\nimport Button from '@shared/Button';\r\nimport { address, BalanceElement, ClusterElement, DisconnectElement, lamportsToSol, useCluster, useConnectorClient } from '@solana/connector';\r\nimport { createSolanaRpc } from '@solana/kit';\r\nimport { clsx } from 'clsx';\r\n\r\ninterface WalletDropdownProps {\r\n CN_ConnectButton?: string;\r\n selectedAccount: string;\r\n walletIcon?: string;\r\n walletName: string;\r\n theme?: 'light' | 'dark';\r\n\r\n allowNetworkSwitch?: boolean;\r\n showSolBalance?: boolean;\r\n}\r\n\r\ntype DropdownView = 'wallet' | 'network';\r\n\r\nconst networkColor: Record<string, string> = {\r\n 'solana:mainnet': '#00c950',\r\n 'solana:devnet': '#2b7fff',\r\n 'solana:testnet': '#f0b100',\r\n 'solana:localnet': '#ff3b3b',\r\n};\r\n\r\nexport function WalletDropdown(props: WalletDropdownProps) {\r\n const client = useConnectorClient();\r\n\r\n const { CN_ConnectButton, selectedAccount, walletIcon, walletName, theme, allowNetworkSwitch, showSolBalance } = props\r\n\r\n const [view, setView] = useState<DropdownView>('wallet');\r\n const [copied, setCopied] = useState(false);\r\n\r\n const fetching = useRef(false);\r\n const [isFetchingBalance, setIsFetchingBalance] = useState(false);\r\n const [solBalance, setSolBalance] = useState<number | null>(null);\r\n\r\n const shortAddress = `${selectedAccount.slice(0, 4)}...${selectedAccount.slice(-4)}`;\r\n\r\n async function handleCopy() {\r\n try {\r\n await navigator.clipboard.writeText(selectedAccount);\r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n } catch (error) {\r\n setCopied(false);\r\n console.error('Failed to copy to clipboard:', error);\r\n }\r\n }\r\n\r\n async function fetchSolBalance() {\r\n if (!client || fetching.current) return;\r\n setIsFetchingBalance(true);\r\n fetching.current = true;\r\n try {\r\n const rpcUrl = client.getRpcUrl();\r\n const pubkey = address(selectedAccount);\r\n if (!rpcUrl) throw new Error('No RPC endpoint configured');\r\n const rpc = createSolanaRpc(rpcUrl);\r\n const solLamports = (await rpc.getBalance(pubkey).send()).value || 0;\r\n const sol = lamportsToSol(solLamports);\r\n setSolBalance(sol);\r\n\r\n } catch (error) {\r\n setSolBalance(0);\r\n } finally {\r\n setIsFetchingBalance(false);\r\n fetching.current = false;\r\n }\r\n }\r\n\r\n useEffect(() => {\r\n if (showSolBalance && selectedAccount && client) {\r\n fetchSolBalance();\r\n }\r\n }, [selectedAccount, client, showSolBalance]);\r\n\r\n if (view === 'wallet') {\r\n return (\r\n <motion.div\r\n initial={{ opacity: 0 }}\r\n animate={{ opacity: 1 }}\r\n exit={{ opacity: 0 }}\r\n transition={{ duration: 0.2 }}\r\n className={clsx(styles.WalletDropdown, CN_ConnectButton)}\r\n data-theme={theme}\r\n >\r\n {/* Header with Avatar and Address */}\r\n <div className={styles.Header}>\r\n <div className={styles.addressAndAvatar}>\r\n <Avatar\r\n width={48}\r\n height={48}\r\n src={walletIcon}\r\n alt={walletName}\r\n />\r\n <div className={styles.address}>\r\n <span className={styles.shortAddress}>{shortAddress}</span>\r\n <span className={styles.walletName}>{walletName}</span>\r\n </div>\r\n </div>\r\n\r\n <div className={styles.actions}>\r\n <Button\r\n type=\"button\"\r\n onClick={handleCopy}\r\n variant=\"outline\"\r\n size=\"icon\"\r\n className=\"rounded-full\"\r\n title={copied ? 'Copied!' : 'Copy address'}\r\n >\r\n {copied ?\r\n <Check className={styles.checkIcon} /> :\r\n <Copy />\r\n }\r\n </Button>\r\n\r\n {/* Network Selector Globe Button */}\r\n {allowNetworkSwitch && (\r\n <ClusterElement\r\n render={({ cluster }) => (\r\n <Button\r\n type=\"button\"\r\n variant=\"outline\"\r\n size=\"icon\"\r\n onClick={() => setView('network')}\r\n title={`Network: ${cluster?.label || 'Unknown'}`}\r\n >\r\n <Globe />\r\n <span\r\n className={styles.networkIndicator}\r\n style={{ background: networkColor[cluster?.id || 'solana:mainnet'] }}\r\n />\r\n </Button>\r\n )}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n\r\n {showSolBalance && (\r\n <div className={styles.balanceSection}>\r\n <div\r\n className={styles.balanceHeader}\r\n >\r\n <span className={styles.balanceLabel}>Balance</span>\r\n <button\r\n onClick={() => fetchSolBalance()}\r\n disabled={isFetchingBalance}\r\n title=\"Refresh balance\"\r\n className={styles.refreshButton}\r\n data-loading={isFetchingBalance}\r\n >\r\n <RefreshCw\r\n className={styles.refreshIcon}\r\n />\r\n </button>\r\n </div>\r\n <div className={styles.balanceValue}>\r\n {isFetchingBalance ? (\r\n <div className={styles.balanceLoading} />\r\n ) : solBalance !== null ? (\r\n `${solBalance.toFixed(4)} SOL`\r\n ) : (\r\n '-- SOL'\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n <DisconnectElement\r\n render={({ disconnect, disconnecting }) => (\r\n <Button\r\n variant=\"default\"\r\n className={styles.disconnectButton}\r\n onClick={disconnect}\r\n disabled={disconnecting}\r\n >\r\n <LogOut className={styles.disconnectIcon} />\r\n {disconnecting ? 'Disconnecting...' : 'Disconnect'}\r\n </Button>\r\n )}\r\n />\r\n </motion.div>\r\n )\r\n }\r\n\r\n //network switch view\r\n if (view === 'network') {\r\n console.count('Network view rendered');\r\n return (\r\n <motion.div\r\n initial={{ opacity: 0 }}\r\n animate={{ opacity: 1 }}\r\n exit={{ opacity: 0 }}\r\n transition={{ duration: 0.2 }}\r\n className={clsx(styles.WalletDropdown, CN_ConnectButton)}\r\n data-theme={theme}\r\n >\r\n {/* Header */}\r\n <div className={styles.NetworkHeader}>\r\n <Button\r\n type=\"button\"\r\n variant=\"outline\"\r\n size=\"icon\"\r\n onClick={() => setView('wallet')}\r\n title={`Network: Back to Wallet`}\r\n className={styles.backButton}\r\n >\r\n <ChevronLeft />\r\n </Button>\r\n <span>Network Settings</span>\r\n </div>\r\n\r\n {/* Network Options */}\r\n <ClusterElement\r\n render={({ cluster, clusters, setCluster }) => {\r\n const currentClusterId = (cluster as { id?: string })?.id || 'solana:mainnet';\r\n return (\r\n <div className={styles.networkOptions}>\r\n {clusters.map((network, index) => {\r\n const isSelected = currentClusterId === network.id;\r\n return (\r\n <div\r\n key={network.id}\r\n role=\"button\"\r\n tabIndex={0}\r\n onClick={() => setCluster(network.id)}\r\n onKeyDown={e => {\r\n if (e.key === 'Enter' || e.key === ' ') {\r\n e.preventDefault();\r\n setCluster(network.id);\r\n }\r\n }}\r\n className={styles.networkButton}\r\n >\r\n <div className={styles.networkName}>\r\n <span\r\n className={styles.networkColor}\r\n style={{ background: networkColor[network.id] }}\r\n />\r\n <span className={styles.networkLabel}>{network.label}</span>\r\n </div>\r\n <div className={styles.checkMark} data-selected={isSelected}>\r\n {isSelected && <Check />}\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n );\r\n }}\r\n />\r\n </motion.div>\r\n )\r\n }\r\n}\r\n\r\nexport default WalletDropdown","import { useState } from 'react';\r\nimport styles from './Avatar.module.css';\r\nimport { Wallet } from 'lucide-react';\r\ninterface AvatarProps {\r\n height?: number | string;\r\n width?: number | string;\r\n src?: string;\r\n alt?: string;\r\n theme?: 'light' | 'dark';\r\n}\r\nexport function Avatar({\r\n height,\r\n width,\r\n src,\r\n alt,\r\n theme = 'light',\r\n}: AvatarProps) {\r\n const [hasError, setHasError] = useState(false);\r\n return (\r\n <div className={styles.avatar} data-theme={theme}>\r\n {src && !hasError ? (\r\n <img\r\n height={height}\r\n width={width}\r\n src={src}\r\n alt={alt || \"Avatar\"}\r\n onError={() => setHasError(true)}\r\n />\r\n ) : (\r\n <div className={styles.fallback} style={{ height, width }}>\r\n <Wallet />\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { Avatar } from './Avatar';\r\n\r\nexport default Avatar;","'use client';\r\n\r\nimport * as React from 'react';\r\nimport { Button as BaseButton } from '@base-ui/react/button';\r\nimport styles from './Button.module.css';\r\n\r\n// 1. Define Types\r\ntype ButtonVariant = 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';\r\ntype ButtonSize = 'default' | 'sm' | 'lg' | 'icon';\r\n\r\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n variant?: ButtonVariant;\r\n size?: ButtonSize;\r\n}\r\n\r\n// 2. The Component\r\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\r\n ({ className, variant = 'default', size = 'default', ...props }, ref) => {\r\n return (\r\n <BaseButton\r\n ref={ref}\r\n\r\n className={`${styles.button} ${className || ''}`}\r\n data-variant={variant}\r\n data-size={size}\r\n\r\n {...props}\r\n />\r\n );\r\n }\r\n);\r\nButton.displayName = 'Button';\r\n\r\nexport default Button;","import Button from \"./Button\";\r\n\r\nexport default Button;","import WalletDropdown from './WalletDropdown';\r\n\r\n\r\nexport default WalletDropdown"],"mappings":"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","names":["useState","styles","styles","jsx","Button_default","jsx","useState","styles","Button_default","WalletDropdown_default"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/WalletDropdown/WalletDropdown.tsx","../src/components/shared/Avatar/Avatar.tsx","../src/components/shared/Avatar/index.ts","../src/components/shared/Button/Button.tsx","../src/components/shared/Button/index.ts","../src/utils/fetchBalance.tsx","../src/components/WalletDropdown/index.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\nimport { createSolanaRpc, isAddress } from '@solana/kit';\nimport { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';\nimport { TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022';\nimport styles from './WalletDropdown.module.css'\nimport { motion } from 'motion/react';\nimport Avatar from '@shared/Avatar';\nimport { Check, ChevronLeft, Copy, Globe, LogOut, RefreshCw } from 'lucide-react';\nimport Button from '@shared/Button';\nimport { address, ClusterElement, DisconnectElement, lamportsToSol, useConnectorClient } from '@solana/connector';\nimport { clsx } from 'clsx';\nimport { getSolBalance, getTokenBalance } from 'src/utils/fetchBalance';\n\ninterface WalletDropdownProps {\n CN_ConnectButton?: string;\n selectedAccount: string;\n walletIcon?: string;\n walletName: string;\n theme?: 'light' | 'dark';\n\n allowNetworkSwitch?: boolean;\n showSolBalance?: boolean;\n showDefaultToken?: {\n address: string;\n symbol: string;\n }\n}\n\ntype DropdownView = 'wallet' | 'network';\n\nconst networkColor: Record<string, string> = {\n 'solana:mainnet': '#00c950',\n 'solana:devnet': '#2b7fff',\n 'solana:testnet': '#f0b100',\n 'solana:localnet': '#ff3b3b',\n};\n\nexport function WalletDropdown(props: WalletDropdownProps) {\n const client = useConnectorClient();\n\n const { CN_ConnectButton,\n selectedAccount,\n walletIcon,\n walletName,\n theme,\n allowNetworkSwitch,\n showSolBalance,\n showDefaultToken\n } = props\n\n const [view, setView] = useState<DropdownView>('wallet');\n const [copied, setCopied] = useState(false);\n\n const fetchingSolBalance = useRef(false);\n const [isFetchingBalance, setIsFetchingBalance] = useState(false);\n\n const fetchingDefaultToken = useRef(false);\n const [isFetchingDefaultTokenBalance, setIsFetchingDefaultTokenBalance] = useState(false);\n\n const [solBalance, setSolBalance] = useState<number | null>(null);\n const [defaultTokenBalance, setDefaultTokenBalance] = useState<number | null>(null);\n\n const shortAddress = `${selectedAccount.slice(0, 4)}...${selectedAccount.slice(-4)}`;\n\n async function handleCopy() {\n try {\n await navigator.clipboard.writeText(selectedAccount);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (error) {\n setCopied(false);\n console.error('Failed to copy to clipboard:', error);\n }\n }\n\n async function fetchSolBalance() {\n if (!client || fetchingSolBalance.current) return;\n setIsFetchingBalance(true);\n fetchingSolBalance.current = true;\n\n const solBalance = await getSolBalance(client, selectedAccount);\n setSolBalance(solBalance);\n\n setIsFetchingBalance(false);\n fetchingSolBalance.current = false;\n }\n\n async function fetchDefaultTokenBalance() {\n if (!showDefaultToken || !showDefaultToken.address || !client || fetchingDefaultToken.current) return;\n\n const isValidAddress = isAddress(showDefaultToken.address);\n if (!isValidAddress) {\n console.error('Invalid default token address:', showDefaultToken);\n return\n }\n\n setIsFetchingDefaultTokenBalance(true);\n fetchingDefaultToken.current = true;\n\n const tokenBalance = await getTokenBalance(client, selectedAccount, showDefaultToken.address);\n setDefaultTokenBalance(tokenBalance);\n\n setIsFetchingDefaultTokenBalance(false);\n fetchingDefaultToken.current = false;\n }\n\n useEffect(() => {\n if (showSolBalance && selectedAccount && client) {\n fetchSolBalance();\n }\n if (showDefaultToken && selectedAccount && client) {\n fetchDefaultTokenBalance();\n }\n }, [selectedAccount, client, showSolBalance, showDefaultToken]);\n\n if (view === 'wallet') {\n return (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.2 }}\n className={clsx(styles.WalletDropdown, CN_ConnectButton)}\n data-theme={theme}\n >\n {/* Header with Avatar and Address */}\n <div className={styles.Header}>\n <div className={styles.addressAndAvatar}>\n <Avatar\n width={48}\n height={48}\n src={walletIcon}\n alt={walletName}\n />\n <div className={styles.address}>\n <span className={styles.shortAddress}>{shortAddress}</span>\n <span className={styles.walletName}>{walletName}</span>\n </div>\n </div>\n\n <div className={styles.actions}>\n <Button\n type=\"button\"\n onClick={handleCopy}\n variant=\"outline\"\n size=\"icon\"\n className=\"rounded-full\"\n title={copied ? 'Copied!' : 'Copy address'}\n >\n {copied ?\n <Check className={styles.checkIcon} /> :\n <Copy />\n }\n </Button>\n\n {/* Network Selector Globe Button */}\n {allowNetworkSwitch && (\n <ClusterElement\n render={({ cluster }) => (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon\"\n onClick={() => setView('network')}\n title={`Network: ${cluster?.label || 'Unknown'}`}\n >\n <Globe />\n <span\n className={styles.networkIndicator}\n style={{ background: networkColor[cluster?.id || 'solana:mainnet'] }}\n />\n </Button>\n )}\n />\n )}\n </div>\n </div>\n\n {showSolBalance && (\n <div className={styles.balanceSection}>\n <div\n className={styles.balanceHeader}\n >\n <span className={styles.balanceLabel}>Balance</span>\n <button\n onClick={() => fetchSolBalance()}\n disabled={isFetchingBalance}\n title=\"Refresh balance\"\n className={styles.refreshButton}\n data-loading={isFetchingBalance}\n >\n <RefreshCw\n className={styles.refreshIcon}\n />\n </button>\n </div>\n <div className={styles.balanceValue} title={String(solBalance) || \"0\"}>\n {isFetchingBalance ? (\n <div className={styles.balanceLoading} />\n ) : solBalance !== null ? (\n `${solBalance.toFixed(4)} SOL`\n ) : (\n '-- SOL'\n )}\n </div>\n </div>\n )}\n\n {showDefaultToken && (\n <div className={styles.balanceSection}>\n <div\n className={styles.balanceHeader}\n >\n <span className={styles.balanceLabel}>Balance</span>\n <button\n onClick={() => fetchDefaultTokenBalance()}\n disabled={isFetchingDefaultTokenBalance}\n title=\"Refresh balance\"\n className={styles.refreshButton}\n data-loading={isFetchingDefaultTokenBalance}\n >\n <RefreshCw\n className={styles.refreshIcon}\n />\n </button>\n </div>\n <div className={styles.balanceValue} title={String(defaultTokenBalance) || \"0\"}>\n {isFetchingDefaultTokenBalance ? (\n <div className={styles.balanceLoading} />\n ) : defaultTokenBalance !== null ? (\n `${defaultTokenBalance.toFixed(4)} ${showDefaultToken?.symbol || ''}`\n ) : (\n `-- ${showDefaultToken?.symbol || ''}`\n )}\n </div>\n </div>\n )}\n\n <DisconnectElement\n render={({ disconnect, disconnecting }) => (\n <Button\n variant=\"default\"\n className={styles.disconnectButton}\n onClick={disconnect}\n disabled={disconnecting}\n >\n <LogOut className={styles.disconnectIcon} />\n {disconnecting ? 'Disconnecting...' : 'Disconnect'}\n </Button>\n )}\n />\n </motion.div>\n )\n }\n\n //network switch view\n if (view === 'network') {\n return (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.2 }}\n className={clsx(styles.WalletDropdown, CN_ConnectButton)}\n data-theme={theme}\n >\n {/* Header */}\n <div className={styles.NetworkHeader}>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon\"\n onClick={() => setView('wallet')}\n title={`Network: Back to Wallet`}\n className={styles.backButton}\n >\n <ChevronLeft />\n </Button>\n <span>Network Settings</span>\n </div>\n\n {/* Network Options */}\n <ClusterElement\n render={({ cluster, clusters, setCluster }) => {\n const currentClusterId = (cluster as { id?: string })?.id || 'solana:mainnet';\n return (\n <div className={styles.networkOptions}>\n {clusters.map((network, index) => {\n const isSelected = currentClusterId === network.id;\n return (\n <div\n key={network.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => setCluster(network.id)}\n onKeyDown={e => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setCluster(network.id);\n }\n }}\n className={styles.networkButton}\n >\n <div className={styles.networkName}>\n <span\n className={styles.networkColor}\n style={{ background: networkColor[network.id] }}\n />\n <span className={styles.networkLabel}>{network.label}</span>\n </div>\n <div className={styles.checkMark} data-selected={isSelected}>\n {isSelected && <Check />}\n </div>\n </div>\n );\n })}\n </div>\n );\n }}\n />\n </motion.div>\n )\n }\n}\n\nexport default WalletDropdown","import { useState } from 'react';\nimport styles from './Avatar.module.css';\nimport { Wallet } from 'lucide-react';\ninterface AvatarProps {\n height?: number | string;\n width?: number | string;\n src?: string;\n alt?: string;\n theme?: 'light' | 'dark';\n}\nexport function Avatar({\n height,\n width,\n src,\n alt,\n theme = 'light',\n}: AvatarProps) {\n const [hasError, setHasError] = useState(false);\n return (\n <div className={styles.avatar} data-theme={theme}>\n {src && !hasError ? (\n <img\n height={height}\n width={width}\n src={src}\n alt={alt || \"Avatar\"}\n onError={() => setHasError(true)}\n />\n ) : (\n <div className={styles.fallback} style={{ height, width }}>\n <Wallet />\n </div>\n )}\n </div>\n );\n}\n","import { Avatar } from './Avatar';\n\nexport default Avatar;","'use client';\n\nimport * as React from 'react';\nimport { Button as BaseButton } from '@base-ui/react/button';\nimport styles from './Button.module.css';\n\n// 1. Define Types\ntype ButtonVariant = 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';\ntype ButtonSize = 'default' | 'sm' | 'lg' | 'icon';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n}\n\n// 2. The Component\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'default', size = 'default', ...props }, ref) => {\n return (\n <BaseButton\n ref={ref}\n\n className={`${styles.button} ${className || ''}`}\n data-variant={variant}\n data-size={size}\n\n {...props}\n />\n );\n }\n);\nButton.displayName = 'Button';\n\nexport default Button;","import Button from \"./Button\";\n\nexport default Button;","import { findAssociatedTokenPda } from \"@solana-program/token\";\nimport { address, ConnectorClient, lamportsToSol } from \"@solana/connector\";\nimport { createSolanaRpc } from \"@solana/kit\";\n\nexport async function getSolBalance(\n client: ConnectorClient,\n pubkey: string\n): Promise<number> {\n let balance = 0;\n try {\n const rpcUrl = client.getRpcUrl();\n if (!rpcUrl) {\n console.error(\"RPC URL is not available from the ConnectorClient.\");\n return 0;\n }\n const pubkeyAddress = address(pubkey);\n const rpc = createSolanaRpc(rpcUrl);\n const balanceResponse = await rpc.getBalance(pubkeyAddress).send();\n balance = lamportsToSol(balanceResponse.value);\n } catch (error) {\n console.error(\"Error fetching SOL balance:\", error);\n } finally {\n return balance;\n }\n}\n\nexport async function getTokenBalance(\n client: ConnectorClient,\n pubkey: string,\n mintAddress: string\n): Promise<number> {\n let balance = 0;\n try {\n const rpcUrl = client.getRpcUrl();\n if (!rpcUrl) {\n console.error(\"RPC URL is not available from the ConnectorClient.\");\n return 0;\n }\n const pubkeyAddress = address(pubkey);\n const mintPubkey = address(mintAddress);\n const rpc = createSolanaRpc(rpcUrl);\n\n const mintInfo = await rpc.getAccountInfo(mintPubkey).send();\n const ownerProgram = mintInfo.value?.owner;\n if (!ownerProgram) {\n throw new Error('Failed to fetch mint account info');\n }\n const tokenProgram = address(ownerProgram)\n const [tokenPDA] = await findAssociatedTokenPda({\n mint: mintPubkey,\n owner: pubkeyAddress,\n tokenProgram: tokenProgram\n });\n const tokenBalance = await rpc.getTokenAccountBalance(tokenPDA).send();\n\n if (tokenBalance.value) {\n balance = parseFloat(tokenBalance.value.uiAmountString);\n }\n } catch (error) {\n console.error(\"Error fetching token balance:\", error);\n } finally {\n return balance;\n }\n}","import WalletDropdown from './WalletDropdown';\n\n\nexport default WalletDropdown"],"mappings":"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","names":["useState","styles","styles","jsx","Button_default","jsx","useState","solBalance","styles","Button_default","WalletDropdown_default"]}
|