The Universal Web3 package manager, a clean wrapper around wagmi and viem, designed to simplify connection, network, and contract handling for any blockchain.
- Simple provider-based architecture
- Unified hooks for account, connection, and contract interactions
- Support for multiple networks (Ethereum, Sui, etc.)
- Flexible chain configuration system
npm install @web3-blocks/dapp-ui- Clone the repo and install dependencies:
npm install - Build the package:
npm run build(auto-generates network types and registry) - Run tests:
npm run test - Prefer small, focused PRs with clear descriptions and updated docs.
- Location:
src/networks/<network>(folder name becomes theNetworkId) - Structure:
index.ts: default export implementingNetworkImpl(hooks wiring)hooks/:useAccount,useConnect,useDisconnect,useNetwork,useContractconfig.ts: network-specificwagmi/viemconfig, clients, connectorsclients/: optional helpers and client builders- Types: Use shared types from
src/core/types(AccountState,ConnectState,DisconnectState,NetworkState). Avoidany. - Runtime guards: Use utilities from
src/utils/typeGuards(EIP‑1193 detection, chain helpers). - Chain support logic:
isSupportedChainmust check currentchainIdagainstDappUiProviderchains- When unsupported, set
NetworkState.errorand return a descriptivegetUnsupportedMessage() - Wrap
switch(chainId: number)to switch to supported chains by id
- Auto-generated at build time:
src/core/networkIds.ts—export type NetworkId = '...'andNETWORK_IDSsrc/core/registry.ts— dynamic imports mapping for available networks- How it works:
- Script scans folder names under
src/networks/* - Runs on
prebuildand vianpm run generate:networks - Naming conventions:
- Use lowercase folder names, optionally
kebab-case - Folder name is the canonical
NetworkIdused inDappUiProvider
- Create
src/networks/<your-network>/ - Implement
index.tsexporting adefaultNetworkImpl - Add hooks in
hooks/(shape must match shared types) - Provide network
config.tsfor clients/connectors if applicable - Run
npm run buildto generate types/registry - Use in app:
<DappUiProvider network="<your-network>" ... />
- Unit tests: add scenarios under
tests/network/for validation behavior - Type tests: add assertions under
tests/types/usingvitest - Suggested areas:
- Unsupported chain detection (
isChainSupportedfalse with mismatched ids) - Supported chain detection (
isChainSupportedtrue) - Type generation correctness (
NETWORK_IDSequals folder names) - Provider typing (
DappUiProviderProps.networkisNetworkId)
- IDE autocompletion:
NetworkIdandNETWORK_IDSexported for visibility - Auto-inclusion: New network folders are detected at build — no manual registry edits needed
- Migration: Replace string
networkwith typedNetworkId; the folder name you add is the value you use - Error UX: Use
network.getUnsupportedMessage()and checknetwork.errorwhen mismatched
- Build succeeds:
npm run build - Tests pass:
npm run test - Documentation updated: README includes usage and contributor guidance
- No
anytypes introduced; hooks and components use shared interfaces
import { DappUiProvider, useAccount, useConnect } from '@web3-blocks/dapp-ui';
import { mainnet } from 'viem/chains';
function App() {
return (
<DappUiProvider
network="ethereum"
contract={{
address: '0x1234567890123456789012345678901234567890',
abi: [...],
}}
>
<YourApp />
</DappUiProvider>
);
}You can now provide custom chains to the DappUiProvider:
import { DappUiProvider } from '@web3-blocks/dapp-ui';
import { mainnet, sepolia, optimism } from 'viem/chains';
function App() {
return (
<DappUiProvider
network="ethereum"
chains={[mainnet, sepolia, optimism]} // Custom chain configuration
contract={{
address: '0x1234567890123456789012345678901234567890',
abi: [...],
}}
>
<YourApp />
</DappUiProvider>
);
}The chains prop accepts an array of chain objects from viem/chains. If not provided, the library will default to using mainnet.
The main provider component that sets up the Web3 context.
Props:
network(NetworkId): Strongly-typed network identifier (e.g.,"ethereum","sui"). IDE autocompletes based on folders insrc/networks.chains(Chain[], required): At least one chain must be supplied (recommended default:mainnetfromviem/chains).contract(ContractData): The contract data (address and ABI)children(ReactNode): Child components
useAccount(): Get the current account informationuseConnect(): Connect to a walletuseDisconnect(): Disconnect from a walletuseNetwork(): Get network informationuseContract(): Interact with the configured contract
The library includes comprehensive error handling for chain configuration:
- Invalid chain configurations will throw descriptive errors
- The provider includes error state handling
- All contract interactions include proper error handling
All components and hooks are fully typed with TypeScript, ensuring type safety throughout your application.
The useEthereum() hook returns a UseEthereumResult with strictly typed slices:
account: AccountStateconnect: ConnectStatedisconnect: DisconnectStatenetwork: NetworkState
Key fields:
connect.isWalletAvailable: boolean— detected via a runtime EIP‑1193 provider checkconnect.fn(connector?: Connector): Promise<void>— initiates wallet connectiondisconnect.fn(): Promise<void>— disconnects the current walletnetwork.switch(chainId: number)— switches to a supported chain by id
hasEthereumProvider(value): value is Eip1193Provider— verifies a minimal EIP‑1193 provider shape.getWalletAvailability(): boolean— uses the guard to detect wallet availability at runtime.isChainSupported(chainId, chains): boolean— returns whether current chain id is in provider-supported chains.getSupportedChainById(chainId, chains): Chain | undefined— returns the chain object if supported.getUnsupportedChainMessage(chainId, chains): string— user-friendly message for mismatch.getCurrentChainInfo(chainId, chains): { isSupported, chain?, message? }— consolidated helper.
- Mandatory: Provide at least one chain in the
chainsprop. - Recommended: Use
mainnetfromviem/chainsas your default. - Validation: Initialization throws an error if
chainsis missing or empty. - Console warnings:
- When no chains are provided
- When chain verification fails for the current wallet chain
import { DappUiProvider } from '@web3-blocks/dapp-ui';
import { mainnet, base, liskSepolia } from 'viem/chains';
function App() {
return (
<DappUiProvider
network="ethereum"
chains={[mainnet, base]} // At least one chain required
>
<YourApp />
</DappUiProvider>
);
}// Single-chain setup (recommended default mainnet)
<DappUiProvider network="ethereum" chains={[mainnet]}>
<YourApp />
</DappUiProvider>- Compares the user's current wallet chain to
chainsprovided to the provider. - Returns
trueonly if the current chain matches one of the configured chains. - Returns
falsewhen:- The current chain is not in the list
- The current chain value is undefined or invalid
- Formats differ (hex vs decimal) — normalization is applied before comparison
- Utilities:
verifyChainMatch(currentChain, providerChains): booleannormalizeChainId(chainId): number | nullisChainSupported(chainId, chains): boolean
- During build, a script scans
src/networks/*and generates:src/core/networkIds.ts—export type NetworkId = '...'andNETWORK_IDSarraysrc/core/registry.ts—export const networkRegistry = { ... }with dynamic imports
- This enables IDE autocompletion for
network, and automatically incorporates new networks when contributors add folders.
- Create a folder under
src/networks/<your-network>with its implementation. - Run
npm run build(ornpm run generate:networks) to regenerate types and registry. - Use in provider:
network="<your-network>".
- All network operations are compile-time checked via
NetworkId. - Clear error messages for unsupported networks through
network.errorandgetUnsupportedMessage(). - Type generation occurs only during build (
prebuild), minimizing runtime overhead.