Add a web3 connect button to your React App with TypeScript and Metamask.
Tags: react, typescript, web3, javascript
Published: 2022-11-09 06:43:41

<!-- wp:paragraph -->
<p><a href="https://metamask.io/">Metamask</a> is the most popular cryptocurrency wallet with over <a href="https://consensys.net/blog/press-release/metamask-surpasses-10-million-maus-making-it-the-worlds-leading-non-custodial-crypto-wallet/">10 Million monthly active users</a>. Available as a browser extension and mobile app, Metamask provides key functionalities that make it easy to interact with the Ethereum blockchain and other notable chains like Binance, Avalanche, and Polygon. Web3 developers may use these capabilities to power decentralized apps (dApps), allowing users to perform blockchain-based transactions securely with a single sign-on.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In this article, we will use TypeScript to add a Metamask connect button to a basic React project. Google's Firebase social login, which allows developers to build apps that authenticate users using their Google, Facebook, GitHub, and Twitter accounts, is a similar traditional web equivalent.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Let's get started.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:more -->
<!--more-->
<!-- /wp:more -->

<!-- wp:heading -->
<h2>Create React App</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>We will use the <a href="https://create-react-app.dev/docs/adding-typescript/">official Create-react app documentation</a> to add TypeScript to a react app.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>npx create-react-app typescript-metamask --template typescript 
cd typescript-metamask
npm start
</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>This command will create a basic react app, as shown below. If you're using Visual Studio Code, you can run <em>code . </em>to launch the editor direct from the terminal.</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh3.googleusercontent.com/j8aXhws1DBF2hWaitRVgILcf_swLO0H3aQo82C22E_ab837xH0_b1X7MKU1coWCBijJ-qa6cyKvgnJU4swAqvbIK4wGgUPjJmfEgSs9g6OD7zAdPBgjm9p6s336q8qOYEz_LHMHb" alt=""/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Consequently, our file structure will look like below.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>&gt; src/App.tsx</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh6.googleusercontent.com/3SFc0sNkP03Pf6Ytxzno2nUxvajiZp7ob4PE09HV6kZ_iVWBI5V-_tqrG_7ALuRhn9CxDosXMYKVYdYYHnxvwGWZtBFBUiHJYkCHbQi2QfbwMmw4YINipWRD22K2iDasgWnZZSic" alt=""/></figure>
<!-- /wp:image -->

<!-- wp:heading -->
<h2>Does the user have Metamask Installed?</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Next, we will use the <a href="https://docs.metamask.io/guide/ethereum-provider.html">Metamask window.ethereum API</a> to check if the user has Metamask installed. To call and store the API returns, we will need two React Hooks - useState and useEffect.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>import { useEffect, useState } from "react";

