Web3

coderljw 2024-10-13 DAPP
  • 区块链
  • DAPP
  • Web3
大约 2 分钟

# 1. connectors

import { InjectedConnector } from '@web3-react/injected-connector'
import { WalletConnectConnector } from '@web3-react/walletconnect-connector'

const chainId = parseInt(process.env.CHAIN.chainId)
const rpcURL = process.env.CHAIN.rpcUrls[0]

export const injected = new InjectedConnector({
  supportedChainIds: [chainId],
})

export const walletconnect = new WalletConnectConnector({
  rpc: {
    [chainId]: rpcURL,
  },
  qrcode: true,
  supportedChainIds: [chainId],
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 2. hooks

import { useState, useEffect, useRef } from 'react'
import { useIntl, useModel } from 'umi'
import { useWeb3React, UnsupportedChainIdError } from '@web3-react/core'
import {
  NoEthereumProviderError,
  UserRejectedRequestError as UserRejectedRequestErrorInjected,
} from '@web3-react/injected-connector'
import { UserRejectedRequestError as UserRejectedRequestErrorWalletConnect } from '@web3-react/walletconnect-connector'
import { injected } from './connectors'
import contractMap from './contract'
import { notification } from '@/utils'

// 错误提示
export function useErrorMessage() {
  const { formatMessage } = useIntl()

  const getErrorMessage = (error: Error) => {
    if (!error) return
    if (error instanceof NoEthereumProviderError) {
      return formatMessage({ id: 'NoEthereumProviderError' })
    } else if (error instanceof UnsupportedChainIdError) {
      return formatMessage({ id: 'UnsupportedChainIdError' })
    } else if (
      error instanceof UserRejectedRequestErrorInjected ||
      error instanceof UserRejectedRequestErrorWalletConnect
    ) {
      return formatMessage({ id: 'UserRejectedRequestError' })
    } else {
      return formatMessage({ id: 'UnKnownError' })
    }
  }

  const showErrorMessage = (error: Error) => {
    notification.close('notification')
    notification.warning({
      description: getErrorMessage(error),
    })
  }

  return showErrorMessage
}

// 若已连接过MetaMask,则进行快速连接
export function useEagerConnect() {
  const { activate, active } = useWeb3React()

  const [tried, setTried] = useState(false)

  const showErrorMessage = useErrorMessage()

  useEffect(() => {
    injected.isAuthorized().then(isAuthorized => {
      if (isAuthorized) {
        activate(injected, undefined, true).catch(error => {
          setTried(true)
          showErrorMessage(error)
        })
      } else {
        setTried(true)
      }
    })
  }, []) // intentionally only running on mount (make sure it's only mounted once :))

  // if the connection worked, wait until we get confirmation of that to flip the flag
  useEffect(() => {
    if (!tried && active) {
      setTried(true)
    }
  }, [tried, active])

  return tried
}

// 监听MetaMask
export function useInactiveListener(suppress = false) {
  const { active, error, activate } = useWeb3React()

  useEffect(() => {
    const { ethereum } = window as any
    if (ethereum && ethereum.on && !active && !error && !suppress) {
      const handleConnect = () => {
        console.log("Handling 'connect' event")
        activate(injected)
      }
      const handleChainChanged = (chainId: number | string) => {
        console.log("Handling 'chainChanged' event with payload", chainId)
        activate(injected)
      }
      const handleAccountsChanged = (accounts: string[]) => {
        console.log("Handling 'accountsChanged' event with payload", accounts)
        if (accounts.length > 0) {
          activate(injected)
        }
      }
      const handleNetworkChanged = (networkId: number) => {
        console.log("Handling 'networkChanged' event with payload", networkId)
        activate(injected)
      }

      ethereum.on('connect', handleConnect)
      ethereum.on('chainChanged', handleChainChanged)
      ethereum.on('accountsChanged', handleAccountsChanged)
      ethereum.on('networkChanged', handleNetworkChanged)

      return () => {
        if (ethereum.removeListener) {
          ethereum.removeListener('connect', handleConnect)
          ethereum.removeListener('chainChanged', handleChainChanged)
          ethereum.removeListener('accountsChanged', handleAccountsChanged)
          ethereum.removeListener('networkChanged', handleNetworkChanged)
        }
      }
    }
  }, [active, error, suppress, activate])
}

// 实例化合约
export function useContract(name: string) {
  const { initialState } = useModel('@@initialState')
  const { active, library } = useWeb3React()
  const contract = useRef(null)

  useEffect(() => {
    if (active) {
      contract.current = new library.eth.Contract(
        contractMap[name].abi,
        initialState.config[`Contract${name}`]
      )
    }
  }, [active, initialState.config])

  return contract
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

# 3. Error:Transaction was not mined within 50 blocks

以父之名
周杰伦.mp3