Skip to content
/ mipd Public

TypeScript Utilities for EIP-6963: Multi Injected Provider Discovery

License

Notifications You must be signed in to change notification settings

wevm/mipd

Repository files navigation


mipd logo

TypeScript Utilities for EIP-6963: Multi Injected Provider Discovery

Contents

Install

npm i mipd
pnpm add mipd
yarn add mipd

Store

The MIPD Store stores the Providers that have been emitted by a Wallet (or other source), and provides a way to subscribe to the store and retrieve the Providers.

Overview

import { createStore } from 'mipd'

// Set up a MIPD Store, and request Providers.
const store = createStore()

// Subscribe to the MIPD Store.
store.subscribe(providerDetails => {
  console.log(providerDetails)
  // => [EIP6963ProviderDetail, EIP6963ProviderDetail, ...]
})

// Retrieve emitted Providers.
store.getProviders()
// => [EIP6963ProviderDetail, EIP6963ProviderDetail, ...]

// Find a Provider Detail.
store.findProvider({ rdns: 'com.example' })
// => EIP6963ProviderDetail | undefined

// Clear the store, including all Providers.
store.clear()

// Reset the store, and emit an event to request Providers.
store.reset()

// Destroy the store, and remove all Providers and event listeners.
store.destroy()

Usage

Vanilla JS

import { createStore } from 'mipd'

const store = createStore()

let providers = store.getProviders()
store.subscribe(providerDetails => (providers = providerDetails))

React

import { useSyncExternalStore } from 'react'
import { createStore } from 'mipd'

const store = createStore()

function Example() {
  const providers = useSyncExternalStore(store.subscribe, store.getProviders)
  // ...
}

Svelte

<script lang="ts">
  import { readable } from 'svelte/store'
  import { createStore } from 'mipd'
  
  const store = createStore()
  const providers = readable(store.getProviders(), store.subscribe)
</script>

<!-- ... -->

Vue

<script setup lang="ts">
  import { reactive } from 'vue'
  import { createStore } from 'mipd'

  const store = createStore()
  const state = reactive({ providers: store.getProviders() })
  store.subscribe(providers => (state.providers = providers))
</script>

<!-- ... -->

API

createStore()

Creates a MIPD Store, and emits an event to request Providers from the Wallet(s).

const store = createStore()

store.subscribe(listener, args)

Subscribes to the MIPD Store, and returns a function to unsubscribe.

const unsubscribe = store.subscribe(providers => {
  console.log(providers)
  // => [EIP6963ProviderDetail, EIP6963ProviderDetail, ...]
})

Definition

export type Listener = (
  // The updated Providers store.
  providerDetails: EIP6963ProviderDetail[],
  meta?: {
    // The Providers that were added to the store.
    added?: EIP6963ProviderDetail[]
    // The Providers that were removed from the store.
    removed?: EIP6963ProviderDetail[]
  },
) => void

function subscribe(
  // The listener function.
  listener: Listener, 
  args?: { 
    // If `true`, the listener will be called immediately with the stored Providers.
    emitImmediately?: boolean 
  }
): () => void // Returns an unsubscribe function.

store.getProviders()

Returns the current Providers.

const providers = store.getProviders()
// => [EIP6963ProviderDetail, EIP6963ProviderDetail, ...]

Definition

function getProviders(): EIP6963ProviderDetail[]

store.findProvider(args)

Finds a provider detail by its RDNS (Reverse Domain Name Identifier).

const provider = store.findProvider({ rdns: 'com.example' })

Definition

function findProvider(args: { 
  // The RDNS of the Provider Detail to find.
  rdns: string 
}): EIP6963ProviderDetail | undefined

store.clear()

Clears the store, including all Providers.

store.clear()

Definition

function clear(): void

store.reset()

Resets the store, and emits an event to request Providers from the Wallet(s).

store.reset()

Definition

function reset(): void

store.destroy()

Destroys the store, and removes all Providers and event listeners.

store.destroy()

Definition

function destroy(): void

Utilities

requestProviders

The requestProviders utility emits an event to request Providers from the Wallet(s). It returns an unsubscribe function to clean up event listeners.

