-
Notifications
You must be signed in to change notification settings - Fork 168
/
useWeb3React.tsx
116 lines (105 loc) · 4.27 KB
/
useWeb3React.tsx
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
import { JsonRpcProvider } from '@ethersproject/providers'
import { initializeConnector, Web3ReactHooks, Web3ReactProvider } from '@web3-react/core'
import { EIP1193 } from '@web3-react/eip1193'
import { MetaMask } from '@web3-react/metamask'
import { Network } from '@web3-react/network'
import { Connector, Provider as Eip1193Provider, Web3ReactStore } from '@web3-react/types'
import { WalletConnect } from '@web3-react/walletconnect'
import { SupportedChainId } from 'constants/chains'
import { atom, useAtom } from 'jotai'
import { PropsWithChildren, useEffect, useMemo } from 'react'
import JsonRpcConnector from 'utils/JsonRpcConnector'
export type Web3Connection = [Connector, Web3ReactHooks]
export let connections: Web3Connection[] = []
export const defaultChainIdAtom = atom<number>(1)
function toWeb3Connection<T extends Connector>([connector, hooks]: [
T,
Web3ReactHooks,
Web3ReactStore
]): Web3Connection {
return [connector, hooks]
}
export function getConnectorName(connector: Connector) {
if (connector instanceof MetaMask) return 'MetaMask'
if (connector instanceof WalletConnect) return 'WalletConnect'
if (connector instanceof Network) return 'Network'
if (connector instanceof JsonRpcConnector) return 'JsonRpcConnector'
if (connector instanceof EIP1193) return 'EIP1193'
return 'Unknown'
}
function getConnectionFromProvider(onError: (error: Error) => void, provider?: JsonRpcProvider | Eip1193Provider) {
if (!provider) return
if (JsonRpcProvider.isProvider(provider)) {
return toWeb3Connection(initializeConnector((actions) => new JsonRpcConnector(actions, provider)))
} else if (JsonRpcProvider.isProvider((provider as any).provider)) {
throw new Error('Eip1193Bridge is experimental: pass your ethers Provider directly')
} else {
return toWeb3Connection(initializeConnector((actions) => new EIP1193({ actions, provider, onError })))
}
}
function getConnectionFromWalletConnect(
useDefault: boolean,
jsonRpcUrlMap: { [chainId: number]: string[] },
defaultChainId: SupportedChainId,
onError: (error: Error) => void
) {
return toWeb3Connection(
initializeConnector<WalletConnect>(
(actions) =>
new WalletConnect({
actions,
options: {
rpc: jsonRpcUrlMap,
qrcode: useDefault,
},
onError,
defaultChainId,
})
)
)
}
interface ActiveWeb3ProviderProps {
provider?: Eip1193Provider | JsonRpcProvider
jsonRpcUrlMap: { [chainId: number]: string[] }
defaultChainId: SupportedChainId
}
export function ActiveWeb3Provider({
provider,
jsonRpcUrlMap,
defaultChainId: propsDefaultChainId,
children,
}: PropsWithChildren<ActiveWeb3ProviderProps>) {
const onError = console.error
const [defaultChainId, setDefaultChainId] = useAtom(defaultChainIdAtom)
useEffect(() => {
if (propsDefaultChainId !== defaultChainId) setDefaultChainId(propsDefaultChainId)
}, [propsDefaultChainId, defaultChainId, setDefaultChainId])
const integratorConnection = useMemo(() => getConnectionFromProvider(onError, provider), [onError, provider])
const metaMaskConnection = useMemo(
() => toWeb3Connection(initializeConnector<MetaMask>((actions) => new MetaMask({ actions, onError }))),
[onError]
)
const walletConnectConnectionQR = useMemo(
() => getConnectionFromWalletConnect(false, jsonRpcUrlMap, defaultChainId, onError),
[jsonRpcUrlMap, defaultChainId, onError]
) // WC via tile QR code scan
const walletConnectConnectionPopup = useMemo(
() => getConnectionFromWalletConnect(true, jsonRpcUrlMap, defaultChainId, onError),
[jsonRpcUrlMap, defaultChainId, onError]
) // WC via built-in popup
const networkConnection = useMemo(
() =>
toWeb3Connection(
initializeConnector<Network>((actions) => new Network({ actions, urlMap: jsonRpcUrlMap, defaultChainId }))
),
[jsonRpcUrlMap, defaultChainId]
)
connections = [metaMaskConnection, walletConnectConnectionQR, walletConnectConnectionPopup, networkConnection]
if (integratorConnection) connections = [integratorConnection, ...connections]
const key = `${connections.length}+${Object.entries(jsonRpcUrlMap)}+${propsDefaultChainId}+${defaultChainId}`
return (
<Web3ReactProvider connectors={connections} key={key}>
{children}
</Web3ReactProvider>
)
}