const App: React.FC = () =&gt; {
 const &#91;isMetamaskInstalled, setIsMetamaskInstalled] = useState&lt;boolean&gt;(false);
 const &#91;account, setAccount] = useState&lt;string | null&gt;(null);

useEffect(() =&gt; {
   if((window as any).ethereum){
     //check if Metamask wallet is installed
     setIsMetamaskInstalled(true);
   }
 },&#91;]);
</code></pre>
<!-- /wp:code -->

<!-- wp:heading -->
<h2>Does the User have an Ethereum wallet/account?</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>After that, we need to verify if the user has an Ethereum account. To do this, we will query Metamask's <a href="https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts">eth_requestAccounts</a> function, which returns an Array of strings - string [].&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>If the user has an Ethereum account, we'll create a function to retrieve and store the wallet address.&nbsp;&nbsp;&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>//Does the User have an Ethereum wallet/account?
 async function connectWallet(): Promise&lt;void&gt; {
   //to get around type checking
   (window as any).ethereum
     .request({
         method: "eth_requestAccounts",
     })
     .then((accounts : string&#91;]) =&gt; {
         setAccount(accounts&#91;0]);
     })
     .catch((error: any) =&gt; {
         alert(`Something went wrong: ${error}`);
     });
 }</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>And also display the connected wallet address.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>return (
   &lt;div className="App"&gt;
     &lt;header className="App-header"&gt;
       &lt;img src={logo} className="App-logo" alt="logo" /&gt;
       &lt;p&gt;
         ETH wallet connected as: {account}
       &lt;/p&gt;
     &lt;/header&gt;
   &lt;/div&gt;
 );</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>If the user does not have an Ethereum account, we can have the app prompt the user to install Metamask crypto wallet and create and add an Ethereum account to your wallet.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>if (ethereumAccount === null) {
   return (
     &lt;div className="App App-header"&gt;
       {
         isMetamaskInstalled ? (
           &lt;div&gt;
             &lt;img src={logo} className="App-logo" alt="logo" /&gt;
             &lt;button onClick={connectMetamaskWallet}&gt;Connect Your Metamask Wallet&lt;/button&gt;
           &lt;/div&gt;
         ) : (
           &lt;p&gt;Install Your Metamask wallet&lt;/p&gt;
         )
       }
 
     &lt;/div&gt;
   );
 }</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Here's the final <em>App.tsx</em> version:</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>import { useEffect, useState } from "react";
import logo from './logo.svg';
import './App.css';
 
const App: React.FC = () =&gt; {
 const &#91;isMetamaskInstalled, setIsMetamaskInstalled] = useState&lt;boolean&gt;(false);
 const &#91;ethereumAccount, setEthereumAccount] = useState&lt;string | null&gt;(null);
 
 useEffect(() =&gt; {
   if((window as any).ethereum){
     //check if Metamask wallet is installed
     setIsMetamaskInstalled(true);
   }
 },&#91;]);
 
 //Does the User have an Ethereum wallet/account?
 async function connectMetamaskWallet(): Promise&lt;void&gt; {
   //to get around type checking
   (window as any).ethereum
     .request({
         method: "eth_requestAccounts",
     })
     .then((accounts : string&#91;]) =&gt; {
       setEthereumAccount(accounts&#91;0]);
     })
     .catch((error: any) =&gt; {
         alert(`Something went wrong: ${error}`);
     });
 }
 
 if (ethereumAccount === null) {
   return (
     &lt;div className="App App-header"&gt;
       {
         isMetamaskInstalled ? (
           &lt;div&gt;
             &lt;img src={logo} alt="logo" /&gt;
             &lt;button onClick={connectMetamaskWallet}&gt;Connect Your Metamask Wallet&lt;/button&gt;
           &lt;/div&gt;
         ) : (
           &lt;p&gt;Install Your Metamask wallet&lt;/p&gt;
         )
       }
 
     &lt;/div&gt;
   );
 }
 
 
 return (
   &lt;div className="App"&gt;
     &lt;header className="App-header"&gt;
       &lt;img src={logo} className="App-logo" alt="logo" /&gt;
       &lt;p&gt;
         ETH wallet connected as: {ethereumAccount}
       &lt;/p&gt;
     &lt;/header&gt;
   &lt;/div&gt;
 );
}
 
export default App;
</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>The final version before a user connect:</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh6.googleusercontent.com/SYHpVih-sKxqNwenoO5q6t_ZnQhWOSw-u1lWGtfb4EW2AUQbMOelTPjqX-UKwvnypDCXW48xfp9KnWI0KHy8ZN1CFed26Rmp24E6JLbugMxiS43M3xNmlfwP76IA0GOVjS7G1kD0" alt=""/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>After a user connects:</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh4.googleusercontent.com/7voSgROUbVVlK8FYm4wa8EPjBvW7YSJkenSqy81kFFvQDHHtezEUgD_PdhzZii9bBaKfr4QJC0VYfauEf1GrC3xxuye_WOd0uG7NcgzXk_NOUzDcNhNfpscAOYCM1amAvM3P8hcq" alt=""/></figure>
<!-- /wp:image -->

<!-- wp:heading -->
<h2><strong>Conclusion</strong></h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>That's all. Metamask provides powerful APIs web3 React developers can query when building their Ethereum-based dApps. </p>
<!-- /wp:paragraph -->