@openzeppelin/ui-react 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index-B_dOGVNW.d.ts","names":[],"sources":["../src/hooks/AdapterContext.tsx","../src/hooks/AdapterProvider.tsx","../src/hooks/WalletStateContext.tsx","../src/hooks/WalletStateProvider.tsx","../src/hooks/AnalyticsContext.tsx","../src/hooks/AnalyticsProvider.tsx","../src/hooks/useAnalytics.ts","../src/hooks/useAdapterContext.ts","../src/hooks/useDerivedAccountStatus.ts","../src/hooks/useDerivedSwitchChainStatus.ts","../src/hooks/useDerivedChainInfo.ts","../src/hooks/useDerivedConnectStatus.ts","../src/hooks/useDerivedDisconnect.ts","../src/hooks/useWalletReconnectionHandler.ts","../src/components/WalletConnectionHeader.tsx","../src/components/WalletConnectionUI.tsx","../src/components/NetworkSwitchManager.tsx"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index-B_dOGVNW.d.ts","names":[],"sources":["../src/hooks/AdapterContext.tsx","../src/hooks/AdapterProvider.tsx","../src/hooks/WalletStateContext.ts","../src/hooks/WalletStateProvider.tsx","../src/hooks/AnalyticsContext.tsx","../src/hooks/AnalyticsProvider.tsx","../src/hooks/useAnalytics.ts","../src/hooks/useAdapterContext.ts","../src/hooks/useDerivedAccountStatus.ts","../src/hooks/useDerivedSwitchChainStatus.ts","../src/hooks/useDerivedChainInfo.ts","../src/hooks/useDerivedConnectStatus.ts","../src/hooks/useDerivedDisconnect.ts","../src/hooks/useWalletReconnectionHandler.ts","../src/components/WalletConnectionHeader.tsx","../src/components/WalletConnectionUI.tsx","../src/components/NetworkSwitchManager.tsx"],"sourcesContent":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index-Cfc5cQFd.d.cts","names":[],"sources":["../src/hooks/AdapterContext.tsx","../src/hooks/AdapterProvider.tsx","../src/hooks/WalletStateContext.tsx","../src/hooks/WalletStateProvider.tsx","../src/hooks/AnalyticsContext.tsx","../src/hooks/AnalyticsProvider.tsx","../src/hooks/useAnalytics.ts","../src/hooks/useAdapterContext.ts","../src/hooks/useDerivedAccountStatus.ts","../src/hooks/useDerivedSwitchChainStatus.ts","../src/hooks/useDerivedChainInfo.ts","../src/hooks/useDerivedConnectStatus.ts","../src/hooks/useDerivedDisconnect.ts","../src/hooks/useWalletReconnectionHandler.ts","../src/components/WalletConnectionHeader.tsx","../src/components/WalletConnectionUI.tsx","../src/components/NetworkSwitchManager.tsx"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index-Cfc5cQFd.d.cts","names":[],"sources":["../src/hooks/AdapterContext.tsx","../src/hooks/AdapterProvider.tsx","../src/hooks/WalletStateContext.ts","../src/hooks/WalletStateProvider.tsx","../src/hooks/AnalyticsContext.tsx","../src/hooks/AnalyticsProvider.tsx","../src/hooks/useAnalytics.ts","../src/hooks/useAdapterContext.ts","../src/hooks/useDerivedAccountStatus.ts","../src/hooks/useDerivedSwitchChainStatus.ts","../src/hooks/useDerivedChainInfo.ts","../src/hooks/useDerivedConnectStatus.ts","../src/hooks/useDerivedDisconnect.ts","../src/hooks/useWalletReconnectionHandler.ts","../src/components/WalletConnectionHeader.tsx","../src/components/WalletConnectionUI.tsx","../src/components/NetworkSwitchManager.tsx"],"sourcesContent":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -164,8 +164,64 @@ function AdapterProvider({ children, resolveAdapter }) {
164
164
  }
165
165
 
166
166
  //#endregion
