Web3.js 扩展窗口界面类型定义

Posted

技术标签:

【中文标题】Web3.js 扩展窗口界面类型定义【英文标题】:Web3.js extending the window interface type definitions 【发布时间】:2021-04-06 20:08:14 【问题描述】:

Web3.js web3window 对象中。

MetaMask 这样的浏览器钱包将ethereum 注入到window 对象中。

现在在打字稿中,为了减轻编译错误,我将按如下方式进行转换(window as any).ethereum

查看 Web3 存储库和 Wallet 存储库(例如 MetaMask)后,Window 对象没有可导入/可复制的打字稿定义/接口。

一个可能的解决方案是编写我自己的接口并扩展 Window,查看 Window 对象并尝试推断类型 - 不理想

其他使用过 web3.js 和 typescript 的开发者,您是如何解决 VSCode 中的 Window 类型界面问题和智能感知建议的?

【问题讨论】:

从技术上讲,window.ethereum 是由 MetaMask 或任何其他浏览器内钱包注入的。请注意,其他钱包没有window.ethereum。 ethereum.stackexchange.com/questions/82531/… 谢谢@MikkoOhtamaa 我假设最受欢迎和采用的钱包是将其注入浏览器的钱包。 您的假设不正确。只有浏览器插件钱包可以注入ethereum,而且大部分钱包都是手机钱包。 @MikkoOhtamaa 我已更新问题以反映您的解释,感谢您的澄清。 @MikkoOhtamaa 抱歉,但我的问题不在于扩展 Window 的接口,这在此处记录相对简单:***.com/questions/12709074/… 我更感兴趣的是其他开发人员已经处理了 Web3.js 和 MetaMasks 缺少用于扩展窗口对象的类型的问题。我在 Web3.js 存储库中进行了挖掘,发现了一些类型,其中包括 window.ethereum 上可用的功能,因此这可能是一个不错的起点。 【参考方案1】:

我最近也遇到了这个问题。我找不到合适的typings package from DefinitelyTyped,所以我开始根据我自己的用法和Metamask Documentation 进行推断,并创建了一些迄今为止有效的东西。

也许社区可以用他们自己的贡献来编辑这个答案。

为了在没有TS投诉的情况下使用ethereum对象,我在window对象中声明:

declare global 
    interface Window 
        ethereum: Ethereumish;
    

临时的 Ethereum Provider 类型,Ethereumish 看起来像这样:

import  ProviderMessage, ProviderRpcError, ProviderConnectInfo, RequestArguments  from 'hardhat/types';

export interface EthereumEvent 
    connect: ProviderConnectInfo;
    disconnect: ProviderRpcError;
    accountsChanged: Array<string>;
    chainChanged: string;
    message: ProviderMessage


type EventKeys = keyof EthereumEvent;
type EventHandler<K extends EventKeys> = (event: EthereumEvent[K]) => void;

export interface Ethereumish 
    autoRefreshOnNetworkChange: boolean;
    chainId: string;
    isMetaMask?: boolean;
    isStatus?: boolean;
    networkVersion: string;
    selectedAddress: any;

    on<K extends EventKeys>(event: K, eventHandler: EventHandler<K>): void;
    enable(): Promise<any>;
    request?: (request:  method: string, params?: Array<any> ) => Promise<any>
    /**
     * @deprecated
     */
    send?: (request:  method: string, params?: Array<any> , callback: (error: any, response: any) => void) => void
    sendAsync: (request: RequestArguments) => Promise<unknown>

如您所见,到目前为止,我还无法弄清楚许多事物的确切类型,但重要的方法,sendsendAsync 在我的经验中是准确的。

另一个有用的模板是我在 @ethersproject/providers/src.ts/web3-provider.ts 中找到的

export type ExternalProvider = 
    isMetaMask?: boolean;
    isStatus?: boolean;
    host?: string;
    path?: string;
    sendAsync?: (request:  method: string, params?: Array<any> , callback: (error: any, response: any) => void) => void
    send?: (request:  method: string, params?: Array<any> , callback: (error: any, response: any) => void) => void
    request?: (request:  method: string, params?: Array<any> ) => Promise<any>

这可以在加载新的提供者时使用

new ethers.providers.Web3Provider(myProvider: ExternalProvider)

【讨论】:

这个来自 metamask 的 repo 似乎提供了类型定义 MetaMaskInpageProvider: github.com/MetaMask/providers【参考方案2】:

官方 Metamask Provider 存储库现在导出您可以/应该用于扩展 Window 界面的类型。

与@Felipe 的回答相同,使用MetamaskInpageProvider 而不是Ethereumish

import  MetaMaskInpageProvider  from "@metamask/providers";

declare global 
  interface Window 
    ethereum: MetaMaskInpageProvider;
  


【讨论】:

以上是关于Web3.js 扩展窗口界面类型定义的主要内容,如果未能解决你的问题,请参考以下文章

安卓开发 自定义界面的弹窗

如何通过“@solana/web3.js”传输自定义令牌

flowable入门(四)增加自定义类型的扩展属性

如何使用 @solana/web3.js 从 Solana 中的自定义令牌中删除铸币权限?

如何获取在与@solana/web3.js 的交易中转移的自定义令牌数量?

Typescript:用'this'获取自定义界面的类型?