1
- import type { WindowProvider } from '../../../types/utils' ;
2
- import { isAndroid , isIOS } from '../../../utils/isMobile' ;
3
- import type { DefaultWalletOptions , Wallet } from '../../Wallet' ;
4
- import {
5
- getInjectedConnector ,
6
- hasInjectedProvider ,
7
- } from '../../getInjectedConnector' ;
1
+ import { createConnector } from 'wagmi' ;
2
+ import { metaMask } from 'wagmi/connectors' ;
3
+ import type {
4
+ DefaultWalletOptions ,
5
+ Wallet ,
6
+ WalletDetailsParams ,
7
+ } from '../../Wallet' ;
8
+ import { hasInjectedProvider } from '../../getInjectedConnector' ;
8
9
import { getWalletConnectConnector } from '../../getWalletConnectConnector' ;
10
+ import { isMobile } from '../../../utils/isMobile' ;
11
+ import type { WindowProvider } from '../../../types/utils' ;
9
12
10
13
export type MetaMaskWalletOptions = DefaultWalletOptions ;
11
14
12
15
function isMetaMask ( ethereum ?: WindowProvider [ 'ethereum' ] ) : boolean {
13
- // Logic borrowed from wagmi's MetaMaskConnector
14
- // https://github.com/wagmi-dev/references/blob/main/packages/connectors/src/metaMask.ts
16
+ // Logic borrowed from wagmi's legacy MetaMaskConnector
17
+ // Non-exhaustive list of wallets that try to make themselves look like MetaMask
15
18
if ( ! ethereum ?. isMetaMask ) return false ;
16
19
// Brave tries to make itself look like MetaMask
17
20
// Could also try RPC `web3_clientVersion` if following is unreliable
@@ -61,22 +64,16 @@ export const metaMaskWallet = ({
61
64
projectId,
62
65
walletConnectParameters,
63
66
} : MetaMaskWalletOptions ) : Wallet => {
64
- // Not using the explicit isMetaMask fn to check for MetaMask
65
- // so that users can continue to use the MetaMask button
66
- // to interact with wallets compatible with window.ethereum.
67
- // The connector's getProvider will instead favor the real MetaMask
68
- // in window.providers scenarios with multiple wallets injected.
69
- const isMetaMaskInjected = hasInjectedProvider ( { flag : 'isMetaMask' } ) ;
70
- const shouldUseWalletConnect = ! isMetaMaskInjected ;
67
+ // Custom logic to explicitly detect MetaMask
68
+ // Whereas hasInjectedProvider only checks for impersonated `isMetaMask`
69
+ // We need this because MetaMask SDK hangs on impersonated wallets
70
+ // Previously MetaMask provider would trigger for impersonated wallets
71
+ const isMetaMaskInjected =
72
+ typeof window !== 'undefined' ? isMetaMask ( window . ethereum ) : false ;
71
73
72
- const getUri = ( uri : string ) => {
73
- return isAndroid ( )
74
- ? uri
75
- : isIOS ( )
76
- ? // currently broken in MetaMask v6.5.0 https://github.com/MetaMask/metamask-mobile/issues/6457
77
- `metamask://wc?uri=${ encodeURIComponent ( uri ) } `
78
- : `https://metamask.app.link/wc?uri=${ encodeURIComponent ( uri ) } ` ;
79
- } ;
74
+ // TODO: This is a temporary solution to prefer WalletConnect for desktop qr code.
75
+ const shouldUseWalletConnect = ! isMetaMaskInjected && ! isMobile ( ) ;
76
+ const shouldUseMetaMaskConnector = isMetaMaskInjected || isMobile ( ) ;
80
77
81
78
return {
82
79
id : 'metaMask' ,
@@ -85,7 +82,7 @@ export const metaMaskWallet = ({
85
82
iconUrl : async ( ) => ( await import ( './metaMaskWallet.svg' ) ) . default ,
86
83
iconAccent : '#f6851a' ,
87
84
iconBackground : '#fff' ,
88
- installed : ! shouldUseWalletConnect ? isMetaMaskInjected : undefined ,
85
+ installed : isMetaMaskInjected ? isMetaMaskInjected : undefined ,
89
86
downloadUrls : {
90
87
android : 'https://play.google.com/store/apps/details?id=io.metamask' ,
91
88
ios : 'https://apps.apple.com/us/app/metamask/id1438144202' ,
@@ -98,13 +95,14 @@ export const metaMaskWallet = ({
98
95
opera : 'https://addons.opera.com/extensions/details/metamask-10' ,
99
96
browserExtension : 'https://metamask.io/download' ,
100
97
} ,
101
-
102
98
mobile : {
103
- getUri : shouldUseWalletConnect ? getUri : undefined ,
99
+ // MetaMask mobile deep linking handled by wagmi, return URI unchanged.
100
+ getUri : shouldUseMetaMaskConnector ? ( uri : string ) => uri : undefined ,
104
101
} ,
105
102
qrCode : shouldUseWalletConnect
106
103
? {
107
- getUri,
104
+ getUri : ( uri : string ) =>
105
+ `https://metamask.app.link/wc?uri=${ encodeURIComponent ( uri ) } ` ,
108
106
instructions : {
109
107
learnMoreUrl : 'https://metamask.io/faqs/' ,
110
108
steps : [
@@ -160,13 +158,39 @@ export const metaMaskWallet = ({
160
158
projectId,
161
159
walletConnectParameters,
162
160
} )
163
- : getInjectedConnector ( {
164
- target :
165
- typeof window !== 'undefined'
166
- ? ( window as WindowProvider ) . ethereum ?. providers ?. find (
167
- isMetaMask ,
168
- ) ?? window . ethereum
169
- : undefined ,
170
- } ) ,
161
+ : // MetaMask connector
162
+ ( walletDetails : WalletDetailsParams ) => {
163
+ return createConnector ( ( config ) => {
164
+ const metamaskConnector = metaMask ( {
165
+ dappMetadata : {
166
+ connector : 'rainbowkit' ,
167
+ name : walletConnectParameters ?. metadata ?. name ,
168
+ iconUrl : walletConnectParameters ?. metadata ?. icons [ 0 ] ,
169
+ url : walletConnectParameters ?. metadata ?. url ,
170
+ } ,
171
+ headless : true ,
172
+ checkInstallationImmediately : false ,
173
+ enableAnalytics : false ,
174
+ } ) ( config ) ;
175
+
176
+ /**
177
+ * Override getChainId to avoid metamask error
178
+ *
179
+ * @see https://github.com/rainbow-me/rainbowkit/blob/cdcaa25d66b522119852502f71c8efc02b1abdd9/packages/rainbowkit/src/wallets/useWalletConnectors.ts#L57
180
+ * And @see https://github.com/wevm/wagmi/blob/275cccb51437908a2d7d3dab0549c6050b6340d3/packages/connectors/src/metaMask.ts#L154
181
+ */
182
+ return {
183
+ ...metamaskConnector ,
184
+ ...walletDetails ,
185
+ getChainId : async ( ) => {
186
+ try {
187
+ return await metamaskConnector . getChainId ( ) ;
188
+ } catch {
189
+ return config . chains [ 0 ] ?. id ?? 1 ;
190
+ }
191
+ } ,
192
+ } ;
193
+ } ) ;
194
+ } ,
171
195
} ;
172
196
} ;
0 commit comments