how to get provider value from @web3modal/react

1.5k views Asked by At

I am using the web3modal

import { useWeb3Modal } from "@web3modal/react";

const foo = () => {
const { open, close } = useWeb3Modal();

async function connect_wallet() {
    try {
      await open(); // Open the web3modal provider selection modal
      console.log("web3 and provider")
      // provider
    } catch (error) {
      console.error("Error connecting to provider:", error);
    }
  
 }

return(
 <div>
  <button onClick={connect_wallet}>
    Connect Wallet
  </button>
 </div>
 )
}

so the web3modal pops up fine and gets connected, but how to grab the values of provider and web3 from it ?

2

There are 2 answers

0
Isaac Frank On

Okay, A little background, I needed to work on a project, just to realize that there have been a lot of changes to the @web3mnodal library, I was frustrated trying to get the connected provider from the open method but failed to.

Now, when setting web3modal up, I chose the web3modal+wagmi setup (not the ethers setup), the reason being that most of my ethers code was using v6, and the web3modal ether version is stuck in v5(meaning I'd have to switch my codebase back to 5), the good thing about wagmi set up is that it is connected to the web3modal in some way.

I imported some hooks from the wagmi library i.e import {useAccount, useWalletClient} from 'wagmi'

The useAccount hook gives you the state of the account, like the address, the current connector(if connected else null), the connected state, and the connecting state (if it's connecting at the moment)

const { address, isConnected, connector, isConnecting, isDisconnected, isReconnecting, status } = useAccount()

The useWalletClient on the other hand gets the actual connector/walletCient (this is what you need, as this has more information unlike the connector gotten from the useAccount hook, you could do a connector.getWalletClient() tho)

This was the easy part, the hard part was trying to convert the connector/walletCliend to an ethers Provider and/or Signer, I had to create a helper function for that.

Code would look like this sample

import { useWeb3Modal } from "@web3modal/wagmi/react";
import { useEffect } from "react";
import { ethers } from "ethers";
import { WalletClient } from "viem";
import { useAccount, useWalletClient } from "wagmi";

const clientToProviderSigner = async (client: WalletClient) => {
  const { account, chain, transport } = client;
  const network = {
    chainId: chain?.id,
    name: chain?.name,
    ensAddress: chain?.contracts?.ensRegistry?.address,
  };
  // You can use whatever provider that fits your need here.
  const provider = new ethers.BrowserProvider(transport, network);
  const signer = await provider.getSigner(account?.address);
  return { provider, signer };
};

const App = () => {
    const { open } = useWeb3Modal()
    const { isConnected } = useAccount()
    const { data: walletClient } = useWalletClient();

    // This is to update ya state/redux store
    const connectWallet = async () => {
        if (!walletClient) return;
        const { signer, provider } = await clientToProviderSigner(walletClient)
        // Do whatever you want with the provider and signer like storing them in a state or context
    };
    
    useEffect(() => {
        // Only open modal if the user isn't connected
        !isConnected && open()
    }, [])

    useEffect(() => {
        // Finally we only want to get a provider if the user is connected(from the modal) AND there's a wallet client
        isConnected && walletClient && connectWallet();
    }, [isConnected, walletClient])


}

export default App

Hope this helps.

1
Blue Beam321 On

You can try in the following way.

import Web3Modal from "web3modal";
...
const provider = await web3Modal.connect();
console.log("Provider:", provider);