@openzeppelin/ui-renderer 1.0.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,"file":"index.cjs","names":["User","Key","AddressDisplay","User","Shield","Users","Key","DialogTrigger","AlertCircle","Info","Settings","Shield","RelayerDetailsCard","Network","EmptyState","AlertTriangle","Dialog","DialogContent","DialogHeader","DialogTitle","AlertCircle","DialogDescription","PasswordField","Alert","AlertDescription","LoadingButton","TextField","NumberField","BigIntField","AddressField","BooleanField","RadioField","SelectField","SelectGroupedField","TextAreaField","BytesField","CodeEditorField","React","PasswordField","AmountField","ArrayField","ObjectField","ArrayObjectField","MapField","UrlField","EnumField","FileUploadField","ExternalLinkIcon","Loader2","CheckCircle","AlertCircle","Alert","AlertTitle","AlertDescription","FormProvider","AlertCircle","userRpcConfigService","Button","RefreshCw","Card","CardHeader","CardTitle","Button","Minimize2","CardContent","Loader2","FileText","NetworkStatusBadge","ViewContractStateButton","userNetworkServiceConfigService","Alert","Info","AlertTitle","AlertDescription","AlertTriangle","Accordion","AccordionItem","AccordionTrigger","AccordionContent","CheckCircle2","XCircle","Button","Loader2","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Tabs","TabsList","TabsTrigger","TabsContent","appConfigService","WalletConnectionUI","Button","Settings"],"sources":["../src/components/ExecutionConfigDisplay/components/EoaConfigDetails.tsx","../src/components/ExecutionConfigDisplay/components/ExecutionMethodTrigger.tsx","../src/components/ExecutionConfigDisplay/components/ExecutionConfigCard.tsx","../src/components/ExecutionConfigDisplay/components/RelayerConfigDetails.tsx","../src/components/ExecutionConfigDisplay/hooks/useExecutionValidation.ts","../src/components/ExecutionConfigDisplay/ExecutionConfigDisplay.tsx","../src/components/transaction/TransactionExecuteButton.tsx","../src/utils/formUtils.ts","../src/utils/runtimeSecretExtractor.ts","../src/components/fieldRegistry.ts","../src/components/DynamicFormField.tsx","../src/components/transaction/TransactionHashDisplay.tsx","../src/components/transaction/TransactionStatusDisplay.tsx","../src/components/TransactionForm.tsx","../src/components/ContractStateWidget/components/FunctionResult.tsx","../src/components/ContractStateWidget/components/ViewFunctionsPanel.tsx","../src/components/ContractStateWidget/ContractStateWidget.tsx","../src/components/ContractActionBar/ContractActionBar.tsx","../src/components/network/NetworkServiceSettingsPanel.tsx","../src/components/network/NetworkSettingsDialog.tsx","../src/components/WalletConnectionWithSettings.tsx"],"sourcesContent":["import { Key, User } from 'lucide-react';\nimport React from 'react';\n\nimport { AddressDisplay } from '@openzeppelin/ui-components';\nimport type { EoaExecutionConfig } from '@openzeppelin/ui-types';\n\ninterface EoaConfigDetailsProps {\n config: EoaExecutionConfig;\n}\n\nexport const EoaConfigDetails: React.FC<EoaConfigDetailsProps> = ({ config }) => (\n <div className=\"space-y-4\">\n <div className=\"flex items-start space-x-3 p-3 bg-slate-50 rounded-md\">\n <User className=\"size-5 text-primary mt-0.5 flex-shrink-0\" />\n <div>\n <h4 className=\"text-sm font-medium mb-1\">Externally Owned Account (EOA)</h4>\n <p className=\"text-sm text-muted-foreground\">\n Transaction will be executed directly from the connected wallet.\n </p>\n </div>\n </div>\n\n <div className=\"flex items-start space-x-3 p-3 bg-slate-50 rounded-md\">\n <Key className=\"size-5 text-primary mt-0.5 flex-shrink-0\" />\n <div>\n <h4 className=\"text-sm font-medium mb-1\">Execution Restrictions</h4>\n <p className=\"text-sm text-muted-foreground\">\n {config.allowAny\n ? 'Any connected wallet can try to execute this transaction.'\n : config.specificAddress\n ? 'Only this address can try to execute this transaction:'\n : 'No specific address restrictions defined.'}\n </p>\n {config.specificAddress && !config.allowAny && (\n <AddressDisplay className=\"mt-2\" address={config.specificAddress} />\n )}\n </div>\n </div>\n </div>\n);\n","import { AlertCircle, Info, Key, Shield, User, Users } from 'lucide-react';\nimport React from 'react';\n\nimport { DialogTrigger } from '@openzeppelin/ui-components';\nimport type { ExecutionConfig } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\ninterface ExecutionMethodTriggerProps {\n executionConfig: ExecutionConfig;\n isValid: boolean;\n error?: string;\n className?: string;\n}\n\nexport const ExecutionMethodTrigger: React.FC<ExecutionMethodTriggerProps> = ({\n executionConfig,\n isValid,\n error,\n className,\n}) => {\n // Get the appropriate icon for the execution method\n const getMethodIcon = (method: string): React.ReactNode => {\n // Determine icon color based on validation state\n const iconColorClass = !isValid ? 'text-red-500' : 'text-primary';\n\n switch (method) {\n case 'eoa':\n return <User className={`size-3.5 ${iconColorClass}`} />;\n case 'relayer':\n return <Shield className={`size-3.5 ${iconColorClass}`} />;\n case 'multisig':\n return <Users className={`size-3.5 ${iconColorClass}`} />;\n default:\n return <Key className={`size-3.5 ${!isValid ? 'text-red-500' : 'text-muted'}`} />;\n }\n };\n\n return (\n <DialogTrigger\n className={cn(\n 'inline-flex items-center gap-2 px-3 py-2 text-xs rounded-md border group',\n 'transition-all duration-200 hover:bg-accent hover:text-accent-foreground',\n !isValid\n ? 'border-red-300 bg-red-50 text-red-800 hover:bg-red-50/80'\n : 'border-slate-200 bg-white text-slate-700',\n className\n )}\n style={\n !isValid\n ? {\n animation: 'subtle-pulse-scale 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',\n }\n : undefined\n }\n >\n <div className=\"flex items-center gap-1.5\">\n {getMethodIcon(executionConfig.method)}\n <span className=\"font-semibold\">Execution:</span>\n <span className=\"uppercase\">{executionConfig.method}</span>\n </div>\n\n <div className=\"flex items-center ml-2\">\n {!isValid ? (\n <AlertCircle className=\"size-3.5 text-red-500\" />\n ) : (\n <Info className=\"size-3.5 text-muted-foreground transition-colors group-hover:text-foreground\" />\n )}\n </div>\n\n {/* Show error message on hover when invalid */}\n {!isValid && error && (\n <div className=\"sr-only group-hover:not-sr-only group-hover:absolute group-hover:top-full group-hover:left-0 group-hover:mt-1 group-hover:px-2 group-hover:py-1 group-hover:bg-red-900 group-hover:text-white group-hover:text-xs group-hover:rounded group-hover:shadow-lg group-hover:z-50 group-hover:max-w-xs\">\n {error}\n </div>\n )}\n\n {/* Custom keyframe animation */}\n <style\n dangerouslySetInnerHTML={{\n __html: `\n @keyframes subtle-pulse-scale {\n 0%, 100% {\n opacity: 0.65;\n transform: scale(1);\n }\n 50% {\n opacity: 1;\n transform: scale(1.02);\n }\n }\n `,\n }}\n />\n </DialogTrigger>\n );\n};\n","import { Settings } from 'lucide-react';\nimport React from 'react';\n\nimport type { RelayerExecutionConfig } from '@openzeppelin/ui-types';\n\ninterface ExecutionConfigCardProps {\n config: RelayerExecutionConfig;\n}\n\nexport const ExecutionConfigCard: React.FC<ExecutionConfigCardProps> = ({ config }) => {\n return (\n <div className=\"flex items-start space-x-3 p-3 bg-slate-50 rounded-md\">\n <Settings className=\"size-5 text-primary mt-0.5 flex-shrink-0\" />\n <div className=\"flex-1\">\n <h4 className=\"text-sm font-medium mb-1\">Execution Configuration</h4>\n <p className=\"text-sm text-muted-foreground mb-2\">\n Configuration parameters that will be used for transaction execution.\n </p>\n\n <div className=\"space-y-2\">\n {config.transactionOptions && Object.keys(config.transactionOptions).length > 0 && (\n <div>\n <span className=\"text-xs text-muted-foreground font-medium\">\n Transaction Options:\n </span>\n <div className=\"mt-1 bg-white border rounded p-2\">\n {Object.entries(config.transactionOptions).map(([key, value]) => (\n <div\n key={key}\n className=\"flex items-center justify-between py-1 border-b last:border-b-0\"\n >\n <span className=\"text-xs font-mono text-slate-600\">{key}:</span>\n <span className=\"text-xs font-mono bg-slate-100 px-2 py-0.5 rounded\">\n {typeof value === 'object' && value !== null\n ? JSON.stringify(value)\n : String(value)}\n </span>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {(!config.transactionOptions || Object.keys(config.transactionOptions).length === 0) && (\n <div>\n <span className=\"text-xs text-muted-foreground font-medium\">\n Transaction Options:\n </span>\n <span className=\"text-xs text-muted-foreground ml-2\">None configured</span>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n};\n","import { Network, Shield } from 'lucide-react';\nimport React from 'react';\n\nimport { RelayerDetailsCard } from '@openzeppelin/ui-components';\nimport { useWalletState } from '@openzeppelin/ui-react';\nimport type { RelayerDetailsRich, RelayerExecutionConfig } from '@openzeppelin/ui-types';\n\nimport { ExecutionConfigCard } from './ExecutionConfigCard';\n\ninterface RelayerConfigDetailsProps {\n config: RelayerExecutionConfig;\n enhancedDetails?: RelayerDetailsRich | null;\n loading?: boolean;\n}\n\nexport const RelayerConfigDetails: React.FC<RelayerConfigDetailsProps> = ({\n config,\n enhancedDetails,\n loading = false,\n}) => {\n const { relayer } = config;\n const { activeAdapter } = useWalletState();\n const labels = activeAdapter?.getUiLabels?.();\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-start space-x-3 p-3 bg-slate-50 rounded-md\">\n <Shield className=\"size-5 text-primary mt-0.5 flex-shrink-0\" />\n <div>\n <h4 className=\"text-sm font-medium mb-1\">OpenZeppelin Relayer</h4>\n <p className=\"text-sm text-muted-foreground\">\n Transaction will be sent via the selected OpenZeppelin Relayer.\n </p>\n </div>\n </div>\n\n <RelayerDetailsCard\n details={relayer}\n enhancedDetails={enhancedDetails}\n loading={loading}\n labels={labels}\n />\n\n {/* Service Information */}\n <div className=\"flex items-start space-x-3 p-3 bg-slate-50 rounded-md\">\n <Network className=\"size-5 text-primary mt-0.5 flex-shrink-0\" />\n <div>\n <h4 className=\"text-sm font-medium mb-1\">Service Endpoint</h4>\n <p className=\"text-xs text-muted-foreground font-mono break-all\">{config.serviceUrl}</p>\n </div>\n </div>\n\n {/* Execution Configuration */}\n <ExecutionConfigCard config={config} />\n </div>\n );\n};\n","import { useCallback, useEffect, useState } from 'react';\n\nimport type { ContractAdapter, ExecutionConfig } from '@openzeppelin/ui-types';\n\nexport interface ValidationResult {\n isValid: boolean;\n error?: string;\n}\n\nexport interface UseExecutionValidationProps {\n executionConfig: ExecutionConfig;\n adapter?: ContractAdapter;\n runtimeApiKey?: string;\n}\n\nexport const useExecutionValidation = ({\n executionConfig,\n adapter,\n runtimeApiKey,\n}: UseExecutionValidationProps): ValidationResult => {\n const [validationResult, setValidationResult] = useState<ValidationResult>({\n isValid: true,\n });\n\n const validateConfig = useCallback(async () => {\n if (!adapter) {\n setValidationResult({\n isValid: false,\n error: 'No adapter available for validation',\n });\n return;\n }\n\n try {\n const result = await adapter.validateExecutionConfig(executionConfig);\n\n if (result === true) {\n // Additional validation for runtime requirements\n let runtimeError: string | undefined;\n\n // Check if relayer method requires API key\n if (\n executionConfig.method === 'relayer' &&\n (!runtimeApiKey || runtimeApiKey.trim() === '')\n ) {\n runtimeError = 'Relayer API key is required for transaction execution';\n }\n\n setValidationResult({\n isValid: !runtimeError,\n error: runtimeError,\n });\n } else {\n setValidationResult({\n isValid: false,\n error: result,\n });\n }\n } catch (error) {\n setValidationResult({\n isValid: false,\n error: error instanceof Error ? error.message : 'Validation failed',\n });\n }\n }, [executionConfig, adapter, runtimeApiKey]);\n\n useEffect(() => {\n validateConfig();\n }, [validateConfig]);\n\n return validationResult;\n};\n","import { AlertCircle, AlertTriangle } from 'lucide-react';\nimport React, { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\n\nimport {\n Alert,\n AlertDescription,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n EmptyState,\n PasswordField,\n} from '@openzeppelin/ui-components';\nimport type {\n ContractAdapter,\n EoaExecutionConfig,\n ExecutionConfig,\n RelayerDetailsRich,\n RelayerExecutionConfig,\n} from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { EoaConfigDetails } from './components/EoaConfigDetails';\nimport { ExecutionMethodTrigger } from './components/ExecutionMethodTrigger';\nimport { RelayerConfigDetails } from './components/RelayerConfigDetails';\nimport { useExecutionValidation } from './hooks/useExecutionValidation';\n\ninterface ExecutionConfigDisplayProps {\n executionConfig: ExecutionConfig;\n adapter?: ContractAdapter;\n error?: string | null;\n connectedWalletAddress?: string;\n onRuntimeApiKeyChange?: (apiKey: string) => void;\n}\n\ninterface ApiKeyFormData {\n runtimeApiKey: string;\n}\n\nexport const ExecutionConfigDisplay: React.FC<ExecutionConfigDisplayProps> = ({\n executionConfig,\n adapter,\n error,\n onRuntimeApiKeyChange,\n}) => {\n // Create a local form for the API key\n const { control, watch } = useForm<ApiKeyFormData>({\n defaultValues: {\n runtimeApiKey: '',\n },\n });\n\n const runtimeApiKey = watch('runtimeApiKey');\n\n // State for dialog open/close\n const [isOpen, setIsOpen] = useState(false);\n\n // State for enhanced relayer details\n const [enhancedRelayerDetails, setEnhancedRelayerDetails] = useState<RelayerDetailsRich | null>(\n null\n );\n const [relayerDetailsLoading, setRelayerDetailsLoading] = useState(false);\n\n // Use the validation hook to determine if the execution config is valid\n const { isValid, error: validationError } = useExecutionValidation({\n executionConfig,\n adapter,\n runtimeApiKey,\n });\n\n // Notify parent component when API key changes\n useEffect(() => {\n onRuntimeApiKeyChange?.(runtimeApiKey);\n }, [runtimeApiKey, onRuntimeApiKeyChange]);\n\n // Fetch enhanced relayer details when dialog opens and it's a relayer execution\n useEffect(() => {\n if (isOpen && executionConfig.method === 'relayer' && runtimeApiKey && adapter?.getRelayer) {\n const relayerConfig = executionConfig as RelayerExecutionConfig;\n setRelayerDetailsLoading(true);\n\n adapter\n .getRelayer(relayerConfig.serviceUrl, runtimeApiKey, relayerConfig.relayer.relayerId)\n .then((details) => {\n setEnhancedRelayerDetails(details);\n })\n .catch((err) => {\n logger.error('ExecutionConfigDisplay', 'Failed to fetch enhanced relayer details:', err);\n // Keep using basic details if enhanced fetch fails\n setEnhancedRelayerDetails(null);\n })\n .finally(() => {\n setRelayerDetailsLoading(false);\n });\n }\n }, [isOpen, executionConfig, runtimeApiKey, adapter]);\n\n // Determine the content to display based on execution method\n const getExecutionContent = (): React.ReactNode => {\n switch (executionConfig.method) {\n case 'eoa':\n return <EoaConfigDetails config={executionConfig as EoaExecutionConfig} />;\n case 'relayer':\n return (\n <RelayerConfigDetails\n config={executionConfig as RelayerExecutionConfig}\n enhancedDetails={enhancedRelayerDetails}\n loading={relayerDetailsLoading}\n />\n );\n // TODO: Add cases for 'multisig' when implemented\n // case 'multisig':\n // return <MultisigConfigDetails config={executionConfig as MultisigExecutionConfig} />;\n default:\n return (\n <EmptyState\n icon={<AlertTriangle className=\"h-6 w-6 text-muted-foreground\" />}\n title=\"Unknown Execution Method\"\n description=\"The selected execution method is not recognized. Please check your configuration or contact support.\"\n size=\"small\"\n />\n );\n }\n };\n\n // Use validation error if present, otherwise use prop error\n const displayError = validationError || error || undefined;\n\n return (\n <Dialog open={isOpen} onOpenChange={setIsOpen}>\n <div className=\"flex justify-end w-full\">\n <ExecutionMethodTrigger\n executionConfig={executionConfig}\n isValid={isValid}\n error={displayError}\n />\n </div>\n\n <DialogContent className=\"sm:max-w-[550px] max-h-[90vh] flex flex-col\">\n <DialogHeader className=\"border-b pb-4 shrink-0\">\n <div className=\"flex items-start justify-between\">\n <DialogTitle className=\"flex items-center gap-2 text-xl\">\n Execution Method\n {displayError && <AlertCircle className=\"h-5 w-5 text-red-500\" />}\n </DialogTitle>\n </div>\n <DialogDescription className=\"mt-2\">\n This outlines how the transaction will be signed and submitted to the blockchain.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"overflow-y-auto grow\">\n <div className=\"p-6\">{getExecutionContent()}</div>\n\n {executionConfig.method === 'relayer' && (\n <div className=\"px-6 pb-4\">\n <PasswordField\n id=\"runtime-api-key\"\n label=\"Relayer API Key\"\n name=\"runtimeApiKey\"\n control={control}\n placeholder=\"Enter your API key\"\n validation={{ required: true }}\n helperText=\"This key is required to send the transaction and is not stored.\"\n />\n </div>\n )}\n\n {displayError && (\n <div className=\"px-6 pb-4\">\n <Alert variant=\"destructive\" className=\"p-3 border border-red-300\">\n <div className=\"flex items-start\">\n <AlertCircle className=\"h-4 w-4 mt-0.5 shrink-0\" />\n <AlertDescription className=\"pl-2 text-sm\">{displayError}</AlertDescription>\n </div>\n </Alert>\n </div>\n )}\n </div>\n </DialogContent>\n </Dialog>\n );\n};\n","import { ButtonProps, LoadingButton } from '@openzeppelin/ui-components';\nimport type { ContractFunction } from '@openzeppelin/ui-types';\n\nexport interface TransactionExecuteButtonProps {\n /**\n * Whether the wallet is connected\n */\n isWalletConnected: boolean;\n\n /**\n * Whether a transaction is currently being submitted\n */\n isSubmitting: boolean;\n\n /**\n * Whether the form is valid\n */\n isFormValid: boolean;\n\n /**\n * Button variant\n */\n variant?: ButtonProps['variant'];\n\n /**\n * Optional function details to determine if local execution is possible\n * Functions with stateMutability === 'pure' can execute locally without wallet\n */\n functionDetails?: ContractFunction;\n\n /**\n * Whether this function can execute locally without wallet connection\n * If true, the wallet connection check is bypassed\n */\n canExecuteLocally?: boolean;\n}\n\n/**\n * TransactionExecuteButton Component\n *\n * Displays a button for executing a transaction, which is disabled if the wallet is not connected,\n * the form is invalid, or a transaction is currently being submitted.\n *\n * @param props The component props\n * @returns A React component\n */\nexport function TransactionExecuteButton({\n isWalletConnected,\n isSubmitting,\n isFormValid,\n variant = 'default',\n functionDetails,\n canExecuteLocally = false,\n}: TransactionExecuteButtonProps): React.ReactElement {\n // Check if this function can execute locally (chain-agnostic check)\n // Prefer explicit prop, fallback to functionDetails if not provided\n const canExecute = canExecuteLocally || functionDetails?.stateMutability === 'pure';\n\n const buttonText = canExecute\n ? isSubmitting\n ? 'Executing...'\n : 'Execute Locally'\n : isSubmitting\n ? 'Executing...'\n : 'Execute Transaction';\n\n return (\n <LoadingButton\n type=\"submit\"\n disabled={(!isWalletConnected && !canExecute) || !isFormValid}\n loading={isSubmitting}\n variant={variant}\n size=\"lg\"\n className=\"w-full md:w-auto\"\n >\n {buttonText}\n </LoadingButton>\n );\n}\n","/**\n * Form Utilities\n *\n * Utilities for form field transformations, validation, and more.\n * These functions handle converting between UI and blockchain data formats.\n */\nimport type { ContractAdapter } from '@openzeppelin/ui-types';\nimport { FieldTransforms, FieldType, FormFieldType, FormValues } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\n/**\n * Parameter constraints for validation and default value generation\n */\nexport interface ParameterConstraints {\n required?: boolean;\n min?: number;\n max?: number;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n}\n\n/**\n * Validate a field value against validation rules\n */\nexport function validateField(\n value: unknown,\n validation?: { required?: boolean; min?: number; max?: number; pattern?: string }\n): string | null {\n if (validation?.required && (value === '' || value === null || value === undefined)) {\n return 'This field is required';\n }\n\n if (validation?.min !== undefined && typeof value === 'number' && value < validation.min) {\n return `Value must be at least ${validation.min}`;\n }\n\n if (validation?.max !== undefined && typeof value === 'number' && value > validation.max) {\n return `Value must be at most ${validation.max}`;\n }\n\n if (\n validation?.pattern !== undefined &&\n typeof value === 'string' &&\n new RegExp(validation.pattern).test(value) === false\n ) {\n return 'Value does not match the required pattern';\n }\n\n return null;\n}\n\n/**\n * Creates a transform for address fields\n *\n * @param adapter The blockchain adapter to use for validation\n * @returns Transform functions for address fields\n */\nexport function createAddressTransform(adapter: ContractAdapter): FieldTransforms<string> {\n return {\n input: (value: unknown): string => {\n if (value === null || value === undefined) return '';\n return String(value);\n },\n output: (value: unknown): string => {\n const address = String(value || '');\n if (adapter.isValidAddress?.(address)) {\n return address;\n }\n return '';\n },\n };\n}\n\n/**\n * Creates a transform for number fields\n *\n * @returns Transform functions for number fields\n */\nexport function createNumberTransform(): FieldTransforms<number> {\n return {\n input: (value: unknown): string => {\n if (value === undefined || value === null) return '';\n return String(value);\n },\n output: (value: unknown): number => {\n const num = Number(value);\n return isNaN(num) ? 0 : num;\n },\n };\n}\n\n/**\n * Creates a transform for bigint fields (large integers beyond JS Number precision)\n *\n * @returns Transform functions for bigint fields\n */\nexport function createBigIntTransform(): FieldTransforms<string> {\n return {\n input: (value: unknown): string => {\n if (value === undefined || value === null) return '';\n return String(value);\n },\n output: (value: unknown): string => {\n // Keep as string to avoid precision loss\n const str = String(value || '');\n // Return empty string if not a valid integer format\n if (str && !/^-?\\d+$/.test(str)) {\n return '';\n }\n return str;\n },\n };\n}\n\n/**\n * Creates a transform for boolean fields\n *\n * @returns Transform functions for boolean fields\n */\nexport function createBooleanTransform(): FieldTransforms<boolean> {\n return {\n input: (value: unknown): boolean => {\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') {\n return value.toLowerCase() === 'true' || value === '1';\n }\n return Boolean(value);\n },\n output: (value: unknown): boolean => {\n if (typeof value === 'string') {\n return value.toLowerCase() === 'true' || value === '1';\n }\n return Boolean(value);\n },\n };\n}\n\n/**\n * Creates a transform for complex type fields (arrays, objects, etc.)\n *\n * @returns Transform functions for complex fields\n */\nexport function createComplexTypeTransform(): FieldTransforms<unknown> {\n return {\n input: (value: unknown): string => {\n if (value === undefined || value === null) return '';\n if (typeof value === 'string') return value;\n\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return '';\n }\n },\n output: (value: unknown): unknown => {\n if (typeof value !== 'string' || !value) return null;\n\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n },\n };\n}\n\n/**\n * Creates a transform for text fields\n *\n * @returns Transform functions for text-based fields\n */\nexport function createTextTransform(): FieldTransforms<string> {\n return {\n input: (value: unknown): string => {\n if (value === null || value === undefined) return '';\n return String(value);\n },\n output: (value: unknown): string => {\n return String(value || '');\n },\n };\n}\n\n/**\n * Creates a transform function based on field type\n *\n * @param fieldType The type of field to create transforms for\n * @param adapter Optional adapter for address validation\n * @returns Transform functions for the field type\n */\n// TODO: Refine the return type of this function using conditional types\n// to provide more specific FieldTransforms<T> based on the fieldType.\n// For example, createTransformForFieldType('text') should ideally return FieldTransforms<string>.\n// Currently, it returns FieldTransforms<unknown>, which is type-safe but loses specificity.\nexport function createTransformForFieldType(\n fieldType: FieldType,\n adapter?: ContractAdapter\n): FieldTransforms<unknown> {\n switch (fieldType) {\n case 'blockchain-address':\n if (!adapter) {\n throw new Error(\n `createTransformForFieldType: Adapter is required for 'blockchain-address' field type but was not provided.`\n );\n }\n return createAddressTransform(adapter) as FieldTransforms<unknown>;\n case 'number':\n case 'amount':\n return createNumberTransform() as FieldTransforms<unknown>;\n case 'bigint':\n return createBigIntTransform() as FieldTransforms<unknown>;\n case 'checkbox':\n return createBooleanTransform() as FieldTransforms<unknown>;\n case 'text':\n case 'email':\n case 'password':\n case 'textarea':\n return createTextTransform() as FieldTransforms<unknown>;\n case 'array':\n return createArrayTransform() as FieldTransforms<unknown>;\n case 'object':\n return createObjectTransform() as FieldTransforms<unknown>;\n case 'array-object':\n return createArrayObjectTransform() as FieldTransforms<unknown>;\n case 'enum':\n // Enum fields use complex type transform for JSON serialization of enum values\n return createComplexTypeTransform() as FieldTransforms<unknown>;\n default:\n // For unhandled field types, log a warning and fallback to complex type (JSON) transform.\n // Ideally, all common ABI types should be mapped by the adapter to specific FieldTypes.\n logger.warn(\n 'formUtils',\n `createTransformForFieldType: No specific transform for fieldType \"${fieldType as string}\". Falling back to createComplexTypeTransform. Ensure adapter maps all expected ABI types to specific FieldTypes.`\n );\n return createComplexTypeTransform();\n }\n}\n\n/**\n * Generate a default value for a given field type based on parameter constraints\n */\nexport function generateDefaultValue(\n parameterType: string,\n constraints: Partial<ParameterConstraints> = {}\n): unknown {\n const type = parameterType.toLowerCase();\n\n // Basic default values based on type\n if (type.includes('bool')) {\n return false;\n } else if (type.includes('int') || type.includes('number')) {\n return constraints.min !== undefined ? constraints.min : 0;\n } else if (type.includes('string') || type.includes('address')) {\n return '';\n } else if (type.includes('array') || type.includes('[]')) {\n return [];\n } else {\n return null;\n }\n}\n\n/**\n * Returns the appropriate default value based on field type\n */\nexport function getDefaultValueByFieldType(fieldType: FieldType): string | boolean | number {\n switch (fieldType) {\n case 'checkbox':\n return false;\n case 'number':\n return '';\n default:\n return '';\n }\n}\n\n/**\n * Creates a complete default values object for form initialization\n * Ensures all fields have appropriate default values to avoid React controlled/uncontrolled input warnings\n *\n * @param fields The form field definitions\n * @param existingDefaults Any existing default values to preserve\n * @returns A complete form values object with no undefined values\n */\nexport function createDefaultFormValues(\n fields: FormFieldType[] | undefined,\n existingDefaults: Record<string, unknown> = {}\n): FormValues {\n const defaults: FormValues = { ...existingDefaults };\n\n if (!fields) {\n return defaults;\n }\n\n fields.forEach((field) => {\n // Only set default if not already set\n if (defaults[field.name] === undefined) {\n defaults[field.name] = getDefaultValueByFieldType(field.type);\n }\n });\n\n return defaults;\n}\n\n/**\n * Creates a transform for array fields\n *\n * @returns Transform functions for array fields\n */\nexport function createArrayTransform(): FieldTransforms<unknown[]> {\n return {\n input: (value: unknown[]): string => {\n // Blockchain to UI: Convert array to JSON string.\n // The type system expects `value` to be `unknown[]` here.\n // A truly empty or uninitialized array state should be represented by an empty array `[]`.\n if (!Array.isArray(value)) {\n // This case should ideally not be hit if types are followed,\n // but as a safeguard, return empty array string.\n logger.warn('formUtils', 'createArrayTransform input received non-array value:', value);\n return '[]';\n }\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n // Handle potential stringify errors (e.g., circular refs, though less likely with unknown[])\n return '[]';\n }\n },\n output: (value: unknown): unknown[] => {\n // UI to Blockchain: Convert UI string (e.g., JSON) back to array\n if (typeof value === 'string') {\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return []; // Default to empty array on parse error\n }\n }\n // If it's already an array (e.g. from direct manipulation if not using string input), pass through\n return Array.isArray(value) ? value : [];\n },\n };\n}\n\n/**\n * Creates a transform for object fields\n *\n * @returns Transform functions for object fields\n */\nexport function createObjectTransform(): FieldTransforms<Record<string, unknown>> {\n return {\n input: (value: Record<string, unknown>): string => {\n // Blockchain to UI: Convert object to JSON string for display/editing\n // The type system expects `value` to be Record<string, unknown> here.\n // An empty or uninitialized object state should be represented by an empty object `{}`.\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n // This case should ideally not be hit if types are strictly followed.\n logger.warn(\n 'formUtils',\n 'createObjectTransform input received non-object or null value:',\n value\n );\n return '{}'; // Default to empty object string\n }\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return '{}'; // Default to empty object string on error\n }\n },\n output: (value: unknown): Record<string, unknown> => {\n // UI to Blockchain: Convert UI string (e.g., JSON) back to object\n if (typeof value === 'string') {\n if (!value.trim()) return {}; // Handle empty string input from UI\n try {\n const parsed = JSON.parse(value);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed;\n }\n return {}; // Parsed but not an object\n } catch {\n return {}; // Default to empty object on parse error\n }\n }\n // If it's already an object (e.g. from direct manipulation if not using string input), pass through\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n return {};\n },\n };\n}\n\n/**\n * Creates a transform for array-object fields\n *\n * @returns Transform functions for array-object fields\n */\nexport function createArrayObjectTransform(): FieldTransforms<Record<string, unknown>[]> {\n return {\n input: (value: Record<string, unknown>[]): string => {\n // Blockchain to UI: Convert array of objects to JSON string\n if (!Array.isArray(value)) {\n // This case should ideally not be hit if types are strictly followed.\n // However, if it occurs at runtime, log a warning and return default.\n logger.warn(\n 'formUtils',\n 'createArrayObjectTransform input received non-array value:',\n value\n );\n return '[]';\n }\n try {\n // Ensure all items are actual objects before stringifying\n const validItems = value.filter(\n (item) => item && typeof item === 'object' && !Array.isArray(item)\n );\n return JSON.stringify(validItems, null, 2);\n } catch {\n return '[]'; // Default to empty array string on error\n }\n },\n output: (value: unknown): Record<string, unknown>[] => {\n // UI to Blockchain: Convert UI string (JSON) back to array of objects\n if (typeof value === 'string') {\n if (!value.trim()) return []; // Handle empty string from UI\n try {\n const parsed = JSON.parse(value);\n if (Array.isArray(parsed)) {\n return parsed.filter(\n (item): item is Record<string, unknown> =>\n item && typeof item === 'object' && !Array.isArray(item)\n );\n }\n return []; // Parsed but not an array\n } catch {\n return []; // Default to empty array on parse error\n }\n }\n // If it's already an array of objects (e.g. from direct manipulation)\n if (Array.isArray(value)) {\n return value.filter(\n (item): item is Record<string, unknown> =>\n item && typeof item === 'object' && !Array.isArray(item)\n );\n }\n return [];\n },\n };\n}\n","import type { FormFieldType, FormValues } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\n/**\n * Extracts runtime secrets from form submission data and field configuration.\n *\n * Handles two cases:\n * 1. User-provided runtime secret (field value in form data)\n * 2. Hardcoded readonly runtime secret (from field configuration)\n *\n * Returns both the extracted secrets and the cleaned contract arguments\n * (with runtimeSecret fields removed).\n *\n * @param data - Form submission data from React Hook Form\n * @param fields - Field configuration array from the schema\n * @returns Object containing extracted secrets and cleaned contract arguments\n */\nexport function extractRuntimeSecrets(\n data: FormValues,\n fields: FormFieldType[]\n): {\n runtimeSecrets: Record<string, string>;\n contractArgs: FormValues;\n} {\n const runtimeSecrets: Record<string, string> = {};\n const contractArgs = { ...data };\n\n logger.debug('TransactionForm', 'All form data values:', data);\n logger.debug(\n 'TransactionForm',\n 'Schema fields:',\n fields.map((f) => ({ name: f.name, type: f.type, readOnly: f.readOnly }))\n );\n\n // Identify and extract runtimeSecret fields\n fields.forEach((field) => {\n if (field.type === 'runtimeSecret' && field.adapterBinding?.key) {\n // Try to get value from form data first\n let secretValue = data[field.name];\n\n // If readonly and no value in form data, try to get hardcoded value from field config\n if (field.readOnly && !secretValue && 'hardcodedValue' in field) {\n secretValue = (field as unknown as { hardcodedValue?: string }).hardcodedValue;\n logger.debug(\n 'TransactionForm',\n `Using hardcoded value for readonly runtimeSecret field: ${field.name}`,\n {\n secretValue,\n }\n );\n }\n\n logger.debug('TransactionForm', `Processing runtimeSecret field: ${field.name}`, {\n secretValue,\n readOnly: field.readOnly,\n });\n\n if (secretValue) {\n runtimeSecrets[field.adapterBinding.key] = secretValue as string;\n }\n // Remove from contract args\n delete contractArgs[field.name];\n }\n });\n\n logger.debug(\n 'TransactionForm',\n 'Extracted runtime secrets:',\n Object.keys(runtimeSecrets),\n runtimeSecrets\n );\n\n return { runtimeSecrets, contractArgs };\n}\n","import React from 'react';\n\nimport {\n AddressField,\n AmountField,\n ArrayField,\n ArrayObjectField,\n BaseFieldProps,\n BigIntField,\n BooleanField,\n BytesField,\n CodeEditorField,\n EnumField,\n FileUploadField,\n MapField,\n NumberField,\n ObjectField,\n PasswordField,\n RadioField,\n SelectField,\n SelectGroupedField,\n TextAreaField,\n TextField,\n UrlField,\n} from '@openzeppelin/ui-components';\nimport type { ContractAdapter, ContractSchema } from '@openzeppelin/ui-types';\nimport { FieldType, FormValues } from '@openzeppelin/ui-types';\n\n/**\n * Registry of field components mapped to their respective types.\n * All field components in this registry are designed specifically for React Hook Form integration\n * and are meant to be used within the DynamicFormField system, not as standalone components.\n */\nexport const fieldComponents: Record<\n FieldType,\n React.ComponentType<\n BaseFieldProps<FormValues> & { adapter?: ContractAdapter; contractSchema?: ContractSchema }\n >\n> = {\n text: TextField,\n number: NumberField,\n bigint: BigIntField,\n 'blockchain-address': AddressField,\n checkbox: BooleanField,\n radio: RadioField,\n select: SelectField,\n 'select-grouped': SelectGroupedField,\n textarea: TextAreaField,\n bytes: BytesField,\n 'code-editor': CodeEditorField,\n date: () => React.createElement('div', null, 'Date field not implemented yet'),\n email: () => React.createElement('div', null, 'Email field not implemented yet'),\n password: PasswordField,\n amount: AmountField,\n array: ArrayField,\n object: ObjectField,\n 'array-object': ArrayObjectField,\n map: MapField,\n url: UrlField,\n enum: EnumField,\n hidden: () => null, // Return null for hidden type\n 'file-upload': FileUploadField,\n runtimeSecret: PasswordField,\n};\n","import React, { useCallback } from 'react';\nimport { Control, useWatch } from 'react-hook-form';\n\nimport type { ContractAdapter, ContractSchema, FunctionParameter } from '@openzeppelin/ui-types';\nimport { FieldCondition, FormFieldType, FormValues } from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { fieldComponents } from './fieldRegistry';\n\n// Import the shared registry\n\n/**\n * Props for the DynamicFormField component\n */\ninterface DynamicFormFieldProps {\n /**\n * The field configuration to render\n */\n field: FormFieldType;\n\n /**\n * The React Hook Form control\n */\n control: Control<FormValues>;\n\n /**\n * The adapter for chain-specific validation and formatting\n */\n adapter: ContractAdapter;\n\n /**\n * Optional contract schema for nested metadata lookups\n */\n contractSchema?: ContractSchema;\n\n /**\n * The field error message, if any (Kept for potential direct use, though RHF handles it)\n */\n error?: string;\n}\n\n/**\n * Evaluates whether a field should be rendered based on its visibility conditions\n */\nfunction useShouldRenderField(field: FormFieldType, control: Control<FormValues>): boolean {\n // Use React Hook Form's useWatch to get the values of form fields\n // This will reactively update when form values change\n const formValues = useWatch({ control });\n\n // If the field is explicitly hidden, don't render it\n if (field.isHidden) {\n return false;\n }\n\n // If there are no visible conditions, always render\n if (!field.visibleWhen) {\n return true;\n }\n\n // Convert single condition to array for consistent processing\n const conditions: FieldCondition[] = Array.isArray(field.visibleWhen)\n ? field.visibleWhen\n : [field.visibleWhen];\n\n // Check if all conditions are met\n return conditions.every((condition) => {\n const dependentValue = formValues[condition.field];\n\n switch (condition.operator) {\n case 'equals':\n return dependentValue === condition.value;\n case 'notEquals':\n return dependentValue !== condition.value;\n case 'contains':\n return String(dependentValue).includes(String(condition.value || ''));\n case 'greaterThan':\n return Number(dependentValue) > Number(condition.value || 0);\n case 'lessThan':\n return Number(dependentValue) < Number(condition.value || 0);\n case 'matches':\n if (typeof condition.value === 'string') {\n const regex = new RegExp(condition.value);\n return regex.test(String(dependentValue || ''));\n }\n return false;\n default:\n return true;\n }\n });\n}\n\n/**\n * Dynamic Form Field Component\n *\n * Renders the appropriate field component based on the field type defined in the form schema.\n * This component is part of the app rendering system architecture where:\n * 1. Form schemas are generated from contract functions using adapters\n * 2. The schemas are rendered using the TransactionForm component\n * 3. TransactionForm uses DynamicFormField to render appropriate field components based on the schema\n *\n * The field components (TextField, NumberField, AddressField, etc.) are specifically designed\n * for React Hook Form integration and should not be used as standalone components.\n *\n * @returns The rendered form field component or null if the field should not be visible\n */\nexport function DynamicFormField({\n field,\n control,\n adapter,\n contractSchema,\n}: DynamicFormFieldProps): React.ReactElement | null {\n // Memoized render functions to prevent unnecessary re-renders\n // These must be called before any early returns to satisfy React Hooks rules\n const renderPayloadField = useCallback(\n (payloadField: FormFieldType, payloadIndex: number): React.ReactElement => {\n let enhancedPayloadField: FormFieldType;\n\n if (payloadField.originalParameterType) {\n const generatedField = adapter.generateDefaultField(\n {\n name: payloadField.name || `payload_${payloadIndex}`,\n type: payloadField.originalParameterType,\n } as FunctionParameter,\n contractSchema\n );\n\n enhancedPayloadField = {\n ...generatedField,\n ...payloadField,\n type: generatedField.type,\n label: payloadField.label ?? generatedField.label,\n placeholder: payloadField.placeholder ?? generatedField.placeholder,\n helperText: payloadField.helperText ?? generatedField.helperText,\n };\n } else {\n enhancedPayloadField = {\n ...payloadField,\n type: payloadField.type ?? 'text',\n };\n }\n\n return (\n <DynamicFormField\n key={`${field.id}-payload-${payloadIndex}`}\n field={enhancedPayloadField}\n control={control}\n adapter={adapter}\n contractSchema={contractSchema}\n />\n );\n },\n [field.id, control, adapter, contractSchema]\n );\n\n const renderKeyField = useCallback(\n (keyField: FormFieldType, entryIndex: number): React.ReactElement => {\n // Map the key type using the adapter if originalParameterType is available\n const mappedKeyType = keyField.originalParameterType\n ? adapter.mapParameterTypeToFieldType(keyField.originalParameterType)\n : keyField.type;\n\n // Create enhanced field with proper type mapping\n const enhancedKeyField: FormFieldType = {\n ...keyField,\n type: mappedKeyType,\n // Inherit readOnly from parent field\n readOnly: keyField.readOnly ?? field.readOnly,\n };\n\n return (\n <DynamicFormField\n key={`${field.id}-key-${entryIndex}`}\n field={enhancedKeyField}\n control={control}\n adapter={adapter}\n contractSchema={contractSchema}\n />\n );\n },\n [field.id, field.readOnly, control, adapter, contractSchema]\n );\n\n const renderValueField = useCallback(\n (valueField: FormFieldType, entryIndex: number): React.ReactElement => {\n // Map the value type using the adapter if originalParameterType is available\n const mappedValueType = valueField.originalParameterType\n ? adapter.mapParameterTypeToFieldType(valueField.originalParameterType)\n : valueField.type;\n\n // Create enhanced field with proper type mapping\n const enhancedValueField: FormFieldType = {\n ...valueField,\n type: mappedValueType,\n // Inherit readOnly from parent field\n readOnly: valueField.readOnly ?? field.readOnly,\n };\n\n return (\n <DynamicFormField\n key={`${field.id}-value-${entryIndex}`}\n field={enhancedValueField}\n control={control}\n adapter={adapter}\n contractSchema={contractSchema}\n />\n );\n },\n [field.id, field.readOnly, control, adapter, contractSchema]\n );\n\n // Check if the field should be rendered based on visibility conditions\n const shouldRender = useShouldRenderField(field, control);\n if (!shouldRender) {\n return null;\n }\n\n // Get the appropriate component for this field type from the registry\n const FieldComponent = fieldComponents[field.type];\n\n // If no component is registered for this field type, log a warning and return null\n if (!FieldComponent) {\n logger.warn('DynamicFormField', `No component registered for field type: ${field.type}`);\n return null;\n }\n\n // Get field-specific props based on type\n const fieldSpecificProps = getFieldSpecificProps(\n field,\n {\n renderPayloadField,\n renderKeyField,\n renderValueField,\n },\n contractSchema\n );\n\n // Add render functions for complex fields\n const enhancedProps = {\n ...fieldSpecificProps,\n // For array fields, provide a render function for elements\n ...(field.type === 'array' && {\n renderElement: (elementField: FormFieldType, index: number): React.ReactElement => (\n <DynamicFormField\n key={`${field.id}-element-${index}`}\n field={{\n ...elementField,\n // Inherit readOnly from parent field\n readOnly: elementField.readOnly ?? field.readOnly,\n }}\n control={control}\n adapter={adapter}\n contractSchema={contractSchema}\n />\n ),\n }),\n // For object fields, provide a render function for properties\n ...(field.type === 'object' && {\n renderProperty: (propertyField: FormFieldType, propertyName: string): React.ReactElement => (\n <DynamicFormField\n key={`${field.id}-property-${propertyName}`}\n field={{\n ...propertyField,\n // Inherit readOnly from parent field\n readOnly: propertyField.readOnly ?? field.readOnly,\n }}\n control={control}\n adapter={adapter}\n contractSchema={contractSchema}\n />\n ),\n }),\n // For array-object fields, provide a render function for properties\n ...(field.type === 'array-object' && {\n renderProperty: (\n propertyField: FormFieldType,\n itemIndex: number,\n propertyName: string\n ): React.ReactElement => (\n <DynamicFormField\n key={`${field.id}-item-${itemIndex}-property-${propertyName}`}\n field={{\n ...propertyField,\n // Inherit readOnly from parent field\n readOnly: propertyField.readOnly ?? field.readOnly,\n }}\n control={control}\n adapter={adapter}\n contractSchema={contractSchema}\n />\n ),\n }),\n };\n\n // Pass all necessary props directly to the field component\n // Each specific field component knows how to handle its own props based on field type\n return (\n <FieldComponent\n id={field.id}\n label={field.label}\n placeholder={field.placeholder}\n helperText={field.helperText}\n width={field.width}\n validation={field.validation}\n control={control as unknown as Control<FormValues>}\n name={field.name}\n adapter={adapter}\n readOnly={field.readOnly}\n contractSchema={contractSchema}\n {...enhancedProps}\n />\n );\n}\n\n/**\n * Render functions for memoization\n */\ninterface RenderFunctions {\n renderPayloadField: (payloadField: FormFieldType, payloadIndex: number) => React.ReactElement;\n renderKeyField: (keyField: FormFieldType, entryIndex: number) => React.ReactElement;\n renderValueField: (valueField: FormFieldType, entryIndex: number) => React.ReactElement;\n}\n\n/**\n * Extract field-specific props based on field type\n */\nfunction getFieldSpecificProps(\n field: FormFieldType,\n renderFunctions: RenderFunctions,\n contractSchema?: ContractSchema\n): Record<string, unknown> {\n switch (field.type) {\n case 'number':\n // Extract number-specific props from validation\n return {\n min: field.validation?.min,\n max: field.validation?.max,\n step: field.options?.find((opt) => opt.label === 'step')?.value,\n };\n case 'array':\n // Extract array-specific props\n return {\n elementType: field.elementType || 'text',\n minItems: field.validation?.min,\n maxItems: field.validation?.max,\n elementFieldConfig: field.elementFieldConfig,\n };\n case 'object':\n // Extract object-specific props\n return {\n components: field.components || [],\n showCard: true,\n contractSchema,\n };\n case 'array-object':\n // Extract array-object-specific props\n const components = field.components || [];\n\n return {\n components,\n minItems: field.validation?.min,\n maxItems: field.validation?.max,\n collapsible: true,\n defaultCollapsed: false,\n };\n case 'blockchain-address':\n // Add address-specific props\n return {};\n case 'checkbox':\n // Add checkbox-specific props\n return {};\n case 'code-editor':\n // Extract code editor-specific props\n return {\n language: field.codeEditorProps?.language || 'json',\n theme: field.codeEditorProps?.theme || 'light',\n height: field.codeEditorProps?.height || '200px',\n maxHeight: field.codeEditorProps?.maxHeight || '400px',\n performanceThreshold: field.codeEditorProps?.performanceThreshold || 5000,\n };\n case 'enum':\n // Extract enum-specific props\n return {\n enumMetadata: field.enumMetadata,\n renderPayloadField: renderFunctions.renderPayloadField,\n };\n case 'select':\n // Pass options through to SelectField\n return {\n options: field.options || [],\n defaultValue: (field.defaultValue as string | undefined) || undefined,\n };\n case 'radio':\n // Pass options through to RadioField\n return {\n options: field.options || [],\n };\n case 'map':\n // Extract map-specific props using memoized render functions\n return {\n mapMetadata: field.mapMetadata,\n minItems: field.validation?.min,\n renderKeyField: renderFunctions.renderKeyField,\n renderValueField: renderFunctions.renderValueField,\n };\n default:\n return {};\n }\n}\n","import { ExternalLink as ExternalLinkIcon } from 'lucide-react';\nimport React from 'react';\n\nimport { logger } from '@openzeppelin/ui-utils';\n\ninterface TransactionHashDisplayProps {\n /**\n * The transaction hash to display\n */\n txHash: string;\n\n /**\n * Optional URL to view the transaction on a block explorer\n */\n explorerUrl: string | null;\n}\n\n/**\n * Renders a transaction hash with proper formatting and optional explorer link.\n * This component ensures transaction hashes are displayed in a consistent way\n * with proper word-breaking for long strings.\n */\nexport function TransactionHashDisplay({\n txHash,\n explorerUrl,\n}: TransactionHashDisplayProps): React.ReactElement {\n return (\n <div className=\"text-sm mt-2 relative\">\n <div className=\"text-muted-foreground text-xs mb-1\">Transaction:</div>\n\n {/* Transaction hash with monospace font */}\n <div className=\"mb-2\">\n <code className=\"font-mono text-xs bg-gray-100 px-2 py-1.5 rounded break-all inline-block\">\n {txHash}\n </code>\n </div>\n\n {/* Explorer link with improved clickability */}\n {explorerUrl && (\n <div className=\"relative z-10 pointer-events-auto\">\n <a\n href={explorerUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center text-xs text-primary hover:text-primary/80 hover:underline py-1 px-2 cursor-pointer\"\n onClick={() => {\n // Add a debug log to ensure click is working\n logger.info('TransactionHashDisplay', 'Explorer link clicked', explorerUrl);\n // Don't stop propagation - we want to bubble up\n }}\n >\n <ExternalLinkIcon size={12} className=\"mr-1 flex-shrink-0\" />\n <span>View on explorer</span>\n </a>\n </div>\n )}\n </div>\n );\n}\n","import { AlertCircle, CheckCircle, Loader2 } from 'lucide-react';\nimport React from 'react';\n\nimport { Alert, AlertDescription, AlertTitle } from '@openzeppelin/ui-components';\nimport type { ContractFunction, FullContractAdapter, TxStatus } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { TransactionHashDisplay } from './TransactionHashDisplay';\n\ninterface TransactionStatusDisplayProps {\n status: TxStatus;\n txHash: string | null;\n error: string | null;\n explorerUrl?: string | null; // URL for the transaction hash link\n className?: string; // Allow custom styling\n // Optional adapter-provided copy\n customTitle?: string;\n customMessage?: string;\n // Optional execution result and adapter for formatting\n result?: unknown;\n functionDetails?: ContractFunction;\n adapter?: FullContractAdapter;\n}\n\n/**\n * Helper function to format error messages that contain transaction hashes\n * This adds proper word breaking for transaction hashes while maintaining readability\n */\nfunction formatErrorWithHash(errorMsg: string): React.ReactNode {\n if (!errorMsg) return 'An unknown error occurred.';\n\n // Check if the error message contains a transaction hash (0x followed by hex characters)\n const hashRegex = /(0x[a-fA-F0-9]{40,})/g;\n\n if (!hashRegex.test(errorMsg)) {\n return <span className=\"break-word\">{errorMsg}</span>;\n }\n\n // If we found a hash, format it for better display\n const parts = errorMsg.split(hashRegex);\n\n return (\n <span className=\"break-word\">\n {parts.map((part, i) => {\n if (part.match(/^0x[a-fA-F0-9]{40,}$/)) {\n // This part is a hash, format it specially\n return (\n <code key={i} className=\"font-mono px-1 py-0.5 bg-gray-100 rounded text-xs break-all\">\n {part}\n </code>\n );\n }\n return part;\n })}\n </span>\n );\n}\n\n/** Displays the current status of a transaction with appropriate icons and messages. */\nexport function TransactionStatusDisplay({\n status,\n txHash,\n error,\n explorerUrl,\n className,\n customTitle,\n customMessage,\n result,\n functionDetails,\n adapter,\n}: TransactionStatusDisplayProps): React.ReactElement | null {\n if (status === 'idle') {\n return null;\n }\n\n let variant: 'default' | 'destructive' | 'success' = 'default';\n let defaultTitle = '';\n let defaultMessage: string | null = null;\n let icon: React.ReactNode = null;\n\n if (status === 'pendingSignature') {\n defaultTitle = 'Pending Signature';\n icon = <Loader2 className=\"size-5 animate-spin text-primary\" />;\n // Default copy covers both signature and auto-confirmation in one message (chain-agnostic).\n defaultMessage =\n 'Please check your wallet to sign. After signing, your transaction will be submitted and confirmed automatically.';\n variant = 'default';\n } else if (status === 'pendingConfirmation') {\n defaultTitle = 'Processing Transaction';\n icon = <Loader2 className=\"size-5 animate-spin text-primary\" />;\n defaultMessage = 'Waiting for the transaction to be confirmed on the blockchain...';\n variant = 'default';\n } else if (status === 'pendingRelayer') {\n defaultTitle = 'Waiting for Relayer';\n icon = <Loader2 className=\"size-5 animate-spin text-primary\" />;\n defaultMessage = 'The transaction is pending with the relayer and will be submitted shortly.';\n variant = 'default';\n } else if (status === 'success') {\n defaultTitle = 'Transaction Successful';\n icon = <CheckCircle className=\"size-5 text-green-600\" />;\n defaultMessage = 'Your transaction has been confirmed.';\n variant = 'success';\n } else if (status === 'error') {\n defaultTitle = 'Transaction Failed';\n icon = <AlertCircle className=\"size-5 text-destructive\" />;\n variant = 'destructive';\n }\n\n const title = customTitle || defaultTitle;\n\n // Format result if available (chain-agnostic, adapter-led formatting)\n let formattedResult: string | null = null;\n if (result !== undefined && result !== null && adapter && functionDetails) {\n try {\n formattedResult = adapter.formatFunctionResult(result, functionDetails);\n } catch {\n // Fallback to JSON.stringify if formatting fails\n formattedResult = JSON.stringify(result, null, 2);\n }\n } else if (result !== undefined && result !== null) {\n // Fallback formatting when adapter/functionDetails not available\n formattedResult = JSON.stringify(result, null, 2);\n }\n\n let content: React.ReactNode = null;\n if (status === 'error') {\n content = (\n <div>\n {error ? (\n formatErrorWithHash(error)\n ) : customMessage ? (\n <span className=\"break-word\">{customMessage}</span>\n ) : (\n <span className=\"break-word\">An unknown error occurred.</span>\n )}\n {txHash && <TransactionHashDisplay txHash={txHash} explorerUrl={explorerUrl || null} />}\n </div>\n );\n } else {\n const messageText = customMessage || defaultMessage || '';\n content = (\n <div className=\"space-y-3\">\n {messageText && <p>{messageText}</p>}\n {txHash && <TransactionHashDisplay txHash={txHash} explorerUrl={explorerUrl || null} />}\n {formattedResult && (\n <div className=\"mt-3 pt-3 border-t border-border\">\n <p className=\"text-sm font-medium mb-2\">Result:</p>\n <pre className=\"text-xs bg-muted p-3 rounded-md overflow-auto max-h-48\">\n {formattedResult}\n </pre>\n </div>\n )}\n </div>\n );\n }\n\n return (\n <Alert variant={variant} className={cn('relative py-4 px-5 overflow-hidden', className)}>\n <div className=\"flex items-start\">\n <div className=\"shrink-0 mr-3 mt-0.5\">{icon}</div>\n <div className=\"flex-1 min-w-0\">\n <AlertTitle className=\"mb-1 text-base font-medium\">{title}</AlertTitle>\n <AlertDescription className=\"text-sm overflow-hidden\">{content}</AlertDescription>\n </div>\n </div>\n </Alert>\n );\n}\n","import { AlertCircle } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { FormProvider, useForm } from 'react-hook-form';\n\nimport type {\n FormValues,\n TransactionFormProps,\n TransactionStatusUpdate,\n TxStatus,\n} from '@openzeppelin/ui-types';\nimport { logger } from '@openzeppelin/ui-utils';\n\nimport { ExecutionConfigDisplay } from './ExecutionConfigDisplay/ExecutionConfigDisplay';\nimport { TransactionExecuteButton } from './transaction/TransactionExecuteButton';\n\nimport { createDefaultFormValues } from '../utils/formUtils';\nimport { extractRuntimeSecrets } from '../utils/runtimeSecretExtractor';\nimport { DynamicFormField } from './DynamicFormField';\nimport { TransactionStatusDisplay } from './transaction';\n\n/**\n * Transaction states that should disable the form (pending operations)\n */\nconst PENDING_STATES: TxStatus[] = ['pendingSignature', 'pendingConfirmation', 'pendingRelayer'];\n\n/**\n * Transaction Form Component\n *\n * This is the main entry point for the app rendering system. It represents the top level of\n * the app rendering architecture:\n *\n * 1. TransactionForm receives a schema and adapter from the transaction builder app\n * 2. It sets up React Hook Form for state management and validation\n * 3. It renders fields dynamically using the DynamicFormField component\n * 4. Provides wallet connection UI (demo implementation)\n * 5. On submission, it processes data through the adapter before passing to handlers\n *\n * Note: The previewMode prop is currently used only for demo purposes and does not affect\n * the visibility of wallet connection or transaction execution UI. In the future, it will be used\n * to enable/disable actual blockchain interactions without changing the UI structure.\n *\n * @returns The rendered form component\n */\nexport function TransactionForm({\n schema,\n contractSchema,\n adapter,\n isWalletConnected = false,\n executionConfig,\n}: TransactionFormProps): React.ReactElement {\n const [formError, setFormError] = useState<string | null>(null);\n const [executionConfigError, setExecutionConfigError] = useState<string | null>(null);\n const [runtimeApiKey, setRuntimeApiKey] = useState('');\n\n // Transaction Lifecycle State\n const [txStatus, setTxStatus] = useState<TxStatus>('idle');\n const [txHash, setTxHash] = useState<string | null>(null);\n const [txError, setTxError] = useState<string | null>(null);\n const [txStatusDetails, setTxStatusDetails] = useState<TransactionStatusUpdate | null>(null);\n const [txResult, setTxResult] = useState<unknown | null>(null);\n\n // Derive networkConfig from the adapter instance\n const networkConfig = adapter.networkConfig;\n\n // Initialize form with React Hook Form\n const methods = useForm<FormValues>({\n mode: schema.validation?.mode || 'onChange',\n defaultValues: createDefaultFormValues(schema.fields, schema.defaultValues),\n });\n\n // Destructure necessary parts of formState to ensure re-renders\n const { isValid } = methods.formState;\n\n // Determine if the current function can execute locally (chain-agnostic check)\n const currentFunction = contractSchema?.functions.find((fn) => fn.id === schema.functionId);\n const canExecuteLocally = currentFunction?.stateMutability === 'pure';\n\n // Reset form when schema changes\n useEffect(() => {\n methods.reset(createDefaultFormValues(schema.fields, schema.defaultValues));\n setTxStatus('idle');\n setTxHash(null);\n setTxError(null);\n setFormError(null);\n setExecutionConfigError(null);\n setTxStatusDetails(null);\n setTxResult(null);\n }, [schema, methods]);\n\n // Effect to validate executionConfig\n useEffect(() => {\n const validateExecConfig = async (): Promise<void> => {\n if (executionConfig && adapter && adapter.validateExecutionConfig) {\n try {\n logger.info('TransactionForm', 'Re-validating execution config:', executionConfig);\n const validationResult = await adapter.validateExecutionConfig(executionConfig);\n if (typeof validationResult === 'string') {\n setExecutionConfigError(`Execution Configuration Error: ${validationResult}`);\n } else {\n setExecutionConfigError(null);\n }\n } catch (error) {\n logger.error('TransactionForm', 'Error reactive exec config validation:', error);\n setExecutionConfigError(\n `Exec Config Validation Failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n } else {\n setExecutionConfigError(null);\n }\n };\n void validateExecConfig();\n }, [executionConfig, adapter, isWalletConnected]);\n\n const executeTransaction = async (data: FormValues): Promise<void> => {\n logger.info('TransactionForm', 'Internal form submission attempt', data);\n setTxStatus('idle');\n setTxHash(null);\n setTxError(null);\n setTxStatusDetails(null);\n setTxResult(null);\n\n if (!adapter) {\n logger.error('TransactionForm', 'Adapter not provided.');\n setTxError('Configuration error: Adapter not available.');\n setTxStatus('error');\n return;\n }\n\n // Check if this function can execute locally (doesn't require wallet connection)\n // Chain-agnostic check: functions with stateMutability === 'pure' can execute locally\n if (!canExecuteLocally && !isWalletConnected) {\n logger.warn('TransactionForm', 'Wallet not connected for submission.');\n setTxError('Please connect your wallet to submit the transaction.');\n setTxStatus('error');\n return;\n }\n\n try {\n // Extract runtime secrets from form data and remove them from contract args\n const { contractArgs, runtimeSecrets } = extractRuntimeSecrets(data, schema.fields);\n\n const formattedData = adapter.formatTransactionData(\n contractSchema,\n schema.functionId as string,\n contractArgs,\n schema.fields\n );\n logger.info('TransactionForm', 'Formatted transaction data:', formattedData);\n\n const onStatusChange = (status: string, details: TransactionStatusUpdate): void => {\n logger.info('TransactionForm', `Status Update: ${status}`, details);\n setTxStatus(status as TxStatus);\n setTxStatusDetails(details);\n if (details.transactionId) {\n setTxHash(details.transactionId); // Show relayer ID\n }\n if (details.txHash) {\n setTxHash(details.txHash); // Show final hash\n }\n };\n\n // Pass first runtime secret via runtimeApiKey parameter\n // Adapters can implement getRuntimeFieldBinding() to customize secret handling\n const firstSecretValue = Object.values(runtimeSecrets)[0];\n\n // The initial status is set by the strategy via the callback\n const { txHash: finalTxHash, result } = await adapter.signAndBroadcast(\n formattedData,\n executionConfig || { method: 'eoa', allowAny: true },\n onStatusChange,\n runtimeApiKey, // Execution method credential (e.g., relayer API key)\n firstSecretValue // Adapter-specific runtime secret (e.g., organizer key)\n );\n\n logger.info('TransactionForm', `Transaction submitted with final hash: ${finalTxHash}`);\n setTxHash(finalTxHash);\n\n // Store result if provided (e.g., from local execution or blockchain transactions that return values)\n if (result !== undefined) {\n setTxResult(result);\n logger.info('TransactionForm', 'Execution result received:', result);\n }\n\n // Functions that execute locally don't need confirmation - they complete immediately\n if (canExecuteLocally) {\n setTxStatus('success');\n setTxError(null);\n return;\n }\n\n // --> Start: Wait for confirmation <--\n if (adapter.waitForTransactionConfirmation) {\n setTxStatus('pendingConfirmation');\n logger.info('TransactionForm', `Waiting for confirmation for tx: ${finalTxHash}`);\n const confirmationResult = await adapter.waitForTransactionConfirmation(finalTxHash);\n if (confirmationResult.status === 'success') {\n logger.info(\n 'TransactionForm',\n `Transaction confirmed: ${finalTxHash}`,\n confirmationResult.receipt\n );\n setTxStatus('success');\n setTxError(null);\n } else {\n logger.error(\n 'TransactionForm',\n `Transaction failed confirmation: ${finalTxHash}`,\n confirmationResult.error\n );\n setTxError(\n confirmationResult.error?.message ?? 'Transaction failed during confirmation.'\n );\n setTxStatus('error');\n }\n } else {\n // If adapter doesn't support waiting, consider submission as success immediately\n logger.warn(\n 'TransactionForm',\n 'Adapter does not support waitForTransactionConfirmation. Marking as success after submission.'\n );\n setTxStatus('success'); // Or maybe a different status like 'submitted'?\n setTxError(null);\n }\n // --> End: Wait for confirmation <--\n } catch (error) {\n logger.error('TransactionForm', 'Transaction error during submission process:', error);\n setTxError(error instanceof Error ? error.message : 'An unknown error occurred.');\n setTxStatus('error');\n }\n };\n\n // Build form layout with fields\n const renderFormContent = (): React.ReactNode => {\n if (!schema.fields || schema.fields.length === 0) {\n return <div className=\"form-empty-state\">No fields defined in schema</div>;\n }\n\n const { errors } = methods.formState;\n\n return (\n <div className=\"form-fields-container space-y-4\">\n {schema.fields.map((field) => (\n <DynamicFormField\n key={field.id}\n field={field}\n control={methods.control}\n error={errors[field.name]?.message as string}\n adapter={adapter}\n contractSchema={contractSchema}\n />\n ))}\n </div>\n );\n };\n\n // Apply fixed column layout\n // TODO: Add support for layout customization in the UI\n const getLayoutClasses = (): string => {\n // Fixed layout with 1 column and normal spacing\n return 'grid grid-cols-1 gap-4';\n };\n\n // TODO: temporary, refactor to use the button component from the ui package\n // Determine button variant based on schema configuration\n const getButtonVariant = ():\n | 'default'\n | 'destructive'\n | 'outline'\n | 'secondary'\n | 'ghost'\n | 'link' => {\n const { submitButton } = schema;\n if (!submitButton?.variant) return 'default';\n\n // Map schema button variant to our button component variants\n switch (submitButton.variant) {\n case 'primary':\n return 'default';\n case 'secondary':\n return 'secondary';\n case 'outline':\n return 'outline';\n default:\n return 'default';\n }\n };\n\n // Get explorer URL for the transaction\n const getExplorerTxUrl = (hash: string): string | null => {\n if (!adapter || !hash || !networkConfig) return null;\n\n if (adapter.getExplorerTxUrl) {\n // Call adapter method (which uses its internal networkConfig)\n return adapter.getExplorerTxUrl(hash);\n }\n\n // Fallback using getExplorerUrl (also uses internal networkConfig)\n logger.warn(\n 'TransactionForm',\n 'getExplorerTxUrl not implemented by adapter, trying getExplorerUrl as fallback (might expect address).'\n );\n // Ensure adapter.getExplorerUrl exists before calling\n return adapter.getExplorerUrl ? adapter.getExplorerUrl(hash) : null;\n };\n\n return (\n <FormProvider {...methods}>\n <div className=\"mb-4 flex items-center justify-between\">\n {schema.title && <h2 className=\"text-xl font-bold\">{schema.title}</h2>}\n </div>\n\n {/* Always render description container, just change content */}\n <div className=\"description-container mb-6\">\n <p className=\"text-muted-foreground rounded-md border border-gray-100 bg-gray-50 p-3 text-sm\">\n {schema.description || 'No description provided.'}\n </p>\n </div>\n\n <div className=\"flex flex-col space-y-4\">\n {/* Display General Form Error (if any) */}\n {formError && (\n <div className=\"form-error rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700\">\n {formError}\n </div>\n )}\n\n {/* Transaction Status Display - Moved OUTSIDE the form to avoid pointer-events-none */}\n {txStatus !== 'idle' && (\n <div className=\"mb-8 pointer-events-auto\">\n <TransactionStatusDisplay\n status={txStatus}\n txHash={txHash}\n error={txError}\n explorerUrl={txHash ? getExplorerTxUrl(txHash) : null}\n customTitle={txStatusDetails?.title}\n customMessage={txStatusDetails?.message}\n result={txResult}\n functionDetails={currentFunction}\n adapter={adapter}\n />\n </div>\n )}\n\n <form\n className={`transaction-form flex flex-col ${getLayoutClasses()} ${PENDING_STATES.includes(txStatus) ? 'opacity-70 pointer-events-none' : ''}`}\n noValidate\n onSubmit={methods.handleSubmit(executeTransaction)}\n >\n {/* Display Execution Config Error (if any) */}\n {executionConfigError && (\n <div className=\"form-error rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700\">\n <AlertCircle className=\"mr-2 h-4 w-4\" />\n {executionConfigError}\n </div>\n )}\n\n <div className=\"mb-6\">{renderFormContent()}</div>\n\n {/* Execution Config Display - Placed above the form actions */}\n {executionConfig && (\n <div className=\"w-full\">\n <ExecutionConfigDisplay\n executionConfig={executionConfig}\n adapter={adapter}\n error={executionConfigError}\n onRuntimeApiKeyChange={setRuntimeApiKey}\n />\n </div>\n )}\n\n {/* Form actions - Button only */}\n <div className=\"mt-4 border-t border-gray-100 pt-4\">\n <div className=\"flex justify-end items-center gap-2\">\n <TransactionExecuteButton\n isWalletConnected={isWalletConnected}\n isSubmitting={txStatus === 'pendingSignature' || txStatus === 'pendingConfirmation'}\n isFormValid={isValid && executionConfigError === null}\n variant={getButtonVariant()}\n functionDetails={currentFunction}\n canExecuteLocally={canExecuteLocally}\n />\n </div>\n </div>\n </form>\n </div>\n </FormProvider>\n );\n}\n","import { JSX, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { ContractFunction } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\ninterface FunctionResultProps {\n functionDetails: ContractFunction;\n result?: string;\n loading: boolean;\n}\n\n/**\n * Component for displaying formatted function results (strings)\n */\nexport function FunctionResult({\n functionDetails,\n result,\n loading,\n}: FunctionResultProps): JSX.Element {\n const formattedResult = result ?? '';\n const hasResult = typeof result === 'string';\n const isError = hasResult && (result.startsWith('Error:') || result.startsWith('[Error:'));\n\n const headerRef = useRef<HTMLDivElement>(null);\n const [fontSize, setFontSize] = useState<'xs' | '2xs'>('xs');\n const hasScaledDownRef = useRef(false);\n const lastContentRef = useRef<string>('');\n\n const outputs = useMemo(() => functionDetails.outputs || [], [functionDetails.outputs]);\n const currentContent = `${functionDetails.name}-${outputs.map((o) => o.type).join(',')}`;\n\n // Check if content overflows and adjust font size accordingly\n useEffect(() => {\n // Reset scaling state when content changes\n if (lastContentRef.current !== currentContent) {\n lastContentRef.current = currentContent;\n hasScaledDownRef.current = false;\n setFontSize('xs');\n return;\n }\n\n const checkOverflow = (): void => {\n if (!headerRef.current) return;\n\n const container = headerRef.current;\n const isOverflowing = container.scrollWidth > container.clientWidth;\n\n if (isOverflowing && fontSize === 'xs' && !hasScaledDownRef.current) {\n hasScaledDownRef.current = true;\n setFontSize('2xs');\n }\n };\n\n // Small delay to ensure rendering is complete\n const timeoutId = setTimeout(checkOverflow, 10);\n\n return (): void => {\n clearTimeout(timeoutId);\n };\n }, [functionDetails.name, outputs, fontSize, currentContent]);\n\n return (\n <div className=\"border rounded-sm p-2\">\n <div\n ref={headerRef}\n className={cn(\n 'font-medium mb-1 flex flex-wrap items-baseline gap-x-2 gap-y-1 leading-tight overflow-hidden',\n fontSize === 'xs' ? 'text-xs' : 'text-[10px]'\n )}\n >\n <span className=\"flex-shrink-0 min-w-0 break-all\">{functionDetails.name}</span>\n {outputs.length > 0 && (\n <span className=\"text-muted-foreground flex-shrink-0 whitespace-nowrap\">\n {`→ ${outputs.map((o) => o.type).join(', ')}`}\n </span>\n )}\n </div>\n\n {loading ? (\n <div className=\"text-xs text-muted-foreground italic animate-pulse\">Loading...</div>\n ) : hasResult ? (\n <pre\n className={cn(\n 'text-xs p-1 max-h-24 bg-muted overflow-auto rounded whitespace-pre-wrap break-all',\n 'animate-fade-in',\n isError && 'text-destructive'\n )}\n >\n {formattedResult}\n </pre>\n ) : (\n <div className=\"text-xs text-muted-foreground italic\">Click Refresh to fetch result</div>\n )}\n </div>\n );\n}\n","import { RefreshCw } from 'lucide-react';\nimport { JSX, useCallback, useEffect, useState } from 'react';\n\nimport { Button } from '@openzeppelin/ui-components';\nimport type { ContractAdapter, ContractFunction, ContractSchema } from '@openzeppelin/ui-types';\nimport {\n cn,\n logger,\n rateLimitedBatch,\n userRpcConfigService,\n type RpcConfigEvent,\n} from '@openzeppelin/ui-utils';\n\nimport { FunctionResult } from './FunctionResult';\n\ninterface ViewFunctionsPanelProps {\n functions: ContractFunction[];\n contractAddress: string;\n adapter: ContractAdapter;\n contractSchema: ContractSchema;\n className?: string;\n}\n\n/**\n * Panel for displaying and querying simple view functions (functions without parameters)\n */\nexport function ViewFunctionsPanel({\n functions,\n contractAddress,\n adapter,\n contractSchema,\n className,\n}: ViewFunctionsPanelProps): JSX.Element {\n const safeFunctions = adapter.filterAutoQueryableFunctions\n ? adapter.filterAutoQueryableFunctions(functions)\n : functions;\n const [results, setResults] = useState<Record<string, unknown>>({});\n const [loadingStates, setLoadingStates] = useState<Record<string, boolean>>({});\n const [hasQueried, setHasQueried] = useState(false);\n const [isQueryInProgress, setIsQueryInProgress] = useState(false);\n\n // Query all view functions at once\n const handleQueryAll = useCallback(async () => {\n if (safeFunctions.length === 0) return;\n\n // Prevent duplicate queries\n if (isQueryInProgress) {\n logger.info('ViewFunctionsPanel', 'Query already in progress, skipping...');\n return;\n }\n\n setIsQueryInProgress(true);\n\n // Set all functions to loading state\n const initialLoadingStates: Record<string, boolean> = {};\n safeFunctions.forEach((func) => {\n initialLoadingStates[func.id] = true;\n });\n setLoadingStates(initialLoadingStates);\n\n try {\n // Create query functions with incremental result updates\n const queryFunctions = safeFunctions.map(\n (func) => async (): Promise<{ funcId: string; success: boolean }> => {\n try {\n const result = await adapter.queryViewFunction(\n contractAddress,\n func.id,\n [],\n contractSchema\n );\n\n // Format the result immediately\n let formattedResult: string;\n try {\n formattedResult = adapter.formatFunctionResult(result, func);\n } catch (formatError) {\n logger.error(\n 'ViewFunctionsPanel',\n `Error formatting result for ${func.name}:`,\n formatError\n );\n formattedResult = `Error formatting result: ${formatError instanceof Error ? formatError.message : 'Unknown error'}`;\n }\n\n // Update results and loading state incrementally\n setResults((prev) => ({ ...prev, [func.id]: formattedResult }));\n setLoadingStates((prev) => ({ ...prev, [func.id]: false }));\n\n return { funcId: func.id, success: true };\n } catch (err) {\n logger.error('ViewFunctionsPanel', `Error calling ${func.name}:`, err);\n const errorMessage = `Error: ${err instanceof Error ? err.message : 'Unknown error'}`;\n\n // Update with error message and clear loading state\n setResults((prev) => ({ ...prev, [func.id]: errorMessage }));\n setLoadingStates((prev) => ({ ...prev, [func.id]: false }));\n\n return { funcId: func.id, success: false };\n }\n }\n );\n\n // Execute queries with rate limiting (1 at a time with 200ms delay between requests)\n await rateLimitedBatch(queryFunctions, 1, 200);\n } catch (err) {\n logger.error('ViewFunctionsPanel', 'Error querying functions:', err);\n // Clear all loading states on error\n setLoadingStates({});\n } finally {\n setHasQueried(true);\n setIsQueryInProgress(false);\n }\n }, [safeFunctions, contractAddress, adapter, contractSchema, isQueryInProgress]);\n\n // Auto-query all functions on component mount\n useEffect(() => {\n let mounted = true;\n let timeoutId: NodeJS.Timeout | null = null;\n\n const performInitialQuery = async (): Promise<void> => {\n if (safeFunctions.length > 0 && mounted && !hasQueried && !isQueryInProgress) {\n // Add a small delay to help with React StrictMode double mounting\n timeoutId = setTimeout(() => {\n if (mounted) {\n void handleQueryAll();\n }\n }, 100);\n }\n };\n\n void performInitialQuery();\n\n return (): void => {\n mounted = false;\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n }, [safeFunctions.length, hasQueried, isQueryInProgress, handleQueryAll]);\n\n // Listen for RPC configuration changes\n useEffect(() => {\n // Get the network ID from the adapter\n const networkId = adapter.networkConfig?.id;\n if (!networkId) return;\n\n // Subscribe to RPC config changes for this network\n const unsubscribe = userRpcConfigService.subscribe(networkId, (event: RpcConfigEvent) => {\n logger.info('ViewFunctionsPanel', 'RPC configuration changed:', event);\n // Re-query all functions when RPC config changes\n void handleQueryAll();\n });\n\n // Cleanup subscription on unmount\n return unsubscribe;\n }, [adapter.networkConfig?.id, handleQueryAll]);\n\n if (safeFunctions.length === 0) {\n return (\n <div className=\"text-xs text-muted-foreground\">\n No simple view functions found in this contract.\n </div>\n );\n }\n\n return (\n <div className={cn('space-y-4', className)}>\n <div className=\"flex items-center justify-between\">\n <h4 className=\"text-xs font-medium\">View Functions</h4>\n <Button\n onClick={() => {\n setHasQueried(false);\n void handleQueryAll();\n }}\n disabled={isQueryInProgress}\n size=\"sm\"\n variant=\"outline\"\n className=\"h-6 w-6 p-0 rounded-full\"\n title=\"Refresh all view functions\"\n >\n <RefreshCw size={14} className={`${isQueryInProgress ? 'animate-spin' : ''}`} />\n <span className=\"sr-only\">{isQueryInProgress ? 'Querying...' : 'Refresh All'}</span>\n </Button>\n </div>\n\n <div className=\"space-y-2 overflow-y-auto pr-1 flex-grow min-h-0\">\n {safeFunctions.map((func) => (\n <FunctionResult\n key={func.id}\n functionDetails={func}\n result={results[func.id] as string | undefined}\n loading={loadingStates[func.id] || false}\n />\n ))}\n </div>\n </div>\n );\n}\n","import { FileText, Loader2, Minimize2 } from 'lucide-react';\nimport { JSX, useEffect, useMemo, useState } from 'react';\n\nimport { Button, Card, CardContent, CardHeader, CardTitle } from '@openzeppelin/ui-components';\nimport type { ContractFunction, ContractSchema, FullContractAdapter } from '@openzeppelin/ui-types';\nimport { cn } from '@openzeppelin/ui-utils';\n\nimport { ViewFunctionsPanel } from './components/ViewFunctionsPanel';\n\ninterface ContractStateWidgetProps {\n contractSchema: ContractSchema | null;\n contractAddress: string | null;\n adapter: FullContractAdapter;\n isVisible?: boolean;\n onToggle?: () => void;\n className?: string;\n error?: Error | null;\n}\n\n/**\n * ContractStateWidget - Compact widget for displaying contract state\n * Shows contract state by allowing users to query simple view functions (no parameters)\n */\nexport function ContractStateWidget({\n contractSchema,\n contractAddress,\n adapter,\n isVisible = true,\n onToggle,\n className,\n error,\n}: ContractStateWidgetProps): JSX.Element | null {\n const [viewFunctions, setViewFunctions] = useState<ContractFunction[]>([]);\n const [animationState, setAnimationState] = useState<\n 'entering' | 'entered' | 'exiting' | 'exited'\n >(isVisible ? 'entered' : 'exited');\n\n const networkConfig = adapter?.networkConfig;\n\n // Preserve the last known schema so transient reloads don't flip the UI to a loading state\n const [lastSchema, setLastSchema] = useState<ContractSchema | null>(contractSchema ?? null);\n useEffect(() => {\n if (contractSchema) {\n setLastSchema(contractSchema);\n }\n }, [contractSchema]);\n const effectiveSchema = useMemo(() => contractSchema ?? lastSchema, [contractSchema, lastSchema]);\n\n useEffect((): void => {\n if (!effectiveSchema || !adapter) return;\n // Filter functions to only simple view functions (no parameters)\n const viewFns = effectiveSchema.functions.filter((fn) => adapter.isViewFunction(fn));\n setViewFunctions(viewFns.filter((fn) => fn.inputs.length === 0));\n }, [effectiveSchema, adapter]);\n\n // Control the animation state based on isVisible prop changes\n useEffect(() => {\n if (isVisible) {\n setAnimationState('entering');\n const timer = setTimeout(() => {\n setAnimationState('entered');\n }, 300);\n return (): void => clearTimeout(timer);\n } else {\n setAnimationState('exiting');\n const timer = setTimeout(() => {\n setAnimationState('exited');\n }, 500);\n return (): void => clearTimeout(timer);\n }\n }, [isVisible]);\n\n const handleToggle = (): void => {\n if (onToggle) {\n onToggle();\n }\n };\n\n if (!contractAddress || !adapter || !networkConfig) {\n return null;\n }\n\n // Keep mounted to allow exit animation on mobile. We'll hide on desktop via classes.\n\n return (\n <>\n {(animationState === 'entering' ||\n animationState === 'entered' ||\n animationState === 'exiting') && (\n <div\n className={cn(\n 'fixed inset-0 z-[9998] md:hidden bg-background/60 backdrop-blur-sm transition-opacity duration-500 ease-in-out',\n animationState === 'entering' || animationState === 'entered'\n ? 'opacity-100'\n : 'opacity-0'\n )}\n aria-hidden=\"true\"\n onClick={onToggle ? handleToggle : undefined}\n />\n )}\n <Card\n className={cn(\n 'overflow-hidden p-0 gap-0 flex flex-col transition-transform duration-500 ease-in-out will-change-transform transform-gpu',\n // Mobile: slide from bottom using translate classes\n animationState === 'entering' || animationState === 'entered'\n ? 'translate-y-0'\n : 'translate-y-[120%]',\n // Desktop: subtle scale/opacity\n animationState === 'entering' || animationState === 'entered'\n ? 'md:scale-100 md:opacity-100'\n : 'md:scale-95 md:opacity-0',\n // Mobile: fixed overlay positioned at bottom\n 'fixed bottom-4 inset-x-4 z-[9999] max-h-[50vh] shadow-xl bg-background backdrop-blur-md rounded-lg border border-border',\n // Desktop: relative positioned card in sidebar\n 'md:relative md:inset-auto md:bottom-auto md:shadow-none md:bg-card md:backdrop-blur-none md:z-auto md:mb-2 md:max-h-160',\n // Prevent interactions while animating out; hide entirely on desktop when exited\n (animationState === 'exiting' || animationState === 'exited') && 'pointer-events-none',\n animationState === 'exited' && 'md:hidden',\n className\n )}\n aria-hidden={animationState === 'exited'}\n >\n <CardHeader className=\"pb-2 pt-2 px-3 flex-shrink-0 flex flex-row items-center justify-between\">\n <CardTitle className=\"text-sm font-medium\">Contract State</CardTitle>\n {onToggle && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0\"\n onClick={handleToggle}\n title=\"Minimize Contract State\"\n >\n <Minimize2 size={14} />\n <span className=\"sr-only\">Minimize Contract State</span>\n </Button>\n )}\n </CardHeader>\n <CardContent className=\"space-y-3 px-3 py-2 flex-grow overflow-y-auto flex flex-col min-h-0\">\n {error ? (\n <div className=\"text-sm text-red-500 bg-red-50 border border-red-200 rounded-md p-3 flex flex-col items-center justify-center h-full\">\n <p className=\"font-medium text-center\">Error loading contract state</p>\n <p className=\"mt-1 text-xs text-center\">{error.message}</p>\n </div>\n ) : (!effectiveSchema && !lastSchema) || !adapter ? (\n <div className=\"flex flex-col items-center justify-center h-full space-y-3 py-6\">\n <Loader2 className=\"h-8 w-8 text-primary animate-spin opacity-70\" />\n <div className=\"text-center space-y-1\">\n <p className=\"text-sm font-medium text-muted-foreground\">\n Loading contract info...\n </p>\n <p className=\"text-xs text-muted-foreground\">\n Retrieving contract data and available functions\n </p>\n </div>\n </div>\n ) : viewFunctions.length > 0 && effectiveSchema ? (\n <ViewFunctionsPanel\n functions={viewFunctions}\n contractAddress={contractAddress}\n adapter={adapter}\n contractSchema={effectiveSchema}\n className=\"flex-grow flex flex-col min-h-0\"\n />\n ) : (\n <div className=\"flex flex-col items-center justify-center h-full py-4 text-center\">\n <div className=\"rounded-full bg-muted p-3 mb-3\">\n <FileText className=\"h-6 w-6 text-muted-foreground\" />\n </div>\n <p className=\"text-sm font-medium\">No simple view functions found</p>\n <p className=\"text-xs text-muted-foreground mt-1 mb-4 max-w-[220px]\">\n This contract doesn&apos;t have any simple view functions that can be queried\n without parameters\n </p>\n </div>\n )}\n </CardContent>\n </Card>\n </>\n );\n}\n","import React from 'react';\n\nimport { NetworkStatusBadge, ViewContractStateButton } from '@openzeppelin/ui-components';\nimport type { NetworkConfig } from '@openzeppelin/ui-types';\n\ninterface ContractActionBarProps {\n networkConfig: NetworkConfig | null;\n contractAddress?: string | null;\n onToggleContractState?: () => void;\n isWidgetExpanded?: boolean;\n children?: React.ReactNode;\n className?: string;\n}\n\n/**\n * ContractActionBar - A composable action bar for contract forms\n * Displays network information and contract state toggle button\n * Can be extended with additional actions via children\n */\nexport function ContractActionBar({\n networkConfig,\n contractAddress = null,\n onToggleContractState,\n isWidgetExpanded = false,\n children,\n className = '',\n}: ContractActionBarProps): React.ReactElement | null {\n if (!networkConfig) return null;\n\n return (\n <div\n className={`bg-background border-b mb-6 pb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between ${className}`}\n >\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center\">\n <NetworkStatusBadge network={networkConfig} />\n {contractAddress && onToggleContractState && !isWidgetExpanded && (\n <ViewContractStateButton\n contractAddress={contractAddress}\n onToggle={onToggleContractState}\n />\n )}\n </div>\n\n {/* Additional actions can be passed as children */}\n {children && <div className=\"flex gap-2 sm:ml-auto\">{children}</div>}\n </div>\n );\n}\n","'use client';\n\nimport { AlertTriangle, CheckCircle2, Info, Loader2, XCircle } from 'lucide-react';\nimport { JSX, useCallback, useEffect, useMemo, useState } from 'react';\nimport { Control, useForm } from 'react-hook-form';\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n Alert,\n AlertDescription,\n AlertTitle,\n Button,\n} from '@openzeppelin/ui-components';\nimport type { ContractAdapter, FormValues, NetworkServiceForm } from '@openzeppelin/ui-types';\nimport { logger, sanitizeHtml, userNetworkServiceConfigService } from '@openzeppelin/ui-utils';\n\nimport { DynamicFormField } from '../DynamicFormField';\n\ninterface Props {\n adapter: ContractAdapter;\n networkId: string;\n service: NetworkServiceForm;\n onSettingsChanged?: () => void;\n}\n\n/** Panel for configuring network service settings like RPC endpoints. */\nexport function NetworkServiceSettingsPanel({\n adapter,\n networkId,\n service,\n onSettingsChanged,\n}: Props): JSX.Element {\n const [isTesting, setIsTesting] = useState(false);\n const [result, setResult] = useState<{\n success: boolean;\n message: string;\n latencyMs?: number;\n } | null>(null);\n\n const {\n control,\n handleSubmit,\n setValue,\n getValues,\n watch,\n formState: { isDirty },\n } = useForm<FormValues>({ defaultValues: {} });\n const fields = useMemo(() => service.fields, [service]);\n const primaryFields = useMemo(\n () => fields.filter((f) => !(f.metadata as Record<string, unknown> | undefined)?.section),\n [fields]\n );\n const sectionGroups = useMemo(() => {\n const groups: Record<string, { label?: string; help?: string; fields: typeof fields }> =\n {} as never;\n for (const f of fields) {\n const md = (f.metadata as Record<string, unknown> | undefined) || {};\n const section = typeof md.section === 'string' ? (md.section as string) : undefined;\n if (!section) continue;\n if (!groups[section]) {\n groups[section] = {\n label: typeof md.sectionLabel === 'string' ? (md.sectionLabel as string) : undefined,\n help: typeof md.sectionHelp === 'string' ? (md.sectionHelp as string) : undefined,\n fields: [],\n };\n }\n // Update label/help if not already set and this field has them\n if (!groups[section]!.label && typeof md.sectionLabel === 'string') {\n groups[section]!.label = md.sectionLabel as string;\n }\n if (!groups[section]!.help && typeof md.sectionHelp === 'string') {\n groups[section]!.help = md.sectionHelp as string;\n }\n groups[section]!.fields.push(f);\n }\n return groups;\n }, [fields]);\n\n // Load existing saved values\n useEffect(() => {\n try {\n const existing = userNetworkServiceConfigService.get(networkId, service.id);\n if (existing && typeof existing === 'object') {\n for (const f of fields) {\n const v = (existing as Record<string, unknown>)[f.name];\n if (v !== undefined) setValue(f.name, v as never);\n }\n }\n\n // Seed adapter-provided defaults for any fields that remain unset\n for (const f of fields) {\n const current = (getValues() as Record<string, unknown>)[f.name];\n const hasValue = current !== undefined && current !== null && current !== '';\n if (!hasValue && 'defaultValue' in f && f.defaultValue !== undefined) {\n setValue(f.name, f.defaultValue as never);\n }\n }\n } catch (e) {\n logger.error('NetworkServiceSettingsPanel', 'Error loading config', e);\n }\n }, [networkId, service.id, fields, setValue, getValues]);\n\n const testConnection = useCallback(async () => {\n if (!adapter.testNetworkServiceConnection) return;\n setIsTesting(true);\n setResult(null);\n try {\n const data = getValues() as unknown as Record<string, unknown>;\n const r = await adapter.testNetworkServiceConnection(service.id, data);\n setResult({\n success: r.success,\n message: r.error || (r.success ? 'Connection successful' : 'Connection failed'),\n latencyMs: r.latency,\n });\n } catch (e) {\n setResult({\n success: false,\n message: e instanceof Error ? e.message : 'Connection test failed',\n });\n } finally {\n setIsTesting(false);\n }\n }, [adapter, service.id, getValues]);\n\n const onSubmit = useCallback(\n async (formData: FormValues) => {\n const data = formData as unknown as Record<string, unknown>;\n if (adapter.validateNetworkServiceConfig) {\n const ok = await adapter.validateNetworkServiceConfig(service.id, data);\n if (!ok) {\n setResult({ success: false, message: 'Invalid configuration' });\n return;\n }\n }\n const nonEmpty = Object.values(data).some((v) => v !== undefined && v !== null && v !== '');\n if (nonEmpty) {\n userNetworkServiceConfigService.save(networkId, service.id, data);\n } else {\n userNetworkServiceConfigService.clear(networkId, service.id);\n }\n\n onSettingsChanged?.();\n setResult({ success: true, message: 'Settings saved successfully' });\n },\n [adapter, networkId, service.id, onSettingsChanged]\n );\n\n return (\n <form onSubmit={handleSubmit(onSubmit)} className=\"space-y-6\">\n {service.description && (\n <Alert>\n <Info className=\"h-4 w-4\" />\n <AlertTitle className=\"text-sm\">{service.label}</AlertTitle>\n <AlertDescription className=\"space-y-1 text-xs\">\n <p className=\"mt-2\">{service.description}</p>\n </AlertDescription>\n </Alert>\n )}\n\n {/* Adapter-provided informational notes */}\n {fields.filter((f) => (f.metadata as Record<string, unknown> | undefined)?.note).length >\n 0 && (\n <div className=\"space-y-4\">\n {fields\n .filter((f) => (f.metadata as Record<string, unknown> | undefined)?.note)\n .map((f) => {\n const note = (f.metadata as Record<string, unknown> | undefined)?.note as\n | { variant?: 'info' | 'warning'; title?: string; lines?: string[]; html?: boolean }\n | undefined;\n const isWarning = note?.variant === 'warning';\n const Icon = isWarning ? AlertTriangle : Info;\n return (\n <Alert key={f.id}>\n <Icon className=\"h-4 w-4\" />\n {note?.title && <AlertTitle className=\"text-sm\">{note.title}</AlertTitle>}\n {note?.lines && note.lines.length > 0 && (\n <AlertDescription className=\"space-y-1 text-xs\">\n {note.lines.map((ln, idx) =>\n note.html ? (\n <p key={idx} dangerouslySetInnerHTML={{ __html: sanitizeHtml(ln) }} />\n ) : (\n <p key={idx}>{ln}</p>\n )\n )}\n </AlertDescription>\n )}\n </Alert>\n );\n })}\n </div>\n )}\n\n {/* Primary, ungrouped fields */}\n {primaryFields.length > 0 && (\n <div className=\"space-y-4\">\n {primaryFields.map((field) => (\n <DynamicFormField\n key={field.id}\n field={field}\n control={control as unknown as Control<FormValues>}\n adapter={adapter}\n />\n ))}\n </div>\n )}\n\n {/* Advanced, adapter-defined section groups */}\n {Object.keys(sectionGroups).length > 0 && (\n <Accordion type=\"single\" collapsible className=\"w-full\">\n <AccordionItem value=\"advanced-settings\" className=\"border rounded-md\">\n <AccordionTrigger className=\"text-sm font-medium px-3 py-2 hover:no-underline\">\n Advanced Settings\n </AccordionTrigger>\n <AccordionContent className=\"px-3 pb-4\">\n <div className=\"space-y-6 pt-2\">\n {Object.entries(sectionGroups).map(([sectionId, group]) => (\n <div key={sectionId}>\n <div className=\"mb-3\">\n <h4 className=\"text-sm font-medium text-foreground\">\n {group.label ||\n sectionId.replace(/[-_]/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase())}\n </h4>\n {group.help && (\n <p className=\"text-xs text-muted-foreground mt-1\">{group.help}</p>\n )}\n </div>\n <div className=\"space-y-4\">\n {group.fields.map((field) => {\n const md = (field.metadata as Record<string, unknown> | undefined) || {};\n const indentUnder =\n typeof md['nestUnder'] === 'string'\n ? (md['nestUnder'] as string)\n : undefined;\n const disabledWhen = md['disabledWhen'] as\n | { field: string; equals?: unknown; notEquals?: unknown }\n | undefined;\n let isDisabled = false;\n if (disabledWhen && typeof disabledWhen.field === 'string') {\n const depVal = watch(disabledWhen.field);\n if ('equals' in disabledWhen) isDisabled = depVal === disabledWhen.equals;\n else if ('notEquals' in disabledWhen)\n isDisabled = depVal !== disabledWhen.notEquals;\n }\n const wrappedField = { ...field, readOnly: isDisabled } as typeof field;\n return (\n <div key={field.id} className={indentUnder ? 'ml-6' : ''}>\n <DynamicFormField\n field={wrappedField}\n control={control as unknown as Control<FormValues>}\n adapter={adapter}\n />\n </div>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n </AccordionContent>\n </AccordionItem>\n </Accordion>\n )}\n\n {result && (\n <div\n className={`flex items-center gap-2 text-sm ${result.success ? 'text-green-600' : 'text-red-600'}`}\n >\n {result.success ? <CheckCircle2 className=\"h-4 w-4\" /> : <XCircle className=\"h-4 w-4\" />}\n <span>{result.message}</span>\n {result.latencyMs && (\n <span className=\"text-muted-foreground\">({result.latencyMs}ms)</span>\n )}\n </div>\n )}\n\n <div className=\"flex justify-end gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n // Reset to default\n for (const f of fields) setValue(f.name, undefined as never);\n userNetworkServiceConfigService.clear(networkId, service.id);\n setResult(null);\n onSettingsChanged?.();\n }}\n >\n Reset to Default\n </Button>\n {((): boolean => {\n // Check if service explicitly disables connection testing\n if (service.supportsConnectionTest === false) {\n return false;\n }\n // Allow adapters to hide the test button by setting a field metadata flag\n const hideTest = fields.some((f) => {\n const md = f.metadata as Record<string, unknown> | undefined;\n return (md?.hideTestConnection as boolean) === true;\n });\n return Boolean(adapter.testNetworkServiceConnection) && !hideTest;\n })() ? (\n <Button type=\"button\" variant=\"outline\" onClick={testConnection} disabled={isTesting}>\n {isTesting ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n Testing...\n </>\n ) : (\n 'Test Connection'\n )}\n </Button>\n ) : null}\n <Button type=\"submit\" disabled={!isDirty}>\n Save Settings\n </Button>\n </div>\n </form>\n );\n}\n","import React from 'react';\n\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@openzeppelin/ui-components';\nimport type { ContractAdapter, UiKitConfiguration } from '@openzeppelin/ui-types';\nimport { appConfigService } from '@openzeppelin/ui-utils';\n\nimport { NetworkServiceSettingsPanel } from './NetworkServiceSettingsPanel';\n\ninterface Props {\n isOpen: boolean;\n onOpenChange: (open: boolean) => void;\n networkConfig: { id: string; name: string } | null;\n adapter: ContractAdapter | null;\n}\n\nexport const NetworkSettingsDialog: React.FC<Props> = ({\n isOpen,\n onOpenChange,\n networkConfig,\n adapter,\n}) => {\n const services = adapter?.getNetworkServiceForms?.() ?? [];\n\n return (\n <Dialog open={isOpen} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-w-2xl sm:max-w-3xl\">\n <DialogHeader>\n <DialogTitle>Network Settings</DialogTitle>\n <DialogDescription>Configure settings for {networkConfig?.name}</DialogDescription>\n </DialogHeader>\n\n {networkConfig && adapter && services.length > 0 ? (\n <Tabs defaultValue={services[0]?.id} className=\"w-full\">\n <TabsList\n className={`grid w-full ${services.length <= 2 ? 'grid-cols-2' : services.length === 3 ? 'grid-cols-3' : 'grid-cols-4'}`}\n >\n {services.map((svc) => (\n <TabsTrigger key={svc.id} value={svc.id}>\n {svc.label}\n </TabsTrigger>\n ))}\n </TabsList>\n {services.map((svc) => (\n <TabsContent key={svc.id} value={svc.id} className=\"px-2\">\n <NetworkServiceSettingsPanel\n adapter={adapter}\n networkId={networkConfig.id}\n service={svc}\n onSettingsChanged={() => {\n // Reconfigure the adapter's UI kit so wallet transports pick up new RPCs\n const cfg = appConfigService.getTypedNestedConfig<UiKitConfiguration>(\n 'walletui',\n 'config'\n );\n // Optional chaining because not all adapters expose this method\n adapter.configureUiKit?.(cfg ?? { kitName: 'custom', kitConfig: {} });\n }}\n />\n </TabsContent>\n ))}\n </Tabs>\n ) : (\n <div className=\"flex items-center justify-center py-8\">\n <div className=\"text-center text-muted-foreground\">\n <p className=\"text-sm\">No network configuration available</p>\n <p className=\"text-xs mt-1\">\n This network uses default settings that cannot be customized\n </p>\n </div>\n </div>\n )}\n </DialogContent>\n </Dialog>\n );\n};\n","import { Settings } from 'lucide-react';\nimport React, { useCallback, useEffect, useState } from 'react';\n\nimport { Button, useNetworkErrors } from '@openzeppelin/ui-components';\nimport { useWalletState, WalletConnectionUI } from '@openzeppelin/ui-react';\n\nimport { NetworkSettingsDialog } from './network/NetworkSettingsDialog';\n\n/**\n * Enhanced wallet connection header with network settings menu.\n * Used in exported apps to provide access to RPC and Explorer configuration.\n */\nexport const WalletConnectionWithSettings: React.FC = () => {\n const { isAdapterLoading, activeAdapter, activeNetworkConfig } = useWalletState();\n const { setOpenNetworkSettingsHandler } = useNetworkErrors();\n\n // Network settings dialog state\n const [showNetworkSettings, setShowNetworkSettings] = useState(false);\n\n // Create a stable callback for opening network settings\n const openNetworkSettings = useCallback(\n (networkId: string) => {\n // In exported apps, we only support the current network\n // The dialog will show tabs based on adapter.getNetworkServiceForms()\n if (activeNetworkConfig && networkId === activeNetworkConfig.id) {\n setShowNetworkSettings(true);\n }\n },\n [activeNetworkConfig]\n );\n\n // Register handler for opening network settings from error notifications\n useEffect(() => {\n setOpenNetworkSettingsHandler(openNetworkSettings);\n }, [openNetworkSettings, setOpenNetworkSettingsHandler]);\n\n if (isAdapterLoading) {\n return <div className=\"h-9 w-28 animate-pulse rounded bg-muted\"></div>;\n }\n\n return (\n <>\n <div className=\"flex items-center gap-2\">\n <WalletConnectionUI />\n\n {/* Settings Button */}\n {activeAdapter && activeNetworkConfig && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-9 w-9\"\n title=\"Network Settings\"\n onClick={() => setShowNetworkSettings(true)}\n >\n <Settings className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n\n {/* Network Settings Dialog */}\n <NetworkSettingsDialog\n isOpen={showNetworkSettings}\n onOpenChange={setShowNetworkSettings}\n networkConfig={activeNetworkConfig}\n adapter={activeAdapter}\n />\n </>\n );\n};\n"],"mappings":"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"}