Events & Listeners
Relevant source files
The following files were used as context for generating this wiki page:
Events and listeners in the Walletless library facilitate communication between the virtual EIP-1193 provider and the consuming application (such as a DApp or a Wagmi connector). This system ensures that changes in the provider's internal state—such as account switching, chain updates, or connection status—are immediately propagated to the UI or the underlying blockchain framework.
The event system is built into the createE2EProvider factory, providing a standardized way to subscribe to and emit EIP-1193 compliant events. This is critical for E2E testing scenarios where the test runner needs to simulate user interactions like switching wallets or disconnecting from a site.
Architecture and Event Handling
The provider manages events using an internal EventListeners structure, which maps specific event names to sets of listener functions. This implementation supports multiple listeners for the same event and provides methods for both subscription (on) and unsubscription (removeListener).
Core Event Lifecycle
When a state change is triggered—either through an RPC call like wallet_switchEthereumChain or a control method like setSigningAccount—the provider updates its internal state and calls the emit function. The emit function iterates through all registered listeners for that specific event type and executes them with the relevant data.
Supported Events
The library implements standard EIP-1193 events required for Ethereum provider compatibility.
| Event Name | Parameter Type | Description |
|---|---|---|
accountsChanged | Address[] | Emitted when the active signing account is updated. |
chainChanged | Hex | Emitted when the provider switches to a different blockchain. |
connect | { chainId: Hex } | Emitted on the first successful account request. |
disconnect | { code: number; message: string } | Emitted when the provider is manually disconnected. |
message | { type: string; data: unknown } | Generic event for passing provider-specific messages. |
Sources: src/types.ts:77-83, src/provider.ts:136-142
Internal Event Flow
The following sequence diagram illustrates how an account change triggered by a test runner propagates through the system to a Wagmi-configured UI.
Event Subscription API
The E2EProvider interface exposes standard methods for managing event subscriptions.
Subscription Methods
on(event, listener): Adds a listener to the internalSetfor the specified event.removeListener(event, listener): Removes a specific listener from the internalSet.emit(event, ...args): Manually triggers all listeners associated with an event (primarily used internally or by control helpers).
Sources: src/types.ts:98-105, src/provider.ts:452-463
Connector Integration
When used within the e2eConnector for Wagmi, the connector sets up internal listeners during its setup() phase. It bridges the E2EProvider events to Wagmi's internal emitter.
// Example of event bridging in the connector
async setup(): Promise<void> {
if (externalProvider) {
externalProvider.on("accountsChanged", (accounts: Address[]) => {
config.emitter.emit("change", {
accounts: accounts.map((x) => getAddress(x)),
});
});
// ... similar for chainChanged and disconnect
}
}
Sources: src/connector.ts:115-131
Triggering Events via Control Methods
Walletless provides several "Control Methods" that are designed to be used in E2E tests (often via page.evaluate()). These methods are the primary way developers trigger events during a test run.
setSigningAccount(account): Updates the signing account and emitsaccountsChanged.setChain(chainId): Validates the chain, updates RPC endpoints, and emitschainChanged.disconnect(): Emits thedisconnectevent with EIP-1193 error code4900.
Sources: src/provider.ts:468-498, src/provider-controls.ts:1-40
Conclusion
The Events & Listeners system in Walletless serves as the backbone for reactive state management. By adhering to EIP-1193 standards, it ensures that the virtual provider behaves exactly like a real browser extension wallet, allowing DApps to react naturally to account and network changes during automated testing.
Summary of significance:
- Realism: Mimics browser wallet behavior (Metamask, etc.).
- Synchronization: Keeps the DApp UI and the provider state in sync.
- Testability: Allows deterministic testing of complex flows like "User switches account mid-transaction".
Sources: src/provider.ts:101-115, test/provider.spec.ts:162-185