@solana/connector 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +1460 -0
  2. package/dist/chunk-52WUWW5R.mjs +2533 -0
  3. package/dist/chunk-52WUWW5R.mjs.map +1 -0
  4. package/dist/chunk-5NSUFMCB.js +393 -0
  5. package/dist/chunk-5NSUFMCB.js.map +1 -0
  6. package/dist/chunk-5ZUVZZWU.mjs +180 -0
  7. package/dist/chunk-5ZUVZZWU.mjs.map +1 -0
  8. package/dist/chunk-7TADXRFD.mjs +298 -0
  9. package/dist/chunk-7TADXRFD.mjs.map +1 -0
  10. package/dist/chunk-ACFSCMUI.mjs +359 -0
  11. package/dist/chunk-ACFSCMUI.mjs.map +1 -0
  12. package/dist/chunk-SGAIPK7Q.js +314 -0
  13. package/dist/chunk-SGAIPK7Q.js.map +1 -0
  14. package/dist/chunk-SMUUAKC3.js +186 -0
  15. package/dist/chunk-SMUUAKC3.js.map +1 -0
  16. package/dist/chunk-ZLPQUOFK.js +2594 -0
  17. package/dist/chunk-ZLPQUOFK.js.map +1 -0
  18. package/dist/compat.d.mts +106 -0
  19. package/dist/compat.d.ts +106 -0
  20. package/dist/compat.js +98 -0
  21. package/dist/compat.js.map +1 -0
  22. package/dist/compat.mjs +94 -0
  23. package/dist/compat.mjs.map +1 -0
  24. package/dist/headless.d.mts +400 -0
  25. package/dist/headless.d.ts +400 -0
  26. package/dist/headless.js +325 -0
  27. package/dist/headless.js.map +1 -0
  28. package/dist/headless.mjs +4 -0
  29. package/dist/headless.mjs.map +1 -0
  30. package/dist/index.d.mts +10 -0
  31. package/dist/index.d.ts +10 -0
  32. package/dist/index.js +382 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/index.mjs +5 -0
  35. package/dist/index.mjs.map +1 -0
  36. package/dist/react.d.mts +645 -0
  37. package/dist/react.d.ts +645 -0
  38. package/dist/react.js +65 -0
  39. package/dist/react.js.map +1 -0
  40. package/dist/react.mjs +4 -0
  41. package/dist/react.mjs.map +1 -0
  42. package/dist/transaction-signer-BtJPGXIg.d.mts +373 -0
  43. package/dist/transaction-signer-BtJPGXIg.d.ts +373 -0
  44. package/dist/wallet-standard-shim-Af7ejSld.d.mts +1090 -0
  45. package/dist/wallet-standard-shim-BGlvGRbB.d.ts +1090 -0
  46. package/package.json +87 -10
  47. package/index.js +0 -1
