问:web3 typescript 错误 ethereum.request 找不到名称 'ethereum'

Q: web3 typescript error ethereum.request cannot find name 'ethereum'

我正在使用 metamask/detect-provider 制作一个简单的按钮,该按钮连接到元掩码文档之后的元掩码扩展。但是,它 returns Typescript 错误找不到名称 'ethereum'。当我启动 npm 时出现 TS3204。有谁知道这个错误的原因吗?

import Web3 from 'web3';
import { Message, Button } from "semantic-ui-react";
import 'semantic-ui-css/semantic.min.css';
import detectEthereumProvider from '@metamask/detect-provider';
import './App.css';

function App() {
  const loadMetamask = () => {
    ethereum.request({ method: 'eth_requestAccounts' });
  }
  return (
    <div className="App">
      <div className="App-header">
        <h1>Testing</h1>

        <Message warning>Metamask is not connected</Message>
        <button color="green"
          onClick={() => loadMetamask()}
        >Connect to Metamask</button>
      </div>
    </div>
  );
}
export default App;

这是因为 typescript 编译器找不到 ethereum 模块,因为 ethereum 模块在全局 window.

解决方法很少

第一种方法,为 window.ethereum 创建您自己的类型定义。你可以参考这里

第二种方式,要求typescript编译器忽略错误,不推荐,因为它违背了使用typescript的目的。

//@ts-ignore
 ethereum.request({ method: 'eth_requestAccounts' });

最后一种方式,也是最懒的一种方式。 @metamask/provides 确实为 window.ethereum 提供了类型定义。因此,我们通过运行

安装
npm i @metamask/providers

之后,导入 class

import { MetaMaskInpageProvider } from '@metamask/providers';

然后,告诉打字稿编译器将 window.ethereum 视为 MetaMaskInpageProvider

const ethereum = window.ethereum as MetaMaskInpageProvider;

现在,您应该可以

ethereum.request<string[]>({ method: 'eth_requestAccounts' });

您的代码应类似于以下内容

import Web3 from 'web3';
import { Message, Button } from "semantic-ui-react";
import 'semantic-ui-css/semantic.min.css';
import detectEthereumProvider from '@metamask/detect-provider';
import { MetaMaskInpageProvider } from '@metamask/providers';
import './App.css';

function App() {
  const loadMetamask = async () => {
    // You need to await for user response on the metamask popup dialog
    const accounts = await ethereum.request<string[]>({ method: 'eth_requestAccounts' });
    if(accounts){
       console.log(accounts[0]);
    }
  }
  return (
    <div className="App">
      <div className="App-header">
        <h1>Testing</h1>

        <Message warning>Metamask is not connected</Message>
        <button color="green"
          onClick={() => loadMetamask()}
        >Connect to Metamask</button>
      </div>
    </div>
  );
}
export default App;

尽管它有效,但我们安装了未使用的 @metamask/providers 库。