mipd eip6963工具封装
DEMO

Site
代码分析
这段代码定义了一组用于管理和处理 EIP-1193 提供者(Provider)的类型和函数。EIP-1193 是一个以太坊标准,用于定义与区块链交互的提供者接口。这些提供者通常是钱包应用程序,如 MetaMask、Coinbase Wallet 等。
以下是代码的详细分析:
1. 导出类型和函数
export type { DefaultRegister, EIP1193Provider, Rdns, Register, ResolvedRegister } from './register.js';
export { createStore, type Listener, type Store } from './store.js';
export type { EIP6963AnnounceProviderEvent, EIP6963ProviderDetail, EIP6963ProviderInfo, EIP6963RequestProviderEvent } from './types.js';
export {
type AnnounceProviderParameters,
type AnnounceProviderReturnType,
announceProvider,
type RequestProvidersParameters,
type RequestProvidersReturnType,
requestProviders,
} from './utils.js';
这些导出语句将其他模块中的类型和函数重新导出,以便在其他地方使用。具体来说:
register.js中导出的类型包括DefaultRegister,EIP1193Provider,Rdns,Register,ResolvedRegister。store.js中导出的函数和类型包括createStore,Listener,Store。types.js中导出的类型包括EIP6963AnnounceProviderEvent,EIP6963ProviderDetail,EIP6963ProviderInfo,EIP6963RequestProviderEvent。utils.js中导出的函数和类型包括announceProvider,requestProviders及其相关类型。
2. 定义和扩展 Register 接口
export interface Register {}
export type DefaultRegister = {
provider: import('viem').EIP1193Provider;
rdns: 'com.coinbase' | 'com.enkrypt' | 'io.metamask' | 'io.zerion';
};
export type ResolvedRegister = {
provider: Register extends {
provider: infer provider extends DefaultRegister['provider'];
}
? provider
: DefaultRegister['provider'];
rdns: Register extends { rdns: infer rdns extends string } ? rdns : DefaultRegister['rdns'] | (string & {}); // loose autocomplete
};
export type EIP1193Provider = ResolvedRegister['provider'];
export type Rdns = ResolvedRegister['rdns'];
这些类型定义了一个 Register 接口和一些相关的类型:
DefaultRegister定义了默认的注册类型,包括provider和rdns(反向域名表示)。ResolvedRegister通过条件类型从Register接口中推导出provider和rdns的类型。EIP1193Provider和Rdns是从ResolvedRegister中提取的类型。
3. 创建和管理存储
export function createStore(): Store {
const listeners: Set<Listener> = new Set();
let providerDetails: readonly EIP6963ProviderDetail[] = [];
const request = () =>
requestProviders((providerDetail) => {
if (providerDetails.some(({ info }) => info.uuid === providerDetail.info.uuid)) return;
providerDetails = [...providerDetails, providerDetail];
listeners.forEach((listener) => listener(providerDetails, { added: [providerDetail] }));
});
let unwatch = request();
return {
_listeners() {
return listeners;
},
clear() {
listeners.forEach((listener) => listener([], { removed: [...providerDetails] }));
providerDetails = [];
},
destroy() {
this.clear();
listeners.clear();
unwatch?.();
},
findProvider({ rdns }) {
return providerDetails.find((providerDetail) => providerDetail.info.rdns === rdns);
},
getProviders() {
return providerDetails;
},
reset() {
this.clear();
unwatch?.();
unwatch = request();
},
subscribe(listener, { emitImmediately } = {}) {
listeners.add(listener);
if (emitImmediately) listener(providerDetails, { added: providerDetails });
return () => listeners.delete(listener);
},
};
}
createStore 函数创建了一个存储对象,用于管理提供者详情和监听器。存储对象包含以下方法:
_listeners: 返回当前的监听器集合。clear: 清除所有提供者详情,并通知所有监听器。destroy: 销毁存储,包括清除所有详情 和监听器。findProvider: 根据rdns查找特定的提供者详情。getProviders: 返回所有提供者详情。reset: 重置存储,并重新请求提供者详情。subscribe: 订阅提供者详情的变化,并返回一个取消订阅的函数。
4. 定义事件和实用函数
export interface EIP6963ProviderDetail<TProvider = EIP1193Provider, TRdns extends string = Rdns> {
info: EIP6963ProviderInfo<TRdns>;
provider: TProvider;
}
export interface EIP6963ProviderInfo<TRdns extends string = Rdns> {
icon: `data:image/${string}`;
name: string;
rdns: TRdns;
uuid: string;
}
export interface EIP6963AnnounceProviderEvent<TProvider = EIP1193Provider> extends CustomEvent<EIP6963ProviderDetail<TProvider>> {
type: 'eip6963:announceProvider';
}
export interface EIP6963RequestProviderEvent extends Event {
type: 'eip6963:requestProvider';
}
这些接口定义了 EIP-6963 事件和提供者详情的结构:
EIP6963ProviderDetail包含提供者信息和提供者实例。EIP6963ProviderInfo包含提供者的元数据。EIP6963AnnounceProviderEvent和EIP6963RequestProviderEvent定义了相应的事件类型。
export function announceProvider(detail: AnnounceProviderParameters): AnnounceProviderReturnType {
const event: CustomEvent<EIP6963ProviderDetail> = new CustomEvent('eip6963:announceProvider', { detail: Object.freeze(detail) });
window.dispatchEvent(event);
const handler = () => window.dispatchEvent(event);
window.addEventListener('eip6963:requestProvider', handler);
return () => window.removeEventListener('eip6963:requestProvider', handler);
}
export function requestProviders(listener: RequestProvidersParameters): RequestProvidersReturnType {
if (typeof window === 'undefined') return;
const handler = (event: EIP6963AnnounceProviderEvent) => listener(event.detail);
window.addEventListener('eip6963:announceProvider', handler);
window.dispatchEvent(new CustomEvent('eip6963:requestProvider'));
return () => window.removeEventListener('eip6963:announceProvider', handler);
}
announceProvider 和 requestProviders 是两个用于处理提供者事件的实用函数:
announceProvider用于宣布一个新的提供者,触发eip6963:announceProvider事件,并监听eip6963:requestProvider事件。requestProviders用于请求提供者详情,监听eip6963:announceProvider事件,并触发eip6963:requestProvider事件。
5. 扩展全局事件映射
declare global {
interface WindowEventMap {
'eip6963:announceProvider': EIP6963AnnounceProviderEvent;
'eip6963:requestProvider': EIP6963RequestProviderEvent;
}
}
这段代码扩展了全局 WindowEventMap 接口,以便在 TypeScript 中能够正确识别 eip6963:announceProvider 和 eip6963:requestProvider 事件。
总结
这段代码通过定义类型、接口和实用函数,提供了一套完整的机制来管理和处理 EIP-1193 提供者。这些提供者通常是区块链钱包,代码中的机制允许应用程序宣布、请求和管理这些提供者的详情。