@solana/connector 0.1.3 → 0.1.5

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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +685 -1071
  3. package/dist/chunk-3STZXVXD.mjs +2185 -0
  4. package/dist/chunk-3STZXVXD.mjs.map +1 -0
  5. package/dist/chunk-I64FD2EH.js +312 -0
  6. package/dist/chunk-I64FD2EH.js.map +1 -0
  7. package/dist/{chunk-TIW3EQPC.js → chunk-JUZVCBAI.js} +127 -104
  8. package/dist/chunk-JUZVCBAI.js.map +1 -0
  9. package/dist/{chunk-7CKCRY25.js → chunk-NQXK7PGX.js} +75 -79
  10. package/dist/chunk-NQXK7PGX.js.map +1 -0
  11. package/dist/{chunk-HPENTIPE.mjs → chunk-QKVL45F6.mjs} +57 -57
  12. package/dist/chunk-QKVL45F6.mjs.map +1 -0
  13. package/dist/chunk-QL3IT3TS.mjs +299 -0
  14. package/dist/chunk-QL3IT3TS.mjs.map +1 -0
  15. package/dist/chunk-ULUYX23Q.js +2213 -0
  16. package/dist/chunk-ULUYX23Q.js.map +1 -0
  17. package/dist/{chunk-TKJSKXSA.mjs → chunk-VMSZJPR5.mjs} +42 -20
  18. package/dist/chunk-VMSZJPR5.mjs.map +1 -0
  19. package/dist/compat.d.mts +4 -2
  20. package/dist/compat.d.ts +4 -2
  21. package/dist/compat.js +3 -3
  22. package/dist/compat.mjs +1 -1
  23. package/dist/headless.d.mts +146 -18
  24. package/dist/headless.d.ts +146 -18
  25. package/dist/headless.js +144 -111
  26. package/dist/headless.mjs +3 -2
  27. package/dist/index.d.mts +6 -5
  28. package/dist/index.d.ts +6 -5
  29. package/dist/index.js +207 -126
  30. package/dist/index.mjs +4 -3
  31. package/dist/react.d.mts +707 -67
  32. package/dist/react.d.ts +707 -67
  33. package/dist/react.js +64 -16
  34. package/dist/react.mjs +2 -2
  35. package/dist/{transaction-signer-D3csM_Mf.d.mts → transaction-signer-D9d8nxwb.d.mts} +3 -1
  36. package/dist/{transaction-signer-D3csM_Mf.d.ts → transaction-signer-D9d8nxwb.d.ts} +3 -1
  37. package/dist/{wallet-standard-shim-Cg0GVGwu.d.mts → wallet-standard-shim--YcrQNRt.d.ts} +216 -6
  38. package/dist/{wallet-standard-shim-C1tisl9S.d.ts → wallet-standard-shim-Dx7H8Ctf.d.mts} +216 -6
  39. package/package.json +16 -12
  40. package/dist/chunk-5ZUVZZWU.mjs +0 -180
  41. package/dist/chunk-5ZUVZZWU.mjs.map +0 -1
  42. package/dist/chunk-7CKCRY25.js.map +0 -1
  43. package/dist/chunk-FTD7F7CS.js +0 -314
  44. package/dist/chunk-FTD7F7CS.js.map +0 -1
  45. package/dist/chunk-HPENTIPE.mjs.map +0 -1
  46. package/dist/chunk-MPZFJEJK.mjs +0 -298
  47. package/dist/chunk-MPZFJEJK.mjs.map +0 -1
  48. package/dist/chunk-SMUUAKC3.js +0 -186
  49. package/dist/chunk-SMUUAKC3.js.map +0 -1
  50. package/dist/chunk-TIW3EQPC.js.map +0 -1
  51. package/dist/chunk-TKJSKXSA.mjs.map +0 -1
