Multichain Configuration
Relevant source files
The following files were used as context for generating this wiki page:
Multichain Configuration in the walletless library allows developers to simulate a production-like environment where a DApp interacts with multiple blockchain networks simultaneously. This system manages per-chain RPC routing, stateful chain switching, and internal wallet client synchronization to ensure that testing remains deterministic across different network contexts.
The library supports configuring a list of CompatibleChain objects and a mapping of RPC URLs. When a chain switch is triggered—either via standard EIP-1193 RPC calls like wallet_switchEthereumChain or internal control methods—the provider automatically updates its internal transport layer and notifies the DApp through standard event emitters.
Sources: README.md:143-162, src/provider.ts:166-177
Core Configuration Structure
The multichain behavior is defined during the initialization of either the createE2EProvider or the e2eConnector. The configuration relies on two primary fields: a list of supported chains and a mapping of RPC endpoints.
Configuration Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
chains | readonly CompatibleChain[] | [mainnet] | A list of networks the provider can interact with. The first element becomes the default chain. |
rpcUrls | Record<number, string> | {} | A map of chainId to RPC endpoints (e.g., Anvil instances). Defaults to http://127.0.0.1:8545 for missing IDs. |
Sources: src/types.ts:24-38, src/provider.ts:161-175, src/constants.ts:4
Data Models
The system uses the CompatibleChain type, which extends the standard viem Chain interface to ensure compatibility with both internal logic and external libraries like Wagmi.
Sources: src/types.ts:6-12
Architecture and Data Flow
The architecture employs a "Man-in-the-Middle" pattern. When a request is made, the provider determines if it is a read, write, or wallet-state operation. For multichain environments, the currentChain and rpcUrl in the internal state dictate where requests are routed.
The internal state manager ensures that the walletClient (used for signing) and the transport layer are always synchronized with the selected network.
Sources: README.md:14-25, src/provider.ts:145-155, src/provider.ts:446-455
Chain Switching Logic
Chain switching can be initiated through two primary flows: the standard EIP-1193 RPC interface and the developer-focused control API.
1. EIP-1193: wallet_switchEthereumChain
When the DApp requests a chain switch via provider.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: '0x...' }] }):
- The provider validates the
chainIdagainst thesupportedChainIdsin the internal state. - If valid, it updates the
currentChainand retrieves the corresponding RPC URL from therpcUrlsmap. - The
walletClientis recreated with the new chain configuration. - It emits the
chainChangedevent with the new hex chain ID.
Sources: src/provider.ts:413-437, test/provider.spec.ts:140-165
2. Control API: setChain()
Developers can force a chain switch during tests using the setChain helper. This is particularly useful in E2E environments like Playwright to simulate network changes from the test runner.
Sources: src/provider.ts:543-561, README.md:204-210
Multi-RPC Routing
The provider maintains a mapping of RPC URLs to support multiple local Anvil instances or different forks.
const provider = createE2EProvider({
chains: [mainnet, arbitrum],
rpcUrls: {
1: "http://localhost:8545", // Mainnet Anvil
42161: "http://localhost:8546", // Arbitrum Anvil
},
});
- Fallback Behavior: If a chain is configured in the
chainsarray but its ID is missing fromrpcUrls, the provider falls back toDEFAULT_ANVIL_RPC_URL(http://127.0.0.1:8545). - Dynamic Updates: Read operations like
eth_callare automatically routed to the RPC URL associated with the currentinternal.rpcUrl.
Sources: src/provider.ts:175-180, src/constants.ts:4, test/provider.spec.ts:316-335
Integration with Wagmi Connector
The e2eConnector wraps the provider and facilitates multichain synchronization with Wagmi's internal state.
- Initialization: The connector can either create a provider internally or accept an
externalProvider. - Event Forwarding: The connector listens to the provider's
chainChangedevents and emits achangeevent to Wagmi's emitter, ensuring the UI reflects the network change. - Wagmi switchChain: Implementing
switchChainin the connector calls the provider'swallet_switchEthereumChainmethod to ensure the underlying virtual wallet and the Wagmi store remain in sync.
Sources: src/connector.ts:133-140, src/connector.ts:203-219
Conclusion
Multichain Configuration in walletless provides a robust framework for testing complex cross-chain DApp behaviors. By centralizing chain metadata, RPC routing, and event emission, it allows developers to switch between networks (e.g., Mainnet to Arbitrum) while maintaining local control over signing and state, effectively eliminating the need for manual network configuration in browser extensions during E2E test execution.