Spin up a front-end for any contract call in seconds. Select the function, auto-generate a React UI with wallet connect and multi-network support, and export a complete app.
This project is currently in development.
This project is organized as a monorepo with the following packages:
- packages/builder: The main application with the builder app UI and core logic.
- packages/react-core: Contains core React context providers and hooks (AdapterProvider, WalletStateProvider, useWalletState) for managing global wallet/network state and adapter interactions. Used by
@builder
and exported apps. - packages/renderer: The shared app rendering library (published to npm), responsible for dynamically rendering forms and other components based on schemas and an active adapter.
- packages/ui: Contains shared React UI components, including basic primitives (buttons, inputs, cards) and specialized form field components. Used by
builder
andrenderer
to ensure a consistent look and feel. - packages/storage: Local storage services built on IndexedDB for persisting contract UI configurations, providing history, auto-save, and import/export capabilities.
- packages/types: Shared TypeScript type definitions for all packages (published to npm).
- packages/styles: Centralized styling system with shared CSS variables and configurations.
- packages/utils: Shared, framework-agnostic utility functions (e.g., logger, app configuration service).
- packages/adapter-evm: Adapter implementation for EVM-compatible chains.
- packages/adapter-solana: Adapter implementation for the Solana blockchain.
- packages/adapter-stellar: Adapter implementation for the Stellar network.
- packages/adapter-midnight: Adapter implementation for the Midnight blockchain.
The renderer
package provides a reusable library for rendering transaction forms and other components. It's published to npm and can be used independently of the main application.
Features:
- Lightweight app rendering components
- Framework-agnostic design
- TypeScript support with full type definitions
- Support for both ESM and CommonJS environments
- Customizable styling options
For more details, see the Renderer README.
The types
package contains shared TypeScript type definitions for all packages in the ecosystem. It serves as the single source of truth for types used across the Contracts UI Builder.
Features:
- Centralized type definitions
- Organized namespaces for contracts, adapters, and forms
- Clear separation of concerns
- TypeScript project references for proper type checking
For more details, see the Types README.
The styles
package contains the centralized styling system used across all packages. It provides consistent theming, spacing, and component styles throughout the application.
Features:
- Shared CSS variables with direct OKLCH color values
- Consistent form component spacing
- Dark mode support
- Tailwind CSS v4 integration
For more details, see the Styles README.
The storage
package provides local storage services built on IndexedDB using Dexie.js for persisting contract UI configurations. It enables a complete history and auto-save system for the builder application.
Features:
- Generic storage base class for extensible type-safe storage services
- Reactive updates with automatic UI synchronization across browser tabs
- Complete CRUD operations with performance optimization for 1000+ records
- Built-in auto-save functionality with debouncing and duplicate operation prevention
- Import/export capabilities for sharing configurations as JSON files
- Full TypeScript support with proper type definitions
- Integration with React hooks for seamless UI state management
For more details, see the Storage README.
- Chain-agnostic architecture supporting multiple blockchain ecosystems
- Adapter pattern for easily adding support for new blockchains
- Modern React components for building transaction forms
- Customizable UI with Tailwind CSS and shadcn/ui
- Local Storage & History: Complete auto-save system with IndexedDB-based persistence for contract UI configurations
- Import/Export: Save and share configurations as JSON files with built-in validation
- Multi-tab Synchronization: Real-time synchronization of saved configurations across browser tabs
- Handles wallet connection state consistently in both builder app and exported forms
- Configure transaction execution methods (EOA, Relayer, Multisig) via a powerful Execution Strategy pattern
- Type-safe with TypeScript
- Fast development with Vite
- Component documentation with Storybook
- Comprehensive test suite with Vitest
- Automated dependency management and security checks
- React: UI library supporting both React 18 and 19 with modern hooks API
- TypeScript 5.8+: Enhanced type safety with template literal types
- Vite 6: Fast, modern build tool and dev server with standardized library builds
- Tailwind CSS v4: Next-gen utility-first CSS framework with OKLCH color format
- shadcn/ui: Unstyled, accessible component system built on Radix UI
- pnpm (v9 or higher): Fast, disk-efficient package manager
- Vitest: Testing framework integrated with Vite
- Storybook 8: Component documentation and visual testing
- Zustand: Lightweight, performant state management for React
- Changesets: Automated versioning and package releases
- ESLint 9: Modern linting with improved TypeScript support
- tsup: Fast, modern bundler for TypeScript libraries
- Vite: Used for the builder application's dev server
- Dexie.js: Modern IndexedDB wrapper for local storage and offline capabilities
- @openzeppelin/relayer-sdk: For gasless transaction support via the Relayer execution method.
- Node.js (v20.11.1 or higher)
- pnpm (v9 or higher)
-
Clone the repository:
git clone https://github.com/OpenZeppelin/contracts-ui-builder.git cd contracts-ui-builder
-
Install dependencies:
pnpm install
-
Start the development server:
pnpm dev
-
Open your browser and navigate to
http://localhost:5173
For a consistent and reliable development environment, it is highly recommended to run the application using Docker. This avoids potential issues with local Node.js, pnpm, or operating system configurations.
-
Prerequisites: Make sure you have Docker and Docker Compose installed on your system.
-
Build and Run the Container:
docker-compose up --build
This command will build the Docker image and start the application. Once it's running, you can access it at
http://localhost:3000
.
pnpm dev
- Start the development serverpnpm build
- Build for productionpnpm lint
- Run ESLintpnpm lint:adapters
- Validate adapter implementations against the ContractAdapter interfacepnpm lint:fix
- Fix ESLint issuespnpm lint:all-fix
- Fix ESLint issues across all file typespnpm lint:config-files
- Fix linting in configuration filespnpm format
- Format code with Prettierpnpm format:check
- Check formatting without making changespnpm fix-all
- Run Prettier first, then ESLint to avoid conflicts with CSS class sortingpnpm preview
- Preview the production buildpnpm ui:add
- Add shadcn/ui componentspnpm test
- Run testspnpm test:watch
- Run tests in watch modepnpm test:coverage
- Run tests with coverage reportpnpm storybook
- Start Storybook development serverpnpm build-storybook
- Build Storybook for productionpnpm commit
- Run commitizen for guided commitspnpm changeset
- Create a changeset for your changespnpm update-deps
- Update all monorepo dependencies to their latest versionspnpm update-deps:major
- Update dependencies including major versionspnpm check-deps
- Check for deprecated dependenciespnpm outdated
- List outdated dependencies across the monorepopnpm export-app [cmd] [opts]
- Export a standalone form project (seepnpm export-app --help
)pnpm update-export-versions
- Update the hardcoded versions of internal packages used in exported forms
This monorepo is organized into several specialized packages, each with a specific purpose:
- packages/builder/ - Main application with builder UI, export system, and core logic
- packages/renderer/ - Shared library for rendering transaction forms and components (published to npm)
- packages/react-core/ - Core React providers and hooks for wallet/adapter state management
- packages/ui/ - Shared UI components and form field components
- packages/storage/ - Local storage services with IndexedDB for configuration persistence
- packages/types/ - Shared TypeScript type definitions (published to npm)
- packages/styles/ - Centralized styling system with CSS variables and configurations
- packages/utils/ - Framework-agnostic utility functions
- packages/adapter-evm/ - EVM-compatible chains (Ethereum, Polygon, BSC, etc.)
- packages/adapter-solana/ - Solana blockchain implementation
- packages/adapter-stellar/ - Stellar network implementation
- packages/adapter-midnight/ - Midnight blockchain implementation
contracts-ui-builder/
├── .github/ # GitHub workflows and templates
├── .storybook/ # Storybook configuration
├── .husky/ # Git hooks
├── test/ # Shared test setup and utilities
├── packages/ # Monorepo packages (see individual READMEs for detailed structure)
├── scripts/ # Utility scripts
├── tailwind.config.cjs # Central Tailwind CSS configuration
├── postcss.config.cjs # Central PostCSS configuration
├── components.json # Central shadcn/ui configuration
├── tsconfig.base.json # Base TypeScript configuration for all packages
├── pnpm-workspace.yaml # PNPM workspace configuration
└── ... # Other configuration files
For detailed internal structure of each package, please refer to the individual package README files linked above.
The application uses a modular, domain-driven adapter pattern to support multiple blockchain ecosystems. For a detailed explanation of the adapter architecture and module responsibilities, please see the Adapter Architecture Guide.
Key Components:
-
Builder: Chain-agnostic application logic, UI components, and the export system. It includes:
- The
ecosystemManager.ts
for discovering network configurations and adapter capabilities. - Modular State Management: Decomposed hook architecture with specialized responsibilities.
- Application Sidebar: Complete UI for managing saved configurations with import/export capabilities
- The
-
Storage System (
packages/storage
): IndexedDB-based persistence layer built on Dexie.js providing:- Auto-Save Engine: Debounced saving with in-memory caching and global coordination
- Multi-Tab Synchronization: Real-time updates across browser tabs
- Import/Export: JSON-based configuration sharing with validation
- CRUD Operations: Complete lifecycle management for contract UI configurations
- Performance Optimization: Efficient handling of 1000+ records with reactive updates
-
Adapters (
packages/adapter-*
): Individual packages containing chain-specific implementations (e.g.,EvmAdapter
,SolanaAdapter
). Each adapter conforms to the commonContractAdapter
interface defined inpackages/types
. Adapters are instantiated with a specificNetworkConfig
, making them network-aware. Thebuilder
package (via providers from@openzeppelin/contracts-ui-builder-react-core
) dynamically loads and uses these adapters. Furthermore, adapters can optionally provide UI-specific functionalities:- React UI Context Provider (e.g., for
wagmi/react
on EVM):WalletStateProvider
(from@openzeppelin/contracts-ui-builder-react-core
) consumes this to set up the necessary app-wide context for the active adapter. - Facade Hooks (e.g.,
useAccount
,useSwitchChain
): These are exposed byWalletStateProvider
(viauseWalletState().walletFacadeHooks
from@openzeppelin/contracts-ui-builder-react-core
) for UI components to interact with wallet functionalities reactively and agnostically. - Standardized UI Components (e.g.,
ConnectButton
): These components are retrieved viaactiveAdapter.getEcosystemWalletComponents()
and are expected to internally use the facade hooks.
- React UI Context Provider (e.g., for
-
Renderer: Shared library containing app rendering components and common utilities (like logging).
-
React Core (
packages/react-core
): Centralized React state management providing:- Adapter Provider: Singleton pattern for adapter instance management
- Wallet State Provider: Global wallet/network state coordination
- Context Hooks:
useWalletState()
anduseAdapterContext()
for consistent state access
-
UI Components (
packages/ui
): Comprehensive component library including:- Basic Primitives: Buttons, inputs, cards, dialogs following shadcn/ui patterns
- Form Fields: Specialized components for React Hook Form integration
- Field Utilities: Validation, accessibility, and layout helpers
-
Types: Shared TypeScript type definitions across all packages, including the crucial
ContractAdapter
interface and types for adapter UI enhancements. -
Styling System: Centralized CSS variables and styling approach used across all packages.
This architecture allows for easy extension to support additional blockchain ecosystems without modifying the builder application logic. The builder
package dynamically loads and uses adapters via ecosystemManager.ts
and the provider model (from @openzeppelin/contracts-ui-builder-react-core
) and the export system includes the specific adapter package needed for the target chain in exported forms. It utilizes custom Vite plugins to create virtual modules, enabling reliable loading of shared assets (like configuration files between packages) across package boundaries, ensuring consistency between development, testing, and exported builds.
The project uses a standardized tsup
-based build system for all library packages, ensuring proper ES module output with correct import extensions:
- tsup: All library packages are built using
tsup
to generate both ES modules (.js
) and CommonJS (.cjs
) formats. - TypeScript: The TypeScript compiler (
tsc
) is used alongsidetsup
to generate declaration files (.d.ts
). - ES Module Support: The dual-format build ensures packages can be consumed in both modern and legacy JavaScript environments.
- Optimized Output: Builds are configured for optimal tree-shaking and performance.
Each package contains its own tsup.config.ts
and the build
script in its package.json
orchestrates the two-stage build process. This ensures consistency and reliability across the monorepo.
To maintain the integrity of the adapter pattern, this project includes:
- Custom ESLint Rule: Enforces that adapter implementations only include methods defined in the
ContractAdapter
interface - Automated Validation: The
lint:adapters
command automatically discovers and validates all adapter implementations - CI Integration: Adapter pattern compliance is checked on every pull request
- Pre-Push Hook: Prevents pushing code that violates the adapter pattern
These enforcement mechanisms ensure that the adapter interface remains the single source of truth for adapter implementations, preventing interface drift and maintaining architectural consistency.
For more detailed documentation about the adapter pattern, implementation guidelines, and validation rules, see the documentation within the packages/types/src/adapters/base.ts
file where the ContractAdapter
interface is defined.
The project follows a structured component architecture centered around app rendering:
The renderer package provides the core TransactionForm
component for rendering transaction forms. It dynamically selects and renders appropriate field components using its DynamicFormField
component. The actual UI primitives and field component implementations (like TextField
, AddressField
, Button
, Input
) are sourced from the @openzeppelin/contracts-ui-builder-ui
package.
These field components are designed to work exclusively with React Hook Form and are orchestrated by DynamicFormField
.
The project uses Storybook 8 for component documentation and development:
# Start Storybook at the root level
pnpm storybook
# Or start Storybook for a specific package
pnpm --filter=@openzeppelin/contracts-ui-builder-renderer storybook
Storybook stories are organized to:
- Document component usage and API
- Showcase different component states and variations
- Provide interactive examples for development
- Serve as visual regression tests
Stories are located in the stories
directory of each package, with renderer components having the most comprehensive documentation.
This project uses Husky to enforce code quality using Git hooks:
- pre-commit: Runs lint-staged to format and lint staged files (Prettier first, then ESLint)
- pre-push: Runs comprehensive linting and formatting before pushing to remote
- commit-msg: Enforces conventional commit message format
These hooks ensure that code pushed to the repository maintains consistent quality and style.
For consistent CSS class name sorting in Tailwind CSS, always run Prettier first, then ESLint:
# Recommended approach (runs formatting, then linting)
pnpm fix-all
This approach ensures that Tailwind CSS classes are consistently sorted by the prettier-plugin-tailwindcss plugin and prevents conflicts between formatting and linting tools.
This project uses a single, shared Prettier configuration at the root of the monorepo. Individual packages should not include their own .prettierrc
files. The root configuration includes:
- Common code style settings (single quotes, semi-colons, etc.)
- Tailwind CSS class sorting via prettier-plugin-tailwindcss
- Configuration for special utility functions like
cva
,cn
,clsx
, andtwMerge
To format all packages:
pnpm format
Imports are automatically sorted in the following order:
- React and related packages
- External packages
- Internal packages (alias imports starting with
@/
) - Parent imports (starting with
..
) - Other relative imports (starting with
.
) - Style imports
- Type imports
This ordering is enforced by ESLint and automatically fixed on commit.
This project uses several tools to manage dependencies effectively:
- pnpm: Fast, disk space efficient package manager
- check-deps script: Custom utility to identify deprecated dependencies
- update-deps script: Easily update all dependencies to their latest versions
- Dependencies workflow: Regular checks for outdated dependencies
- Update Dependencies workflow: Weekly automated updates
The versions of internal @openzeppelin/
packages used in exported forms are centrally managed in the packages/builder/src/export/versions.ts
file. This ensures that all exported projects use stable, tested, and reproducible dependency versions.
To update these versions to the latest published releases, run the following command from the root of the monorepo:
pnpm update-export-versions
This script will fetch the latest versions from the npm registry and update the versions.ts
file automatically.
To see which dependencies are outdated:
pnpm outdated
For regular updates (respecting semver):
pnpm update-deps
For major version updates (may include breaking changes):
pnpm update-deps:major
The project is configured with:
- Update Dependencies workflow: Runs weekly to check for and apply updates
To add support for a new blockchain ecosystem:
- Create Package: Create a new directory
packages/adapter-<chain-name>
(e.g.,packages/adapter-sui
). - Define
package.json
:- Set the package name (e.g.,
@openzeppelin/contracts-ui-builder-adapter-sui
). - Add a dependency on
@openzeppelin/contracts-ui-builder-types
(workspace:*
). - Add any chain-specific SDKs or libraries required by the adapter.
- Include standard build scripts (refer to existing adapter packages).
- Important: Ensure your package exports a named array of its
NetworkConfig[]
objects (e.g.,export const suiNetworks = [...]
) and its mainAdapter
class from its entry point (src/index.ts
).
- Set the package name (e.g.,
- Define
tsconfig.json
: Create atsconfig.json
extending the roottsconfig.base.json
. - Implement Adapter:
- Create
src/adapter.ts
. - Import
ContractAdapter
, the specificYourEcosystemNetworkConfig
(e.g.,SuiNetworkConfig
), and related types from@openzeppelin/contracts-ui-builder-types
. - Implement the
ContractAdapter
interface. The constructor must accept its specificNetworkConfig
(e.g.,constructor(networkConfig: SuiNetworkConfig)
). - Implement methods to use
this.networkConfig
internally for network-specific operations (e.g., initializing HTTP clients with RPC URLs from the config).
- Create
- Define Network Configurations:\
- Create
src/networks/mainnet.ts
,testnet.ts
, etc., definingYourEcosystemNetworkConfig
objects for each supported network. - Each network config must provide all necessary details for the adapter to function, such as RPC endpoints (
rpcUrl
orrpcEndpoint
), chain identifiers (chainId
for EVM), explorer URLs, native currency details, etc., as defined by itsYourEcosystemNetworkConfig
interface. - Create
src/networks/index.ts
to export the combined list of networks (e.g.,export const suiNetworks = [...mainnetSuiNetworks, ...testnetSuiNetworks];
) and also export each network configuration individually by its constant name (e.g.,export { suiMainnet, suiTestnet } from './mainnet';
).
- Create
- Export Adapter & Networks: Create
src/index.ts
in your adapter package and export the adapter class (e.g.,export { SuiAdapter } from './adapter';
) and the main networks array (e.g.,export { suiNetworks } from './networks';
). It's also good practice to re-export individual network configurations from the adapter's main entry point if they might be directly imported by consumers. - Register Ecosystem in Builder:
- Open
packages/builder/src/core/ecosystemManager.ts
. - Import the new adapter class (e.g.,
import { SuiAdapter } from '@openzeppelin/contracts-ui-builder-adapter-sui';
). - Add a new entry to the
ecosystemRegistry
object. This entry defines:networksExportName
: The string name of the exported network list (e.g., 'suiNetworks'). This is used by theEcosystemManager
to dynamically load all network configurations for an ecosystem.AdapterClass
: The constructor of your adapter (e.g.,SuiAdapter as AnyAdapterConstructor
).
- Add a case for your new ecosystem in the
switch
statement withinloadAdapterPackageModule
to enable dynamic import of your adapter package module (which should export theAdapterClass
and thenetworksExportName
list). - Note: If the adapter requires specific package dependencies for exported projects (beyond its own runtime dependencies), these are typically managed by the
PackageManager
configuration within the adapter package itself (e.g., anadapter.config.ts
file exporting dependency details).
- Open
- Workspace: Ensure the new package is included in the
pnpm-workspace.yaml
(if not covered bypackages/*
). - Build & Test:
- Build the new adapter package (
pnpm --filter @openzeppelin/contracts-ui-builder-adapter-<chain-name> build
). - Add relevant unit/integration tests.
- Ensure the builder application (
pnpm --filter @openzeppelin/contracts-ui-builder-app build
) and the export system still function correctly.
- Build the new adapter package (
This project follows Conventional Commits. See COMMIT_CONVENTION.md for more details.
Example:
feat(ui): add button component
Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.
Please read SECURITY.md for details on our security policy and how to report vulnerabilities.
This project is licensed under the MIT License - see the LICENSE file for details.
This project uses GitHub Actions for continuous integration and delivery:
- CI Workflow: Runs tests, linting, and type checking for all packages
- Coverage Workflow: Generates and uploads test coverage reports
- Release Workflow: Manages versioning and releases using Changesets
- Renderer Publish Workflow: Builds and tests the renderer package automatically when changes are merged to main
- Security Workflow: Checks for security vulnerabilities
- Dependencies Workflow: Checks for outdated dependencies
- Update Dependencies Workflow: Automatically updates dependencies
The project uses Changesets for managing package versions and releases. All public packages in the monorepo are published to the npm registry.
The publishing process:
- Developers create changesets for their changes using
pnpm changeset
- Changesets are committed alongside the code changes
- When changes are pushed to the main branch, the GitHub Action:
- Creates a "Version Packages" PR that aggregates all changesets
- Updates package versions according to the changesets
- Updates changelogs for affected packages
- When the Version Packages PR is merged:
- Packages are automatically published to npm
- Git tags are created for each published package version
- GitHub releases are created with changelogs
To create a changeset for your changes:
pnpm changeset
This will prompt you to:
- Select which packages have changed
- Specify the type of change (major, minor, patch)
- Provide a description of the changes for the changelog
This project uses a centralized configuration approach to maintain consistency across all packages:
- tailwind.config.cjs: Root configuration for Tailwind CSS, used by all packages
- postcss.config.cjs: Root configuration for PostCSS, used by all packages
- components.json: Root configuration for shadcn/ui components, referenced by packages
Packages consume these root configs via:
- JS proxy files (
packages/*/tailwind.config.cjs
andpackages/*/postcss.config.cjs
) that require the root configs - Per-package
components.json
files (regular JSON) that reference the package CSS entry (e.g.,../styles/global.css
)
During the export process, proxy configs and JSON are included to create standalone configuration files for the exported project.
Both the main Contracts UI Builder application and its exported forms support runtime configuration for certain parameters. This is primarily managed via an AppConfigService
and allows customization without rebuilding the application code.
During development of the builder application, configurations are typically provided via Vite environment variables defined in .env
files (e.g., .env.local
). These variables usually follow a prefix like VITE_APP_CFG_...
.
Key configurable items include:
- Explorer API Keys: For services like Etherscan, PolygonScan, etc., used by adapters to fetch ABIs. Example:
VITE_APP_CFG_API_KEY_ETHERSCAN_MAINNET="your_key"
. - WalletConnect Project ID: For EVM adapter's WalletConnect functionality. Example:
VITE_APP_CFG_SERVICE_WALLETCONNECT_PROJECT_ID="your_id"
. - RPC URL Overrides: To use custom RPC endpoints instead of public defaults for specific networks. Example:
VITE_APP_CFG_RPC_ENDPOINT_ETHEREUM_MAINNET="https://your_custom_rpc.com"
.
Exported forms include a public/app.config.json
file. Users of the exported form should edit this file to provide their own API keys and RPC URLs.
The structure of this JSON file includes sections for:
networkServiceConfigs
: For explorer API keys, keyed by a service identifier (e.g.,"etherscan-mainnet"
).globalServiceConfigs
: For global service parameters (e.g.,walletconnect.projectId
).rpcEndpoints
: For RPC URL overrides, keyed by the network ID (e.g.,"ethereum-mainnet"
).
Refer to the README included with the exported application for detailed instructions on configuring public/app.config.json
.
When adding new EVM network definitions (in packages/adapter-evm/src/networks/
), ensure you define:
id
: A unique string identifier (e.g., "my-custom-chain-mainnet").chainId
: The numeric EVM chain ID.rpcUrl
: A default public RPC URL.primaryExplorerApiIdentifier
: A string (e.g., "mychainscan-mainnet") that will be used as the key inapp.config.json
'snetworkServiceConfigs
if this network's explorer requires an API key for ABI fetching.apiUrl
andexplorerUrl
for the block explorer.
If this network is also to be a chain-switchable target within Wagmi (for the EVM adapter), you may need to update the defaultSupportedChains
array and the viemChainIdToAppNetworkIdMap
in packages/adapter-evm/src/wallet/wagmi-implementation.ts
to ensure RPC overrides from app.config.json
apply correctly to Wagmi's transports for this chain.
The @openzeppelin/contracts-ui-builder-adapter-midnight
package handles integration with the Midnight ecosystem, specifically the Lace wallet. Integrating with the Midnight wallet requires special handling due to its unique, non-blocking connection flow, which differs from many other wallet APIs.
Key characteristics of the Midnight wallet integration:
- Non-Blocking
enable()
: The wallet'senable()
method resolves immediately, returning a "pre-flight" API object before the user has granted or denied connection permissions. - State Polling: To manage this, the adapter implements a state-polling mechanism. After
enable()
is called, the adapter repeatedly checks the wallet's state until the user approves the connection. - Explicit Disconnect Handling: The wallet's API does not provide a programmatic
disconnect
function. The adapter simulates disconnection by setting a flag inlocalStorage
to prevent automatic reconnection in subsequent sessions, respecting the user's intent to disconnect.
This implementation ensures a robust and user-friendly connection experience despite the underlying API's unconventional behavior. For a detailed look at the implementation, see the MidnightWalletProvider.tsx
component within the adapter package.
The @openzeppelin/contracts-ui-builder-adapter-evm
package offers robust integration with EVM wallets, leveraging the wagmi
library. It features an enhanced architecture for UI kit integration, providing:
- Stable UI Rendering: A new internal architecture (
EvmUiKitManager
andEvmWalletUiRoot
) significantly reduces UI flickering during network switches when using supported UI kits. - Support for UI Kits (e.g., RainbowKit): Easily integrate popular Wagmi-based UI kits like RainbowKit.
- Flexible Configuration: Configure your chosen UI kit through a layered system involving global application settings (via
app.config.json
or environment variables), detailed kit-specific parameters in user-authored native TypeScript configuration files (e.g.,src/config/wallet/rainbowkit.config.ts
), and programmatic overrides. - Automatic Asset Loading: For supported kits like RainbowKit, necessary CSS and JavaScript assets are loaded dynamically by the adapter.
- Custom UI Option: Retains support for a default set of custom-styled wallet components if no third-party kit is preferred.
For comprehensive details on configuring the EVM adapter's wallet module, setting up UI kits like RainbowKit, understanding the configuration flow, and the pattern for extending support to other UI kits, please refer to the dedicated EVM Adapter Wallet Module README.