Uniswap / web3-react

A simple, maximally extensible, dependency minimized framework for building modern Ethereum dApps
https://web3-react-mu.vercel.app/
GNU General Public License v3.0
5.48k stars 1.51k forks source link

How can i use network connection as a fallback connector? #929

Closed lxiiiixi closed 2 months ago

lxiiiixi commented 2 months ago

I am encountering an issue with the following connections configuration:

export const connections = [eip6963Connection, networkConnection];
import { ReactNode } from "react";
import { Connector } from "@web3-react/types";
import { Web3ReactHooks, Web3ReactProvider } from "@web3-react/core";
import { connections } from "@/config/connection";

export default function Web3Provider({ children }: { children: ReactNode }) {
  const connectors = connections.map<[Connector, Web3ReactHooks]>(
    ({ hooks, connector }) => [connector, hooks],
  );

  return (
    <Web3ReactProvider connectors={connectors}>{children}</Web3ReactProvider>
  );
}

However, if a user does not connect a wallet, the application fails to retrieve data such as blockNumber from the provider:

const useBlockNumber = () => {
  const [blockNumber, setBlockNumber] = useState(0);
  const { provider } = useWeb3React();

  useEffect(() => {
    if (!provider) return;
    const handleBolock = (blockNumber: number) => {
      setBlockNumber(blockNumber);
    };

    provider
      .getBlockNumber()
      .then((res) => {
        handleBolock(res);
      })
      .catch((error) => console.error(`Failed to get block number`, error));

    provider.on("block", handleBolock);
    return () => {
      provider.removeListener("block", handleBolock);
    };
  }, [provider]);
  return blockNumber;
};

When the wallet is connected, I can successfully obtain the blockNumber. If not, I encounter the following error:

Error: could not detect network (event="noNetwork", code=NETWORK_ERROR, version=providers/5.7.2)

Can someone explain why the fallback network is not functioning? I am somewhat confused by this behavior.

lxiiiixi commented 2 months ago

Okay, I now understand the reason. I should attempt to establish a connection by activating the network.

import { Connector } from "@web3-react/types";
import { ConnectionType } from "./types";
import { useEffect } from "react";
import { useRecentConnection } from "./useRecentConnection";
import { getConnection } from ".";

async function connect(connector: Connector, type: ConnectionType) {
  console.log("Tring to connect by", type, "......");
  try {
    if (connector.connectEagerly) {
      await connector.connectEagerly();
    } else {
      await connector.activate();
    }
    return true;
  } catch (error) {
    console.debug(`web3-react eager connection error: ${error}`);
    return false;
  }
}

export const useEagerlyConnect = () => {
  const { getRecentConnectionMeta } = useRecentConnection();
  const connectionMeta = getRecentConnectionMeta();
  console.log("Last connected by", connectionMeta, connectionMeta?.walletName);

  const networkConnection = getConnection(ConnectionType.NETWORK);
  if (networkConnection && networkConnection.connector)
    connect(networkConnection.connector, ConnectionType.NETWORK);

  useEffect(() => {
    // try to connect with the most recent connection
    if (connectionMeta && connectionMeta?.type) {
      const connection = getConnection(connectionMeta?.type);
      if (connection && connection.connector) {
        connect(connection.connector, ConnectionType.EIP_6963_INJECTED);
      } else {
        console.warn("unsupported connector");
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
};