A Simple Guide to MetaMask — React + Ethereum
Sometimes using the MetaMask wallet directly is the simplest approach to making transactions on ethereum blockchains. In this tutorial I’m going to cover a range of topics for you and the important ones to get you going with your decentralized application, like Login / Disconnect, Request Authorization with Personal Sign, and sending tokens via a Transaction. Also I will cover some good practices to help you understand how MetaMask works.
For the full open source codebase to follow along please checkout my GitHub repo: https://github.com/blakewood84/metamask-transactions
#1 Initializing your app
First and most important is initializing your app to support MetaMask. The following code is good practice to use as in a useEffect() hook at the init of your application.
To give you a breakdown of what the above code is doing, we are first checking if MetaMask is actually installed on the supported browser the client is using. You will always access MetaMask via the following code: window.ethereum
which is targeting the browser’s plugin. To see more details about this check Getting Started from the MetaMask documentation.
In addition to checking if MetaMask is installed, I am dropping in 2 event listeners to listen to some important values if they change, like the ChainID the wallet is currently on, and the current account that’s selected if the wallet’s account does in fact change during the lifecycle of your application.
To add any event listeners you simply add:
window.ethereum.on(‘message’, (value) => { // callback })
For a rundown on the different event messages you can listen for simply reference the Events section of MetaMask documentation. According to the docs as well a good practice is reloading the browser incase the ChainID / chain does change because things could get a bit complicated. I’ll let you decide what to do for your app.
Moving on to #2 — Connecting to your App
To connect MetaMask to your site you want to somehow think state of the user’s account address. There are a few ways to do this.
Every time you submit a request and transact with MetaMask you will be using the following code:
window.ethereum.request({ method: ‘method’, params: [ ] })
Sometimes requests may or may not have params. For more details on requests please visit the Api Playground which is very useful for dissecting each request.
- Connect to the wallet with eth_requestAccounts which will trigger the user to login to their MetaMask wallet if no account is connected to the app or site address… If the MetaMask wallet is already connected to the app, then it will not alert you, just grab the account that is currently selected.
Above, I’ve created a button that will display the account’s address if the wallet is connected to the app. Tap the button again, and we will disconnect the wallet from the app by changing state.
To understand this simply, if you currently have a user’s wallet address in your useState variable, for me I am using walletAccount, then your app is connected to MetaMask.
2. You can also create another useState() called:
Which can be used to keep track of the connected state of the app to the MetaMask wallet like so:
Whenever a user’s account is supplied to the state of the application, we will then consider the MetaMask wallet “connected” to the application.
3. To disconnect the app, we can simply remove the account from state.
4. Sometimes however this isn’t good enough. For some people, we’d like to see the MetaMask wallet window opening back up to somehow force the user to engage on choosing the wallet they wish to connect to the app. For this you can run a wallet_requestPermissions followed by eth_requestAccounts which will generate that user flow for you, triggering the MetaMask to force the user to choose a new account to connect each time. You can do this like so:
Which will pop up the following each time:
This can help generate a user flow for you using all these connection methods.
#3 Personal Sign / Authentication
Are you familiar with OpenSea and their authentication process to sign a user in? It looks sort of like this:
This method is called personal_sign and can be used in different ways but forces the user to simply sign a request or message, showing they confirm or approve of that request. To handle a personal sign for Authentication purposes you can simply use the following code to do so:
The signed response will be a hashed signature using your wallet’s account you’re signing with. First we are requesting eth_requestAccounts to get the current selected account in the MetaMask wallet, then calling personal_sign followed by the message and account being used into the params. For more information on such requests visit Signing Data documentation.
#4 Getting an Account’s Token Balance
Want to get the token balance of the selected wallet in MetaMask? Simply use the request method eth_getBalance and pass in the account + ‘latest’ as the params like so:
await window.ethereum.request({ method: ‘eth_getBalance’, params: [ account, ‘latest’ ]})
In this function the request will return the balance in Wei, which to convert to Gwei (gas) you would divide by 10⁹ power and to convert to actual Ether (ETH) we will divide by 10¹⁸ power.
For this request I am running a local Ganache server and I’ve imported the first account into my MetaMask wallet.
Running a local Ganache node is one of the easiest ways to test transactions and using MetaMask requests locally. It’s a must for local development besides using a Testnet like Ropsten or Kovan and having to visit a Faucet frequently to refill your ETH balance. You can also use a local Blockchain explorer such as Ethernal to view transactions.
#5 Simple Send Transaction
Sending tokens between accounts using MetaMask can be quite simple. The following function will send a transaction between two parties as long as you have the sender’s address, receiver’s address, and amount (converted to Hex):
await window.ethereum.request({ method: ‘eth_sendTransaction’, params: [tx]})
For more info on transactions visit Sending Transactions.
I am also using a fixed gas price of 21000 which is in hexadecimal format. Most all your transaction information will be in hexadecimal format just to note. Running this function will generate the following request:
To test transactions, I setup a local Ganache server and sent ETH between two of the local accounts. It’s quite simple to import accounts on your local Ganache server, just visit this guide How to import an Account. You’ll want to import your account’s private key by click on the key icon in the Ganache GUI.
Conclusion
That’s it for now! 5 simple ways to use MetaMask with your decentralized application. For convenience purposes here is the full open source link to this project on GitHub: https://github.com/blakewood84/metamask-transactions
As always if you have any questions, please feel free to contact me via LinkedIn at: https://www.linkedin.com/in/blakewoodjr/ !
Wishing you all a blessed day and happy coding!
Join Coinmonks Telegram Channel and Youtube Channel learn about crypto trading and investing