@wagmi/connectors 5.0.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/coinbaseWallet.js +274 -36
- package/dist/esm/coinbaseWallet.js.map +1 -1
- package/dist/esm/metaMask.js +67 -96
- package/dist/esm/metaMask.js.map +1 -1
- package/dist/esm/safe.js +20 -13
- package/dist/esm/safe.js.map +1 -1
- package/dist/esm/tsconfig.build.tsbuildinfo +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/walletConnect.js +147 -77
- package/dist/esm/walletConnect.js.map +1 -1
- package/dist/types/coinbaseWallet.d.ts +38 -7
- package/dist/types/coinbaseWallet.d.ts.map +1 -1
- package/dist/types/metaMask.d.ts +3 -10
- package/dist/types/metaMask.d.ts.map +1 -1
- package/dist/types/safe.d.ts +2 -2
- package/dist/types/safe.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/walletConnect.d.ts +5 -9
- package/dist/types/walletConnect.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/coinbaseWallet.ts +378 -66
- package/src/metaMask.ts +81 -110
- package/src/safe.ts +29 -14
- package/src/version.ts +1 -1
- package/src/walletConnect.ts +173 -99
- package/dist/esm/exports/index.test-d.js +0 -4
- package/dist/esm/exports/index.test-d.js.map +0 -1
- package/dist/types/exports/index.test-d.d.ts +0 -2
- package/dist/types/exports/index.test-d.d.ts.map +0 -1
package/src/metaMask.ts
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EventType,
|
|
1
|
+
import type {
|
|
3
2
|
MetaMaskSDK,
|
|
4
|
-
|
|
3
|
+
MetaMaskSDKOptions,
|
|
5
4
|
SDKProvider,
|
|
6
5
|
} from '@metamask/sdk'
|
|
6
|
+
import { ChainNotConfiguredError, createConnector } from '@wagmi/core'
|
|
7
|
+
import type { Evaluate, ExactPartial } from '@wagmi/core/internal'
|
|
7
8
|
import {
|
|
8
|
-
|
|
9
|
-
createConnector,
|
|
10
|
-
normalizeChainId,
|
|
11
|
-
} from '@wagmi/core'
|
|
12
|
-
import type { Evaluate, ExactPartial, Omit } from '@wagmi/core/internal'
|
|
13
|
-
import {
|
|
9
|
+
type AddEthereumChainParameter,
|
|
14
10
|
type Address,
|
|
15
11
|
type ProviderConnectInfo,
|
|
16
12
|
type ProviderRpcError,
|
|
@@ -18,31 +14,15 @@ import {
|
|
|
18
14
|
RpcError,
|
|
19
15
|
SwitchChainError,
|
|
20
16
|
UserRejectedRequestError,
|
|
21
|
-
type WalletPermission,
|
|
22
17
|
getAddress,
|
|
23
18
|
numberToHex,
|
|
24
19
|
} from 'viem'
|
|
25
20
|
|
|
26
21
|
export type MetaMaskParameters = Evaluate<
|
|
27
|
-
ExactPartial<
|
|
28
|
-
Omit<
|
|
29
|
-
MetaMaskSDKOptions,
|
|
30
|
-
| 'checkInstallationImmediately'
|
|
31
|
-
| 'checkInstallationOnAllCalls'
|
|
32
|
-
| 'defaultReadOnlyChainId'
|
|
33
|
-
| 'readonlyRPCMap'
|
|
34
|
-
>
|
|
35
|
-
>
|
|
22
|
+
ExactPartial<Omit<MetaMaskSDKOptions, '_source' | 'readonlyRPCMap'>>
|
|
36
23
|
>
|
|
37
24
|
|
|
38
25
|
metaMask.type = 'metaMask' as const
|
|
39
|
-
/**
|
|
40
|
-
* @deprecated
|
|
41
|
-
*
|
|
42
|
-
* __Warning__ This connector has a large file size due to the underlying `@metamask/sdk`. For mobile
|
|
43
|
-
* support, it is recommended to use {@link walletConnect}. For desktop support, you should rely on Multi Injected
|
|
44
|
-
* Provider Discovery (EIP-6963) via the Wagmi {@link Config}.
|
|
45
|
-
*/
|
|
46
26
|
export function metaMask(parameters: MetaMaskParameters = {}) {
|
|
47
27
|
type Provider = SDKProvider
|
|
48
28
|
type Properties = {
|
|
@@ -52,7 +32,8 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
|
|
|
52
32
|
type Listener = Parameters<Provider['on']>[1]
|
|
53
33
|
|
|
54
34
|
let sdk: MetaMaskSDK
|
|
55
|
-
let
|
|
35
|
+
let provider: Provider | undefined
|
|
36
|
+
let providerPromise: Promise<typeof provider>
|
|
56
37
|
|
|
57
38
|
return createConnector<Provider, Properties, StorageItem>((config) => ({
|
|
58
39
|
id: 'metaMaskSDK',
|
|
@@ -66,33 +47,13 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
|
|
|
66
47
|
async connect({ chainId, isReconnecting } = {}) {
|
|
67
48
|
const provider = await this.getProvider()
|
|
68
49
|
|
|
69
|
-
let accounts: readonly Address[]
|
|
70
|
-
if (
|
|
71
|
-
accounts = await this.getAccounts().catch(() => null)
|
|
72
|
-
const isAuthorized = !!accounts?.length
|
|
73
|
-
if (isAuthorized)
|
|
74
|
-
// Attempt to show another prompt for selecting account if already connected
|
|
75
|
-
try {
|
|
76
|
-
const permissions = (await provider.request({
|
|
77
|
-
method: 'wallet_requestPermissions',
|
|
78
|
-
params: [{ eth_accounts: {} }],
|
|
79
|
-
})) as WalletPermission[]
|
|
80
|
-
accounts = permissions[0]?.caveats?.[0]?.value?.map(getAddress)
|
|
81
|
-
} catch (err) {
|
|
82
|
-
const error = err as RpcError
|
|
83
|
-
// Not all injected providers support `wallet_requestPermissions` (e.g. MetaMask iOS).
|
|
84
|
-
// Only bubble up error if user rejects request
|
|
85
|
-
if (error.code === UserRejectedRequestError.code)
|
|
86
|
-
throw new UserRejectedRequestError(error)
|
|
87
|
-
// Or prompt is already open
|
|
88
|
-
if (error.code === ResourceUnavailableRpcError.code) throw error
|
|
89
|
-
}
|
|
90
|
-
}
|
|
50
|
+
let accounts: readonly Address[] = []
|
|
51
|
+
if (isReconnecting) accounts = await this.getAccounts().catch(() => [])
|
|
91
52
|
|
|
92
53
|
try {
|
|
93
54
|
if (!accounts?.length) {
|
|
94
55
|
const requestedAccounts = (await sdk.connect()) as string[]
|
|
95
|
-
accounts = requestedAccounts.map(getAddress)
|
|
56
|
+
accounts = requestedAccounts.map((x) => getAddress(x))
|
|
96
57
|
}
|
|
97
58
|
|
|
98
59
|
provider.removeListener(
|
|
@@ -106,20 +67,8 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
|
|
|
106
67
|
provider.on('chainChanged', this.onChainChanged as Listener)
|
|
107
68
|
provider.on('disconnect', this.onDisconnect.bind(this) as Listener)
|
|
108
69
|
|
|
109
|
-
// Backward compatibility with older wallet (<7.3) version that return accounts before authorization
|
|
110
|
-
if (!sdk.isExtensionActive() && !sdk._getConnection()?.isAuthorized()) {
|
|
111
|
-
function waitForAuthorized() {
|
|
112
|
-
return new Promise((resolve) => {
|
|
113
|
-
const connection = sdk._getConnection()
|
|
114
|
-
const connector = connection?.getConnector()
|
|
115
|
-
connector?.once(EventType.AUTHORIZED, () => resolve(true))
|
|
116
|
-
})
|
|
117
|
-
}
|
|
118
|
-
await waitForAuthorized()
|
|
119
|
-
}
|
|
120
|
-
|
|
121
70
|
// Switch to chain if provided
|
|
122
|
-
let currentChainId = await this.getChainId()
|
|
71
|
+
let currentChainId = (await this.getChainId()) as number
|
|
123
72
|
if (chainId && currentChainId !== chainId) {
|
|
124
73
|
const chain = await this.switchChain!({ chainId }).catch((error) => {
|
|
125
74
|
if (error.code === UserRejectedRequestError.code) throw error
|
|
@@ -161,48 +110,51 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
|
|
|
161
110
|
const accounts = (await provider.request({
|
|
162
111
|
method: 'eth_accounts',
|
|
163
112
|
})) as string[]
|
|
164
|
-
return accounts.map(getAddress)
|
|
113
|
+
return accounts.map((x) => getAddress(x))
|
|
165
114
|
},
|
|
166
115
|
async getChainId() {
|
|
167
116
|
const provider = await this.getProvider()
|
|
168
117
|
const chainId =
|
|
169
|
-
provider.
|
|
170
|
-
|
|
118
|
+
provider.getChainId() ||
|
|
119
|
+
(await provider?.request({ method: 'eth_chainId' }))
|
|
120
|
+
return Number(chainId)
|
|
171
121
|
},
|
|
172
122
|
async getProvider() {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
try {
|
|
195
|
-
walletProvider = sdk.getProvider()
|
|
196
|
-
} catch (error) {
|
|
197
|
-
// TODO: SDK sometimes throws errors when MM extension or mobile provider is not detected (don't throw for those errors)
|
|
198
|
-
const regex = /^SDK state invalid -- undefined( mobile)? provider$/
|
|
199
|
-
if (!regex.test((error as Error).message)) throw error
|
|
200
|
-
}
|
|
123
|
+
async function initProvider() {
|
|
124
|
+
const { MetaMaskSDK } = await import('@metamask/sdk')
|
|
125
|
+
sdk = new MetaMaskSDK({
|
|
126
|
+
dappMetadata: {},
|
|
127
|
+
...parameters,
|
|
128
|
+
_source: 'wagmi',
|
|
129
|
+
readonlyRPCMap: Object.fromEntries(
|
|
130
|
+
config.chains.map((chain) => [
|
|
131
|
+
chain.id,
|
|
132
|
+
chain.rpcUrls.default.http[0]!,
|
|
133
|
+
]),
|
|
134
|
+
),
|
|
135
|
+
})
|
|
136
|
+
await sdk.init()
|
|
137
|
+
return sdk.getProvider()!
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!provider) {
|
|
141
|
+
if (!providerPromise) providerPromise = initProvider()
|
|
142
|
+
provider = await providerPromise
|
|
201
143
|
}
|
|
202
|
-
return
|
|
144
|
+
return provider!
|
|
203
145
|
},
|
|
204
146
|
async isAuthorized() {
|
|
205
147
|
try {
|
|
148
|
+
const isMobileBrowser =
|
|
149
|
+
typeof navigator !== 'undefined'
|
|
150
|
+
? /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
151
|
+
navigator.userAgent,
|
|
152
|
+
)
|
|
153
|
+
: false
|
|
154
|
+
|
|
155
|
+
// MetaMask Mobile doesn't support persisted sessions.
|
|
156
|
+
if (isMobileBrowser) return false
|
|
157
|
+
|
|
206
158
|
const isDisconnected =
|
|
207
159
|
// If shim exists in storage, connector is disconnected
|
|
208
160
|
await config.storage?.getItem('metaMaskSDK.disconnected')
|
|
@@ -214,7 +166,7 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
|
|
|
214
166
|
return false
|
|
215
167
|
}
|
|
216
168
|
},
|
|
217
|
-
async switchChain({ chainId }) {
|
|
169
|
+
async switchChain({ addEthereumChainParameter, chainId }) {
|
|
218
170
|
const provider = await this.getProvider()
|
|
219
171
|
|
|
220
172
|
const chain = config.chains.find((x) => x.id === chainId)
|
|
@@ -247,24 +199,34 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
|
|
|
247
199
|
try {
|
|
248
200
|
const { default: blockExplorer, ...blockExplorers } =
|
|
249
201
|
chain.blockExplorers ?? {}
|
|
250
|
-
let blockExplorerUrls
|
|
251
|
-
if (
|
|
202
|
+
let blockExplorerUrls
|
|
203
|
+
if (addEthereumChainParameter?.blockExplorerUrls)
|
|
204
|
+
blockExplorerUrls = addEthereumChainParameter.blockExplorerUrls
|
|
205
|
+
else if (blockExplorer)
|
|
252
206
|
blockExplorerUrls = [
|
|
253
207
|
blockExplorer.url,
|
|
254
208
|
...Object.values(blockExplorers).map((x) => x.url),
|
|
255
209
|
]
|
|
256
210
|
|
|
211
|
+
let rpcUrls
|
|
212
|
+
if (addEthereumChainParameter?.rpcUrls?.length)
|
|
213
|
+
rpcUrls = addEthereumChainParameter.rpcUrls
|
|
214
|
+
else rpcUrls = [chain.rpcUrls.default?.http[0] ?? '']
|
|
215
|
+
|
|
216
|
+
const addEthereumChain = {
|
|
217
|
+
blockExplorerUrls,
|
|
218
|
+
chainId: numberToHex(chainId),
|
|
219
|
+
chainName: addEthereumChainParameter?.chainName ?? chain.name,
|
|
220
|
+
iconUrls: addEthereumChainParameter?.iconUrls,
|
|
221
|
+
nativeCurrency:
|
|
222
|
+
addEthereumChainParameter?.nativeCurrency ??
|
|
223
|
+
chain.nativeCurrency,
|
|
224
|
+
rpcUrls,
|
|
225
|
+
} satisfies AddEthereumChainParameter
|
|
226
|
+
|
|
257
227
|
await provider.request({
|
|
258
228
|
method: 'wallet_addEthereumChain',
|
|
259
|
-
params: [
|
|
260
|
-
{
|
|
261
|
-
chainId: numberToHex(chainId),
|
|
262
|
-
chainName: chain.name,
|
|
263
|
-
nativeCurrency: chain.nativeCurrency,
|
|
264
|
-
rpcUrls: [chain.rpcUrls.default?.http[0] ?? ''],
|
|
265
|
-
blockExplorerUrls,
|
|
266
|
-
},
|
|
267
|
-
],
|
|
229
|
+
params: [addEthereumChain],
|
|
268
230
|
})
|
|
269
231
|
|
|
270
232
|
const currentChainId = await this.getChainId()
|
|
@@ -294,17 +256,20 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
|
|
|
294
256
|
await config.storage?.removeItem('metaMaskSDK.disconnected')
|
|
295
257
|
}
|
|
296
258
|
// Regular change event
|
|
297
|
-
else
|
|
259
|
+
else
|
|
260
|
+
config.emitter.emit('change', {
|
|
261
|
+
accounts: accounts.map((x) => getAddress(x)),
|
|
262
|
+
})
|
|
298
263
|
},
|
|
299
264
|
onChainChanged(chain) {
|
|
300
|
-
const chainId =
|
|
265
|
+
const chainId = Number(chain)
|
|
301
266
|
config.emitter.emit('change', { chainId })
|
|
302
267
|
},
|
|
303
268
|
async onConnect(connectInfo) {
|
|
304
269
|
const accounts = await this.getAccounts()
|
|
305
270
|
if (accounts.length === 0) return
|
|
306
271
|
|
|
307
|
-
const chainId =
|
|
272
|
+
const chainId = Number(connectInfo.chainId)
|
|
308
273
|
config.emitter.emit('connect', { accounts, chainId })
|
|
309
274
|
|
|
310
275
|
const provider = await this.getProvider()
|
|
@@ -324,6 +289,12 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
|
|
|
324
289
|
if (provider && !!(await this.getAccounts()).length) return
|
|
325
290
|
}
|
|
326
291
|
|
|
292
|
+
// Remove cached SDK properties.
|
|
293
|
+
if (typeof localStorage !== 'undefined') {
|
|
294
|
+
localStorage.removeItem('MMSDK_cached_address')
|
|
295
|
+
localStorage.removeItem('MMSDK_cached_chainId')
|
|
296
|
+
}
|
|
297
|
+
|
|
327
298
|
// No need to remove 'metaMaskSDK.disconnected' from storage because `onDisconnect` is typically
|
|
328
299
|
// only called when the wallet is disconnected through the wallet's interface, meaning the wallet
|
|
329
300
|
// actually disconnected and we don't need to simulate it.
|
package/src/safe.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { SafeAppProvider } from '@safe-global/safe-apps-provider'
|
|
2
|
-
import {
|
|
1
|
+
import type { SafeAppProvider } from '@safe-global/safe-apps-provider'
|
|
2
|
+
import type { Opts } from '@safe-global/safe-apps-sdk'
|
|
3
3
|
import {
|
|
4
|
+
type Connector,
|
|
4
5
|
ProviderNotFoundError,
|
|
5
6
|
createConnector,
|
|
6
|
-
normalizeChainId,
|
|
7
7
|
} from '@wagmi/core'
|
|
8
8
|
import type { Evaluate } from '@wagmi/core/internal'
|
|
9
9
|
import { getAddress } from 'viem'
|
|
@@ -31,14 +31,8 @@ export function safe(parameters: SafeParameters = {}) {
|
|
|
31
31
|
type StorageItem = { 'safe.disconnected': true }
|
|
32
32
|
|
|
33
33
|
let provider_: Provider | undefined
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
typeof SafeAppsSDK !== 'function' &&
|
|
37
|
-
typeof SafeAppsSDK.default === 'function'
|
|
38
|
-
)
|
|
39
|
-
SDK = SafeAppsSDK.default
|
|
40
|
-
else SDK = SafeAppsSDK as unknown as typeof SafeAppsSDK.default
|
|
41
|
-
const sdk = new SDK(parameters)
|
|
34
|
+
|
|
35
|
+
let disconnect: Connector['onDisconnect'] | undefined
|
|
42
36
|
|
|
43
37
|
return createConnector<Provider, Properties, StorageItem>((config) => ({
|
|
44
38
|
id: 'safe',
|
|
@@ -51,7 +45,10 @@ export function safe(parameters: SafeParameters = {}) {
|
|
|
51
45
|
const accounts = await this.getAccounts()
|
|
52
46
|
const chainId = await this.getChainId()
|
|
53
47
|
|
|
54
|
-
|
|
48
|
+
if (!disconnect) {
|
|
49
|
+
disconnect = this.onDisconnect.bind(this)
|
|
50
|
+
provider.on('disconnect', disconnect)
|
|
51
|
+
}
|
|
55
52
|
|
|
56
53
|
// Remove disconnected shim if it exists
|
|
57
54
|
if (shimDisconnect) await config.storage?.removeItem('safe.disconnected')
|
|
@@ -62,7 +59,10 @@ export function safe(parameters: SafeParameters = {}) {
|
|
|
62
59
|
const provider = await this.getProvider()
|
|
63
60
|
if (!provider) throw new ProviderNotFoundError()
|
|
64
61
|
|
|
65
|
-
|
|
62
|
+
if (disconnect) {
|
|
63
|
+
provider.removeListener('disconnect', disconnect)
|
|
64
|
+
disconnect = undefined
|
|
65
|
+
}
|
|
66
66
|
|
|
67
67
|
// Add shim signalling connector is disconnected
|
|
68
68
|
if (shimDisconnect)
|
|
@@ -82,8 +82,23 @@ export function safe(parameters: SafeParameters = {}) {
|
|
|
82
82
|
if (!isIframe) return
|
|
83
83
|
|
|
84
84
|
if (!provider_) {
|
|
85
|
+
const { default: SafeAppsSDK } = await import(
|
|
86
|
+
'@safe-global/safe-apps-sdk'
|
|
87
|
+
)
|
|
88
|
+
let SDK: typeof SafeAppsSDK.default
|
|
89
|
+
if (
|
|
90
|
+
typeof SafeAppsSDK !== 'function' &&
|
|
91
|
+
typeof SafeAppsSDK.default === 'function'
|
|
92
|
+
)
|
|
93
|
+
SDK = SafeAppsSDK.default
|
|
94
|
+
else SDK = SafeAppsSDK as unknown as typeof SafeAppsSDK.default
|
|
95
|
+
const sdk = new SDK(parameters)
|
|
96
|
+
|
|
85
97
|
const safe = await sdk.safe.getInfo()
|
|
86
98
|
if (!safe) throw new Error('Could not load Safe information')
|
|
99
|
+
const { SafeAppProvider } = await import(
|
|
100
|
+
'@safe-global/safe-apps-provider'
|
|
101
|
+
)
|
|
87
102
|
provider_ = new SafeAppProvider(safe, sdk)
|
|
88
103
|
}
|
|
89
104
|
return provider_
|
|
@@ -91,7 +106,7 @@ export function safe(parameters: SafeParameters = {}) {
|
|
|
91
106
|
async getChainId() {
|
|
92
107
|
const provider = await this.getProvider()
|
|
93
108
|
if (!provider) throw new ProviderNotFoundError()
|
|
94
|
-
return
|
|
109
|
+
return Number(provider.chainId)
|
|
95
110
|
},
|
|
96
111
|
async isAuthorized() {
|
|
97
112
|
try {
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '5.0.
|
|
1
|
+
export const version = '5.0.1'
|