# Connecting to web3 with Web3Modal, react & ethers.js **Published by:** [woj.eth](https://paragraph.com/@woj/) **Published on:** 2021-10-15 **URL:** https://paragraph.com/@woj/connecting-to-web3-with-web3modal-react-ethers-js ## Content I’m writing this article solely with hope that one day it ends up high in web searches for this specific problem & it saves lives of devs like me. Or at least I will be sending that to friends starting out with building web3 apps 😄 Why should I use Web3Modal? Web3Modal allows you to connect your app to many wallet providers in a unified way. It’s a real blessing if you’re a dev trying to develop a web3 mvp really fast, but don’t want to compromise on wallet diversity. Here is their Github repo https://github.com/Web3Modal/web3modal How to use Web3Modal to connect to wallets? It’s very simple! First, let’s start with an empty component export default function Home(props) { return <button onClick={}>Connect</button> } and paste the setup code from the readme. import Web3Modal from 'web3modal' import WalletConnectProvider from '@walletconnect/web3-provider' import { useState, useEffect } from 'react'; export default function Home(props) { const [web3Modal, setWeb3Modal] = useState(null) useEffect(() => { const providerOptions = { walletconnect: { package: WalletConnectProvider, options: { infuraId: YOUR_INFURA_KEY, } }, }; const newWeb3Modal = new Web3Modal({ cacheProvider: true, // very important network: "mainnet", providerOptions, }); setWeb3Modal(newWeb3Modal) }, []) return <button onClick={}>Connect</button> } Ok, config done. Now it’s time for the actual connection logic! import Web3Modal from 'web3modal' import WalletConnectProvider from '@walletconnect/web3-provider' import { useState, useEffect } from 'react'; export default function Home(props) { const [web3Modal, setWeb3Modal] = useState(null) useEffect(() => { // initiate web3modal const providerOptions = { walletconnect: { package: WalletConnectProvider, options: { infuraId: YOUR_INFURA_KEY, } }, }; const newWeb3Modal = new Web3Modal({ cacheProvider: true, // very important network: "mainnet", providerOptions, }); setWeb3Modal(newWeb3Modal) }, []) async function connectWallet() { const provider = await web3Modal.connect(); } return <button onClick={connectWallet}>Connect wallet</button> } Perfect! Now we have a “Connect wallet” button, which will display the web3 modal after clicking. Once the user connects their wallet, we can read their data & prompt them to perform transactions or signatures. Integration with ethers.js (vs web3.js) I’m not picking wars here and web3.js is a great library, but the concept of providers & signers works much better in my head so for any custom on chain interaction I’m using ethers.js Web3Modal is not directly compatible with ethers, but you can wrap the Web3Modal provider into an ethers provider just like that: import { ethers, providers } from "ethers"; import Web3Modal from 'web3modal' import WalletConnectProvider from '@walletconnect/web3-provider' import { useState, useEffect } from 'react'; export default function Home(props) { const [web3Modal, setWeb3Modal] = useState(null) const [address, setAddress] = useState("") useEffect(() => { // initiate web3modal ... }, []) async function connectWallet() { const provider = await web3Modal.connect(); const ethersProvider = new providers.Web3Provider(provider) const userAddress = await ethersProvider.getSigner().getAddress() setAddress(userAddress) } return ( <div> <button onClick={connectWallet}>Connect wallet</button> <p>{address}</p> </div> ) } Connecting from cache & disconnecting When I coded my first web3 experiments I googled this phrase a 1000 times: ethers how to check if wallet already connected It wasn’t really helpful as there is no standard way of doing this. Fortunately, if you enable the option cacheProvider: true in Web3Modal config, you will be able to automatically connect, without displaying the modal. Example below! // imports export default function Home(props) { const [web3Modal, setWeb3Modal] = useState(null) const [address, setAddress] = useState("") useEffect(() => { // initiate web3modal ... }, []) useEffect(() => { // connect automatically and without a popup if user is already connected if(web3Modal && web3Modal.cachedProvider){ connectWallet() } }, [web3Modal]) async function connectWallet() { ... } return ( <div> <button onClick={connectWallet}>Connect wallet</button> <p>{address}</p> </div> ) } Listeners With Web3Modal we have an easy way to subscribe to wallet events like network or account changes. I recommend doing that over playing with ethers provider, since the latter option was very messy for me. Web3Modal listeners obey EIP-1193 standard and you can easily integrate them like in the function addListeners // imports export default function Home(props) { const [web3Modal, setWeb3Modal] = useState(null) const [address, setAddress] = useState("") useEffect(() => { // initiate web3modal ... }, []) useEffect(() => { // connect automatically and without a popup if user is already connected if(web3Modal && web3Modal.cachedProvider){ connectWallet() } }, [web3Modal]) async function connectWallet() { const provider = await web3Modal.connect(); addListeners(provider); const ethersProvider = new providers.Web3Provider(provider) const userAddress = await ethersProvider.getSigner().getAddress() setAddress(userAddress) } async function addListeners(web3ModalProvider) { web3ModalProvider.on("accountsChanged", (accounts) => { window.location.reload() }); // Subscribe to chainId change web3ModalProvider.on("chainChanged", (chainId) => { window.location.reload() }); } return ( <div> <button onClick={connectWallet}>Connect wallet</button> <p>{address}</p> </div> ) } Now the app will automatically reload on a network or an account change. Of course you should customize it to you needs. Summary Hopefully this helped you with a problem or gave you a better mindset for building this integration! If so, you should follow me on twitter or check out some cool stuff that we’re building at Mazury. ## Publication Information - [woj.eth](https://paragraph.com/@woj/): Publication homepage - [All Posts](https://paragraph.com/@woj/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@woj): Subscribe to updates - [Twitter](https://twitter.com/wojtekwtf): Follow on Twitter