Web3
coderljw 2024-10-13 大约 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
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
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
调用主合约合卡前,需将用户选择的卡片授权给主合约,调用授权方法时报此错误。查询无果后,此 DAPP 采用曲线救国方式,当查询到所有卡片已授权为主合约地址时,表示已授权成功(后修改为通过事件监听方式判断是否授权成功)。