@thehoneyjar/sigil-dev-toolbar 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/DevToolbarProvider.tsx","../src/hooks/useUserLens.ts","../src/hooks/useIPCClient.ts","../src/ipc/types.ts","../src/ipc/client.ts","../src/hooks/useForkState.ts","../src/services/fork.ts","../src/hooks/useTransactionSimulation.ts","../src/services/simulation.ts","../src/components/UserLens.tsx","../src/components/DevToolbar.tsx","../src/components/DiagnosticPanel.tsx","../src/components/SimulationPanel.tsx","../src/components/StateComparison.tsx"],"names":["useState","useCallback","useEffect","useRef","jsx","jsxs","truncateAddress","useMemo","Fragment"],"mappings":"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","sourcesContent":["import { createContext, useContext, useEffect, useMemo, type ReactNode } from 'react'\nimport { create } from 'zustand'\nimport { persist } from 'zustand/middleware'\nimport type {\n DevToolbarState,\n DevToolbarActions,\n DevToolbarConfig,\n SavedAddress,\n SimulationScenario,\n PhysicsViolation,\n TasteSignal,\n ToolbarTab,\n} from '../types'\nimport type { Address } from 'viem'\n\n/**\n * Initial state for the toolbar\n */\nconst initialState: DevToolbarState = {\n visible: true,\n collapsed: true,\n activeTab: 'lens',\n userLens: {\n enabled: false,\n impersonatedAddress: null,\n savedAddresses: [],\n },\n simulation: {\n enabled: false,\n scenario: null,\n },\n comparison: {\n enabled: false,\n beforeState: null,\n afterState: null,\n },\n diagnostics: {\n enabled: false,\n violations: [],\n tasteSignals: [],\n },\n}\n\n/**\n * Create the Zustand store with persistence\n */\ntype DevToolbarStore = DevToolbarState & DevToolbarActions\n\nconst createDevToolbarStore = (config: Partial<DevToolbarConfig>) =>\n create<DevToolbarStore>()(\n persist(\n (set, get) => ({\n ...initialState,\n collapsed: config.defaultCollapsed ?? true,\n\n // Visibility\n show: () => set({ visible: true }),\n hide: () => set({ visible: false }),\n toggle: () => set((state) => ({ visible: !state.visible })),\n collapse: () => set({ collapsed: true }),\n expand: () => set({ collapsed: false }),\n setActiveTab: (tab: ToolbarTab) => set({ activeTab: tab, collapsed: false }),\n\n // User Lens\n enableLens: (address: Address) =>\n set({\n userLens: {\n ...get().userLens,\n enabled: true,\n impersonatedAddress: address,\n },\n }),\n disableLens: () =>\n set({\n userLens: {\n ...get().userLens,\n enabled: false,\n },\n }),\n setImpersonatedAddress: (address: Address | null) =>\n set({\n userLens: {\n ...get().userLens,\n impersonatedAddress: address,\n enabled: address !== null,\n },\n }),\n saveAddress: (entry: SavedAddress) =>\n set({\n userLens: {\n ...get().userLens,\n savedAddresses: [\n ...get().userLens.savedAddresses.filter((a) => a.address !== entry.address),\n entry,\n ],\n },\n }),\n removeAddress: (address: Address) =>\n set({\n userLens: {\n ...get().userLens,\n savedAddresses: get().userLens.savedAddresses.filter((a) => a.address !== address),\n },\n }),\n\n // Simulation\n enableSimulation: (scenario: SimulationScenario) =>\n set({\n simulation: {\n enabled: true,\n scenario,\n },\n }),\n disableSimulation: () =>\n set({\n simulation: {\n enabled: false,\n scenario: null,\n },\n }),\n\n // Comparison\n captureBeforeState: (state: Record<string, unknown>) =>\n set({\n comparison: {\n ...get().comparison,\n enabled: true,\n beforeState: state,\n },\n }),\n captureAfterState: (state: Record<string, unknown>) =>\n set({\n comparison: {\n ...get().comparison,\n afterState: state,\n },\n }),\n clearComparison: () =>\n set({\n comparison: {\n enabled: false,\n beforeState: null,\n afterState: null,\n },\n }),\n\n // Diagnostics\n addViolation: (violation: PhysicsViolation) =>\n set({\n diagnostics: {\n ...get().diagnostics,\n violations: [...get().diagnostics.violations.slice(-49), violation],\n },\n }),\n clearViolations: () =>\n set({\n diagnostics: {\n ...get().diagnostics,\n violations: [],\n },\n }),\n addTasteSignal: (signal: TasteSignal) => {\n set({\n diagnostics: {\n ...get().diagnostics,\n tasteSignals: [...get().diagnostics.tasteSignals.slice(-49), signal],\n },\n })\n // Call external callback if provided\n config.onTasteSignal?.(signal)\n },\n clearTasteSignals: () =>\n set({\n diagnostics: {\n ...get().diagnostics,\n tasteSignals: [],\n },\n }),\n\n // Reset\n reset: () => set(initialState),\n }),\n {\n name: 'sigil-dev-toolbar',\n partialize: (state) => ({\n collapsed: state.collapsed,\n activeTab: state.activeTab,\n userLens: {\n savedAddresses: state.userLens.savedAddresses,\n },\n }),\n }\n )\n )\n\n/**\n * Context for the store\n */\nconst DevToolbarContext = createContext<ReturnType<typeof createDevToolbarStore> | null>(null)\n\n/**\n * Context for the config\n */\nconst DevToolbarConfigContext = createContext<DevToolbarConfig | null>(null)\n\n/**\n * Default configuration\n */\nconst defaultConfig: DevToolbarConfig = {\n position: 'bottom-right',\n defaultCollapsed: true,\n enableUserLens: true,\n enableSimulation: true,\n enableComparison: true,\n enableDiagnostics: true,\n toggleShortcut: 'ctrl+shift+d',\n}\n\n/**\n * Props for DevToolbarProvider\n */\nexport interface DevToolbarProviderProps {\n children: ReactNode\n config?: Partial<DevToolbarConfig>\n}\n\n/**\n * Provider component for the dev toolbar\n */\nexport function DevToolbarProvider({ children, config: userConfig }: DevToolbarProviderProps) {\n const config = useMemo(() => ({ ...defaultConfig, ...userConfig }), [userConfig])\n const store = useMemo(() => createDevToolbarStore(config), [config])\n\n // Keyboard shortcut handler\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n const keys = config.toggleShortcut.toLowerCase().split('+')\n const ctrlMatch = keys.includes('ctrl') === (e.ctrlKey || e.metaKey)\n const shiftMatch = keys.includes('shift') === e.shiftKey\n const altMatch = keys.includes('alt') === e.altKey\n const keyMatch = keys.filter((k) => !['ctrl', 'shift', 'alt'].includes(k))[0] === e.key.toLowerCase()\n\n if (ctrlMatch && shiftMatch && altMatch && keyMatch) {\n e.preventDefault()\n store.getState().toggle()\n }\n }\n\n window.addEventListener('keydown', handleKeyDown)\n return () => window.removeEventListener('keydown', handleKeyDown)\n }, [config.toggleShortcut, store])\n\n return (\n <DevToolbarConfigContext.Provider value={config}>\n <DevToolbarContext.Provider value={store}>{children}</DevToolbarContext.Provider>\n </DevToolbarConfigContext.Provider>\n )\n}\n\n/**\n * Hook to access the dev toolbar store\n */\nexport function useDevToolbar(): DevToolbarStore {\n const store = useContext(DevToolbarContext)\n if (!store) {\n throw new Error('useDevToolbar must be used within a DevToolbarProvider')\n }\n return store()\n}\n\n/**\n * Hook to access specific state with selector\n */\nexport function useDevToolbarSelector<T>(selector: (state: DevToolbarStore) => T): T {\n const store = useContext(DevToolbarContext)\n if (!store) {\n throw new Error('useDevToolbarSelector must be used within a DevToolbarProvider')\n }\n return store(selector)\n}\n\n/**\n * Hook to access the toolbar config\n */\nexport function useDevToolbarConfig(): DevToolbarConfig {\n const config = useContext(DevToolbarConfigContext)\n if (!config) {\n throw new Error('useDevToolbarConfig must be used within a DevToolbarProvider')\n }\n return config\n}\n","import { useAccount } from 'wagmi'\nimport { useDevToolbarSelector } from '../providers/DevToolbarProvider'\nimport type { Address } from 'viem'\n\n/**\n * Return type for useLensAwareAccount\n */\nexport interface LensAwareAccount {\n /** Address for reads - impersonated if lens enabled, otherwise real */\n address: Address | undefined\n /** The user's real connected address (always available for signing) */\n realAddress: Address | undefined\n /** Whether currently impersonating another address */\n isImpersonating: boolean\n /** The impersonated address (if any) */\n impersonatedAddress: Address | null\n /** Whether the wallet is connected */\n isConnected: boolean\n}\n\n/**\n * Hook that returns impersonated address for reads, real address for writes.\n *\n * Use this hook in place of wagmi's `useAccount` when you want components\n * to display data for an impersonated address while still being able to\n * sign transactions with the real connected wallet.\n *\n * @example\n * ```tsx\n * function WalletInfo() {\n * const { address, realAddress, isImpersonating } = useLensAwareAccount()\n *\n * // Use `address` for reading data (respects impersonation)\n * const { data: balance } = useBalance({ address })\n *\n * // Use `realAddress` for signing transactions\n * const { writeContract } = useWriteContract()\n *\n * return (\n * <div>\n * <p>Viewing: {address}</p>\n * {isImpersonating && <Badge>Lens Active</Badge>}\n * <button onClick={() => writeContract({ ... })}>\n * Sign with {realAddress}\n * </button>\n * </div>\n * )\n * }\n * ```\n */\nexport function useLensAwareAccount(): LensAwareAccount {\n const { address: realAddress, isConnected } = useAccount()\n\n const userLens = useDevToolbarSelector((state) => state.userLens)\n\n const isImpersonating = userLens.enabled && userLens.impersonatedAddress !== null\n const address = isImpersonating ? userLens.impersonatedAddress! : realAddress\n\n return {\n address,\n realAddress,\n isImpersonating,\n impersonatedAddress: userLens.impersonatedAddress,\n isConnected,\n }\n}\n\n/**\n * Hook to get just the impersonation status\n *\n * @example\n * ```tsx\n * function LensBadge() {\n * const isImpersonating = useIsImpersonating()\n * if (!isImpersonating) return null\n * return <Badge variant=\"warning\">Lens Active</Badge>\n * }\n * ```\n */\nexport function useIsImpersonating(): boolean {\n return useDevToolbarSelector(\n (state) => state.userLens.enabled && state.userLens.impersonatedAddress !== null\n )\n}\n\n/**\n * Hook to get the impersonated address (or null if not impersonating)\n */\nexport function useImpersonatedAddress(): Address | null {\n return useDevToolbarSelector((state) =>\n state.userLens.enabled ? state.userLens.impersonatedAddress : null\n )\n}\n\n/**\n * Hook to get saved addresses for quick selection\n */\nexport function useSavedAddresses() {\n const savedAddresses = useDevToolbarSelector((state) => state.userLens.savedAddresses)\n const { saveAddress, removeAddress, setImpersonatedAddress } = useDevToolbarSelector((state) => ({\n saveAddress: state.saveAddress,\n removeAddress: state.removeAddress,\n setImpersonatedAddress: state.setImpersonatedAddress,\n }))\n\n return {\n savedAddresses,\n saveAddress,\n removeAddress,\n selectAddress: setImpersonatedAddress,\n }\n}\n","/**\n * React hook for IPC Client\n */\n\nimport { useState, useCallback, useRef } from 'react'\nimport { getIPCClient, type IPCClient } from '../ipc/client'\nimport type { LensValidateResponse, AnchorValidateResponse } from '../ipc/types'\nimport type { LensContext, Zone } from '../types'\n\nexport interface UseIPCClientReturn {\n /** Validate lens context */\n validateLens: (context: LensContext, zone?: Zone) => Promise<LensValidateResponse>\n /** Validate with Anchor */\n validateAnchor: (statement?: string, lensContext?: LensContext, zone?: Zone) => Promise<AnchorValidateResponse>\n /** Whether a request is in progress */\n isLoading: boolean\n /** Last error message */\n error: string | null\n /** Clear error */\n clearError: () => void\n}\n\n/**\n * Hook for using the IPC client in components\n */\nexport function useIPCClient(): UseIPCClientReturn {\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const clientRef = useRef<IPCClient | null>(null)\n\n // Get or create client\n const getClient = useCallback((): IPCClient => {\n if (!clientRef.current) {\n clientRef.current = getIPCClient()\n }\n return clientRef.current\n }, [])\n\n // Validate lens context\n const validateLens = useCallback(\n async (context: LensContext, zone?: Zone): Promise<LensValidateResponse> => {\n setIsLoading(true)\n setError(null)\n try {\n const client = getClient()\n const result = await client.validateLensContext(context, zone)\n return result\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Unknown error'\n setError(message)\n throw err\n } finally {\n setIsLoading(false)\n }\n },\n [getClient]\n )\n\n // Validate with Anchor\n const validateAnchor = useCallback(\n async (\n statement?: string,\n lensContext?: LensContext,\n zone?: Zone\n ): Promise<AnchorValidateResponse> => {\n setIsLoading(true)\n setError(null)\n try {\n const client = getClient()\n const result = await client.validateAnchor(statement, lensContext, zone)\n return result\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Unknown error'\n setError(message)\n throw err\n } finally {\n setIsLoading(false)\n }\n },\n [getClient]\n )\n\n // Clear error\n const clearError = useCallback(() => {\n setError(null)\n }, [])\n\n return {\n validateLens,\n validateAnchor,\n isLoading,\n error,\n clearError,\n }\n}\n","/**\n * IPC Types for Toolbar <-> Anchor/Lens Communication\n */\n\nimport type { LensContext, LensValidationResult, Zone } from '../types'\n\n/** IPC Request types */\nexport type IPCRequestType = 'lens-validate' | 'anchor-validate' | 'lens-verify'\n\n/** Base IPC Request */\nexport interface IPCRequest<T = unknown> {\n /** Unique request ID */\n id: string\n /** Request type */\n type: IPCRequestType\n /** Timestamp */\n timestamp: number\n /** Request payload */\n payload: T\n}\n\n/** Lens validation request payload */\nexport interface LensValidatePayload {\n /** Lens context to validate */\n context: LensContext\n /** Zone for validation */\n zone?: Zone\n}\n\n/** Anchor validation request payload */\nexport interface AnchorValidatePayload {\n /** Grounding statement */\n statement?: string\n /** Lens context (optional) */\n lensContext?: LensContext\n /** Zone for lens validation */\n zone?: Zone\n}\n\n/** IPC Response status */\nexport type IPCResponseStatus = 'success' | 'error' | 'timeout'\n\n/** Base IPC Response */\nexport interface IPCResponse<T = unknown> {\n /** Request ID this responds to */\n requestId: string\n /** Response status */\n status: IPCResponseStatus\n /** Timestamp */\n timestamp: number\n /** Response data (if success) */\n data?: T\n /** Error message (if error) */\n error?: string\n /** Exit code from CLI */\n exitCode?: number\n}\n\n/** Lens validation response data */\nexport interface LensValidateResponse {\n valid: boolean\n issues: LensValidationResult['issues']\n summary: string\n}\n\n/** Anchor validation response data */\nexport interface AnchorValidateResponse {\n status?: 'VALID' | 'DRIFT' | 'DECEPTIVE'\n checks?: {\n relevance: { passed: boolean; reason: string }\n hierarchy: { passed: boolean; reason: string }\n rules: { passed: boolean; reason: string }\n }\n requiredZone?: Zone\n citedZone?: Zone | null\n correction?: string\n lens_validation?: LensValidateResponse\n}\n\n/** IPC Client configuration */\nexport interface IPCClientConfig {\n /** Base path for IPC files */\n basePath?: string\n /** Timeout for responses (ms) */\n timeout?: number\n /** Polling interval for responses (ms) */\n pollInterval?: number\n}\n\n/** Default IPC configuration */\nexport const DEFAULT_IPC_CONFIG: Required<IPCClientConfig> = {\n basePath: 'grimoires/pub',\n timeout: 30000,\n pollInterval: 100,\n}\n","/**\n * IPC Client for Toolbar <-> Anchor/Lens Communication\n *\n * Provides a transport-agnostic interface for communicating with\n * Anchor and Lens CLIs. In development mode, uses localStorage for\n * request/response exchange. In production, would use file-based IPC.\n */\n\nimport type {\n IPCRequest,\n IPCResponse,\n IPCRequestType,\n IPCClientConfig,\n LensValidatePayload,\n LensValidateResponse,\n AnchorValidatePayload,\n AnchorValidateResponse,\n} from './types'\nimport { DEFAULT_IPC_CONFIG } from './types'\nimport type { LensContext, Zone } from '../types'\n\n/** Generate a UUID v4 */\nfunction generateUUID(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID()\n }\n // Fallback for older browsers\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0\n const v = c === 'x' ? r : (r & 0x3) | 0x8\n return v.toString(16)\n })\n}\n\n/** IPC Transport interface */\nexport interface IPCTransport {\n /** Write a request */\n writeRequest(request: IPCRequest): Promise<void>\n /** Read a response (returns null if not found) */\n readResponse(requestId: string, cliType: string): Promise<IPCResponse | null>\n /** Cleanup request/response files */\n cleanup(requestId: string): Promise<void>\n}\n\n/**\n * LocalStorage-based transport for development/browser\n * Stores requests in localStorage, responses come from external source\n */\nexport class LocalStorageTransport implements IPCTransport {\n private prefix: string\n\n constructor(prefix = 'sigil-ipc') {\n this.prefix = prefix\n }\n\n async writeRequest(request: IPCRequest): Promise<void> {\n const key = `${this.prefix}:request:${request.id}`\n localStorage.setItem(key, JSON.stringify(request))\n }\n\n async readResponse(requestId: string, cliType: string): Promise<IPCResponse | null> {\n const key = `${this.prefix}:response:${requestId}:${cliType}`\n const data = localStorage.getItem(key)\n if (!data) return null\n try {\n return JSON.parse(data) as IPCResponse\n } catch {\n return null\n }\n }\n\n async cleanup(requestId: string): Promise<void> {\n // Remove all keys related to this request\n const keysToRemove: string[] = []\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i)\n if (key?.includes(requestId)) {\n keysToRemove.push(key)\n }\n }\n keysToRemove.forEach((key) => localStorage.removeItem(key))\n }\n}\n\n/**\n * File-system operations interface for FileSystemTransport\n * Inject your own implementation (e.g., Node.js fs/promises)\n */\nexport interface FileSystemOps {\n mkdir(path: string, options?: { recursive?: boolean }): Promise<void>\n writeFile(path: string, data: string): Promise<void>\n readFile(path: string, encoding: 'utf-8'): Promise<string>\n unlink(path: string): Promise<void>\n}\n\n/**\n * File-system based transport for production/Electron/CLI\n * Uses grimoires/pub/ directory for request/response exchange\n *\n * Response files are prefixed with CLI name to prevent collision:\n * - anchor responses: grimoires/pub/responses/anchor-{request_id}.json\n * - lens responses: grimoires/pub/responses/lens-{request_id}.json\n *\n * Note: Requires injecting file system operations (e.g., Node.js fs/promises)\n * Example:\n * import fs from 'fs/promises'\n * const transport = new FileSystemTransport('grimoires/pub', fs)\n */\nexport class FileSystemTransport implements IPCTransport {\n private basePath: string\n private fs: FileSystemOps\n\n constructor(basePath: string, fsOps: FileSystemOps) {\n this.basePath = basePath\n this.fs = fsOps\n }\n\n async writeRequest(request: IPCRequest): Promise<void> {\n const dir = `${this.basePath}/requests`\n try {\n await this.fs.mkdir(dir, { recursive: true })\n } catch {\n // Directory may already exist\n }\n const path = `${dir}/${request.id}.json`\n await this.fs.writeFile(path, JSON.stringify(request, null, 2))\n }\n\n async readResponse(requestId: string, cliType: string): Promise<IPCResponse | null> {\n // Response files are prefixed with CLI name: {cli}-{request_id}.json\n const path = `${this.basePath}/responses/${cliType}-${requestId}.json`\n try {\n const data = await this.fs.readFile(path, 'utf-8')\n return JSON.parse(data) as IPCResponse\n } catch {\n return null\n }\n }\n\n async cleanup(requestId: string): Promise<void> {\n // Clean up request file\n try {\n await this.fs.unlink(`${this.basePath}/requests/${requestId}.json`)\n } catch {\n // File may not exist\n }\n // Clean up all CLI response files\n for (const cli of ['anchor', 'lens']) {\n try {\n await this.fs.unlink(`${this.basePath}/responses/${cli}-${requestId}.json`)\n } catch {\n // File may not exist\n }\n }\n }\n}\n\n/**\n * Mock transport for testing\n * Immediately resolves with mock responses\n */\nexport class MockTransport implements IPCTransport {\n private mockResponses: Map<string, IPCResponse> = new Map()\n\n setMockResponse(requestId: string, cliType: string, response: IPCResponse): void {\n this.mockResponses.set(`${requestId}:${cliType}`, response)\n }\n\n async writeRequest(_request: IPCRequest): Promise<void> {\n // No-op for mock\n }\n\n async readResponse(requestId: string, cliType: string): Promise<IPCResponse | null> {\n return this.mockResponses.get(`${requestId}:${cliType}`) ?? null\n }\n\n async cleanup(_requestId: string): Promise<void> {\n // No-op for mock\n }\n}\n\n/**\n * IPC Client for communicating with Anchor/Lens CLIs\n */\nexport class IPCClient {\n private config: Required<IPCClientConfig>\n private transport: IPCTransport\n\n constructor(transport?: IPCTransport, config?: IPCClientConfig) {\n this.config = { ...DEFAULT_IPC_CONFIG, ...config }\n this.transport = transport ?? new LocalStorageTransport()\n }\n\n /**\n * Send a request and wait for response\n */\n async send<T, R>(type: IPCRequestType, payload: T, cliType = 'anchor'): Promise<R> {\n const request: IPCRequest<T> = {\n id: generateUUID(),\n type,\n timestamp: Date.now(),\n payload,\n }\n\n // Write request\n await this.transport.writeRequest(request)\n\n // Wait for response with polling\n const response = await this.waitForResponse<R>(request.id, cliType)\n\n // Cleanup\n await this.transport.cleanup(request.id)\n\n if (response.status === 'error') {\n throw new Error(response.error ?? 'Unknown IPC error')\n }\n\n if (response.status === 'timeout') {\n throw new Error('IPC request timed out')\n }\n\n return response.data as R\n }\n\n /**\n * Poll for response until timeout\n */\n private async waitForResponse<R>(requestId: string, cliType: string): Promise<IPCResponse<R>> {\n const startTime = Date.now()\n\n while (Date.now() - startTime < this.config.timeout) {\n const response = await this.transport.readResponse(requestId, cliType)\n if (response) {\n return response as IPCResponse<R>\n }\n\n // Wait before polling again\n await new Promise((resolve) => setTimeout(resolve, this.config.pollInterval))\n }\n\n // Timeout\n return {\n requestId,\n status: 'timeout',\n timestamp: Date.now(),\n error: 'Request timed out',\n }\n }\n\n /**\n * Validate lens context via Anchor CLI\n */\n async validateLensContext(\n context: LensContext,\n zone?: Zone\n ): Promise<LensValidateResponse> {\n const payload: LensValidatePayload = { context, zone }\n return this.send<LensValidatePayload, LensValidateResponse>('lens-validate', payload, 'anchor')\n }\n\n /**\n * Run full Anchor validation with optional lens context\n */\n async validateAnchor(\n statement?: string,\n lensContext?: LensContext,\n zone?: Zone\n ): Promise<AnchorValidateResponse> {\n const payload: AnchorValidatePayload = { statement, lensContext, zone }\n return this.send<AnchorValidatePayload, AnchorValidateResponse>('anchor-validate', payload, 'anchor')\n }\n\n /**\n * Get the current transport\n */\n getTransport(): IPCTransport {\n return this.transport\n }\n\n /**\n * Set a new transport\n */\n setTransport(transport: IPCTransport): void {\n this.transport = transport\n }\n}\n\n/** Default IPC client instance */\nlet defaultClient: IPCClient | null = null\n\n/**\n * Get the default IPC client instance\n */\nexport function getIPCClient(): IPCClient {\n if (!defaultClient) {\n defaultClient = new IPCClient()\n }\n return defaultClient\n}\n\n/**\n * Reset the default IPC client (useful for testing)\n */\nexport function resetIPCClient(): void {\n defaultClient = null\n}\n\n/**\n * Create an IPC client with file-system transport\n * Use this in Node.js/Electron environments for production IPC\n *\n * Example:\n * import fs from 'fs/promises'\n * const client = createFileSystemClient(fs, 'grimoires/pub')\n */\nexport function createFileSystemClient(\n fsOps: FileSystemOps,\n basePath = 'grimoires/pub',\n config?: IPCClientConfig\n): IPCClient {\n return new IPCClient(new FileSystemTransport(basePath, fsOps), config)\n}\n","/**\n * Hook for managing fork chain state\n *\n * Provides React integration for fork service.\n */\n\nimport { useState, useCallback, useEffect, useRef } from 'react'\nimport type { Address } from 'viem'\nimport {\n createForkService,\n type ForkService,\n type ForkConfig,\n type ForkState,\n type ForkSnapshot,\n type ForkProvider,\n} from '../services/fork'\n\n/**\n * Fork state hook return type\n */\nexport interface UseForkStateReturn {\n /** Current fork state */\n state: ForkState\n /** Whether fork operation is in progress */\n isLoading: boolean\n /** Error message if any */\n error: string | null\n /** Create a new fork */\n createFork: (config: ForkConfig) => Promise<void>\n /** Take a snapshot */\n snapshot: (description?: string) => Promise<ForkSnapshot | null>\n /** Revert to a snapshot */\n revert: (snapshotId: string) => Promise<boolean>\n /** Reset fork to initial state */\n reset: () => Promise<void>\n /** Destroy the fork */\n destroy: () => Promise<void>\n /** Set account balance */\n setBalance: (address: Address, balance: bigint) => Promise<void>\n /** Impersonate an account */\n impersonateAccount: (address: Address) => Promise<void>\n /** Stop impersonating an account */\n stopImpersonating: (address: Address) => Promise<void>\n /** Mine blocks */\n mineBlock: (blocks?: number) => Promise<void>\n /** All snapshots taken */\n snapshots: ForkSnapshot[]\n}\n\n/**\n * Hook for managing fork chain state\n */\nexport function useForkState(defaultProvider: ForkProvider = 'anvil'): UseForkStateReturn {\n const [state, setState] = useState<ForkState>({\n active: false,\n rpcUrl: null,\n blockNumber: null,\n chainId: null,\n createdAt: null,\n snapshotCount: 0,\n currentSnapshotId: null,\n })\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [snapshots, setSnapshots] = useState<ForkSnapshot[]>([])\n\n const serviceRef = useRef<ForkService | null>(null)\n\n // Initialize service on mount\n useEffect(() => {\n serviceRef.current = createForkService(defaultProvider)\n return () => {\n if (serviceRef.current) {\n serviceRef.current.destroy()\n serviceRef.current = null\n }\n }\n }, [defaultProvider])\n\n const createFork = useCallback(async (config: ForkConfig) => {\n if (!serviceRef.current) {\n serviceRef.current = createForkService(config.provider)\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n const newState = await serviceRef.current.createFork(config)\n setState(newState)\n setSnapshots([])\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to create fork'\n setError(message)\n throw err\n } finally {\n setIsLoading(false)\n }\n }, [])\n\n const snapshot = useCallback(async (description?: string): Promise<ForkSnapshot | null> => {\n if (!serviceRef.current) {\n setError('Fork service not initialized')\n return null\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n const snap = await serviceRef.current.snapshot(description)\n setSnapshots(prev => [...prev, snap])\n setState(serviceRef.current!.getState())\n return snap\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to take snapshot'\n setError(message)\n return null\n } finally {\n setIsLoading(false)\n }\n }, [])\n\n const revert = useCallback(async (snapshotId: string): Promise<boolean> => {\n if (!serviceRef.current) {\n setError('Fork service not initialized')\n return false\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n const success = await serviceRef.current.revert(snapshotId)\n if (success) {\n setState(serviceRef.current.getState())\n }\n return success\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to revert'\n setError(message)\n return false\n } finally {\n setIsLoading(false)\n }\n }, [])\n\n const reset = useCallback(async () => {\n if (!serviceRef.current) {\n setError('Fork service not initialized')\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n await serviceRef.current.reset()\n setState(serviceRef.current.getState())\n setSnapshots([])\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to reset'\n setError(message)\n } finally {\n setIsLoading(false)\n }\n }, [])\n\n const destroy = useCallback(async () => {\n if (!serviceRef.current) return\n\n setIsLoading(true)\n setError(null)\n\n try {\n await serviceRef.current.destroy()\n setState({\n active: false,\n rpcUrl: null,\n blockNumber: null,\n chainId: null,\n createdAt: null,\n snapshotCount: 0,\n currentSnapshotId: null,\n })\n setSnapshots([])\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to destroy fork'\n setError(message)\n } finally {\n setIsLoading(false)\n }\n }, [])\n\n const setBalance = useCallback(async (address: Address, balance: bigint) => {\n if (!serviceRef.current) {\n setError('Fork service not initialized')\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n await serviceRef.current.setBalance(address, balance)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to set balance'\n setError(message)\n } finally {\n setIsLoading(false)\n }\n }, [])\n\n const impersonateAccount = useCallback(async (address: Address) => {\n if (!serviceRef.current) {\n setError('Fork service not initialized')\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n await serviceRef.current.impersonateAccount(address)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to impersonate account'\n setError(message)\n } finally {\n setIsLoading(false)\n }\n }, [])\n\n const stopImpersonating = useCallback(async (address: Address) => {\n if (!serviceRef.current) {\n setError('Fork service not initialized')\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n await serviceRef.current.stopImpersonating(address)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to stop impersonating'\n setError(message)\n } finally {\n setIsLoading(false)\n }\n }, [])\n\n const mineBlock = useCallback(async (blocks = 1) => {\n if (!serviceRef.current) {\n setError('Fork service not initialized')\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n await serviceRef.current.mineBlock(blocks)\n setState(serviceRef.current.getState())\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to mine block'\n setError(message)\n } finally {\n setIsLoading(false)\n }\n }, [])\n\n return {\n state,\n isLoading,\n error,\n createFork,\n snapshot,\n revert,\n reset,\n destroy,\n setBalance,\n impersonateAccount,\n stopImpersonating,\n mineBlock,\n snapshots,\n }\n}\n","/**\n * Fork Chain State Service\n *\n * Provides integration with Anvil/Tenderly for chain state forking.\n * Enables transaction simulation without real funds.\n */\n\nimport type { Address } from 'viem'\n\n/**\n * Fork provider type\n */\nexport type ForkProvider = 'anvil' | 'tenderly' | 'custom'\n\n/**\n * Fork configuration\n */\nexport interface ForkConfig {\n /** Fork provider type */\n provider: ForkProvider\n /** RPC URL to fork from (mainnet, testnet, etc.) */\n forkUrl: string\n /** Block number to fork at (undefined = latest) */\n forkBlockNumber?: bigint\n /** Chain ID for the fork */\n chainId: number\n /** Anvil-specific: port to run on */\n anvilPort?: number\n /** Tenderly-specific: project slug */\n tenderlyProject?: string\n /** Tenderly-specific: API key */\n tenderlyApiKey?: string\n /** Custom fork RPC URL (when provider = 'custom') */\n customForkRpc?: string\n}\n\n/**\n * Fork state\n */\nexport interface ForkState {\n /** Whether fork is active */\n active: boolean\n /** Fork RPC URL */\n rpcUrl: string | null\n /** Block number fork was created at */\n blockNumber: bigint | null\n /** Chain ID */\n chainId: number | null\n /** Fork creation timestamp */\n createdAt: number | null\n /** Number of snapshots taken */\n snapshotCount: number\n /** Current snapshot ID */\n currentSnapshotId: string | null\n}\n\n/**\n * Fork snapshot for state restoration\n */\nexport interface ForkSnapshot {\n id: string\n blockNumber: bigint\n timestamp: number\n description?: string\n}\n\n/**\n * Fork service interface\n */\nexport interface ForkService {\n /** Create a new fork */\n createFork(config: ForkConfig): Promise<ForkState>\n /** Get current fork state */\n getState(): ForkState\n /** Take a snapshot of current fork state */\n snapshot(description?: string): Promise<ForkSnapshot>\n /** Revert to a snapshot */\n revert(snapshotId: string): Promise<boolean>\n /** Reset fork to initial state */\n reset(): Promise<void>\n /** Destroy the fork */\n destroy(): Promise<void>\n /** Set account balance (for testing) */\n setBalance(address: Address, balance: bigint): Promise<void>\n /** Impersonate an address (for testing) */\n impersonateAccount(address: Address): Promise<void>\n /** Stop impersonating an address */\n stopImpersonating(address: Address): Promise<void>\n /** Mine a block */\n mineBlock(blocks?: number): Promise<void>\n /** Get fork RPC URL */\n getRpcUrl(): string | null\n}\n\n/**\n * Create an Anvil-based fork service\n */\nexport function createAnvilForkService(): ForkService {\n let state: ForkState = {\n active: false,\n rpcUrl: null,\n blockNumber: null,\n chainId: null,\n createdAt: null,\n snapshotCount: 0,\n currentSnapshotId: null,\n }\n\n const snapshots: Map<string, ForkSnapshot> = new Map()\n\n async function jsonRpc(method: string, params: unknown[] = []): Promise<unknown> {\n if (!state.rpcUrl) {\n throw new Error('Fork not active')\n }\n\n const response = await fetch(state.rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: Date.now(),\n method,\n params,\n }),\n })\n\n const data = await response.json()\n if (data.error) {\n throw new Error(data.error.message || 'RPC error')\n }\n return data.result\n }\n\n return {\n async createFork(config: ForkConfig): Promise<ForkState> {\n // For Anvil, we assume it's already running at the specified port\n // In a real implementation, we might spawn Anvil as a subprocess\n const rpcUrl = config.customForkRpc || `http://127.0.0.1:${config.anvilPort || 8545}`\n\n try {\n // Test connection and get chain ID\n const chainIdHex = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'eth_chainId',\n params: [],\n }),\n }).then(r => r.json()).then(d => d.result)\n\n const blockNumberHex = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 2,\n method: 'eth_blockNumber',\n params: [],\n }),\n }).then(r => r.json()).then(d => d.result)\n\n state = {\n active: true,\n rpcUrl,\n blockNumber: BigInt(blockNumberHex),\n chainId: parseInt(chainIdHex, 16),\n createdAt: Date.now(),\n snapshotCount: 0,\n currentSnapshotId: null,\n }\n\n return state\n } catch (error) {\n throw new Error(`Failed to connect to Anvil at ${rpcUrl}: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n },\n\n getState(): ForkState {\n return { ...state }\n },\n\n async snapshot(description?: string): Promise<ForkSnapshot> {\n const result = await jsonRpc('evm_snapshot') as string\n const id = result\n\n const blockNumberHex = await jsonRpc('eth_blockNumber') as string\n const snapshot: ForkSnapshot = {\n id,\n blockNumber: BigInt(blockNumberHex),\n timestamp: Date.now(),\n description,\n }\n\n snapshots.set(id, snapshot)\n state.snapshotCount++\n state.currentSnapshotId = id\n\n return snapshot\n },\n\n async revert(snapshotId: string): Promise<boolean> {\n const result = await jsonRpc('evm_revert', [snapshotId]) as boolean\n if (result) {\n state.currentSnapshotId = snapshotId\n }\n return result\n },\n\n async reset(): Promise<void> {\n await jsonRpc('anvil_reset')\n snapshots.clear()\n state.snapshotCount = 0\n state.currentSnapshotId = null\n },\n\n async destroy(): Promise<void> {\n state = {\n active: false,\n rpcUrl: null,\n blockNumber: null,\n chainId: null,\n createdAt: null,\n snapshotCount: 0,\n currentSnapshotId: null,\n }\n snapshots.clear()\n },\n\n async setBalance(address: Address, balance: bigint): Promise<void> {\n await jsonRpc('anvil_setBalance', [address, `0x${balance.toString(16)}`])\n },\n\n async impersonateAccount(address: Address): Promise<void> {\n await jsonRpc('anvil_impersonateAccount', [address])\n },\n\n async stopImpersonating(address: Address): Promise<void> {\n await jsonRpc('anvil_stopImpersonatingAccount', [address])\n },\n\n async mineBlock(blocks = 1): Promise<void> {\n await jsonRpc('anvil_mine', [blocks])\n },\n\n getRpcUrl(): string | null {\n return state.rpcUrl\n },\n }\n}\n\n/**\n * Create a Tenderly-based fork service\n */\nexport function createTenderlyForkService(): ForkService {\n let state: ForkState = {\n active: false,\n rpcUrl: null,\n blockNumber: null,\n chainId: null,\n createdAt: null,\n snapshotCount: 0,\n currentSnapshotId: null,\n }\n\n let forkId: string | null = null\n let config: ForkConfig | null = null\n\n async function tenderlyApi(endpoint: string, method = 'GET', body?: unknown): Promise<unknown> {\n if (!config?.tenderlyApiKey || !config?.tenderlyProject) {\n throw new Error('Tenderly API key and project required')\n }\n\n const response = await fetch(`https://api.tenderly.co/api/v1/account/${config.tenderlyProject}/project/${config.tenderlyProject}${endpoint}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'X-Access-Key': config.tenderlyApiKey,\n },\n body: body ? JSON.stringify(body) : undefined,\n })\n\n if (!response.ok) {\n throw new Error(`Tenderly API error: ${response.statusText}`)\n }\n\n return response.json()\n }\n\n return {\n async createFork(cfg: ForkConfig): Promise<ForkState> {\n config = cfg\n\n const forkResponse = await tenderlyApi('/fork', 'POST', {\n network_id: cfg.chainId.toString(),\n block_number: cfg.forkBlockNumber ? Number(cfg.forkBlockNumber) : undefined,\n }) as { simulation_fork: { id: string; block_number: number; rpc_url: string } }\n\n forkId = forkResponse.simulation_fork.id\n\n state = {\n active: true,\n rpcUrl: forkResponse.simulation_fork.rpc_url,\n blockNumber: BigInt(forkResponse.simulation_fork.block_number),\n chainId: cfg.chainId,\n createdAt: Date.now(),\n snapshotCount: 0,\n currentSnapshotId: null,\n }\n\n return state\n },\n\n getState(): ForkState {\n return { ...state }\n },\n\n async snapshot(description?: string): Promise<ForkSnapshot> {\n if (!forkId) throw new Error('Fork not active')\n\n const response = await tenderlyApi(`/fork/${forkId}/snapshot`, 'POST') as { snapshot: { id: string; block_number: number } }\n\n const snapshot: ForkSnapshot = {\n id: response.snapshot.id,\n blockNumber: BigInt(response.snapshot.block_number),\n timestamp: Date.now(),\n description,\n }\n\n state.snapshotCount++\n state.currentSnapshotId = snapshot.id\n\n return snapshot\n },\n\n async revert(snapshotId: string): Promise<boolean> {\n if (!forkId) throw new Error('Fork not active')\n\n try {\n await tenderlyApi(`/fork/${forkId}/snapshot/${snapshotId}`, 'PUT')\n state.currentSnapshotId = snapshotId\n return true\n } catch {\n return false\n }\n },\n\n async reset(): Promise<void> {\n if (!forkId || !config) throw new Error('Fork not active')\n\n // Delete and recreate the fork\n await tenderlyApi(`/fork/${forkId}`, 'DELETE')\n await this.createFork(config)\n },\n\n async destroy(): Promise<void> {\n if (forkId) {\n try {\n await tenderlyApi(`/fork/${forkId}`, 'DELETE')\n } catch {\n // Ignore errors during cleanup\n }\n }\n\n state = {\n active: false,\n rpcUrl: null,\n blockNumber: null,\n chainId: null,\n createdAt: null,\n snapshotCount: 0,\n currentSnapshotId: null,\n }\n forkId = null\n config = null\n },\n\n async setBalance(address: Address, balance: bigint): Promise<void> {\n if (!state.rpcUrl) throw new Error('Fork not active')\n\n await fetch(state.rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: Date.now(),\n method: 'tenderly_setBalance',\n params: [address, `0x${balance.toString(16)}`],\n }),\n })\n },\n\n async impersonateAccount(_address: Address): Promise<void> {\n // Tenderly handles impersonation differently - not needed for basic fork\n },\n\n async stopImpersonating(_address: Address): Promise<void> {\n // Tenderly handles impersonation differently - not needed for basic fork\n },\n\n async mineBlock(blocks = 1): Promise<void> {\n if (!state.rpcUrl) throw new Error('Fork not active')\n\n await fetch(state.rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: Date.now(),\n method: 'evm_increaseTime',\n params: [blocks * 12], // 12 seconds per block\n }),\n })\n },\n\n getRpcUrl(): string | null {\n return state.rpcUrl\n },\n }\n}\n\n/**\n * Create a fork service based on provider type\n */\nexport function createForkService(provider: ForkProvider): ForkService {\n switch (provider) {\n case 'anvil':\n return createAnvilForkService()\n case 'tenderly':\n return createTenderlyForkService()\n case 'custom':\n return createAnvilForkService() // Custom uses same interface as Anvil\n default:\n throw new Error(`Unknown fork provider: ${provider}`)\n }\n}\n\n/**\n * Default fork service singleton\n */\nlet defaultForkService: ForkService | null = null\n\n/**\n * Get the default fork service\n */\nexport function getForkService(provider: ForkProvider = 'anvil'): ForkService {\n if (!defaultForkService) {\n defaultForkService = createForkService(provider)\n }\n return defaultForkService\n}\n\n/**\n * Reset the default fork service\n */\nexport function resetForkService(): void {\n if (defaultForkService) {\n defaultForkService.destroy()\n defaultForkService = null\n }\n}\n","/**\n * Hook for Transaction Simulation\n *\n * Provides easy integration for simulating transactions against a fork.\n * Manages fork state, simulation service, and result caching.\n */\n\nimport { useState, useCallback, useRef, useEffect } from 'react'\nimport type { Address, Hex } from 'viem'\nimport {\n createForkService,\n type ForkService,\n type ForkConfig,\n type ForkProvider,\n} from '../services/fork'\nimport {\n createSimulationService,\n type SimulationService,\n type SimulationResult,\n type SimulationTransactionRequest,\n} from '../services/simulation'\n\n/**\n * Transaction request input for the hook\n */\nexport interface TransactionInput {\n /** Transaction recipient */\n to: Address\n /** Transaction data */\n data?: Hex\n /** Transaction value in wei */\n value?: bigint\n /** Gas limit (optional) */\n gas?: bigint\n}\n\n/**\n * Hook configuration\n */\nexport interface UseTransactionSimulationConfig {\n /** Fork provider (default: 'anvil') */\n provider?: ForkProvider\n /** Fork RPC URL (for custom provider) */\n forkUrl?: string\n /** Chain ID */\n chainId?: number\n /** Anvil port (default: 8545) */\n anvilPort?: number\n /** Auto-connect on mount */\n autoConnect?: boolean\n /** Sender address (will be impersonated) */\n from?: Address\n}\n\n/**\n * Hook return type\n */\nexport interface UseTransactionSimulationReturn {\n /** Latest simulation result */\n result: SimulationResult | null\n /** Whether simulation is running */\n isSimulating: boolean\n /** Whether fork is connected */\n isConnected: boolean\n /** Whether fork is connecting */\n isConnecting: boolean\n /** Error message if any */\n error: string | null\n /** Simulate a transaction */\n simulate: (tx: TransactionInput) => Promise<SimulationResult | null>\n /** Connect to fork */\n connect: (config?: Partial<ForkConfig>) => Promise<void>\n /** Disconnect from fork */\n disconnect: () => Promise<void>\n /** Clear the last result */\n clearResult: () => void\n /** Reset the fork state */\n reset: () => Promise<void>\n}\n\n/**\n * Hook for transaction simulation\n *\n * @example\n * ```tsx\n * const { result, isSimulating, error, simulate } = useTransactionSimulation({\n * from: '0x...',\n * autoConnect: true,\n * })\n *\n * const handleSimulate = async () => {\n * await simulate({\n * to: '0x...',\n * data: '0x...',\n * value: 0n,\n * })\n * }\n * ```\n */\nexport function useTransactionSimulation(\n config: UseTransactionSimulationConfig = {}\n): UseTransactionSimulationReturn {\n const {\n provider = 'anvil',\n forkUrl,\n chainId = 1,\n anvilPort = 8545,\n autoConnect = false,\n from,\n } = config\n\n const [result, setResult] = useState<SimulationResult | null>(null)\n const [isSimulating, setIsSimulating] = useState(false)\n const [isConnected, setIsConnected] = useState(false)\n const [isConnecting, setIsConnecting] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const forkServiceRef = useRef<ForkService | null>(null)\n const simulationServiceRef = useRef<SimulationService | null>(null)\n const fromAddressRef = useRef<Address | undefined>(from)\n\n // Update from address ref when prop changes\n useEffect(() => {\n fromAddressRef.current = from\n }, [from])\n\n // Connect to fork\n const connect = useCallback(async (overrideConfig?: Partial<ForkConfig>) => {\n if (isConnected || isConnecting) return\n\n setIsConnecting(true)\n setError(null)\n\n try {\n const forkConfig: ForkConfig = {\n provider: overrideConfig?.provider ?? provider,\n forkUrl: overrideConfig?.forkUrl ?? forkUrl ?? '',\n chainId: overrideConfig?.chainId ?? chainId,\n anvilPort: overrideConfig?.anvilPort ?? anvilPort,\n customForkRpc: overrideConfig?.customForkRpc,\n }\n\n // Create fork service\n forkServiceRef.current = createForkService(forkConfig.provider)\n await forkServiceRef.current.createFork(forkConfig)\n\n // Create simulation service\n simulationServiceRef.current = createSimulationService(forkServiceRef.current)\n\n setIsConnected(true)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to connect to fork'\n setError(message)\n forkServiceRef.current = null\n simulationServiceRef.current = null\n } finally {\n setIsConnecting(false)\n }\n }, [isConnected, isConnecting, provider, forkUrl, chainId, anvilPort])\n\n // Disconnect from fork\n const disconnect = useCallback(async () => {\n if (forkServiceRef.current) {\n await forkServiceRef.current.destroy()\n forkServiceRef.current = null\n simulationServiceRef.current = null\n }\n setIsConnected(false)\n setResult(null)\n setError(null)\n }, [])\n\n // Auto-connect on mount if enabled\n useEffect(() => {\n if (autoConnect) {\n connect()\n }\n return () => {\n // Cleanup on unmount\n if (forkServiceRef.current) {\n forkServiceRef.current.destroy()\n }\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Simulate transaction\n const simulate = useCallback(async (tx: TransactionInput): Promise<SimulationResult | null> => {\n if (!simulationServiceRef.current || !forkServiceRef.current) {\n setError('Not connected to fork. Call connect() first.')\n return null\n }\n\n const senderAddress = fromAddressRef.current\n if (!senderAddress) {\n setError('No sender address provided. Set \"from\" in config.')\n return null\n }\n\n setIsSimulating(true)\n setError(null)\n\n try {\n const request: SimulationTransactionRequest = {\n from: senderAddress,\n to: tx.to,\n data: tx.data,\n value: tx.value,\n gas: tx.gas,\n }\n\n const simResult = await simulationServiceRef.current.simulate(request)\n setResult(simResult)\n return simResult\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Simulation failed'\n setError(message)\n return null\n } finally {\n setIsSimulating(false)\n }\n }, [])\n\n // Clear result\n const clearResult = useCallback(() => {\n setResult(null)\n setError(null)\n }, [])\n\n // Reset fork state\n const reset = useCallback(async () => {\n if (forkServiceRef.current) {\n await forkServiceRef.current.reset()\n setResult(null)\n setError(null)\n }\n }, [])\n\n return {\n result,\n isSimulating,\n isConnected,\n isConnecting,\n error,\n simulate,\n connect,\n disconnect,\n clearResult,\n reset,\n }\n}\n\n/**\n * Hook for simulation with automatic fork management\n *\n * Simplified version that auto-connects and manages fork lifecycle.\n *\n * @example\n * ```tsx\n * const { result, isSimulating, simulate } = useSimulation('0x...')\n *\n * // Simulate a simple transfer\n * await simulate({\n * to: recipientAddress,\n * value: parseEther('1'),\n * })\n * ```\n */\nexport function useSimulation(\n from: Address,\n options: Omit<UseTransactionSimulationConfig, 'from' | 'autoConnect'> = {}\n): Omit<UseTransactionSimulationReturn, 'connect' | 'disconnect'> {\n const hook = useTransactionSimulation({\n ...options,\n from,\n autoConnect: true,\n })\n\n // Destructure to omit connect/disconnect from return\n const { connect: _connect, disconnect: _disconnect, ...rest } = hook\n return rest\n}\n","/**\n * Transaction Simulation Service\n *\n * Executes transactions against fork and captures results.\n * Provides dry-run functionality without real funds.\n */\n\nimport type { Address, Hash, Hex } from 'viem'\nimport type { ForkService } from './fork'\n\n/**\n * Transaction request for simulation\n */\nexport interface SimulationTransactionRequest {\n /** Transaction sender */\n from: Address\n /** Transaction recipient */\n to: Address\n /** Transaction value in wei */\n value?: bigint\n /** Transaction data */\n data?: Hex\n /** Gas limit (optional, will be estimated if not provided) */\n gas?: bigint\n /** Gas price (optional) */\n gasPrice?: bigint\n /** Max fee per gas (EIP-1559) */\n maxFeePerGas?: bigint\n /** Max priority fee per gas (EIP-1559) */\n maxPriorityFeePerGas?: bigint\n /** Nonce (optional, will be fetched if not provided) */\n nonce?: number\n}\n\n/**\n * Balance change from simulation\n */\nexport interface BalanceChange {\n /** Address whose balance changed */\n address: Address\n /** Token address (null for ETH) */\n token: Address | null\n /** Token symbol (if known) */\n symbol?: string\n /** Balance before transaction */\n before: bigint\n /** Balance after transaction */\n after: bigint\n /** Change amount (can be negative) */\n delta: bigint\n}\n\n/**\n * State change from simulation\n */\nexport interface StateChange {\n /** Contract address */\n address: Address\n /** Storage slot */\n slot: Hex\n /** Value before transaction */\n before: Hex\n /** Value after transaction */\n after: Hex\n}\n\n/**\n * Event log from simulation\n */\nexport interface SimulationLog {\n /** Contract address that emitted the log */\n address: Address\n /** Log topics */\n topics: Hex[]\n /** Log data */\n data: Hex\n /** Decoded event name (if ABI available) */\n eventName?: string\n /** Decoded event args (if ABI available) */\n decodedArgs?: Record<string, unknown>\n}\n\n/**\n * Simulation result\n */\nexport interface SimulationResult {\n /** Whether transaction succeeded */\n success: boolean\n /** Transaction hash (from simulation) */\n hash?: Hash\n /** Gas used */\n gasUsed: bigint\n /** Gas limit */\n gasLimit: bigint\n /** Effective gas price */\n effectiveGasPrice: bigint\n /** Total cost in wei (gasUsed * effectiveGasPrice + value) */\n totalCost: bigint\n /** Return value (if any) */\n returnValue?: Hex\n /** Revert reason (if failed) */\n revertReason?: string\n /** Balance changes */\n balanceChanges: BalanceChange[]\n /** State changes */\n stateChanges: StateChange[]\n /** Event logs */\n logs: SimulationLog[]\n /** Block number simulation was run at */\n blockNumber: bigint\n /** Timestamp of simulation */\n timestamp: number\n}\n\n/**\n * Simulation service interface\n */\nexport interface SimulationService {\n /** Simulate a transaction */\n simulate(tx: SimulationTransactionRequest): Promise<SimulationResult>\n /** Estimate gas for a transaction */\n estimateGas(tx: SimulationTransactionRequest): Promise<bigint>\n /** Get current gas price */\n getGasPrice(): Promise<bigint>\n /** Decode revert reason from error data */\n decodeRevertReason(data: Hex): string | null\n}\n\n/**\n * Parse revert reason from error data\n */\nfunction parseRevertReason(data: Hex): string | null {\n // Check for Error(string) selector: 0x08c379a0\n if (data.startsWith('0x08c379a0') && data.length >= 138) {\n try {\n // Skip selector (4 bytes) and offset (32 bytes)\n const lengthHex = data.slice(74, 138)\n const length = parseInt(lengthHex, 16)\n if (length > 0 && length < 1000) {\n const messageHex = data.slice(138, 138 + length * 2)\n const message = Buffer.from(messageHex, 'hex').toString('utf8')\n return message\n }\n } catch {\n // Ignore parsing errors\n }\n }\n\n // Check for Panic(uint256) selector: 0x4e487b71\n if (data.startsWith('0x4e487b71') && data.length >= 74) {\n const panicCode = parseInt(data.slice(10, 74), 16)\n const panicMessages: Record<number, string> = {\n 0x00: 'Generic compiler panic',\n 0x01: 'Assert failed',\n 0x11: 'Arithmetic overflow/underflow',\n 0x12: 'Division by zero',\n 0x21: 'Invalid enum value',\n 0x22: 'Invalid storage byte array',\n 0x31: 'Pop on empty array',\n 0x32: 'Array index out of bounds',\n 0x41: 'Too much memory allocated',\n 0x51: 'Internal function called',\n }\n return panicMessages[panicCode] || `Panic(0x${panicCode.toString(16)})`\n }\n\n // Custom error or unknown format\n if (data.length > 10) {\n const selector = data.slice(0, 10)\n return `Custom error: ${selector}`\n }\n\n return null\n}\n\n/**\n * Create a simulation service using a fork service\n */\nexport function createSimulationService(forkService: ForkService): SimulationService {\n async function jsonRpc(method: string, params: unknown[] = []): Promise<unknown> {\n const rpcUrl = forkService.getRpcUrl()\n if (!rpcUrl) {\n throw new Error('Fork not active')\n }\n\n const response = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: Date.now(),\n method,\n params,\n }),\n })\n\n const data = await response.json()\n if (data.error) {\n throw new Error(data.error.message || 'RPC error')\n }\n return data.result\n }\n\n async function getBalance(address: Address): Promise<bigint> {\n const result = await jsonRpc('eth_getBalance', [address, 'latest'])\n return BigInt(result as string)\n }\n\n return {\n async simulate(tx: SimulationTransactionRequest): Promise<SimulationResult> {\n const timestamp = Date.now()\n\n // Get current block number\n const blockNumberHex = await jsonRpc('eth_blockNumber') as string\n const blockNumber = BigInt(blockNumberHex)\n\n // Get balances before\n const fromBalanceBefore = await getBalance(tx.from)\n const toBalanceBefore = await getBalance(tx.to)\n\n // Estimate gas if not provided\n const gasLimit = tx.gas ?? await this.estimateGas(tx)\n\n // Get gas price\n const gasPrice = tx.gasPrice ?? tx.maxFeePerGas ?? await this.getGasPrice()\n\n // Take a snapshot before simulation\n const snapshot = await forkService.snapshot('pre-simulation')\n\n // Prepare transaction params\n const txParams = {\n from: tx.from,\n to: tx.to,\n value: tx.value ? `0x${tx.value.toString(16)}` : '0x0',\n data: tx.data ?? '0x',\n gas: `0x${gasLimit.toString(16)}`,\n gasPrice: `0x${gasPrice.toString(16)}`,\n nonce: tx.nonce !== undefined ? `0x${tx.nonce.toString(16)}` : undefined,\n }\n\n let success = true\n let hash: Hash | undefined\n let gasUsed = 0n\n let returnValue: Hex | undefined\n let revertReason: string | undefined\n const logs: SimulationLog[] = []\n\n try {\n // Impersonate the sender\n await forkService.impersonateAccount(tx.from)\n\n // Send transaction\n hash = await jsonRpc('eth_sendTransaction', [txParams]) as Hash\n\n // Wait for transaction receipt\n let receipt = null\n let attempts = 0\n while (!receipt && attempts < 50) {\n await new Promise(resolve => setTimeout(resolve, 100))\n receipt = await jsonRpc('eth_getTransactionReceipt', [hash])\n attempts++\n }\n\n if (receipt) {\n const r = receipt as {\n status: string\n gasUsed: string\n logs: Array<{ address: string; topics: string[]; data: string }>\n }\n\n success = r.status === '0x1'\n gasUsed = BigInt(r.gasUsed)\n\n // Parse logs\n for (const log of r.logs) {\n logs.push({\n address: log.address as Address,\n topics: log.topics as Hex[],\n data: log.data as Hex,\n })\n }\n\n // If failed, try to get revert reason\n if (!success) {\n try {\n await jsonRpc('eth_call', [txParams, 'latest'])\n } catch (callError) {\n if (callError instanceof Error && callError.message) {\n revertReason = callError.message\n }\n }\n }\n }\n } catch (error) {\n success = false\n if (error instanceof Error) {\n // Try to extract revert reason from error\n const errorData = (error as unknown as { data?: string }).data\n if (errorData) {\n revertReason = parseRevertReason(errorData as Hex) ?? error.message\n } else {\n revertReason = error.message\n }\n }\n } finally {\n // Always stop impersonating, even on error (FR-006 fix)\n try {\n await forkService.stopImpersonating(tx.from)\n } catch {\n // Ignore cleanup errors to avoid masking original error\n }\n }\n\n // Get balances after\n const fromBalanceAfter = await getBalance(tx.from)\n const toBalanceAfter = await getBalance(tx.to)\n\n // Calculate balance changes\n const balanceChanges: BalanceChange[] = []\n\n if (fromBalanceBefore !== fromBalanceAfter) {\n balanceChanges.push({\n address: tx.from,\n token: null,\n symbol: 'ETH',\n before: fromBalanceBefore,\n after: fromBalanceAfter,\n delta: fromBalanceAfter - fromBalanceBefore,\n })\n }\n\n if (tx.from !== tx.to && toBalanceBefore !== toBalanceAfter) {\n balanceChanges.push({\n address: tx.to,\n token: null,\n symbol: 'ETH',\n before: toBalanceBefore,\n after: toBalanceAfter,\n delta: toBalanceAfter - toBalanceBefore,\n })\n }\n\n // Revert to snapshot to restore state\n await forkService.revert(snapshot.id)\n\n // Calculate total cost\n const effectiveGasPrice = gasPrice\n const totalCost = gasUsed * effectiveGasPrice + (tx.value ?? 0n)\n\n return {\n success,\n hash,\n gasUsed,\n gasLimit,\n effectiveGasPrice,\n totalCost,\n returnValue,\n revertReason,\n balanceChanges,\n stateChanges: [], // State changes require trace API\n logs,\n blockNumber,\n timestamp,\n }\n },\n\n async estimateGas(tx: SimulationTransactionRequest): Promise<bigint> {\n const txParams = {\n from: tx.from,\n to: tx.to,\n value: tx.value ? `0x${tx.value.toString(16)}` : '0x0',\n data: tx.data ?? '0x',\n }\n\n try {\n const result = await jsonRpc('eth_estimateGas', [txParams])\n // Add 20% buffer\n const estimate = BigInt(result as string)\n return (estimate * 120n) / 100n\n } catch (error) {\n // Return a default gas limit if estimation fails\n return 21000n\n }\n },\n\n async getGasPrice(): Promise<bigint> {\n const result = await jsonRpc('eth_gasPrice')\n return BigInt(result as string)\n },\n\n decodeRevertReason(data: Hex): string | null {\n return parseRevertReason(data)\n },\n }\n}\n\n/**\n * Default simulation service singleton\n */\nlet defaultSimulationService: SimulationService | null = null\n\n/**\n * Get the default simulation service\n */\nexport function getSimulationService(forkService: ForkService): SimulationService {\n if (!defaultSimulationService) {\n defaultSimulationService = createSimulationService(forkService)\n }\n return defaultSimulationService\n}\n\n/**\n * Reset the default simulation service\n */\nexport function resetSimulationService(): void {\n defaultSimulationService = null\n}\n","import { useState, useCallback } from 'react'\nimport { isAddress } from 'viem'\nimport type { Address } from 'viem'\nimport { useDevToolbar } from '../providers/DevToolbarProvider'\nimport { useSavedAddresses, useIsImpersonating } from '../hooks/useUserLens'\n\n/**\n * Validates an Ethereum address or ENS name\n */\nfunction isValidAddressInput(input: string): boolean {\n // Check if it's a valid address\n if (isAddress(input)) return true\n // Check if it looks like an ENS name\n if (input.endsWith('.eth') && input.length > 4) return true\n return false\n}\n\n/**\n * Truncates an address for display\n */\nfunction truncateAddress(address: string): string {\n if (address.length <= 10) return address\n return `${address.slice(0, 6)}...${address.slice(-4)}`\n}\n\n/**\n * User Lens panel for address impersonation\n */\nexport function UserLens() {\n const [input, setInput] = useState('')\n const [error, setError] = useState<string | null>(null)\n const [isResolving, setIsResolving] = useState(false)\n\n const { setImpersonatedAddress, disableLens, saveAddress, userLens } = useDevToolbar()\n const { savedAddresses, selectAddress, removeAddress } = useSavedAddresses()\n const isImpersonating = useIsImpersonating()\n\n const handleSubmit = useCallback(\n async (e: React.FormEvent) => {\n e.preventDefault()\n setError(null)\n\n const trimmed = input.trim()\n if (!trimmed) return\n\n if (!isValidAddressInput(trimmed)) {\n setError('Invalid address or ENS name')\n return\n }\n\n // If it's an ENS name, we'd need to resolve it\n // For now, we just check if it's a valid address\n if (isAddress(trimmed)) {\n setImpersonatedAddress(trimmed as Address)\n setInput('')\n } else if (trimmed.endsWith('.eth')) {\n // ENS resolution would go here\n // For MVP, show placeholder\n setIsResolving(true)\n setError('ENS resolution not yet implemented. Please use address.')\n setIsResolving(false)\n }\n },\n [input, setImpersonatedAddress]\n )\n\n const handleClear = useCallback(() => {\n disableLens()\n setInput('')\n setError(null)\n }, [disableLens])\n\n const handleSaveCurrentAddress = useCallback(() => {\n const trimmed = input.trim()\n if (isAddress(trimmed)) {\n saveAddress({\n address: trimmed as Address,\n label: `Address ${savedAddresses.length + 1}`,\n })\n }\n }, [input, saveAddress, savedAddresses.length])\n\n return (\n <div className=\"sigil-user-lens\">\n <div className=\"sigil-user-lens__header\">\n <h3>User Lens</h3>\n {isImpersonating && (\n <span className=\"sigil-user-lens__badge\">Active</span>\n )}\n </div>\n\n <p className=\"sigil-user-lens__description\">\n View the app as another address. Reads use the impersonated address,\n transactions still sign with your real wallet.\n </p>\n\n <form onSubmit={handleSubmit} className=\"sigil-user-lens__form\">\n <div className=\"sigil-user-lens__input-group\">\n <input\n type=\"text\"\n value={input}\n onChange={(e) => setInput(e.target.value)}\n placeholder=\"0x... or name.eth\"\n className=\"sigil-user-lens__input\"\n disabled={isResolving}\n />\n <button\n type=\"submit\"\n className=\"sigil-user-lens__button sigil-user-lens__button--primary\"\n disabled={isResolving || !input.trim()}\n >\n {isResolving ? 'Resolving...' : 'Impersonate'}\n </button>\n </div>\n {error && <p className=\"sigil-user-lens__error\">{error}</p>}\n </form>\n\n {isImpersonating && (\n <div className=\"sigil-user-lens__active\">\n <div className=\"sigil-user-lens__active-header\">\n <span>Currently viewing as:</span>\n <button\n onClick={handleClear}\n className=\"sigil-user-lens__button sigil-user-lens__button--danger\"\n >\n Clear\n </button>\n </div>\n <code className=\"sigil-user-lens__address\">\n {userLens.impersonatedAddress}\n </code>\n </div>\n )}\n\n {savedAddresses.length > 0 && (\n <div className=\"sigil-user-lens__saved\">\n <h4>Saved Addresses</h4>\n <ul className=\"sigil-user-lens__saved-list\">\n {savedAddresses.map((entry) => (\n <li key={entry.address} className=\"sigil-user-lens__saved-item\">\n <button\n onClick={() => selectAddress(entry.address)}\n className=\"sigil-user-lens__saved-button\"\n >\n <span className=\"sigil-user-lens__saved-label\">\n {entry.label}\n </span>\n <span className=\"sigil-user-lens__saved-address\">\n {truncateAddress(entry.address)}\n </span>\n </button>\n <button\n onClick={() => removeAddress(entry.address)}\n className=\"sigil-user-lens__remove\"\n aria-label=\"Remove\"\n >\n ×\n </button>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {input && isAddress(input) && !savedAddresses.find((a) => a.address === input) && (\n <button\n onClick={handleSaveCurrentAddress}\n className=\"sigil-user-lens__button sigil-user-lens__button--secondary\"\n >\n Save Address\n </button>\n )}\n </div>\n )\n}\n\n/**\n * Badge component showing when lens is active\n */\nexport function LensActiveBadge() {\n const isImpersonating = useIsImpersonating()\n\n if (!isImpersonating) return null\n\n return (\n <div className=\"sigil-lens-badge\">\n <span className=\"sigil-lens-badge__icon\">👁</span>\n <span className=\"sigil-lens-badge__text\">Lens Active</span>\n </div>\n )\n}\n","import { useCallback } from 'react'\nimport { useDevToolbar, useDevToolbarConfig } from '../providers/DevToolbarProvider'\nimport { UserLens, LensActiveBadge } from './UserLens'\nimport type { ToolbarTab } from '../types'\n\n/**\n * Tab configuration\n */\nconst TABS: Array<{\n id: ToolbarTab\n label: string\n icon: string\n configKey: keyof Pick<\n ReturnType<typeof useDevToolbarConfig>,\n 'enableUserLens' | 'enableSimulation' | 'enableComparison' | 'enableDiagnostics'\n >\n}> = [\n { id: 'lens', label: 'Lens', icon: '👁', configKey: 'enableUserLens' },\n { id: 'simulate', label: 'Simulate', icon: '🎭', configKey: 'enableSimulation' },\n { id: 'compare', label: 'Compare', icon: '⚖️', configKey: 'enableComparison' },\n { id: 'diagnose', label: 'Diagnose', icon: '🔍', configKey: 'enableDiagnostics' },\n]\n\n/**\n * Placeholder panel for unimplemented tabs\n */\nfunction PlaceholderPanel({ title }: { title: string }) {\n return (\n <div className=\"sigil-toolbar__placeholder\">\n <h3>{title}</h3>\n <p>Coming in Sprint 4+</p>\n </div>\n )\n}\n\n/**\n * Render the active tab content\n */\nfunction TabContent({ tab }: { tab: ToolbarTab }) {\n switch (tab) {\n case 'lens':\n return <UserLens />\n case 'simulate':\n return <PlaceholderPanel title=\"Simulation\" />\n case 'compare':\n return <PlaceholderPanel title=\"State Comparison\" />\n case 'diagnose':\n return <PlaceholderPanel title=\"Diagnostics\" />\n default:\n return null\n }\n}\n\n/**\n * Main Dev Toolbar component\n *\n * Renders only in development mode (checks process.env.NODE_ENV)\n */\nexport function DevToolbar() {\n const config = useDevToolbarConfig()\n const {\n visible,\n collapsed,\n activeTab,\n setActiveTab,\n collapse,\n expand,\n toggle,\n userLens,\n } = useDevToolbar()\n\n const handleTabClick = useCallback(\n (tab: ToolbarTab) => {\n if (collapsed) {\n expand()\n }\n setActiveTab(tab)\n },\n [collapsed, expand, setActiveTab]\n )\n\n const handleToggleCollapse = useCallback(() => {\n if (collapsed) {\n expand()\n } else {\n collapse()\n }\n }, [collapsed, collapse, expand])\n\n // Only render in development\n if (process.env.NODE_ENV === 'production') {\n return null\n }\n\n if (!visible) {\n return null\n }\n\n // Filter tabs based on config\n const enabledTabs = TABS.filter((tab) => config[tab.configKey])\n\n // Position classes\n const positionClass = `sigil-toolbar--${config.position}`\n\n return (\n <div className={`sigil-toolbar ${positionClass} ${collapsed ? 'sigil-toolbar--collapsed' : ''}`}>\n {/* Header / Tab bar */}\n <div className=\"sigil-toolbar__header\">\n <div className=\"sigil-toolbar__tabs\">\n {enabledTabs.map((tab) => (\n <button\n key={tab.id}\n onClick={() => handleTabClick(tab.id)}\n className={`sigil-toolbar__tab ${activeTab === tab.id ? 'sigil-toolbar__tab--active' : ''}`}\n title={tab.label}\n >\n <span className=\"sigil-toolbar__tab-icon\">{tab.icon}</span>\n {!collapsed && <span className=\"sigil-toolbar__tab-label\">{tab.label}</span>}\n </button>\n ))}\n </div>\n\n <div className=\"sigil-toolbar__controls\">\n {/* Show lens badge when impersonating */}\n {userLens.enabled && collapsed && (\n <span className=\"sigil-toolbar__lens-indicator\" title=\"Lens Active\">\n 👁\n </span>\n )}\n\n <button\n onClick={handleToggleCollapse}\n className=\"sigil-toolbar__collapse-btn\"\n aria-label={collapsed ? 'Expand toolbar' : 'Collapse toolbar'}\n >\n {collapsed ? '◀' : '▶'}\n </button>\n\n <button\n onClick={toggle}\n className=\"sigil-toolbar__close-btn\"\n aria-label=\"Close toolbar\"\n >\n ×\n </button>\n </div>\n </div>\n\n {/* Content panel */}\n {!collapsed && (\n <div className=\"sigil-toolbar__content\">\n <TabContent tab={activeTab} />\n </div>\n )}\n\n {/* Keyboard shortcut hint */}\n {collapsed && (\n <div className=\"sigil-toolbar__shortcut-hint\">\n {config.toggleShortcut}\n </div>\n )}\n </div>\n )\n}\n\n/**\n * Floating trigger button to show toolbar when hidden\n */\nexport function DevToolbarTrigger() {\n const { visible, show } = useDevToolbar()\n const config = useDevToolbarConfig()\n\n // Only render in development\n if (process.env.NODE_ENV === 'production') {\n return null\n }\n\n if (visible) {\n return null\n }\n\n const positionClass = `sigil-toolbar-trigger--${config.position}`\n\n return (\n <button\n onClick={show}\n className={`sigil-toolbar-trigger ${positionClass}`}\n aria-label=\"Open Sigil Dev Toolbar\"\n title={`Sigil Dev Toolbar (${config.toggleShortcut})`}\n >\n <span>⚡</span>\n </button>\n )\n}\n\n/**\n * Complete toolbar with trigger\n */\nexport function DevToolbarWithTrigger() {\n return (\n <>\n <DevToolbar />\n <DevToolbarTrigger />\n <LensActiveBadge />\n </>\n )\n}\n","/**\n * Diagnostic Panel Component\n *\n * Query-first diagnostics for validating on-chain state against UI.\n * Shows verified data vs items needing user confirmation.\n */\n\nimport { useState, useCallback, useEffect } from 'react'\nimport { useDevToolbar, useDevToolbarSelector } from '../providers/DevToolbarProvider'\nimport { useIPCClient } from '../hooks/useIPCClient'\nimport { useLensAwareAccount } from '../hooks/useUserLens'\nimport type { LensContext, LensValidationIssue, Zone } from '../types'\n\n/** Diagnostic query item */\ninterface DiagnosticItem {\n id: string\n label: string\n component: string\n observedValue: string\n onChainValue?: string\n indexedValue?: string\n dataSource: 'on-chain' | 'indexed' | 'mixed' | 'unknown'\n zone: Zone\n status: 'pending' | 'verified' | 'mismatch' | 'unknown'\n}\n\n/** Diagnostic question for user */\ninterface DiagnosticQuestion {\n id: string\n question: string\n context: string\n severity: 'critical' | 'important' | 'info'\n}\n\n/**\n * Generate diagnostic questions from lens issues\n */\nfunction generateQuestions(issues: LensValidationIssue[]): DiagnosticQuestion[] {\n return issues.map((issue, index) => {\n let question: string\n let severity: DiagnosticQuestion['severity']\n\n switch (issue.type) {\n case 'data_source_mismatch':\n question = `The ${issue.component} shows \"${issue.actual}\" but on-chain value is \"${issue.expected}\". Which is correct?`\n severity = issue.severity === 'error' ? 'critical' : 'important'\n break\n case 'stale_indexed_data':\n question = `The indexer shows stale data for ${issue.component}. Expected: \"${issue.expected}\", Got: \"${issue.actual}\". Has this been recently updated?`\n severity = issue.severity === 'error' ? 'critical' : 'info'\n break\n case 'lens_financial_check':\n question = `${issue.component} uses indexed data for financial operations. Should this use on-chain data instead?`\n severity = 'critical'\n break\n case 'impersonation_leak':\n question = `${issue.component} appears to show the real address instead of the impersonated one. Is this intentional?`\n severity = 'critical'\n break\n default:\n question = issue.message\n severity = 'info'\n }\n\n return {\n id: `q-${index}`,\n question,\n context: issue.suggestion ?? '',\n severity,\n }\n })\n}\n\n/**\n * Diagnostic Panel Props\n */\nexport interface DiagnosticPanelProps {\n /** Items to diagnose */\n items?: DiagnosticItem[]\n /** Whether to auto-query on mount */\n autoQuery?: boolean\n /** Callback when diagnosis completes */\n onDiagnosisComplete?: (result: { verified: DiagnosticItem[]; issues: LensValidationIssue[] }) => void\n}\n\n/**\n * Diagnostic Panel Component\n */\nexport function DiagnosticPanel({\n items: initialItems = [],\n autoQuery = false,\n onDiagnosisComplete,\n}: DiagnosticPanelProps) {\n const [items, setItems] = useState<DiagnosticItem[]>(initialItems)\n const [questions, setQuestions] = useState<DiagnosticQuestion[]>([])\n const [isQuerying, setIsQuerying] = useState(false)\n\n const { validateLens, isLoading, error } = useIPCClient()\n const { address, isImpersonating, realAddress, impersonatedAddress } = useLensAwareAccount()\n const diagnosticsState = useDevToolbarSelector((state) => state.diagnostics)\n const { addViolation } = useDevToolbar()\n\n // Run diagnostics for all items\n const runDiagnostics = useCallback(async () => {\n if (!address) return\n\n setIsQuerying(true)\n const newIssues: LensValidationIssue[] = []\n const updatedItems = [...items]\n\n for (let i = 0; i < updatedItems.length; i++) {\n const item = updatedItems[i]\n\n // Build lens context\n const context: LensContext = {\n impersonatedAddress: isImpersonating ? (impersonatedAddress as string) : (address as string),\n realAddress: realAddress as string | undefined,\n component: item.component,\n observedValue: item.observedValue,\n onChainValue: item.onChainValue,\n indexedValue: item.indexedValue,\n dataSource: item.dataSource,\n }\n\n try {\n const result = await validateLens(context, item.zone)\n\n if (result.valid) {\n updatedItems[i] = { ...item, status: 'verified' }\n } else {\n updatedItems[i] = { ...item, status: 'mismatch' }\n newIssues.push(...result.issues)\n\n // Add violations to diagnostics state\n result.issues.forEach((issue) => {\n addViolation({\n id: `${item.id}-${issue.type}`,\n timestamp: Date.now(),\n type: 'behavioral',\n severity: issue.severity,\n message: issue.message,\n element: issue.component,\n suggestion: issue.suggestion,\n })\n })\n }\n } catch {\n updatedItems[i] = { ...item, status: 'unknown' }\n }\n }\n\n setItems(updatedItems)\n setQuestions(generateQuestions(newIssues))\n setIsQuerying(false)\n\n // Notify parent\n if (onDiagnosisComplete) {\n onDiagnosisComplete({\n verified: updatedItems.filter((i) => i.status === 'verified'),\n issues: newIssues,\n })\n }\n }, [address, items, isImpersonating, impersonatedAddress, realAddress, validateLens, addViolation, onDiagnosisComplete])\n\n // Auto-query on mount if enabled\n useEffect(() => {\n if (autoQuery && address && items.length > 0) {\n runDiagnostics()\n }\n }, [autoQuery, address]) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Split items into verified and needs attention\n const verifiedItems = items.filter((i) => i.status === 'verified')\n const attentionItems = items.filter((i) => i.status === 'mismatch' || i.status === 'unknown')\n const pendingItems = items.filter((i) => i.status === 'pending')\n\n return (\n <div className=\"sigil-diagnostic-panel\">\n {/* Header */}\n <div className=\"sigil-diagnostic-header\">\n <h3>Diagnostics</h3>\n {isImpersonating && (\n <span className=\"sigil-diagnostic-lens-badge\">\n Lens Active: {impersonatedAddress?.slice(0, 6)}...{impersonatedAddress?.slice(-4)}\n </span>\n )}\n </div>\n\n {/* Error display */}\n {error && (\n <div className=\"sigil-diagnostic-error\">\n {error}\n </div>\n )}\n\n {/* Query button */}\n <div className=\"sigil-diagnostic-actions\">\n <button\n onClick={runDiagnostics}\n disabled={isLoading || isQuerying || items.length === 0}\n className=\"sigil-diagnostic-query-btn\"\n >\n {isQuerying ? 'Querying...' : 'Run Diagnostics'}\n </button>\n </div>\n\n {/* Verified Section */}\n {verifiedItems.length > 0 && (\n <div className=\"sigil-diagnostic-section sigil-diagnostic-verified\">\n <h4>✓ Verified ({verifiedItems.length})</h4>\n <ul>\n {verifiedItems.map((item) => (\n <li key={item.id} className=\"sigil-diagnostic-item verified\">\n <span className=\"sigil-diagnostic-label\">{item.label}</span>\n <span className=\"sigil-diagnostic-value\">{item.observedValue}</span>\n <span className=\"sigil-diagnostic-source\">{item.dataSource}</span>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Needs Attention Section */}\n {attentionItems.length > 0 && (\n <div className=\"sigil-diagnostic-section sigil-diagnostic-attention\">\n <h4>⚠ Needs Attention ({attentionItems.length})</h4>\n <ul>\n {attentionItems.map((item) => (\n <li key={item.id} className=\"sigil-diagnostic-item attention\">\n <span className=\"sigil-diagnostic-label\">{item.label}</span>\n <div className=\"sigil-diagnostic-comparison\">\n <span className=\"sigil-diagnostic-observed\">\n UI: {item.observedValue}\n </span>\n {item.onChainValue && (\n <span className=\"sigil-diagnostic-onchain\">\n On-chain: {item.onChainValue}\n </span>\n )}\n {item.indexedValue && (\n <span className=\"sigil-diagnostic-indexed\">\n Indexed: {item.indexedValue}\n </span>\n )}\n </div>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Pending Section */}\n {pendingItems.length > 0 && (\n <div className=\"sigil-diagnostic-section sigil-diagnostic-pending\">\n <h4>○ Pending ({pendingItems.length})</h4>\n <ul>\n {pendingItems.map((item) => (\n <li key={item.id} className=\"sigil-diagnostic-item pending\">\n <span className=\"sigil-diagnostic-label\">{item.label}</span>\n <span className=\"sigil-diagnostic-value\">{item.observedValue}</span>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Diagnostic Questions */}\n {questions.length > 0 && (\n <div className=\"sigil-diagnostic-section sigil-diagnostic-questions\">\n <h4>Questions for User</h4>\n <ul>\n {questions.map((q) => (\n <li key={q.id} className={`sigil-diagnostic-question ${q.severity}`}>\n <span className=\"sigil-diagnostic-question-text\">{q.question}</span>\n {q.context && (\n <span className=\"sigil-diagnostic-question-context\">\n Suggestion: {q.context}\n </span>\n )}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Anchor Issues from State */}\n {diagnosticsState.violations.length > 0 && (\n <div className=\"sigil-diagnostic-section sigil-diagnostic-violations\">\n <h4>Recent Violations ({diagnosticsState.violations.length})</h4>\n <ul>\n {diagnosticsState.violations.slice(0, 5).map((v) => (\n <li key={v.id} className={`sigil-diagnostic-violation ${v.severity}`}>\n <span className=\"sigil-diagnostic-violation-msg\">{v.message}</span>\n {v.suggestion && (\n <span className=\"sigil-diagnostic-violation-suggestion\">\n → {v.suggestion}\n </span>\n )}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Empty State */}\n {items.length === 0 && (\n <div className=\"sigil-diagnostic-empty\">\n <p>No items to diagnose.</p>\n <p>Add diagnostic items to validate on-chain state.</p>\n </div>\n )}\n </div>\n )\n}\n\n/**\n * Hook for managing diagnostic items\n */\nexport function useDiagnosticItems() {\n const [items, setItems] = useState<DiagnosticItem[]>([])\n\n const addItem = useCallback((item: Omit<DiagnosticItem, 'id' | 'status'>) => {\n setItems((prev) => [\n ...prev,\n {\n ...item,\n id: `diag-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\n status: 'pending',\n },\n ])\n }, [])\n\n const removeItem = useCallback((id: string) => {\n setItems((prev) => prev.filter((i) => i.id !== id))\n }, [])\n\n const clearItems = useCallback(() => {\n setItems([])\n }, [])\n\n const updateItem = useCallback((id: string, updates: Partial<DiagnosticItem>) => {\n setItems((prev) =>\n prev.map((i) => (i.id === id ? { ...i, ...updates } : i))\n )\n }, [])\n\n return {\n items,\n addItem,\n removeItem,\n clearItems,\n updateItem,\n }\n}\n","/**\n * Simulation Panel Component\n *\n * Displays transaction simulation results in the dev toolbar.\n * Shows success/failure, gas estimates, balance deltas, and event logs.\n */\n\nimport { useState, useCallback } from 'react'\nimport type { Address, Hex } from 'viem'\nimport type {\n SimulationResult,\n SimulationTransactionRequest,\n BalanceChange,\n SimulationLog,\n} from '../services/simulation'\n\n/**\n * Format wei to human-readable ETH\n */\nfunction formatEther(wei: bigint, decimals = 4): string {\n const ethString = (Number(wei) / 1e18).toFixed(decimals)\n return `${ethString} ETH`\n}\n\n/**\n * Format gas to human-readable string\n */\nfunction formatGas(gas: bigint): string {\n if (gas >= 1_000_000n) {\n return `${(Number(gas) / 1_000_000).toFixed(2)}M`\n }\n if (gas >= 1_000n) {\n return `${(Number(gas) / 1_000).toFixed(1)}K`\n }\n return gas.toString()\n}\n\n/**\n * Truncate address for display\n */\nfunction truncateAddress(address: string): string {\n return `${address.slice(0, 6)}...${address.slice(-4)}`\n}\n\n/**\n * Format balance change\n */\nfunction formatBalanceChange(change: BalanceChange): string {\n const sign = change.delta >= 0n ? '+' : ''\n return `${sign}${formatEther(change.delta)}`\n}\n\n/**\n * Estimate USD value (placeholder - would use price feed in production)\n */\nfunction estimateUSD(wei: bigint, ethPrice = 2000): string {\n const eth = Number(wei) / 1e18\n const usd = eth * ethPrice\n return `~$${usd.toFixed(2)}`\n}\n\n/**\n * Simulation Panel Props\n */\nexport interface SimulationPanelProps {\n /** Function to run simulation */\n onSimulate?: (tx: SimulationTransactionRequest) => Promise<SimulationResult>\n /** Latest simulation result */\n result?: SimulationResult | null\n /** Whether simulation is in progress */\n isSimulating?: boolean\n /** Error message if simulation failed */\n error?: string | null\n /** ETH price for USD estimates (optional) */\n ethPrice?: number\n /** Whether to show detailed state changes */\n showStateChanges?: boolean\n /** Whether to show decoded logs (requires ABI) */\n showDecodedLogs?: boolean\n}\n\n/**\n * Balance Changes Section\n */\nfunction BalanceChangesSection({ changes }: { changes: BalanceChange[] }) {\n if (changes.length === 0) return null\n\n return (\n <div className=\"sigil-simulation-section sigil-simulation-balances\">\n <h4>Balance Changes</h4>\n <ul>\n {changes.map((change, i) => (\n <li key={i} className=\"sigil-simulation-balance-item\">\n <span className=\"sigil-simulation-address\" title={change.address}>\n {truncateAddress(change.address)}\n </span>\n <span className={`sigil-simulation-delta ${change.delta >= 0n ? 'positive' : 'negative'}`}>\n {formatBalanceChange(change)}\n </span>\n <span className=\"sigil-simulation-token\">\n {change.symbol ?? (change.token ? truncateAddress(change.token) : 'ETH')}\n </span>\n </li>\n ))}\n </ul>\n </div>\n )\n}\n\n/**\n * Event Logs Section\n */\nfunction EventLogsSection({ logs, showDecoded }: { logs: SimulationLog[]; showDecoded: boolean }) {\n if (logs.length === 0) return null\n\n return (\n <div className=\"sigil-simulation-section sigil-simulation-logs\">\n <h4>Event Logs ({logs.length})</h4>\n <ul>\n {logs.slice(0, 10).map((log, i) => (\n <li key={i} className=\"sigil-simulation-log-item\">\n <span className=\"sigil-simulation-address\" title={log.address}>\n {truncateAddress(log.address)}\n </span>\n {showDecoded && log.eventName ? (\n <span className=\"sigil-simulation-event-name\">\n {log.eventName}\n </span>\n ) : (\n <span className=\"sigil-simulation-topic\" title={log.topics[0]}>\n {log.topics[0]?.slice(0, 10)}...\n </span>\n )}\n </li>\n ))}\n {logs.length > 10 && (\n <li className=\"sigil-simulation-more\">\n +{logs.length - 10} more events\n </li>\n )}\n </ul>\n </div>\n )\n}\n\n/**\n * Gas Summary Section\n */\nfunction GasSummarySection({\n result,\n ethPrice,\n}: {\n result: SimulationResult\n ethPrice: number\n}) {\n return (\n <div className=\"sigil-simulation-section sigil-simulation-gas\">\n <h4>Gas</h4>\n <div className=\"sigil-simulation-gas-grid\">\n <div className=\"sigil-simulation-gas-item\">\n <span className=\"sigil-simulation-label\">Used</span>\n <span className=\"sigil-simulation-value\">{formatGas(result.gasUsed)}</span>\n </div>\n <div className=\"sigil-simulation-gas-item\">\n <span className=\"sigil-simulation-label\">Limit</span>\n <span className=\"sigil-simulation-value\">{formatGas(result.gasLimit)}</span>\n </div>\n <div className=\"sigil-simulation-gas-item\">\n <span className=\"sigil-simulation-label\">Price</span>\n <span className=\"sigil-simulation-value\">\n {(Number(result.effectiveGasPrice) / 1e9).toFixed(2)} gwei\n </span>\n </div>\n <div className=\"sigil-simulation-gas-item sigil-simulation-gas-total\">\n <span className=\"sigil-simulation-label\">Total Cost</span>\n <span className=\"sigil-simulation-value\">\n {formatEther(result.totalCost)}\n <span className=\"sigil-simulation-usd\">\n {estimateUSD(result.totalCost, ethPrice)}\n </span>\n </span>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * Simulation Result Display\n */\nfunction SimulationResultDisplay({\n result,\n ethPrice,\n showDecodedLogs,\n}: {\n result: SimulationResult\n ethPrice: number\n showDecodedLogs: boolean\n}) {\n return (\n <div className={`sigil-simulation-result ${result.success ? 'success' : 'failure'}`}>\n {/* Status Banner */}\n <div className=\"sigil-simulation-status\">\n <span className=\"sigil-simulation-status-icon\">\n {result.success ? '✓' : '✗'}\n </span>\n <span className=\"sigil-simulation-status-text\">\n {result.success ? 'Transaction Successful' : 'Transaction Failed'}\n </span>\n </div>\n\n {/* Revert Reason (if failed) */}\n {!result.success && result.revertReason && (\n <div className=\"sigil-simulation-revert\">\n <h4>Revert Reason</h4>\n <pre className=\"sigil-simulation-revert-message\">\n {result.revertReason}\n </pre>\n </div>\n )}\n\n {/* Gas Summary */}\n <GasSummarySection result={result} ethPrice={ethPrice} />\n\n {/* Balance Changes */}\n <BalanceChangesSection changes={result.balanceChanges} />\n\n {/* Event Logs */}\n <EventLogsSection logs={result.logs} showDecoded={showDecodedLogs} />\n\n {/* Metadata */}\n <div className=\"sigil-simulation-section sigil-simulation-meta\">\n <span className=\"sigil-simulation-block\">\n Block: {result.blockNumber.toString()}\n </span>\n <span className=\"sigil-simulation-time\">\n {new Date(result.timestamp).toLocaleTimeString()}\n </span>\n </div>\n </div>\n )\n}\n\n/**\n * Transaction Input Form\n */\nfunction TransactionInputForm({\n onSimulate,\n isSimulating,\n}: {\n onSimulate: (tx: SimulationTransactionRequest) => void\n isSimulating: boolean\n}) {\n const [from, setFrom] = useState('')\n const [to, setTo] = useState('')\n const [value, setValue] = useState('')\n const [data, setData] = useState('')\n\n const handleSubmit = useCallback(\n (e: React.FormEvent) => {\n e.preventDefault()\n\n if (!from || !to) return\n\n const tx: SimulationTransactionRequest = {\n from: from as Address,\n to: to as Address,\n value: value ? BigInt(value) : undefined,\n data: data ? (data as Hex) : undefined,\n }\n\n onSimulate(tx)\n },\n [from, to, value, data, onSimulate]\n )\n\n return (\n <form onSubmit={handleSubmit} className=\"sigil-simulation-form\">\n <div className=\"sigil-simulation-field\">\n <label htmlFor=\"sim-from\">From</label>\n <input\n id=\"sim-from\"\n type=\"text\"\n value={from}\n onChange={(e) => setFrom(e.target.value)}\n placeholder=\"0x...\"\n disabled={isSimulating}\n />\n </div>\n\n <div className=\"sigil-simulation-field\">\n <label htmlFor=\"sim-to\">To</label>\n <input\n id=\"sim-to\"\n type=\"text\"\n value={to}\n onChange={(e) => setTo(e.target.value)}\n placeholder=\"0x...\"\n disabled={isSimulating}\n />\n </div>\n\n <div className=\"sigil-simulation-field\">\n <label htmlFor=\"sim-value\">Value (wei)</label>\n <input\n id=\"sim-value\"\n type=\"text\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n placeholder=\"0\"\n disabled={isSimulating}\n />\n </div>\n\n <div className=\"sigil-simulation-field\">\n <label htmlFor=\"sim-data\">Data</label>\n <input\n id=\"sim-data\"\n type=\"text\"\n value={data}\n onChange={(e) => setData(e.target.value)}\n placeholder=\"0x...\"\n disabled={isSimulating}\n />\n </div>\n\n <button\n type=\"submit\"\n disabled={isSimulating || !from || !to}\n className=\"sigil-simulation-submit\"\n >\n {isSimulating ? 'Simulating...' : 'Simulate'}\n </button>\n </form>\n )\n}\n\n/**\n * Simulation Panel Component\n */\nexport function SimulationPanel({\n onSimulate,\n result,\n isSimulating = false,\n error,\n ethPrice = 2000,\n showDecodedLogs = true,\n}: SimulationPanelProps) {\n const handleSimulate = useCallback(\n async (tx: SimulationTransactionRequest) => {\n if (onSimulate) {\n await onSimulate(tx)\n }\n },\n [onSimulate]\n )\n\n return (\n <div className=\"sigil-simulation-panel\">\n {/* Header */}\n <div className=\"sigil-simulation-header\">\n <h3>Transaction Simulation</h3>\n </div>\n\n {/* Input Form */}\n {onSimulate && (\n <TransactionInputForm\n onSimulate={handleSimulate}\n isSimulating={isSimulating}\n />\n )}\n\n {/* Error Display */}\n {error && (\n <div className=\"sigil-simulation-error\">\n {error}\n </div>\n )}\n\n {/* Loading State */}\n {isSimulating && !result && (\n <div className=\"sigil-simulation-loading\">\n <span className=\"sigil-simulation-spinner\" />\n <span>Running simulation...</span>\n </div>\n )}\n\n {/* Result Display */}\n {result && (\n <SimulationResultDisplay\n result={result}\n ethPrice={ethPrice}\n showDecodedLogs={showDecodedLogs}\n />\n )}\n\n {/* Empty State */}\n {!result && !isSimulating && !error && (\n <div className=\"sigil-simulation-empty\">\n <p>No simulation results yet.</p>\n <p>Enter transaction details above to simulate.</p>\n </div>\n )}\n </div>\n )\n}\n","/**\n * State Comparison Component\n *\n * Side-by-side comparison of app state with diff highlighting.\n * Shows data source tracing (indexed vs on-chain) and discrepancies.\n */\n\nimport { useState, useCallback, useMemo } from 'react'\n\n/**\n * Data source type\n */\nexport type DataSource = 'on-chain' | 'indexed' | 'cache' | 'local' | 'unknown'\n\n/**\n * State value with metadata\n */\nexport interface StateValue {\n /** The actual value */\n value: unknown\n /** Data source */\n source: DataSource\n /** Timestamp when value was fetched */\n fetchedAt?: number\n /** Key path in state tree */\n path: string\n}\n\n/**\n * Comparison result for a single value\n */\nexport interface ComparisonItem {\n /** Key/path of the value */\n path: string\n /** Left side value (e.g., \"before\" or \"indexed\") */\n left?: StateValue\n /** Right side value (e.g., \"after\" or \"on-chain\") */\n right?: StateValue\n /** Whether values differ */\n isDifferent: boolean\n /** Change type */\n changeType: 'added' | 'removed' | 'modified' | 'unchanged'\n}\n\n/**\n * State snapshot for comparison\n */\nexport interface StateSnapshot {\n /** Snapshot ID */\n id: string\n /** Snapshot label */\n label: string\n /** Timestamp */\n timestamp: number\n /** State values */\n values: Record<string, StateValue>\n}\n\n/**\n * Props for StateComparison component\n */\nexport interface StateComparisonProps {\n /** Left state snapshot (e.g., \"before\" or \"indexed\") */\n leftSnapshot?: StateSnapshot | null\n /** Right state snapshot (e.g., \"after\" or \"on-chain\") */\n rightSnapshot?: StateSnapshot | null\n /** Left label */\n leftLabel?: string\n /** Right label */\n rightLabel?: string\n /** Filter to show only differences */\n showOnlyDifferences?: boolean\n /** Filter by data source */\n filterSource?: DataSource | null\n /** Callback when export is requested */\n onExport?: (data: ComparisonItem[]) => void\n}\n\n/**\n * Format a value for display\n */\nfunction formatValue(value: unknown): string {\n if (value === undefined) return 'undefined'\n if (value === null) return 'null'\n if (typeof value === 'bigint') return `${value.toString()}n`\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value, null, 2)\n } catch {\n return '[Object]'\n }\n }\n return String(value)\n}\n\n/**\n * Check if two values are equal\n */\nfunction valuesEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (typeof a === 'bigint' && typeof b === 'bigint') return a === b\n if (typeof a === 'object' && typeof b === 'object') {\n try {\n return JSON.stringify(a) === JSON.stringify(b)\n } catch {\n return false\n }\n }\n return false\n}\n\n/**\n * Get source badge color\n */\nfunction getSourceColor(source: DataSource): string {\n switch (source) {\n case 'on-chain':\n return 'sigil-source-onchain'\n case 'indexed':\n return 'sigil-source-indexed'\n case 'cache':\n return 'sigil-source-cache'\n case 'local':\n return 'sigil-source-local'\n default:\n return 'sigil-source-unknown'\n }\n}\n\n/**\n * Get change type badge color\n */\nfunction getChangeColor(type: ComparisonItem['changeType']): string {\n switch (type) {\n case 'added':\n return 'sigil-change-added'\n case 'removed':\n return 'sigil-change-removed'\n case 'modified':\n return 'sigil-change-modified'\n default:\n return 'sigil-change-unchanged'\n }\n}\n\n/**\n * Comparison Item Row\n */\nfunction ComparisonRow({ item }: { item: ComparisonItem }) {\n const [expanded, setExpanded] = useState(false)\n\n const leftValue = item.left ? formatValue(item.left.value) : '—'\n const rightValue = item.right ? formatValue(item.right.value) : '—'\n const isLongValue = leftValue.length > 50 || rightValue.length > 50\n\n return (\n <div className={`sigil-comparison-row ${item.isDifferent ? 'different' : ''}`}>\n {/* Path and Change Type */}\n <div className=\"sigil-comparison-path\">\n <code>{item.path}</code>\n <span className={`sigil-comparison-badge ${getChangeColor(item.changeType)}`}>\n {item.changeType}\n </span>\n </div>\n\n {/* Values */}\n <div className=\"sigil-comparison-values\">\n {/* Left Value */}\n <div className=\"sigil-comparison-value sigil-comparison-left\">\n {item.left ? (\n <>\n <span className={`sigil-comparison-source ${getSourceColor(item.left.source)}`}>\n {item.left.source}\n </span>\n {isLongValue ? (\n <button\n className=\"sigil-comparison-expand\"\n onClick={() => setExpanded(!expanded)}\n >\n {expanded ? 'Collapse' : 'Expand'}\n </button>\n ) : (\n <code className=\"sigil-comparison-value-text\">{leftValue}</code>\n )}\n </>\n ) : (\n <span className=\"sigil-comparison-empty\">—</span>\n )}\n </div>\n\n {/* Right Value */}\n <div className=\"sigil-comparison-value sigil-comparison-right\">\n {item.right ? (\n <>\n <span className={`sigil-comparison-source ${getSourceColor(item.right.source)}`}>\n {item.right.source}\n </span>\n {isLongValue ? (\n <button\n className=\"sigil-comparison-expand\"\n onClick={() => setExpanded(!expanded)}\n >\n {expanded ? 'Collapse' : 'Expand'}\n </button>\n ) : (\n <code className=\"sigil-comparison-value-text\">{rightValue}</code>\n )}\n </>\n ) : (\n <span className=\"sigil-comparison-empty\">—</span>\n )}\n </div>\n </div>\n\n {/* Expanded Values */}\n {expanded && isLongValue && (\n <div className=\"sigil-comparison-expanded\">\n <div className=\"sigil-comparison-expanded-left\">\n <pre>{leftValue}</pre>\n </div>\n <div className=\"sigil-comparison-expanded-right\">\n <pre>{rightValue}</pre>\n </div>\n </div>\n )}\n </div>\n )\n}\n\n/**\n * State Comparison Component\n */\nexport function StateComparison({\n leftSnapshot,\n rightSnapshot,\n leftLabel = 'Before',\n rightLabel = 'After',\n showOnlyDifferences = false,\n filterSource = null,\n onExport,\n}: StateComparisonProps) {\n const [filter, setFilter] = useState('')\n const [onlyDiff, setOnlyDiff] = useState(showOnlyDifferences)\n const [sourceFilter, setSourceFilter] = useState<DataSource | null>(filterSource)\n\n // Compute comparison items\n const comparisonItems = useMemo((): ComparisonItem[] => {\n const items: ComparisonItem[] = []\n const allPaths = new Set<string>()\n\n // Collect all paths from both snapshots\n if (leftSnapshot) {\n Object.keys(leftSnapshot.values).forEach(path => allPaths.add(path))\n }\n if (rightSnapshot) {\n Object.keys(rightSnapshot.values).forEach(path => allPaths.add(path))\n }\n\n // Create comparison items\n for (const path of allPaths) {\n const left = leftSnapshot?.values[path]\n const right = rightSnapshot?.values[path]\n\n let changeType: ComparisonItem['changeType'] = 'unchanged'\n let isDifferent = false\n\n if (left && !right) {\n changeType = 'removed'\n isDifferent = true\n } else if (!left && right) {\n changeType = 'added'\n isDifferent = true\n } else if (left && right && !valuesEqual(left.value, right.value)) {\n changeType = 'modified'\n isDifferent = true\n }\n\n items.push({\n path,\n left,\n right,\n isDifferent,\n changeType,\n })\n }\n\n // Sort by path\n items.sort((a, b) => a.path.localeCompare(b.path))\n\n return items\n }, [leftSnapshot, rightSnapshot])\n\n // Filter items\n const filteredItems = useMemo(() => {\n return comparisonItems.filter(item => {\n // Text filter\n if (filter && !item.path.toLowerCase().includes(filter.toLowerCase())) {\n return false\n }\n\n // Only differences\n if (onlyDiff && !item.isDifferent) {\n return false\n }\n\n // Source filter\n if (sourceFilter) {\n const leftMatch = item.left?.source === sourceFilter\n const rightMatch = item.right?.source === sourceFilter\n if (!leftMatch && !rightMatch) {\n return false\n }\n }\n\n return true\n })\n }, [comparisonItems, filter, onlyDiff, sourceFilter])\n\n // Statistics\n const stats = useMemo(() => {\n const added = comparisonItems.filter(i => i.changeType === 'added').length\n const removed = comparisonItems.filter(i => i.changeType === 'removed').length\n const modified = comparisonItems.filter(i => i.changeType === 'modified').length\n const unchanged = comparisonItems.filter(i => i.changeType === 'unchanged').length\n return { added, removed, modified, unchanged, total: comparisonItems.length }\n }, [comparisonItems])\n\n // Export handler\n const handleExport = useCallback(() => {\n if (onExport) {\n onExport(filteredItems)\n } else {\n // Default: download as JSON\n const blob = new Blob([JSON.stringify(filteredItems, null, 2)], {\n type: 'application/json',\n })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `state-comparison-${Date.now()}.json`\n a.click()\n URL.revokeObjectURL(url)\n }\n }, [filteredItems, onExport])\n\n return (\n <div className=\"sigil-state-comparison\">\n {/* Header */}\n <div className=\"sigil-comparison-header\">\n <h3>State Comparison</h3>\n <div className=\"sigil-comparison-stats\">\n <span className=\"sigil-stat sigil-stat-added\">+{stats.added}</span>\n <span className=\"sigil-stat sigil-stat-removed\">-{stats.removed}</span>\n <span className=\"sigil-stat sigil-stat-modified\">~{stats.modified}</span>\n <span className=\"sigil-stat sigil-stat-unchanged\">={stats.unchanged}</span>\n </div>\n </div>\n\n {/* Snapshot Info */}\n <div className=\"sigil-comparison-snapshots\">\n <div className=\"sigil-comparison-snapshot-left\">\n <span className=\"sigil-comparison-label\">{leftLabel}</span>\n {leftSnapshot && (\n <span className=\"sigil-comparison-time\">\n {new Date(leftSnapshot.timestamp).toLocaleTimeString()}\n </span>\n )}\n </div>\n <div className=\"sigil-comparison-snapshot-right\">\n <span className=\"sigil-comparison-label\">{rightLabel}</span>\n {rightSnapshot && (\n <span className=\"sigil-comparison-time\">\n {new Date(rightSnapshot.timestamp).toLocaleTimeString()}\n </span>\n )}\n </div>\n </div>\n\n {/* Filters */}\n <div className=\"sigil-comparison-filters\">\n <input\n type=\"text\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n placeholder=\"Filter by path...\"\n className=\"sigil-comparison-filter-input\"\n />\n\n <label className=\"sigil-comparison-filter-checkbox\">\n <input\n type=\"checkbox\"\n checked={onlyDiff}\n onChange={(e) => setOnlyDiff(e.target.checked)}\n />\n Only differences\n </label>\n\n <select\n value={sourceFilter ?? ''}\n onChange={(e) => setSourceFilter(e.target.value as DataSource || null)}\n className=\"sigil-comparison-filter-select\"\n >\n <option value=\"\">All sources</option>\n <option value=\"on-chain\">On-chain</option>\n <option value=\"indexed\">Indexed</option>\n <option value=\"cache\">Cache</option>\n <option value=\"local\">Local</option>\n </select>\n\n <button onClick={handleExport} className=\"sigil-comparison-export\">\n Export JSON\n </button>\n </div>\n\n {/* Comparison Items */}\n <div className=\"sigil-comparison-items\">\n {filteredItems.length === 0 ? (\n <div className=\"sigil-comparison-empty-state\">\n {comparisonItems.length === 0\n ? 'No state to compare. Capture snapshots first.'\n : 'No items match the current filters.'}\n </div>\n ) : (\n filteredItems.map((item) => (\n <ComparisonRow key={item.path} item={item} />\n ))\n )}\n </div>\n </div>\n )\n}\n\n/**\n * Hook for managing state snapshots\n */\nexport function useStateSnapshots() {\n const [snapshots, setSnapshots] = useState<StateSnapshot[]>([])\n const [leftId, setLeftId] = useState<string | null>(null)\n const [rightId, setRightId] = useState<string | null>(null)\n\n const captureSnapshot = useCallback((label: string, values: Record<string, StateValue>): StateSnapshot => {\n const snapshot: StateSnapshot = {\n id: `snap-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\n label,\n timestamp: Date.now(),\n values,\n }\n\n setSnapshots(prev => [...prev, snapshot])\n return snapshot\n }, [])\n\n const deleteSnapshot = useCallback((id: string) => {\n setSnapshots(prev => prev.filter(s => s.id !== id))\n if (leftId === id) setLeftId(null)\n if (rightId === id) setRightId(null)\n }, [leftId, rightId])\n\n const clearSnapshots = useCallback(() => {\n setSnapshots([])\n setLeftId(null)\n setRightId(null)\n }, [])\n\n const leftSnapshot = snapshots.find(s => s.id === leftId) ?? null\n const rightSnapshot = snapshots.find(s => s.id === rightId) ?? null\n\n return {\n snapshots,\n leftSnapshot,\n rightSnapshot,\n leftId,\n rightId,\n setLeftId,\n setRightId,\n captureSnapshot,\n deleteSnapshot,\n clearSnapshots,\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@thehoneyjar/sigil-dev-toolbar",
3
+ "version": "0.1.0",
4
+ "description": "Development toolbar for Sigil with User Lens, simulation, and diagnostics",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./styles.css": "./dist/styles.css"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "peerDependencies": {
21
+ "react": "^18.0.0",
22
+ "react-dom": "^18.0.0",
23
+ "viem": "^2.0.0",
24
+ "wagmi": "^2.0.0"
25
+ },
26
+ "dependencies": {
27
+ "zustand": "^4.4.7"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^20.11.0",
31
+ "@types/react": "^18.2.45",
32
+ "@types/react-dom": "^18.2.18",
33
+ "react": "^18.2.0",
34
+ "react-dom": "^18.2.0",
35
+ "tsup": "^8.0.1",
36
+ "typescript": "^5.3.3",
37
+ "viem": "^2.0.0",
38
+ "wagmi": "^2.0.0"
39
+ },
40
+ "keywords": [
41
+ "sigil",
42
+ "dev-toolbar",
43
+ "web3",
44
+ "wagmi",
45
+ "user-lens",
46
+ "impersonation"
47
+ ],
48
+ "author": "Sigil Framework",
49
+ "license": "MIT",
50
+ "publishConfig": {
51
+ "access": "public",
52
+ "registry": "https://registry.npmjs.org/"
53
+ },
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "https://github.com/0xHoneyJar/sigil.git",
57
+ "directory": "packages/sigil-dev-toolbar"
58
+ },
59
+ "bugs": {
60
+ "url": "https://github.com/0xHoneyJar/sigil/issues"
61
+ },
62
+ "homepage": "https://github.com/0xHoneyJar/sigil/tree/main/packages/sigil-dev-toolbar#readme",
63
+ "engines": {
64
+ "node": ">=20.0.0"
65
+ },
66
+ "scripts": {
67
+ "dev": "tsup --watch",
68
+ "build": "tsup",
69
+ "type-check": "tsc --noEmit",
70
+ "lint": "eslint src --ext .ts,.tsx"
71
+ }
72
+ }