EIP-6963 Multi-Injected Provider Discovery Utilities
mipd (Multi Injected Provider Discovery) is a TypeScript utility library from the wevm (formerly wagmi-dev) ecosystem, designed to facilitate the discovery and management of EIP-6963 compliant Ethereum wallet providers within dapps. EIP-6963 standardizes how multiple injected wallets announce themselves via custom DOM events, moving beyond the single `window.ethereum` paradigm. Currently at version 0.0.7, mipd offers a reactive store (`createStore`) that accumulates announced `EIP6963ProviderDetail` objects and allows dapps to subscribe to updates or retrieve the current list of providers. It includes essential TypeScript types such as `EIP6963ProviderDetail` and `EIP6963AnnounceProviderEvent`, and also provides a `/window` polyfill for enhanced type inference on global event listeners. Its release cadence is likely tied to updates within the broader wevm stack and EIP-6963 evolution. mipd is a foundational component for building robust multi-wallet dapps, complementing libraries like wagmi and viem by abstracting EIP-6963 complexities.
Common errors
-
Property 'detail' does not exist on type 'Event'. Property 'detail' does not exist on type 'CustomEvent<any>'.
cause Attempting to access `event.detail` from an `eip6963:announceProvider` event without `mipd/window` global type augmentation.fixAdd `import 'mipd/window';` to your application's entry file to ensure TypeScript recognizes the `EIP6963AnnounceProviderEvent` type for `CustomEvent` dispatched on `window`. -
TypeError: createStore is not a function (in CommonJS environments)
cause `mipd` is an ESM-first package, and direct `require('mipd')` might not correctly resolve the `createStore` named export in some CommonJS environments without proper transpilation or explicit pathing.fixFor projects that need to use CommonJS `require`, ensure your build tool correctly handles ESM imports from `node_modules`. Alternatively, if applicable, consider migrating to ESM or using dynamic `import('mipd')` within an `async` context. -
TS2345: Argument of type '(providers: EIP6963ProviderDetail[]) => void' is not assignable to parameter of type 'Listener<EIP6963ProviderDetail[]>'.
cause Type incompatibility with `mipdStore.subscribe` listener function, often due to an outdated or incorrect `typescript` version, or incorrect type imports.fixVerify that your project's `typescript` version meets the `mipd` peer dependency (`>=5.0.4`). Ensure `EIP6963ProviderDetail` is imported as a type (`import type { EIP6963ProviderDetail } from 'mipd';`). Review the `mipd` source or documentation for the exact `Listener` type signature.
Warnings
- breaking As a 0.0.x version package, `mipd` is in early development. Minor and patch releases may introduce breaking changes without adhering to strict semantic versioning, particularly as the EIP-6963 standard itself evolves or as it integrates more deeply with other `wevm` libraries.
- gotcha When using `mipd` with TypeScript, ensure you import the global window types via `import 'mipd/window';`. Without this side-effect import, TypeScript may not correctly infer the types for `window.addEventListener` when listening for `eip6963:announceProvider` events, leading to type errors.
- gotcha `mipd` primarily targets modern JavaScript environments and uses ES Modules (ESM). While it provides CommonJS (CJS) bundles, direct `require()` statements might behave differently or require specific bundler configurations, especially in older Node.js environments or complex build setups.
- gotcha The `typescript` peer dependency, listed as `>=5.0.4`, is marked as optional in `mipd`'s `package.json`. While it's not strictly required at runtime, developing with `mipd` without a compatible TypeScript version can lead to compilation errors or incorrect type inferences in your project.
Install
-
npm install mipd -
yarn add mipd -
pnpm add mipd
Imports
- createStore
const { createStore } = require('mipd');import { createStore } from 'mipd'; - EIP6963ProviderDetail
import { EIP6963ProviderDetail } from 'mipd';import type { EIP6963ProviderDetail } from 'mipd'; - EIP6963AnnounceProviderEvent
import { EIP6963AnnounceProviderEvent } from 'mipd';import type { EIP6963AnnounceProviderEvent } from 'mipd'; - Global Window Types
import 'mipd/window';
Quickstart
import { createStore } from 'mipd';
import type { EIP6963ProviderDetail } from 'mipd';
import 'mipd/window'; // Import to augment window types for EIP-6963 events
// Create a new EIP-6963 provider store
const mipdStore = createStore();
// Subscribe to provider changes (e.g., when a wallet announces itself or is removed)
const unsubscribe = mipdStore.subscribe((providers: EIP6963ProviderDetail[]) => {
console.log('EIP-6963 Providers updated:', providers);
if (providers.length > 0) {
console.log('First provider UUID:', providers[0].info.uuid);
console.log('First provider Name:', providers[0].info.name);
// You can now use providers[0].provider for interactions if needed
}
});
// Get current providers immediately
const initialProviders = mipdStore.getProviders();
console.log('Initial EIP-6963 Providers:', initialProviders);
// Example of how you might stop listening after some time (in a real app, this would be on unmount)
setTimeout(() => {
unsubscribe();
console.log('Unsubscribed from mipd store updates.');
}, 10000);
// In a React component (using React 18+ useSyncExternalStore):
// import { useSyncExternalStore } from 'react';
// import { createStore } from 'mipd';
// const store = createStore();
// function MyWalletConnector() {
// const providers = useSyncExternalStore(store.subscribe, store.getProviders);
// return (
// <div>
// <h2>Detected EIP-6963 Wallets:</h2>
// {providers.length === 0 ? (
// <p>No EIP-6963 wallets found.</p>
// ) : (
// <ul>
// {providers.map((providerDetail) => (
// <li key={providerDetail.info.uuid}>
// <img src={providerDetail.info.icon} alt={providerDetail.info.name} width="24" height="24" />
// {providerDetail.info.name} ({providerDetail.info.rdns})
// </li>
// ))}
// </ul>
// )}
// </div>
// );
// }