import { requestProviders } from 'mipd'

let providers = []

const unsubscribe = requestProviders(providerDetail => providers.push(providerDetail))

Definition

function requestProviders(
  // The listener.
  listener: (providerDetail: EIP6963ProviderDetail) => void
// Unsubscribe function to clean up the listener.
): () => void

announceProvider

The announceProvider utility emits an event to announce a Provider to the Wallet(s), and also listen for incoming requests. It returns an unsubscribe function to clean up event listeners.

import { announceProvider } from 'mipd'

const unsubscribe = announceProvider({
  info: {
    icon: 'data:image/svg+xml,<svg width="32px" height="32px" viewBox="0 0 32 32"/>',
    name: 'Example',
    rdns: 'com.example',
    uuid: '00000000-0000-0000-0000-000000000000'
  },
  provider: new EIP1193Provider()
})

Definition

function requestProviders(
  // The EIP-1193 Provider and Provider Info.
  detail: EIP6963ProviderDetail
// Unsubscribe function to clean up the listener.
): () => void

window Polyfill

By importing the mipd/window Polyfill, the types on window.addEventListener will be inferred to include the EIP6963AnnounceProviderEvent and EIP6963RequestProviderEvent types.

import 'mipd/window'

window.addEventListener(
  'eip6963:announceProvider'
  // ^? 'eip6963:announceProvider' | 'eip6963:requestProvider' | 'click' | ...

  event => {
  // ^? EIP6963AnnounceProviderEvent

    event.type
    //    ^? 'eip6963:announceProvider'
    event.detail
    //    ^? EIP6963ProviderDetail
    event.detail.info
    //           ^? EIP6963ProviderInfo
    event.detail.provider
    //           ^? EIP1193Provider
  }
)

window.addEventListener(
  'eip6963:requestProvider'
  // ^? 'eip6963:announceProvider' | 'eip6963:requestProvider' | 'click' | ...

  event => {
  // ^? EIP6963RequestProviderEvent

    event.type
    //    ^? 'eip6963:requestProvider'
  }
)

Types

EIP6963ProviderDetail

Event detail from eip6963:announceProvider.

Import

import { type EIP6963ProviderDetail } from 'mipd'

Definition

export interface EIP6963ProviderDetail<TProvider = Config['EIP1193Provider']> {
  info: EIP6963ProviderInfo
  provider: TProvider
}

EIP6963ProviderInfo

Metadata of the EIP-1193 Provider.

Import

import { type EIP6963ProviderInfo } from 'mipd'

Definition

export interface EIP6963ProviderInfo {
  icon: string
  name: string
  rdns?: ... | (string & {})
  uuid: string
}

EIP6963AnnounceProviderEvent

Event type to announce an EIP-1193 Provider.

Import

import { type EIP6963AnnounceProviderEvent } from 'mipd'

Definition

export interface EIP6963AnnounceProviderEvent<TProvider = DefaultProvider>
  extends CustomEvent<EIP6963ProviderDetail<TProvider>> {
  type: 'eip6963:announceProvider'
}

EIP6963RequestProviderEvent

Event type to request EIP-1193 Providers.

Import

import { type EIP6963RequestProviderEvent } from 'mipd'

Definition

export interface EIP6963RequestProviderEvent extends Event {
  type: 'eip6963:requestProvider'
}

Configuration

In some cases you might want to tune the global types (e.g. the EIP1193Provider). To do this, the following configuration options are available:

Type Default Description
provider import('viem').EIP1193Provider The EIP-1193 Provider.
rdns 'com.coinbase' | 'com.enkrypt' | 'io.metamask' | 'io.zerion' | (string & {}) Deterministic identifier for the Provider in the form of an rDNS (Reverse Domain Name Notation)

Configuration options are customizable using declaration merging. Extend the Register interface either directly in your code or in a d.ts file (e.g. eip6963.d.ts):

import { type EIP1193Provider } from './eip1193-provider'

declare module 'mipd' {
  interface Register {
    provider: EIP1193Provider
  }
}

Authors

License

MIT License