I'm using metamask/detect-provider to make a simple button that connects to the metamask extension following the metamask documentation. However, it returns
Typescript error Cannot find name 'ethereum'. TS3204 when I do npm start. Does anyone know the reason for this error?
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;
This is due to typescript compiler couldn't find the ethereum
module as ethereum
module is in global window
.
There are few ways to solve it.
First way, create your own type definition for window.ethereum
. You may refer to here Web3.js extending the window interface type definitions
Second way, ask typescript compiler to ignore the error, which is not recommended as it beat the purpose of using typescript.
//@ts-ignore
ethereum.request({ method: 'eth_requestAccounts' });
Last way, which is the laziest way. @metamask/provides
did provide the type definition for window.ethereum
. Therefore, we install it by running
npm i @metamask/providers
After that, import the class
import { MetaMaskInpageProvider } from '@metamask/providers';
Then, tell the typescript compiler to treat window.ethereum
as MetaMaskInpageProvider
const ethereum = window.ethereum as MetaMaskInpageProvider;
Now, you should be able to
ethereum.request<string[]>({ method: 'eth_requestAccounts' });
Your code should looks similar to below
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;
Even though it works, but we installed unused @metamask/providers
library.