@@ -0,0 +1,2213 @@
1
+ 'use strict';
2
+
3
+ var chunkJUZVCBAI_js = require('./chunk-JUZVCBAI.js');
4
+ var chunkI64FD2EH_js = require('./chunk-I64FD2EH.js');
5
+ var React = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var addresses = require('@solana/addresses');
8
+ var keys = require('@solana/keys');
9
+
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
+
12
+ var React__default = /*#__PURE__*/_interopDefault(React);
13
+
14
+ var logger = chunkI64FD2EH_js.createLogger("ConnectorProvider");
15
+ chunkJUZVCBAI_js.installPolyfills();
16
+ var ConnectorContext = React.createContext(null);
17
+ ConnectorContext.displayName = "ConnectorContext";
18
+ function ConnectorProviderInternal({
19
+ children,
20
+ config,
21
+ mobile
22
+ }) {
23
+ let clientRef = React.useRef(null), client = React__default.default.useCallback(() => {
24
+ if (!clientRef.current)
25
+ try {
26
+ clientRef.current = new chunkJUZVCBAI_js.ConnectorClient(config), typeof window < "u" && (window.__connectorClient = clientRef.current), config?.debug && logger.info("Client initialized successfully");
27
+ } catch (error) {
28
+ let err = error;
29
+ logger.error("Failed to initialize client", { error: err });
30
+ let extendedConfig = config;
31
+ return extendedConfig?.errorBoundary?.onError && extendedConfig.errorBoundary.onError(err, {
32
+ componentStack: "client-initialization",
33
+ digest: `constructor-${(/* @__PURE__ */ new Date()).toISOString()}`
34
+ }), null;
35
+ }
36
+ return clientRef.current;
37
+ }, [config])();
38
+ return React__default.default.useEffect(() => {
39
+ let currentClient = clientRef.current;
40
+ if (currentClient) {
41
+ let privateClient = currentClient;
42
+ privateClient.initialize && typeof privateClient.initialize == "function" && privateClient.initialize();
43
+ }
44
+ return () => {
45
+ typeof window < "u" && (window.__connectorClient = void 0), currentClient && typeof currentClient.destroy == "function" && currentClient.destroy();
46
+ };
47
+ }, []), React__default.default.useEffect(() => {
48
+ if (!mobile) return;
49
+ let cancelled = false;
50
+ return (async () => {
51
+ try {
52
+ let mod = await import('@solana-mobile/wallet-standard-mobile');
53
+ if (cancelled) return;
54
+ let {
55
+ registerMwa,
56
+ createDefaultAuthorizationCache,
57
+ createDefaultChainSelector,
58
+ createDefaultWalletNotFoundHandler
59
+ } = mod, defaultChains = [
60
+ "solana:mainnet",
61
+ "solana:devnet",
62
+ "solana:testnet"
63
+ ];
64
+ registerMwa({
65
+ appIdentity: mobile.appIdentity,
66
+ authorizationCache: mobile.authorizationCache ?? createDefaultAuthorizationCache(),
67
+ chains: mobile.chains ?? defaultChains,
68
+ chainSelector: mobile.chainSelector ?? createDefaultChainSelector(),
69
+ remoteHostAuthority: mobile.remoteHostAuthority,
70
+ onWalletNotFound: mobile.onWalletNotFound ?? createDefaultWalletNotFoundHandler()
71
+ });
72
+ } catch {
73
+ }
74
+ })(), () => {
75
+ cancelled = true;
76
+ };
77
+ }, [mobile]), /* @__PURE__ */ jsxRuntime.jsx(ConnectorContext.Provider, { value: client, children });
78
+ }
79
+ function ConnectorProvider({
80
+ children,
81
+ config,
82
+ mobile
83
+ }) {
84
+ let errorBoundaryConfig = config?.errorBoundary;
85
+ return errorBoundaryConfig?.enabled ? /* @__PURE__ */ jsxRuntime.jsx(
86
+ chunkJUZVCBAI_js.ConnectorErrorBoundary,
87
+ {
88
+ maxRetries: errorBoundaryConfig.maxRetries ?? 3,
89
+ onError: errorBoundaryConfig.onError,
90
+ fallback: errorBoundaryConfig.fallback,
91
+ children: /* @__PURE__ */ jsxRuntime.jsx(ConnectorProviderInternal, { config, mobile, children })
92
+ }
93
+ ) : /* @__PURE__ */ jsxRuntime.jsx(ConnectorProviderInternal, { config, mobile, children });
94
+ }
95
+ function useConnector() {
96
+ let client = React.useContext(ConnectorContext);
97
+ if (!client)
98
+ throw new Error(
99
+ "useConnector must be used within ConnectorProvider. Wrap your app with <ConnectorProvider> or <UnifiedProvider> to use connector hooks."
100
+ );
101
+ let state = React.useSyncExternalStore(
102
+ React__default.default.useCallback((cb) => client.subscribe(cb), [client]),
103
+ React__default.default.useCallback(() => client.getSnapshot(), [client]),
104
+ React__default.default.useCallback(() => client.getSnapshot(), [client])
105
+ ), methods = React.useMemo(
106
+ () => ({
107
+ select: client.select.bind(client),
108
+ disconnect: client.disconnect.bind(client),
109
+ selectAccount: client.selectAccount.bind(client)
110
+ }),
111
+ [client]
112
+ );
113
+ return React.useMemo(
114
+ () => ({
115
+ ...state,
116
+ ...methods
117
+ }),
118
+ [state, methods]
119
+ );
120
+ }
121
+ function useConnectorClient() {
122
+ return React.useContext(ConnectorContext);
123
+ }
124
+ function UnifiedProvider({ children, config, connectorConfig, mobile, providers = [] }) {
125
+ let actualConnectorConfig = config?.connectorConfig ?? connectorConfig, actualMobile = config?.mobile ?? mobile, content = /* @__PURE__ */ jsxRuntime.jsx(ConnectorProvider, { config: actualConnectorConfig, mobile: actualMobile, children });
126
+ for (let i = providers.length - 1; i >= 0; i--) {
127
+ let { component: Provider, props = {} } = providers[i];
128
+ content = /* @__PURE__ */ jsxRuntime.jsx(Provider, { ...props, children: content });
129
+ }
130
+ return content;
131
+ }
132
+ function useCluster() {
133
+ let { cluster, clusters } = useConnector(), client = useConnectorClient();
134
+ if (!client)
135
+ throw new Error("useCluster must be used within ConnectorProvider");
136
+ let setCluster = React.useMemo(
137
+ () => async (id) => {
138
+ await client.setCluster(id);
139
+ },
140
+ [client]
141
+ );
142
+ return React.useMemo(() => {
143
+ let isMainnet = cluster ? chunkJUZVCBAI_js.isMainnetCluster(cluster) : false, isDevnet = cluster ? chunkJUZVCBAI_js.isDevnetCluster(cluster) : false, isTestnet = cluster ? chunkJUZVCBAI_js.isTestnetCluster(cluster) : false, isLocal = cluster ? chunkJUZVCBAI_js.isLocalCluster(cluster) : false, explorerUrl = cluster ? chunkJUZVCBAI_js.getClusterExplorerUrl(cluster) : "", type = cluster ? chunkJUZVCBAI_js.getClusterType(cluster) : null;
144
+ return {
145
+ cluster,
146
+ clusters,
147
+ setCluster,
148
+ isMainnet,
149
+ isDevnet,
150
+ isTestnet,
151
+ isLocal,
152
+ explorerUrl,
153
+ type
154
+ };
155
+ }, [cluster, clusters, setCluster]);
156
+ }
157
+ function useAccount() {
158
+ let { selectedAccount, accounts, connected, selectAccount } = useConnector(), [copied, setCopied] = React.useState(false), copyTimeoutRef = React__default.default.useRef(void 0), account = React.useMemo(
159
+ () => accounts.find((a) => a.address === selectedAccount) ?? null,
160
+ [accounts, selectedAccount]
161
+ ), formatted = React.useMemo(() => selectedAccount ? chunkJUZVCBAI_js.formatAddress(selectedAccount) : "", [selectedAccount]), copy = React.useCallback(async () => selectedAccount ? (copyTimeoutRef.current && clearTimeout(copyTimeoutRef.current), await chunkJUZVCBAI_js.copyAddressToClipboard(selectedAccount, {
162
+ onSuccess: () => {
163
+ setCopied(true), copyTimeoutRef.current = setTimeout(() => setCopied(false), 2e3);
164
+ }
165
+ })) : {
166
+ success: false,
167
+ error: "empty_value" /* EMPTY_VALUE */,
168
+ errorMessage: "No account selected"
169
+ }, [selectedAccount]);
170
+ return React__default.default.useEffect(() => () => {
171
+ copyTimeoutRef.current && clearTimeout(copyTimeoutRef.current);
172
+ }, []), React.useMemo(
173
+ () => ({
174
+ address: selectedAccount,
175
+ account,
176
+ connected,
177
+ formatted,
178
+ copy,
179
+ copied,
180
+ accounts,
181
+ selectAccount
182
+ }),
183
+ [selectedAccount, account, connected, formatted, copy, copied, accounts, selectAccount]
184
+ );
185
+ }
186
+ function useWalletInfo() {
187
+ let { selectedWallet, wallets, connected, connecting } = useConnector(), mappedWallets = React.useMemo(
188
+ () => wallets.map(
189
+ (walletInfo) => ({
190
+ name: walletInfo.wallet.name,
191
+ icon: walletInfo.wallet.icon,
192
+ installed: walletInfo.installed,
193
+ connectable: walletInfo.connectable
194
+ })
195
+ ),
196
+ [wallets]
197
+ ), selectedWalletInfo = React.useMemo(() => {
198
+ if (!selectedWallet)
199
+ return {
200
+ name: null,
201
+ icon: null,
202
+ installed: false,
203
+ connectable: false
204
+ };
205
+ let walletInfo = wallets.find((w) => w.wallet.name === selectedWallet.name);
206
+ return {
207
+ name: selectedWallet.name,
208
+ icon: selectedWallet.icon ?? null,
209
+ installed: walletInfo?.installed ?? false,
210
+ connectable: walletInfo?.connectable ?? false
211
+ };
212
+ }, [selectedWallet, wallets]);
213
+ return React.useMemo(
214
+ () => ({
215
+ ...selectedWalletInfo,
216
+ connected,
217
+ connecting,
218
+ wallets: mappedWallets
219
+ }),
220
+ [selectedWalletInfo, connected, connecting, mappedWallets]
221
+ );
222
+ }
223
+ function useTransactionSigner() {
224
+ let { selectedWallet, selectedAccount, accounts, cluster, connected } = useConnector(), client = useConnectorClient(), account = React.useMemo(
225
+ () => accounts.find((a) => a.address === selectedAccount)?.raw ?? null,
226
+ [accounts, selectedAccount]
227
+ ), signer = React.useMemo(() => !connected || !selectedWallet || !account ? null : chunkJUZVCBAI_js.createTransactionSigner({
228
+ wallet: selectedWallet,
229
+ account,
230
+ cluster: cluster ?? void 0,
231
+ eventEmitter: client ? {
232
+ emit: (event) => {
233
+ client.emitEvent(event);
234
+ }
235
+ } : void 0
236
+ }), [connected, selectedWallet, account, cluster, client]), capabilities = React.useMemo(
237
+ () => signer?.getCapabilities() ?? {
238
+ canSign: false,
239
+ canSend: false,
240
+ canSignMessage: false,
241
+ supportsBatchSigning: false
242
+ },
243
+ [signer]
244
+ );
245
+ return {
246
+ signer,
247
+ ready: !!signer,
248
+ address: selectedAccount,
249
+ capabilities
250
+ };
251
+ }
252
+ function useKitTransactionSigner() {
253
+ let { signer: connectorSigner, ready } = useTransactionSigner();
254
+ return {
255
+ signer: React.useMemo(() => connectorSigner ? chunkJUZVCBAI_js.createKitTransactionSigner(connectorSigner) : null, [connectorSigner]),
256
+ ready
257
+ };
258
+ }
259
+ var useGillTransactionSigner = useKitTransactionSigner;
260
+ var logger2 = chunkI64FD2EH_js.createLogger("useSolanaClient");
261
+ function useSolanaClient() {
262
+ let { type } = useCluster(), connectorClient = useConnectorClient(), client = React.useMemo(() => {
263
+ if (!type || !connectorClient) return null;
264
+ try {
265
+ let rpcUrl = connectorClient.getRpcUrl();
266
+ return rpcUrl ? chunkI64FD2EH_js.createSolanaClient({
267
+ urlOrMoniker: rpcUrl
268
+ }) : type !== "custom" ? chunkI64FD2EH_js.createSolanaClient({
269
+ urlOrMoniker: type
270
+ }) : null;
271
+ } catch (error) {
272
+ return logger2.error("Failed to create Solana client", { error }), null;
273
+ }
274
+ }, [type, connectorClient]);
275
+ return React.useMemo(
276
+ () => ({
277
+ client,
278
+ ready: !!client,
279
+ clusterType: type
280
+ }),
281
+ [client, type]
282
+ );
283
+ }
284
+ var useGillSolanaClient = useSolanaClient;
285
+ function useTransactionPreparer() {
286
+ let { client, ready } = useSolanaClient(), prepare = React.useCallback(
287
+ async (transaction, options = {}) => {
288
+ if (!client)
289
+ throw new chunkJUZVCBAI_js.NetworkError("RPC_ERROR", "Solana client not available. Cannot prepare transaction.");
290
+ return chunkI64FD2EH_js.prepareTransaction({
291
+ transaction,
292
+ rpc: client.rpc,
293
+ computeUnitLimitMultiplier: options.computeUnitLimitMultiplier,
294
+ computeUnitLimitReset: options.computeUnitLimitReset,
295
+ blockhashReset: options.blockhashReset
296
+ });
297
+ },
298
+ [client]
299
+ );
300
+ return React.useMemo(
301
+ () => ({
302
+ prepare,
303
+ ready
304
+ }),
305
+ [prepare, ready]
306
+ );
307
+ }
308
+ var LAMPORTS_PER_SOL2 = 1000000000n;
309
+ function formatSol(lamports, decimals = 4) {
310
+ return (Number(lamports) / Number(LAMPORTS_PER_SOL2)).toLocaleString(void 0, {
311
+ minimumFractionDigits: 0,
312
+ maximumFractionDigits: decimals
313
+ }) + " SOL";
314
+ }
315
+ function useBalance() {
316
+ let { address, connected } = useAccount(); useCluster(); let client = useSolanaClient(), [lamports, setLamports] = React.useState(0n), [tokens, setTokens] = React.useState([]), [isLoading, setIsLoading] = React.useState(false), [error, setError] = React.useState(null), [lastUpdated, setLastUpdated] = React.useState(null), hasDataRef = React.useRef(false), rpcClient = client?.client ?? null, fetchBalance = React.useCallback(async () => {
317
+ if (!connected || !address || !rpcClient) {
318
+ setLamports(0n), setTokens([]), hasDataRef.current = false;
319
+ return;
320
+ }
321
+ setIsLoading(true), setError(null);
322
+ try {
323
+ let rpc = rpcClient.rpc, walletAddress = addresses.address(address), balanceResult = await rpc.getBalance(walletAddress).send();
324
+ setLamports(balanceResult.value);
325
+ try {
326
+ let tokenProgramId = addresses.address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"), tokenAccountsResult = await rpc.getTokenAccountsByOwner(walletAddress, { programId: tokenProgramId }, { encoding: "jsonParsed" }).send(), tokenBalances = [];
327
+ for (let account of tokenAccountsResult.value) {
328
+ let parsed = account.account.data;
329
+ if (parsed?.parsed?.info) {
330
+ let info = parsed.parsed.info, amount = BigInt(info.tokenAmount?.amount || "0"), decimals = info.tokenAmount?.decimals || 0, formatted = (Number(amount) / Math.pow(10, decimals)).toLocaleString(void 0, {
331
+ minimumFractionDigits: 0,
332
+ maximumFractionDigits: Math.min(decimals, 6)
333
+ });
334
+ amount > 0n && tokenBalances.push({
335
+ mint: info.mint,
336
+ amount,
337
+ decimals,
338
+ formatted
339
+ });
340
+ }
341
+ }
342
+ setTokens(tokenBalances);
343
+ } catch (tokenError) {
344
+ console.warn("Failed to fetch token balances:", tokenError), setTokens([]);
345
+ }
346
+ hasDataRef.current = true, setLastUpdated(/* @__PURE__ */ new Date());
347
+ } catch (err) {
348
+ hasDataRef.current || (setError(err), console.error("Failed to fetch balance:", err));
349
+ } finally {
350
+ setIsLoading(false);
351
+ }
352
+ }, [connected, address, rpcClient]);
353
+ React.useEffect(() => {
354
+ fetchBalance();
355
+ }, [fetchBalance]), React.useEffect(() => {
356
+ if (!connected) return;
357
+ let interval = setInterval(fetchBalance, 3e4);
358
+ return () => clearInterval(interval);
359
+ }, [connected, fetchBalance]);
360
+ let solBalance = React.useMemo(() => Number(lamports) / Number(LAMPORTS_PER_SOL2), [lamports]), formattedSol = React.useMemo(() => formatSol(lamports), [lamports]);
361
+ return React.useMemo(
362
+ () => ({
363
+ solBalance,
364
+ lamports,
365
+ formattedSol,
366
+ tokens,
367
+ isLoading,
368
+ error,
369
+ refetch: fetchBalance,
370
+ lastUpdated
371
+ }),
372
+ [solBalance, lamports, formattedSol, tokens, isLoading, error, fetchBalance, lastUpdated]
373
+ );
374
+ }
375
+ function formatDate(timestamp) {
376
+ if (!timestamp)
377
+ return { date: "Unknown", time: "" };
378
+ let date = new Date(timestamp * 1e3), diffDays = Math.floor(((/* @__PURE__ */ new Date()).getTime() - date.getTime()) / (1e3 * 60 * 60 * 24)), formattedDate;
379
+ diffDays === 0 ? formattedDate = "Today" : diffDays === 1 ? formattedDate = "Yesterday" : diffDays < 7 ? formattedDate = `${diffDays} days ago` : formattedDate = date.toLocaleDateString();
380
+ let formattedTime = date.toLocaleTimeString(void 0, {
381
+ hour: "2-digit",
382
+ minute: "2-digit"
383
+ });
384
+ return { date: formattedDate, time: formattedTime };
385
+ }
386
+ function isAccountKey(value) {
387
+ return typeof value == "object" && value !== null && "pubkey" in value && typeof value.pubkey == "string";
388
+ }
389
+ function isTransactionMeta(value) {
390
+ if (typeof value != "object" || value === null || !("preBalances" in value) || !("postBalances" in value))
391
+ return false;
392
+ let meta = value;
393
+ if (!Array.isArray(meta.preBalances) || !Array.isArray(meta.postBalances))
394
+ return false;
395
+ let isValidBalance = (b) => typeof b == "number" || typeof b == "bigint";
396
+ return meta.preBalances.every(isValidBalance) && meta.postBalances.every(isValidBalance);
397
+ }
398
+ function isTokenBalance(value) {
399
+ return typeof value == "object" && value !== null && "accountIndex" in value && "mint" in value && "uiTokenAmount" in value && typeof value.accountIndex == "number" && typeof value.mint == "string" && typeof value.uiTokenAmount == "object" && value.uiTokenAmount !== null;
400
+ }
401
+ function isUiTokenAmount(value) {
402
+ return typeof value == "object" && value !== null && "amount" in value && "decimals" in value && typeof value.amount == "string" && typeof value.decimals == "number";
403
+ }
404
+ function isTransactionWithMeta(value) {
405
+ return typeof value == "object" && value !== null && "meta" in value && "transaction" in value && value.meta !== null && typeof value.transaction == "object" && value.transaction !== null && "message" in value.transaction;
406
+ }
407
+ function isTransactionMessage(value) {
408
+ return typeof value == "object" && value !== null && "accountKeys" in value && Array.isArray(value.accountKeys);
409
+ }
410
+ function getAccountKeys(message) {
411
+ return Array.isArray(message.accountKeys) ? message.accountKeys.map((key) => typeof key == "string" ? key : isAccountKey(key) ? key.pubkey : "").filter(Boolean) : [];
412
+ }
413
+ function detectProgramIds(message, accountKeys) {
414
+ let programIds = /* @__PURE__ */ new Set();
415
+ if (!Array.isArray(message.instructions))
416
+ return programIds;
417
+ for (let instruction of message.instructions)
418
+ if (typeof instruction == "object" && instruction !== null) {
419
+ if (typeof instruction.programIdIndex == "number" && accountKeys[instruction.programIdIndex])
420
+ programIds.add(accountKeys[instruction.programIdIndex]);
421
+ else if (typeof instruction.programId == "string")
422
+ programIds.add(instruction.programId);
423
+ else if (instruction.programId && typeof instruction.programId == "object") {
424
+ let programIdStr = String(instruction.programId);
425
+ programIdStr && programIdStr !== "[object Object]" && programIds.add(programIdStr);
426
+ }
427
+ }
428
+ return programIds;
429
+ }
430
+ function parseSolChange(meta, walletIndex) {
431
+ if (!isTransactionMeta(meta) || !Array.isArray(meta.preBalances) || !Array.isArray(meta.postBalances))
432
+ return { balanceChange: 0, solChange: 0 };
433
+ let preBalanceRaw = meta.preBalances[walletIndex], postBalanceRaw = meta.postBalances[walletIndex], preBalance = typeof preBalanceRaw == "number" ? preBalanceRaw : typeof preBalanceRaw == "bigint" ? Number(preBalanceRaw) : 0, balanceChange = (typeof postBalanceRaw == "number" ? postBalanceRaw : typeof postBalanceRaw == "bigint" ? Number(postBalanceRaw) : 0) - preBalance, solChange = balanceChange / 1e9;
434
+ return { balanceChange, solChange };
435
+ }
436
+ function parseTokenTransfers(meta, accountKeys, walletAddress) {
437
+ if (!isTransactionMeta(meta))
438
+ return null;
439
+ let preTokenBalances = Array.isArray(meta.preTokenBalances) ? meta.preTokenBalances : [], postTokenBalances = Array.isArray(meta.postTokenBalances) ? meta.postTokenBalances : [], ourPreTokens = preTokenBalances.filter((balance) => {
440
+ if (!isTokenBalance(balance)) return false;
441
+ let accountKey = accountKeys[balance.accountIndex];
442
+ return accountKey && accountKey.trim() === walletAddress.trim() || balance.owner && balance.owner.trim() === walletAddress.trim();
443
+ }), ourPostTokens = postTokenBalances.filter((balance) => {
444
+ if (!isTokenBalance(balance)) return false;
445
+ let accountKey = accountKeys[balance.accountIndex];
446
+ return accountKey && accountKey.trim() === walletAddress.trim() || balance.owner && balance.owner.trim() === walletAddress.trim();
447
+ }), allMints = /* @__PURE__ */ new Set();
448
+ for (let token of ourPreTokens)
449
+ isTokenBalance(token) && allMints.add(token.mint);
450
+ for (let token of ourPostTokens)
451
+ isTokenBalance(token) && allMints.add(token.mint);
452
+ for (let mint of allMints) {
453
+ let preBal = ourPreTokens.find((b) => isTokenBalance(b) && b.mint === mint), postBal = ourPostTokens.find((b) => isTokenBalance(b) && b.mint === mint);
454
+ if (!isTokenBalance(preBal) && !isTokenBalance(postBal))
455
+ continue;
456
+ let preAmount = isTokenBalance(preBal) && isUiTokenAmount(preBal.uiTokenAmount) ? Number(preBal.uiTokenAmount.amount) : 0, change = (isTokenBalance(postBal) && isUiTokenAmount(postBal.uiTokenAmount) ? Number(postBal.uiTokenAmount.amount) : 0) - preAmount;
457
+ if (change !== 0) {
458
+ let decimals = isTokenBalance(postBal) && isUiTokenAmount(postBal.uiTokenAmount) ? postBal.uiTokenAmount.decimals : isTokenBalance(preBal) && isUiTokenAmount(preBal.uiTokenAmount) ? preBal.uiTokenAmount.decimals : 0;
459
+ if (typeof decimals != "number" || decimals < 0)
460
+ continue;
461
+ return {
462
+ tokenMint: mint,
463
+ tokenAmount: Math.abs(change) / Math.pow(10, decimals),
464
+ tokenDecimals: decimals,
465
+ direction: change > 0 ? "in" : "out",
466
+ type: change > 0 ? "received" : "sent"
467
+ };
468
+ }
469
+ }
470
+ if (ourPostTokens.length > ourPreTokens.length) {
471
+ let newToken = ourPostTokens.find(
472
+ (b) => isTokenBalance(b) && !ourPreTokens.some((p) => isTokenBalance(p) && p.mint === b.mint)
473
+ );
474
+ if (isTokenBalance(newToken) && isUiTokenAmount(newToken.uiTokenAmount)) {
475
+ let decimals = newToken.uiTokenAmount.decimals;
476
+ if (typeof decimals == "number" && decimals >= 0) {
477
+ let amount = Number(newToken.uiTokenAmount.amount) / Math.pow(10, decimals);
478
+ return {
479
+ tokenMint: newToken.mint,
480
+ tokenAmount: amount,
481
+ tokenDecimals: decimals,
482
+ direction: "in",
483
+ type: "received"
484
+ };
485
+ }
486
+ }
487
+ }
488
+ return null;
489
+ }
490
+ function formatAmount(tokenAmount, tokenDecimals, direction, solChange) {
491
+ if (tokenAmount !== void 0 && tokenDecimals !== void 0 && direction !== void 0) {
492
+ let sign = direction === "in" ? "+" : "-", maxDecimals = Math.min(tokenDecimals, 6);
493
+ return `${sign}${tokenAmount.toLocaleString(void 0, { maximumFractionDigits: maxDecimals })}`;
494
+ }
495
+ if (solChange !== 0)
496
+ return `${solChange > 0 ? "+" : ""}${solChange.toFixed(4)} SOL`;
497
+ }
498
+ var tokenMetadataCache = /* @__PURE__ */ new Map();
499
+ function transformImageUrl(url, imageProxy) {
500
+ if (url)
501
+ return imageProxy ? `${imageProxy}${encodeURIComponent(url)}` : url;
502
+ }
503
+ async function fetchTokenMetadata(mints) {
504
+ let results = /* @__PURE__ */ new Map();
505
+ if (mints.length === 0) return results;
506
+ let uncachedMints = [];
507
+ for (let mint of mints) {
508
+ let cached = tokenMetadataCache.get(mint);
509
+ cached ? results.set(mint, cached) : uncachedMints.push(mint);
510
+ }
511
+ if (uncachedMints.length === 0) return results;
512
+ try {
513
+ let response = await fetch("https://token-list-api.solana.cloud/v1/mints?chainId=101", {
514
+ method: "POST",
515
+ headers: { "Content-Type": "application/json" },
516
+ body: JSON.stringify({ addresses: uncachedMints }),
517
+ signal: AbortSignal.timeout(5e3)
518
+ });
519
+ if (!response.ok) return results;
520
+ let data = await response.json();
521
+ for (let item of data.content) {
522
+ let metadata = { symbol: item.symbol, icon: item.logoURI };
523
+ results.set(item.address, metadata), tokenMetadataCache.set(item.address, metadata);
524
+ }
525
+ } catch (error) {
526
+ console.warn("[useTransactions] Failed to fetch token metadata:", error);
527
+ }
528
+ return results;
529
+ }
530
+ function useTransactions(options = {}) {
531
+ let { limit = 10, autoRefresh = false, refreshInterval = 6e4, fetchDetails = true } = options, { address, connected } = useAccount(), { cluster } = useCluster(), client = useSolanaClient(), connectorClient = useConnectorClient(), [transactions, setTransactions] = React.useState([]), [isLoading, setIsLoading] = React.useState(false), [error, setError] = React.useState(null), [hasMore, setHasMore] = React.useState(true), [lastUpdated, setLastUpdated] = React.useState(null), beforeSignatureRef = React.useRef(void 0), prevDepsRef = React.useRef(
532
+ null
533
+ ), rpcClient = client?.client ?? null, imageProxy = connectorClient?.getConfig().imageProxy, parseTransaction = React.useCallback(
534
+ (tx, walletAddress, sig, blockTime, slot, err, explorerUrl) => {
535
+ let { date, time } = formatDate(blockTime), baseInfo = {
536
+ signature: sig,
537
+ blockTime,
538
+ slot,
539
+ status: err ? "failed" : "success",
540
+ error: err ? JSON.stringify(
541
+ err,
542
+ (_key, value) => typeof value == "bigint" ? value.toString() : value
543
+ ) : void 0,
544
+ type: "unknown",
545
+ formattedDate: date,
546
+ formattedTime: time,
547
+ explorerUrl
548
+ };
549
+ if (!isTransactionWithMeta(tx))
550
+ return baseInfo;
551
+ try {
552
+ let { meta, transaction } = tx;
553
+ if (!isTransactionMeta(meta))
554
+ return baseInfo;
555
+ let { message } = transaction;
556
+ if (!isTransactionMessage(message))
557
+ return baseInfo;
558
+ let accountKeys = getAccountKeys(message), walletIndex = accountKeys.findIndex((key) => key.trim() === walletAddress.trim());
559
+ if (walletIndex === -1)
560
+ return baseInfo;
561
+ let { balanceChange, solChange } = parseSolChange(meta, walletIndex), programIds = detectProgramIds(message, accountKeys), hasJupiter = programIds.has("JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"), hasOrca = programIds.has("whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc"), hasRaydium = programIds.has("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"), hasStake = programIds.has("Stake11111111111111111111111111111111111111"), hasMetaplex = programIds.has("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"), hasSystemProgram = programIds.has("11111111111111111111111111111111"), hasTokenProgram = programIds.has("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"), type = "unknown", direction, counterparty, tokenMint, tokenAmount, tokenDecimals;
562
+ if (hasJupiter || hasOrca || hasRaydium)
563
+ type = "swap";
564
+ else if (hasStake)
565
+ type = "stake";
566
+ else if (hasMetaplex)
567
+ type = "nft";
568
+ else if (hasSystemProgram && Math.abs(balanceChange) > 0)
569
+ type = balanceChange > 0 ? "received" : "sent", direction = balanceChange > 0 ? "in" : "out", tokenMint = "So11111111111111111111111111111111111111112", accountKeys.length >= 2 && (counterparty = accountKeys.find(
570
+ (key, idx) => idx !== walletIndex && key !== "11111111111111111111111111111111"
571
+ ));
572
+ else if (hasTokenProgram) {
573
+ let tokenTransfer = parseTokenTransfers(meta, accountKeys, walletAddress);
574
+ tokenTransfer && (type = tokenTransfer.type, direction = tokenTransfer.direction, tokenMint = tokenTransfer.tokenMint, tokenAmount = tokenTransfer.tokenAmount, tokenDecimals = tokenTransfer.tokenDecimals);
575
+ } else programIds.size > 0 && (type = "program");
576
+ let formattedAmount = formatAmount(tokenAmount, tokenDecimals, direction, solChange);
577
+ return {
578
+ ...baseInfo,
579
+ type,
580
+ direction,
581
+ amount: tokenAmount ?? Math.abs(solChange),
582
+ formattedAmount,
583
+ tokenMint,
584
+ counterparty: counterparty ? `${counterparty.slice(0, 4)}...${counterparty.slice(-4)}` : void 0
585
+ };
586
+ } catch (parseError) {
587
+ return console.warn("Failed to parse transaction:", parseError), baseInfo;
588
+ }
589
+ },
590
+ []
591
+ ), fetchTransactions = React.useCallback(
592
+ async (loadMore = false) => {
593
+ if (!connected || !address || !rpcClient || !cluster) {
594
+ setTransactions([]);
595
+ return;
596
+ }
597
+ setIsLoading(true), setError(null);
598
+ try {
599
+ let rpc = rpcClient.rpc, walletAddress = addresses.address(address), signaturesResult = await rpc.getSignaturesForAddress(walletAddress, {
600
+ limit,
601
+ ...loadMore && beforeSignatureRef.current ? { before: keys.signature(beforeSignatureRef.current) } : {}
602
+ }).send(), newTransactions;
603
+ if (fetchDetails && signaturesResult.length > 0) {
604
+ let txPromises = signaturesResult.map(
605
+ (s) => rpc.getTransaction(keys.signature(String(s.signature)), {
606
+ encoding: "jsonParsed",
607
+ maxSupportedTransactionVersion: 0
608
+ }).send().catch(() => null)
609
+ ), txDetails = await Promise.all(txPromises);
610
+ newTransactions = signaturesResult.map((sig, idx) => {
611
+ let blockTimeNum = sig.blockTime ? Number(sig.blockTime) : null, tx = txDetails[idx];
612
+ return parseTransaction(
613
+ tx,
614
+ address,
615
+ String(sig.signature),
616
+ blockTimeNum,
617
+ Number(sig.slot),
618
+ sig.err,
619
+ chunkJUZVCBAI_js.getTransactionUrl(String(sig.signature), cluster)
620
+ );
621
+ });
622
+ } else
623
+ newTransactions = signaturesResult.map((sig) => {
624
+ let blockTimeNum = sig.blockTime ? Number(sig.blockTime) : null, { date, time } = formatDate(blockTimeNum);
625
+ return {
626
+ signature: String(sig.signature),
627
+ blockTime: blockTimeNum,
628
+ slot: Number(sig.slot),
629
+ status: sig.err ? "failed" : "success",
630
+ error: sig.err ? JSON.stringify(sig.err) : void 0,
631
+ type: "unknown",
632
+ formattedDate: date,
633
+ formattedTime: time,
634
+ explorerUrl: chunkJUZVCBAI_js.getTransactionUrl(String(sig.signature), cluster)
635
+ };
636
+ });
637
+ setTransactions(loadMore ? (prev) => [...prev, ...newTransactions] : newTransactions);
638
+ let mintsToFetch = [...new Set(newTransactions.filter((tx) => tx.tokenMint).map((tx) => tx.tokenMint))];
639
+ if (mintsToFetch.length > 0) {
640
+ let tokenMetadata = await fetchTokenMetadata(mintsToFetch);
641
+ if (tokenMetadata.size > 0) {
642
+ let enrichedTransactions = newTransactions.map((tx) => {
643
+ if (tx.tokenMint && tokenMetadata.has(tx.tokenMint)) {
644
+ let meta = tokenMetadata.get(tx.tokenMint);
645
+ return {
646
+ ...tx,
647
+ tokenSymbol: meta.symbol,
648
+ tokenIcon: transformImageUrl(meta.icon, imageProxy),
649
+ // Update formatted amount with symbol
650
+ formattedAmount: tx.formattedAmount ? `${tx.formattedAmount} ${meta.symbol}` : tx.formattedAmount
651
+ };
652
+ }
653
+ return tx;
654
+ });
655
+ setTransactions(loadMore ? (prev) => [...prev.slice(0, -newTransactions.length), ...enrichedTransactions] : enrichedTransactions);
656
+ }
657
+ }
658
+ if (typeof newTransactions < "u" && Array.isArray(newTransactions)) {
659
+ if (newTransactions.length > 0) {
660
+ let newBeforeSignature = newTransactions[newTransactions.length - 1].signature;
661
+ beforeSignatureRef.current = newBeforeSignature;
662
+ }
663
+ setHasMore(newTransactions.length === limit);
664
+ }
665
+ setLastUpdated(/* @__PURE__ */ new Date());
666
+ } catch (err) {
667
+ setError(err), console.error("Failed to fetch transactions:", err);
668
+ } finally {
669
+ setIsLoading(false);
670
+ }
671
+ },
672
+ [connected, address, rpcClient, cluster, limit, fetchDetails, parseTransaction, imageProxy]
673
+ ), refetch = React.useCallback(async () => {
674
+ beforeSignatureRef.current = void 0, await fetchTransactions(false);
675
+ }, [fetchTransactions]), loadMoreFn = React.useCallback(async () => {
676
+ hasMore && !isLoading && await fetchTransactions(true);
677
+ }, [hasMore, isLoading, fetchTransactions]);
678
+ return React.useEffect(() => {
679
+ let prevDeps = prevDepsRef.current, currentDeps = { connected, address, cluster };
680
+ (!prevDeps || prevDeps.connected !== connected || prevDeps.address !== address || prevDeps.cluster !== cluster) && (prevDepsRef.current = currentDeps, beforeSignatureRef.current = void 0, fetchTransactions(false));
681
+ }, [connected, address, cluster, fetchTransactions]), React.useEffect(() => {
682
+ if (!connected || !autoRefresh) return;
683
+ let interval = setInterval(refetch, refreshInterval);
684
+ return () => clearInterval(interval);
685
+ }, [connected, autoRefresh, refreshInterval, refetch]), React.useMemo(
686
+ () => ({
687
+ transactions,
688
+ isLoading,
689
+ error,
690
+ hasMore,
691
+ loadMore: loadMoreFn,
692
+ refetch,
693
+ lastUpdated
694
+ }),
695
+ [transactions, isLoading, error, hasMore, loadMoreFn, refetch, lastUpdated]
696
+ );
697
+ }
698
+ function createTimeoutSignal(ms) {
699
+ if (typeof AbortSignal.timeout == "function")
700
+ return { signal: AbortSignal.timeout(ms), cleanup: () => {
701
+ } };
702
+ let controller = new AbortController(), timeoutId = setTimeout(() => controller.abort(), ms);
703
+ return {
704
+ signal: controller.signal,
705
+ cleanup: () => clearTimeout(timeoutId)
706
+ };
707
+ }
708
+ var NATIVE_MINT = "So11111111111111111111111111111111111111112", CACHE_MAX_SIZE = 500, PRICE_CACHE_TTL = 6e4, STALE_CLEANUP_INTERVAL = 12e4, COINGECKO_DEFAULT_MAX_RETRIES = 3, COINGECKO_DEFAULT_BASE_DELAY = 1e3, COINGECKO_DEFAULT_MAX_TIMEOUT = 3e4, COINGECKO_API_BASE_URL = "https://api.coingecko.com/api/v3", LRUCache = class {
709
+ constructor(maxSize, options) {
710
+ chunkI64FD2EH_js.__publicField(this, "cache", /* @__PURE__ */ new Map());
711
+ chunkI64FD2EH_js.__publicField(this, "maxSize");
712
+ chunkI64FD2EH_js.__publicField(this, "getTtl");
713
+ chunkI64FD2EH_js.__publicField(this, "getTimestamp");
714
+ this.maxSize = maxSize, this.getTtl = options?.getTtl, this.getTimestamp = options?.getTimestamp;
715
+ }
716
+ get(key) {
717
+ let value = this.cache.get(key);
718
+ if (value !== void 0) {
719
+ if (this.getTtl && this.getTimestamp) {
720
+ let ttl = this.getTtl(value), timestamp = this.getTimestamp(value);
721
+ if (ttl !== void 0 && timestamp !== void 0 && Date.now() - timestamp >= ttl) {
722
+ this.cache.delete(key);
723
+ return;
724
+ }
725
+ }
726
+ return this.cache.delete(key), this.cache.set(key, value), value;
727
+ }
728
+ }
729
+ set(key, value) {
730
+ if (this.cache.has(key) && this.cache.delete(key), this.cache.size >= this.maxSize) {
731
+ let oldestKey = this.cache.keys().next().value;
732
+ oldestKey !== void 0 && this.cache.delete(oldestKey);
733
+ }
734
+ this.cache.set(key, value);
735
+ }
736
+ has(key) {
737
+ return this.cache.has(key);
738
+ }
739
+ delete(key) {
740
+ return this.cache.delete(key);
741
+ }
742
+ clear() {
743
+ this.cache.clear();
744
+ }
745
+ get size() {
746
+ return this.cache.size;
747
+ }
748
+ /**
749
+ * Prune stale entries based on TTL.
750
+ * Only works if getTtl and getTimestamp are provided.
751
+ */
752
+ pruneStale() {
753
+ if (!this.getTtl || !this.getTimestamp) return 0;
754
+ let now = Date.now(), pruned = 0;
755
+ for (let [key, value] of this.cache) {
756
+ let ttl = this.getTtl(value), timestamp = this.getTimestamp(value);
757
+ ttl !== void 0 && timestamp !== void 0 && now - timestamp >= ttl && (this.cache.delete(key), pruned++);
758
+ }
759
+ return pruned;
760
+ }
761
+ }, metadataCache = new LRUCache(CACHE_MAX_SIZE), priceCache = new LRUCache(CACHE_MAX_SIZE, {
762
+ getTtl: () => PRICE_CACHE_TTL,
763
+ getTimestamp: (entry) => entry.timestamp
764
+ }), cleanupIntervalId = null, cleanupRefCount = 0;
765
+ function startCacheCleanup() {
766
+ cleanupRefCount++, cleanupIntervalId === null && (cleanupIntervalId = setInterval(() => {
767
+ priceCache.pruneStale();
768
+ }, STALE_CLEANUP_INTERVAL));
769
+ }
770
+ function stopCacheCleanup() {
771
+ cleanupRefCount = Math.max(0, cleanupRefCount - 1), cleanupRefCount === 0 && cleanupIntervalId !== null && (clearInterval(cleanupIntervalId), cleanupIntervalId = null);
772
+ }
773
+ function clearTokenCaches() {
774
+ metadataCache.clear(), priceCache.clear();
775
+ }
776
+ async function fetchSolanaTokenMetadata(mints) {
777
+ let results = /* @__PURE__ */ new Map();
778
+ if (mints.length === 0) return results;
779
+ let { signal, cleanup } = createTimeoutSignal(1e4);
780
+ try {
781
+ let response = await fetch("https://token-list-api.solana.cloud/v1/mints?chainId=101", {
782
+ method: "POST",
783
+ headers: { "Content-Type": "application/json" },
784
+ body: JSON.stringify({ addresses: mints }),
785
+ signal
786
+ });
787
+ if (cleanup(), !response.ok)
788
+ throw new Error(`Solana Token List API error: ${response.status}`);
789
+ let data = await response.json();
790
+ for (let item of data.content)
791
+ results.set(item.address, item);
792
+ } catch (error) {
793
+ cleanup(), console.warn("[useTokens] Solana Token List API failed:", error);
794
+ }
795
+ return results;
796
+ }
797
+ function calculateBackoffDelay(attempt, baseDelay, retryAfter) {
798
+ if (retryAfter !== void 0 && retryAfter > 0) {
799
+ let jitter2 = Math.random() * 500;
800
+ return retryAfter * 1e3 + jitter2;
801
+ }
802
+ let exponentialDelay = baseDelay * Math.pow(2, attempt), jitter = Math.random() * 500;
803
+ return exponentialDelay + jitter;
804
+ }
805
+ function parseRetryAfter(retryAfterHeader) {
806
+ if (!retryAfterHeader) return;
807
+ let seconds = parseInt(retryAfterHeader, 10);
808
+ if (!isNaN(seconds) && seconds >= 0)
809
+ return seconds;
810
+ let date = Date.parse(retryAfterHeader);
811
+ if (!isNaN(date)) {
812
+ let waitMs = date - Date.now();
813
+ return waitMs > 0 ? Math.ceil(waitMs / 1e3) : 0;
814
+ }
815
+ }
816
+ async function fetchCoinGeckoPrices(coingeckoIds, config) {
817
+ let results = /* @__PURE__ */ new Map();
818
+ if (coingeckoIds.length === 0) return results;
819
+ let now = Date.now(), uncachedIds = [];
820
+ for (let id of coingeckoIds) {
821
+ let cached = priceCache.get(id);
822
+ cached && now - cached.timestamp < PRICE_CACHE_TTL ? results.set(id, cached.price) : uncachedIds.push(id);
823
+ }
824
+ if (uncachedIds.length === 0) return results;
825
+ let maxRetries = config?.maxRetries ?? COINGECKO_DEFAULT_MAX_RETRIES, baseDelay = config?.baseDelay ?? COINGECKO_DEFAULT_BASE_DELAY, maxTimeout = config?.maxTimeout ?? COINGECKO_DEFAULT_MAX_TIMEOUT, apiKey = config?.apiKey, isPro = config?.isPro ?? false, url = `${COINGECKO_API_BASE_URL}/simple/price?ids=${uncachedIds.join(",")}&vs_currencies=usd`, headers = {};
826
+ apiKey && (headers[isPro ? "x-cg-pro-api-key" : "x-cg-demo-api-key"] = apiKey);
827
+ let startTime = Date.now(), attempt = 0, lastError = null;
828
+ for (; attempt <= maxRetries; ) {
829
+ let elapsedTime = Date.now() - startTime;
830
+ if (elapsedTime >= maxTimeout) {
831
+ console.warn(
832
+ `[useTokens] CoinGecko API: Total timeout (${maxTimeout}ms) exceeded after ${attempt} attempts. Returning cached/partial results.`
833
+ );
834
+ break;
835
+ }
836
+ let remainingTimeout = maxTimeout - elapsedTime, requestTimeout = Math.min(1e4, remainingTimeout), { signal, cleanup } = createTimeoutSignal(requestTimeout);
837
+ try {
838
+ let response = await fetch(url, {
839
+ headers,
840
+ signal
841
+ });
842
+ if (cleanup(), response.status === 429) {
843
+ let retryAfter = parseRetryAfter(response.headers.get("Retry-After")), delay = calculateBackoffDelay(attempt, baseDelay, retryAfter);
844
+ if (console.warn(
845
+ `[useTokens] CoinGecko API rate limited (429). Attempt ${attempt + 1}/${maxRetries + 1}. Retry-After: ${retryAfter ?? "not specified"}s. Waiting ${Math.round(delay)}ms before retry. Consider adding an API key for higher limits: https://www.coingecko.com/en/api/pricing`
846
+ ), Date.now() - startTime + delay >= maxTimeout) {
847
+ console.warn(
848
+ `[useTokens] CoinGecko API: Skipping retry - would exceed total timeout (${maxTimeout}ms). Returning cached/partial results.`
849
+ );
850
+ break;
851
+ }
852
+ await new Promise((resolve) => setTimeout(resolve, delay)), attempt++;
853
+ continue;
854
+ }
855
+ if (!response.ok)
856
+ throw new Error(`CoinGecko API error: ${response.status} ${response.statusText}`);
857
+ let data = await response.json(), fetchTime = Date.now();
858
+ for (let [id, priceData] of Object.entries(data))
859
+ priceData?.usd !== void 0 && (results.set(id, priceData.usd), priceCache.set(id, { price: priceData.usd, timestamp: fetchTime }));
860
+ return results;
861
+ } catch (error) {
862
+ if (cleanup(), lastError = error, error instanceof DOMException && error.name === "AbortError" ? console.warn(
863
+ `[useTokens] CoinGecko API request timed out. Attempt ${attempt + 1}/${maxRetries + 1}.`
864
+ ) : console.warn(
865
+ `[useTokens] CoinGecko API request failed. Attempt ${attempt + 1}/${maxRetries + 1}:`,
866
+ error
867
+ ), attempt < maxRetries) {
868
+ let delay = calculateBackoffDelay(attempt, baseDelay);
869
+ Date.now() - startTime + delay < maxTimeout && await new Promise((resolve) => setTimeout(resolve, delay));
870
+ }
871
+ attempt++;
872
+ }
873
+ }
874
+ return attempt > maxRetries && console.warn(
875
+ `[useTokens] CoinGecko API: All ${maxRetries + 1} attempts failed. Returning cached/partial results. Last error: ${lastError?.message ?? "Unknown error"}. If you are frequently rate limited, consider adding an API key: https://www.coingecko.com/en/api/pricing`
876
+ ), results;
877
+ }
878
+ async function fetchTokenMetadataHybrid(mints, coingeckoConfig) {
879
+ let results = /* @__PURE__ */ new Map();
880
+ if (mints.length === 0) return results;
881
+ let uncachedMints = [], now = Date.now();
882
+ for (let mint of mints) {
883
+ let cached = metadataCache.get(mint);
884
+ cached ? (cached.coingeckoId && (!priceCache.get(cached.coingeckoId) || now - (priceCache.get(cached.coingeckoId)?.timestamp ?? 0) >= PRICE_CACHE_TTL) && cached.coingeckoId && uncachedMints.push(mint), results.set(mint, cached)) : uncachedMints.push(mint);
885
+ }
886
+ if (uncachedMints.length === 0) return results;
887
+ let solanaMetadata = await fetchSolanaTokenMetadata(uncachedMints), coingeckoIdToMint = /* @__PURE__ */ new Map();
888
+ for (let [mint, meta] of solanaMetadata)
889
+ meta.extensions?.coingeckoId && coingeckoIdToMint.set(meta.extensions.coingeckoId, mint);
890
+ for (let mint of mints) {
891
+ let cached = metadataCache.get(mint);
892
+ cached?.coingeckoId && !coingeckoIdToMint.has(cached.coingeckoId) && coingeckoIdToMint.set(cached.coingeckoId, mint);
893
+ }
894
+ let prices = await fetchCoinGeckoPrices([...coingeckoIdToMint.keys()], coingeckoConfig);
895
+ for (let [mint, meta] of solanaMetadata) {
896
+ let coingeckoId = meta.extensions?.coingeckoId, usdPrice = coingeckoId ? prices.get(coingeckoId) : void 0, combined = {
897
+ address: meta.address,
898
+ name: meta.address === NATIVE_MINT ? "Solana" : meta.name,
899
+ symbol: meta.symbol,
900
+ decimals: meta.decimals,
901
+ logoURI: meta.logoURI,
902
+ coingeckoId,
903
+ usdPrice
904
+ };
905
+ results.set(mint, combined), metadataCache.set(mint, combined);
906
+ }
907
+ for (let [coingeckoId, mint] of coingeckoIdToMint) {
908
+ let cached = results.get(mint) ?? metadataCache.get(mint);
909
+ if (cached) {
910
+ let usdPrice = prices.get(coingeckoId);
911
+ usdPrice !== void 0 && (cached.usdPrice = usdPrice, results.set(mint, cached), metadataCache.set(mint, cached));
912
+ }
913
+ }
914
+ return results;
915
+ }
916
+ function formatBalance(amount, decimals) {
917
+ return (Number(amount) / Math.pow(10, decimals)).toLocaleString(void 0, {
918
+ minimumFractionDigits: 0,
919
+ maximumFractionDigits: Math.min(decimals, 6)
920
+ });
921
+ }
922
+ function formatUsd(amount, decimals, usdPrice) {
923
+ return (Number(amount) / Math.pow(10, decimals) * usdPrice).toLocaleString(void 0, {
924
+ style: "currency",
925
+ currency: "USD",
926
+ minimumFractionDigits: 2,
927
+ maximumFractionDigits: 2
928
+ });
929
+ }
930
+ function transformImageUrl2(url, imageProxy) {
931
+ if (!url) return;
932
+ if (!imageProxy) return url;
933
+ let encodedUrl = encodeURIComponent(url);
934
+ return imageProxy.endsWith("/") ? imageProxy + encodedUrl : imageProxy + "/" + encodedUrl;
935
+ }
936
+ function useTokens(options = {}) {
937
+ let {
938
+ includeZeroBalance = false,
939
+ autoRefresh = false,
940
+ refreshInterval = 6e4,
941
+ fetchMetadata = true,
942
+ includeNativeSol = true
943
+ } = options, { address, connected } = useAccount(), client = useSolanaClient(), connectorClient = useConnectorClient(), [tokens, setTokens] = React.useState([]), [isLoading, setIsLoading] = React.useState(false), [error, setError] = React.useState(null), [lastUpdated, setLastUpdated] = React.useState(null), [totalAccounts, setTotalAccounts] = React.useState(0), rpcClient = client?.client ?? null, connectorConfig = connectorClient?.getConfig(), imageProxy = connectorConfig?.imageProxy, coingeckoConfig = connectorConfig?.coingecko, fetchTokens = React.useCallback(async () => {
944
+ if (!connected || !address || !rpcClient) {
945
+ setTokens([]), setTotalAccounts(0);
946
+ return;
947
+ }
948
+ setIsLoading(true), setError(null);
949
+ try {
950
+ let rpc = rpcClient.rpc, walletAddress = addresses.address(address), tokenProgramId = addresses.address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"), [balanceResult, tokenAccountsResult] = await Promise.all([
951
+ includeNativeSol ? rpc.getBalance(walletAddress).send() : Promise.resolve(null),
952
+ rpc.getTokenAccountsByOwner(walletAddress, { programId: tokenProgramId }, { encoding: "jsonParsed" }).send()
953
+ ]), tokenList = [], mints = [];
954
+ if (includeNativeSol && balanceResult !== null) {
955
+ let solBalance = balanceResult.value;
956
+ (includeZeroBalance || solBalance > 0n) && (tokenList.push({
957
+ mint: NATIVE_MINT,
958
+ tokenAccount: address,
959
+ // SOL uses wallet address
960
+ amount: solBalance,
961
+ decimals: 9,
962
+ formatted: formatBalance(solBalance, 9),
963
+ isFrozen: false,
964
+ owner: address
965
+ }), mints.push(NATIVE_MINT));
966
+ }
967
+ for (let account of tokenAccountsResult.value) {
968
+ let parsed = account.account.data;
969
+ if (parsed?.parsed?.info) {
970
+ let info = parsed.parsed.info, amount = BigInt(info.tokenAmount?.amount || "0"), decimals = info.tokenAmount?.decimals || 0;
971
+ if (!includeZeroBalance && amount === 0n)
972
+ continue;
973
+ tokenList.push({
974
+ mint: info.mint,
975
+ tokenAccount: account.pubkey,
976
+ amount,
977
+ decimals,
978
+ formatted: formatBalance(amount, decimals),
979
+ isFrozen: info.state === "frozen",
980
+ owner: info.owner
981
+ }), mints.push(info.mint);
982
+ }
983
+ }
984
+ if (setTokens([...tokenList]), setTotalAccounts(tokenAccountsResult.value.length + (includeNativeSol ? 1 : 0)), setLastUpdated(/* @__PURE__ */ new Date()), fetchMetadata && mints.length > 0) {
985
+ let metadata = await fetchTokenMetadataHybrid(mints, coingeckoConfig);
986
+ for (let i = 0; i < tokenList.length; i++) {
987
+ let meta = metadata.get(tokenList[i].mint);
988
+ meta && (tokenList[i] = {
989
+ ...tokenList[i],
990
+ name: meta.name,
991
+ symbol: meta.symbol,
992
+ logo: transformImageUrl2(meta.logoURI, imageProxy),
993
+ usdPrice: meta.usdPrice,
994
+ formattedUsd: meta.usdPrice ? formatUsd(tokenList[i].amount, tokenList[i].decimals, meta.usdPrice) : void 0
995
+ });
996
+ }
997
+ tokenList.sort((a, b) => {
998
+ let metadataSort = (b.logo ? 1 : 0) - (a.logo ? 1 : 0);
999
+ if (metadataSort !== 0) return metadataSort;
1000
+ let aValue = Number(a.amount) / Math.pow(10, a.decimals) * (a.usdPrice ?? 0);
1001
+ return Number(b.amount) / Math.pow(10, b.decimals) * (b.usdPrice ?? 0) - aValue;
1002
+ }), setTokens([...tokenList]);
1003
+ }
1004
+ } catch (err) {
1005
+ setError(err), console.error("[useTokens] Failed to fetch tokens:", err);
1006
+ } finally {
1007
+ setIsLoading(false);
1008
+ }
1009
+ }, [connected, address, rpcClient, includeZeroBalance, fetchMetadata, includeNativeSol, imageProxy, coingeckoConfig]);
1010
+ React.useEffect(() => {
1011
+ fetchTokens();
1012
+ }, [fetchTokens]), React.useEffect(() => {
1013
+ if (!connected || !autoRefresh) return;
1014
+ let interval = setInterval(fetchTokens, refreshInterval);
1015
+ return () => clearInterval(interval);
1016
+ }, [connected, autoRefresh, refreshInterval, fetchTokens]), React.useEffect(() => (startCacheCleanup(), () => stopCacheCleanup()), []);
1017
+ let wasConnectedRef = React.useRef(connected);
1018
+ return React.useEffect(() => {
1019
+ wasConnectedRef.current && !connected && clearTokenCaches(), wasConnectedRef.current = connected;
1020
+ }, [connected]), React.useMemo(
1021
+ () => ({
1022
+ tokens,
1023
+ isLoading,
1024
+ error,
1025
+ refetch: fetchTokens,
1026
+ lastUpdated,
1027
+ totalAccounts
1028
+ }),
1029
+ [tokens, isLoading, error, fetchTokens, lastUpdated, totalAccounts]
1030
+ );
1031
+ }
1032
+ function DisconnectElement({
1033
+ variant = "menuitem",
1034
+ className,
1035
+ label = "Disconnect",
1036
+ icon,
1037
+ showIcon = true,
1038
+ onDisconnect,
1039
+ render
1040
+ }) {
1041
+ let { disconnect, connecting } = useConnector(), [disconnecting, setDisconnecting] = React__default.default.useState(false), handleDisconnect = async () => {
1042
+ setDisconnecting(true);
1043
+ try {
1044
+ await disconnect(), onDisconnect?.();
1045
+ } finally {
1046
+ setDisconnecting(false);
1047
+ }
1048
+ };
1049
+ if (render)
1050
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render({ disconnect: handleDisconnect, disconnecting }) });
1051
+ let isDisabled = connecting || disconnecting, content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1052
+ showIcon && (icon || showIcon && !icon && /* @__PURE__ */ jsxRuntime.jsxs(
1053
+ "svg",
1054
+ {
1055
+ width: "16",
1056
+ height: "16",
1057
+ viewBox: "0 0 24 24",
1058
+ fill: "none",
1059
+ stroke: "currentColor",
1060
+ strokeWidth: "2",
1061
+ strokeLinecap: "round",
1062
+ strokeLinejoin: "round",
1063
+ className: "ck-block-icon",
1064
+ "data-slot": "disconnect-element-icon",
1065
+ children: [
1066
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
1067
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "16 17 21 12 16 7" }),
1068
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
1069
+ ]
1070
+ }
1071
+ )),
1072
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "disconnect-element-label", children: label })
1073
+ ] });
1074
+ return variant === "button" ? /* @__PURE__ */ jsxRuntime.jsx(
1075
+ "button",
1076
+ {
1077
+ type: "button",
1078
+ className: `ck-disconnect-block ck-disconnect-block--button ${className || ""}`,
1079
+ onClick: handleDisconnect,
1080
+ disabled: isDisabled,
1081
+ "data-slot": "disconnect-element",
1082
+ "data-variant": "button",
1083
+ "data-disconnecting": disconnecting,
1084
+ children: content
1085
+ }
1086
+ ) : variant === "link" ? /* @__PURE__ */ jsxRuntime.jsx(
1087
+ "button",
1088
+ {
1089
+ type: "button",
1090
+ className: `ck-disconnect-block ck-disconnect-block--link ${className || ""}`,
1091
+ onClick: handleDisconnect,
1092
+ disabled: isDisabled,
1093
+ "data-slot": "disconnect-element",
1094
+ "data-variant": "link",
1095
+ "data-disconnecting": disconnecting,
1096
+ children: content
1097
+ }
1098
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1099
+ "button",
1100
+ {
1101
+ type: "button",
1102
+ role: "menuitem",
1103
+ className: `ck-disconnect-block ck-disconnect-block--menuitem ${className || ""}`,
1104
+ onClick: handleDisconnect,
1105
+ disabled: isDisabled,
1106
+ "data-slot": "disconnect-element",
1107
+ "data-variant": "menuitem",
1108
+ "data-disconnecting": disconnecting,
1109
+ children: content
1110
+ }
1111
+ );
1112
+ }
1113
+ DisconnectElement.displayName = "DisconnectElement";
1114
+ function AccountElement({
1115
+ showAvatar = true,
1116
+ showCopy = true,
1117
+ showFullAddress = false,
1118
+ className,
1119
+ avatarSize = 32,
1120
+ variant = "compact",
1121
+ render
1122
+ }) {
1123
+ let { address, formatted, copy, copied } = useAccount(), { name: walletName, icon: walletIcon } = useWalletInfo();
1124
+ if (render)
1125
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render({ address, formatted, walletName, walletIcon, copy, copied }) });
1126
+ if (!address) return null;
1127
+ let displayAddress = showFullAddress ? address : formatted, handleCopy = async (e) => {
1128
+ e.stopPropagation(), await copy();
1129
+ }, copyIcon = /* @__PURE__ */ jsxRuntime.jsx(
1130
+ "svg",
1131
+ {
1132
+ width: "14",
1133
+ height: "14",
1134
+ viewBox: "0 0 24 24",
1135
+ fill: "none",
1136
+ stroke: "currentColor",
1137
+ strokeWidth: "2",
1138
+ strokeLinecap: "round",
1139
+ strokeLinejoin: "round",
1140
+ className: "ck-block-icon",
1141
+ "data-slot": "account-element-copy-icon",
1142
+ children: copied ? /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1143
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
1144
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
1145
+ ] })
1146
+ }
1147
+ );
1148
+ return variant === "inline" ? /* @__PURE__ */ jsxRuntime.jsxs(
1149
+ "div",
1150
+ {
1151
+ className: `ck-account-block ck-account-block--inline ${className || ""}`,
1152
+ "data-slot": "account-element",
1153
+ "data-variant": "inline",
1154
+ children: [
1155
+ showAvatar && walletIcon && /* @__PURE__ */ jsxRuntime.jsx(
1156
+ "img",
1157
+ {
1158
+ src: walletIcon,
1159
+ alt: walletName || "Wallet",
1160
+ className: "ck-account-block-avatar",
1161
+ style: { width: avatarSize, height: avatarSize },
1162
+ "data-slot": "account-element-avatar"
1163
+ }
1164
+ ),
1165
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-account-block-address", "data-slot": "account-element-address", children: displayAddress }),
1166
+ showCopy && /* @__PURE__ */ jsxRuntime.jsx(
1167
+ "button",
1168
+ {
1169
+ type: "button",
1170
+ className: "ck-account-block-copy",
1171
+ onClick: handleCopy,
1172
+ title: copied ? "Copied!" : "Copy address",
1173
+ "data-slot": "account-element-copy",
1174
+ "data-copied": copied,
1175
+ children: copyIcon
1176
+ }
1177
+ )
1178
+ ]
1179
+ }
1180
+ ) : variant === "expanded" ? /* @__PURE__ */ jsxRuntime.jsxs(
1181
+ "div",
1182
+ {
1183
+ className: `ck-account-block ck-account-block--expanded ${className || ""}`,
1184
+ "data-slot": "account-element",
1185
+ "data-variant": "expanded",
1186
+ children: [
1187
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-account-block-header", "data-slot": "account-element-header", children: [
1188
+ showAvatar && walletIcon && /* @__PURE__ */ jsxRuntime.jsx(
1189
+ "img",
1190
+ {
1191
+ src: walletIcon,
1192
+ alt: walletName || "Wallet",
1193
+ className: "ck-account-block-avatar",
1194
+ style: { width: avatarSize, height: avatarSize },
1195
+ "data-slot": "account-element-avatar"
1196
+ }
1197
+ ),
1198
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-account-block-info", "data-slot": "account-element-info", children: [
1199
+ walletName && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-account-block-wallet-name", "data-slot": "account-element-wallet-name", children: walletName }),
1200
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-account-block-address", "data-slot": "account-element-address", children: displayAddress })
1201
+ ] })
1202
+ ] }),
1203
+ showCopy && /* @__PURE__ */ jsxRuntime.jsxs(
1204
+ "button",
1205
+ {
1206
+ type: "button",
1207
+ className: "ck-account-block-copy",
1208
+ onClick: handleCopy,
1209
+ "data-slot": "account-element-copy",
1210
+ "data-copied": copied,
1211
+ children: [
1212
+ copyIcon,
1213
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: copied ? "Copied!" : "Copy" })
1214
+ ]
1215
+ }
1216
+ )
1217
+ ]
1218
+ }
1219
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1220
+ "div",
1221
+ {
1222
+ className: `ck-account-block ck-account-block--compact ${className || ""}`,
1223
+ "data-slot": "account-element",
1224
+ "data-variant": "compact",
1225
+ children: [
1226
+ showAvatar && walletIcon && /* @__PURE__ */ jsxRuntime.jsx(
1227
+ "img",
1228
+ {
1229
+ src: walletIcon,
1230
+ alt: walletName || "Wallet",
1231
+ className: "ck-account-block-avatar",
1232
+ style: { width: avatarSize, height: avatarSize },
1233
+ "data-slot": "account-element-avatar"
1234
+ }
1235
+ ),
1236
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-account-block-content", "data-slot": "account-element-content", children: [
1237
+ walletName && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-account-block-wallet-name", "data-slot": "account-element-wallet-name", children: walletName }),
1238
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-account-block-address", "data-slot": "account-element-address", children: displayAddress })
1239
+ ] }),
1240
+ showCopy && /* @__PURE__ */ jsxRuntime.jsx(
1241
+ "button",
1242
+ {
1243
+ type: "button",
1244
+ className: "ck-account-block-copy",
1245
+ onClick: handleCopy,
1246
+ title: copied ? "Copied!" : "Copy address",
1247
+ "data-slot": "account-element-copy",
1248
+ "data-copied": copied,
1249
+ children: copyIcon
1250
+ }
1251
+ )
1252
+ ]
1253
+ }
1254
+ );
1255
+ }
1256
+ AccountElement.displayName = "AccountElement";
1257
+ var DEFAULT_LABELS = {
1258
+ "mainnet-beta": "Mainnet",
1259
+ devnet: "Devnet",
1260
+ testnet: "Testnet",
1261
+ localnet: "Localnet"
1262
+ };
1263
+ function getClusterColor(clusterId) {
1264
+ switch (clusterId) {
1265
+ case "mainnet-beta":
1266
+ return "var(--ck-cluster-mainnet, #22c55e)";
1267
+ case "devnet":
1268
+ return "var(--ck-cluster-devnet, #3b82f6)";
1269
+ case "testnet":
1270
+ return "var(--ck-cluster-testnet, #eab308)";
1271
+ case "localnet":
1272
+ return "var(--ck-cluster-localnet, #ef4444)";
1273
+ default:
1274
+ return "var(--ck-cluster-custom, #8b5cf6)";
1275
+ }
1276
+ }
1277
+ function ClusterElement({
1278
+ variant = "badge",
1279
+ className,
1280
+ allowChange = false,
1281
+ showIndicator = true,
1282
+ labels = {},
1283
+ render
1284
+ }) {
1285
+ let { cluster, clusters, setCluster, isMainnet, isDevnet, isTestnet, isLocal } = useCluster(), [isOpen, setIsOpen] = React__default.default.useState(false);
1286
+ if (render)
1287
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render({ cluster, clusters, setCluster, isMainnet, isDevnet, isTestnet, isLocal }) });
1288
+ if (!cluster) return null;
1289
+ let allLabels = { ...DEFAULT_LABELS, ...labels }, displayLabel = allLabels[cluster.id] || cluster.label || cluster.id, color = getClusterColor(cluster.id), indicator = showIndicator && /* @__PURE__ */ jsxRuntime.jsx(
1290
+ "span",
1291
+ {
1292
+ className: "ck-cluster-indicator",
1293
+ style: { backgroundColor: color },
1294
+ "data-slot": "cluster-element-indicator",
1295
+ "aria-hidden": "true"
1296
+ }
1297
+ );
1298
+ return variant === "badge" ? /* @__PURE__ */ jsxRuntime.jsxs(
1299
+ "span",
1300
+ {
1301
+ className: `ck-cluster-block ck-cluster-block--badge ${className || ""}`,
1302
+ "data-slot": "cluster-element",
1303
+ "data-variant": "badge",
1304
+ "data-cluster": cluster.id,
1305
+ children: [
1306
+ indicator,
1307
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "cluster-element-label", children: displayLabel })
1308
+ ]
1309
+ }
1310
+ ) : variant === "menuitem" ? allowChange ? /* @__PURE__ */ jsxRuntime.jsxs(
1311
+ "div",
1312
+ {
1313
+ className: `ck-cluster-block ck-cluster-block--menuitem ${className || ""}`,
1314
+ "data-slot": "cluster-element",
1315
+ "data-variant": "menuitem",
1316
+ "data-cluster": cluster.id,
1317
+ children: [
1318
+ /* @__PURE__ */ jsxRuntime.jsxs(
1319
+ "button",
1320
+ {
1321
+ type: "button",
1322
+ className: "ck-cluster-block-trigger",
1323
+ onClick: () => setIsOpen(!isOpen),
1324
+ "data-slot": "cluster-element-trigger",
1325
+ children: [
1326
+ indicator,
1327
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "cluster-element-label", children: displayLabel }),
1328
+ /* @__PURE__ */ jsxRuntime.jsx(
1329
+ "svg",
1330
+ {
1331
+ width: "12",
1332
+ height: "12",
1333
+ viewBox: "0 0 24 24",
1334
+ fill: "none",
1335
+ stroke: "currentColor",
1336
+ strokeWidth: "2",
1337
+ className: `ck-cluster-block-chevron ${isOpen ? "ck-cluster-block-chevron--open" : ""}`,
1338
+ "data-slot": "cluster-element-chevron",
1339
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" })
1340
+ }
1341
+ )
1342
+ ]
1343
+ }
1344
+ ),
1345
+ isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-cluster-block-options", "data-slot": "cluster-element-options", children: clusters.map((c) => {
1346
+ let cLabel = allLabels[c.id] || c.label || c.id, cColor = getClusterColor(c.id), isSelected = c.id === cluster.id;
1347
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1348
+ "button",
1349
+ {
1350
+ type: "button",
1351
+ className: `ck-cluster-block-option ${isSelected ? "ck-cluster-block-option--selected" : ""}`,
1352
+ onClick: () => {
1353
+ setCluster(c.id), setIsOpen(false);
1354
+ },
1355
+ "data-slot": "cluster-element-option",
1356
+ "data-selected": isSelected,
1357
+ children: [
1358
+ /* @__PURE__ */ jsxRuntime.jsx(
1359
+ "span",
1360
+ {
1361
+ className: "ck-cluster-indicator",
1362
+ style: { backgroundColor: cColor },
1363
+ "data-slot": "cluster-element-indicator"
1364
+ }
1365
+ ),
1366
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: cLabel }),
1367
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx(
1368
+ "svg",
1369
+ {
1370
+ width: "12",
1371
+ height: "12",
1372
+ viewBox: "0 0 24 24",
1373
+ fill: "none",
1374
+ stroke: "currentColor",
1375
+ strokeWidth: "3",
1376
+ className: "ck-cluster-block-check",
1377
+ "data-slot": "cluster-element-check",
1378
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" })
1379
+ }
1380
+ )
1381
+ ]
1382
+ },
1383
+ c.id
1384
+ );
1385
+ }) })
1386
+ ]
1387
+ }
1388
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1389
+ "div",
1390
+ {
1391
+ className: `ck-cluster-block ck-cluster-block--menuitem ${className || ""}`,
1392
+ role: "menuitem",
1393
+ "data-slot": "cluster-element",
1394
+ "data-variant": "menuitem",
1395
+ "data-cluster": cluster.id,
1396
+ children: [
1397
+ indicator,
1398
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "cluster-element-label", children: displayLabel })
1399
+ ]
1400
+ }
1401
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1402
+ "div",
1403
+ {
1404
+ className: `ck-cluster-block ck-cluster-block--select ${className || ""}`,
1405
+ "data-slot": "cluster-element",
1406
+ "data-variant": "select",
1407
+ "data-cluster": cluster.id,
1408
+ children: [
1409
+ /* @__PURE__ */ jsxRuntime.jsxs(
1410
+ "button",
1411
+ {
1412
+ type: "button",
1413
+ className: "ck-cluster-block-trigger",
1414
+ onClick: () => setIsOpen(!isOpen),
1415
+ disabled: !allowChange,
1416
+ "data-slot": "cluster-element-trigger",
1417
+ children: [
1418
+ indicator,
1419
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "cluster-element-label", children: displayLabel }),
1420
+ allowChange && /* @__PURE__ */ jsxRuntime.jsx(
1421
+ "svg",
1422
+ {
1423
+ width: "12",
1424
+ height: "12",
1425
+ viewBox: "0 0 24 24",
1426
+ fill: "none",
1427
+ stroke: "currentColor",
1428
+ strokeWidth: "2",
1429
+ className: `ck-cluster-block-chevron ${isOpen ? "ck-cluster-block-chevron--open" : ""}`,
1430
+ "data-slot": "cluster-element-chevron",
1431
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" })
1432
+ }
1433
+ )
1434
+ ]
1435
+ }
1436
+ ),
1437
+ isOpen && allowChange && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1438
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-cluster-block-backdrop", onClick: () => setIsOpen(false), "aria-hidden": "true" }),
1439
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-cluster-block-options", "data-slot": "cluster-element-options", children: clusters.map((c) => {
1440
+ let cLabel = allLabels[c.id] || c.label || c.id, cColor = getClusterColor(c.id), isSelected = c.id === cluster.id;
1441
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1442
+ "button",
1443
+ {
1444
+ type: "button",
1445
+ className: `ck-cluster-block-option ${isSelected ? "ck-cluster-block-option--selected" : ""}`,
1446
+ onClick: () => {
1447
+ setCluster(c.id), setIsOpen(false);
1448
+ },
1449
+ "data-slot": "cluster-element-option",
1450
+ "data-selected": isSelected,
1451
+ children: [
1452
+ /* @__PURE__ */ jsxRuntime.jsx(
1453
+ "span",
1454
+ {
1455
+ className: "ck-cluster-indicator",
1456
+ style: { backgroundColor: cColor },
1457
+ "data-slot": "cluster-element-indicator"
1458
+ }
1459
+ ),
1460
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: cLabel }),
1461
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx(
1462
+ "svg",
1463
+ {
1464
+ width: "12",
1465
+ height: "12",
1466
+ viewBox: "0 0 24 24",
1467
+ fill: "none",
1468
+ stroke: "currentColor",
1469
+ strokeWidth: "3",
1470
+ className: "ck-cluster-block-check",
1471
+ "data-slot": "cluster-element-check",
1472
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" })
1473
+ }
1474
+ )
1475
+ ]
1476
+ },
1477
+ c.id
1478
+ );
1479
+ }) })
1480
+ ] })
1481
+ ]
1482
+ }
1483
+ );
1484
+ }
1485
+ ClusterElement.displayName = "ClusterElement";
1486
+ function WalletListElement({
1487
+ installedOnly = false,
1488
+ className,
1489
+ variant = "list",
1490
+ showStatus = true,
1491
+ onSelect,
1492
+ render,
1493
+ renderWallet
1494
+ }) {
1495
+ let { wallets, connecting } = useWalletInfo(), { select } = useConnector(), installedWallets = wallets.filter((w) => w.installed), displayWallets = installedOnly ? installedWallets : wallets, handleSelect = async (walletName) => {
1496
+ await select(walletName), onSelect?.(walletName);
1497
+ };
1498
+ if (render)
1499
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render({ wallets, installedWallets, select: handleSelect, connecting }) });
1500
+ if (displayWallets.length === 0)
1501
+ return /* @__PURE__ */ jsxRuntime.jsx(
1502
+ "div",
1503
+ {
1504
+ className: `ck-wallet-list-block ck-wallet-list-block--empty ${className || ""}`,
1505
+ "data-slot": "wallet-list-element",
1506
+ "data-empty": "true",
1507
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-wallet-list-empty", "data-slot": "wallet-list-empty", children: [
1508
+ /* @__PURE__ */ jsxRuntime.jsxs(
1509
+ "svg",
1510
+ {
1511
+ width: "48",
1512
+ height: "48",
1513
+ viewBox: "0 0 24 24",
1514
+ fill: "none",
1515
+ stroke: "currentColor",
1516
+ strokeWidth: "1.5",
1517
+ strokeLinecap: "round",
1518
+ strokeLinejoin: "round",
1519
+ className: "ck-wallet-list-empty-icon",
1520
+ "data-slot": "wallet-list-empty-icon",
1521
+ children: [
1522
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1" }),
1523
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4" })
1524
+ ]
1525
+ }
1526
+ ),
1527
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ck-wallet-list-empty-text", "data-slot": "wallet-list-empty-text", children: installedOnly ? "No wallets detected" : "No wallets available" }),
1528
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ck-wallet-list-empty-hint", "data-slot": "wallet-list-empty-hint", children: "Install a Solana wallet extension to continue" })
1529
+ ] })
1530
+ }
1531
+ );
1532
+ let walletIcon = /* @__PURE__ */ jsxRuntime.jsxs(
1533
+ "svg",
1534
+ {
1535
+ width: "20",
1536
+ height: "20",
1537
+ viewBox: "0 0 24 24",
1538
+ fill: "none",
1539
+ stroke: "currentColor",
1540
+ strokeWidth: "2",
1541
+ strokeLinecap: "round",
1542
+ strokeLinejoin: "round",
1543
+ className: "ck-wallet-list-item-fallback-icon",
1544
+ "data-slot": "wallet-list-item-fallback-icon",
1545
+ children: [
1546
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1" }),
1547
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4" })
1548
+ ]
1549
+ }
1550
+ );
1551
+ return variant === "grid" ? /* @__PURE__ */ jsxRuntime.jsx(
1552
+ "div",
1553
+ {
1554
+ className: `ck-wallet-list-block ck-wallet-list-block--grid ${className || ""}`,
1555
+ "data-slot": "wallet-list-element",
1556
+ "data-variant": "grid",
1557
+ children: displayWallets.map((wallet) => renderWallet ? /* @__PURE__ */ jsxRuntime.jsx(React__default.default.Fragment, { children: renderWallet({
1558
+ wallet,
1559
+ select: () => handleSelect(wallet.name),
1560
+ connecting
1561
+ }) }, wallet.name) : /* @__PURE__ */ jsxRuntime.jsxs(
1562
+ "button",
1563
+ {
1564
+ type: "button",
1565
+ className: "ck-wallet-list-item ck-wallet-list-item--grid",
1566
+ onClick: () => handleSelect(wallet.name),
1567
+ disabled: connecting || !wallet.installed && installedOnly,
1568
+ "data-slot": "wallet-list-item",
1569
+ "data-wallet": wallet.name,
1570
+ "data-installed": wallet.installed,
1571
+ children: [
1572
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-wallet-list-item-icon", "data-slot": "wallet-list-item-icon", children: wallet.icon ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: wallet.icon, alt: wallet.name }) : walletIcon }),
1573
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-wallet-list-item-name", "data-slot": "wallet-list-item-name", children: wallet.name }),
1574
+ showStatus && !wallet.installed && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-wallet-list-item-status", "data-slot": "wallet-list-item-status", children: "Not installed" })
1575
+ ]
1576
+ },
1577
+ wallet.name
1578
+ ))
1579
+ }
1580
+ ) : variant === "compact" ? /* @__PURE__ */ jsxRuntime.jsx(
1581
+ "div",
1582
+ {
1583
+ className: `ck-wallet-list-block ck-wallet-list-block--compact ${className || ""}`,
1584
+ "data-slot": "wallet-list-element",
1585
+ "data-variant": "compact",
1586
+ children: displayWallets.map((wallet) => renderWallet ? /* @__PURE__ */ jsxRuntime.jsx(React__default.default.Fragment, { children: renderWallet({
1587
+ wallet,
1588
+ select: () => handleSelect(wallet.name),
1589
+ connecting
1590
+ }) }, wallet.name) : /* @__PURE__ */ jsxRuntime.jsxs(
1591
+ "button",
1592
+ {
1593
+ type: "button",
1594
+ className: "ck-wallet-list-item ck-wallet-list-item--compact",
1595
+ onClick: () => handleSelect(wallet.name),
1596
+ disabled: connecting || !wallet.installed && installedOnly,
1597
+ "data-slot": "wallet-list-item",
1598
+ "data-wallet": wallet.name,
1599
+ "data-installed": wallet.installed,
1600
+ children: [
1601
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-wallet-list-item-icon", "data-slot": "wallet-list-item-icon", children: wallet.icon ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: wallet.icon, alt: wallet.name }) : walletIcon }),
1602
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-wallet-list-item-name", "data-slot": "wallet-list-item-name", children: wallet.name })
1603
+ ]
1604
+ },
1605
+ wallet.name
1606
+ ))
1607
+ }
1608
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1609
+ "div",
1610
+ {
1611
+ className: `ck-wallet-list-block ck-wallet-list-block--list ${className || ""}`,
1612
+ "data-slot": "wallet-list-element",
1613
+ "data-variant": "list",
1614
+ children: displayWallets.map((wallet) => renderWallet ? /* @__PURE__ */ jsxRuntime.jsx(React__default.default.Fragment, { children: renderWallet({
1615
+ wallet,
1616
+ select: () => handleSelect(wallet.name),
1617
+ connecting
1618
+ }) }, wallet.name) : /* @__PURE__ */ jsxRuntime.jsxs(
1619
+ "button",
1620
+ {
1621
+ type: "button",
1622
+ className: "ck-wallet-list-item ck-wallet-list-item--list",
1623
+ onClick: () => handleSelect(wallet.name),
1624
+ disabled: connecting || !wallet.installed && installedOnly,
1625
+ "data-slot": "wallet-list-item",
1626
+ "data-wallet": wallet.name,
1627
+ "data-installed": wallet.installed,
1628
+ children: [
1629
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-wallet-list-item-icon", "data-slot": "wallet-list-item-icon", children: wallet.icon ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: wallet.icon, alt: wallet.name }) : walletIcon }),
1630
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-wallet-list-item-info", "data-slot": "wallet-list-item-info", children: [
1631
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-wallet-list-item-name", "data-slot": "wallet-list-item-name", children: wallet.name }),
1632
+ showStatus && /* @__PURE__ */ jsxRuntime.jsx(
1633
+ "span",
1634
+ {
1635
+ className: "ck-wallet-list-item-status",
1636
+ "data-slot": "wallet-list-item-status",
1637
+ "data-installed": wallet.installed,
1638
+ children: wallet.installed ? "Detected" : "Not installed"
1639
+ }
1640
+ )
1641
+ ] }),
1642
+ /* @__PURE__ */ jsxRuntime.jsx(
1643
+ "svg",
1644
+ {
1645
+ width: "16",
1646
+ height: "16",
1647
+ viewBox: "0 0 24 24",
1648
+ fill: "none",
1649
+ stroke: "currentColor",
1650
+ strokeWidth: "2",
1651
+ strokeLinecap: "round",
1652
+ strokeLinejoin: "round",
1653
+ className: "ck-wallet-list-item-arrow",
1654
+ "data-slot": "wallet-list-item-arrow",
1655
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" })
1656
+ }
1657
+ )
1658
+ ]
1659
+ },
1660
+ wallet.name
1661
+ ))
1662
+ }
1663
+ );
1664
+ }
1665
+ WalletListElement.displayName = "WalletListElement";
1666
+ function BalanceElement({
1667
+ showSol = true,
1668
+ showTokens = false,
1669
+ tokenCount = 3,
1670
+ className,
1671
+ variant = "compact",
1672
+ showRefresh = false,
1673
+ showSkeleton = true,
1674
+ render
1675
+ }) {
1676
+ let { solBalance, formattedSol, tokens, isLoading, error, refetch } = useBalance();
1677
+ if (render)
1678
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render({ solBalance, formattedSol, tokens, isLoading, error, refetch }) });
1679
+ let displayTokens = tokens.slice(0, tokenCount), refreshIcon = /* @__PURE__ */ jsxRuntime.jsxs(
1680
+ "svg",
1681
+ {
1682
+ width: "14",
1683
+ height: "14",
1684
+ viewBox: "0 0 24 24",
1685
+ fill: "none",
1686
+ stroke: "currentColor",
1687
+ strokeWidth: "2",
1688
+ strokeLinecap: "round",
1689
+ strokeLinejoin: "round",
1690
+ className: `ck-block-icon ${isLoading ? "ck-block-icon--spinning" : ""}`,
1691
+ "data-slot": "balance-element-refresh-icon",
1692
+ children: [
1693
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
1694
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 3v5h5" }),
1695
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" }),
1696
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 16h5v5" })
1697
+ ]
1698
+ }
1699
+ );
1700
+ return isLoading && showSkeleton && solBalance === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1701
+ "div",
1702
+ {
1703
+ className: `ck-balance-block ck-balance-block--${variant} ck-balance-block--loading ${className || ""}`,
1704
+ "data-slot": "balance-element",
1705
+ "data-variant": variant,
1706
+ "data-loading": "true",
1707
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-balance-block-skeleton", "data-slot": "balance-element-skeleton", children: [
1708
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-skeleton ck-skeleton--text" }),
1709
+ showTokens && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1710
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-skeleton ck-skeleton--text ck-skeleton--short" }),
1711
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-skeleton ck-skeleton--text ck-skeleton--short" })
1712
+ ] })
1713
+ ] })
1714
+ }
1715
+ ) : error ? /* @__PURE__ */ jsxRuntime.jsxs(
1716
+ "div",
1717
+ {
1718
+ className: `ck-balance-block ck-balance-block--${variant} ck-balance-block--error ${className || ""}`,
1719
+ "data-slot": "balance-element",
1720
+ "data-variant": variant,
1721
+ "data-error": "true",
1722
+ children: [
1723
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-balance-block-error", "data-slot": "balance-element-error", children: "Failed to load balance" }),
1724
+ showRefresh && /* @__PURE__ */ jsxRuntime.jsx(
1725
+ "button",
1726
+ {
1727
+ type: "button",
1728
+ className: "ck-balance-block-refresh",
1729
+ onClick: () => refetch(),
1730
+ "data-slot": "balance-element-refresh",
1731
+ children: refreshIcon
1732
+ }
1733
+ )
1734
+ ]
1735
+ }
1736
+ ) : variant === "inline" ? /* @__PURE__ */ jsxRuntime.jsxs(
1737
+ "div",
1738
+ {
1739
+ className: `ck-balance-block ck-balance-block--inline ${className || ""}`,
1740
+ "data-slot": "balance-element",
1741
+ "data-variant": "inline",
1742
+ children: [
1743
+ showSol && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-balance-block-sol", "data-slot": "balance-element-sol", children: formattedSol }),
1744
+ showRefresh && /* @__PURE__ */ jsxRuntime.jsx(
1745
+ "button",
1746
+ {
1747
+ type: "button",
1748
+ className: "ck-balance-block-refresh",
1749
+ onClick: () => refetch(),
1750
+ disabled: isLoading,
1751
+ "data-slot": "balance-element-refresh",
1752
+ children: refreshIcon
1753
+ }
1754
+ )
1755
+ ]
1756
+ }
1757
+ ) : variant === "expanded" ? /* @__PURE__ */ jsxRuntime.jsxs(
1758
+ "div",
1759
+ {
1760
+ className: `ck-balance-block ck-balance-block--expanded ${className || ""}`,
1761
+ "data-slot": "balance-element",
1762
+ "data-variant": "expanded",
1763
+ children: [
1764
+ showSol && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-balance-block-sol-section", "data-slot": "balance-element-sol-section", children: [
1765
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-balance-block-label", "data-slot": "balance-element-label", children: "SOL Balance" }),
1766
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-balance-block-sol", "data-slot": "balance-element-sol", children: formattedSol })
1767
+ ] }),
1768
+ showTokens && displayTokens.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-balance-block-tokens-section", "data-slot": "balance-element-tokens-section", children: [
1769
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ck-balance-block-label", "data-slot": "balance-element-label", children: [
1770
+ "Tokens (",
1771
+ tokens.length,
1772
+ ")"
1773
+ ] }),
1774
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-balance-block-tokens", "data-slot": "balance-element-tokens", children: [
1775
+ displayTokens.map((token) => /* @__PURE__ */ jsxRuntime.jsxs(
1776
+ "div",
1777
+ {
1778
+ className: "ck-balance-block-token",
1779
+ "data-slot": "balance-element-token",
1780
+ children: [
1781
+ token.logo && /* @__PURE__ */ jsxRuntime.jsx(
1782
+ "img",
1783
+ {
1784
+ src: token.logo,
1785
+ alt: token.symbol || "Token",
1786
+ className: "ck-balance-block-token-logo",
1787
+ "data-slot": "balance-element-token-logo"
1788
+ }
1789
+ ),
1790
+ /* @__PURE__ */ jsxRuntime.jsxs(
1791
+ "span",
1792
+ {
1793
+ className: "ck-balance-block-token-info",
1794
+ "data-slot": "balance-element-token-info",
1795
+ children: [
1796
+ /* @__PURE__ */ jsxRuntime.jsx(
1797
+ "span",
1798
+ {
1799
+ className: "ck-balance-block-token-symbol",
1800
+ "data-slot": "balance-element-token-symbol",
1801
+ children: token.symbol || token.mint.slice(0, 4) + "..." + token.mint.slice(-4)
1802
+ }
1803
+ ),
1804
+ /* @__PURE__ */ jsxRuntime.jsx(
1805
+ "span",
1806
+ {
1807
+ className: "ck-balance-block-token-amount",
1808
+ "data-slot": "balance-element-token-amount",
1809
+ children: token.formatted
1810
+ }
1811
+ )
1812
+ ]
1813
+ }
1814
+ )
1815
+ ]
1816
+ },
1817
+ token.mint
1818
+ )),
1819
+ tokens.length > tokenCount && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-balance-block-more", "data-slot": "balance-element-more", children: [
1820
+ "+",
1821
+ tokens.length - tokenCount,
1822
+ " more"
1823
+ ] })
1824
+ ] })
1825
+ ] }),
1826
+ showRefresh && /* @__PURE__ */ jsxRuntime.jsxs(
1827
+ "button",
1828
+ {
1829
+ type: "button",
1830
+ className: "ck-balance-block-refresh",
1831
+ onClick: () => refetch(),
1832
+ disabled: isLoading,
1833
+ "data-slot": "balance-element-refresh",
1834
+ children: [
1835
+ refreshIcon,
1836
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Refresh" })
1837
+ ]
1838
+ }
1839
+ )
1840
+ ]
1841
+ }
1842
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1843
+ "div",
1844
+ {
1845
+ className: `ck-balance-block ck-balance-block--compact ${className || ""}`,
1846
+ "data-slot": "balance-element",
1847
+ "data-variant": "compact",
1848
+ children: [
1849
+ showSol && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-balance-block-sol", "data-slot": "balance-element-sol", children: formattedSol }),
1850
+ showTokens && displayTokens.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ck-balance-block-token-count", "data-slot": "balance-element-token-count", children: [
1851
+ "+",
1852
+ tokens.length,
1853
+ " tokens"
1854
+ ] }),
1855
+ showRefresh && /* @__PURE__ */ jsxRuntime.jsx(
1856
+ "button",
1857
+ {
1858
+ type: "button",
1859
+ className: "ck-balance-block-refresh",
1860
+ onClick: () => refetch(),
1861
+ disabled: isLoading,
1862
+ "data-slot": "balance-element-refresh",
1863
+ children: refreshIcon
1864
+ }
1865
+ )
1866
+ ]
1867
+ }
1868
+ );
1869
+ }
1870
+ BalanceElement.displayName = "BalanceElement";
1871
+ function TransactionHistoryElement({
1872
+ limit = 5,
1873
+ showStatus = true,
1874
+ showTime = true,
1875
+ className,
1876
+ variant = "list",
1877
+ showLoadMore = false,
1878
+ showSkeleton = true,
1879
+ render,
1880
+ renderItem
1881
+ }) {
1882
+ let { transactions, isLoading, error, hasMore, loadMore, refetch } = useTransactions({ limit });
1883
+ if (render)
1884
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render({ transactions, isLoading, error, hasMore, loadMore, refetch }) });
1885
+ let statusIcon = (status) => /* @__PURE__ */ jsxRuntime.jsx(
1886
+ "svg",
1887
+ {
1888
+ width: "12",
1889
+ height: "12",
1890
+ viewBox: "0 0 24 24",
1891
+ fill: "none",
1892
+ stroke: "currentColor",
1893
+ strokeWidth: "2",
1894
+ strokeLinecap: "round",
1895
+ strokeLinejoin: "round",
1896
+ className: `ck-tx-status-icon ck-tx-status-icon--${status}`,
1897
+ "data-slot": "tx-status-icon",
1898
+ "data-status": status,
1899
+ children: status === "success" ? /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1900
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1901
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1902
+ ] })
1903
+ }
1904
+ ), externalLinkIcon = /* @__PURE__ */ jsxRuntime.jsxs(
1905
+ "svg",
1906
+ {
1907
+ width: "12",
1908
+ height: "12",
1909
+ viewBox: "0 0 24 24",
1910
+ fill: "none",
1911
+ stroke: "currentColor",
1912
+ strokeWidth: "2",
1913
+ strokeLinecap: "round",
1914
+ strokeLinejoin: "round",
1915
+ className: "ck-block-icon",
1916
+ "data-slot": "tx-external-link-icon",
1917
+ children: [
1918
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
1919
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }),
1920
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
1921
+ ]
1922
+ }
1923
+ );
1924
+ if (isLoading && showSkeleton && transactions.length === 0)
1925
+ return /* @__PURE__ */ jsxRuntime.jsx(
1926
+ "div",
1927
+ {
1928
+ className: `ck-tx-history-block ck-tx-history-block--${variant} ck-tx-history-block--loading ${className || ""}`,
1929
+ "data-slot": "tx-history-element",
1930
+ "data-variant": variant,
1931
+ "data-loading": "true",
1932
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-tx-history-skeleton", "data-slot": "tx-history-skeleton", children: Array.from({ length: Math.min(limit, 3) }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-skeleton ck-skeleton--tx" }, i)) })
1933
+ }
1934
+ );
1935
+ if (error)
1936
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1937
+ "div",
1938
+ {
1939
+ className: `ck-tx-history-block ck-tx-history-block--${variant} ck-tx-history-block--error ${className || ""}`,
1940
+ "data-slot": "tx-history-element",
1941
+ "data-variant": variant,
1942
+ "data-error": "true",
1943
+ children: [
1944
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-tx-history-error", "data-slot": "tx-history-error", children: "Failed to load transactions" }),
1945
+ /* @__PURE__ */ jsxRuntime.jsx(
1946
+ "button",
1947
+ {
1948
+ type: "button",
1949
+ className: "ck-tx-history-retry",
1950
+ onClick: () => refetch(),
1951
+ "data-slot": "tx-history-retry",
1952
+ children: "Retry"
1953
+ }
1954
+ )
1955
+ ]
1956
+ }
1957
+ );
1958
+ if (transactions.length === 0)
1959
+ return /* @__PURE__ */ jsxRuntime.jsx(
1960
+ "div",
1961
+ {
1962
+ className: `ck-tx-history-block ck-tx-history-block--${variant} ck-tx-history-block--empty ${className || ""}`,
1963
+ "data-slot": "tx-history-element",
1964
+ "data-variant": variant,
1965
+ "data-empty": "true",
1966
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-tx-history-empty", "data-slot": "tx-history-empty", children: "No transactions yet" })
1967
+ }
1968
+ );
1969
+ let itemRenderer = renderItem || ((tx) => /* @__PURE__ */ jsxRuntime.jsxs(
1970
+ "a",
1971
+ {
1972
+ href: tx.explorerUrl,
1973
+ target: "_blank",
1974
+ rel: "noopener noreferrer",
1975
+ className: "ck-tx-item",
1976
+ "data-slot": "tx-item",
1977
+ "data-status": tx.status,
1978
+ children: [
1979
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-tx-item-main", "data-slot": "tx-item-main", children: [
1980
+ showStatus && /* @__PURE__ */ jsxRuntime.jsx(
1981
+ "span",
1982
+ {
1983
+ className: `ck-tx-status ck-tx-status--${tx.status}`,
1984
+ "data-slot": "tx-status",
1985
+ "data-status": tx.status,
1986
+ children: statusIcon(tx.status)
1987
+ }
1988
+ ),
1989
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ck-tx-signature", "data-slot": "tx-signature", children: [
1990
+ tx.signature.slice(0, 8),
1991
+ "...",
1992
+ tx.signature.slice(-8)
1993
+ ] })
1994
+ ] }),
1995
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-tx-item-meta", "data-slot": "tx-item-meta", children: [
1996
+ showTime && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ck-tx-time", "data-slot": "tx-time", children: [
1997
+ tx.formattedDate,
1998
+ " ",
1999
+ tx.formattedTime
2000
+ ] }),
2001
+ externalLinkIcon
2002
+ ] })
2003
+ ]
2004
+ },
2005
+ tx.signature
2006
+ ));
2007
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2008
+ "div",
2009
+ {
2010
+ className: `ck-tx-history-block ck-tx-history-block--${variant} ${className || ""}`,
2011
+ "data-slot": "tx-history-element",
2012
+ "data-variant": variant,
2013
+ children: [
2014
+ variant === "expanded" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-tx-history-header", "data-slot": "tx-history-header", children: [
2015
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-tx-history-title", "data-slot": "tx-history-title", children: "Recent Transactions" }),
2016
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-tx-history-count", "data-slot": "tx-history-count", children: transactions.length })
2017
+ ] }),
2018
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-tx-history-list", "data-slot": "tx-history-list", children: transactions.map(itemRenderer) }),
2019
+ showLoadMore && hasMore && /* @__PURE__ */ jsxRuntime.jsx(
2020
+ "button",
2021
+ {
2022
+ type: "button",
2023
+ className: "ck-tx-history-load-more",
2024
+ onClick: () => loadMore(),
2025
+ disabled: isLoading,
2026
+ "data-slot": "tx-history-load-more",
2027
+ children: isLoading ? "Loading..." : "Load more"
2028
+ }
2029
+ )
2030
+ ]
2031
+ }
2032
+ );
2033
+ }
2034
+ TransactionHistoryElement.displayName = "TransactionHistoryElement";
2035
+ function TokenListElement({
2036
+ limit = 10,
2037
+ showValue = false,
2038
+ className,
2039
+ variant = "compact",
2040
+ showRefresh = false,
2041
+ showSkeleton = true,
2042
+ render,
2043
+ renderItem
2044
+ }) {
2045
+ let { tokens, isLoading, error, refetch, totalAccounts } = useTokens();
2046
+ if (render)
2047
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render({ tokens, isLoading, error, refetch, totalAccounts }) });
2048
+ let displayTokens = tokens.slice(0, limit), refreshIcon = /* @__PURE__ */ jsxRuntime.jsxs(
2049
+ "svg",
2050
+ {
2051
+ width: "14",
2052
+ height: "14",
2053
+ viewBox: "0 0 24 24",
2054
+ fill: "none",
2055
+ stroke: "currentColor",
2056
+ strokeWidth: "2",
2057
+ strokeLinecap: "round",
2058
+ strokeLinejoin: "round",
2059
+ className: `ck-block-icon ${isLoading ? "ck-block-icon--spinning" : ""}`,
2060
+ "data-slot": "token-list-refresh-icon",
2061
+ children: [
2062
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
2063
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 3v5h5" }),
2064
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" }),
2065
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 16h5v5" })
2066
+ ]
2067
+ }
2068
+ ), tokenIcon = /* @__PURE__ */ jsxRuntime.jsxs(
2069
+ "svg",
2070
+ {
2071
+ width: "20",
2072
+ height: "20",
2073
+ viewBox: "0 0 24 24",
2074
+ fill: "none",
2075
+ stroke: "currentColor",
2076
+ strokeWidth: "2",
2077
+ strokeLinecap: "round",
2078
+ strokeLinejoin: "round",
2079
+ className: "ck-token-placeholder-icon",
2080
+ "data-slot": "token-placeholder-icon",
2081
+ children: [
2082
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
2083
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 6v12" }),
2084
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 12h12" })
2085
+ ]
2086
+ }
2087
+ );
2088
+ if (isLoading && showSkeleton && tokens.length === 0)
2089
+ return /* @__PURE__ */ jsxRuntime.jsx(
2090
+ "div",
2091
+ {
2092
+ className: `ck-token-list-block ck-token-list-block--${variant} ck-token-list-block--loading ${className || ""}`,
2093
+ "data-slot": "token-list-element",
2094
+ "data-variant": variant,
2095
+ "data-loading": "true",
2096
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-token-list-skeleton", "data-slot": "token-list-skeleton", children: Array.from({ length: Math.min(limit, 3) }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-skeleton ck-skeleton--token" }, i)) })
2097
+ }
2098
+ );
2099
+ if (error)
2100
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2101
+ "div",
2102
+ {
2103
+ className: `ck-token-list-block ck-token-list-block--${variant} ck-token-list-block--error ${className || ""}`,
2104
+ "data-slot": "token-list-element",
2105
+ "data-variant": variant,
2106
+ "data-error": "true",
2107
+ children: [
2108
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-token-list-error", "data-slot": "token-list-error", children: "Failed to load tokens" }),
2109
+ /* @__PURE__ */ jsxRuntime.jsx(
2110
+ "button",
2111
+ {
2112
+ type: "button",
2113
+ className: "ck-token-list-retry",
2114
+ onClick: () => refetch(),
2115
+ "data-slot": "token-list-retry",
2116
+ children: "Retry"
2117
+ }
2118
+ )
2119
+ ]
2120
+ }
2121
+ );
2122
+ if (tokens.length === 0)
2123
+ return /* @__PURE__ */ jsxRuntime.jsx(
2124
+ "div",
2125
+ {
2126
+ className: `ck-token-list-block ck-token-list-block--${variant} ck-token-list-block--empty ${className || ""}`,
2127
+ "data-slot": "token-list-element",
2128
+ "data-variant": variant,
2129
+ "data-empty": "true",
2130
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-token-list-empty", "data-slot": "token-list-empty", children: "No tokens found" })
2131
+ }
2132
+ );
2133
+ let itemRenderer = renderItem || ((token) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-token-item", "data-slot": "token-item", children: [
2134
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ck-token-item-icon", "data-slot": "token-item-icon", children: token.logo ? /* @__PURE__ */ jsxRuntime.jsx(
2135
+ "img",
2136
+ {
2137
+ src: token.logo,
2138
+ alt: token.symbol || "Token",
2139
+ className: "ck-token-logo",
2140
+ "data-slot": "token-logo",
2141
+ onError: (e) => {
2142
+ e.currentTarget.style.display = "none";
2143
+ }
2144
+ }
2145
+ ) : tokenIcon }),
2146
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-token-item-info", "data-slot": "token-item-info", children: [
2147
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-token-symbol", "data-slot": "token-symbol", children: token.symbol || token.mint.slice(0, 4) + "..." + token.mint.slice(-4) }),
2148
+ token.name && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-token-name", "data-slot": "token-name", children: token.name })
2149
+ ] }),
2150
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-token-item-balance", "data-slot": "token-item-balance", children: [
2151
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-token-amount", "data-slot": "token-amount", children: token.formatted }),
2152
+ showValue && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-token-value", "data-slot": "token-value", children: "-" })
2153
+ ] })
2154
+ ] }, token.mint));
2155
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2156
+ "div",
2157
+ {
2158
+ className: `ck-token-list-block ck-token-list-block--${variant} ${className || ""}`,
2159
+ "data-slot": "token-list-element",
2160
+ "data-variant": variant,
2161
+ children: [
2162
+ variant === "expanded" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-token-list-header", "data-slot": "token-list-header", children: [
2163
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-token-list-title", "data-slot": "token-list-title", children: "Tokens" }),
2164
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ck-token-list-count", "data-slot": "token-list-count", children: totalAccounts }),
2165
+ showRefresh && /* @__PURE__ */ jsxRuntime.jsx(
2166
+ "button",
2167
+ {
2168
+ type: "button",
2169
+ className: "ck-token-list-refresh",
2170
+ onClick: () => refetch(),
2171
+ disabled: isLoading,
2172
+ "data-slot": "token-list-refresh",
2173
+ children: refreshIcon
2174
+ }
2175
+ )
2176
+ ] }),
2177
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `ck-token-list ${variant === "grid" ? "ck-token-list--grid" : ""}`, "data-slot": "token-list", children: displayTokens.map(itemRenderer) }),
2178
+ tokens.length > limit && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ck-token-list-more", "data-slot": "token-list-more", children: [
2179
+ "+",
2180
+ tokens.length - limit,
2181
+ " more tokens"
2182
+ ] })
2183
+ ]
2184
+ }
2185
+ );
2186
+ }
2187
+ TokenListElement.displayName = "TokenListElement";
2188
+
2189
+ exports.AccountElement = AccountElement;
2190
+ exports.BalanceElement = BalanceElement;
2191
+ exports.ClusterElement = ClusterElement;
2192
+ exports.ConnectorProvider = ConnectorProvider;
2193
+ exports.DisconnectElement = DisconnectElement;
2194
+ exports.TokenListElement = TokenListElement;
2195
+ exports.TransactionHistoryElement = TransactionHistoryElement;
2196
+ exports.UnifiedProvider = UnifiedProvider;
2197
+ exports.WalletListElement = WalletListElement;
2198
+ exports.useAccount = useAccount;
2199
+ exports.useBalance = useBalance;
2200
+ exports.useCluster = useCluster;
2201
+ exports.useConnector = useConnector;
2202
+ exports.useConnectorClient = useConnectorClient;
2203
+ exports.useGillSolanaClient = useGillSolanaClient;
2204
+ exports.useGillTransactionSigner = useGillTransactionSigner;
2205
+ exports.useKitTransactionSigner = useKitTransactionSigner;
2206
+ exports.useSolanaClient = useSolanaClient;
2207
+ exports.useTokens = useTokens;
2208
+ exports.useTransactionPreparer = useTransactionPreparer;
2209
+ exports.useTransactionSigner = useTransactionSigner;
2210
+ exports.useTransactions = useTransactions;
2211
+ exports.useWalletInfo = useWalletInfo;
2212
+ //# sourceMappingURL=chunk-ULUYX23Q.js.map
2213
+ //# sourceMappingURL=chunk-ULUYX23Q.js.map