167
- //#region src/hooks/WalletStateContext.tsx
168
- const WalletStateContext = (0, react.createContext)(void 0);
167
+ //#region src/hooks/WalletStateContext.ts
168
+ /**
169
+ * Shared Global Context Pattern
170
+ * =============================
171
+ *
172
+ * WHY THIS EXISTS:
173
+ * When bundlers (like Vite's optimizeDeps with esbuild) pre-bundle dependencies,
174
+ * they may inline transitive dependencies like @openzeppelin/ui-react into the
175
+ * consuming package's bundle. This creates MULTIPLE instances of this module:
176
+ *
177
+ * 1. The app's direct import → packages/react/dist/index.js
178
+ * 2. The adapter's inlined copy → .vite/deps/@openzeppelin_ui-builder-adapter-evm.js
179
+ *
180
+ * Since React contexts use referential identity, these two module instances have
181
+ * DIFFERENT context objects. When the adapter's components call useWalletState(),
182
+ * they look for a context that was never provided (because WalletStateProvider
183
+ * uses the app's context, not the adapter's inlined copy).
184
+ *
185
+ * SOLUTION:
186
+ * Store the context object on globalThis so ALL module instances share the same
187
+ * React context, regardless of how they were loaded or bundled.
188
+ *
189
+ * WHEN IS THIS NEEDED:
190
+ * - Development with Vite's dependency pre-bundling (optimizeDeps)
191
+ * - When adapters are installed from npm (not workspace-linked with same bundler)
192
+ * - Any scenario where @openzeppelin/ui-react might be duplicated
193
+ *
194
+ * PRODUCTION APPS:
195
+ * In production builds where the app and adapters are bundled together with proper
196
+ * deduplication (e.g., via bundler configuration or peer dependencies), this
197
+ * workaround may not be strictly necessary. However, it provides a safety net
198
+ * and has minimal overhead.
199
+ */
200
+ /**
201
+ * Use Symbol.for() to create a globally unique key that is consistent across
202
+ * all module instances. Unlike Symbol(), Symbol.for() returns the same symbol
203
+ * for the same key string, which is essential for cross-module sharing.
204
+ */
205
+ const WALLET_STATE_CONTEXT_KEY = Symbol.for("@openzeppelin/ui-react/WalletStateContext");
206
+ /**
207
+ * Retrieves or creates the shared WalletStateContext.
208
+ *
209
+ * NOTE ON ATOMICITY:
210
+ * The check-then-set pattern here is not atomic, but this is acceptable because:
211
+ * 1. JavaScript is single-threaded; module initialization is synchronous
212
+ * 2. Even if multiple modules initialize "simultaneously" during parallel loading,
213
+ * they execute sequentially on the main thread
214
+ * 3. The worst case (two contexts created) would only happen if the check and set
215
+ * were somehow interleaved, which cannot occur in JS's execution model
216
+ * 4. For React contexts specifically, having the same context object is what matters,
217
+ * and this pattern guarantees that after initialization
218
+ */
219
+ function getOrCreateSharedContext() {
220
+ const global = globalThis;
221
+ if (!global[WALLET_STATE_CONTEXT_KEY]) global[WALLET_STATE_CONTEXT_KEY] = (0, react.createContext)(void 0);
222
+ return global[WALLET_STATE_CONTEXT_KEY];
223
+ }
224
+ const WalletStateContext = getOrCreateSharedContext();
169
225
  /**
170
226
  * Hook to access wallet state from WalletStateProvider.
171
227
  * @throws Error if used outside of WalletStateProvider
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["React","AnalyticsService","Button"],"sources":["../src/hooks/AdapterContext.tsx","../src/hooks/AdapterProvider.tsx","../src/hooks/WalletStateContext.tsx","../src/hooks/useAdapterContext.ts","../src/hooks/WalletStateProvider.tsx","../src/hooks/AnalyticsContext.tsx","../src/hooks/AnalyticsProvider.tsx","../src/hooks/useAnalytics.ts","../src/hooks/useDerivedAccountStatus.ts","../src/hooks/useDerivedSwitchChainStatus.ts","../src/hooks/useDerivedChainInfo.ts","../src/hooks/useDerivedConnectStatus.ts","../src/hooks/useDerivedDisconnect.ts","../src/hooks/useWalletReconnectionHandler.ts","../src/components/WalletConnectionUI.tsx","../src/components/WalletConnectionHeader.tsx","../src/components/NetworkSwitchManager.tsx"],"sourcesContent":["/**\n * AdapterContext.tsx\n *\n * This file defines the React Context used for the adapter singleton pattern.\n * It provides types and the context definition, but the actual implementation\n * is in the AdapterProvider component.\n *\n * The adapter singleton pattern ensures that only one adapter instance exists\n * per network configuration, which is critical for consistent wallet connection\n * state across the application.\n */\nimport { createContext } from 'react';\n\nimport type { ContractAdapter, NetworkConfig } from '@openzeppelin/ui-types';\n\n/**\n * Registry type that maps network IDs to their corresponding adapter instances\n * This is the core data structure for the singleton pattern\n */\nexport interface AdapterRegistry {\n [networkId: string]: ContractAdapter;\n}\n\n/**\n * Context value interface defining what's provided through the context\n * The main functionality is getAdapterForNetwork which either returns\n * an existing adapter or initiates loading of a new one\n */\nexport interface AdapterContextValue {\n getAdapterForNetwork: (networkConfig: NetworkConfig | null) => {\n adapter: ContractAdapter | null;\n isLoading: boolean;\n };\n}\n\n/**\n * The React Context that provides adapter registry access throughout the app\n * Components can access this through the useAdapterContext hook\n */\nexport const AdapterContext = createContext<AdapterContextValue | null>(null);\n","/**\n * AdapterProvider.tsx\n *\n * This file implements the Adapter Provider component which manages a registry of\n * adapter instances. It's a key part of the adapter singleton pattern which ensures\n * that only one adapter instance exists per network configuration.\n *\n * The adapter registry is shared across the application via React Context, allowing\n * components to access the same adapter instances and maintain consistent wallet\n * connection state.\n *\n * IMPORTANT: This implementation needs special care to avoid React state update errors\n * during component rendering. Direct state updates during render are not allowed, which\n * is why adapter loading is controlled carefully.\n */\nimport { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type { ContractAdapter, NetworkConfig } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { AdapterContext, AdapterContextValue, AdapterRegistry } from './AdapterContext';\n\nexport interface AdapterProviderProps {\n children: ReactNode;\n /** Function to resolve/create an adapter instance for a given NetworkConfig. */\n resolveAdapter: (networkConfig: NetworkConfig) => Promise<ContractAdapter>;\n}\n\n/**\n * Provider component that manages adapter instances centrally\n * to avoid creating multiple instances of the same adapter.\n *\n * This component:\n * 1. Maintains a registry of adapter instances by network ID\n * 2. Tracks loading states for adapters being initialized\n * 3. Provides a function to get or load adapters for specific networks\n * 4. Ensures adapter instances are reused when possible\n */\nexport function AdapterProvider({ children, resolveAdapter }: AdapterProviderProps) {\n // Registry to store adapter instances by network ID\n const [adapterRegistry, setAdapterRegistry] = useState<AdapterRegistry>({});\n\n // Track loading states by network ID\n const [loadingNetworks, setLoadingNetworks] = useState<Set<string>>(new Set());\n\n // Log registry status on changes\n useEffect(() => {\n const adapterCount = Object.keys(adapterRegistry).length;\n if (adapterCount > 0) {\n logger.info('AdapterProvider', `Registry contains ${adapterCount} adapters:`, {\n networkIds: Object.keys(adapterRegistry),\n loadingCount: loadingNetworks.size,\n loadingNetworkIds: Array.from(loadingNetworks),\n });\n }\n }, [adapterRegistry, loadingNetworks]);\n\n /**\n * Function to get or create an adapter for a network\n *\n * IMPORTANT: The actual adapter loading is handled in the useConfiguredAdapterSingleton hook\n * to avoid React state updates during render, which would cause errors.\n *\n * This function:\n * 1. Returns existing adapters immediately if available\n * 2. Reports loading state for adapters being initialized\n * 3. Initiates adapter loading when needed\n */\n const getAdapterForNetwork = useCallback(\n (networkConfig: NetworkConfig | null) => {\n if (!networkConfig) {\n return { adapter: null, isLoading: false };\n }\n\n const networkId = networkConfig.id;\n\n // Debug log to track adapter requests\n logger.debug('AdapterProvider', `Adapter requested for network ${networkId}`);\n\n // If we already have this adapter, return it\n if (adapterRegistry[networkId]) {\n logger.debug('AdapterProvider', `Using existing adapter for network ${networkId}`);\n return {\n adapter: adapterRegistry[networkId],\n isLoading: false,\n };\n }\n\n // If we're already loading this adapter, indicate loading\n if (loadingNetworks.has(networkId)) {\n logger.debug('AdapterProvider', `Adapter for network ${networkId} is currently loading`);\n return {\n adapter: null,\n isLoading: true,\n };\n }\n\n // Start loading the adapter\n // NOTE: This state update during render is handled safely in the useConfiguredAdapterSingleton hook\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.add(networkId);\n return newSet;\n });\n\n logger.info(\n 'AdapterProvider',\n `Starting adapter initialization for network ${networkId} (${networkConfig.name})`\n );\n\n // Use the passed-in resolveAdapter function\n void resolveAdapter(networkConfig)\n .then((adapter) => {\n logger.info('AdapterProvider', `Adapter for network ${networkId} loaded successfully`, {\n type: adapter.constructor.name,\n objectId: Object.prototype.toString.call(adapter),\n });\n\n // Update registry with new adapter\n setAdapterRegistry((prev) => ({\n ...prev,\n [networkId]: adapter,\n }));\n\n // Remove from loading networks\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.delete(networkId);\n return newSet;\n });\n })\n .catch((error) => {\n logger.error('AdapterProvider', `Error loading adapter for network ${networkId}:`, error);\n\n // Remove from loading networks on error\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.delete(networkId);\n return newSet;\n });\n });\n\n return {\n adapter: null,\n isLoading: true,\n };\n },\n [adapterRegistry, loadingNetworks, resolveAdapter]\n );\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue = useMemo<AdapterContextValue>(\n () => ({\n getAdapterForNetwork,\n }),\n [getAdapterForNetwork]\n );\n\n return <AdapterContext.Provider value={contextValue}>{children}</AdapterContext.Provider>;\n}\n","import React, { createContext } from 'react';\n\nimport type {\n ContractAdapter,\n EcosystemSpecificReactHooks,\n NetworkConfig,\n UiKitConfiguration,\n} from '@openzeppelin/ui-types';\n\nexport interface WalletStateContextValue {\n // Globally selected network state\n activeNetworkId: string | null;\n setActiveNetworkId: (networkId: string | null) => void;\n activeNetworkConfig: NetworkConfig | null;\n\n // Active adapter state\n activeAdapter: ContractAdapter | null;\n isAdapterLoading: boolean;\n\n // Facade hooks object from the active adapter\n // Consumers will call these hooks (e.g., walletFacadeHooks.useAccount())\n walletFacadeHooks: EcosystemSpecificReactHooks | null;\n reconfigureActiveAdapterUiKit: (uiKitConfig?: Partial<UiKitConfiguration>) => void;\n}\n\nexport const WalletStateContext = createContext<WalletStateContextValue | undefined>(undefined);\n\n/**\n * Hook to access wallet state from WalletStateProvider.\n * @throws Error if used outside of WalletStateProvider\n */\nexport function useWalletState(): WalletStateContextValue {\n const context = React.useContext(WalletStateContext);\n if (context === undefined) {\n throw new Error('useWalletState must be used within a WalletStateProvider');\n }\n return context;\n}\n","/**\n * useAdapterContext.ts\n *\n * This file provides a hook to access the AdapterContext throughout the application.\n * It's a critical part of the adapter singleton pattern, allowing components to\n * access the centralized adapter registry.\n *\n * The adapter singleton pattern ensures:\n * - Only one adapter instance exists per network\n * - Wallet connection state is consistent across the app\n * - Better performance by eliminating redundant adapter initialization\n */\nimport { useContext } from 'react';\n\nimport { AdapterContext, AdapterContextValue } from './AdapterContext';\n\n/**\n * Hook to access the adapter context\n *\n * This hook provides access to the getAdapterForNetwork function which\n * retrieves or creates adapter instances from the singleton registry.\n *\n * Components should typically use useConfiguredAdapterSingleton instead\n * of this hook directly, as it handles React state update timing properly.\n *\n * @throws Error if used outside of an AdapterProvider context\n * @returns The adapter context value\n */\nexport function useAdapterContext(): AdapterContextValue {\n const context = useContext(AdapterContext);\n\n if (!context) {\n throw new Error('useAdapterContext must be used within an AdapterProvider');\n }\n\n return context;\n}\n","import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type {\n ContractAdapter,\n EcosystemReactUiProviderProps,\n EcosystemSpecificReactHooks,\n NativeConfigLoader,\n NetworkConfig,\n UiKitConfiguration,\n} from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useAdapterContext } from './useAdapterContext';\nimport { WalletStateContext, type WalletStateContextValue } from './WalletStateContext';\n\n// Extended adapter interface that includes the callback-based configureUiKit method\ninterface ExtendedContractAdapter extends ContractAdapter {\n configureUiKit?(\n config: Partial<UiKitConfiguration>,\n options?: {\n loadUiKitNativeConfig?: (kitName: string) => Promise<Record<string, unknown> | null>;\n }\n ): void | Promise<void>;\n getEcosystemReactUiContextProvider?():\n | React.ComponentType<EcosystemReactUiProviderProps>\n | undefined;\n}\n\nexport interface WalletStateProviderProps {\n children: ReactNode;\n /** Optional initial network ID to set as active when the provider mounts. */\n initialNetworkId?: string | null;\n /** Function to retrieve a NetworkConfig object by its ID. */\n getNetworkConfigById: (\n networkId: string\n ) => Promise<NetworkConfig | null | undefined> | NetworkConfig | null | undefined;\n /**\n * Optional generic function to load configuration modules by relative path.\n * The adapter is responsible for constructing the conventional path (e.g., './config/wallet/[kitName].config').\n * @param relativePath The conventional relative path to the configuration module.\n * @returns A Promise resolving to the configuration object (expected to have a default export) or null.\n */\n loadConfigModule?: NativeConfigLoader;\n}\n\n/**\n * Configures the adapter's UI kit and returns the UI provider component and hooks.\n */\nasync function configureAdapterUiKit(\n adapter: ExtendedContractAdapter,\n loadConfigModule?: (relativePath: string) => Promise<Record<string, unknown> | null>,\n programmaticOverrides: Partial<UiKitConfiguration> = {}\n): Promise<{\n providerComponent: React.ComponentType<EcosystemReactUiProviderProps> | null;\n hooks: EcosystemSpecificReactHooks | null;\n}> {\n try {\n // Ensure the adapter (and thus the EvmUiKitManager) is configured.\n if (typeof adapter.configureUiKit === 'function') {\n logger.info(\n '[WSP configureAdapterUiKit] Calling configureUiKit for adapter:',\n adapter?.networkConfig?.id\n );\n await adapter.configureUiKit(programmaticOverrides, {\n loadUiKitNativeConfig: loadConfigModule,\n });\n logger.info(\n '[WSP configureAdapterUiKit] configureUiKit completed for adapter:',\n adapter?.networkConfig?.id\n );\n }\n\n const providerComponent = adapter.getEcosystemReactUiContextProvider?.() || null;\n const hooks = adapter.getEcosystemReactHooks?.() || null;\n\n logger.info('[WSP configureAdapterUiKit]', 'UI provider and hooks retrieved successfully.');\n\n return { providerComponent, hooks };\n } catch (error) {\n logger.error('[WSP configureAdapterUiKit]', 'Error during adapter UI setup:', error);\n throw error; // Re-throw to be handled by caller\n }\n}\n\n/**\n * @name WalletStateProvider\n * @description This provider is a central piece of the application's state management for wallet and network interactions.\n * It is responsible for:\n * 1. Managing the globally selected active network ID (`activeNetworkId`).\n * 2. Deriving the full `NetworkConfig` object (`activeNetworkConfig`) for the active network.\n * 3. Fetching and providing the corresponding `ContractAdapter` instance (`activeAdapter`) for the active network,\n * leveraging the `AdapterProvider` to ensure adapter singletons.\n * 4. Storing and providing the `EcosystemSpecificReactHooks` (`walletFacadeHooks`) from the active adapter.\n * 5. Rendering the adapter-specific UI context provider (e.g., WagmiProvider for EVM) around its children,\n * which is essential for the facade hooks to function correctly.\n * 6. Providing a function (`setActiveNetworkId`) to change the globally active network.\n *\n * Consumers use the `useWalletState()` hook to access this global state.\n * It should be placed high in the component tree, inside an `<AdapterProvider>`.\n */\nexport function WalletStateProvider({\n children,\n initialNetworkId = null,\n getNetworkConfigById,\n loadConfigModule,\n}: WalletStateProviderProps) {\n // State for the ID of the globally selected network.\n const [currentGlobalNetworkId, setCurrentGlobalNetworkIdState] = useState<string | null>(\n initialNetworkId\n );\n // State for the full NetworkConfig object of the globally selected network.\n const [currentGlobalNetworkConfig, setCurrentGlobalNetworkConfig] =\n useState<NetworkConfig | null>(null);\n\n // State for the active ContractAdapter instance corresponding to the currentGlobalNetworkConfig.\n const [globalActiveAdapter, setGlobalActiveAdapter] = useState<ContractAdapter | null>(null);\n // Loading state for the globalActiveAdapter.\n const [isGlobalAdapterLoading, setIsGlobalAdapterLoading] = useState<boolean>(false);\n // State for the facade hooks provided by the globalActiveAdapter.\n const [walletFacadeHooks, setWalletFacadeHooks] = useState<EcosystemSpecificReactHooks | null>(\n null\n );\n // State to hold the Component Type\n const [AdapterUiContextProviderToRender, setAdapterUiContextProviderToRender] =\n useState<React.ComponentType<EcosystemReactUiProviderProps> | null>(null);\n\n // New state to act as a manual trigger for re-configuring the UI kit.\n const [uiKitConfigVersion, setUiKitConfigVersion] = useState(0);\n // State to hold programmatic overrides for the next reconfiguration.\n const [programmaticUiKitConfig, setProgrammaticUiKitConfig] = useState<\n Partial<UiKitConfiguration> | undefined\n >(undefined);\n\n // Consume AdapterContext to get the function for fetching adapter instances.\n const { getAdapterForNetwork } = useAdapterContext();\n\n // Effect to derive the full NetworkConfig object when currentGlobalNetworkId changes.\n useEffect(() => {\n const abortController = new AbortController();\n\n async function fetchNetworkConfig() {\n if (!currentGlobalNetworkId) {\n // If currentGlobalNetworkId is null, clear the config.\n if (!abortController.signal.aborted) {\n setCurrentGlobalNetworkConfig(null);\n }\n return;\n }\n\n try {\n const config = await Promise.resolve(getNetworkConfigById(currentGlobalNetworkId));\n if (!abortController.signal.aborted) {\n setCurrentGlobalNetworkConfig(config || null);\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n logger.error('[WSP fetchNetworkConfig]', 'Failed to fetch network config:', error);\n setCurrentGlobalNetworkConfig(null);\n }\n }\n }\n\n void fetchNetworkConfig();\n return () => abortController.abort();\n }, [currentGlobalNetworkId, getNetworkConfigById]);\n\n // Effect to load the active adapter and its UI capabilities when currentGlobalNetworkConfig changes.\n useEffect(() => {\n const abortController = new AbortController();\n\n async function loadAdapterAndConfigureUi() {\n if (!currentGlobalNetworkConfig) {\n // No network config - clear everything\n if (!abortController.signal.aborted) {\n setGlobalActiveAdapter(null);\n setIsGlobalAdapterLoading(false);\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n }\n return;\n }\n\n const { adapter: newAdapter, isLoading: newIsLoading } = getAdapterForNetwork(\n currentGlobalNetworkConfig\n ) as { adapter: ExtendedContractAdapter | null; isLoading: boolean };\n\n if (abortController.signal.aborted) return;\n\n // Update loading state immediately, but defer exposing the new adapter\n // until its UI provider and hooks are configured to avoid mismatch renders.\n setIsGlobalAdapterLoading(newIsLoading);\n\n if (newAdapter && !newIsLoading) {\n try {\n const { providerComponent, hooks } = await configureAdapterUiKit(\n newAdapter,\n loadConfigModule,\n programmaticUiKitConfig\n );\n\n if (!abortController.signal.aborted) {\n // Ensure provider component and hooks are ready before exposing the new adapter\n // to consumers. This prevents rendering ecosystem-specific components under the\n // previous ecosystem provider (e.g., Stellar components under EVM provider).\n setAdapterUiContextProviderToRender(() => providerComponent);\n setWalletFacadeHooks(hooks);\n setGlobalActiveAdapter(newAdapter);\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n logger.error(\n '[WSP loadAdapterAndConfigureUi]',\n 'Error during adapter UI setup:',\n error\n );\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n }\n }\n } else if (!newAdapter && !newIsLoading) {\n // Adapter is null and not loading, clear UI specific state\n if (!abortController.signal.aborted) {\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n setGlobalActiveAdapter(null);\n }\n }\n // If newIsLoading is true, retain previous AdapterUiContextProviderToRender and hooks\n // to prevent UI flicker, EvmWalletUiRoot will handle its loading state internally.\n }\n\n void loadAdapterAndConfigureUi();\n return () => abortController.abort();\n }, [\n currentGlobalNetworkConfig,\n getAdapterForNetwork,\n loadConfigModule,\n uiKitConfigVersion,\n programmaticUiKitConfig,\n ]);\n\n /**\n * Callback to set the globally active network ID.\n * Also clears dependent states (config, adapter, hooks) if the network ID is cleared.\n */\n const setActiveNetworkIdCallback = useCallback((networkId: string | null) => {\n logger.info('WalletStateProvider', `Setting global network ID to: ${networkId}`);\n setCurrentGlobalNetworkIdState(networkId); // This will trigger the fetchNetworkConfig effect.\n if (!networkId) {\n // If clearing the network, proactively clear downstream states.\n // The effects above will also clear them, but this is more immediate.\n setCurrentGlobalNetworkConfig(null);\n setGlobalActiveAdapter(null);\n setIsGlobalAdapterLoading(false);\n setWalletFacadeHooks(null);\n // Do not clear AdapterUiContextProviderToRender here, let the effect handle it\n // based on whether it's a loading transition or an actual clearing.\n // setAdapterUiContextProviderToRender(() => null);\n }\n }, []); // Empty dependency array as it only uses setters from useState.\n\n /**\n * Callback to explicitly trigger a re-configuration of the active adapter's UI kit.\n * This is useful when a UI kit setting changes (e.g., via a wizard) without a network change.\n */\n const reconfigureActiveAdapterUiKit = useCallback(\n (uiKitConfig?: Partial<UiKitConfiguration>) => {\n logger.info(\n 'WalletStateProvider',\n 'Explicitly triggering UI kit re-configuration by bumping version.',\n uiKitConfig\n );\n setProgrammaticUiKitConfig(uiKitConfig);\n setUiKitConfigVersion((v) => v + 1);\n },\n [setProgrammaticUiKitConfig, setUiKitConfigVersion]\n );\n\n // The context value now only provides the raw walletFacadeHooks object.\n // Consumers are responsible for calling specific hooks from it and handling their results.\n const contextValue = useMemo<WalletStateContextValue>(\n () => ({\n activeNetworkId: currentGlobalNetworkId,\n setActiveNetworkId: setActiveNetworkIdCallback,\n activeNetworkConfig: currentGlobalNetworkConfig,\n activeAdapter: globalActiveAdapter,\n isAdapterLoading: isGlobalAdapterLoading,\n walletFacadeHooks,\n reconfigureActiveAdapterUiKit,\n }),\n [\n currentGlobalNetworkId,\n setActiveNetworkIdCallback,\n currentGlobalNetworkConfig,\n globalActiveAdapter,\n isGlobalAdapterLoading,\n walletFacadeHooks,\n reconfigureActiveAdapterUiKit,\n ]\n );\n\n const ActualProviderToRender = AdapterUiContextProviderToRender;\n let childrenToRender: ReactNode;\n\n if (ActualProviderToRender) {\n // Generate a unique key based on adapter's network ecosystem and ID\n // This ensures proper unmounting/mounting when switching between EVM/Stellar/etc.\n const key = `${globalActiveAdapter?.networkConfig?.ecosystem || 'unknown'}-${globalActiveAdapter?.networkConfig?.id || 'unknown'}`;\n\n // EvmWalletUiRoot (and similar for other adapters) no longer needs uiKitConfiguration prop\n // as it manages its own configuration internally via the EvmUiKitManager or equivalent.\n logger.info(\n '[WSP RENDER]',\n 'Rendering adapter-provided UI context provider:',\n ActualProviderToRender.displayName || ActualProviderToRender.name || 'UnknownComponent',\n 'with key:',\n key\n );\n childrenToRender = <ActualProviderToRender key={key}>{children}</ActualProviderToRender>;\n } else {\n logger.info(\n '[WSP RENDER]',\n 'No adapter UI context provider to render. Rendering direct children.'\n );\n childrenToRender = children;\n }\n\n return (\n <WalletStateContext.Provider value={contextValue}>\n {childrenToRender}\n </WalletStateContext.Provider>\n );\n}\n","import { createContext, useContext } from 'react';\n\n/**\n * Analytics context value interface.\n * Provides access to analytics functionality throughout the React component tree.\n */\nexport interface AnalyticsContextValue {\n /** Google Analytics tag ID */\n tagId?: string;\n /**\n * Check if analytics is enabled via feature flag.\n * Returns fresh state on each call to handle dynamic feature flag changes.\n */\n isEnabled: () => boolean;\n /** Initialize analytics with optional tag ID override */\n initialize: (tagIdOverride?: string) => void;\n /**\n * Track a generic event with custom parameters.\n * Use this for app-specific events.\n *\n * @example\n * ```typescript\n * trackEvent('button_clicked', { button_name: 'submit' });\n * ```\n */\n trackEvent: (eventName: string, parameters: Record<string, string | number>) => void;\n /**\n * Track page view event.\n *\n * @example\n * ```typescript\n * trackPageView('Dashboard', '/dashboard');\n * ```\n */\n trackPageView: (pageName: string, pagePath: string) => void;\n /**\n * Track network selection event.\n *\n * @example\n * ```typescript\n * trackNetworkSelection('ethereum-mainnet', 'evm');\n * ```\n */\n trackNetworkSelection: (networkId: string, ecosystem: string) => void;\n}\n\n/**\n * Analytics context for providing analytics functionality to React components.\n * Must be used within an AnalyticsProvider.\n */\nexport const AnalyticsContext = createContext<AnalyticsContextValue | null>(null);\n\n/**\n * Internal hook to access analytics context.\n * Throws an error if used outside of an AnalyticsProvider.\n *\n * @internal\n * @throws Error if used outside of AnalyticsProvider\n */\nexport const useAnalyticsContext = (): AnalyticsContextValue => {\n const context = useContext(AnalyticsContext);\n if (!context) {\n throw new Error('useAnalyticsContext must be used within an AnalyticsProvider');\n }\n return context;\n};\n","import React, { ReactNode, useEffect, useMemo } from 'react';\n\nimport { AnalyticsService, logger } from '@openzeppelin/ui-utils';\n\nimport { AnalyticsContext, AnalyticsContextValue } from './AnalyticsContext';\n\n/**\n * Props for the AnalyticsProvider component\n */\nexport interface AnalyticsProviderProps {\n /** Google Analytics tag ID (e.g., 'G-XXXXXXXXXX') */\n tagId?: string;\n /** Whether to automatically initialize analytics on mount (default: true) */\n autoInit?: boolean;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Analytics Provider component.\n * Provides analytics functionality throughout the React component tree.\n *\n * @example\n * ```tsx\n * function App() {\n * return (\n * <AnalyticsProvider tagId={import.meta.env.VITE_GA_TAG_ID} autoInit={true}>\n * <YourApp />\n * </AnalyticsProvider>\n * );\n * }\n * ```\n */\nexport const AnalyticsProvider: React.FC<AnalyticsProviderProps> = ({\n tagId,\n autoInit = true,\n children,\n}) => {\n useEffect(() => {\n if (autoInit && tagId) {\n AnalyticsService.initialize(tagId);\n }\n }, [tagId, autoInit]);\n\n const contextValue: AnalyticsContextValue = useMemo(\n () => ({\n tagId,\n isEnabled: () => AnalyticsService.isEnabled(),\n initialize: (tagIdOverride?: string) => {\n const effectiveTagId = tagIdOverride || tagId;\n if (effectiveTagId) {\n AnalyticsService.initialize(effectiveTagId);\n }\n },\n trackEvent: (eventName: string, parameters: Record<string, string | number>) => {\n try {\n AnalyticsService.trackEvent(eventName, parameters);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking event:', error);\n }\n },\n trackPageView: (pageName: string, pagePath: string) => {\n try {\n AnalyticsService.trackPageView(pageName, pagePath);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking page view:', error);\n }\n },\n trackNetworkSelection: (networkId: string, ecosystem: string) => {\n try {\n AnalyticsService.trackNetworkSelection(networkId, ecosystem);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking network selection:', error);\n }\n },\n }),\n [tagId]\n );\n\n return <AnalyticsContext.Provider value={contextValue}>{children}</AnalyticsContext.Provider>;\n};\n","import { useAnalyticsContext } from './AnalyticsContext';\n\n/**\n * Custom hook for accessing analytics functionality.\n *\n * This hook provides a convenient interface for tracking user interactions\n * throughout the application. It must be used within an AnalyticsProvider.\n *\n * For app-specific tracking methods, create a wrapper hook that uses this\n * hook and adds your custom tracking functions.\n *\n * @example\n * ```tsx\n * // Basic usage\n * function MyComponent() {\n * const { trackEvent, trackPageView, isEnabled } = useAnalytics();\n *\n * const handleClick = () => {\n * trackEvent('button_clicked', { button_name: 'submit' });\n * };\n *\n * return (\n * <div>\n * Analytics enabled: {isEnabled().toString()}\n * <button onClick={handleClick}>Submit</button>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Creating app-specific wrapper hook\n * function useMyAppAnalytics() {\n * const analytics = useAnalytics();\n *\n * return {\n * ...analytics,\n * trackFormSubmit: (formName: string) => {\n * analytics.trackEvent('form_submitted', { form_name: formName });\n * },\n * };\n * }\n * ```\n *\n * @returns Analytics context with tracking methods and state\n * @throws Error if used outside of AnalyticsProvider\n */\nexport const useAnalytics = () => {\n try {\n return useAnalyticsContext();\n } catch {\n throw new Error('useAnalytics must be used within an AnalyticsProvider');\n }\n};\n","// Assumes WalletStateContext exports useWalletState\nimport { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedAccountStatus {\n isConnected: boolean;\n address?: string;\n chainId?: number;\n // Potentially add other commonly used and safely extracted properties from useAccount's result\n}\n\nconst defaultAccountStatus: DerivedAccountStatus = {\n isConnected: false,\n address: undefined,\n chainId: undefined,\n};\n\n/**\n * A custom hook that consumes useWalletState to get the walletFacadeHooks,\n * then calls the useAccount facade hook (if available) and returns a structured,\n * safely-accessed account status (isConnected, address, chainId).\n * Provides default values if the hook or its properties are unavailable.\n */\nexport function useDerivedAccountStatus(): DerivedAccountStatus {\n const { walletFacadeHooks } = useWalletState();\n\n // Call the useAccount hook from the facade\n const accountHookOutput = walletFacadeHooks?.useAccount\n ? walletFacadeHooks.useAccount()\n : undefined;\n\n if (isRecordWithProperties(accountHookOutput)) {\n const isConnected =\n 'isConnected' in accountHookOutput && typeof accountHookOutput.isConnected === 'boolean'\n ? accountHookOutput.isConnected\n : defaultAccountStatus.isConnected;\n const address =\n 'address' in accountHookOutput && typeof accountHookOutput.address === 'string'\n ? accountHookOutput.address\n : defaultAccountStatus.address;\n const chainId =\n 'chainId' in accountHookOutput && typeof accountHookOutput.chainId === 'number'\n ? accountHookOutput.chainId\n : defaultAccountStatus.chainId;\n return { isConnected, address, chainId };\n }\n return defaultAccountStatus;\n}\n","import { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\n// Define the expected return shape for the derived hook\nexport interface DerivedSwitchChainStatus {\n /** Function to initiate a network switch. Undefined if not available. */\n switchChain?: (args: { chainId: number }) => void;\n /** True if a network switch is currently in progress. */\n isSwitching: boolean;\n /** Error object if the last switch attempt failed, otherwise null. */\n error: Error | null;\n}\n\nconst defaultSwitchChainStatus: DerivedSwitchChainStatus = {\n switchChain: undefined,\n isSwitching: false,\n error: null,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useSwitchChain` facade hook (if available) and returns a structured,\n * safely-accessed status and control function for network switching.\n * Provides default values if the hook or its properties are unavailable.\n */\nexport function useDerivedSwitchChainStatus(): DerivedSwitchChainStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const switchChainHookOutput = walletFacadeHooks?.useSwitchChain\n ? walletFacadeHooks.useSwitchChain()\n : undefined;\n\n if (isRecordWithProperties(switchChainHookOutput)) {\n const execSwitchFn =\n 'switchChain' in switchChainHookOutput &&\n typeof switchChainHookOutput.switchChain === 'function'\n ? (switchChainHookOutput.switchChain as (args: { chainId: number }) => void)\n : defaultSwitchChainStatus.switchChain;\n\n const isPending =\n 'isPending' in switchChainHookOutput && typeof switchChainHookOutput.isPending === 'boolean'\n ? switchChainHookOutput.isPending\n : defaultSwitchChainStatus.isSwitching;\n\n const err =\n 'error' in switchChainHookOutput && switchChainHookOutput.error instanceof Error\n ? switchChainHookOutput.error\n : defaultSwitchChainStatus.error;\n\n return { switchChain: execSwitchFn, isSwitching: isPending, error: err };\n }\n\n return defaultSwitchChainStatus;\n}\n","import { logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedChainInfo {\n /** The current chain ID reported by the wallet's active connection, if available. */\n currentChainId?: number;\n /** Array of chains configured in the underlying wallet library (e.g., wagmi). Type is any[] for generic compatibility. */\n availableChains: unknown[];\n}\n\nconst defaultChainInfo: DerivedChainInfo = {\n currentChainId: undefined,\n availableChains: [],\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useChainId` and `useChains` facade hooks (if available)\n * and returns a structured object with this information.\n * Provides default values if the hooks or their properties are unavailable.\n */\nexport function useDerivedChainInfo(): DerivedChainInfo {\n const { walletFacadeHooks } = useWalletState();\n\n let chainIdToReturn: number | undefined = defaultChainInfo.currentChainId;\n const chainIdHookOutput = walletFacadeHooks?.useChainId\n ? walletFacadeHooks.useChainId()\n : undefined;\n // The useChainId hook from wagmi directly returns the number or undefined\n if (typeof chainIdHookOutput === 'number') {\n chainIdToReturn = chainIdHookOutput;\n } else if (chainIdHookOutput !== undefined) {\n // If it's not a number but not undefined, log a warning but use default. Could be an adapter returning unexpected type.\n logger.warn(\n 'useDerivedChainInfo',\n 'useChainId facade hook returned non-numeric value:',\n chainIdHookOutput\n );\n }\n\n let chainsToReturn: unknown[] = defaultChainInfo.availableChains;\n const chainsHookOutput = walletFacadeHooks?.useChains ? walletFacadeHooks.useChains() : undefined;\n // The useChains hook from wagmi directly returns an array of Chain objects\n if (Array.isArray(chainsHookOutput)) {\n chainsToReturn = chainsHookOutput;\n } else if (chainsHookOutput !== undefined) {\n logger.warn(\n 'useDerivedChainInfo',\n 'useChains facade hook returned non-array value:',\n chainsHookOutput\n );\n }\n\n return { currentChainId: chainIdToReturn, availableChains: chainsToReturn };\n}\n","import type { Connector } from '@openzeppelin/ui-types';\nimport { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\n// Assuming Connector type is available\n\nexport interface DerivedConnectStatus {\n /** Function to initiate a connection, usually takes a connector. Undefined if not available. */\n connect?: (args?: { connector?: Connector /* or string for id */ }) => void;\n /** Array of available connectors. Type is any[] for broad compatibility until Connector type is fully generic here. */\n connectors: Connector[]; // Or any[] if Connector type from types pkg is too specific for generic hook here\n /** True if a connection attempt is in progress. */\n isConnecting: boolean;\n /** Error object if the last connection attempt failed, otherwise null. */\n error: Error | null;\n /** The connector a connection is pending for, if any. */\n pendingConnector?: Connector; // Or any\n}\n\nconst defaultConnectStatus: DerivedConnectStatus = {\n connect: undefined,\n connectors: [],\n isConnecting: false,\n error: null,\n pendingConnector: undefined,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useConnect` facade hook (if available) and returns a structured,\n * safely-accessed status and control functions for wallet connection.\n */\nexport function useDerivedConnectStatus(): DerivedConnectStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const connectHookOutput = walletFacadeHooks?.useConnect\n ? walletFacadeHooks.useConnect()\n : undefined;\n\n if (isRecordWithProperties(connectHookOutput)) {\n const connectFn =\n 'connect' in connectHookOutput && typeof connectHookOutput.connect === 'function'\n ? (connectHookOutput.connect as (args?: { connector?: Connector }) => void)\n : defaultConnectStatus.connect;\n\n const conns =\n 'connectors' in connectHookOutput && Array.isArray(connectHookOutput.connectors)\n ? (connectHookOutput.connectors as Connector[])\n : defaultConnectStatus.connectors;\n\n const isPending =\n 'isPending' in connectHookOutput && typeof connectHookOutput.isPending === 'boolean'\n ? connectHookOutput.isPending\n : 'isLoading' in connectHookOutput && typeof connectHookOutput.isLoading === 'boolean'\n ? connectHookOutput.isLoading\n : defaultConnectStatus.isConnecting;\n\n const err =\n 'error' in connectHookOutput && connectHookOutput.error instanceof Error\n ? connectHookOutput.error\n : defaultConnectStatus.error;\n\n const pendingConn =\n 'pendingConnector' in connectHookOutput &&\n typeof connectHookOutput.pendingConnector === 'object' // Assuming Connector is an object\n ? (connectHookOutput.pendingConnector as Connector)\n : defaultConnectStatus.pendingConnector;\n\n return {\n connect: connectFn,\n connectors: conns,\n isConnecting: isPending,\n error: err,\n pendingConnector: pendingConn,\n };\n }\n\n return defaultConnectStatus;\n}\n","import { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedDisconnectStatus {\n /** Function to initiate disconnection. Undefined if not available. */\n disconnect?: () => void | Promise<void>; // Can be sync or async\n /** True if a disconnection attempt is in progress (if hook provides this). */\n isDisconnecting: boolean;\n /** Error object if the last disconnection attempt failed (if hook provides this). */\n error: Error | null;\n}\n\nconst defaultDisconnectStatus: DerivedDisconnectStatus = {\n disconnect: undefined,\n isDisconnecting: false,\n error: null,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useDisconnect` facade hook (if available) and returns a structured,\n * safely-accessed status and control function for wallet disconnection.\n */\nexport function useDerivedDisconnect(): DerivedDisconnectStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const disconnectHookOutput = walletFacadeHooks?.useDisconnect\n ? walletFacadeHooks.useDisconnect()\n : undefined;\n\n if (isRecordWithProperties(disconnectHookOutput)) {\n const disconnectFn =\n 'disconnect' in disconnectHookOutput && typeof disconnectHookOutput.disconnect === 'function'\n ? (disconnectHookOutput.disconnect as () => void | Promise<void>)\n : defaultDisconnectStatus.disconnect;\n\n // wagmi's useDisconnect doesn't have isPending/isLoading directly, but has error and variables (which is the connector it disconnected)\n // We will assume a simple isDisconnecting is not provided by current wagmi facade, but include for future flexibility\n const isPending =\n 'isPending' in disconnectHookOutput && typeof disconnectHookOutput.isPending === 'boolean'\n ? disconnectHookOutput.isPending\n : 'isLoading' in disconnectHookOutput && typeof disconnectHookOutput.isLoading === 'boolean'\n ? disconnectHookOutput.isLoading\n : defaultDisconnectStatus.isDisconnecting;\n\n const err =\n 'error' in disconnectHookOutput && disconnectHookOutput.error instanceof Error\n ? disconnectHookOutput.error\n : defaultDisconnectStatus.error;\n\n return { disconnect: disconnectFn, isDisconnecting: isPending, error: err };\n }\n\n return defaultDisconnectStatus;\n}\n","import { useEffect, useRef } from 'react';\n\nimport type { ContractAdapter } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useDerivedAccountStatus } from './useDerivedAccountStatus';\n\n/**\n * Hook that detects wallet reconnection and re-queues network switch if needed.\n *\n * When a user disconnects their wallet and then reconnects in the same session,\n * the wallet may connect to a different chain than what's selected in the app.\n * This hook detects that scenario and invokes a callback to re-queue the network switch.\n *\n * @param selectedNetworkConfigId - Currently selected network in the app\n * @param selectedAdapter - Currently active adapter instance\n * @param networkToSwitchTo - Current network switch queue state (null if no switch pending)\n * @param onRequeueSwitch - Callback invoked when a network switch should be re-queued\n */\nexport function useWalletReconnectionHandler(\n selectedNetworkConfigId: string | null,\n selectedAdapter: ContractAdapter | null,\n networkToSwitchTo: string | null,\n onRequeueSwitch: (networkId: string) => void\n): void {\n const { isConnected, chainId: walletChainId } = useDerivedAccountStatus();\n const prevConnectedRef = useRef(isConnected);\n\n useEffect(() => {\n const wasDisconnected = !prevConnectedRef.current;\n const isNowConnected = isConnected;\n const isReconnection = wasDisconnected && isNowConnected;\n\n // Update ref for next render\n prevConnectedRef.current = isConnected;\n\n if (!isReconnection || !selectedNetworkConfigId || !selectedAdapter) {\n return;\n }\n\n // Skip if already queued\n if (networkToSwitchTo === selectedNetworkConfigId) {\n return;\n }\n\n // Check if adapter config has chainId (only EVM chains support network switching)\n const adapterConfig = selectedAdapter.networkConfig;\n if (!('chainId' in adapterConfig) || !walletChainId) {\n return;\n }\n\n const targetChainId = Number(adapterConfig.chainId);\n if (walletChainId !== targetChainId) {\n logger.info(\n 'useWalletReconnectionHandler',\n `Wallet reconnected with chain ${walletChainId}, but selected network requires ${targetChainId}. Re-queueing switch.`\n );\n onRequeueSwitch(selectedNetworkConfigId);\n }\n }, [\n isConnected,\n walletChainId,\n selectedNetworkConfigId,\n selectedAdapter,\n networkToSwitchTo,\n onRequeueSwitch,\n ]);\n}\n","import React, { useEffect, useState } from 'react';\n\nimport { Button } from '@openzeppelin/ui-components';\nimport { cn, logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from '../hooks/WalletStateContext';\n\ninterface WalletConnectionUIProps {\n className?: string;\n}\n\n/**\n * Component that displays wallet connection UI components\n * provided by the active adapter.\n */\nexport const WalletConnectionUI: React.FC<WalletConnectionUIProps> = ({ className }) => {\n const [isError, setIsError] = useState(false);\n const { activeAdapter, walletFacadeHooks } = useWalletState();\n\n useEffect(() => {\n logger.debug('WalletConnectionUI', '[Debug] State from useWalletState:', {\n adapterId: activeAdapter?.networkConfig.id,\n hasFacadeHooks: !!walletFacadeHooks,\n });\n }, [activeAdapter, walletFacadeHooks]);\n\n // Compute wallet components on each render to ensure UI kit changes are reflected immediately\n const walletComponents = (() => {\n if (!activeAdapter || typeof activeAdapter.getEcosystemWalletComponents !== 'function') {\n logger.debug(\n 'WalletConnectionUI',\n '[Debug] No activeAdapter or getEcosystemWalletComponents method, returning null.'\n );\n return null;\n }\n\n try {\n const components = activeAdapter.getEcosystemWalletComponents();\n logger.debug('WalletConnectionUI', '[Debug] walletComponents from adapter:', components);\n return components;\n } catch (error) {\n logger.error('WalletConnectionUI', '[Debug] Error getting wallet components:', error);\n setIsError(true);\n return null;\n }\n })();\n\n if (!walletComponents) {\n logger.debug(\n 'WalletConnectionUI',\n '[Debug] getEcosystemWalletComponents returned null/undefined, rendering null.'\n );\n return null;\n }\n\n // Log available components for debugging\n logger.debug('WalletConnectionUI', 'Rendering wallet components:', {\n hasConnectButton: !!walletComponents.ConnectButton,\n hasAccountDisplay: !!walletComponents.AccountDisplay,\n hasNetworkSwitcher: !!walletComponents.NetworkSwitcher,\n });\n\n const { ConnectButton, AccountDisplay, NetworkSwitcher } = walletComponents;\n\n // If there was an error, show an error button\n if (isError) {\n return (\n <div className={cn('flex items-center gap-4', className)}>\n <Button variant=\"destructive\" size=\"sm\" onClick={() => window.location.reload()}>\n Wallet Error - Retry\n </Button>\n </div>\n );\n }\n\n return (\n <div className={cn('flex items-center gap-4', className)}>\n {/* Display network switcher if available - moved before account to match typical wallet UI flow */}\n {NetworkSwitcher && <NetworkSwitcher />}\n\n {/* Display account info if available */}\n {AccountDisplay && <AccountDisplay />}\n\n {/* Display connect button if available */}\n {ConnectButton && <ConnectButton />}\n </div>\n );\n};\n","import React, { useEffect } from 'react';\n\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from '../hooks/WalletStateContext';\nimport { WalletConnectionUI } from './WalletConnectionUI';\n\n/**\n * Component that renders the wallet connection UI.\n * Uses useWalletState to get its data.\n */\nexport const WalletConnectionHeader: React.FC = () => {\n const { isAdapterLoading, activeAdapter } = useWalletState();\n\n useEffect(() => {\n logger.debug('WalletConnectionHeader', '[Debug] State from useWalletState:', {\n adapterPresent: !!activeAdapter,\n adapterNetwork: activeAdapter?.networkConfig.id,\n isLoading: isAdapterLoading,\n });\n }, [activeAdapter, isAdapterLoading]);\n\n if (isAdapterLoading) {\n logger.debug('WalletConnectionHeader', '[Debug] Adapter loading, showing skeleton.');\n return <div className=\"h-9 w-28 animate-pulse rounded bg-muted\"></div>;\n }\n\n return <WalletConnectionUI />;\n};\n","import React, { useEffect, useRef, useState } from 'react';\n\nimport { ContractAdapter } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useDerivedAccountStatus } from '../hooks/useDerivedAccountStatus';\nimport { useDerivedSwitchChainStatus } from '../hooks/useDerivedSwitchChainStatus';\n\n/**\n * Props for the NetworkSwitchManager component.\n */\nexport interface NetworkSwitchManagerProps {\n /** The adapter instance for the target network */\n adapter: ContractAdapter;\n /** The network ID we want to switch to */\n targetNetworkId: string;\n /** Callback when network switch completes (success or error) */\n onNetworkSwitchComplete?: () => void;\n}\n\n/**\n * Component that handles wallet network switching based on the selected network.\n *\n * This component manages the lifecycle of network switching operations,\n * coordinating between the wallet's current chain state and the target network.\n * It's designed to be used in any application that needs seamless wallet network switching.\n *\n * Features:\n * - Automatically initiates network switch when mounted with a target network\n * - Handles EVM chain switching gracefully\n * - No-ops for non-EVM networks that don't support chain switching\n * - Tracks switch attempts to prevent duplicate operations\n * - Provides completion callback for parent components to handle state cleanup\n */\nexport const NetworkSwitchManager: React.FC<NetworkSwitchManagerProps> = ({\n adapter,\n targetNetworkId,\n onNetworkSwitchComplete,\n}) => {\n const isMountedRef = useRef(true);\n const [hasAttemptedSwitch, setHasAttemptedSwitch] = useState(false);\n\n const { isConnected, chainId: currentChainIdFromHook } = useDerivedAccountStatus();\n const {\n switchChain: execSwitchNetwork,\n isSwitching: isSwitchingNetworkViaHook,\n error: switchNetworkError,\n } = useDerivedSwitchChainStatus();\n\n useEffect(() => {\n isMountedRef.current = true;\n logger.info(\n 'NetworkSwitchManager',\n `Mounted with target: ${targetNetworkId}, current attempt status: ${hasAttemptedSwitch}`\n );\n setHasAttemptedSwitch(false);\n return () => {\n logger.info('NetworkSwitchManager', `Unmounting, was for target: ${targetNetworkId}`);\n isMountedRef.current = false;\n };\n // hasAttemptedSwitch is intentionally omitted from deps: we only want to reset when targetNetworkId changes,\n // not when hasAttemptedSwitch itself changes (which would cause unnecessary re-renders)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [targetNetworkId]);\n\n useEffect(() => {\n logger.info('NetworkSwitchManager', 'State Update:', {\n target: targetNetworkId,\n adapterNetwork: adapter.networkConfig.id,\n isSwitching: isSwitchingNetworkViaHook,\n hookError: !!switchNetworkError,\n canExec: !!execSwitchNetwork,\n connected: isConnected,\n walletChain: currentChainIdFromHook,\n attempted: hasAttemptedSwitch,\n });\n }, [\n adapter,\n targetNetworkId,\n isSwitchingNetworkViaHook,\n switchNetworkError,\n execSwitchNetwork,\n isConnected,\n currentChainIdFromHook,\n hasAttemptedSwitch,\n ]);\n\n // Main Orchestration & Pre-flight Effect\n useEffect(() => {\n const completeOperation = (\n logMessage?: string,\n options: { notifyComplete?: boolean } = { notifyComplete: true }\n ) => {\n if (logMessage) logger.info('NetworkSwitchManager', logMessage);\n if (options.notifyComplete && isMountedRef.current && onNetworkSwitchComplete)\n onNetworkSwitchComplete();\n if (isMountedRef.current) setHasAttemptedSwitch(false);\n };\n\n if (!execSwitchNetwork) {\n completeOperation('No switchChain function available from hook. Operation halted.', {\n notifyComplete: false,\n });\n return;\n }\n\n if (isSwitchingNetworkViaHook && hasAttemptedSwitch) {\n // If hook is pending AND we initiated this attempt, let completion effect handle it.\n logger.info(\n 'NetworkSwitchManager',\n 'Hook reports switch in progress for current attempt. Waiting...'\n );\n return;\n }\n\n // If hasAttemptedSwitch is true here, but hook is NOT pending, means it completed/errored very fast.\n // The completion effect should pick this up.\n if (hasAttemptedSwitch && !isSwitchingNetworkViaHook) {\n logger.info(\n 'NetworkSwitchManager',\n 'Previous switch attempt concluded. Deferring to completion effect.'\n );\n return;\n }\n\n // If we are here, no attempt has been made for the current targetNetworkId yet, or a previous attempt on a *different* target completed.\n // OR, the hook is not pending from a previous unrelated call.\n // Reset attempt flag for a fresh try if it was from a different context/target.\n // Note: setHasAttemptedSwitch(false) is in mount effect for targetNetworkId change.\n\n // === Pre-flight checks for the current targetNetworkId ===\n if (adapter.networkConfig.id !== targetNetworkId) {\n completeOperation(\n `CRITICAL: Adapter (${adapter.networkConfig.id}) vs Target (${targetNetworkId}) mismatch. Operation halted.`,\n {\n notifyComplete: false,\n }\n );\n return;\n }\n if (!isConnected) {\n completeOperation('Wallet not connected (derived status). Awaiting connection.', {\n notifyComplete: false,\n });\n return;\n }\n if (!('chainId' in adapter.networkConfig)) {\n completeOperation(\n 'Network does not support chain switching (non-EVM). Operation complete (no-op).'\n );\n return;\n }\n const targetChainToBeSwitchedTo = Number(adapter.networkConfig.chainId);\n if (currentChainIdFromHook === targetChainToBeSwitchedTo) {\n completeOperation('Already on correct chain (derived status). Operation complete.');\n return;\n }\n\n const performSwitchActual = () => {\n if (!isMountedRef.current || isSwitchingNetworkViaHook || hasAttemptedSwitch) {\n // If hook became pending, or an attempt was already made and concluded, don't re-issue.\n logger.info(\n 'NetworkSwitchManager',\n `Switch attempt aborted in timeout or already handled. Conditions: isSwitching: ${isSwitchingNetworkViaHook}, hasAttempted: ${hasAttemptedSwitch}`\n );\n return;\n }\n logger.info(\n 'NetworkSwitchManager',\n `Attempting switch to ${targetChainToBeSwitchedTo} via derived hook.`\n );\n setHasAttemptedSwitch(true); // Mark that this specific attempt for this target is now starting\n execSwitchNetwork({ chainId: targetChainToBeSwitchedTo });\n };\n\n const timeoutId = setTimeout(performSwitchActual, 100);\n return () => clearTimeout(timeoutId);\n }, [\n adapter,\n targetNetworkId,\n execSwitchNetwork,\n isSwitchingNetworkViaHook,\n onNetworkSwitchComplete,\n isConnected,\n currentChainIdFromHook,\n hasAttemptedSwitch,\n ]);\n\n // Completion/Error Effect (handles outcomes of an initiated execSwitchNetwork call)\n useEffect(() => {\n if (!isMountedRef.current || !execSwitchNetwork || !hasAttemptedSwitch) return;\n\n // Only act if the hook is NOT pending AND an attempt was made\n if (!isSwitchingNetworkViaHook) {\n let completionMessage = 'Switch hook operation concluded.';\n if (switchNetworkError) {\n logger.error('NetworkSwitchManager', 'Error from derived switch hook:', switchNetworkError);\n completionMessage = 'Switch hook completed with error.';\n } else {\n logger.info('NetworkSwitchManager', 'Derived switch hook completed successfully.');\n }\n if (onNetworkSwitchComplete) onNetworkSwitchComplete();\n if (isMountedRef.current) setHasAttemptedSwitch(false);\n logger.info('NetworkSwitchManager', completionMessage);\n }\n }, [\n isSwitchingNetworkViaHook,\n switchNetworkError,\n execSwitchNetwork,\n hasAttemptedSwitch,\n onNetworkSwitchComplete,\n ]);\n\n return null;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["React","AnalyticsService","Button"],"sources":["../src/hooks/AdapterContext.tsx","../src/hooks/AdapterProvider.tsx","../src/hooks/WalletStateContext.ts","../src/hooks/useAdapterContext.ts","../src/hooks/WalletStateProvider.tsx","../src/hooks/AnalyticsContext.tsx","../src/hooks/AnalyticsProvider.tsx","../src/hooks/useAnalytics.ts","../src/hooks/useDerivedAccountStatus.ts","../src/hooks/useDerivedSwitchChainStatus.ts","../src/hooks/useDerivedChainInfo.ts","../src/hooks/useDerivedConnectStatus.ts","../src/hooks/useDerivedDisconnect.ts","../src/hooks/useWalletReconnectionHandler.ts","../src/components/WalletConnectionUI.tsx","../src/components/WalletConnectionHeader.tsx","../src/components/NetworkSwitchManager.tsx"],"sourcesContent":["/**\n * AdapterContext.tsx\n *\n * This file defines the React Context used for the adapter singleton pattern.\n * It provides types and the context definition, but the actual implementation\n * is in the AdapterProvider component.\n *\n * The adapter singleton pattern ensures that only one adapter instance exists\n * per network configuration, which is critical for consistent wallet connection\n * state across the application.\n */\nimport { createContext } from 'react';\n\nimport type { ContractAdapter, NetworkConfig } from '@openzeppelin/ui-types';\n\n/**\n * Registry type that maps network IDs to their corresponding adapter instances\n * This is the core data structure for the singleton pattern\n */\nexport interface AdapterRegistry {\n [networkId: string]: ContractAdapter;\n}\n\n/**\n * Context value interface defining what's provided through the context\n * The main functionality is getAdapterForNetwork which either returns\n * an existing adapter or initiates loading of a new one\n */\nexport interface AdapterContextValue {\n getAdapterForNetwork: (networkConfig: NetworkConfig | null) => {\n adapter: ContractAdapter | null;\n isLoading: boolean;\n };\n}\n\n/**\n * The React Context that provides adapter registry access throughout the app\n * Components can access this through the useAdapterContext hook\n */\nexport const AdapterContext = createContext<AdapterContextValue | null>(null);\n","/**\n * AdapterProvider.tsx\n *\n * This file implements the Adapter Provider component which manages a registry of\n * adapter instances. It's a key part of the adapter singleton pattern which ensures\n * that only one adapter instance exists per network configuration.\n *\n * The adapter registry is shared across the application via React Context, allowing\n * components to access the same adapter instances and maintain consistent wallet\n * connection state.\n *\n * IMPORTANT: This implementation needs special care to avoid React state update errors\n * during component rendering. Direct state updates during render are not allowed, which\n * is why adapter loading is controlled carefully.\n */\nimport { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type { ContractAdapter, NetworkConfig } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { AdapterContext, AdapterContextValue, AdapterRegistry } from './AdapterContext';\n\nexport interface AdapterProviderProps {\n children: ReactNode;\n /** Function to resolve/create an adapter instance for a given NetworkConfig. */\n resolveAdapter: (networkConfig: NetworkConfig) => Promise<ContractAdapter>;\n}\n\n/**\n * Provider component that manages adapter instances centrally\n * to avoid creating multiple instances of the same adapter.\n *\n * This component:\n * 1. Maintains a registry of adapter instances by network ID\n * 2. Tracks loading states for adapters being initialized\n * 3. Provides a function to get or load adapters for specific networks\n * 4. Ensures adapter instances are reused when possible\n */\nexport function AdapterProvider({ children, resolveAdapter }: AdapterProviderProps) {\n // Registry to store adapter instances by network ID\n const [adapterRegistry, setAdapterRegistry] = useState<AdapterRegistry>({});\n\n // Track loading states by network ID\n const [loadingNetworks, setLoadingNetworks] = useState<Set<string>>(new Set());\n\n // Log registry status on changes\n useEffect(() => {\n const adapterCount = Object.keys(adapterRegistry).length;\n if (adapterCount > 0) {\n logger.info('AdapterProvider', `Registry contains ${adapterCount} adapters:`, {\n networkIds: Object.keys(adapterRegistry),\n loadingCount: loadingNetworks.size,\n loadingNetworkIds: Array.from(loadingNetworks),\n });\n }\n }, [adapterRegistry, loadingNetworks]);\n\n /**\n * Function to get or create an adapter for a network\n *\n * IMPORTANT: The actual adapter loading is handled in the useConfiguredAdapterSingleton hook\n * to avoid React state updates during render, which would cause errors.\n *\n * This function:\n * 1. Returns existing adapters immediately if available\n * 2. Reports loading state for adapters being initialized\n * 3. Initiates adapter loading when needed\n */\n const getAdapterForNetwork = useCallback(\n (networkConfig: NetworkConfig | null) => {\n if (!networkConfig) {\n return { adapter: null, isLoading: false };\n }\n\n const networkId = networkConfig.id;\n\n // Debug log to track adapter requests\n logger.debug('AdapterProvider', `Adapter requested for network ${networkId}`);\n\n // If we already have this adapter, return it\n if (adapterRegistry[networkId]) {\n logger.debug('AdapterProvider', `Using existing adapter for network ${networkId}`);\n return {\n adapter: adapterRegistry[networkId],\n isLoading: false,\n };\n }\n\n // If we're already loading this adapter, indicate loading\n if (loadingNetworks.has(networkId)) {\n logger.debug('AdapterProvider', `Adapter for network ${networkId} is currently loading`);\n return {\n adapter: null,\n isLoading: true,\n };\n }\n\n // Start loading the adapter\n // NOTE: This state update during render is handled safely in the useConfiguredAdapterSingleton hook\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.add(networkId);\n return newSet;\n });\n\n logger.info(\n 'AdapterProvider',\n `Starting adapter initialization for network ${networkId} (${networkConfig.name})`\n );\n\n // Use the passed-in resolveAdapter function\n void resolveAdapter(networkConfig)\n .then((adapter) => {\n logger.info('AdapterProvider', `Adapter for network ${networkId} loaded successfully`, {\n type: adapter.constructor.name,\n objectId: Object.prototype.toString.call(adapter),\n });\n\n // Update registry with new adapter\n setAdapterRegistry((prev) => ({\n ...prev,\n [networkId]: adapter,\n }));\n\n // Remove from loading networks\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.delete(networkId);\n return newSet;\n });\n })\n .catch((error) => {\n logger.error('AdapterProvider', `Error loading adapter for network ${networkId}:`, error);\n\n // Remove from loading networks on error\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.delete(networkId);\n return newSet;\n });\n });\n\n return {\n adapter: null,\n isLoading: true,\n };\n },\n [adapterRegistry, loadingNetworks, resolveAdapter]\n );\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue = useMemo<AdapterContextValue>(\n () => ({\n getAdapterForNetwork,\n }),\n [getAdapterForNetwork]\n );\n\n return <AdapterContext.Provider value={contextValue}>{children}</AdapterContext.Provider>;\n}\n","import React, { createContext } from 'react';\n\nimport type {\n ContractAdapter,\n EcosystemSpecificReactHooks,\n NetworkConfig,\n UiKitConfiguration,\n} from '@openzeppelin/ui-types';\n\nexport interface WalletStateContextValue {\n // Globally selected network state\n activeNetworkId: string | null;\n setActiveNetworkId: (networkId: string | null) => void;\n activeNetworkConfig: NetworkConfig | null;\n\n // Active adapter state\n activeAdapter: ContractAdapter | null;\n isAdapterLoading: boolean;\n\n // Facade hooks object from the active adapter\n // Consumers will call these hooks (e.g., walletFacadeHooks.useAccount())\n walletFacadeHooks: EcosystemSpecificReactHooks | null;\n reconfigureActiveAdapterUiKit: (uiKitConfig?: Partial<UiKitConfiguration>) => void;\n}\n\n/**\n * Shared Global Context Pattern\n * =============================\n *\n * WHY THIS EXISTS:\n * When bundlers (like Vite's optimizeDeps with esbuild) pre-bundle dependencies,\n * they may inline transitive dependencies like @openzeppelin/ui-react into the\n * consuming package's bundle. This creates MULTIPLE instances of this module:\n *\n * 1. The app's direct import → packages/react/dist/index.js\n * 2. The adapter's inlined copy → .vite/deps/@openzeppelin_ui-builder-adapter-evm.js\n *\n * Since React contexts use referential identity, these two module instances have\n * DIFFERENT context objects. When the adapter's components call useWalletState(),\n * they look for a context that was never provided (because WalletStateProvider\n * uses the app's context, not the adapter's inlined copy).\n *\n * SOLUTION:\n * Store the context object on globalThis so ALL module instances share the same\n * React context, regardless of how they were loaded or bundled.\n *\n * WHEN IS THIS NEEDED:\n * - Development with Vite's dependency pre-bundling (optimizeDeps)\n * - When adapters are installed from npm (not workspace-linked with same bundler)\n * - Any scenario where @openzeppelin/ui-react might be duplicated\n *\n * PRODUCTION APPS:\n * In production builds where the app and adapters are bundled together with proper\n * deduplication (e.g., via bundler configuration or peer dependencies), this\n * workaround may not be strictly necessary. However, it provides a safety net\n * and has minimal overhead.\n */\n\n/**\n * Use Symbol.for() to create a globally unique key that is consistent across\n * all module instances. Unlike Symbol(), Symbol.for() returns the same symbol\n * for the same key string, which is essential for cross-module sharing.\n */\nconst WALLET_STATE_CONTEXT_KEY = Symbol.for('@openzeppelin/ui-react/WalletStateContext');\n\n/**\n * Type-safe interface for the global object extension.\n * This provides better type safety than using Record<string, unknown>.\n */\ninterface GlobalWithWalletContext {\n [WALLET_STATE_CONTEXT_KEY]?: React.Context<WalletStateContextValue | undefined>;\n}\n\n/**\n * Retrieves or creates the shared WalletStateContext.\n *\n * NOTE ON ATOMICITY:\n * The check-then-set pattern here is not atomic, but this is acceptable because:\n * 1. JavaScript is single-threaded; module initialization is synchronous\n * 2. Even if multiple modules initialize \"simultaneously\" during parallel loading,\n * they execute sequentially on the main thread\n * 3. The worst case (two contexts created) would only happen if the check and set\n * were somehow interleaved, which cannot occur in JS's execution model\n * 4. For React contexts specifically, having the same context object is what matters,\n * and this pattern guarantees that after initialization\n */\nfunction getOrCreateSharedContext(): React.Context<WalletStateContextValue | undefined> {\n const global = globalThis as GlobalWithWalletContext;\n\n if (!global[WALLET_STATE_CONTEXT_KEY]) {\n global[WALLET_STATE_CONTEXT_KEY] = createContext<WalletStateContextValue | undefined>(\n undefined\n );\n }\n\n return global[WALLET_STATE_CONTEXT_KEY];\n}\n\nexport const WalletStateContext = getOrCreateSharedContext();\n\n/**\n * Hook to access wallet state from WalletStateProvider.\n * @throws Error if used outside of WalletStateProvider\n */\nexport function useWalletState(): WalletStateContextValue {\n const context = React.useContext(WalletStateContext);\n if (context === undefined) {\n throw new Error('useWalletState must be used within a WalletStateProvider');\n }\n return context;\n}\n","/**\n * useAdapterContext.ts\n *\n * This file provides a hook to access the AdapterContext throughout the application.\n * It's a critical part of the adapter singleton pattern, allowing components to\n * access the centralized adapter registry.\n *\n * The adapter singleton pattern ensures:\n * - Only one adapter instance exists per network\n * - Wallet connection state is consistent across the app\n * - Better performance by eliminating redundant adapter initialization\n */\nimport { useContext } from 'react';\n\nimport { AdapterContext, AdapterContextValue } from './AdapterContext';\n\n/**\n * Hook to access the adapter context\n *\n * This hook provides access to the getAdapterForNetwork function which\n * retrieves or creates adapter instances from the singleton registry.\n *\n * Components should typically use useConfiguredAdapterSingleton instead\n * of this hook directly, as it handles React state update timing properly.\n *\n * @throws Error if used outside of an AdapterProvider context\n * @returns The adapter context value\n */\nexport function useAdapterContext(): AdapterContextValue {\n const context = useContext(AdapterContext);\n\n if (!context) {\n throw new Error('useAdapterContext must be used within an AdapterProvider');\n }\n\n return context;\n}\n","import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type {\n ContractAdapter,\n EcosystemReactUiProviderProps,\n EcosystemSpecificReactHooks,\n NativeConfigLoader,\n NetworkConfig,\n UiKitConfiguration,\n} from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useAdapterContext } from './useAdapterContext';\nimport { WalletStateContext, type WalletStateContextValue } from './WalletStateContext';\n\n// Extended adapter interface that includes the callback-based configureUiKit method\ninterface ExtendedContractAdapter extends ContractAdapter {\n configureUiKit?(\n config: Partial<UiKitConfiguration>,\n options?: {\n loadUiKitNativeConfig?: (kitName: string) => Promise<Record<string, unknown> | null>;\n }\n ): void | Promise<void>;\n getEcosystemReactUiContextProvider?():\n | React.ComponentType<EcosystemReactUiProviderProps>\n | undefined;\n}\n\nexport interface WalletStateProviderProps {\n children: ReactNode;\n /** Optional initial network ID to set as active when the provider mounts. */\n initialNetworkId?: string | null;\n /** Function to retrieve a NetworkConfig object by its ID. */\n getNetworkConfigById: (\n networkId: string\n ) => Promise<NetworkConfig | null | undefined> | NetworkConfig | null | undefined;\n /**\n * Optional generic function to load configuration modules by relative path.\n * The adapter is responsible for constructing the conventional path (e.g., './config/wallet/[kitName].config').\n * @param relativePath The conventional relative path to the configuration module.\n * @returns A Promise resolving to the configuration object (expected to have a default export) or null.\n */\n loadConfigModule?: NativeConfigLoader;\n}\n\n/**\n * Configures the adapter's UI kit and returns the UI provider component and hooks.\n */\nasync function configureAdapterUiKit(\n adapter: ExtendedContractAdapter,\n loadConfigModule?: (relativePath: string) => Promise<Record<string, unknown> | null>,\n programmaticOverrides: Partial<UiKitConfiguration> = {}\n): Promise<{\n providerComponent: React.ComponentType<EcosystemReactUiProviderProps> | null;\n hooks: EcosystemSpecificReactHooks | null;\n}> {\n try {\n // Ensure the adapter (and thus the EvmUiKitManager) is configured.\n if (typeof adapter.configureUiKit === 'function') {\n logger.info(\n '[WSP configureAdapterUiKit] Calling configureUiKit for adapter:',\n adapter?.networkConfig?.id\n );\n await adapter.configureUiKit(programmaticOverrides, {\n loadUiKitNativeConfig: loadConfigModule,\n });\n logger.info(\n '[WSP configureAdapterUiKit] configureUiKit completed for adapter:',\n adapter?.networkConfig?.id\n );\n }\n\n const providerComponent = adapter.getEcosystemReactUiContextProvider?.() || null;\n const hooks = adapter.getEcosystemReactHooks?.() || null;\n\n logger.info('[WSP configureAdapterUiKit]', 'UI provider and hooks retrieved successfully.');\n\n return { providerComponent, hooks };\n } catch (error) {\n logger.error('[WSP configureAdapterUiKit]', 'Error during adapter UI setup:', error);\n throw error; // Re-throw to be handled by caller\n }\n}\n\n/**\n * @name WalletStateProvider\n * @description This provider is a central piece of the application's state management for wallet and network interactions.\n * It is responsible for:\n * 1. Managing the globally selected active network ID (`activeNetworkId`).\n * 2. Deriving the full `NetworkConfig` object (`activeNetworkConfig`) for the active network.\n * 3. Fetching and providing the corresponding `ContractAdapter` instance (`activeAdapter`) for the active network,\n * leveraging the `AdapterProvider` to ensure adapter singletons.\n * 4. Storing and providing the `EcosystemSpecificReactHooks` (`walletFacadeHooks`) from the active adapter.\n * 5. Rendering the adapter-specific UI context provider (e.g., WagmiProvider for EVM) around its children,\n * which is essential for the facade hooks to function correctly.\n * 6. Providing a function (`setActiveNetworkId`) to change the globally active network.\n *\n * Consumers use the `useWalletState()` hook to access this global state.\n * It should be placed high in the component tree, inside an `<AdapterProvider>`.\n */\nexport function WalletStateProvider({\n children,\n initialNetworkId = null,\n getNetworkConfigById,\n loadConfigModule,\n}: WalletStateProviderProps) {\n // State for the ID of the globally selected network.\n const [currentGlobalNetworkId, setCurrentGlobalNetworkIdState] = useState<string | null>(\n initialNetworkId\n );\n // State for the full NetworkConfig object of the globally selected network.\n const [currentGlobalNetworkConfig, setCurrentGlobalNetworkConfig] =\n useState<NetworkConfig | null>(null);\n\n // State for the active ContractAdapter instance corresponding to the currentGlobalNetworkConfig.\n const [globalActiveAdapter, setGlobalActiveAdapter] = useState<ContractAdapter | null>(null);\n // Loading state for the globalActiveAdapter.\n const [isGlobalAdapterLoading, setIsGlobalAdapterLoading] = useState<boolean>(false);\n // State for the facade hooks provided by the globalActiveAdapter.\n const [walletFacadeHooks, setWalletFacadeHooks] = useState<EcosystemSpecificReactHooks | null>(\n null\n );\n // State to hold the Component Type\n const [AdapterUiContextProviderToRender, setAdapterUiContextProviderToRender] =\n useState<React.ComponentType<EcosystemReactUiProviderProps> | null>(null);\n\n // New state to act as a manual trigger for re-configuring the UI kit.\n const [uiKitConfigVersion, setUiKitConfigVersion] = useState(0);\n // State to hold programmatic overrides for the next reconfiguration.\n const [programmaticUiKitConfig, setProgrammaticUiKitConfig] = useState<\n Partial<UiKitConfiguration> | undefined\n >(undefined);\n\n // Consume AdapterContext to get the function for fetching adapter instances.\n const { getAdapterForNetwork } = useAdapterContext();\n\n // Effect to derive the full NetworkConfig object when currentGlobalNetworkId changes.\n useEffect(() => {\n const abortController = new AbortController();\n\n async function fetchNetworkConfig() {\n if (!currentGlobalNetworkId) {\n // If currentGlobalNetworkId is null, clear the config.\n if (!abortController.signal.aborted) {\n setCurrentGlobalNetworkConfig(null);\n }\n return;\n }\n\n try {\n const config = await Promise.resolve(getNetworkConfigById(currentGlobalNetworkId));\n if (!abortController.signal.aborted) {\n setCurrentGlobalNetworkConfig(config || null);\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n logger.error('[WSP fetchNetworkConfig]', 'Failed to fetch network config:', error);\n setCurrentGlobalNetworkConfig(null);\n }\n }\n }\n\n void fetchNetworkConfig();\n return () => abortController.abort();\n }, [currentGlobalNetworkId, getNetworkConfigById]);\n\n // Effect to load the active adapter and its UI capabilities when currentGlobalNetworkConfig changes.\n useEffect(() => {\n const abortController = new AbortController();\n\n async function loadAdapterAndConfigureUi() {\n if (!currentGlobalNetworkConfig) {\n // No network config - clear everything\n if (!abortController.signal.aborted) {\n setGlobalActiveAdapter(null);\n setIsGlobalAdapterLoading(false);\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n }\n return;\n }\n\n const { adapter: newAdapter, isLoading: newIsLoading } = getAdapterForNetwork(\n currentGlobalNetworkConfig\n ) as { adapter: ExtendedContractAdapter | null; isLoading: boolean };\n\n if (abortController.signal.aborted) return;\n\n // Update loading state immediately, but defer exposing the new adapter\n // until its UI provider and hooks are configured to avoid mismatch renders.\n setIsGlobalAdapterLoading(newIsLoading);\n\n if (newAdapter && !newIsLoading) {\n try {\n const { providerComponent, hooks } = await configureAdapterUiKit(\n newAdapter,\n loadConfigModule,\n programmaticUiKitConfig\n );\n\n if (!abortController.signal.aborted) {\n // Ensure provider component and hooks are ready before exposing the new adapter\n // to consumers. This prevents rendering ecosystem-specific components under the\n // previous ecosystem provider (e.g., Stellar components under EVM provider).\n setAdapterUiContextProviderToRender(() => providerComponent);\n setWalletFacadeHooks(hooks);\n setGlobalActiveAdapter(newAdapter);\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n logger.error(\n '[WSP loadAdapterAndConfigureUi]',\n 'Error during adapter UI setup:',\n error\n );\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n }\n }\n } else if (!newAdapter && !newIsLoading) {\n // Adapter is null and not loading, clear UI specific state\n if (!abortController.signal.aborted) {\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n setGlobalActiveAdapter(null);\n }\n }\n // If newIsLoading is true, retain previous AdapterUiContextProviderToRender and hooks\n // to prevent UI flicker, EvmWalletUiRoot will handle its loading state internally.\n }\n\n void loadAdapterAndConfigureUi();\n return () => abortController.abort();\n }, [\n currentGlobalNetworkConfig,\n getAdapterForNetwork,\n loadConfigModule,\n uiKitConfigVersion,\n programmaticUiKitConfig,\n ]);\n\n /**\n * Callback to set the globally active network ID.\n * Also clears dependent states (config, adapter, hooks) if the network ID is cleared.\n */\n const setActiveNetworkIdCallback = useCallback((networkId: string | null) => {\n logger.info('WalletStateProvider', `Setting global network ID to: ${networkId}`);\n setCurrentGlobalNetworkIdState(networkId); // This will trigger the fetchNetworkConfig effect.\n if (!networkId) {\n // If clearing the network, proactively clear downstream states.\n // The effects above will also clear them, but this is more immediate.\n setCurrentGlobalNetworkConfig(null);\n setGlobalActiveAdapter(null);\n setIsGlobalAdapterLoading(false);\n setWalletFacadeHooks(null);\n // Do not clear AdapterUiContextProviderToRender here, let the effect handle it\n // based on whether it's a loading transition or an actual clearing.\n // setAdapterUiContextProviderToRender(() => null);\n }\n }, []); // Empty dependency array as it only uses setters from useState.\n\n /**\n * Callback to explicitly trigger a re-configuration of the active adapter's UI kit.\n * This is useful when a UI kit setting changes (e.g., via a wizard) without a network change.\n */\n const reconfigureActiveAdapterUiKit = useCallback(\n (uiKitConfig?: Partial<UiKitConfiguration>) => {\n logger.info(\n 'WalletStateProvider',\n 'Explicitly triggering UI kit re-configuration by bumping version.',\n uiKitConfig\n );\n setProgrammaticUiKitConfig(uiKitConfig);\n setUiKitConfigVersion((v) => v + 1);\n },\n [setProgrammaticUiKitConfig, setUiKitConfigVersion]\n );\n\n // The context value now only provides the raw walletFacadeHooks object.\n // Consumers are responsible for calling specific hooks from it and handling their results.\n const contextValue = useMemo<WalletStateContextValue>(\n () => ({\n activeNetworkId: currentGlobalNetworkId,\n setActiveNetworkId: setActiveNetworkIdCallback,\n activeNetworkConfig: currentGlobalNetworkConfig,\n activeAdapter: globalActiveAdapter,\n isAdapterLoading: isGlobalAdapterLoading,\n walletFacadeHooks,\n reconfigureActiveAdapterUiKit,\n }),\n [\n currentGlobalNetworkId,\n setActiveNetworkIdCallback,\n currentGlobalNetworkConfig,\n globalActiveAdapter,\n isGlobalAdapterLoading,\n walletFacadeHooks,\n reconfigureActiveAdapterUiKit,\n ]\n );\n\n const ActualProviderToRender = AdapterUiContextProviderToRender;\n let childrenToRender: ReactNode;\n\n if (ActualProviderToRender) {\n // Generate a unique key based on adapter's network ecosystem and ID\n // This ensures proper unmounting/mounting when switching between EVM/Stellar/etc.\n const key = `${globalActiveAdapter?.networkConfig?.ecosystem || 'unknown'}-${globalActiveAdapter?.networkConfig?.id || 'unknown'}`;\n\n // EvmWalletUiRoot (and similar for other adapters) no longer needs uiKitConfiguration prop\n // as it manages its own configuration internally via the EvmUiKitManager or equivalent.\n logger.info(\n '[WSP RENDER]',\n 'Rendering adapter-provided UI context provider:',\n ActualProviderToRender.displayName || ActualProviderToRender.name || 'UnknownComponent',\n 'with key:',\n key\n );\n childrenToRender = <ActualProviderToRender key={key}>{children}</ActualProviderToRender>;\n } else {\n logger.info(\n '[WSP RENDER]',\n 'No adapter UI context provider to render. Rendering direct children.'\n );\n childrenToRender = children;\n }\n\n return (\n <WalletStateContext.Provider value={contextValue}>\n {childrenToRender}\n </WalletStateContext.Provider>\n );\n}\n","import { createContext, useContext } from 'react';\n\n/**\n * Analytics context value interface.\n * Provides access to analytics functionality throughout the React component tree.\n */\nexport interface AnalyticsContextValue {\n /** Google Analytics tag ID */\n tagId?: string;\n /**\n * Check if analytics is enabled via feature flag.\n * Returns fresh state on each call to handle dynamic feature flag changes.\n */\n isEnabled: () => boolean;\n /** Initialize analytics with optional tag ID override */\n initialize: (tagIdOverride?: string) => void;\n /**\n * Track a generic event with custom parameters.\n * Use this for app-specific events.\n *\n * @example\n * ```typescript\n * trackEvent('button_clicked', { button_name: 'submit' });\n * ```\n */\n trackEvent: (eventName: string, parameters: Record<string, string | number>) => void;\n /**\n * Track page view event.\n *\n * @example\n * ```typescript\n * trackPageView('Dashboard', '/dashboard');\n * ```\n */\n trackPageView: (pageName: string, pagePath: string) => void;\n /**\n * Track network selection event.\n *\n * @example\n * ```typescript\n * trackNetworkSelection('ethereum-mainnet', 'evm');\n * ```\n */\n trackNetworkSelection: (networkId: string, ecosystem: string) => void;\n}\n\n/**\n * Analytics context for providing analytics functionality to React components.\n * Must be used within an AnalyticsProvider.\n */\nexport const AnalyticsContext = createContext<AnalyticsContextValue | null>(null);\n\n/**\n * Internal hook to access analytics context.\n * Throws an error if used outside of an AnalyticsProvider.\n *\n * @internal\n * @throws Error if used outside of AnalyticsProvider\n */\nexport const useAnalyticsContext = (): AnalyticsContextValue => {\n const context = useContext(AnalyticsContext);\n if (!context) {\n throw new Error('useAnalyticsContext must be used within an AnalyticsProvider');\n }\n return context;\n};\n","import React, { ReactNode, useEffect, useMemo } from 'react';\n\nimport { AnalyticsService, logger } from '@openzeppelin/ui-utils';\n\nimport { AnalyticsContext, AnalyticsContextValue } from './AnalyticsContext';\n\n/**\n * Props for the AnalyticsProvider component\n */\nexport interface AnalyticsProviderProps {\n /** Google Analytics tag ID (e.g., 'G-XXXXXXXXXX') */\n tagId?: string;\n /** Whether to automatically initialize analytics on mount (default: true) */\n autoInit?: boolean;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Analytics Provider component.\n * Provides analytics functionality throughout the React component tree.\n *\n * @example\n * ```tsx\n * function App() {\n * return (\n * <AnalyticsProvider tagId={import.meta.env.VITE_GA_TAG_ID} autoInit={true}>\n * <YourApp />\n * </AnalyticsProvider>\n * );\n * }\n * ```\n */\nexport const AnalyticsProvider: React.FC<AnalyticsProviderProps> = ({\n tagId,\n autoInit = true,\n children,\n}) => {\n useEffect(() => {\n if (autoInit && tagId) {\n AnalyticsService.initialize(tagId);\n }\n }, [tagId, autoInit]);\n\n const contextValue: AnalyticsContextValue = useMemo(\n () => ({\n tagId,\n isEnabled: () => AnalyticsService.isEnabled(),\n initialize: (tagIdOverride?: string) => {\n const effectiveTagId = tagIdOverride || tagId;\n if (effectiveTagId) {\n AnalyticsService.initialize(effectiveTagId);\n }\n },\n trackEvent: (eventName: string, parameters: Record<string, string | number>) => {\n try {\n AnalyticsService.trackEvent(eventName, parameters);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking event:', error);\n }\n },\n trackPageView: (pageName: string, pagePath: string) => {\n try {\n AnalyticsService.trackPageView(pageName, pagePath);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking page view:', error);\n }\n },\n trackNetworkSelection: (networkId: string, ecosystem: string) => {\n try {\n AnalyticsService.trackNetworkSelection(networkId, ecosystem);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking network selection:', error);\n }\n },\n }),\n [tagId]\n );\n\n return <AnalyticsContext.Provider value={contextValue}>{children}</AnalyticsContext.Provider>;\n};\n","import { useAnalyticsContext } from './AnalyticsContext';\n\n/**\n * Custom hook for accessing analytics functionality.\n *\n * This hook provides a convenient interface for tracking user interactions\n * throughout the application. It must be used within an AnalyticsProvider.\n *\n * For app-specific tracking methods, create a wrapper hook that uses this\n * hook and adds your custom tracking functions.\n *\n * @example\n * ```tsx\n * // Basic usage\n * function MyComponent() {\n * const { trackEvent, trackPageView, isEnabled } = useAnalytics();\n *\n * const handleClick = () => {\n * trackEvent('button_clicked', { button_name: 'submit' });\n * };\n *\n * return (\n * <div>\n * Analytics enabled: {isEnabled().toString()}\n * <button onClick={handleClick}>Submit</button>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Creating app-specific wrapper hook\n * function useMyAppAnalytics() {\n * const analytics = useAnalytics();\n *\n * return {\n * ...analytics,\n * trackFormSubmit: (formName: string) => {\n * analytics.trackEvent('form_submitted', { form_name: formName });\n * },\n * };\n * }\n * ```\n *\n * @returns Analytics context with tracking methods and state\n * @throws Error if used outside of AnalyticsProvider\n */\nexport const useAnalytics = () => {\n try {\n return useAnalyticsContext();\n } catch {\n throw new Error('useAnalytics must be used within an AnalyticsProvider');\n }\n};\n","// Assumes WalletStateContext exports useWalletState\nimport { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedAccountStatus {\n isConnected: boolean;\n address?: string;\n chainId?: number;\n // Potentially add other commonly used and safely extracted properties from useAccount's result\n}\n\nconst defaultAccountStatus: DerivedAccountStatus = {\n isConnected: false,\n address: undefined,\n chainId: undefined,\n};\n\n/**\n * A custom hook that consumes useWalletState to get the walletFacadeHooks,\n * then calls the useAccount facade hook (if available) and returns a structured,\n * safely-accessed account status (isConnected, address, chainId).\n * Provides default values if the hook or its properties are unavailable.\n */\nexport function useDerivedAccountStatus(): DerivedAccountStatus {\n const { walletFacadeHooks } = useWalletState();\n\n // Call the useAccount hook from the facade\n const accountHookOutput = walletFacadeHooks?.useAccount\n ? walletFacadeHooks.useAccount()\n : undefined;\n\n if (isRecordWithProperties(accountHookOutput)) {\n const isConnected =\n 'isConnected' in accountHookOutput && typeof accountHookOutput.isConnected === 'boolean'\n ? accountHookOutput.isConnected\n : defaultAccountStatus.isConnected;\n const address =\n 'address' in accountHookOutput && typeof accountHookOutput.address === 'string'\n ? accountHookOutput.address\n : defaultAccountStatus.address;\n const chainId =\n 'chainId' in accountHookOutput && typeof accountHookOutput.chainId === 'number'\n ? accountHookOutput.chainId\n : defaultAccountStatus.chainId;\n return { isConnected, address, chainId };\n }\n return defaultAccountStatus;\n}\n","import { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\n// Define the expected return shape for the derived hook\nexport interface DerivedSwitchChainStatus {\n /** Function to initiate a network switch. Undefined if not available. */\n switchChain?: (args: { chainId: number }) => void;\n /** True if a network switch is currently in progress. */\n isSwitching: boolean;\n /** Error object if the last switch attempt failed, otherwise null. */\n error: Error | null;\n}\n\nconst defaultSwitchChainStatus: DerivedSwitchChainStatus = {\n switchChain: undefined,\n isSwitching: false,\n error: null,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useSwitchChain` facade hook (if available) and returns a structured,\n * safely-accessed status and control function for network switching.\n * Provides default values if the hook or its properties are unavailable.\n */\nexport function useDerivedSwitchChainStatus(): DerivedSwitchChainStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const switchChainHookOutput = walletFacadeHooks?.useSwitchChain\n ? walletFacadeHooks.useSwitchChain()\n : undefined;\n\n if (isRecordWithProperties(switchChainHookOutput)) {\n const execSwitchFn =\n 'switchChain' in switchChainHookOutput &&\n typeof switchChainHookOutput.switchChain === 'function'\n ? (switchChainHookOutput.switchChain as (args: { chainId: number }) => void)\n : defaultSwitchChainStatus.switchChain;\n\n const isPending =\n 'isPending' in switchChainHookOutput && typeof switchChainHookOutput.isPending === 'boolean'\n ? switchChainHookOutput.isPending\n : defaultSwitchChainStatus.isSwitching;\n\n const err =\n 'error' in switchChainHookOutput && switchChainHookOutput.error instanceof Error\n ? switchChainHookOutput.error\n : defaultSwitchChainStatus.error;\n\n return { switchChain: execSwitchFn, isSwitching: isPending, error: err };\n }\n\n return defaultSwitchChainStatus;\n}\n","import { logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedChainInfo {\n /** The current chain ID reported by the wallet's active connection, if available. */\n currentChainId?: number;\n /** Array of chains configured in the underlying wallet library (e.g., wagmi). Type is any[] for generic compatibility. */\n availableChains: unknown[];\n}\n\nconst defaultChainInfo: DerivedChainInfo = {\n currentChainId: undefined,\n availableChains: [],\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useChainId` and `useChains` facade hooks (if available)\n * and returns a structured object with this information.\n * Provides default values if the hooks or their properties are unavailable.\n */\nexport function useDerivedChainInfo(): DerivedChainInfo {\n const { walletFacadeHooks } = useWalletState();\n\n let chainIdToReturn: number | undefined = defaultChainInfo.currentChainId;\n const chainIdHookOutput = walletFacadeHooks?.useChainId\n ? walletFacadeHooks.useChainId()\n : undefined;\n // The useChainId hook from wagmi directly returns the number or undefined\n if (typeof chainIdHookOutput === 'number') {\n chainIdToReturn = chainIdHookOutput;\n } else if (chainIdHookOutput !== undefined) {\n // If it's not a number but not undefined, log a warning but use default. Could be an adapter returning unexpected type.\n logger.warn(\n 'useDerivedChainInfo',\n 'useChainId facade hook returned non-numeric value:',\n chainIdHookOutput\n );\n }\n\n let chainsToReturn: unknown[] = defaultChainInfo.availableChains;\n const chainsHookOutput = walletFacadeHooks?.useChains ? walletFacadeHooks.useChains() : undefined;\n // The useChains hook from wagmi directly returns an array of Chain objects\n if (Array.isArray(chainsHookOutput)) {\n chainsToReturn = chainsHookOutput;\n } else if (chainsHookOutput !== undefined) {\n logger.warn(\n 'useDerivedChainInfo',\n 'useChains facade hook returned non-array value:',\n chainsHookOutput\n );\n }\n\n return { currentChainId: chainIdToReturn, availableChains: chainsToReturn };\n}\n","import type { Connector } from '@openzeppelin/ui-types';\nimport { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\n// Assuming Connector type is available\n\nexport interface DerivedConnectStatus {\n /** Function to initiate a connection, usually takes a connector. Undefined if not available. */\n connect?: (args?: { connector?: Connector /* or string for id */ }) => void;\n /** Array of available connectors. Type is any[] for broad compatibility until Connector type is fully generic here. */\n connectors: Connector[]; // Or any[] if Connector type from types pkg is too specific for generic hook here\n /** True if a connection attempt is in progress. */\n isConnecting: boolean;\n /** Error object if the last connection attempt failed, otherwise null. */\n error: Error | null;\n /** The connector a connection is pending for, if any. */\n pendingConnector?: Connector; // Or any\n}\n\nconst defaultConnectStatus: DerivedConnectStatus = {\n connect: undefined,\n connectors: [],\n isConnecting: false,\n error: null,\n pendingConnector: undefined,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useConnect` facade hook (if available) and returns a structured,\n * safely-accessed status and control functions for wallet connection.\n */\nexport function useDerivedConnectStatus(): DerivedConnectStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const connectHookOutput = walletFacadeHooks?.useConnect\n ? walletFacadeHooks.useConnect()\n : undefined;\n\n if (isRecordWithProperties(connectHookOutput)) {\n const connectFn =\n 'connect' in connectHookOutput && typeof connectHookOutput.connect === 'function'\n ? (connectHookOutput.connect as (args?: { connector?: Connector }) => void)\n : defaultConnectStatus.connect;\n\n const conns =\n 'connectors' in connectHookOutput && Array.isArray(connectHookOutput.connectors)\n ? (connectHookOutput.connectors as Connector[])\n : defaultConnectStatus.connectors;\n\n const isPending =\n 'isPending' in connectHookOutput && typeof connectHookOutput.isPending === 'boolean'\n ? connectHookOutput.isPending\n : 'isLoading' in connectHookOutput && typeof connectHookOutput.isLoading === 'boolean'\n ? connectHookOutput.isLoading\n : defaultConnectStatus.isConnecting;\n\n const err =\n 'error' in connectHookOutput && connectHookOutput.error instanceof Error\n ? connectHookOutput.error\n : defaultConnectStatus.error;\n\n const pendingConn =\n 'pendingConnector' in connectHookOutput &&\n typeof connectHookOutput.pendingConnector === 'object' // Assuming Connector is an object\n ? (connectHookOutput.pendingConnector as Connector)\n : defaultConnectStatus.pendingConnector;\n\n return {\n connect: connectFn,\n connectors: conns,\n isConnecting: isPending,\n error: err,\n pendingConnector: pendingConn,\n };\n }\n\n return defaultConnectStatus;\n}\n","import { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedDisconnectStatus {\n /** Function to initiate disconnection. Undefined if not available. */\n disconnect?: () => void | Promise<void>; // Can be sync or async\n /** True if a disconnection attempt is in progress (if hook provides this). */\n isDisconnecting: boolean;\n /** Error object if the last disconnection attempt failed (if hook provides this). */\n error: Error | null;\n}\n\nconst defaultDisconnectStatus: DerivedDisconnectStatus = {\n disconnect: undefined,\n isDisconnecting: false,\n error: null,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useDisconnect` facade hook (if available) and returns a structured,\n * safely-accessed status and control function for wallet disconnection.\n */\nexport function useDerivedDisconnect(): DerivedDisconnectStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const disconnectHookOutput = walletFacadeHooks?.useDisconnect\n ? walletFacadeHooks.useDisconnect()\n : undefined;\n\n if (isRecordWithProperties(disconnectHookOutput)) {\n const disconnectFn =\n 'disconnect' in disconnectHookOutput && typeof disconnectHookOutput.disconnect === 'function'\n ? (disconnectHookOutput.disconnect as () => void | Promise<void>)\n : defaultDisconnectStatus.disconnect;\n\n // wagmi's useDisconnect doesn't have isPending/isLoading directly, but has error and variables (which is the connector it disconnected)\n // We will assume a simple isDisconnecting is not provided by current wagmi facade, but include for future flexibility\n const isPending =\n 'isPending' in disconnectHookOutput && typeof disconnectHookOutput.isPending === 'boolean'\n ? disconnectHookOutput.isPending\n : 'isLoading' in disconnectHookOutput && typeof disconnectHookOutput.isLoading === 'boolean'\n ? disconnectHookOutput.isLoading\n : defaultDisconnectStatus.isDisconnecting;\n\n const err =\n 'error' in disconnectHookOutput && disconnectHookOutput.error instanceof Error\n ? disconnectHookOutput.error\n : defaultDisconnectStatus.error;\n\n return { disconnect: disconnectFn, isDisconnecting: isPending, error: err };\n }\n\n return defaultDisconnectStatus;\n}\n","import { useEffect, useRef } from 'react';\n\nimport type { ContractAdapter } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useDerivedAccountStatus } from './useDerivedAccountStatus';\n\n/**\n * Hook that detects wallet reconnection and re-queues network switch if needed.\n *\n * When a user disconnects their wallet and then reconnects in the same session,\n * the wallet may connect to a different chain than what's selected in the app.\n * This hook detects that scenario and invokes a callback to re-queue the network switch.\n *\n * @param selectedNetworkConfigId - Currently selected network in the app\n * @param selectedAdapter - Currently active adapter instance\n * @param networkToSwitchTo - Current network switch queue state (null if no switch pending)\n * @param onRequeueSwitch - Callback invoked when a network switch should be re-queued\n */\nexport function useWalletReconnectionHandler(\n selectedNetworkConfigId: string | null,\n selectedAdapter: ContractAdapter | null,\n networkToSwitchTo: string | null,\n onRequeueSwitch: (networkId: string) => void\n): void {\n const { isConnected, chainId: walletChainId } = useDerivedAccountStatus();\n const prevConnectedRef = useRef(isConnected);\n\n useEffect(() => {\n const wasDisconnected = !prevConnectedRef.current;\n const isNowConnected = isConnected;\n const isReconnection = wasDisconnected && isNowConnected;\n\n // Update ref for next render\n prevConnectedRef.current = isConnected;\n\n if (!isReconnection || !selectedNetworkConfigId || !selectedAdapter) {\n return;\n }\n\n // Skip if already queued\n if (networkToSwitchTo === selectedNetworkConfigId) {\n return;\n }\n\n // Check if adapter config has chainId (only EVM chains support network switching)\n const adapterConfig = selectedAdapter.networkConfig;\n if (!('chainId' in adapterConfig) || !walletChainId) {\n return;\n }\n\n const targetChainId = Number(adapterConfig.chainId);\n if (walletChainId !== targetChainId) {\n logger.info(\n 'useWalletReconnectionHandler',\n `Wallet reconnected with chain ${walletChainId}, but selected network requires ${targetChainId}. Re-queueing switch.`\n );\n onRequeueSwitch(selectedNetworkConfigId);\n }\n }, [\n isConnected,\n walletChainId,\n selectedNetworkConfigId,\n selectedAdapter,\n networkToSwitchTo,\n onRequeueSwitch,\n ]);\n}\n","import React, { useEffect, useState } from 'react';\n\nimport { Button } from '@openzeppelin/ui-components';\nimport { cn, logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from '../hooks/WalletStateContext';\n\ninterface WalletConnectionUIProps {\n className?: string;\n}\n\n/**\n * Component that displays wallet connection UI components\n * provided by the active adapter.\n */\nexport const WalletConnectionUI: React.FC<WalletConnectionUIProps> = ({ className }) => {\n const [isError, setIsError] = useState(false);\n const { activeAdapter, walletFacadeHooks } = useWalletState();\n\n useEffect(() => {\n logger.debug('WalletConnectionUI', '[Debug] State from useWalletState:', {\n adapterId: activeAdapter?.networkConfig.id,\n hasFacadeHooks: !!walletFacadeHooks,\n });\n }, [activeAdapter, walletFacadeHooks]);\n\n // Compute wallet components on each render to ensure UI kit changes are reflected immediately\n const walletComponents = (() => {\n if (!activeAdapter || typeof activeAdapter.getEcosystemWalletComponents !== 'function') {\n logger.debug(\n 'WalletConnectionUI',\n '[Debug] No activeAdapter or getEcosystemWalletComponents method, returning null.'\n );\n return null;\n }\n\n try {\n const components = activeAdapter.getEcosystemWalletComponents();\n logger.debug('WalletConnectionUI', '[Debug] walletComponents from adapter:', components);\n return components;\n } catch (error) {\n logger.error('WalletConnectionUI', '[Debug] Error getting wallet components:', error);\n setIsError(true);\n return null;\n }\n })();\n\n if (!walletComponents) {\n logger.debug(\n 'WalletConnectionUI',\n '[Debug] getEcosystemWalletComponents returned null/undefined, rendering null.'\n );\n return null;\n }\n\n // Log available components for debugging\n logger.debug('WalletConnectionUI', 'Rendering wallet components:', {\n hasConnectButton: !!walletComponents.ConnectButton,\n hasAccountDisplay: !!walletComponents.AccountDisplay,\n hasNetworkSwitcher: !!walletComponents.NetworkSwitcher,\n });\n\n const { ConnectButton, AccountDisplay, NetworkSwitcher } = walletComponents;\n\n // If there was an error, show an error button\n if (isError) {\n return (\n <div className={cn('flex items-center gap-4', className)}>\n <Button variant=\"destructive\" size=\"sm\" onClick={() => window.location.reload()}>\n Wallet Error - Retry\n </Button>\n </div>\n );\n }\n\n return (\n <div className={cn('flex items-center gap-4', className)}>\n {/* Display network switcher if available - moved before account to match typical wallet UI flow */}\n {NetworkSwitcher && <NetworkSwitcher />}\n\n {/* Display account info if available */}\n {AccountDisplay && <AccountDisplay />}\n\n {/* Display connect button if available */}\n {ConnectButton && <ConnectButton />}\n </div>\n );\n};\n","import React, { useEffect } from 'react';\n\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from '../hooks/WalletStateContext';\nimport { WalletConnectionUI } from './WalletConnectionUI';\n\n/**\n * Component that renders the wallet connection UI.\n * Uses useWalletState to get its data.\n */\nexport const WalletConnectionHeader: React.FC = () => {\n const { isAdapterLoading, activeAdapter } = useWalletState();\n\n useEffect(() => {\n logger.debug('WalletConnectionHeader', '[Debug] State from useWalletState:', {\n adapterPresent: !!activeAdapter,\n adapterNetwork: activeAdapter?.networkConfig.id,\n isLoading: isAdapterLoading,\n });\n }, [activeAdapter, isAdapterLoading]);\n\n if (isAdapterLoading) {\n logger.debug('WalletConnectionHeader', '[Debug] Adapter loading, showing skeleton.');\n return <div className=\"h-9 w-28 animate-pulse rounded bg-muted\"></div>;\n }\n\n return <WalletConnectionUI />;\n};\n","import React, { useEffect, useRef, useState } from 'react';\n\nimport { ContractAdapter } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useDerivedAccountStatus } from '../hooks/useDerivedAccountStatus';\nimport { useDerivedSwitchChainStatus } from '../hooks/useDerivedSwitchChainStatus';\n\n/**\n * Props for the NetworkSwitchManager component.\n */\nexport interface NetworkSwitchManagerProps {\n /** The adapter instance for the target network */\n adapter: ContractAdapter;\n /** The network ID we want to switch to */\n targetNetworkId: string;\n /** Callback when network switch completes (success or error) */\n onNetworkSwitchComplete?: () => void;\n}\n\n/**\n * Component that handles wallet network switching based on the selected network.\n *\n * This component manages the lifecycle of network switching operations,\n * coordinating between the wallet's current chain state and the target network.\n * It's designed to be used in any application that needs seamless wallet network switching.\n *\n * Features:\n * - Automatically initiates network switch when mounted with a target network\n * - Handles EVM chain switching gracefully\n * - No-ops for non-EVM networks that don't support chain switching\n * - Tracks switch attempts to prevent duplicate operations\n * - Provides completion callback for parent components to handle state cleanup\n */\nexport const NetworkSwitchManager: React.FC<NetworkSwitchManagerProps> = ({\n adapter,\n targetNetworkId,\n onNetworkSwitchComplete,\n}) => {\n const isMountedRef = useRef(true);\n const [hasAttemptedSwitch, setHasAttemptedSwitch] = useState(false);\n\n const { isConnected, chainId: currentChainIdFromHook } = useDerivedAccountStatus();\n const {\n switchChain: execSwitchNetwork,\n isSwitching: isSwitchingNetworkViaHook,\n error: switchNetworkError,\n } = useDerivedSwitchChainStatus();\n\n useEffect(() => {\n isMountedRef.current = true;\n logger.info(\n 'NetworkSwitchManager',\n `Mounted with target: ${targetNetworkId}, current attempt status: ${hasAttemptedSwitch}`\n );\n setHasAttemptedSwitch(false);\n return () => {\n logger.info('NetworkSwitchManager', `Unmounting, was for target: ${targetNetworkId}`);\n isMountedRef.current = false;\n };\n // hasAttemptedSwitch is intentionally omitted from deps: we only want to reset when targetNetworkId changes,\n // not when hasAttemptedSwitch itself changes (which would cause unnecessary re-renders)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [targetNetworkId]);\n\n useEffect(() => {\n logger.info('NetworkSwitchManager', 'State Update:', {\n target: targetNetworkId,\n adapterNetwork: adapter.networkConfig.id,\n isSwitching: isSwitchingNetworkViaHook,\n hookError: !!switchNetworkError,\n canExec: !!execSwitchNetwork,\n connected: isConnected,\n walletChain: currentChainIdFromHook,\n attempted: hasAttemptedSwitch,\n });\n }, [\n adapter,\n targetNetworkId,\n isSwitchingNetworkViaHook,\n switchNetworkError,\n execSwitchNetwork,\n isConnected,\n currentChainIdFromHook,\n hasAttemptedSwitch,\n ]);\n\n // Main Orchestration & Pre-flight Effect\n useEffect(() => {\n const completeOperation = (\n logMessage?: string,\n options: { notifyComplete?: boolean } = { notifyComplete: true }\n ) => {\n if (logMessage) logger.info('NetworkSwitchManager', logMessage);\n if (options.notifyComplete && isMountedRef.current && onNetworkSwitchComplete)\n onNetworkSwitchComplete();\n if (isMountedRef.current) setHasAttemptedSwitch(false);\n };\n\n if (!execSwitchNetwork) {\n completeOperation('No switchChain function available from hook. Operation halted.', {\n notifyComplete: false,\n });\n return;\n }\n\n if (isSwitchingNetworkViaHook && hasAttemptedSwitch) {\n // If hook is pending AND we initiated this attempt, let completion effect handle it.\n logger.info(\n 'NetworkSwitchManager',\n 'Hook reports switch in progress for current attempt. Waiting...'\n );\n return;\n }\n\n // If hasAttemptedSwitch is true here, but hook is NOT pending, means it completed/errored very fast.\n // The completion effect should pick this up.\n if (hasAttemptedSwitch && !isSwitchingNetworkViaHook) {\n logger.info(\n 'NetworkSwitchManager',\n 'Previous switch attempt concluded. Deferring to completion effect.'\n );\n return;\n }\n\n // If we are here, no attempt has been made for the current targetNetworkId yet, or a previous attempt on a *different* target completed.\n // OR, the hook is not pending from a previous unrelated call.\n // Reset attempt flag for a fresh try if it was from a different context/target.\n // Note: setHasAttemptedSwitch(false) is in mount effect for targetNetworkId change.\n\n // === Pre-flight checks for the current targetNetworkId ===\n if (adapter.networkConfig.id !== targetNetworkId) {\n completeOperation(\n `CRITICAL: Adapter (${adapter.networkConfig.id}) vs Target (${targetNetworkId}) mismatch. Operation halted.`,\n {\n notifyComplete: false,\n }\n );\n return;\n }\n if (!isConnected) {\n completeOperation('Wallet not connected (derived status). Awaiting connection.', {\n notifyComplete: false,\n });\n return;\n }\n if (!('chainId' in adapter.networkConfig)) {\n completeOperation(\n 'Network does not support chain switching (non-EVM). Operation complete (no-op).'\n );\n return;\n }\n const targetChainToBeSwitchedTo = Number(adapter.networkConfig.chainId);\n if (currentChainIdFromHook === targetChainToBeSwitchedTo) {\n completeOperation('Already on correct chain (derived status). Operation complete.');\n return;\n }\n\n const performSwitchActual = () => {\n if (!isMountedRef.current || isSwitchingNetworkViaHook || hasAttemptedSwitch) {\n // If hook became pending, or an attempt was already made and concluded, don't re-issue.\n logger.info(\n 'NetworkSwitchManager',\n `Switch attempt aborted in timeout or already handled. Conditions: isSwitching: ${isSwitchingNetworkViaHook}, hasAttempted: ${hasAttemptedSwitch}`\n );\n return;\n }\n logger.info(\n 'NetworkSwitchManager',\n `Attempting switch to ${targetChainToBeSwitchedTo} via derived hook.`\n );\n setHasAttemptedSwitch(true); // Mark that this specific attempt for this target is now starting\n execSwitchNetwork({ chainId: targetChainToBeSwitchedTo });\n };\n\n const timeoutId = setTimeout(performSwitchActual, 100);\n return () => clearTimeout(timeoutId);\n }, [\n adapter,\n targetNetworkId,\n execSwitchNetwork,\n isSwitchingNetworkViaHook,\n onNetworkSwitchComplete,\n isConnected,\n currentChainIdFromHook,\n hasAttemptedSwitch,\n ]);\n\n // Completion/Error Effect (handles outcomes of an initiated execSwitchNetwork call)\n useEffect(() => {\n if (!isMountedRef.current || !execSwitchNetwork || !hasAttemptedSwitch) return;\n\n // Only act if the hook is NOT pending AND an attempt was made\n if (!isSwitchingNetworkViaHook) {\n let completionMessage = 'Switch hook operation concluded.';\n if (switchNetworkError) {\n logger.error('NetworkSwitchManager', 'Error from derived switch hook:', switchNetworkError);\n completionMessage = 'Switch hook completed with error.';\n } else {\n logger.info('NetworkSwitchManager', 'Derived switch hook completed successfully.');\n }\n if (onNetworkSwitchComplete) onNetworkSwitchComplete();\n if (isMountedRef.current) setHasAttemptedSwitch(false);\n logger.info('NetworkSwitchManager', completionMessage);\n }\n }, [\n isSwitchingNetworkViaHook,\n switchNetworkError,\n execSwitchNetwork,\n hasAttemptedSwitch,\n onNetworkSwitchComplete,\n ]);\n\n return null;\n};\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -136,8 +136,64 @@ function AdapterProvider({ children, resolveAdapter }) {
136
136
  }
137
137
 
138
138
  //#endregion
139
- //#region src/hooks/WalletStateContext.tsx
140
- const WalletStateContext = createContext(void 0);
139
+ //#region src/hooks/WalletStateContext.ts
140
+ /**
141
+ * Shared Global Context Pattern
142
+ * =============================
143
+ *
144
+ * WHY THIS EXISTS:
145
+ * When bundlers (like Vite's optimizeDeps with esbuild) pre-bundle dependencies,
146
+ * they may inline transitive dependencies like @openzeppelin/ui-react into the
147
+ * consuming package's bundle. This creates MULTIPLE instances of this module:
148
+ *
149
+ * 1. The app's direct import → packages/react/dist/index.js
150
+ * 2. The adapter's inlined copy → .vite/deps/@openzeppelin_ui-builder-adapter-evm.js
151
+ *
152
+ * Since React contexts use referential identity, these two module instances have
153
+ * DIFFERENT context objects. When the adapter's components call useWalletState(),
154
+ * they look for a context that was never provided (because WalletStateProvider
155
+ * uses the app's context, not the adapter's inlined copy).
156
+ *
157
+ * SOLUTION:
158
+ * Store the context object on globalThis so ALL module instances share the same
159
+ * React context, regardless of how they were loaded or bundled.
160
+ *
161
+ * WHEN IS THIS NEEDED:
162
+ * - Development with Vite's dependency pre-bundling (optimizeDeps)
163
+ * - When adapters are installed from npm (not workspace-linked with same bundler)
164
+ * - Any scenario where @openzeppelin/ui-react might be duplicated
165
+ *
166
+ * PRODUCTION APPS:
167
+ * In production builds where the app and adapters are bundled together with proper
168
+ * deduplication (e.g., via bundler configuration or peer dependencies), this
169
+ * workaround may not be strictly necessary. However, it provides a safety net
170
+ * and has minimal overhead.
171
+ */
172
+ /**
173
+ * Use Symbol.for() to create a globally unique key that is consistent across
174
+ * all module instances. Unlike Symbol(), Symbol.for() returns the same symbol
175
+ * for the same key string, which is essential for cross-module sharing.
176
+ */
177
+ const WALLET_STATE_CONTEXT_KEY = Symbol.for("@openzeppelin/ui-react/WalletStateContext");
178
+ /**
179
+ * Retrieves or creates the shared WalletStateContext.
180
+ *
181
+ * NOTE ON ATOMICITY:
182
+ * The check-then-set pattern here is not atomic, but this is acceptable because:
183
+ * 1. JavaScript is single-threaded; module initialization is synchronous
184
+ * 2. Even if multiple modules initialize "simultaneously" during parallel loading,
185
+ * they execute sequentially on the main thread
186
+ * 3. The worst case (two contexts created) would only happen if the check and set
187
+ * were somehow interleaved, which cannot occur in JS's execution model
188
+ * 4. For React contexts specifically, having the same context object is what matters,
189
+ * and this pattern guarantees that after initialization
190
+ */
191
+ function getOrCreateSharedContext() {
192
+ const global = globalThis;
193
+ if (!global[WALLET_STATE_CONTEXT_KEY]) global[WALLET_STATE_CONTEXT_KEY] = createContext(void 0);
194
+ return global[WALLET_STATE_CONTEXT_KEY];
195
+ }
196
+ const WalletStateContext = getOrCreateSharedContext();
141
197
  /**
142
198
  * Hook to access wallet state from WalletStateProvider.
143
199
  * @throws Error if used outside of WalletStateProvider
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/hooks/AdapterContext.tsx","../src/hooks/AdapterProvider.tsx","../src/hooks/WalletStateContext.tsx","../src/hooks/useAdapterContext.ts","../src/hooks/WalletStateProvider.tsx","../src/hooks/AnalyticsContext.tsx","../src/hooks/AnalyticsProvider.tsx","../src/hooks/useAnalytics.ts","../src/hooks/useDerivedAccountStatus.ts","../src/hooks/useDerivedSwitchChainStatus.ts","../src/hooks/useDerivedChainInfo.ts","../src/hooks/useDerivedConnectStatus.ts","../src/hooks/useDerivedDisconnect.ts","../src/hooks/useWalletReconnectionHandler.ts","../src/components/WalletConnectionUI.tsx","../src/components/WalletConnectionHeader.tsx","../src/components/NetworkSwitchManager.tsx"],"sourcesContent":["/**\n * AdapterContext.tsx\n *\n * This file defines the React Context used for the adapter singleton pattern.\n * It provides types and the context definition, but the actual implementation\n * is in the AdapterProvider component.\n *\n * The adapter singleton pattern ensures that only one adapter instance exists\n * per network configuration, which is critical for consistent wallet connection\n * state across the application.\n */\nimport { createContext } from 'react';\n\nimport type { ContractAdapter, NetworkConfig } from '@openzeppelin/ui-types';\n\n/**\n * Registry type that maps network IDs to their corresponding adapter instances\n * This is the core data structure for the singleton pattern\n */\nexport interface AdapterRegistry {\n [networkId: string]: ContractAdapter;\n}\n\n/**\n * Context value interface defining what's provided through the context\n * The main functionality is getAdapterForNetwork which either returns\n * an existing adapter or initiates loading of a new one\n */\nexport interface AdapterContextValue {\n getAdapterForNetwork: (networkConfig: NetworkConfig | null) => {\n adapter: ContractAdapter | null;\n isLoading: boolean;\n };\n}\n\n/**\n * The React Context that provides adapter registry access throughout the app\n * Components can access this through the useAdapterContext hook\n */\nexport const AdapterContext = createContext<AdapterContextValue | null>(null);\n","/**\n * AdapterProvider.tsx\n *\n * This file implements the Adapter Provider component which manages a registry of\n * adapter instances. It's a key part of the adapter singleton pattern which ensures\n * that only one adapter instance exists per network configuration.\n *\n * The adapter registry is shared across the application via React Context, allowing\n * components to access the same adapter instances and maintain consistent wallet\n * connection state.\n *\n * IMPORTANT: This implementation needs special care to avoid React state update errors\n * during component rendering. Direct state updates during render are not allowed, which\n * is why adapter loading is controlled carefully.\n */\nimport { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type { ContractAdapter, NetworkConfig } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { AdapterContext, AdapterContextValue, AdapterRegistry } from './AdapterContext';\n\nexport interface AdapterProviderProps {\n children: ReactNode;\n /** Function to resolve/create an adapter instance for a given NetworkConfig. */\n resolveAdapter: (networkConfig: NetworkConfig) => Promise<ContractAdapter>;\n}\n\n/**\n * Provider component that manages adapter instances centrally\n * to avoid creating multiple instances of the same adapter.\n *\n * This component:\n * 1. Maintains a registry of adapter instances by network ID\n * 2. Tracks loading states for adapters being initialized\n * 3. Provides a function to get or load adapters for specific networks\n * 4. Ensures adapter instances are reused when possible\n */\nexport function AdapterProvider({ children, resolveAdapter }: AdapterProviderProps) {\n // Registry to store adapter instances by network ID\n const [adapterRegistry, setAdapterRegistry] = useState<AdapterRegistry>({});\n\n // Track loading states by network ID\n const [loadingNetworks, setLoadingNetworks] = useState<Set<string>>(new Set());\n\n // Log registry status on changes\n useEffect(() => {\n const adapterCount = Object.keys(adapterRegistry).length;\n if (adapterCount > 0) {\n logger.info('AdapterProvider', `Registry contains ${adapterCount} adapters:`, {\n networkIds: Object.keys(adapterRegistry),\n loadingCount: loadingNetworks.size,\n loadingNetworkIds: Array.from(loadingNetworks),\n });\n }\n }, [adapterRegistry, loadingNetworks]);\n\n /**\n * Function to get or create an adapter for a network\n *\n * IMPORTANT: The actual adapter loading is handled in the useConfiguredAdapterSingleton hook\n * to avoid React state updates during render, which would cause errors.\n *\n * This function:\n * 1. Returns existing adapters immediately if available\n * 2. Reports loading state for adapters being initialized\n * 3. Initiates adapter loading when needed\n */\n const getAdapterForNetwork = useCallback(\n (networkConfig: NetworkConfig | null) => {\n if (!networkConfig) {\n return { adapter: null, isLoading: false };\n }\n\n const networkId = networkConfig.id;\n\n // Debug log to track adapter requests\n logger.debug('AdapterProvider', `Adapter requested for network ${networkId}`);\n\n // If we already have this adapter, return it\n if (adapterRegistry[networkId]) {\n logger.debug('AdapterProvider', `Using existing adapter for network ${networkId}`);\n return {\n adapter: adapterRegistry[networkId],\n isLoading: false,\n };\n }\n\n // If we're already loading this adapter, indicate loading\n if (loadingNetworks.has(networkId)) {\n logger.debug('AdapterProvider', `Adapter for network ${networkId} is currently loading`);\n return {\n adapter: null,\n isLoading: true,\n };\n }\n\n // Start loading the adapter\n // NOTE: This state update during render is handled safely in the useConfiguredAdapterSingleton hook\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.add(networkId);\n return newSet;\n });\n\n logger.info(\n 'AdapterProvider',\n `Starting adapter initialization for network ${networkId} (${networkConfig.name})`\n );\n\n // Use the passed-in resolveAdapter function\n void resolveAdapter(networkConfig)\n .then((adapter) => {\n logger.info('AdapterProvider', `Adapter for network ${networkId} loaded successfully`, {\n type: adapter.constructor.name,\n objectId: Object.prototype.toString.call(adapter),\n });\n\n // Update registry with new adapter\n setAdapterRegistry((prev) => ({\n ...prev,\n [networkId]: adapter,\n }));\n\n // Remove from loading networks\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.delete(networkId);\n return newSet;\n });\n })\n .catch((error) => {\n logger.error('AdapterProvider', `Error loading adapter for network ${networkId}:`, error);\n\n // Remove from loading networks on error\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.delete(networkId);\n return newSet;\n });\n });\n\n return {\n adapter: null,\n isLoading: true,\n };\n },\n [adapterRegistry, loadingNetworks, resolveAdapter]\n );\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue = useMemo<AdapterContextValue>(\n () => ({\n getAdapterForNetwork,\n }),\n [getAdapterForNetwork]\n );\n\n return <AdapterContext.Provider value={contextValue}>{children}</AdapterContext.Provider>;\n}\n","import React, { createContext } from 'react';\n\nimport type {\n ContractAdapter,\n EcosystemSpecificReactHooks,\n NetworkConfig,\n UiKitConfiguration,\n} from '@openzeppelin/ui-types';\n\nexport interface WalletStateContextValue {\n // Globally selected network state\n activeNetworkId: string | null;\n setActiveNetworkId: (networkId: string | null) => void;\n activeNetworkConfig: NetworkConfig | null;\n\n // Active adapter state\n activeAdapter: ContractAdapter | null;\n isAdapterLoading: boolean;\n\n // Facade hooks object from the active adapter\n // Consumers will call these hooks (e.g., walletFacadeHooks.useAccount())\n walletFacadeHooks: EcosystemSpecificReactHooks | null;\n reconfigureActiveAdapterUiKit: (uiKitConfig?: Partial<UiKitConfiguration>) => void;\n}\n\nexport const WalletStateContext = createContext<WalletStateContextValue | undefined>(undefined);\n\n/**\n * Hook to access wallet state from WalletStateProvider.\n * @throws Error if used outside of WalletStateProvider\n */\nexport function useWalletState(): WalletStateContextValue {\n const context = React.useContext(WalletStateContext);\n if (context === undefined) {\n throw new Error('useWalletState must be used within a WalletStateProvider');\n }\n return context;\n}\n","/**\n * useAdapterContext.ts\n *\n * This file provides a hook to access the AdapterContext throughout the application.\n * It's a critical part of the adapter singleton pattern, allowing components to\n * access the centralized adapter registry.\n *\n * The adapter singleton pattern ensures:\n * - Only one adapter instance exists per network\n * - Wallet connection state is consistent across the app\n * - Better performance by eliminating redundant adapter initialization\n */\nimport { useContext } from 'react';\n\nimport { AdapterContext, AdapterContextValue } from './AdapterContext';\n\n/**\n * Hook to access the adapter context\n *\n * This hook provides access to the getAdapterForNetwork function which\n * retrieves or creates adapter instances from the singleton registry.\n *\n * Components should typically use useConfiguredAdapterSingleton instead\n * of this hook directly, as it handles React state update timing properly.\n *\n * @throws Error if used outside of an AdapterProvider context\n * @returns The adapter context value\n */\nexport function useAdapterContext(): AdapterContextValue {\n const context = useContext(AdapterContext);\n\n if (!context) {\n throw new Error('useAdapterContext must be used within an AdapterProvider');\n }\n\n return context;\n}\n","import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type {\n ContractAdapter,\n EcosystemReactUiProviderProps,\n EcosystemSpecificReactHooks,\n NativeConfigLoader,\n NetworkConfig,\n UiKitConfiguration,\n} from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useAdapterContext } from './useAdapterContext';\nimport { WalletStateContext, type WalletStateContextValue } from './WalletStateContext';\n\n// Extended adapter interface that includes the callback-based configureUiKit method\ninterface ExtendedContractAdapter extends ContractAdapter {\n configureUiKit?(\n config: Partial<UiKitConfiguration>,\n options?: {\n loadUiKitNativeConfig?: (kitName: string) => Promise<Record<string, unknown> | null>;\n }\n ): void | Promise<void>;\n getEcosystemReactUiContextProvider?():\n | React.ComponentType<EcosystemReactUiProviderProps>\n | undefined;\n}\n\nexport interface WalletStateProviderProps {\n children: ReactNode;\n /** Optional initial network ID to set as active when the provider mounts. */\n initialNetworkId?: string | null;\n /** Function to retrieve a NetworkConfig object by its ID. */\n getNetworkConfigById: (\n networkId: string\n ) => Promise<NetworkConfig | null | undefined> | NetworkConfig | null | undefined;\n /**\n * Optional generic function to load configuration modules by relative path.\n * The adapter is responsible for constructing the conventional path (e.g., './config/wallet/[kitName].config').\n * @param relativePath The conventional relative path to the configuration module.\n * @returns A Promise resolving to the configuration object (expected to have a default export) or null.\n */\n loadConfigModule?: NativeConfigLoader;\n}\n\n/**\n * Configures the adapter's UI kit and returns the UI provider component and hooks.\n */\nasync function configureAdapterUiKit(\n adapter: ExtendedContractAdapter,\n loadConfigModule?: (relativePath: string) => Promise<Record<string, unknown> | null>,\n programmaticOverrides: Partial<UiKitConfiguration> = {}\n): Promise<{\n providerComponent: React.ComponentType<EcosystemReactUiProviderProps> | null;\n hooks: EcosystemSpecificReactHooks | null;\n}> {\n try {\n // Ensure the adapter (and thus the EvmUiKitManager) is configured.\n if (typeof adapter.configureUiKit === 'function') {\n logger.info(\n '[WSP configureAdapterUiKit] Calling configureUiKit for adapter:',\n adapter?.networkConfig?.id\n );\n await adapter.configureUiKit(programmaticOverrides, {\n loadUiKitNativeConfig: loadConfigModule,\n });\n logger.info(\n '[WSP configureAdapterUiKit] configureUiKit completed for adapter:',\n adapter?.networkConfig?.id\n );\n }\n\n const providerComponent = adapter.getEcosystemReactUiContextProvider?.() || null;\n const hooks = adapter.getEcosystemReactHooks?.() || null;\n\n logger.info('[WSP configureAdapterUiKit]', 'UI provider and hooks retrieved successfully.');\n\n return { providerComponent, hooks };\n } catch (error) {\n logger.error('[WSP configureAdapterUiKit]', 'Error during adapter UI setup:', error);\n throw error; // Re-throw to be handled by caller\n }\n}\n\n/**\n * @name WalletStateProvider\n * @description This provider is a central piece of the application's state management for wallet and network interactions.\n * It is responsible for:\n * 1. Managing the globally selected active network ID (`activeNetworkId`).\n * 2. Deriving the full `NetworkConfig` object (`activeNetworkConfig`) for the active network.\n * 3. Fetching and providing the corresponding `ContractAdapter` instance (`activeAdapter`) for the active network,\n * leveraging the `AdapterProvider` to ensure adapter singletons.\n * 4. Storing and providing the `EcosystemSpecificReactHooks` (`walletFacadeHooks`) from the active adapter.\n * 5. Rendering the adapter-specific UI context provider (e.g., WagmiProvider for EVM) around its children,\n * which is essential for the facade hooks to function correctly.\n * 6. Providing a function (`setActiveNetworkId`) to change the globally active network.\n *\n * Consumers use the `useWalletState()` hook to access this global state.\n * It should be placed high in the component tree, inside an `<AdapterProvider>`.\n */\nexport function WalletStateProvider({\n children,\n initialNetworkId = null,\n getNetworkConfigById,\n loadConfigModule,\n}: WalletStateProviderProps) {\n // State for the ID of the globally selected network.\n const [currentGlobalNetworkId, setCurrentGlobalNetworkIdState] = useState<string | null>(\n initialNetworkId\n );\n // State for the full NetworkConfig object of the globally selected network.\n const [currentGlobalNetworkConfig, setCurrentGlobalNetworkConfig] =\n useState<NetworkConfig | null>(null);\n\n // State for the active ContractAdapter instance corresponding to the currentGlobalNetworkConfig.\n const [globalActiveAdapter, setGlobalActiveAdapter] = useState<ContractAdapter | null>(null);\n // Loading state for the globalActiveAdapter.\n const [isGlobalAdapterLoading, setIsGlobalAdapterLoading] = useState<boolean>(false);\n // State for the facade hooks provided by the globalActiveAdapter.\n const [walletFacadeHooks, setWalletFacadeHooks] = useState<EcosystemSpecificReactHooks | null>(\n null\n );\n // State to hold the Component Type\n const [AdapterUiContextProviderToRender, setAdapterUiContextProviderToRender] =\n useState<React.ComponentType<EcosystemReactUiProviderProps> | null>(null);\n\n // New state to act as a manual trigger for re-configuring the UI kit.\n const [uiKitConfigVersion, setUiKitConfigVersion] = useState(0);\n // State to hold programmatic overrides for the next reconfiguration.\n const [programmaticUiKitConfig, setProgrammaticUiKitConfig] = useState<\n Partial<UiKitConfiguration> | undefined\n >(undefined);\n\n // Consume AdapterContext to get the function for fetching adapter instances.\n const { getAdapterForNetwork } = useAdapterContext();\n\n // Effect to derive the full NetworkConfig object when currentGlobalNetworkId changes.\n useEffect(() => {\n const abortController = new AbortController();\n\n async function fetchNetworkConfig() {\n if (!currentGlobalNetworkId) {\n // If currentGlobalNetworkId is null, clear the config.\n if (!abortController.signal.aborted) {\n setCurrentGlobalNetworkConfig(null);\n }\n return;\n }\n\n try {\n const config = await Promise.resolve(getNetworkConfigById(currentGlobalNetworkId));\n if (!abortController.signal.aborted) {\n setCurrentGlobalNetworkConfig(config || null);\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n logger.error('[WSP fetchNetworkConfig]', 'Failed to fetch network config:', error);\n setCurrentGlobalNetworkConfig(null);\n }\n }\n }\n\n void fetchNetworkConfig();\n return () => abortController.abort();\n }, [currentGlobalNetworkId, getNetworkConfigById]);\n\n // Effect to load the active adapter and its UI capabilities when currentGlobalNetworkConfig changes.\n useEffect(() => {\n const abortController = new AbortController();\n\n async function loadAdapterAndConfigureUi() {\n if (!currentGlobalNetworkConfig) {\n // No network config - clear everything\n if (!abortController.signal.aborted) {\n setGlobalActiveAdapter(null);\n setIsGlobalAdapterLoading(false);\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n }\n return;\n }\n\n const { adapter: newAdapter, isLoading: newIsLoading } = getAdapterForNetwork(\n currentGlobalNetworkConfig\n ) as { adapter: ExtendedContractAdapter | null; isLoading: boolean };\n\n if (abortController.signal.aborted) return;\n\n // Update loading state immediately, but defer exposing the new adapter\n // until its UI provider and hooks are configured to avoid mismatch renders.\n setIsGlobalAdapterLoading(newIsLoading);\n\n if (newAdapter && !newIsLoading) {\n try {\n const { providerComponent, hooks } = await configureAdapterUiKit(\n newAdapter,\n loadConfigModule,\n programmaticUiKitConfig\n );\n\n if (!abortController.signal.aborted) {\n // Ensure provider component and hooks are ready before exposing the new adapter\n // to consumers. This prevents rendering ecosystem-specific components under the\n // previous ecosystem provider (e.g., Stellar components under EVM provider).\n setAdapterUiContextProviderToRender(() => providerComponent);\n setWalletFacadeHooks(hooks);\n setGlobalActiveAdapter(newAdapter);\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n logger.error(\n '[WSP loadAdapterAndConfigureUi]',\n 'Error during adapter UI setup:',\n error\n );\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n }\n }\n } else if (!newAdapter && !newIsLoading) {\n // Adapter is null and not loading, clear UI specific state\n if (!abortController.signal.aborted) {\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n setGlobalActiveAdapter(null);\n }\n }\n // If newIsLoading is true, retain previous AdapterUiContextProviderToRender and hooks\n // to prevent UI flicker, EvmWalletUiRoot will handle its loading state internally.\n }\n\n void loadAdapterAndConfigureUi();\n return () => abortController.abort();\n }, [\n currentGlobalNetworkConfig,\n getAdapterForNetwork,\n loadConfigModule,\n uiKitConfigVersion,\n programmaticUiKitConfig,\n ]);\n\n /**\n * Callback to set the globally active network ID.\n * Also clears dependent states (config, adapter, hooks) if the network ID is cleared.\n */\n const setActiveNetworkIdCallback = useCallback((networkId: string | null) => {\n logger.info('WalletStateProvider', `Setting global network ID to: ${networkId}`);\n setCurrentGlobalNetworkIdState(networkId); // This will trigger the fetchNetworkConfig effect.\n if (!networkId) {\n // If clearing the network, proactively clear downstream states.\n // The effects above will also clear them, but this is more immediate.\n setCurrentGlobalNetworkConfig(null);\n setGlobalActiveAdapter(null);\n setIsGlobalAdapterLoading(false);\n setWalletFacadeHooks(null);\n // Do not clear AdapterUiContextProviderToRender here, let the effect handle it\n // based on whether it's a loading transition or an actual clearing.\n // setAdapterUiContextProviderToRender(() => null);\n }\n }, []); // Empty dependency array as it only uses setters from useState.\n\n /**\n * Callback to explicitly trigger a re-configuration of the active adapter's UI kit.\n * This is useful when a UI kit setting changes (e.g., via a wizard) without a network change.\n */\n const reconfigureActiveAdapterUiKit = useCallback(\n (uiKitConfig?: Partial<UiKitConfiguration>) => {\n logger.info(\n 'WalletStateProvider',\n 'Explicitly triggering UI kit re-configuration by bumping version.',\n uiKitConfig\n );\n setProgrammaticUiKitConfig(uiKitConfig);\n setUiKitConfigVersion((v) => v + 1);\n },\n [setProgrammaticUiKitConfig, setUiKitConfigVersion]\n );\n\n // The context value now only provides the raw walletFacadeHooks object.\n // Consumers are responsible for calling specific hooks from it and handling their results.\n const contextValue = useMemo<WalletStateContextValue>(\n () => ({\n activeNetworkId: currentGlobalNetworkId,\n setActiveNetworkId: setActiveNetworkIdCallback,\n activeNetworkConfig: currentGlobalNetworkConfig,\n activeAdapter: globalActiveAdapter,\n isAdapterLoading: isGlobalAdapterLoading,\n walletFacadeHooks,\n reconfigureActiveAdapterUiKit,\n }),\n [\n currentGlobalNetworkId,\n setActiveNetworkIdCallback,\n currentGlobalNetworkConfig,\n globalActiveAdapter,\n isGlobalAdapterLoading,\n walletFacadeHooks,\n reconfigureActiveAdapterUiKit,\n ]\n );\n\n const ActualProviderToRender = AdapterUiContextProviderToRender;\n let childrenToRender: ReactNode;\n\n if (ActualProviderToRender) {\n // Generate a unique key based on adapter's network ecosystem and ID\n // This ensures proper unmounting/mounting when switching between EVM/Stellar/etc.\n const key = `${globalActiveAdapter?.networkConfig?.ecosystem || 'unknown'}-${globalActiveAdapter?.networkConfig?.id || 'unknown'}`;\n\n // EvmWalletUiRoot (and similar for other adapters) no longer needs uiKitConfiguration prop\n // as it manages its own configuration internally via the EvmUiKitManager or equivalent.\n logger.info(\n '[WSP RENDER]',\n 'Rendering adapter-provided UI context provider:',\n ActualProviderToRender.displayName || ActualProviderToRender.name || 'UnknownComponent',\n 'with key:',\n key\n );\n childrenToRender = <ActualProviderToRender key={key}>{children}</ActualProviderToRender>;\n } else {\n logger.info(\n '[WSP RENDER]',\n 'No adapter UI context provider to render. Rendering direct children.'\n );\n childrenToRender = children;\n }\n\n return (\n <WalletStateContext.Provider value={contextValue}>\n {childrenToRender}\n </WalletStateContext.Provider>\n );\n}\n","import { createContext, useContext } from 'react';\n\n/**\n * Analytics context value interface.\n * Provides access to analytics functionality throughout the React component tree.\n */\nexport interface AnalyticsContextValue {\n /** Google Analytics tag ID */\n tagId?: string;\n /**\n * Check if analytics is enabled via feature flag.\n * Returns fresh state on each call to handle dynamic feature flag changes.\n */\n isEnabled: () => boolean;\n /** Initialize analytics with optional tag ID override */\n initialize: (tagIdOverride?: string) => void;\n /**\n * Track a generic event with custom parameters.\n * Use this for app-specific events.\n *\n * @example\n * ```typescript\n * trackEvent('button_clicked', { button_name: 'submit' });\n * ```\n */\n trackEvent: (eventName: string, parameters: Record<string, string | number>) => void;\n /**\n * Track page view event.\n *\n * @example\n * ```typescript\n * trackPageView('Dashboard', '/dashboard');\n * ```\n */\n trackPageView: (pageName: string, pagePath: string) => void;\n /**\n * Track network selection event.\n *\n * @example\n * ```typescript\n * trackNetworkSelection('ethereum-mainnet', 'evm');\n * ```\n */\n trackNetworkSelection: (networkId: string, ecosystem: string) => void;\n}\n\n/**\n * Analytics context for providing analytics functionality to React components.\n * Must be used within an AnalyticsProvider.\n */\nexport const AnalyticsContext = createContext<AnalyticsContextValue | null>(null);\n\n/**\n * Internal hook to access analytics context.\n * Throws an error if used outside of an AnalyticsProvider.\n *\n * @internal\n * @throws Error if used outside of AnalyticsProvider\n */\nexport const useAnalyticsContext = (): AnalyticsContextValue => {\n const context = useContext(AnalyticsContext);\n if (!context) {\n throw new Error('useAnalyticsContext must be used within an AnalyticsProvider');\n }\n return context;\n};\n","import React, { ReactNode, useEffect, useMemo } from 'react';\n\nimport { AnalyticsService, logger } from '@openzeppelin/ui-utils';\n\nimport { AnalyticsContext, AnalyticsContextValue } from './AnalyticsContext';\n\n/**\n * Props for the AnalyticsProvider component\n */\nexport interface AnalyticsProviderProps {\n /** Google Analytics tag ID (e.g., 'G-XXXXXXXXXX') */\n tagId?: string;\n /** Whether to automatically initialize analytics on mount (default: true) */\n autoInit?: boolean;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Analytics Provider component.\n * Provides analytics functionality throughout the React component tree.\n *\n * @example\n * ```tsx\n * function App() {\n * return (\n * <AnalyticsProvider tagId={import.meta.env.VITE_GA_TAG_ID} autoInit={true}>\n * <YourApp />\n * </AnalyticsProvider>\n * );\n * }\n * ```\n */\nexport const AnalyticsProvider: React.FC<AnalyticsProviderProps> = ({\n tagId,\n autoInit = true,\n children,\n}) => {\n useEffect(() => {\n if (autoInit && tagId) {\n AnalyticsService.initialize(tagId);\n }\n }, [tagId, autoInit]);\n\n const contextValue: AnalyticsContextValue = useMemo(\n () => ({\n tagId,\n isEnabled: () => AnalyticsService.isEnabled(),\n initialize: (tagIdOverride?: string) => {\n const effectiveTagId = tagIdOverride || tagId;\n if (effectiveTagId) {\n AnalyticsService.initialize(effectiveTagId);\n }\n },\n trackEvent: (eventName: string, parameters: Record<string, string | number>) => {\n try {\n AnalyticsService.trackEvent(eventName, parameters);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking event:', error);\n }\n },\n trackPageView: (pageName: string, pagePath: string) => {\n try {\n AnalyticsService.trackPageView(pageName, pagePath);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking page view:', error);\n }\n },\n trackNetworkSelection: (networkId: string, ecosystem: string) => {\n try {\n AnalyticsService.trackNetworkSelection(networkId, ecosystem);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking network selection:', error);\n }\n },\n }),\n [tagId]\n );\n\n return <AnalyticsContext.Provider value={contextValue}>{children}</AnalyticsContext.Provider>;\n};\n","import { useAnalyticsContext } from './AnalyticsContext';\n\n/**\n * Custom hook for accessing analytics functionality.\n *\n * This hook provides a convenient interface for tracking user interactions\n * throughout the application. It must be used within an AnalyticsProvider.\n *\n * For app-specific tracking methods, create a wrapper hook that uses this\n * hook and adds your custom tracking functions.\n *\n * @example\n * ```tsx\n * // Basic usage\n * function MyComponent() {\n * const { trackEvent, trackPageView, isEnabled } = useAnalytics();\n *\n * const handleClick = () => {\n * trackEvent('button_clicked', { button_name: 'submit' });\n * };\n *\n * return (\n * <div>\n * Analytics enabled: {isEnabled().toString()}\n * <button onClick={handleClick}>Submit</button>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Creating app-specific wrapper hook\n * function useMyAppAnalytics() {\n * const analytics = useAnalytics();\n *\n * return {\n * ...analytics,\n * trackFormSubmit: (formName: string) => {\n * analytics.trackEvent('form_submitted', { form_name: formName });\n * },\n * };\n * }\n * ```\n *\n * @returns Analytics context with tracking methods and state\n * @throws Error if used outside of AnalyticsProvider\n */\nexport const useAnalytics = () => {\n try {\n return useAnalyticsContext();\n } catch {\n throw new Error('useAnalytics must be used within an AnalyticsProvider');\n }\n};\n","// Assumes WalletStateContext exports useWalletState\nimport { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedAccountStatus {\n isConnected: boolean;\n address?: string;\n chainId?: number;\n // Potentially add other commonly used and safely extracted properties from useAccount's result\n}\n\nconst defaultAccountStatus: DerivedAccountStatus = {\n isConnected: false,\n address: undefined,\n chainId: undefined,\n};\n\n/**\n * A custom hook that consumes useWalletState to get the walletFacadeHooks,\n * then calls the useAccount facade hook (if available) and returns a structured,\n * safely-accessed account status (isConnected, address, chainId).\n * Provides default values if the hook or its properties are unavailable.\n */\nexport function useDerivedAccountStatus(): DerivedAccountStatus {\n const { walletFacadeHooks } = useWalletState();\n\n // Call the useAccount hook from the facade\n const accountHookOutput = walletFacadeHooks?.useAccount\n ? walletFacadeHooks.useAccount()\n : undefined;\n\n if (isRecordWithProperties(accountHookOutput)) {\n const isConnected =\n 'isConnected' in accountHookOutput && typeof accountHookOutput.isConnected === 'boolean'\n ? accountHookOutput.isConnected\n : defaultAccountStatus.isConnected;\n const address =\n 'address' in accountHookOutput && typeof accountHookOutput.address === 'string'\n ? accountHookOutput.address\n : defaultAccountStatus.address;\n const chainId =\n 'chainId' in accountHookOutput && typeof accountHookOutput.chainId === 'number'\n ? accountHookOutput.chainId\n : defaultAccountStatus.chainId;\n return { isConnected, address, chainId };\n }\n return defaultAccountStatus;\n}\n","import { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\n// Define the expected return shape for the derived hook\nexport interface DerivedSwitchChainStatus {\n /** Function to initiate a network switch. Undefined if not available. */\n switchChain?: (args: { chainId: number }) => void;\n /** True if a network switch is currently in progress. */\n isSwitching: boolean;\n /** Error object if the last switch attempt failed, otherwise null. */\n error: Error | null;\n}\n\nconst defaultSwitchChainStatus: DerivedSwitchChainStatus = {\n switchChain: undefined,\n isSwitching: false,\n error: null,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useSwitchChain` facade hook (if available) and returns a structured,\n * safely-accessed status and control function for network switching.\n * Provides default values if the hook or its properties are unavailable.\n */\nexport function useDerivedSwitchChainStatus(): DerivedSwitchChainStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const switchChainHookOutput = walletFacadeHooks?.useSwitchChain\n ? walletFacadeHooks.useSwitchChain()\n : undefined;\n\n if (isRecordWithProperties(switchChainHookOutput)) {\n const execSwitchFn =\n 'switchChain' in switchChainHookOutput &&\n typeof switchChainHookOutput.switchChain === 'function'\n ? (switchChainHookOutput.switchChain as (args: { chainId: number }) => void)\n : defaultSwitchChainStatus.switchChain;\n\n const isPending =\n 'isPending' in switchChainHookOutput && typeof switchChainHookOutput.isPending === 'boolean'\n ? switchChainHookOutput.isPending\n : defaultSwitchChainStatus.isSwitching;\n\n const err =\n 'error' in switchChainHookOutput && switchChainHookOutput.error instanceof Error\n ? switchChainHookOutput.error\n : defaultSwitchChainStatus.error;\n\n return { switchChain: execSwitchFn, isSwitching: isPending, error: err };\n }\n\n return defaultSwitchChainStatus;\n}\n","import { logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedChainInfo {\n /** The current chain ID reported by the wallet's active connection, if available. */\n currentChainId?: number;\n /** Array of chains configured in the underlying wallet library (e.g., wagmi). Type is any[] for generic compatibility. */\n availableChains: unknown[];\n}\n\nconst defaultChainInfo: DerivedChainInfo = {\n currentChainId: undefined,\n availableChains: [],\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useChainId` and `useChains` facade hooks (if available)\n * and returns a structured object with this information.\n * Provides default values if the hooks or their properties are unavailable.\n */\nexport function useDerivedChainInfo(): DerivedChainInfo {\n const { walletFacadeHooks } = useWalletState();\n\n let chainIdToReturn: number | undefined = defaultChainInfo.currentChainId;\n const chainIdHookOutput = walletFacadeHooks?.useChainId\n ? walletFacadeHooks.useChainId()\n : undefined;\n // The useChainId hook from wagmi directly returns the number or undefined\n if (typeof chainIdHookOutput === 'number') {\n chainIdToReturn = chainIdHookOutput;\n } else if (chainIdHookOutput !== undefined) {\n // If it's not a number but not undefined, log a warning but use default. Could be an adapter returning unexpected type.\n logger.warn(\n 'useDerivedChainInfo',\n 'useChainId facade hook returned non-numeric value:',\n chainIdHookOutput\n );\n }\n\n let chainsToReturn: unknown[] = defaultChainInfo.availableChains;\n const chainsHookOutput = walletFacadeHooks?.useChains ? walletFacadeHooks.useChains() : undefined;\n // The useChains hook from wagmi directly returns an array of Chain objects\n if (Array.isArray(chainsHookOutput)) {\n chainsToReturn = chainsHookOutput;\n } else if (chainsHookOutput !== undefined) {\n logger.warn(\n 'useDerivedChainInfo',\n 'useChains facade hook returned non-array value:',\n chainsHookOutput\n );\n }\n\n return { currentChainId: chainIdToReturn, availableChains: chainsToReturn };\n}\n","import type { Connector } from '@openzeppelin/ui-types';\nimport { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\n// Assuming Connector type is available\n\nexport interface DerivedConnectStatus {\n /** Function to initiate a connection, usually takes a connector. Undefined if not available. */\n connect?: (args?: { connector?: Connector /* or string for id */ }) => void;\n /** Array of available connectors. Type is any[] for broad compatibility until Connector type is fully generic here. */\n connectors: Connector[]; // Or any[] if Connector type from types pkg is too specific for generic hook here\n /** True if a connection attempt is in progress. */\n isConnecting: boolean;\n /** Error object if the last connection attempt failed, otherwise null. */\n error: Error | null;\n /** The connector a connection is pending for, if any. */\n pendingConnector?: Connector; // Or any\n}\n\nconst defaultConnectStatus: DerivedConnectStatus = {\n connect: undefined,\n connectors: [],\n isConnecting: false,\n error: null,\n pendingConnector: undefined,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useConnect` facade hook (if available) and returns a structured,\n * safely-accessed status and control functions for wallet connection.\n */\nexport function useDerivedConnectStatus(): DerivedConnectStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const connectHookOutput = walletFacadeHooks?.useConnect\n ? walletFacadeHooks.useConnect()\n : undefined;\n\n if (isRecordWithProperties(connectHookOutput)) {\n const connectFn =\n 'connect' in connectHookOutput && typeof connectHookOutput.connect === 'function'\n ? (connectHookOutput.connect as (args?: { connector?: Connector }) => void)\n : defaultConnectStatus.connect;\n\n const conns =\n 'connectors' in connectHookOutput && Array.isArray(connectHookOutput.connectors)\n ? (connectHookOutput.connectors as Connector[])\n : defaultConnectStatus.connectors;\n\n const isPending =\n 'isPending' in connectHookOutput && typeof connectHookOutput.isPending === 'boolean'\n ? connectHookOutput.isPending\n : 'isLoading' in connectHookOutput && typeof connectHookOutput.isLoading === 'boolean'\n ? connectHookOutput.isLoading\n : defaultConnectStatus.isConnecting;\n\n const err =\n 'error' in connectHookOutput && connectHookOutput.error instanceof Error\n ? connectHookOutput.error\n : defaultConnectStatus.error;\n\n const pendingConn =\n 'pendingConnector' in connectHookOutput &&\n typeof connectHookOutput.pendingConnector === 'object' // Assuming Connector is an object\n ? (connectHookOutput.pendingConnector as Connector)\n : defaultConnectStatus.pendingConnector;\n\n return {\n connect: connectFn,\n connectors: conns,\n isConnecting: isPending,\n error: err,\n pendingConnector: pendingConn,\n };\n }\n\n return defaultConnectStatus;\n}\n","import { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedDisconnectStatus {\n /** Function to initiate disconnection. Undefined if not available. */\n disconnect?: () => void | Promise<void>; // Can be sync or async\n /** True if a disconnection attempt is in progress (if hook provides this). */\n isDisconnecting: boolean;\n /** Error object if the last disconnection attempt failed (if hook provides this). */\n error: Error | null;\n}\n\nconst defaultDisconnectStatus: DerivedDisconnectStatus = {\n disconnect: undefined,\n isDisconnecting: false,\n error: null,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useDisconnect` facade hook (if available) and returns a structured,\n * safely-accessed status and control function for wallet disconnection.\n */\nexport function useDerivedDisconnect(): DerivedDisconnectStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const disconnectHookOutput = walletFacadeHooks?.useDisconnect\n ? walletFacadeHooks.useDisconnect()\n : undefined;\n\n if (isRecordWithProperties(disconnectHookOutput)) {\n const disconnectFn =\n 'disconnect' in disconnectHookOutput && typeof disconnectHookOutput.disconnect === 'function'\n ? (disconnectHookOutput.disconnect as () => void | Promise<void>)\n : defaultDisconnectStatus.disconnect;\n\n // wagmi's useDisconnect doesn't have isPending/isLoading directly, but has error and variables (which is the connector it disconnected)\n // We will assume a simple isDisconnecting is not provided by current wagmi facade, but include for future flexibility\n const isPending =\n 'isPending' in disconnectHookOutput && typeof disconnectHookOutput.isPending === 'boolean'\n ? disconnectHookOutput.isPending\n : 'isLoading' in disconnectHookOutput && typeof disconnectHookOutput.isLoading === 'boolean'\n ? disconnectHookOutput.isLoading\n : defaultDisconnectStatus.isDisconnecting;\n\n const err =\n 'error' in disconnectHookOutput && disconnectHookOutput.error instanceof Error\n ? disconnectHookOutput.error\n : defaultDisconnectStatus.error;\n\n return { disconnect: disconnectFn, isDisconnecting: isPending, error: err };\n }\n\n return defaultDisconnectStatus;\n}\n","import { useEffect, useRef } from 'react';\n\nimport type { ContractAdapter } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useDerivedAccountStatus } from './useDerivedAccountStatus';\n\n/**\n * Hook that detects wallet reconnection and re-queues network switch if needed.\n *\n * When a user disconnects their wallet and then reconnects in the same session,\n * the wallet may connect to a different chain than what's selected in the app.\n * This hook detects that scenario and invokes a callback to re-queue the network switch.\n *\n * @param selectedNetworkConfigId - Currently selected network in the app\n * @param selectedAdapter - Currently active adapter instance\n * @param networkToSwitchTo - Current network switch queue state (null if no switch pending)\n * @param onRequeueSwitch - Callback invoked when a network switch should be re-queued\n */\nexport function useWalletReconnectionHandler(\n selectedNetworkConfigId: string | null,\n selectedAdapter: ContractAdapter | null,\n networkToSwitchTo: string | null,\n onRequeueSwitch: (networkId: string) => void\n): void {\n const { isConnected, chainId: walletChainId } = useDerivedAccountStatus();\n const prevConnectedRef = useRef(isConnected);\n\n useEffect(() => {\n const wasDisconnected = !prevConnectedRef.current;\n const isNowConnected = isConnected;\n const isReconnection = wasDisconnected && isNowConnected;\n\n // Update ref for next render\n prevConnectedRef.current = isConnected;\n\n if (!isReconnection || !selectedNetworkConfigId || !selectedAdapter) {\n return;\n }\n\n // Skip if already queued\n if (networkToSwitchTo === selectedNetworkConfigId) {\n return;\n }\n\n // Check if adapter config has chainId (only EVM chains support network switching)\n const adapterConfig = selectedAdapter.networkConfig;\n if (!('chainId' in adapterConfig) || !walletChainId) {\n return;\n }\n\n const targetChainId = Number(adapterConfig.chainId);\n if (walletChainId !== targetChainId) {\n logger.info(\n 'useWalletReconnectionHandler',\n `Wallet reconnected with chain ${walletChainId}, but selected network requires ${targetChainId}. Re-queueing switch.`\n );\n onRequeueSwitch(selectedNetworkConfigId);\n }\n }, [\n isConnected,\n walletChainId,\n selectedNetworkConfigId,\n selectedAdapter,\n networkToSwitchTo,\n onRequeueSwitch,\n ]);\n}\n","import React, { useEffect, useState } from 'react';\n\nimport { Button } from '@openzeppelin/ui-components';\nimport { cn, logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from '../hooks/WalletStateContext';\n\ninterface WalletConnectionUIProps {\n className?: string;\n}\n\n/**\n * Component that displays wallet connection UI components\n * provided by the active adapter.\n */\nexport const WalletConnectionUI: React.FC<WalletConnectionUIProps> = ({ className }) => {\n const [isError, setIsError] = useState(false);\n const { activeAdapter, walletFacadeHooks } = useWalletState();\n\n useEffect(() => {\n logger.debug('WalletConnectionUI', '[Debug] State from useWalletState:', {\n adapterId: activeAdapter?.networkConfig.id,\n hasFacadeHooks: !!walletFacadeHooks,\n });\n }, [activeAdapter, walletFacadeHooks]);\n\n // Compute wallet components on each render to ensure UI kit changes are reflected immediately\n const walletComponents = (() => {\n if (!activeAdapter || typeof activeAdapter.getEcosystemWalletComponents !== 'function') {\n logger.debug(\n 'WalletConnectionUI',\n '[Debug] No activeAdapter or getEcosystemWalletComponents method, returning null.'\n );\n return null;\n }\n\n try {\n const components = activeAdapter.getEcosystemWalletComponents();\n logger.debug('WalletConnectionUI', '[Debug] walletComponents from adapter:', components);\n return components;\n } catch (error) {\n logger.error('WalletConnectionUI', '[Debug] Error getting wallet components:', error);\n setIsError(true);\n return null;\n }\n })();\n\n if (!walletComponents) {\n logger.debug(\n 'WalletConnectionUI',\n '[Debug] getEcosystemWalletComponents returned null/undefined, rendering null.'\n );\n return null;\n }\n\n // Log available components for debugging\n logger.debug('WalletConnectionUI', 'Rendering wallet components:', {\n hasConnectButton: !!walletComponents.ConnectButton,\n hasAccountDisplay: !!walletComponents.AccountDisplay,\n hasNetworkSwitcher: !!walletComponents.NetworkSwitcher,\n });\n\n const { ConnectButton, AccountDisplay, NetworkSwitcher } = walletComponents;\n\n // If there was an error, show an error button\n if (isError) {\n return (\n <div className={cn('flex items-center gap-4', className)}>\n <Button variant=\"destructive\" size=\"sm\" onClick={() => window.location.reload()}>\n Wallet Error - Retry\n </Button>\n </div>\n );\n }\n\n return (\n <div className={cn('flex items-center gap-4', className)}>\n {/* Display network switcher if available - moved before account to match typical wallet UI flow */}\n {NetworkSwitcher && <NetworkSwitcher />}\n\n {/* Display account info if available */}\n {AccountDisplay && <AccountDisplay />}\n\n {/* Display connect button if available */}\n {ConnectButton && <ConnectButton />}\n </div>\n );\n};\n","import React, { useEffect } from 'react';\n\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from '../hooks/WalletStateContext';\nimport { WalletConnectionUI } from './WalletConnectionUI';\n\n/**\n * Component that renders the wallet connection UI.\n * Uses useWalletState to get its data.\n */\nexport const WalletConnectionHeader: React.FC = () => {\n const { isAdapterLoading, activeAdapter } = useWalletState();\n\n useEffect(() => {\n logger.debug('WalletConnectionHeader', '[Debug] State from useWalletState:', {\n adapterPresent: !!activeAdapter,\n adapterNetwork: activeAdapter?.networkConfig.id,\n isLoading: isAdapterLoading,\n });\n }, [activeAdapter, isAdapterLoading]);\n\n if (isAdapterLoading) {\n logger.debug('WalletConnectionHeader', '[Debug] Adapter loading, showing skeleton.');\n return <div className=\"h-9 w-28 animate-pulse rounded bg-muted\"></div>;\n }\n\n return <WalletConnectionUI />;\n};\n","import React, { useEffect, useRef, useState } from 'react';\n\nimport { ContractAdapter } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useDerivedAccountStatus } from '../hooks/useDerivedAccountStatus';\nimport { useDerivedSwitchChainStatus } from '../hooks/useDerivedSwitchChainStatus';\n\n/**\n * Props for the NetworkSwitchManager component.\n */\nexport interface NetworkSwitchManagerProps {\n /** The adapter instance for the target network */\n adapter: ContractAdapter;\n /** The network ID we want to switch to */\n targetNetworkId: string;\n /** Callback when network switch completes (success or error) */\n onNetworkSwitchComplete?: () => void;\n}\n\n/**\n * Component that handles wallet network switching based on the selected network.\n *\n * This component manages the lifecycle of network switching operations,\n * coordinating between the wallet's current chain state and the target network.\n * It's designed to be used in any application that needs seamless wallet network switching.\n *\n * Features:\n * - Automatically initiates network switch when mounted with a target network\n * - Handles EVM chain switching gracefully\n * - No-ops for non-EVM networks that don't support chain switching\n * - Tracks switch attempts to prevent duplicate operations\n * - Provides completion callback for parent components to handle state cleanup\n */\nexport const NetworkSwitchManager: React.FC<NetworkSwitchManagerProps> = ({\n adapter,\n targetNetworkId,\n onNetworkSwitchComplete,\n}) => {\n const isMountedRef = useRef(true);\n const [hasAttemptedSwitch, setHasAttemptedSwitch] = useState(false);\n\n const { isConnected, chainId: currentChainIdFromHook } = useDerivedAccountStatus();\n const {\n switchChain: execSwitchNetwork,\n isSwitching: isSwitchingNetworkViaHook,\n error: switchNetworkError,\n } = useDerivedSwitchChainStatus();\n\n useEffect(() => {\n isMountedRef.current = true;\n logger.info(\n 'NetworkSwitchManager',\n `Mounted with target: ${targetNetworkId}, current attempt status: ${hasAttemptedSwitch}`\n );\n setHasAttemptedSwitch(false);\n return () => {\n logger.info('NetworkSwitchManager', `Unmounting, was for target: ${targetNetworkId}`);\n isMountedRef.current = false;\n };\n // hasAttemptedSwitch is intentionally omitted from deps: we only want to reset when targetNetworkId changes,\n // not when hasAttemptedSwitch itself changes (which would cause unnecessary re-renders)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [targetNetworkId]);\n\n useEffect(() => {\n logger.info('NetworkSwitchManager', 'State Update:', {\n target: targetNetworkId,\n adapterNetwork: adapter.networkConfig.id,\n isSwitching: isSwitchingNetworkViaHook,\n hookError: !!switchNetworkError,\n canExec: !!execSwitchNetwork,\n connected: isConnected,\n walletChain: currentChainIdFromHook,\n attempted: hasAttemptedSwitch,\n });\n }, [\n adapter,\n targetNetworkId,\n isSwitchingNetworkViaHook,\n switchNetworkError,\n execSwitchNetwork,\n isConnected,\n currentChainIdFromHook,\n hasAttemptedSwitch,\n ]);\n\n // Main Orchestration & Pre-flight Effect\n useEffect(() => {\n const completeOperation = (\n logMessage?: string,\n options: { notifyComplete?: boolean } = { notifyComplete: true }\n ) => {\n if (logMessage) logger.info('NetworkSwitchManager', logMessage);\n if (options.notifyComplete && isMountedRef.current && onNetworkSwitchComplete)\n onNetworkSwitchComplete();\n if (isMountedRef.current) setHasAttemptedSwitch(false);\n };\n\n if (!execSwitchNetwork) {\n completeOperation('No switchChain function available from hook. Operation halted.', {\n notifyComplete: false,\n });\n return;\n }\n\n if (isSwitchingNetworkViaHook && hasAttemptedSwitch) {\n // If hook is pending AND we initiated this attempt, let completion effect handle it.\n logger.info(\n 'NetworkSwitchManager',\n 'Hook reports switch in progress for current attempt. Waiting...'\n );\n return;\n }\n\n // If hasAttemptedSwitch is true here, but hook is NOT pending, means it completed/errored very fast.\n // The completion effect should pick this up.\n if (hasAttemptedSwitch && !isSwitchingNetworkViaHook) {\n logger.info(\n 'NetworkSwitchManager',\n 'Previous switch attempt concluded. Deferring to completion effect.'\n );\n return;\n }\n\n // If we are here, no attempt has been made for the current targetNetworkId yet, or a previous attempt on a *different* target completed.\n // OR, the hook is not pending from a previous unrelated call.\n // Reset attempt flag for a fresh try if it was from a different context/target.\n // Note: setHasAttemptedSwitch(false) is in mount effect for targetNetworkId change.\n\n // === Pre-flight checks for the current targetNetworkId ===\n if (adapter.networkConfig.id !== targetNetworkId) {\n completeOperation(\n `CRITICAL: Adapter (${adapter.networkConfig.id}) vs Target (${targetNetworkId}) mismatch. Operation halted.`,\n {\n notifyComplete: false,\n }\n );\n return;\n }\n if (!isConnected) {\n completeOperation('Wallet not connected (derived status). Awaiting connection.', {\n notifyComplete: false,\n });\n return;\n }\n if (!('chainId' in adapter.networkConfig)) {\n completeOperation(\n 'Network does not support chain switching (non-EVM). Operation complete (no-op).'\n );\n return;\n }\n const targetChainToBeSwitchedTo = Number(adapter.networkConfig.chainId);\n if (currentChainIdFromHook === targetChainToBeSwitchedTo) {\n completeOperation('Already on correct chain (derived status). Operation complete.');\n return;\n }\n\n const performSwitchActual = () => {\n if (!isMountedRef.current || isSwitchingNetworkViaHook || hasAttemptedSwitch) {\n // If hook became pending, or an attempt was already made and concluded, don't re-issue.\n logger.info(\n 'NetworkSwitchManager',\n `Switch attempt aborted in timeout or already handled. Conditions: isSwitching: ${isSwitchingNetworkViaHook}, hasAttempted: ${hasAttemptedSwitch}`\n );\n return;\n }\n logger.info(\n 'NetworkSwitchManager',\n `Attempting switch to ${targetChainToBeSwitchedTo} via derived hook.`\n );\n setHasAttemptedSwitch(true); // Mark that this specific attempt for this target is now starting\n execSwitchNetwork({ chainId: targetChainToBeSwitchedTo });\n };\n\n const timeoutId = setTimeout(performSwitchActual, 100);\n return () => clearTimeout(timeoutId);\n }, [\n adapter,\n targetNetworkId,\n execSwitchNetwork,\n isSwitchingNetworkViaHook,\n onNetworkSwitchComplete,\n isConnected,\n currentChainIdFromHook,\n hasAttemptedSwitch,\n ]);\n\n // Completion/Error Effect (handles outcomes of an initiated execSwitchNetwork call)\n useEffect(() => {\n if (!isMountedRef.current || !execSwitchNetwork || !hasAttemptedSwitch) return;\n\n // Only act if the hook is NOT pending AND an attempt was made\n if (!isSwitchingNetworkViaHook) {\n let completionMessage = 'Switch hook operation concluded.';\n if (switchNetworkError) {\n logger.error('NetworkSwitchManager', 'Error from derived switch hook:', switchNetworkError);\n completionMessage = 'Switch hook completed with error.';\n } else {\n logger.info('NetworkSwitchManager', 'Derived switch hook completed successfully.');\n }\n if (onNetworkSwitchComplete) onNetworkSwitchComplete();\n if (isMountedRef.current) setHasAttemptedSwitch(false);\n logger.info('NetworkSwitchManager', completionMessage);\n }\n }, [\n isSwitchingNetworkViaHook,\n switchNetworkError,\n execSwitchNetwork,\n hasAttemptedSwitch,\n onNetworkSwitchComplete,\n ]);\n\n return null;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/hooks/AdapterContext.tsx","../src/hooks/AdapterProvider.tsx","../src/hooks/WalletStateContext.ts","../src/hooks/useAdapterContext.ts","../src/hooks/WalletStateProvider.tsx","../src/hooks/AnalyticsContext.tsx","../src/hooks/AnalyticsProvider.tsx","../src/hooks/useAnalytics.ts","../src/hooks/useDerivedAccountStatus.ts","../src/hooks/useDerivedSwitchChainStatus.ts","../src/hooks/useDerivedChainInfo.ts","../src/hooks/useDerivedConnectStatus.ts","../src/hooks/useDerivedDisconnect.ts","../src/hooks/useWalletReconnectionHandler.ts","../src/components/WalletConnectionUI.tsx","../src/components/WalletConnectionHeader.tsx","../src/components/NetworkSwitchManager.tsx"],"sourcesContent":["/**\n * AdapterContext.tsx\n *\n * This file defines the React Context used for the adapter singleton pattern.\n * It provides types and the context definition, but the actual implementation\n * is in the AdapterProvider component.\n *\n * The adapter singleton pattern ensures that only one adapter instance exists\n * per network configuration, which is critical for consistent wallet connection\n * state across the application.\n */\nimport { createContext } from 'react';\n\nimport type { ContractAdapter, NetworkConfig } from '@openzeppelin/ui-types';\n\n/**\n * Registry type that maps network IDs to their corresponding adapter instances\n * This is the core data structure for the singleton pattern\n */\nexport interface AdapterRegistry {\n [networkId: string]: ContractAdapter;\n}\n\n/**\n * Context value interface defining what's provided through the context\n * The main functionality is getAdapterForNetwork which either returns\n * an existing adapter or initiates loading of a new one\n */\nexport interface AdapterContextValue {\n getAdapterForNetwork: (networkConfig: NetworkConfig | null) => {\n adapter: ContractAdapter | null;\n isLoading: boolean;\n };\n}\n\n/**\n * The React Context that provides adapter registry access throughout the app\n * Components can access this through the useAdapterContext hook\n */\nexport const AdapterContext = createContext<AdapterContextValue | null>(null);\n","/**\n * AdapterProvider.tsx\n *\n * This file implements the Adapter Provider component which manages a registry of\n * adapter instances. It's a key part of the adapter singleton pattern which ensures\n * that only one adapter instance exists per network configuration.\n *\n * The adapter registry is shared across the application via React Context, allowing\n * components to access the same adapter instances and maintain consistent wallet\n * connection state.\n *\n * IMPORTANT: This implementation needs special care to avoid React state update errors\n * during component rendering. Direct state updates during render are not allowed, which\n * is why adapter loading is controlled carefully.\n */\nimport { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type { ContractAdapter, NetworkConfig } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { AdapterContext, AdapterContextValue, AdapterRegistry } from './AdapterContext';\n\nexport interface AdapterProviderProps {\n children: ReactNode;\n /** Function to resolve/create an adapter instance for a given NetworkConfig. */\n resolveAdapter: (networkConfig: NetworkConfig) => Promise<ContractAdapter>;\n}\n\n/**\n * Provider component that manages adapter instances centrally\n * to avoid creating multiple instances of the same adapter.\n *\n * This component:\n * 1. Maintains a registry of adapter instances by network ID\n * 2. Tracks loading states for adapters being initialized\n * 3. Provides a function to get or load adapters for specific networks\n * 4. Ensures adapter instances are reused when possible\n */\nexport function AdapterProvider({ children, resolveAdapter }: AdapterProviderProps) {\n // Registry to store adapter instances by network ID\n const [adapterRegistry, setAdapterRegistry] = useState<AdapterRegistry>({});\n\n // Track loading states by network ID\n const [loadingNetworks, setLoadingNetworks] = useState<Set<string>>(new Set());\n\n // Log registry status on changes\n useEffect(() => {\n const adapterCount = Object.keys(adapterRegistry).length;\n if (adapterCount > 0) {\n logger.info('AdapterProvider', `Registry contains ${adapterCount} adapters:`, {\n networkIds: Object.keys(adapterRegistry),\n loadingCount: loadingNetworks.size,\n loadingNetworkIds: Array.from(loadingNetworks),\n });\n }\n }, [adapterRegistry, loadingNetworks]);\n\n /**\n * Function to get or create an adapter for a network\n *\n * IMPORTANT: The actual adapter loading is handled in the useConfiguredAdapterSingleton hook\n * to avoid React state updates during render, which would cause errors.\n *\n * This function:\n * 1. Returns existing adapters immediately if available\n * 2. Reports loading state for adapters being initialized\n * 3. Initiates adapter loading when needed\n */\n const getAdapterForNetwork = useCallback(\n (networkConfig: NetworkConfig | null) => {\n if (!networkConfig) {\n return { adapter: null, isLoading: false };\n }\n\n const networkId = networkConfig.id;\n\n // Debug log to track adapter requests\n logger.debug('AdapterProvider', `Adapter requested for network ${networkId}`);\n\n // If we already have this adapter, return it\n if (adapterRegistry[networkId]) {\n logger.debug('AdapterProvider', `Using existing adapter for network ${networkId}`);\n return {\n adapter: adapterRegistry[networkId],\n isLoading: false,\n };\n }\n\n // If we're already loading this adapter, indicate loading\n if (loadingNetworks.has(networkId)) {\n logger.debug('AdapterProvider', `Adapter for network ${networkId} is currently loading`);\n return {\n adapter: null,\n isLoading: true,\n };\n }\n\n // Start loading the adapter\n // NOTE: This state update during render is handled safely in the useConfiguredAdapterSingleton hook\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.add(networkId);\n return newSet;\n });\n\n logger.info(\n 'AdapterProvider',\n `Starting adapter initialization for network ${networkId} (${networkConfig.name})`\n );\n\n // Use the passed-in resolveAdapter function\n void resolveAdapter(networkConfig)\n .then((adapter) => {\n logger.info('AdapterProvider', `Adapter for network ${networkId} loaded successfully`, {\n type: adapter.constructor.name,\n objectId: Object.prototype.toString.call(adapter),\n });\n\n // Update registry with new adapter\n setAdapterRegistry((prev) => ({\n ...prev,\n [networkId]: adapter,\n }));\n\n // Remove from loading networks\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.delete(networkId);\n return newSet;\n });\n })\n .catch((error) => {\n logger.error('AdapterProvider', `Error loading adapter for network ${networkId}:`, error);\n\n // Remove from loading networks on error\n setLoadingNetworks((prev) => {\n const newSet = new Set(prev);\n newSet.delete(networkId);\n return newSet;\n });\n });\n\n return {\n adapter: null,\n isLoading: true,\n };\n },\n [adapterRegistry, loadingNetworks, resolveAdapter]\n );\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue = useMemo<AdapterContextValue>(\n () => ({\n getAdapterForNetwork,\n }),\n [getAdapterForNetwork]\n );\n\n return <AdapterContext.Provider value={contextValue}>{children}</AdapterContext.Provider>;\n}\n","import React, { createContext } from 'react';\n\nimport type {\n ContractAdapter,\n EcosystemSpecificReactHooks,\n NetworkConfig,\n UiKitConfiguration,\n} from '@openzeppelin/ui-types';\n\nexport interface WalletStateContextValue {\n // Globally selected network state\n activeNetworkId: string | null;\n setActiveNetworkId: (networkId: string | null) => void;\n activeNetworkConfig: NetworkConfig | null;\n\n // Active adapter state\n activeAdapter: ContractAdapter | null;\n isAdapterLoading: boolean;\n\n // Facade hooks object from the active adapter\n // Consumers will call these hooks (e.g., walletFacadeHooks.useAccount())\n walletFacadeHooks: EcosystemSpecificReactHooks | null;\n reconfigureActiveAdapterUiKit: (uiKitConfig?: Partial<UiKitConfiguration>) => void;\n}\n\n/**\n * Shared Global Context Pattern\n * =============================\n *\n * WHY THIS EXISTS:\n * When bundlers (like Vite's optimizeDeps with esbuild) pre-bundle dependencies,\n * they may inline transitive dependencies like @openzeppelin/ui-react into the\n * consuming package's bundle. This creates MULTIPLE instances of this module:\n *\n * 1. The app's direct import → packages/react/dist/index.js\n * 2. The adapter's inlined copy → .vite/deps/@openzeppelin_ui-builder-adapter-evm.js\n *\n * Since React contexts use referential identity, these two module instances have\n * DIFFERENT context objects. When the adapter's components call useWalletState(),\n * they look for a context that was never provided (because WalletStateProvider\n * uses the app's context, not the adapter's inlined copy).\n *\n * SOLUTION:\n * Store the context object on globalThis so ALL module instances share the same\n * React context, regardless of how they were loaded or bundled.\n *\n * WHEN IS THIS NEEDED:\n * - Development with Vite's dependency pre-bundling (optimizeDeps)\n * - When adapters are installed from npm (not workspace-linked with same bundler)\n * - Any scenario where @openzeppelin/ui-react might be duplicated\n *\n * PRODUCTION APPS:\n * In production builds where the app and adapters are bundled together with proper\n * deduplication (e.g., via bundler configuration or peer dependencies), this\n * workaround may not be strictly necessary. However, it provides a safety net\n * and has minimal overhead.\n */\n\n/**\n * Use Symbol.for() to create a globally unique key that is consistent across\n * all module instances. Unlike Symbol(), Symbol.for() returns the same symbol\n * for the same key string, which is essential for cross-module sharing.\n */\nconst WALLET_STATE_CONTEXT_KEY = Symbol.for('@openzeppelin/ui-react/WalletStateContext');\n\n/**\n * Type-safe interface for the global object extension.\n * This provides better type safety than using Record<string, unknown>.\n */\ninterface GlobalWithWalletContext {\n [WALLET_STATE_CONTEXT_KEY]?: React.Context<WalletStateContextValue | undefined>;\n}\n\n/**\n * Retrieves or creates the shared WalletStateContext.\n *\n * NOTE ON ATOMICITY:\n * The check-then-set pattern here is not atomic, but this is acceptable because:\n * 1. JavaScript is single-threaded; module initialization is synchronous\n * 2. Even if multiple modules initialize \"simultaneously\" during parallel loading,\n * they execute sequentially on the main thread\n * 3. The worst case (two contexts created) would only happen if the check and set\n * were somehow interleaved, which cannot occur in JS's execution model\n * 4. For React contexts specifically, having the same context object is what matters,\n * and this pattern guarantees that after initialization\n */\nfunction getOrCreateSharedContext(): React.Context<WalletStateContextValue | undefined> {\n const global = globalThis as GlobalWithWalletContext;\n\n if (!global[WALLET_STATE_CONTEXT_KEY]) {\n global[WALLET_STATE_CONTEXT_KEY] = createContext<WalletStateContextValue | undefined>(\n undefined\n );\n }\n\n return global[WALLET_STATE_CONTEXT_KEY];\n}\n\nexport const WalletStateContext = getOrCreateSharedContext();\n\n/**\n * Hook to access wallet state from WalletStateProvider.\n * @throws Error if used outside of WalletStateProvider\n */\nexport function useWalletState(): WalletStateContextValue {\n const context = React.useContext(WalletStateContext);\n if (context === undefined) {\n throw new Error('useWalletState must be used within a WalletStateProvider');\n }\n return context;\n}\n","/**\n * useAdapterContext.ts\n *\n * This file provides a hook to access the AdapterContext throughout the application.\n * It's a critical part of the adapter singleton pattern, allowing components to\n * access the centralized adapter registry.\n *\n * The adapter singleton pattern ensures:\n * - Only one adapter instance exists per network\n * - Wallet connection state is consistent across the app\n * - Better performance by eliminating redundant adapter initialization\n */\nimport { useContext } from 'react';\n\nimport { AdapterContext, AdapterContextValue } from './AdapterContext';\n\n/**\n * Hook to access the adapter context\n *\n * This hook provides access to the getAdapterForNetwork function which\n * retrieves or creates adapter instances from the singleton registry.\n *\n * Components should typically use useConfiguredAdapterSingleton instead\n * of this hook directly, as it handles React state update timing properly.\n *\n * @throws Error if used outside of an AdapterProvider context\n * @returns The adapter context value\n */\nexport function useAdapterContext(): AdapterContextValue {\n const context = useContext(AdapterContext);\n\n if (!context) {\n throw new Error('useAdapterContext must be used within an AdapterProvider');\n }\n\n return context;\n}\n","import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type {\n ContractAdapter,\n EcosystemReactUiProviderProps,\n EcosystemSpecificReactHooks,\n NativeConfigLoader,\n NetworkConfig,\n UiKitConfiguration,\n} from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useAdapterContext } from './useAdapterContext';\nimport { WalletStateContext, type WalletStateContextValue } from './WalletStateContext';\n\n// Extended adapter interface that includes the callback-based configureUiKit method\ninterface ExtendedContractAdapter extends ContractAdapter {\n configureUiKit?(\n config: Partial<UiKitConfiguration>,\n options?: {\n loadUiKitNativeConfig?: (kitName: string) => Promise<Record<string, unknown> | null>;\n }\n ): void | Promise<void>;\n getEcosystemReactUiContextProvider?():\n | React.ComponentType<EcosystemReactUiProviderProps>\n | undefined;\n}\n\nexport interface WalletStateProviderProps {\n children: ReactNode;\n /** Optional initial network ID to set as active when the provider mounts. */\n initialNetworkId?: string | null;\n /** Function to retrieve a NetworkConfig object by its ID. */\n getNetworkConfigById: (\n networkId: string\n ) => Promise<NetworkConfig | null | undefined> | NetworkConfig | null | undefined;\n /**\n * Optional generic function to load configuration modules by relative path.\n * The adapter is responsible for constructing the conventional path (e.g., './config/wallet/[kitName].config').\n * @param relativePath The conventional relative path to the configuration module.\n * @returns A Promise resolving to the configuration object (expected to have a default export) or null.\n */\n loadConfigModule?: NativeConfigLoader;\n}\n\n/**\n * Configures the adapter's UI kit and returns the UI provider component and hooks.\n */\nasync function configureAdapterUiKit(\n adapter: ExtendedContractAdapter,\n loadConfigModule?: (relativePath: string) => Promise<Record<string, unknown> | null>,\n programmaticOverrides: Partial<UiKitConfiguration> = {}\n): Promise<{\n providerComponent: React.ComponentType<EcosystemReactUiProviderProps> | null;\n hooks: EcosystemSpecificReactHooks | null;\n}> {\n try {\n // Ensure the adapter (and thus the EvmUiKitManager) is configured.\n if (typeof adapter.configureUiKit === 'function') {\n logger.info(\n '[WSP configureAdapterUiKit] Calling configureUiKit for adapter:',\n adapter?.networkConfig?.id\n );\n await adapter.configureUiKit(programmaticOverrides, {\n loadUiKitNativeConfig: loadConfigModule,\n });\n logger.info(\n '[WSP configureAdapterUiKit] configureUiKit completed for adapter:',\n adapter?.networkConfig?.id\n );\n }\n\n const providerComponent = adapter.getEcosystemReactUiContextProvider?.() || null;\n const hooks = adapter.getEcosystemReactHooks?.() || null;\n\n logger.info('[WSP configureAdapterUiKit]', 'UI provider and hooks retrieved successfully.');\n\n return { providerComponent, hooks };\n } catch (error) {\n logger.error('[WSP configureAdapterUiKit]', 'Error during adapter UI setup:', error);\n throw error; // Re-throw to be handled by caller\n }\n}\n\n/**\n * @name WalletStateProvider\n * @description This provider is a central piece of the application's state management for wallet and network interactions.\n * It is responsible for:\n * 1. Managing the globally selected active network ID (`activeNetworkId`).\n * 2. Deriving the full `NetworkConfig` object (`activeNetworkConfig`) for the active network.\n * 3. Fetching and providing the corresponding `ContractAdapter` instance (`activeAdapter`) for the active network,\n * leveraging the `AdapterProvider` to ensure adapter singletons.\n * 4. Storing and providing the `EcosystemSpecificReactHooks` (`walletFacadeHooks`) from the active adapter.\n * 5. Rendering the adapter-specific UI context provider (e.g., WagmiProvider for EVM) around its children,\n * which is essential for the facade hooks to function correctly.\n * 6. Providing a function (`setActiveNetworkId`) to change the globally active network.\n *\n * Consumers use the `useWalletState()` hook to access this global state.\n * It should be placed high in the component tree, inside an `<AdapterProvider>`.\n */\nexport function WalletStateProvider({\n children,\n initialNetworkId = null,\n getNetworkConfigById,\n loadConfigModule,\n}: WalletStateProviderProps) {\n // State for the ID of the globally selected network.\n const [currentGlobalNetworkId, setCurrentGlobalNetworkIdState] = useState<string | null>(\n initialNetworkId\n );\n // State for the full NetworkConfig object of the globally selected network.\n const [currentGlobalNetworkConfig, setCurrentGlobalNetworkConfig] =\n useState<NetworkConfig | null>(null);\n\n // State for the active ContractAdapter instance corresponding to the currentGlobalNetworkConfig.\n const [globalActiveAdapter, setGlobalActiveAdapter] = useState<ContractAdapter | null>(null);\n // Loading state for the globalActiveAdapter.\n const [isGlobalAdapterLoading, setIsGlobalAdapterLoading] = useState<boolean>(false);\n // State for the facade hooks provided by the globalActiveAdapter.\n const [walletFacadeHooks, setWalletFacadeHooks] = useState<EcosystemSpecificReactHooks | null>(\n null\n );\n // State to hold the Component Type\n const [AdapterUiContextProviderToRender, setAdapterUiContextProviderToRender] =\n useState<React.ComponentType<EcosystemReactUiProviderProps> | null>(null);\n\n // New state to act as a manual trigger for re-configuring the UI kit.\n const [uiKitConfigVersion, setUiKitConfigVersion] = useState(0);\n // State to hold programmatic overrides for the next reconfiguration.\n const [programmaticUiKitConfig, setProgrammaticUiKitConfig] = useState<\n Partial<UiKitConfiguration> | undefined\n >(undefined);\n\n // Consume AdapterContext to get the function for fetching adapter instances.\n const { getAdapterForNetwork } = useAdapterContext();\n\n // Effect to derive the full NetworkConfig object when currentGlobalNetworkId changes.\n useEffect(() => {\n const abortController = new AbortController();\n\n async function fetchNetworkConfig() {\n if (!currentGlobalNetworkId) {\n // If currentGlobalNetworkId is null, clear the config.\n if (!abortController.signal.aborted) {\n setCurrentGlobalNetworkConfig(null);\n }\n return;\n }\n\n try {\n const config = await Promise.resolve(getNetworkConfigById(currentGlobalNetworkId));\n if (!abortController.signal.aborted) {\n setCurrentGlobalNetworkConfig(config || null);\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n logger.error('[WSP fetchNetworkConfig]', 'Failed to fetch network config:', error);\n setCurrentGlobalNetworkConfig(null);\n }\n }\n }\n\n void fetchNetworkConfig();\n return () => abortController.abort();\n }, [currentGlobalNetworkId, getNetworkConfigById]);\n\n // Effect to load the active adapter and its UI capabilities when currentGlobalNetworkConfig changes.\n useEffect(() => {\n const abortController = new AbortController();\n\n async function loadAdapterAndConfigureUi() {\n if (!currentGlobalNetworkConfig) {\n // No network config - clear everything\n if (!abortController.signal.aborted) {\n setGlobalActiveAdapter(null);\n setIsGlobalAdapterLoading(false);\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n }\n return;\n }\n\n const { adapter: newAdapter, isLoading: newIsLoading } = getAdapterForNetwork(\n currentGlobalNetworkConfig\n ) as { adapter: ExtendedContractAdapter | null; isLoading: boolean };\n\n if (abortController.signal.aborted) return;\n\n // Update loading state immediately, but defer exposing the new adapter\n // until its UI provider and hooks are configured to avoid mismatch renders.\n setIsGlobalAdapterLoading(newIsLoading);\n\n if (newAdapter && !newIsLoading) {\n try {\n const { providerComponent, hooks } = await configureAdapterUiKit(\n newAdapter,\n loadConfigModule,\n programmaticUiKitConfig\n );\n\n if (!abortController.signal.aborted) {\n // Ensure provider component and hooks are ready before exposing the new adapter\n // to consumers. This prevents rendering ecosystem-specific components under the\n // previous ecosystem provider (e.g., Stellar components under EVM provider).\n setAdapterUiContextProviderToRender(() => providerComponent);\n setWalletFacadeHooks(hooks);\n setGlobalActiveAdapter(newAdapter);\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n logger.error(\n '[WSP loadAdapterAndConfigureUi]',\n 'Error during adapter UI setup:',\n error\n );\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n }\n }\n } else if (!newAdapter && !newIsLoading) {\n // Adapter is null and not loading, clear UI specific state\n if (!abortController.signal.aborted) {\n setAdapterUiContextProviderToRender(null);\n setWalletFacadeHooks(null);\n setGlobalActiveAdapter(null);\n }\n }\n // If newIsLoading is true, retain previous AdapterUiContextProviderToRender and hooks\n // to prevent UI flicker, EvmWalletUiRoot will handle its loading state internally.\n }\n\n void loadAdapterAndConfigureUi();\n return () => abortController.abort();\n }, [\n currentGlobalNetworkConfig,\n getAdapterForNetwork,\n loadConfigModule,\n uiKitConfigVersion,\n programmaticUiKitConfig,\n ]);\n\n /**\n * Callback to set the globally active network ID.\n * Also clears dependent states (config, adapter, hooks) if the network ID is cleared.\n */\n const setActiveNetworkIdCallback = useCallback((networkId: string | null) => {\n logger.info('WalletStateProvider', `Setting global network ID to: ${networkId}`);\n setCurrentGlobalNetworkIdState(networkId); // This will trigger the fetchNetworkConfig effect.\n if (!networkId) {\n // If clearing the network, proactively clear downstream states.\n // The effects above will also clear them, but this is more immediate.\n setCurrentGlobalNetworkConfig(null);\n setGlobalActiveAdapter(null);\n setIsGlobalAdapterLoading(false);\n setWalletFacadeHooks(null);\n // Do not clear AdapterUiContextProviderToRender here, let the effect handle it\n // based on whether it's a loading transition or an actual clearing.\n // setAdapterUiContextProviderToRender(() => null);\n }\n }, []); // Empty dependency array as it only uses setters from useState.\n\n /**\n * Callback to explicitly trigger a re-configuration of the active adapter's UI kit.\n * This is useful when a UI kit setting changes (e.g., via a wizard) without a network change.\n */\n const reconfigureActiveAdapterUiKit = useCallback(\n (uiKitConfig?: Partial<UiKitConfiguration>) => {\n logger.info(\n 'WalletStateProvider',\n 'Explicitly triggering UI kit re-configuration by bumping version.',\n uiKitConfig\n );\n setProgrammaticUiKitConfig(uiKitConfig);\n setUiKitConfigVersion((v) => v + 1);\n },\n [setProgrammaticUiKitConfig, setUiKitConfigVersion]\n );\n\n // The context value now only provides the raw walletFacadeHooks object.\n // Consumers are responsible for calling specific hooks from it and handling their results.\n const contextValue = useMemo<WalletStateContextValue>(\n () => ({\n activeNetworkId: currentGlobalNetworkId,\n setActiveNetworkId: setActiveNetworkIdCallback,\n activeNetworkConfig: currentGlobalNetworkConfig,\n activeAdapter: globalActiveAdapter,\n isAdapterLoading: isGlobalAdapterLoading,\n walletFacadeHooks,\n reconfigureActiveAdapterUiKit,\n }),\n [\n currentGlobalNetworkId,\n setActiveNetworkIdCallback,\n currentGlobalNetworkConfig,\n globalActiveAdapter,\n isGlobalAdapterLoading,\n walletFacadeHooks,\n reconfigureActiveAdapterUiKit,\n ]\n );\n\n const ActualProviderToRender = AdapterUiContextProviderToRender;\n let childrenToRender: ReactNode;\n\n if (ActualProviderToRender) {\n // Generate a unique key based on adapter's network ecosystem and ID\n // This ensures proper unmounting/mounting when switching between EVM/Stellar/etc.\n const key = `${globalActiveAdapter?.networkConfig?.ecosystem || 'unknown'}-${globalActiveAdapter?.networkConfig?.id || 'unknown'}`;\n\n // EvmWalletUiRoot (and similar for other adapters) no longer needs uiKitConfiguration prop\n // as it manages its own configuration internally via the EvmUiKitManager or equivalent.\n logger.info(\n '[WSP RENDER]',\n 'Rendering adapter-provided UI context provider:',\n ActualProviderToRender.displayName || ActualProviderToRender.name || 'UnknownComponent',\n 'with key:',\n key\n );\n childrenToRender = <ActualProviderToRender key={key}>{children}</ActualProviderToRender>;\n } else {\n logger.info(\n '[WSP RENDER]',\n 'No adapter UI context provider to render. Rendering direct children.'\n );\n childrenToRender = children;\n }\n\n return (\n <WalletStateContext.Provider value={contextValue}>\n {childrenToRender}\n </WalletStateContext.Provider>\n );\n}\n","import { createContext, useContext } from 'react';\n\n/**\n * Analytics context value interface.\n * Provides access to analytics functionality throughout the React component tree.\n */\nexport interface AnalyticsContextValue {\n /** Google Analytics tag ID */\n tagId?: string;\n /**\n * Check if analytics is enabled via feature flag.\n * Returns fresh state on each call to handle dynamic feature flag changes.\n */\n isEnabled: () => boolean;\n /** Initialize analytics with optional tag ID override */\n initialize: (tagIdOverride?: string) => void;\n /**\n * Track a generic event with custom parameters.\n * Use this for app-specific events.\n *\n * @example\n * ```typescript\n * trackEvent('button_clicked', { button_name: 'submit' });\n * ```\n */\n trackEvent: (eventName: string, parameters: Record<string, string | number>) => void;\n /**\n * Track page view event.\n *\n * @example\n * ```typescript\n * trackPageView('Dashboard', '/dashboard');\n * ```\n */\n trackPageView: (pageName: string, pagePath: string) => void;\n /**\n * Track network selection event.\n *\n * @example\n * ```typescript\n * trackNetworkSelection('ethereum-mainnet', 'evm');\n * ```\n */\n trackNetworkSelection: (networkId: string, ecosystem: string) => void;\n}\n\n/**\n * Analytics context for providing analytics functionality to React components.\n * Must be used within an AnalyticsProvider.\n */\nexport const AnalyticsContext = createContext<AnalyticsContextValue | null>(null);\n\n/**\n * Internal hook to access analytics context.\n * Throws an error if used outside of an AnalyticsProvider.\n *\n * @internal\n * @throws Error if used outside of AnalyticsProvider\n */\nexport const useAnalyticsContext = (): AnalyticsContextValue => {\n const context = useContext(AnalyticsContext);\n if (!context) {\n throw new Error('useAnalyticsContext must be used within an AnalyticsProvider');\n }\n return context;\n};\n","import React, { ReactNode, useEffect, useMemo } from 'react';\n\nimport { AnalyticsService, logger } from '@openzeppelin/ui-utils';\n\nimport { AnalyticsContext, AnalyticsContextValue } from './AnalyticsContext';\n\n/**\n * Props for the AnalyticsProvider component\n */\nexport interface AnalyticsProviderProps {\n /** Google Analytics tag ID (e.g., 'G-XXXXXXXXXX') */\n tagId?: string;\n /** Whether to automatically initialize analytics on mount (default: true) */\n autoInit?: boolean;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Analytics Provider component.\n * Provides analytics functionality throughout the React component tree.\n *\n * @example\n * ```tsx\n * function App() {\n * return (\n * <AnalyticsProvider tagId={import.meta.env.VITE_GA_TAG_ID} autoInit={true}>\n * <YourApp />\n * </AnalyticsProvider>\n * );\n * }\n * ```\n */\nexport const AnalyticsProvider: React.FC<AnalyticsProviderProps> = ({\n tagId,\n autoInit = true,\n children,\n}) => {\n useEffect(() => {\n if (autoInit && tagId) {\n AnalyticsService.initialize(tagId);\n }\n }, [tagId, autoInit]);\n\n const contextValue: AnalyticsContextValue = useMemo(\n () => ({\n tagId,\n isEnabled: () => AnalyticsService.isEnabled(),\n initialize: (tagIdOverride?: string) => {\n const effectiveTagId = tagIdOverride || tagId;\n if (effectiveTagId) {\n AnalyticsService.initialize(effectiveTagId);\n }\n },\n trackEvent: (eventName: string, parameters: Record<string, string | number>) => {\n try {\n AnalyticsService.trackEvent(eventName, parameters);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking event:', error);\n }\n },\n trackPageView: (pageName: string, pagePath: string) => {\n try {\n AnalyticsService.trackPageView(pageName, pagePath);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking page view:', error);\n }\n },\n trackNetworkSelection: (networkId: string, ecosystem: string) => {\n try {\n AnalyticsService.trackNetworkSelection(networkId, ecosystem);\n } catch (error) {\n logger.error('AnalyticsProvider', 'Error tracking network selection:', error);\n }\n },\n }),\n [tagId]\n );\n\n return <AnalyticsContext.Provider value={contextValue}>{children}</AnalyticsContext.Provider>;\n};\n","import { useAnalyticsContext } from './AnalyticsContext';\n\n/**\n * Custom hook for accessing analytics functionality.\n *\n * This hook provides a convenient interface for tracking user interactions\n * throughout the application. It must be used within an AnalyticsProvider.\n *\n * For app-specific tracking methods, create a wrapper hook that uses this\n * hook and adds your custom tracking functions.\n *\n * @example\n * ```tsx\n * // Basic usage\n * function MyComponent() {\n * const { trackEvent, trackPageView, isEnabled } = useAnalytics();\n *\n * const handleClick = () => {\n * trackEvent('button_clicked', { button_name: 'submit' });\n * };\n *\n * return (\n * <div>\n * Analytics enabled: {isEnabled().toString()}\n * <button onClick={handleClick}>Submit</button>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Creating app-specific wrapper hook\n * function useMyAppAnalytics() {\n * const analytics = useAnalytics();\n *\n * return {\n * ...analytics,\n * trackFormSubmit: (formName: string) => {\n * analytics.trackEvent('form_submitted', { form_name: formName });\n * },\n * };\n * }\n * ```\n *\n * @returns Analytics context with tracking methods and state\n * @throws Error if used outside of AnalyticsProvider\n */\nexport const useAnalytics = () => {\n try {\n return useAnalyticsContext();\n } catch {\n throw new Error('useAnalytics must be used within an AnalyticsProvider');\n }\n};\n","// Assumes WalletStateContext exports useWalletState\nimport { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedAccountStatus {\n isConnected: boolean;\n address?: string;\n chainId?: number;\n // Potentially add other commonly used and safely extracted properties from useAccount's result\n}\n\nconst defaultAccountStatus: DerivedAccountStatus = {\n isConnected: false,\n address: undefined,\n chainId: undefined,\n};\n\n/**\n * A custom hook that consumes useWalletState to get the walletFacadeHooks,\n * then calls the useAccount facade hook (if available) and returns a structured,\n * safely-accessed account status (isConnected, address, chainId).\n * Provides default values if the hook or its properties are unavailable.\n */\nexport function useDerivedAccountStatus(): DerivedAccountStatus {\n const { walletFacadeHooks } = useWalletState();\n\n // Call the useAccount hook from the facade\n const accountHookOutput = walletFacadeHooks?.useAccount\n ? walletFacadeHooks.useAccount()\n : undefined;\n\n if (isRecordWithProperties(accountHookOutput)) {\n const isConnected =\n 'isConnected' in accountHookOutput && typeof accountHookOutput.isConnected === 'boolean'\n ? accountHookOutput.isConnected\n : defaultAccountStatus.isConnected;\n const address =\n 'address' in accountHookOutput && typeof accountHookOutput.address === 'string'\n ? accountHookOutput.address\n : defaultAccountStatus.address;\n const chainId =\n 'chainId' in accountHookOutput && typeof accountHookOutput.chainId === 'number'\n ? accountHookOutput.chainId\n : defaultAccountStatus.chainId;\n return { isConnected, address, chainId };\n }\n return defaultAccountStatus;\n}\n","import { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\n// Define the expected return shape for the derived hook\nexport interface DerivedSwitchChainStatus {\n /** Function to initiate a network switch. Undefined if not available. */\n switchChain?: (args: { chainId: number }) => void;\n /** True if a network switch is currently in progress. */\n isSwitching: boolean;\n /** Error object if the last switch attempt failed, otherwise null. */\n error: Error | null;\n}\n\nconst defaultSwitchChainStatus: DerivedSwitchChainStatus = {\n switchChain: undefined,\n isSwitching: false,\n error: null,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useSwitchChain` facade hook (if available) and returns a structured,\n * safely-accessed status and control function for network switching.\n * Provides default values if the hook or its properties are unavailable.\n */\nexport function useDerivedSwitchChainStatus(): DerivedSwitchChainStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const switchChainHookOutput = walletFacadeHooks?.useSwitchChain\n ? walletFacadeHooks.useSwitchChain()\n : undefined;\n\n if (isRecordWithProperties(switchChainHookOutput)) {\n const execSwitchFn =\n 'switchChain' in switchChainHookOutput &&\n typeof switchChainHookOutput.switchChain === 'function'\n ? (switchChainHookOutput.switchChain as (args: { chainId: number }) => void)\n : defaultSwitchChainStatus.switchChain;\n\n const isPending =\n 'isPending' in switchChainHookOutput && typeof switchChainHookOutput.isPending === 'boolean'\n ? switchChainHookOutput.isPending\n : defaultSwitchChainStatus.isSwitching;\n\n const err =\n 'error' in switchChainHookOutput && switchChainHookOutput.error instanceof Error\n ? switchChainHookOutput.error\n : defaultSwitchChainStatus.error;\n\n return { switchChain: execSwitchFn, isSwitching: isPending, error: err };\n }\n\n return defaultSwitchChainStatus;\n}\n","import { logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedChainInfo {\n /** The current chain ID reported by the wallet's active connection, if available. */\n currentChainId?: number;\n /** Array of chains configured in the underlying wallet library (e.g., wagmi). Type is any[] for generic compatibility. */\n availableChains: unknown[];\n}\n\nconst defaultChainInfo: DerivedChainInfo = {\n currentChainId: undefined,\n availableChains: [],\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useChainId` and `useChains` facade hooks (if available)\n * and returns a structured object with this information.\n * Provides default values if the hooks or their properties are unavailable.\n */\nexport function useDerivedChainInfo(): DerivedChainInfo {\n const { walletFacadeHooks } = useWalletState();\n\n let chainIdToReturn: number | undefined = defaultChainInfo.currentChainId;\n const chainIdHookOutput = walletFacadeHooks?.useChainId\n ? walletFacadeHooks.useChainId()\n : undefined;\n // The useChainId hook from wagmi directly returns the number or undefined\n if (typeof chainIdHookOutput === 'number') {\n chainIdToReturn = chainIdHookOutput;\n } else if (chainIdHookOutput !== undefined) {\n // If it's not a number but not undefined, log a warning but use default. Could be an adapter returning unexpected type.\n logger.warn(\n 'useDerivedChainInfo',\n 'useChainId facade hook returned non-numeric value:',\n chainIdHookOutput\n );\n }\n\n let chainsToReturn: unknown[] = defaultChainInfo.availableChains;\n const chainsHookOutput = walletFacadeHooks?.useChains ? walletFacadeHooks.useChains() : undefined;\n // The useChains hook from wagmi directly returns an array of Chain objects\n if (Array.isArray(chainsHookOutput)) {\n chainsToReturn = chainsHookOutput;\n } else if (chainsHookOutput !== undefined) {\n logger.warn(\n 'useDerivedChainInfo',\n 'useChains facade hook returned non-array value:',\n chainsHookOutput\n );\n }\n\n return { currentChainId: chainIdToReturn, availableChains: chainsToReturn };\n}\n","import type { Connector } from '@openzeppelin/ui-types';\nimport { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\n// Assuming Connector type is available\n\nexport interface DerivedConnectStatus {\n /** Function to initiate a connection, usually takes a connector. Undefined if not available. */\n connect?: (args?: { connector?: Connector /* or string for id */ }) => void;\n /** Array of available connectors. Type is any[] for broad compatibility until Connector type is fully generic here. */\n connectors: Connector[]; // Or any[] if Connector type from types pkg is too specific for generic hook here\n /** True if a connection attempt is in progress. */\n isConnecting: boolean;\n /** Error object if the last connection attempt failed, otherwise null. */\n error: Error | null;\n /** The connector a connection is pending for, if any. */\n pendingConnector?: Connector; // Or any\n}\n\nconst defaultConnectStatus: DerivedConnectStatus = {\n connect: undefined,\n connectors: [],\n isConnecting: false,\n error: null,\n pendingConnector: undefined,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useConnect` facade hook (if available) and returns a structured,\n * safely-accessed status and control functions for wallet connection.\n */\nexport function useDerivedConnectStatus(): DerivedConnectStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const connectHookOutput = walletFacadeHooks?.useConnect\n ? walletFacadeHooks.useConnect()\n : undefined;\n\n if (isRecordWithProperties(connectHookOutput)) {\n const connectFn =\n 'connect' in connectHookOutput && typeof connectHookOutput.connect === 'function'\n ? (connectHookOutput.connect as (args?: { connector?: Connector }) => void)\n : defaultConnectStatus.connect;\n\n const conns =\n 'connectors' in connectHookOutput && Array.isArray(connectHookOutput.connectors)\n ? (connectHookOutput.connectors as Connector[])\n : defaultConnectStatus.connectors;\n\n const isPending =\n 'isPending' in connectHookOutput && typeof connectHookOutput.isPending === 'boolean'\n ? connectHookOutput.isPending\n : 'isLoading' in connectHookOutput && typeof connectHookOutput.isLoading === 'boolean'\n ? connectHookOutput.isLoading\n : defaultConnectStatus.isConnecting;\n\n const err =\n 'error' in connectHookOutput && connectHookOutput.error instanceof Error\n ? connectHookOutput.error\n : defaultConnectStatus.error;\n\n const pendingConn =\n 'pendingConnector' in connectHookOutput &&\n typeof connectHookOutput.pendingConnector === 'object' // Assuming Connector is an object\n ? (connectHookOutput.pendingConnector as Connector)\n : defaultConnectStatus.pendingConnector;\n\n return {\n connect: connectFn,\n connectors: conns,\n isConnecting: isPending,\n error: err,\n pendingConnector: pendingConn,\n };\n }\n\n return defaultConnectStatus;\n}\n","import { isRecordWithProperties } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from './WalletStateContext';\n\nexport interface DerivedDisconnectStatus {\n /** Function to initiate disconnection. Undefined if not available. */\n disconnect?: () => void | Promise<void>; // Can be sync or async\n /** True if a disconnection attempt is in progress (if hook provides this). */\n isDisconnecting: boolean;\n /** Error object if the last disconnection attempt failed (if hook provides this). */\n error: Error | null;\n}\n\nconst defaultDisconnectStatus: DerivedDisconnectStatus = {\n disconnect: undefined,\n isDisconnecting: false,\n error: null,\n};\n\n/**\n * A custom hook that consumes `useWalletState` to get `walletFacadeHooks`,\n * then calls the `useDisconnect` facade hook (if available) and returns a structured,\n * safely-accessed status and control function for wallet disconnection.\n */\nexport function useDerivedDisconnect(): DerivedDisconnectStatus {\n const { walletFacadeHooks } = useWalletState();\n\n const disconnectHookOutput = walletFacadeHooks?.useDisconnect\n ? walletFacadeHooks.useDisconnect()\n : undefined;\n\n if (isRecordWithProperties(disconnectHookOutput)) {\n const disconnectFn =\n 'disconnect' in disconnectHookOutput && typeof disconnectHookOutput.disconnect === 'function'\n ? (disconnectHookOutput.disconnect as () => void | Promise<void>)\n : defaultDisconnectStatus.disconnect;\n\n // wagmi's useDisconnect doesn't have isPending/isLoading directly, but has error and variables (which is the connector it disconnected)\n // We will assume a simple isDisconnecting is not provided by current wagmi facade, but include for future flexibility\n const isPending =\n 'isPending' in disconnectHookOutput && typeof disconnectHookOutput.isPending === 'boolean'\n ? disconnectHookOutput.isPending\n : 'isLoading' in disconnectHookOutput && typeof disconnectHookOutput.isLoading === 'boolean'\n ? disconnectHookOutput.isLoading\n : defaultDisconnectStatus.isDisconnecting;\n\n const err =\n 'error' in disconnectHookOutput && disconnectHookOutput.error instanceof Error\n ? disconnectHookOutput.error\n : defaultDisconnectStatus.error;\n\n return { disconnect: disconnectFn, isDisconnecting: isPending, error: err };\n }\n\n return defaultDisconnectStatus;\n}\n","import { useEffect, useRef } from 'react';\n\nimport type { ContractAdapter } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useDerivedAccountStatus } from './useDerivedAccountStatus';\n\n/**\n * Hook that detects wallet reconnection and re-queues network switch if needed.\n *\n * When a user disconnects their wallet and then reconnects in the same session,\n * the wallet may connect to a different chain than what's selected in the app.\n * This hook detects that scenario and invokes a callback to re-queue the network switch.\n *\n * @param selectedNetworkConfigId - Currently selected network in the app\n * @param selectedAdapter - Currently active adapter instance\n * @param networkToSwitchTo - Current network switch queue state (null if no switch pending)\n * @param onRequeueSwitch - Callback invoked when a network switch should be re-queued\n */\nexport function useWalletReconnectionHandler(\n selectedNetworkConfigId: string | null,\n selectedAdapter: ContractAdapter | null,\n networkToSwitchTo: string | null,\n onRequeueSwitch: (networkId: string) => void\n): void {\n const { isConnected, chainId: walletChainId } = useDerivedAccountStatus();\n const prevConnectedRef = useRef(isConnected);\n\n useEffect(() => {\n const wasDisconnected = !prevConnectedRef.current;\n const isNowConnected = isConnected;\n const isReconnection = wasDisconnected && isNowConnected;\n\n // Update ref for next render\n prevConnectedRef.current = isConnected;\n\n if (!isReconnection || !selectedNetworkConfigId || !selectedAdapter) {\n return;\n }\n\n // Skip if already queued\n if (networkToSwitchTo === selectedNetworkConfigId) {\n return;\n }\n\n // Check if adapter config has chainId (only EVM chains support network switching)\n const adapterConfig = selectedAdapter.networkConfig;\n if (!('chainId' in adapterConfig) || !walletChainId) {\n return;\n }\n\n const targetChainId = Number(adapterConfig.chainId);\n if (walletChainId !== targetChainId) {\n logger.info(\n 'useWalletReconnectionHandler',\n `Wallet reconnected with chain ${walletChainId}, but selected network requires ${targetChainId}. Re-queueing switch.`\n );\n onRequeueSwitch(selectedNetworkConfigId);\n }\n }, [\n isConnected,\n walletChainId,\n selectedNetworkConfigId,\n selectedAdapter,\n networkToSwitchTo,\n onRequeueSwitch,\n ]);\n}\n","import React, { useEffect, useState } from 'react';\n\nimport { Button } from '@openzeppelin/ui-components';\nimport { cn, logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from '../hooks/WalletStateContext';\n\ninterface WalletConnectionUIProps {\n className?: string;\n}\n\n/**\n * Component that displays wallet connection UI components\n * provided by the active adapter.\n */\nexport const WalletConnectionUI: React.FC<WalletConnectionUIProps> = ({ className }) => {\n const [isError, setIsError] = useState(false);\n const { activeAdapter, walletFacadeHooks } = useWalletState();\n\n useEffect(() => {\n logger.debug('WalletConnectionUI', '[Debug] State from useWalletState:', {\n adapterId: activeAdapter?.networkConfig.id,\n hasFacadeHooks: !!walletFacadeHooks,\n });\n }, [activeAdapter, walletFacadeHooks]);\n\n // Compute wallet components on each render to ensure UI kit changes are reflected immediately\n const walletComponents = (() => {\n if (!activeAdapter || typeof activeAdapter.getEcosystemWalletComponents !== 'function') {\n logger.debug(\n 'WalletConnectionUI',\n '[Debug] No activeAdapter or getEcosystemWalletComponents method, returning null.'\n );\n return null;\n }\n\n try {\n const components = activeAdapter.getEcosystemWalletComponents();\n logger.debug('WalletConnectionUI', '[Debug] walletComponents from adapter:', components);\n return components;\n } catch (error) {\n logger.error('WalletConnectionUI', '[Debug] Error getting wallet components:', error);\n setIsError(true);\n return null;\n }\n })();\n\n if (!walletComponents) {\n logger.debug(\n 'WalletConnectionUI',\n '[Debug] getEcosystemWalletComponents returned null/undefined, rendering null.'\n );\n return null;\n }\n\n // Log available components for debugging\n logger.debug('WalletConnectionUI', 'Rendering wallet components:', {\n hasConnectButton: !!walletComponents.ConnectButton,\n hasAccountDisplay: !!walletComponents.AccountDisplay,\n hasNetworkSwitcher: !!walletComponents.NetworkSwitcher,\n });\n\n const { ConnectButton, AccountDisplay, NetworkSwitcher } = walletComponents;\n\n // If there was an error, show an error button\n if (isError) {\n return (\n <div className={cn('flex items-center gap-4', className)}>\n <Button variant=\"destructive\" size=\"sm\" onClick={() => window.location.reload()}>\n Wallet Error - Retry\n </Button>\n </div>\n );\n }\n\n return (\n <div className={cn('flex items-center gap-4', className)}>\n {/* Display network switcher if available - moved before account to match typical wallet UI flow */}\n {NetworkSwitcher && <NetworkSwitcher />}\n\n {/* Display account info if available */}\n {AccountDisplay && <AccountDisplay />}\n\n {/* Display connect button if available */}\n {ConnectButton && <ConnectButton />}\n </div>\n );\n};\n","import React, { useEffect } from 'react';\n\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useWalletState } from '../hooks/WalletStateContext';\nimport { WalletConnectionUI } from './WalletConnectionUI';\n\n/**\n * Component that renders the wallet connection UI.\n * Uses useWalletState to get its data.\n */\nexport const WalletConnectionHeader: React.FC = () => {\n const { isAdapterLoading, activeAdapter } = useWalletState();\n\n useEffect(() => {\n logger.debug('WalletConnectionHeader', '[Debug] State from useWalletState:', {\n adapterPresent: !!activeAdapter,\n adapterNetwork: activeAdapter?.networkConfig.id,\n isLoading: isAdapterLoading,\n });\n }, [activeAdapter, isAdapterLoading]);\n\n if (isAdapterLoading) {\n logger.debug('WalletConnectionHeader', '[Debug] Adapter loading, showing skeleton.');\n return <div className=\"h-9 w-28 animate-pulse rounded bg-muted\"></div>;\n }\n\n return <WalletConnectionUI />;\n};\n","import React, { useEffect, useRef, useState } from 'react';\n\nimport { ContractAdapter } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { useDerivedAccountStatus } from '../hooks/useDerivedAccountStatus';\nimport { useDerivedSwitchChainStatus } from '../hooks/useDerivedSwitchChainStatus';\n\n/**\n * Props for the NetworkSwitchManager component.\n */\nexport interface NetworkSwitchManagerProps {\n /** The adapter instance for the target network */\n adapter: ContractAdapter;\n /** The network ID we want to switch to */\n targetNetworkId: string;\n /** Callback when network switch completes (success or error) */\n onNetworkSwitchComplete?: () => void;\n}\n\n/**\n * Component that handles wallet network switching based on the selected network.\n *\n * This component manages the lifecycle of network switching operations,\n * coordinating between the wallet's current chain state and the target network.\n * It's designed to be used in any application that needs seamless wallet network switching.\n *\n * Features:\n * - Automatically initiates network switch when mounted with a target network\n * - Handles EVM chain switching gracefully\n * - No-ops for non-EVM networks that don't support chain switching\n * - Tracks switch attempts to prevent duplicate operations\n * - Provides completion callback for parent components to handle state cleanup\n */\nexport const NetworkSwitchManager: React.FC<NetworkSwitchManagerProps> = ({\n adapter,\n targetNetworkId,\n onNetworkSwitchComplete,\n}) => {\n const isMountedRef = useRef(true);\n const [hasAttemptedSwitch, setHasAttemptedSwitch] = useState(false);\n\n const { isConnected, chainId: currentChainIdFromHook } = useDerivedAccountStatus();\n const {\n switchChain: execSwitchNetwork,\n isSwitching: isSwitchingNetworkViaHook,\n error: switchNetworkError,\n } = useDerivedSwitchChainStatus();\n\n useEffect(() => {\n isMountedRef.current = true;\n logger.info(\n 'NetworkSwitchManager',\n `Mounted with target: ${targetNetworkId}, current attempt status: ${hasAttemptedSwitch}`\n );\n setHasAttemptedSwitch(false);\n return () => {\n logger.info('NetworkSwitchManager', `Unmounting, was for target: ${targetNetworkId}`);\n isMountedRef.current = false;\n };\n // hasAttemptedSwitch is intentionally omitted from deps: we only want to reset when targetNetworkId changes,\n // not when hasAttemptedSwitch itself changes (which would cause unnecessary re-renders)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [targetNetworkId]);\n\n useEffect(() => {\n logger.info('NetworkSwitchManager', 'State Update:', {\n target: targetNetworkId,\n adapterNetwork: adapter.networkConfig.id,\n isSwitching: isSwitchingNetworkViaHook,\n hookError: !!switchNetworkError,\n canExec: !!execSwitchNetwork,\n connected: isConnected,\n walletChain: currentChainIdFromHook,\n attempted: hasAttemptedSwitch,\n });\n }, [\n adapter,\n targetNetworkId,\n isSwitchingNetworkViaHook,\n switchNetworkError,\n execSwitchNetwork,\n isConnected,\n currentChainIdFromHook,\n hasAttemptedSwitch,\n ]);\n\n // Main Orchestration & Pre-flight Effect\n useEffect(() => {\n const completeOperation = (\n logMessage?: string,\n options: { notifyComplete?: boolean } = { notifyComplete: true }\n ) => {\n if (logMessage) logger.info('NetworkSwitchManager', logMessage);\n if (options.notifyComplete && isMountedRef.current && onNetworkSwitchComplete)\n onNetworkSwitchComplete();\n if (isMountedRef.current) setHasAttemptedSwitch(false);\n };\n\n if (!execSwitchNetwork) {\n completeOperation('No switchChain function available from hook. Operation halted.', {\n notifyComplete: false,\n });\n return;\n }\n\n if (isSwitchingNetworkViaHook && hasAttemptedSwitch) {\n // If hook is pending AND we initiated this attempt, let completion effect handle it.\n logger.info(\n 'NetworkSwitchManager',\n 'Hook reports switch in progress for current attempt. Waiting...'\n );\n return;\n }\n\n // If hasAttemptedSwitch is true here, but hook is NOT pending, means it completed/errored very fast.\n // The completion effect should pick this up.\n if (hasAttemptedSwitch && !isSwitchingNetworkViaHook) {\n logger.info(\n 'NetworkSwitchManager',\n 'Previous switch attempt concluded. Deferring to completion effect.'\n );\n return;\n }\n\n // If we are here, no attempt has been made for the current targetNetworkId yet, or a previous attempt on a *different* target completed.\n // OR, the hook is not pending from a previous unrelated call.\n // Reset attempt flag for a fresh try if it was from a different context/target.\n // Note: setHasAttemptedSwitch(false) is in mount effect for targetNetworkId change.\n\n // === Pre-flight checks for the current targetNetworkId ===\n if (adapter.networkConfig.id !== targetNetworkId) {\n completeOperation(\n `CRITICAL: Adapter (${adapter.networkConfig.id}) vs Target (${targetNetworkId}) mismatch. Operation halted.`,\n {\n notifyComplete: false,\n }\n );\n return;\n }\n if (!isConnected) {\n completeOperation('Wallet not connected (derived status). Awaiting connection.', {\n notifyComplete: false,\n });\n return;\n }\n if (!('chainId' in adapter.networkConfig)) {\n completeOperation(\n 'Network does not support chain switching (non-EVM). Operation complete (no-op).'\n );\n return;\n }\n const targetChainToBeSwitchedTo = Number(adapter.networkConfig.chainId);\n if (currentChainIdFromHook === targetChainToBeSwitchedTo) {\n completeOperation('Already on correct chain (derived status). Operation complete.');\n return;\n }\n\n const performSwitchActual = () => {\n if (!isMountedRef.current || isSwitchingNetworkViaHook || hasAttemptedSwitch) {\n // If hook became pending, or an attempt was already made and concluded, don't re-issue.\n logger.info(\n 'NetworkSwitchManager',\n `Switch attempt aborted in timeout or already handled. Conditions: isSwitching: ${isSwitchingNetworkViaHook}, hasAttempted: ${hasAttemptedSwitch}`\n );\n return;\n }\n logger.info(\n 'NetworkSwitchManager',\n `Attempting switch to ${targetChainToBeSwitchedTo} via derived hook.`\n );\n setHasAttemptedSwitch(true); // Mark that this specific attempt for this target is now starting\n execSwitchNetwork({ chainId: targetChainToBeSwitchedTo });\n };\n\n const timeoutId = setTimeout(performSwitchActual, 100);\n return () => clearTimeout(timeoutId);\n }, [\n adapter,\n targetNetworkId,\n execSwitchNetwork,\n isSwitchingNetworkViaHook,\n onNetworkSwitchComplete,\n isConnected,\n currentChainIdFromHook,\n hasAttemptedSwitch,\n ]);\n\n // Completion/Error Effect (handles outcomes of an initiated execSwitchNetwork call)\n useEffect(() => {\n if (!isMountedRef.current || !execSwitchNetwork || !hasAttemptedSwitch) return;\n\n // Only act if the hook is NOT pending AND an attempt was made\n if (!isSwitchingNetworkViaHook) {\n let completionMessage = 'Switch hook operation concluded.';\n if (switchNetworkError) {\n logger.error('NetworkSwitchManager', 'Error from derived switch hook:', switchNetworkError);\n completionMessage = 'Switch hook completed with error.';\n } else {\n logger.info('NetworkSwitchManager', 'Derived switch hook completed successfully.');\n }\n if (onNetworkSwitchComplete) onNetworkSwitchComplete();\n if (isMountedRef.current) setHasAttemptedSwitch(false);\n logger.info('NetworkSwitchManager', completionMessage);\n }\n }, [\n isSwitchingNetworkViaHook,\n switchNetworkError,\n execSwitchNetwork,\n hasAttemptedSwitch,\n onNetworkSwitchComplete,\n ]);\n\n return null;\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openzeppelin/ui-react",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "private": false,
5
5
  "description": "Core React context providers and hooks for the OpenZeppelin UI ecosystem.",
6
6
  "type": "module",
@@ -40,9 +40,9 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "lucide-react": "^0.510.0",
43
- "@openzeppelin/ui-types": "^1.0.0",
44
- "@openzeppelin/ui-components": "^1.0.0",
45
- "@openzeppelin/ui-utils": "^1.0.0"
43
+ "@openzeppelin/ui-components": "^1.0.4",
44
+ "@openzeppelin/ui-utils": "^1.0.0",
45
+ "@openzeppelin/ui-types": "^1.1.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "@tanstack/react-query": "^5.0.0",