@@ -0,0 +1,314 @@
1
+ 'use strict';
2
+
3
+ var chunkZLPQUOFK_js = require('./chunk-ZLPQUOFK.js');
4
+ var chunkSMUUAKC3_js = require('./chunk-SMUUAKC3.js');
5
+ var React = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var gill = require('gill');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var React__default = /*#__PURE__*/_interopDefault(React);
12
+
13
+ var logger = chunkSMUUAKC3_js.createLogger("ConnectorProvider");
14
+ chunkZLPQUOFK_js.installPolyfills();
15
+ var ConnectorContext = React.createContext(null);
16
+ ConnectorContext.displayName = "ConnectorContext";
17
+ function ConnectorProviderInternal({
18
+ children,
19
+ config,
20
+ mobile
21
+ }) {
22
+ let clientRef = React.useRef(null), client = React__default.default.useCallback(() => {
23
+ if (!clientRef.current)
24
+ try {
25
+ clientRef.current = new chunkZLPQUOFK_js.ConnectorClient(config), typeof window < "u" && (window.__connectorClient = clientRef.current), config?.debug && logger.info("Client initialized successfully");
26
+ } catch (error) {
27
+ let err = error;
28
+ logger.error("Failed to initialize client", { error: err });
29
+ let extendedConfig = config;
30
+ return extendedConfig?.errorBoundary?.onError && extendedConfig.errorBoundary.onError(err, {
31
+ componentStack: "client-initialization",
32
+ digest: `constructor-${(/* @__PURE__ */ new Date()).toISOString()}`
33
+ }), null;
34
+ }
35
+ return clientRef.current;
36
+ }, [config])();
37
+ return React__default.default.useEffect(() => {
38
+ let currentClient = clientRef.current;
39
+ if (currentClient) {
40
+ let privateClient = currentClient;
41
+ privateClient.initialize && typeof privateClient.initialize == "function" && privateClient.initialize();
42
+ }
43
+ return () => {
44
+ typeof window < "u" && (window.__connectorClient = void 0), currentClient && typeof currentClient.destroy == "function" && currentClient.destroy();
45
+ };
46
+ }, []), React__default.default.useEffect(() => {
47
+ if (!mobile) return;
48
+ let cancelled = false;
49
+ return (async () => {
50
+ try {
51
+ let mod = await import('@solana-mobile/wallet-standard-mobile');
52
+ if (cancelled) return;
53
+ let {
54
+ registerMwa,
55
+ createDefaultAuthorizationCache,
56
+ createDefaultChainSelector,
57
+ createDefaultWalletNotFoundHandler
58
+ } = mod, defaultChains = [
59
+ "solana:mainnet",
60
+ "solana:devnet",
61
+ "solana:testnet"
62
+ ];
63
+ registerMwa({
64
+ appIdentity: mobile.appIdentity,
65
+ authorizationCache: mobile.authorizationCache ?? createDefaultAuthorizationCache(),
66
+ chains: mobile.chains ?? defaultChains,
67
+ chainSelector: mobile.chainSelector ?? createDefaultChainSelector(),
68
+ remoteHostAuthority: mobile.remoteHostAuthority,
69
+ onWalletNotFound: mobile.onWalletNotFound ?? createDefaultWalletNotFoundHandler()
70
+ });
71
+ } catch {
72
+ }
73
+ })(), () => {
74
+ cancelled = true;
75
+ };
76
+ }, [mobile]), /* @__PURE__ */ jsxRuntime.jsx(ConnectorContext.Provider, { value: client, children });
77
+ }
78
+ function ConnectorProvider({
79
+ children,
80
+ config,
81
+ mobile
82
+ }) {
83
+ let errorBoundaryConfig = config?.errorBoundary;
84
+ return errorBoundaryConfig?.enabled ? /* @__PURE__ */ jsxRuntime.jsx(
85
+ chunkZLPQUOFK_js.ConnectorErrorBoundary,
86
+ {
87
+ maxRetries: errorBoundaryConfig.maxRetries ?? 3,
88
+ onError: errorBoundaryConfig.onError,
89
+ fallback: errorBoundaryConfig.fallback,
90
+ children: /* @__PURE__ */ jsxRuntime.jsx(ConnectorProviderInternal, { config, mobile, children })
91
+ }
92
+ ) : /* @__PURE__ */ jsxRuntime.jsx(ConnectorProviderInternal, { config, mobile, children });
93
+ }
94
+ function useConnector() {
95
+ let client = React.useContext(ConnectorContext);
96
+ if (!client)
97
+ throw new Error(
98
+ "useConnector must be used within ConnectorProvider. Wrap your app with <ConnectorProvider> or <UnifiedProvider> to use connector hooks."
99
+ );
100
+ let state = React.useSyncExternalStore(
101
+ React__default.default.useCallback((cb) => client.subscribe(cb), [client]),
102
+ React__default.default.useCallback(() => client.getSnapshot(), [client]),
103
+ React__default.default.useCallback(() => client.getSnapshot(), [client])
104
+ ), methods = React.useMemo(
105
+ () => ({
106
+ select: client.select.bind(client),
107
+ disconnect: client.disconnect.bind(client),
108
+ selectAccount: client.selectAccount.bind(client)
109
+ }),
110
+ [client]
111
+ );
112
+ return React.useMemo(
113
+ () => ({
114
+ ...state,
115
+ ...methods
116
+ }),
117
+ [state, methods]
118
+ );
119
+ }
120
+ function useConnectorClient() {
121
+ return React.useContext(ConnectorContext);
122
+ }
123
+ function UnifiedProvider({ children, config, connectorConfig, mobile, providers = [] }) {
124
+ let actualConnectorConfig = config?.connectorConfig ?? connectorConfig, actualMobile = config?.mobile ?? mobile, content = /* @__PURE__ */ jsxRuntime.jsx(ConnectorProvider, { config: actualConnectorConfig, mobile: actualMobile, children });
125
+ for (let i = providers.length - 1; i >= 0; i--) {
126
+ let { component: Provider, props = {} } = providers[i];
127
+ content = /* @__PURE__ */ jsxRuntime.jsx(Provider, { ...props, children: content });
128
+ }
129
+ return content;
130
+ }
131
+ function useCluster() {
132
+ let { cluster, clusters } = useConnector(), client = useConnectorClient();
133
+ if (!client)
134
+ throw new Error("useCluster must be used within ConnectorProvider");
135
+ let setCluster = React.useMemo(
136
+ () => async (id) => {
137
+ await client.setCluster(id);
138
+ },
139
+ [client]
140
+ );
141
+ return React.useMemo(() => {
142
+ let isMainnet = cluster ? chunkZLPQUOFK_js.isMainnetCluster(cluster) : false, isDevnet = cluster ? chunkZLPQUOFK_js.isDevnetCluster(cluster) : false, isTestnet = cluster ? chunkZLPQUOFK_js.isTestnetCluster(cluster) : false, isLocal = cluster ? chunkZLPQUOFK_js.isLocalCluster(cluster) : false, explorerUrl = cluster ? chunkZLPQUOFK_js.getClusterExplorerUrl(cluster) : "", type = cluster ? chunkZLPQUOFK_js.getClusterType(cluster) : null;
143
+ return {
144
+ cluster,
145
+ clusters,
146
+ setCluster,
147
+ isMainnet,
148
+ isDevnet,
149
+ isTestnet,
150
+ isLocal,
151
+ explorerUrl,
152
+ type
153
+ };
154
+ }, [cluster, clusters, setCluster]);
155
+ }
156
+ function useAccount() {
157
+ let { selectedAccount, accounts, connected, selectAccount } = useConnector(), [copied, setCopied] = React.useState(false), copyTimeoutRef = React__default.default.useRef(void 0), account = React.useMemo(
158
+ () => accounts.find((a) => a.address === selectedAccount) ?? null,
159
+ [accounts, selectedAccount]
160
+ ), formatted = React.useMemo(() => selectedAccount ? chunkZLPQUOFK_js.formatAddress(selectedAccount) : "", [selectedAccount]), copy = React.useCallback(async () => selectedAccount ? (copyTimeoutRef.current && clearTimeout(copyTimeoutRef.current), await chunkZLPQUOFK_js.copyAddressToClipboard(selectedAccount, {
161
+ onSuccess: () => {
162
+ setCopied(true), copyTimeoutRef.current = setTimeout(() => setCopied(false), 2e3);
163
+ }
164
+ })) : {
165
+ success: false,
166
+ error: "empty_value" /* EMPTY_VALUE */,
167
+ errorMessage: "No account selected"
168
+ }, [selectedAccount]);
169
+ return React__default.default.useEffect(() => () => {
170
+ copyTimeoutRef.current && clearTimeout(copyTimeoutRef.current);
171
+ }, []), React.useMemo(
172
+ () => ({
173
+ address: selectedAccount,
174
+ account,
175
+ connected,
176
+ formatted,
177
+ copy,
178
+ copied,
179
+ accounts,
180
+ selectAccount
181
+ }),
182
+ [selectedAccount, account, connected, formatted, copy, copied, accounts, selectAccount]
183
+ );
184
+ }
185
+ function useWalletInfo() {
186
+ let { selectedWallet, wallets, connected, connecting } = useConnector(), mappedWallets = React.useMemo(
187
+ () => wallets.map(
188
+ (walletInfo) => ({
189
+ name: walletInfo.wallet.name,
190
+ icon: walletInfo.wallet.icon,
191
+ installed: walletInfo.installed,
192
+ connectable: walletInfo.connectable
193
+ })
194
+ ),
195
+ [wallets]
196
+ ), selectedWalletInfo = React.useMemo(() => {
197
+ if (!selectedWallet)
198
+ return {
199
+ name: null,
200
+ icon: null,
201
+ installed: false,
202
+ connectable: false
203
+ };
204
+ let walletInfo = wallets.find((w) => w.wallet.name === selectedWallet.name);
205
+ return {
206
+ name: selectedWallet.name,
207
+ icon: selectedWallet.icon ?? null,
208
+ installed: walletInfo?.installed ?? false,
209
+ connectable: walletInfo?.connectable ?? false
210
+ };
211
+ }, [selectedWallet, wallets]);
212
+ return React.useMemo(
213
+ () => ({
214
+ ...selectedWalletInfo,
215
+ connected,
216
+ connecting,
217
+ wallets: mappedWallets
218
+ }),
219
+ [selectedWalletInfo, connected, connecting, mappedWallets]
220
+ );
221
+ }
222
+ function useTransactionSigner() {
223
+ let { selectedWallet, selectedAccount, accounts, cluster, connected } = useConnector(), client = useConnectorClient(), account = React.useMemo(
224
+ () => accounts.find((a) => a.address === selectedAccount)?.raw ?? null,
225
+ [accounts, selectedAccount]
226
+ ), signer = React.useMemo(() => !connected || !selectedWallet || !account ? null : chunkZLPQUOFK_js.createTransactionSigner({
227
+ wallet: selectedWallet,
228
+ account,
229
+ cluster: cluster ?? void 0,
230
+ eventEmitter: client ? {
231
+ emit: (event) => {
232
+ client.emitEvent(event);
233
+ }
234
+ } : void 0
235
+ }), [connected, selectedWallet, account, cluster, client]), capabilities = React.useMemo(
236
+ () => signer?.getCapabilities() ?? {
237
+ canSign: false,
238
+ canSend: false,
239
+ canSignMessage: false,
240
+ supportsBatchSigning: false
241
+ },
242
+ [signer]
243
+ );
244
+ return {
245
+ signer,
246
+ ready: !!signer,
247
+ address: selectedAccount,
248
+ capabilities
249
+ };
250
+ }
251
+ function useGillTransactionSigner() {
252
+ let { signer: connectorSigner, ready } = useTransactionSigner();
253
+ return {
254
+ signer: React.useMemo(() => connectorSigner ? chunkZLPQUOFK_js.createGillTransactionSigner(connectorSigner) : null, [connectorSigner]),
255
+ ready
256
+ };
257
+ }
258
+ var logger2 = chunkSMUUAKC3_js.createLogger("useGillSolanaClient");
259
+ function useGillSolanaClient() {
260
+ let { type } = useCluster(), connectorClient = useConnectorClient(), client = React.useMemo(() => {
261
+ if (!type || !connectorClient) return null;
262
+ try {
263
+ if (type !== "custom")
264
+ return gill.createSolanaClient({
265
+ urlOrMoniker: type
266
+ });
267
+ let rpcUrl = connectorClient.getRpcUrl();
268
+ return rpcUrl ? gill.createSolanaClient({
269
+ urlOrMoniker: rpcUrl
270
+ }) : null;
271
+ } catch (error) {
272
+ return logger2.error("Failed to create Gill Solana client", { error }), null;
273
+ }
274
+ }, [type, connectorClient]);
275
+ return {
276
+ client,
277
+ ready: !!client,
278
+ clusterType: type
279
+ };
280
+ }
281
+ function useTransactionPreparer() {
282
+ let { client, ready } = useGillSolanaClient();
283
+ return {
284
+ prepare: React.useCallback(
285
+ async (transaction, options = {}) => {
286
+ if (!client)
287
+ throw new chunkZLPQUOFK_js.NetworkError("RPC_ERROR", "Solana client not available. Cannot prepare transaction.");
288
+ return gill.prepareTransaction({
289
+ transaction,
290
+ rpc: client.rpc,
291
+ computeUnitLimitMultiplier: options.computeUnitLimitMultiplier,
292
+ computeUnitLimitReset: options.computeUnitLimitReset,
293
+ blockhashReset: options.blockhashReset
294
+ });
295
+ },
296
+ [client]
297
+ ),
298
+ ready
299
+ };
300
+ }
301
+
302
+ exports.ConnectorProvider = ConnectorProvider;
303
+ exports.UnifiedProvider = UnifiedProvider;
304
+ exports.useAccount = useAccount;
305
+ exports.useCluster = useCluster;
306
+ exports.useConnector = useConnector;
307
+ exports.useConnectorClient = useConnectorClient;
308
+ exports.useGillSolanaClient = useGillSolanaClient;
309
+ exports.useGillTransactionSigner = useGillTransactionSigner;
310
+ exports.useTransactionPreparer = useTransactionPreparer;
311
+ exports.useTransactionSigner = useTransactionSigner;
312
+ exports.useWalletInfo = useWalletInfo;
313
+ //# sourceMappingURL=chunk-SGAIPK7Q.js.map
314
+ //# sourceMappingURL=chunk-SGAIPK7Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/connector-provider.tsx","../src/ui/unified-provider.tsx","../src/hooks/use-cluster.ts","../src/hooks/use-account.ts","../src/hooks/use-wallet-info.ts","../src/hooks/use-transaction-signer.ts","../src/hooks/use-gill-transaction-signer.ts","../src/hooks/use-gill-solana-client.ts","../src/hooks/use-transaction-preparer.ts"],"names":["createLogger","installPolyfills","createContext","useRef","React","ConnectorClient","jsx","ConnectorErrorBoundary","useContext","useSyncExternalStore","useMemo","isMainnetCluster","isDevnetCluster","isTestnetCluster","isLocalCluster","getClusterExplorerUrl","getClusterType","useState","formatAddress","useCallback","copyAddressToClipboard","createTransactionSigner","createGillTransactionSigner","logger","createSolanaClient","NetworkError","prepareTransaction"],"mappings":"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","file":"chunk-SGAIPK7Q.js","sourcesContent":["'use client';\n\nimport React, { createContext, useContext, useMemo, useRef, useSyncExternalStore } from 'react';\nimport type { ReactNode } from 'react';\nimport { ConnectorClient } from '../lib/core/connector-client';\nimport type { ConnectorConfig } from '../types/connector';\nimport type { ExtendedConnectorConfig } from '../config/default-config';\nimport { ConnectorErrorBoundary } from './error-boundary';\nimport { installPolyfills } from '../lib/utils/polyfills';\nimport { createLogger } from '../lib/utils/secure-logger';\n\nconst logger = createLogger('ConnectorProvider');\n\n// Install browser compatibility polyfills immediately when module loads\n// This ensures crypto operations work across all browser environments\ninstallPolyfills();\n\n// Global connector client declaration for auto-detection\ndeclare global {\n interface Window {\n __connectorClient?: ConnectorClient;\n }\n}\n\nexport type ConnectorSnapshot = ReturnType<ConnectorClient['getSnapshot']> & {\n select: (walletName: string) => Promise<void>;\n disconnect: () => Promise<void>;\n selectAccount: (address: string) => Promise<void>;\n};\n\nexport const ConnectorContext = createContext<ConnectorClient | null>(null);\nConnectorContext.displayName = 'ConnectorContext';\n\nexport interface MobileWalletAdapterConfig {\n appIdentity: {\n name: string;\n uri?: string;\n icon?: string;\n };\n remoteHostAuthority?: string;\n chains?: readonly string[];\n authorizationCache?: unknown;\n chainSelector?: unknown;\n onWalletNotFound?: (wallet: unknown) => Promise<void>;\n}\n\n// Internal provider without error boundary\nfunction ConnectorProviderInternal({\n children,\n config,\n mobile,\n}: {\n children: ReactNode;\n config?: ConnectorConfig;\n mobile?: MobileWalletAdapterConfig;\n}) {\n const clientRef = useRef<ConnectorClient | null>(null);\n\n // Lazy initialization - only create client once on first render\n // This prevents double-initialization in React 19 strict mode\n const getClient = React.useCallback(() => {\n if (!clientRef.current) {\n try {\n clientRef.current = new ConnectorClient(config);\n\n // ✅ Set window.__connectorClient IMMEDIATELY for auto-detection\n if (typeof window !== 'undefined') {\n window.__connectorClient = clientRef.current;\n }\n\n // Log successful initialization in debug mode\n if (config?.debug) {\n logger.info('Client initialized successfully');\n }\n } catch (error) {\n const err = error as Error;\n logger.error('Failed to initialize client', { error: err });\n\n // Call config error handler if provided\n const extendedConfig = config as ExtendedConnectorConfig;\n if (extendedConfig?.errorBoundary?.onError) {\n extendedConfig.errorBoundary.onError(err, {\n componentStack: 'client-initialization',\n digest: `constructor-${new Date().toISOString()}`,\n });\n }\n\n // Return null to allow graceful degradation\n // Components can check for null client and show fallback UI\n return null;\n }\n }\n return clientRef.current;\n }, [config]);\n\n // Get client reference (memoized)\n const client = getClient();\n\n // On client mount, ensure wallet detection runs (run only once)\n React.useEffect(() => {\n const currentClient = clientRef.current;\n\n if (currentClient) {\n // Force re-initialization if client was created during SSR\n // This ensures wallets are detected even if client was created before window existed\n const privateClient = currentClient as unknown as { initialize?: () => void };\n if (privateClient.initialize && typeof privateClient.initialize === 'function') {\n privateClient.initialize();\n }\n }\n\n return () => {\n // Cleanup global reference and client on unmount\n if (typeof window !== 'undefined') {\n window.__connectorClient = undefined;\n }\n if (currentClient && typeof currentClient.destroy === 'function') {\n currentClient.destroy();\n }\n };\n }, []); // Empty dependency array - run only once\n\n // Optionally register Mobile Wallet Adapter on the client\n React.useEffect(() => {\n if (!mobile) return;\n let cancelled = false;\n (async () => {\n try {\n const mod = (await import(\n '@solana-mobile/wallet-standard-mobile'\n )) as typeof import('@solana-mobile/wallet-standard-mobile');\n if (cancelled) return;\n const {\n registerMwa,\n createDefaultAuthorizationCache,\n createDefaultChainSelector,\n createDefaultWalletNotFoundHandler,\n } = mod;\n const defaultChains: readonly `${string}:${string}`[] = [\n 'solana:mainnet',\n 'solana:devnet',\n 'solana:testnet',\n ];\n registerMwa({\n appIdentity: mobile.appIdentity,\n authorizationCache: mobile.authorizationCache ?? (createDefaultAuthorizationCache() as any),\n chains: (mobile.chains ?? defaultChains) as `${string}:${string}`[],\n chainSelector: mobile.chainSelector ?? (createDefaultChainSelector() as any),\n remoteHostAuthority: mobile.remoteHostAuthority,\n onWalletNotFound: mobile.onWalletNotFound ?? createDefaultWalletNotFoundHandler(),\n });\n } catch (e) {\n // Failed to register Mobile Wallet Adapter\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [mobile]);\n\n return <ConnectorContext.Provider value={client}>{children}</ConnectorContext.Provider>;\n}\n\n// Enhanced provider with optional error boundary\nexport function ConnectorProvider({\n children,\n config,\n mobile,\n}: {\n children: ReactNode;\n config?: ExtendedConnectorConfig;\n mobile?: MobileWalletAdapterConfig;\n}) {\n const extendedConfig = config as ExtendedConnectorConfig;\n const errorBoundaryConfig = extendedConfig?.errorBoundary;\n\n // If error boundary is disabled, use internal provider directly\n if (!errorBoundaryConfig?.enabled) {\n return (\n <ConnectorProviderInternal config={config} mobile={mobile}>\n {children}\n </ConnectorProviderInternal>\n );\n }\n\n // Wrap with error boundary for enhanced error handling\n return (\n <ConnectorErrorBoundary\n maxRetries={errorBoundaryConfig.maxRetries ?? 3}\n onError={errorBoundaryConfig.onError}\n fallback={errorBoundaryConfig.fallback}\n >\n <ConnectorProviderInternal config={config} mobile={mobile}>\n {children}\n </ConnectorProviderInternal>\n </ConnectorErrorBoundary>\n );\n}\n\nexport function useConnector(): ConnectorSnapshot {\n const client = useContext(ConnectorContext);\n if (!client) {\n throw new Error(\n 'useConnector must be used within ConnectorProvider. ' +\n 'Wrap your app with <ConnectorProvider> or <UnifiedProvider> to use connector hooks.',\n );\n }\n\n // Subscribe to state changes\n const state = useSyncExternalStore(\n React.useCallback(cb => client.subscribe(cb), [client]),\n React.useCallback(() => client.getSnapshot(), [client]),\n React.useCallback(() => client.getSnapshot(), [client]),\n );\n\n // Stable method references that don't change when state changes\n // These are bound once and reused across renders\n const methods = useMemo(\n () => ({\n select: client.select.bind(client),\n disconnect: client.disconnect.bind(client),\n selectAccount: client.selectAccount.bind(client),\n }),\n [client],\n );\n\n // Optimized: Only create new object when state actually changes\n return useMemo(\n () => ({\n ...state,\n ...methods,\n }),\n [state, methods],\n );\n}\n\n/**\n * Get the connector client instance\n * Returns null if not within ConnectorProvider or if initialization failed\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useConnectorClient()\n *\n * if (!client) {\n * return <div>Connector not available</div>\n * }\n *\n * // Use client methods directly\n * const health = client.getHealth()\n * }\n * ```\n */\nexport function useConnectorClient(): ConnectorClient | null {\n return useContext(ConnectorContext);\n}\n","'use client';\n\nimport type { ReactNode, ComponentType, PropsWithChildren } from 'react';\nimport { ConnectorProvider } from './connector-provider';\nimport type { MobileWalletAdapterConfig } from './connector-provider';\nimport type { ConnectorConfig } from '../types/connector';\nimport type { UnifiedConfig } from '../config/unified-config';\n\nexport interface UnifiedProviderProps {\n children: ReactNode;\n\n // NEW: Option 1 - Pass UnifiedConfig directly (recommended)\n config?: UnifiedConfig;\n\n // OLD: Option 2 - Pass configs separately (backward compatible)\n connectorConfig?: ConnectorConfig;\n mobile?: MobileWalletAdapterConfig;\n\n // Optional additional providers to wrap around children\n providers?: Array<{\n component: ComponentType<PropsWithChildren>;\n props?: Record<string, unknown>;\n }>;\n}\n\nexport function UnifiedProvider({ children, config, connectorConfig, mobile, providers = [] }: UnifiedProviderProps) {\n // Handle both new and old patterns\n const actualConnectorConfig = config?.connectorConfig ?? connectorConfig;\n const actualMobile = config?.mobile ?? mobile;\n\n // Start with connector provider as the base\n let content = (\n <ConnectorProvider config={actualConnectorConfig} mobile={actualMobile}>\n {children}\n </ConnectorProvider>\n );\n\n // Wrap with additional providers in reverse order\n // so they nest properly (first provider is outermost)\n for (let i = providers.length - 1; i >= 0; i--) {\n const { component: Provider, props = {} } = providers[i];\n content = <Provider {...props}>{content}</Provider>;\n }\n\n return content;\n}\n\n// Export with practical alias\nexport { UnifiedProvider as AppProvider };\n","/**\n * @solana/connector - useCluster hook\n *\n * React hook for managing Solana cluster (network) state\n */\n\n'use client';\n\nimport { useMemo } from 'react';\nimport type { SolanaCluster, SolanaClusterId } from '@wallet-ui/core';\nimport { useConnector, useConnectorClient } from '../ui/connector-provider';\nimport {\n getClusterExplorerUrl,\n isMainnetCluster,\n isDevnetCluster,\n isTestnetCluster,\n isLocalCluster,\n getClusterType,\n type ClusterType,\n} from '../utils/cluster';\n\nexport interface UseClusterReturn {\n /** Currently active cluster */\n cluster: SolanaCluster | null;\n /** All available clusters */\n clusters: SolanaCluster[];\n /** Set the active cluster */\n setCluster: (id: SolanaClusterId) => Promise<void>;\n /** Whether the current cluster is mainnet */\n isMainnet: boolean;\n /** Whether the current cluster is devnet */\n isDevnet: boolean;\n /** Whether the current cluster is testnet */\n isTestnet: boolean;\n /** Whether the current cluster is running locally */\n isLocal: boolean;\n /** Solana Explorer base URL for the current cluster */\n explorerUrl: string;\n /** Cluster type (mainnet, devnet, testnet, localnet, custom) */\n type: ClusterType | null;\n}\n\n/**\n * Hook for managing Solana cluster (network) selection\n *\n * @example\n * ```tsx\n * function ClusterSwitcher() {\n * const { cluster, clusters, setCluster, isMainnet } = useCluster()\n *\n * return (\n * <select\n * value={cluster?.id}\n * onChange={(e) => setCluster(e.target.value as SolanaClusterId)}\n * >\n * {clusters.map(c => (\n * <option key={c.id} value={c.id}>{c.label}</option>\n * ))}\n * </select>\n * )\n * }\n * ```\n */\nexport function useCluster(): UseClusterReturn {\n const { cluster, clusters } = useConnector();\n const client = useConnectorClient();\n\n if (!client) {\n throw new Error('useCluster must be used within ConnectorProvider');\n }\n\n const setCluster = useMemo(\n () => async (id: SolanaClusterId) => {\n await client.setCluster(id);\n },\n [client],\n );\n\n return useMemo(() => {\n const isMainnet = cluster ? isMainnetCluster(cluster) : false;\n const isDevnet = cluster ? isDevnetCluster(cluster) : false;\n const isTestnet = cluster ? isTestnetCluster(cluster) : false;\n const isLocal = cluster ? isLocalCluster(cluster) : false;\n const explorerUrl = cluster ? getClusterExplorerUrl(cluster) : '';\n const type = cluster ? getClusterType(cluster) : null;\n\n return {\n cluster,\n clusters,\n setCluster,\n isMainnet,\n isDevnet,\n isTestnet,\n isLocal,\n explorerUrl,\n type,\n };\n }, [cluster, clusters, setCluster]);\n}\n","/**\n * @solana/connector - useAccount hook\n *\n * React hook for working with the connected wallet account\n */\n\n'use client';\n\nimport React, { useState, useCallback, useMemo } from 'react';\nimport { useConnector } from '../ui/connector-provider';\nimport { copyAddressToClipboard, formatAddress, ClipboardErrorType, type ClipboardResult } from '../utils';\nimport type { AccountInfo } from '../types/accounts';\nimport { COPY_FEEDBACK_DURATION_MS } from '../lib/constants';\n\nexport interface UseAccountReturn {\n /** The connected wallet address */\n address: string | null;\n /** Full account info object */\n account: AccountInfo | null;\n /** Whether a wallet is connected */\n connected: boolean;\n /** Shortened formatted address for display */\n formatted: string;\n /** Copy the address to clipboard with enhanced result */\n copy: () => Promise<ClipboardResult>;\n /** Whether the address was recently copied */\n copied: boolean;\n /** All available accounts from the connected wallet */\n accounts: AccountInfo[];\n /** Select a different account from the connected wallet */\n selectAccount: (address: string) => Promise<void>;\n}\n\n/**\n * Hook for working with the connected wallet account\n * Provides formatted address, clipboard copying, and account selection\n *\n * @example\n * ```tsx\n * function AccountDisplay() {\n * const { address, formatted, copy, copied, connected } = useAccount()\n *\n * if (!connected) return <p>Not connected</p>\n *\n * return (\n * <button onClick={copy}>\n * {formatted} {copied && '✓'}\n * </button>\n * )\n * }\n * ```\n */\nexport function useAccount(): UseAccountReturn {\n const { selectedAccount, accounts, connected, selectAccount } = useConnector();\n const [copied, setCopied] = useState(false);\n const copyTimeoutRef = React.useRef<NodeJS.Timeout | undefined>(undefined);\n\n const account = useMemo(\n () => accounts.find((a: AccountInfo) => a.address === selectedAccount) ?? null,\n [accounts, selectedAccount],\n );\n\n const formatted = useMemo(() => (selectedAccount ? formatAddress(selectedAccount) : ''), [selectedAccount]);\n\n const copy = useCallback(async (): Promise<ClipboardResult> => {\n if (!selectedAccount) {\n return {\n success: false,\n error: ClipboardErrorType.EMPTY_VALUE,\n errorMessage: 'No account selected',\n };\n }\n\n if (copyTimeoutRef.current) {\n clearTimeout(copyTimeoutRef.current);\n }\n\n const result = await copyAddressToClipboard(selectedAccount, {\n onSuccess: () => {\n setCopied(true);\n copyTimeoutRef.current = setTimeout(() => setCopied(false), COPY_FEEDBACK_DURATION_MS);\n },\n });\n\n return result;\n }, [selectedAccount]);\n\n React.useEffect(() => {\n return () => {\n if (copyTimeoutRef.current) {\n clearTimeout(copyTimeoutRef.current);\n }\n };\n }, []);\n\n return useMemo(\n () => ({\n address: selectedAccount,\n account,\n connected,\n formatted,\n copy,\n copied,\n accounts,\n selectAccount,\n }),\n [selectedAccount, account, connected, formatted, copy, copied, accounts, selectAccount],\n );\n}\n","/**\n * @solana/connector - useWalletInfo hook\n *\n * React hook for getting information about the connected wallet\n */\n\n'use client';\n\nimport { useMemo } from 'react';\nimport { useConnector } from '../ui/connector-provider';\nimport type { WalletInfo } from '../types/wallets';\n\n/**\n * Simplified wallet information for display purposes\n */\nexport interface WalletDisplayInfo {\n /** Wallet name */\n name: string;\n /** Wallet icon/logo URL if available */\n icon?: string;\n /** Whether the wallet extension is installed */\n installed: boolean;\n /** Whether the wallet supports Solana connections */\n connectable?: boolean;\n}\n\n/**\n * Return value from useWalletInfo hook\n */\nexport interface UseWalletInfoReturn {\n /** Name of the connected wallet (e.g., 'Phantom', 'Solflare') */\n name: string | null;\n /** Wallet icon/logo URL if available */\n icon: string | null;\n /** Whether the wallet extension is installed */\n installed: boolean;\n /** Whether the wallet supports Solana connections */\n connectable: boolean;\n /** Whether currently connected to the wallet */\n connected: boolean;\n /** Whether a connection attempt is in progress */\n connecting: boolean;\n /** All available wallets */\n wallets: WalletDisplayInfo[];\n}\n\n/**\n * Hook for getting information about the connected wallet\n * Provides wallet metadata, connection status, and capabilities\n *\n * @example\n * ```tsx\n * function WalletBadge() {\n * const { name, icon, connected, connecting } = useWalletInfo()\n *\n * if (connecting) return <p>Connecting...</p>\n * if (!connected) return <p>No wallet connected</p>\n *\n * return (\n * <div>\n * {icon && <img src={icon} alt={name} />}\n * <span>{name}</span>\n * </div>\n * )\n * }\n * ```\n */\nexport function useWalletInfo(): UseWalletInfoReturn {\n const { selectedWallet, wallets, connected, connecting } = useConnector();\n\n // Map WalletInfo[] to WalletDisplayInfo[] for simplified consumption\n const mappedWallets = useMemo<WalletDisplayInfo[]>(\n () =>\n wallets.map(\n (walletInfo: WalletInfo): WalletDisplayInfo => ({\n name: walletInfo.wallet.name,\n icon: walletInfo.wallet.icon,\n installed: walletInfo.installed,\n connectable: walletInfo.connectable,\n }),\n ),\n [wallets],\n );\n\n // Extract information about the currently selected wallet\n const selectedWalletInfo = useMemo(() => {\n if (!selectedWallet) {\n return {\n name: null,\n icon: null,\n installed: false,\n connectable: false,\n };\n }\n\n // Find the WalletInfo for the selected wallet\n const walletInfo = wallets.find((w: WalletInfo) => w.wallet.name === selectedWallet.name);\n\n return {\n name: selectedWallet.name,\n icon: selectedWallet.icon ?? null,\n installed: walletInfo?.installed ?? false,\n connectable: walletInfo?.connectable ?? false,\n };\n }, [selectedWallet, wallets]);\n\n return useMemo(\n () => ({\n ...selectedWalletInfo,\n connected,\n connecting,\n wallets: mappedWallets,\n }),\n [selectedWalletInfo, connected, connecting, mappedWallets],\n );\n}\n","/**\n * @solana/connector - useTransactionSigner hook\n *\n * React hook for transaction signing operations\n * Provides a clean interface for signing and sending transactions\n * with automatic signer creation and lifecycle management\n */\n\n'use client';\n\nimport { useMemo } from 'react';\nimport { useConnector } from '../ui/connector-provider';\nimport { useConnectorClient } from '../ui/connector-provider';\nimport { createTransactionSigner, type TransactionSigner } from '../lib/transaction/transaction-signer';\nimport type { TransactionSignerCapabilities } from '../types/transactions';\n\n/**\n * Return value from useTransactionSigner hook\n */\nexport interface UseTransactionSignerReturn {\n /**\n * Transaction signer instance (null if not connected)\n * Use this to sign and send transactions\n */\n signer: TransactionSigner | null;\n\n /**\n * Whether a signer is available and ready to use\n * Useful for disabling transaction buttons\n */\n ready: boolean;\n\n /**\n * Current wallet address that will sign transactions\n * Null if no wallet connected\n */\n address: string | null;\n\n /**\n * Signer capabilities (what operations are supported)\n * Always available even if signer is null (shows all false)\n */\n capabilities: TransactionSignerCapabilities;\n}\n\n/**\n * Hook for transaction signing operations\n *\n * Automatically creates a TransactionSigner when a wallet is connected,\n * and provides convenient state for building transaction UIs.\n *\n * The signer is automatically recreated when:\n * - Wallet connection state changes\n * - Selected account changes\n * - Active cluster/network changes\n *\n * @example\n * ```tsx\n * function SendTransaction() {\n * const { signer, ready, capabilities } = useTransactionSigner()\n * const [txSignature, setTxSignature] = useState<string | null>(null)\n * const [error, setError] = useState<string | null>(null)\n *\n * const handleSend = async () => {\n * if (!signer) return\n *\n * try {\n * const signature = await signer.signAndSendTransaction(transaction)\n * setTxSignature(signature)\n * setError(null)\n * } catch (err) {\n * setError(err instanceof Error ? err.message : 'Transaction failed')\n * }\n * }\n *\n * return (\n * <div>\n * <button onClick={handleSend} disabled={!ready}>\n * {ready ? 'Send Transaction' : 'Connect Wallet'}\n * </button>\n *\n * {!capabilities.canSend && ready && (\n * <p className=\"warning\">\n * Your wallet doesn't support direct sending.\n * Transaction must be signed and broadcast separately.\n * </p>\n * )}\n *\n * {txSignature && (\n * <p>Transaction sent: {txSignature}</p>\n * )}\n *\n * {error && (\n * <p className=\"error\">{error}</p>\n * )}\n * </div>\n * )\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Using with multiple transactions\n * function SendBatch() {\n * const { signer, ready, capabilities } = useTransactionSigner()\n *\n * const handleSendBatch = async () => {\n * if (!signer) return\n *\n * const transactions = [tx1, tx2, tx3]\n *\n * // Check if batch signing is supported\n * if (capabilities.supportsBatchSigning) {\n * // More efficient: sign all at once\n * const signed = await signer.signAllTransactions(transactions)\n * // ... send signed transactions\n * } else {\n * // Fallback: sign and send one by one\n * const signatures = await signer.signAndSendTransactions(transactions)\n * console.log('All sent:', signatures)\n * }\n * }\n *\n * return (\n * <button onClick={handleSendBatch} disabled={!ready}>\n * Send {capabilities.supportsBatchSigning ? 'Batch' : 'Sequential'}\n * </button>\n * )\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Using with message signing for authentication\n * function SignInWithWallet() {\n * const { signer, ready, capabilities } = useTransactionSigner()\n *\n * const handleSignIn = async () => {\n * if (!signer || !capabilities.canSignMessage) {\n * alert('Wallet does not support message signing')\n * return\n * }\n *\n * const message = new TextEncoder().encode('Sign in to MyApp')\n * const signature = await signer.signMessage!(message)\n *\n * // Send signature to backend for verification\n * await fetch('/api/auth/verify', {\n * method: 'POST',\n * body: JSON.stringify({\n * message: Array.from(message),\n * signature: Array.from(signature),\n * address: signer.address\n * })\n * })\n * }\n *\n * if (!capabilities.canSignMessage) {\n * return <p>Message signing not supported</p>\n * }\n *\n * return (\n * <button onClick={handleSignIn} disabled={!ready}>\n * Sign In with Wallet\n * </button>\n * )\n * }\n * ```\n */\nexport function useTransactionSigner(): UseTransactionSignerReturn {\n const { selectedWallet, selectedAccount, accounts, cluster, connected } = useConnector();\n const client = useConnectorClient();\n\n const account = useMemo(\n () => accounts.find(a => a.address === selectedAccount)?.raw ?? null,\n [accounts, selectedAccount],\n );\n\n const signer = useMemo(() => {\n if (!connected || !selectedWallet || !account) {\n return null;\n }\n\n return createTransactionSigner({\n wallet: selectedWallet,\n account,\n cluster: cluster ?? undefined,\n eventEmitter: client\n ? {\n emit: (event: unknown) => {\n // Use the public emitEvent method\n client.emitEvent(event as import('../types/events').ConnectorEvent);\n },\n }\n : undefined,\n });\n }, [connected, selectedWallet, account, cluster, client]);\n\n const capabilities = useMemo(\n () =>\n signer?.getCapabilities() ?? {\n canSign: false,\n canSend: false,\n canSignMessage: false,\n supportsBatchSigning: false,\n },\n [signer],\n );\n\n return {\n signer,\n ready: Boolean(signer),\n address: selectedAccount,\n capabilities,\n };\n}\n","/**\n * @solana/connector - useGillTransactionSigner hook\n *\n * React hook for gill-compatible transaction signing\n * Use this when working with modern Solana libraries (@solana/kit, gill)\n */\n\n'use client';\n\nimport { useMemo } from 'react';\nimport type { TransactionModifyingSigner } from 'gill';\nimport { useTransactionSigner } from './use-transaction-signer';\nimport { createGillTransactionSigner } from '../lib/transaction/gill-transaction-signer';\n\n/**\n * Return value from useGillTransactionSigner hook\n */\nexport interface UseGillTransactionSignerReturn {\n /**\n * Gill-compatible TransactionModifyingSigner instance (null if not connected)\n * Use this with modern Solana libraries (@solana/kit, gill)\n */\n signer: TransactionModifyingSigner | null;\n\n /**\n * Whether a signer is available and ready to use\n * Useful for disabling transaction buttons\n */\n ready: boolean;\n}\n\n/**\n * Hook for gill-compatible transaction signing\n *\n * Creates a TransactionPartialSigner that's compatible with @solana/kit and gill,\n * enabling seamless integration with modern Solana development patterns.\n *\n * This hook wraps the standard useTransactionSigner and adapts it to gill's\n * interface, allowing you to use modern libraries without type incompatibilities.\n *\n * @example\n * ```tsx\n * import { useGillTransactionSigner } from '@solana/connector';\n * import { getTransferSolInstruction } from 'gill/programs';\n * import { address, pipe, createTransactionMessage } from 'gill';\n *\n * function ModernTransfer() {\n * const { signer, ready } = useGillTransactionSigner();\n *\n * const handleTransfer = async (recipient: string, amount: number) => {\n * if (!signer) return;\n *\n * // Fully type-safe with gill!\n * const instruction = getTransferSolInstruction({\n * source: signer, // No type errors\n * destination: address(recipient),\n * amount\n * });\n *\n * const txMessage = pipe(\n * createTransactionMessage({ version: 0 }),\n * (tx) => setTransactionMessageFeePayerSigner(signer, tx), // Works!\n * // ...\n * );\n * };\n *\n * return (\n * <button onClick={handleTransfer} disabled={!ready}>\n * Send with Gill\n * </button>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // For backward compatibility, continue using useTransactionSigner\n * import { useTransactionSigner } from '@solana/connector';\n *\n * function LegacyTransfer() {\n * const { signer } = useTransactionSigner(); // Wallet adapter compatible\n * // Works with @solana/web3.js v1 and wallet-adapter\n * }\n * ```\n */\nexport function useGillTransactionSigner(): UseGillTransactionSignerReturn {\n const { signer: connectorSigner, ready } = useTransactionSigner();\n\n const gillSigner = useMemo(() => {\n if (!connectorSigner) return null;\n return createGillTransactionSigner(connectorSigner);\n }, [connectorSigner]);\n\n return {\n signer: gillSigner,\n ready,\n };\n}\n","/**\n * @solana/connector - useGillSolanaClient hook\n *\n * React hook for Gill's SolanaClient with built-in RPC and WebSocket subscriptions\n * Provides rpc, rpcSubscriptions, sendAndConfirmTransaction, and simulateTransaction\n */\n\n'use client';\n\nimport { useMemo } from 'react';\nimport { createSolanaClient, type SolanaClient, type ModifiedClusterUrl } from 'gill';\nimport { useCluster } from './use-cluster';\nimport { useConnectorClient } from '../ui/connector-provider';\nimport type { ClusterType } from '../utils/cluster';\nimport { createLogger } from '../lib/utils/secure-logger';\n\nconst logger = createLogger('useGillSolanaClient');\n\n/**\n * Return value from useGillSolanaClient hook\n */\nexport interface UseGillSolanaClientReturn {\n /**\n * Gill SolanaClient instance with RPC and subscriptions (null if not available)\n * Includes: rpc, rpcSubscriptions, sendAndConfirmTransaction, simulateTransaction\n */\n client: SolanaClient | null;\n\n /**\n * Whether a client is available and ready to use\n */\n ready: boolean;\n\n /**\n * Cluster type (mainnet, devnet, testnet, localnet, custom)\n */\n clusterType: ClusterType | null;\n}\n\n/**\n * Hook for Gill's SolanaClient with automatic RPC and WebSocket subscription management\n *\n * Creates a fully configured SolanaClient based on the current cluster, providing:\n * - Type-safe RPC client\n * - WebSocket subscription client\n * - Built-in sendAndConfirmTransaction helper\n * - Built-in simulateTransaction helper\n *\n * The client is automatically recreated when the cluster changes.\n *\n * @example\n * ```tsx\n * import { useGillSolanaClient, useGillTransactionSigner } from '@solana/connector';\n * import { signTransactionMessageWithSigners } from 'gill';\n *\n * function SendTransaction() {\n * const { client, ready } = useGillSolanaClient();\n * const { signer } = useGillTransactionSigner();\n *\n * const handleSend = async (transaction) => {\n * if (!client || !signer) return;\n *\n * // Sign the transaction\n * const signed = await signTransactionMessageWithSigners(transaction);\n *\n * // Send and confirm using Gill's built-in helper\n * await client.sendAndConfirmTransaction(signed, {\n * commitment: 'confirmed'\n * });\n * };\n *\n * return (\n * <button onClick={handleSend} disabled={!ready}>\n * Send Transaction\n * </button>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Simulating a transaction\n * function SimulateTransaction() {\n * const { client } = useGillSolanaClient();\n *\n * const handleSimulate = async (transaction) => {\n * if (!client) return;\n *\n * const simulation = await client.simulateTransaction(transaction, {\n * sigVerify: false,\n * commitment: 'processed'\n * });\n *\n * console.log('Simulation result:', simulation);\n * };\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Direct RPC access\n * function GetBalance() {\n * const { client } = useGillSolanaClient();\n *\n * const fetchBalance = async (address: Address) => {\n * if (!client) return;\n *\n * const balance = await client.rpc.getBalance(address).send();\n * console.log('Balance:', balance);\n * };\n * }\n * ```\n */\nexport function useGillSolanaClient(): UseGillSolanaClientReturn {\n const { type } = useCluster();\n const connectorClient = useConnectorClient();\n\n const client = useMemo(() => {\n if (!type || !connectorClient) return null;\n\n try {\n // For non-custom clusters, use moniker\n if (type !== 'custom') {\n return createSolanaClient({\n urlOrMoniker: type,\n });\n }\n\n // For custom clusters, get RPC URL from connector client\n const rpcUrl = connectorClient.getRpcUrl();\n if (!rpcUrl) return null;\n\n return createSolanaClient({\n urlOrMoniker: rpcUrl as ModifiedClusterUrl,\n });\n } catch (error) {\n logger.error('Failed to create Gill Solana client', { error });\n return null;\n }\n }, [type, connectorClient]);\n\n return {\n client,\n ready: Boolean(client),\n clusterType: type,\n };\n}\n","/**\n * @solana/connector - useTransactionPreparer hook\n *\n * React hook for preparing transactions with automatic optimization\n * Handles blockhash fetching, compute unit limits, and transaction simulation\n */\n\n'use client';\n\nimport { useCallback } from 'react';\nimport {\n prepareTransaction,\n type PrepareTransactionConfig,\n type CompilableTransactionMessage,\n type TransactionMessageWithBlockhashLifetime,\n} from 'gill';\nimport { useGillSolanaClient } from './use-gill-solana-client';\nimport { NetworkError } from '../lib/errors';\n\n/**\n * Options for transaction preparation\n */\nexport interface TransactionPrepareOptions {\n /**\n * Multiplier applied to the simulated compute unit value\n * @default 1.1 (10% buffer)\n */\n computeUnitLimitMultiplier?: number;\n\n /**\n * Whether to force reset the compute unit limit value (if one is already set)\n * using the simulation response and computeUnitLimitMultiplier\n * @default false\n */\n computeUnitLimitReset?: boolean;\n\n /**\n * Whether to force reset the latest blockhash (if one is already set)\n * @default true\n */\n blockhashReset?: boolean;\n}\n\n/**\n * Return value from useTransactionPreparer hook\n */\nexport interface UseTransactionPreparerReturn {\n /**\n * Prepare a transaction for sending\n * Automatically adds:\n * - Compute unit limit (via simulation with optional multiplier)\n * - Latest blockhash (if not already set)\n *\n * @param transaction - The transaction to prepare\n * @param options - Optional preparation settings\n * @returns Prepared transaction with blockhash lifetime set\n */\n prepare: <TMessage extends CompilableTransactionMessage>(\n transaction: TMessage,\n options?: TransactionPrepareOptions,\n ) => Promise<TMessage & TransactionMessageWithBlockhashLifetime>;\n\n /**\n * Whether the preparer is ready to use\n * False if Solana client is not available\n */\n ready: boolean;\n}\n\n/**\n * Hook for preparing transactions with automatic optimization\n *\n * Uses Gill's prepareTransaction utility to:\n * 1. Simulate the transaction to determine optimal compute units\n * 2. Set compute unit limit (with configurable multiplier for safety margin)\n * 3. Fetch and set the latest blockhash (if not already present)\n *\n * This significantly improves transaction landing rates by ensuring proper\n * compute budget allocation and fresh blockhashes.\n *\n * @example\n * ```tsx\n * import { useTransactionPreparer, useGillTransactionSigner } from '@solana/connector';\n * import { pipe, createTransactionMessage, appendTransactionMessageInstructions } from 'gill';\n * import { getTransferSolInstruction } from 'gill/programs';\n *\n * function SendOptimizedTransaction() {\n * const { prepare, ready } = useTransactionPreparer();\n * const { signer } = useGillTransactionSigner();\n * const { client } = useGillSolanaClient();\n *\n * const handleSend = async (recipient: string, amount: bigint) => {\n * if (!ready || !signer || !client) return;\n *\n * // Build transaction message\n * const tx = pipe(\n * createTransactionMessage({ version: 0 }),\n * tx => setTransactionMessageFeePayerSigner(signer, tx),\n * tx => appendTransactionMessageInstructions([\n * getTransferSolInstruction({\n * source: signer,\n * destination: address(recipient),\n * amount: lamports(amount),\n * })\n * ], tx)\n * );\n *\n * // Prepare: auto-adds compute units + blockhash\n * const prepared = await prepare(tx);\n *\n * // Sign\n * const signed = await signTransactionMessageWithSigners(prepared);\n *\n * // Send and confirm\n * await client.sendAndConfirmTransaction(signed);\n * };\n *\n * return (\n * <button onClick={handleSend} disabled={!ready}>\n * Send Optimized Transaction\n * </button>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With custom compute unit multiplier for high-priority transactions\n * const { prepare } = useTransactionPreparer();\n *\n * const prepared = await prepare(transaction, {\n * computeUnitLimitMultiplier: 1.3, // 30% buffer instead of default 10%\n * blockhashReset: true // Always fetch fresh blockhash\n * });\n * ```\n *\n * @example\n * ```tsx\n * // Force reset compute units even if already set\n * const { prepare } = useTransactionPreparer();\n *\n * const prepared = await prepare(transaction, {\n * computeUnitLimitReset: true, // Re-simulate and reset compute units\n * computeUnitLimitMultiplier: 1.2\n * });\n * ```\n */\nexport function useTransactionPreparer(): UseTransactionPreparerReturn {\n const { client, ready } = useGillSolanaClient();\n\n const prepare = useCallback(\n async <TMessage extends CompilableTransactionMessage>(\n transaction: TMessage,\n options: TransactionPrepareOptions = {},\n ): Promise<TMessage & TransactionMessageWithBlockhashLifetime> => {\n if (!client) {\n throw new NetworkError('RPC_ERROR', 'Solana client not available. Cannot prepare transaction.');\n }\n\n return prepareTransaction({\n transaction,\n rpc: client.rpc,\n computeUnitLimitMultiplier: options.computeUnitLimitMultiplier,\n computeUnitLimitReset: options.computeUnitLimitReset,\n blockhashReset: options.blockhashReset,\n });\n },\n [client],\n );\n\n return {\n prepare,\n ready,\n };\n}\n"]}
@@ -0,0 +1,186 @@
1
+ 'use strict';
2
+
3
+ var gill = require('gill');
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key != "symbol" ? key + "" : key, value);
8
+ var SENSITIVE_KEYS = [
9
+ "address",
10
+ "publickey",
11
+ "signature",
12
+ "account",
13
+ "rpcurl",
14
+ "url",
15
+ "apikey",
16
+ "api_key",
17
+ "token",
18
+ "secret",
19
+ "password",
20
+ "private",
21
+ "seed",
22
+ "mnemonic"
23
+ ], LOG_LEVELS = {
24
+ debug: 0,
25
+ info: 1,
26
+ warn: 2,
27
+ error: 3
28
+ }, SecureLogger = class {
29
+ constructor(config = {}) {
30
+ __publicField(this, "config");
31
+ let isDevelopment = typeof process < "u" && process.env?.NODE_ENV === "development";
32
+ this.config = {
33
+ enabled: config.enabled ?? isDevelopment,
34
+ level: config.level ?? "debug",
35
+ redactSensitive: config.redactSensitive ?? !isDevelopment,
36
+ prefix: config.prefix ?? "Connector",
37
+ useGillDebug: config.useGillDebug ?? true
38
+ // Default to using gill's debug system
39
+ };
40
+ }
41
+ /**
42
+ * Log debug information (lowest priority)
43
+ */
44
+ debug(message, data) {
45
+ this.log("debug", message, data);
46
+ }
47
+ /**
48
+ * Log general information
49
+ */
50
+ info(message, data) {
51
+ this.log("info", message, data);
52
+ }
53
+ /**
54
+ * Log warnings
55
+ */
56
+ warn(message, data) {
57
+ this.log("warn", message, data);
58
+ }
59
+ /**
60
+ * Log errors (highest priority)
61
+ */
62
+ error(message, data) {
63
+ this.log("error", message, data);
64
+ }
65
+ /**
66
+ * Internal log method that handles level filtering and redaction
67
+ * Integrates with gill's debug system when enabled
68
+ */
69
+ log(level, message, data) {
70
+ let gillDebugEnabled = this.config.useGillDebug ? gill.isDebugEnabled() : false;
71
+ if (!this.config.enabled && !gillDebugEnabled) return;
72
+ let effectiveLevel = this.config.level;
73
+ if (this.config.useGillDebug && typeof globalThis < "u") {
74
+ let gillLevel = globalThis.__GILL_DEBUG_LEVEL__;
75
+ gillLevel && ["debug", "info", "warn", "error"].includes(gillLevel) && (effectiveLevel = gillLevel);
76
+ }
77
+ if (LOG_LEVELS[level] < LOG_LEVELS[effectiveLevel])
78
+ return;
79
+ let processedData = this.config.redactSensitive ? this.redact(data) : data, fullMessage = processedData !== void 0 ? `${message} ${typeof processedData == "object" ? JSON.stringify(processedData, null, 2) : processedData}` : message;
80
+ if (this.config.useGillDebug && gillDebugEnabled)
81
+ gill.debug(fullMessage, level, this.config.prefix);
82
+ else {
83
+ let prefix = `[${this.config.prefix}]`;
84
+ switch (level) {
85
+ case "debug":
86
+ console.debug(prefix, message, processedData !== void 0 ? processedData : "");
87
+ break;
88
+ case "info":
89
+ console.info(prefix, message, processedData !== void 0 ? processedData : "");
90
+ break;
91
+ case "warn":
92
+ console.warn(prefix, message, processedData !== void 0 ? processedData : "");
93
+ break;
94
+ case "error":
95
+ console.error(prefix, message, processedData !== void 0 ? processedData : "");
96
+ break;
97
+ }
98
+ }
99
+ }
100
+ /**
101
+ * Recursively redact sensitive information from data
102
+ */
103
+ redact(data) {
104
+ if (data == null || typeof data != "object")
105
+ return data;
106
+ if (Array.isArray(data))
107
+ return data.map((item) => this.redact(item));
108
+ let redacted = {};
109
+ for (let [key, value] of Object.entries(data)) {
110
+ let keyLower = key.toLowerCase();
111
+ SENSITIVE_KEYS.some((sensitiveKey) => keyLower.includes(sensitiveKey)) ? redacted[key] = this.maskValue(value) : typeof value == "object" && value !== null ? redacted[key] = this.redact(value) : redacted[key] = value;
112
+ }
113
+ return redacted;
114
+ }
115
+ /**
116
+ * Mask a sensitive value for logging
117
+ * Shows first 4 and last 4 characters for strings longer than 8 chars
118
+ */
119
+ maskValue(value) {
120
+ if (value == null)
121
+ return "***";
122
+ let str = String(value);
123
+ return str.length <= 8 ? "***" : `${str.slice(0, 4)}...${str.slice(-4)}`;
124
+ }
125
+ /**
126
+ * Update logger configuration at runtime
127
+ */
128
+ updateConfig(config) {
129
+ this.config = { ...this.config, ...config };
130
+ }
131
+ /**
132
+ * Get current configuration
133
+ */
134
+ getConfig() {
135
+ return { ...this.config };
136
+ }
137
+ }; new SecureLogger({
138
+ prefix: "Connector"
139
+ });
140
+ function createLogger(prefix, config) {
141
+ return new SecureLogger({ ...config, prefix });
142
+ }
143
+
144
+ // src/utils/transaction-format.ts
145
+ function isWeb3jsTransaction(tx) {
146
+ return tx !== null && typeof tx == "object" && "serialize" in tx && typeof tx.serialize == "function";
147
+ }
148
+ function serializeTransaction(tx) {
149
+ if (isWeb3jsTransaction(tx))
150
+ return tx.serialize({
151
+ requireAllSignatures: false,
152
+ verifySignatures: false
153
+ });
154
+ if (tx instanceof Uint8Array)
155
+ return tx;
156
+ if (ArrayBuffer.isView(tx))
157
+ return new Uint8Array(tx.buffer, tx.byteOffset, tx.byteLength);
158
+ throw new Error("Unsupported transaction format - must be Transaction, VersionedTransaction, or Uint8Array");
159
+ }
160
+ function isLegacyTransaction(bytes) {
161
+ return bytes.length === 0 ? false : (bytes[0] & 128) === 0;
162
+ }
163
+ async function deserializeToWeb3jsTransaction(bytes) {
164
+ if (isLegacyTransaction(bytes)) {
165
+ let { Transaction } = await import('@solana/web3.js');
166
+ return Transaction.from(bytes);
167
+ } else {
168
+ let { VersionedTransaction } = await import('@solana/web3.js');
169
+ return VersionedTransaction.deserialize(bytes);
170
+ }
171
+ }
172
+ function prepareTransactionForWallet(tx) {
173
+ let wasWeb3js = isWeb3jsTransaction(tx);
174
+ return { serialized: serializeTransaction(tx), wasWeb3js };
175
+ }
176
+ async function convertSignedTransaction(signedBytes, wasWeb3js) {
177
+ return wasWeb3js ? await deserializeToWeb3jsTransaction(signedBytes) : signedBytes;
178
+ }
179
+
180
+ exports.__publicField = __publicField;
181
+ exports.convertSignedTransaction = convertSignedTransaction;
182
+ exports.createLogger = createLogger;
183
+ exports.isWeb3jsTransaction = isWeb3jsTransaction;
184
+ exports.prepareTransactionForWallet = prepareTransactionForWallet;
185
+ //# sourceMappingURL=chunk-SMUUAKC3.js.map
186
+ //# sourceMappingURL=chunk-SMUUAKC3.js.map