21 |
22 |
Create Dapp
23 |
24 |
25 |
26 |
27 | {account}---
28 | {chainId}
29 |
30 |
31 | );
32 | };
33 |
34 | export default Home;
35 |
--------------------------------------------------------------------------------
/src/hooks/useInactiveListener.ts:
--------------------------------------------------------------------------------
1 | import { useWeb3React as useWeb3ReactCore } from "@web3-react/core";
2 | import { useEffect } from "react";
3 |
4 | import { injected } from "config/constants/wallets";
5 |
6 | /**
7 | * Use for network and injected - logs user in
8 | * and out after checking what network theyre on
9 | */
10 | function useInactiveListener(suppress = false) {
11 | const { active, error, activate } = useWeb3ReactCore(); // specifically using useWeb3React because of what this hook does
12 |
13 | useEffect(() => {
14 | const { ethereum } = window;
15 |
16 | if (ethereum && ethereum.on && !active && !error && !suppress) {
17 | const handleChainChanged = () => {
18 | // eat errors
19 | activate(injected, undefined, true).catch((error) => {
20 | console.error("Failed to activate after chain changed", error);
21 | });
22 | };
23 |
24 | const handleAccountsChanged = (accounts: string[]) => {
25 | if (accounts.length > 0) {
26 | // eat errors
27 | activate(injected, undefined, true).catch((error) => {
28 | console.error("Failed to activate after accounts changed", error);
29 | });
30 | }
31 | };
32 |
33 | ethereum.on("chainChanged", handleChainChanged);
34 | ethereum.on("accountsChanged", handleAccountsChanged);
35 |
36 | return () => {
37 | if (ethereum.removeListener) {
38 | ethereum.removeListener("chainChanged", handleChainChanged);
39 | ethereum.removeListener("accountsChanged", handleAccountsChanged);
40 | }
41 | };
42 | }
43 | return undefined;
44 | }, [active, error, suppress, activate]);
45 | }
46 |
47 | export default useInactiveListener;
48 |
--------------------------------------------------------------------------------
/src/hooks/useContract.ts:
--------------------------------------------------------------------------------
1 | import { useMemo } from "react";
2 | import { useActiveWeb3React } from "hooks/useActiveWeb3React";
3 | import { JsonRpcSigner, Web3Provider } from "@ethersproject/providers";
4 | import { AddressZero } from "@ethersproject/constants";
5 | import { isAddress } from "utils/isAddress";
6 | import { getProviderOrSigner } from "utils";
7 | import { Contract } from "@ethersproject/contracts";
8 |
9 | // export const useExampleContract = (address: string, withSignerIfPossible = true) => {
10 | // return useContract(address, ContractAbi, withSignerIfPossible);
11 | // };
12 |
13 | // Multiple chains
14 |
15 | // export const useBatchTransfer = (withSignerIfPossible?: boolean) => {
16 | // const { chainId } = useActiveWeb3React();
17 | // return useContract(getContractAddress(chainId), ContractAbi, withSignerIfPossible);
18 | // };
19 |
20 | export function useContract(address: string | undefined, ABI: any, withSignerIfPossible = true): Contract | null {
21 | const { library, account } = useActiveWeb3React();
22 | return useMemo(() => {
23 | if (!address || address === AddressZero || !ABI || !library) return null;
24 | try {
25 | return getContract(address, ABI, library, withSignerIfPossible && account ? account : undefined);
26 | } catch (error) {
27 | console.error("Failed to get contract", error);
28 | return null;
29 | }
30 | }, [address, ABI, library, withSignerIfPossible, account]);
31 | }
32 |
33 | export function getContract(address: string, ABI: any, library: Web3Provider, account?: string): Contract {
34 | if (!isAddress(address) || address === AddressZero) {
35 | throw Error(`Invalid 'address' parameter '${address}'.`);
36 | }
37 | return new Contract(address, ABI, getProviderOrSigner(library, account));
38 | }
39 |
--------------------------------------------------------------------------------
/src/hooks/useEagerConnect.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import { useWeb3React as useWeb3ReactCore } from "@web3-react/core";
3 | import { injected } from "config/constants/wallets";
4 | import { isMobile } from "web3modal";
5 | import { connectorLocalStorageKey } from "config/connectors/index";
6 | export function useEagerConnect() {
7 | const { activate, active } = useWeb3ReactCore(); // specifically using useWeb3ReactCore because of what this hook does
8 | const [tried, setTried] = useState(false);
9 |
10 | useEffect(() => {
11 | injected.isAuthorized().then((isAuthorized) => {
12 | const hasSignedIn = window.localStorage.getItem(connectorLocalStorageKey);
13 | if (isAuthorized && hasSignedIn) {
14 | activate(injected, undefined, true)
15 | // .then(() => window.ethereum.removeAllListeners(['networkChanged']))
16 | .catch(() => {
17 | setTried(true);
18 | });
19 | // @ts-ignore TYPE NEEDS FIXING
20 | window.ethereum.removeAllListeners(["networkChanged"]);
21 | } else {
22 | if (isMobile() && window.ethereum && hasSignedIn) {
23 | activate(injected, undefined, true)
24 | // .then(() => window.ethereum.removeAllListeners(['networkChanged']))
25 | .catch(() => {
26 | setTried(true);
27 | });
28 | // @ts-ignore TYPE NEEDS FIXING
29 | window.ethereum.removeAllListeners(["networkChanged"]);
30 | } else {
31 | setTried(true);
32 | }
33 | }
34 | });
35 | }, [activate]);
36 |
37 | useEffect(() => {
38 | if (active) {
39 | setTried(true);
40 | }
41 | }, [active]);
42 |
43 | return tried;
44 | }
45 |
46 | export default useEagerConnect;
47 |
--------------------------------------------------------------------------------
/src/components/Web3ReactManager/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { useWeb3React } from "@web3-react/core";
3 | import { network } from "config/constants/wallets";
4 | import { NetworkContextName } from "config/index";
5 |
6 | import useEagerConnect from "hooks/useEagerConnect";
7 | import useInactiveListener from "hooks/useInactiveListener";
8 |
9 | export default function Web3ReactManager({ children }: { children: JSX.Element }) {
10 | const { active } = useWeb3React();
11 | const { active: networkActive, error: networkError, activate: activateNetwork } = useWeb3React(NetworkContextName);
12 |
13 | // try to eagerly connect to an injected provider, if it exists and has granted access already
14 | const triedEager = useEagerConnect();
15 |
16 | // after eagerly trying injected, if the network connect ever isn't active or in an error state, activate itd
17 | useEffect(() => {
18 | if (triedEager && !networkActive && !networkError && !active) {
19 | activateNetwork(network);
20 | }
21 | }, [triedEager, networkActive, networkError, activateNetwork, active]);
22 |
23 | // when there's no account connected, react to logins (broadly speaking) on the injected provider, if it exists
24 | useInactiveListener(!triedEager);
25 |
26 | // handle delayed loader state
27 | const [showLoader, setShowLoader] = useState(false);
28 | useEffect(() => {
29 | const timeout = setTimeout(() => {
30 | setShowLoader(true);
31 | }, 600);
32 |
33 | return () => {
34 | clearTimeout(timeout);
35 | };
36 | }, []);
37 |
38 | // on page load, do nothing until we've tried to connect to the injected connector
39 | if (!triedEager) {
40 | return null;
41 | }
42 |
43 | // if the account context isn't active, and there's an error on the network context, it's an irrecoverable error
44 | if (!active && networkError) {
45 | return