@metamask/connect-evm 0.1.0
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/CHANGELOG.md +17 -0
- package/LICENSE +20 -0
- package/README.md +134 -0
- package/dist/browser/es/connect-evm.mjs +794 -0
- package/dist/browser/es/connect-evm.mjs.map +1 -0
- package/dist/types/index.d.ts +272 -0
- package/package.json +81 -0
|
@@ -0,0 +1,794 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __typeError = (msg) => {
|
|
8
|
+
throw TypeError(msg);
|
|
9
|
+
};
|
|
10
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
|
+
var __spreadValues = (a, b) => {
|
|
12
|
+
for (var prop in b || (b = {}))
|
|
13
|
+
if (__hasOwnProp.call(b, prop))
|
|
14
|
+
__defNormalProp(a, prop, b[prop]);
|
|
15
|
+
if (__getOwnPropSymbols)
|
|
16
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
17
|
+
if (__propIsEnum.call(b, prop))
|
|
18
|
+
__defNormalProp(a, prop, b[prop]);
|
|
19
|
+
}
|
|
20
|
+
return a;
|
|
21
|
+
};
|
|
22
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
23
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
24
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
25
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
26
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
27
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
28
|
+
var __async = (__this, __arguments, generator) => {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
var fulfilled = (value) => {
|
|
31
|
+
try {
|
|
32
|
+
step(generator.next(value));
|
|
33
|
+
} catch (e) {
|
|
34
|
+
reject(e);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var rejected = (value) => {
|
|
38
|
+
try {
|
|
39
|
+
step(generator.throw(value));
|
|
40
|
+
} catch (e) {
|
|
41
|
+
reject(e);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
45
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// src/index.ts
|
|
50
|
+
import { getInfuraRpcUrls } from "@metamask/connect-multichain";
|
|
51
|
+
|
|
52
|
+
// src/connect.ts
|
|
53
|
+
import { analytics } from "@metamask/analytics";
|
|
54
|
+
import {
|
|
55
|
+
createMetamaskConnect,
|
|
56
|
+
getWalletActionAnalyticsProperties,
|
|
57
|
+
isRejectionError,
|
|
58
|
+
TransportType
|
|
59
|
+
} from "@metamask/connect-multichain";
|
|
60
|
+
import {
|
|
61
|
+
numberToHex as numberToHex2,
|
|
62
|
+
hexToNumber as hexToNumber2,
|
|
63
|
+
isHexString as isHex
|
|
64
|
+
} from "@metamask/utils";
|
|
65
|
+
|
|
66
|
+
// src/constants.ts
|
|
67
|
+
var IGNORED_METHODS = [
|
|
68
|
+
"metamask_getProviderState",
|
|
69
|
+
"metamask_sendDomainMetadata",
|
|
70
|
+
"metamask_logWeb3ShimUsage",
|
|
71
|
+
"wallet_registerOnboarding",
|
|
72
|
+
"net_version",
|
|
73
|
+
"wallet_getPermissions"
|
|
74
|
+
];
|
|
75
|
+
var CONNECT_METHODS = [
|
|
76
|
+
"wallet_requestPermissions",
|
|
77
|
+
"eth_requestAccounts"
|
|
78
|
+
];
|
|
79
|
+
var ACCOUNTS_METHODS = ["eth_accounts", "eth_coinbase"];
|
|
80
|
+
var INTERCEPTABLE_METHODS = [
|
|
81
|
+
...ACCOUNTS_METHODS,
|
|
82
|
+
...IGNORED_METHODS,
|
|
83
|
+
...CONNECT_METHODS,
|
|
84
|
+
// These have bespoke handlers
|
|
85
|
+
"wallet_revokePermissions",
|
|
86
|
+
"wallet_switchEthereumChain",
|
|
87
|
+
"wallet_addEthereumChain"
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
// src/logger.ts
|
|
91
|
+
import {
|
|
92
|
+
createLogger,
|
|
93
|
+
enableDebug as debug
|
|
94
|
+
} from "@metamask/connect-multichain";
|
|
95
|
+
var namespace = "metamask-connect:evm";
|
|
96
|
+
var logger = createLogger(namespace, "63");
|
|
97
|
+
var enableDebug = (debugEnabled = false) => {
|
|
98
|
+
if (debugEnabled) {
|
|
99
|
+
debug(namespace);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// src/provider.ts
|
|
104
|
+
import { EventEmitter } from "@metamask/connect-multichain";
|
|
105
|
+
import { hexToNumber, numberToHex } from "@metamask/utils";
|
|
106
|
+
var _core, _requestInterceptor, _accounts, _selectedChainId;
|
|
107
|
+
var EIP1193Provider = class extends EventEmitter {
|
|
108
|
+
constructor(core, interceptor) {
|
|
109
|
+
super();
|
|
110
|
+
/** The core instance of the Multichain SDK */
|
|
111
|
+
__privateAdd(this, _core);
|
|
112
|
+
/** Interceptor function to handle specific methods */
|
|
113
|
+
__privateAdd(this, _requestInterceptor);
|
|
114
|
+
/** The currently permitted accounts */
|
|
115
|
+
__privateAdd(this, _accounts, []);
|
|
116
|
+
/** The currently selected chain ID on the wallet */
|
|
117
|
+
__privateAdd(this, _selectedChainId);
|
|
118
|
+
__privateSet(this, _core, core);
|
|
119
|
+
__privateSet(this, _requestInterceptor, interceptor);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Performs a EIP-1193 request.
|
|
123
|
+
*
|
|
124
|
+
* @param request - The request object containing the method and params
|
|
125
|
+
* @returns The result of the request
|
|
126
|
+
*/
|
|
127
|
+
request(request) {
|
|
128
|
+
return __async(this, null, function* () {
|
|
129
|
+
var _a, _b, _c;
|
|
130
|
+
logger(
|
|
131
|
+
`request: ${request.method} - chainId: ${this.selectedChainId}`,
|
|
132
|
+
request.params
|
|
133
|
+
);
|
|
134
|
+
if (INTERCEPTABLE_METHODS.includes(request.method)) {
|
|
135
|
+
return (_a = __privateGet(this, _requestInterceptor)) == null ? void 0 : _a.call(this, request);
|
|
136
|
+
}
|
|
137
|
+
if (!__privateGet(this, _selectedChainId)) {
|
|
138
|
+
throw new Error("No chain ID selected");
|
|
139
|
+
}
|
|
140
|
+
const chainId = hexToNumber(__privateGet(this, _selectedChainId));
|
|
141
|
+
const scope = `eip155:${chainId}`;
|
|
142
|
+
const coreOptions = __privateGet(this, _core).options;
|
|
143
|
+
const supportedNetworks = (_c = (_b = coreOptions == null ? void 0 : coreOptions.api) == null ? void 0 : _b.supportedNetworks) != null ? _c : {};
|
|
144
|
+
if (!supportedNetworks[scope]) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
`Chain ${scope} is not configured in supportedNetworks. Requests cannot be made to chains not explicitly configured in supportedNetworks.`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return __privateGet(this, _core).invokeMethod({
|
|
150
|
+
scope,
|
|
151
|
+
request: {
|
|
152
|
+
method: request.method,
|
|
153
|
+
params: request.params
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
// Getters and setters
|
|
159
|
+
get selectedAccount() {
|
|
160
|
+
return this.accounts[0];
|
|
161
|
+
}
|
|
162
|
+
set accounts(accounts) {
|
|
163
|
+
__privateSet(this, _accounts, accounts);
|
|
164
|
+
}
|
|
165
|
+
get accounts() {
|
|
166
|
+
return __privateGet(this, _accounts);
|
|
167
|
+
}
|
|
168
|
+
get selectedChainId() {
|
|
169
|
+
return __privateGet(this, _selectedChainId);
|
|
170
|
+
}
|
|
171
|
+
set selectedChainId(chainId) {
|
|
172
|
+
const hexChainId = chainId && typeof chainId === "number" ? numberToHex(chainId) : chainId;
|
|
173
|
+
if (!hexChainId) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
__privateSet(this, _selectedChainId, hexChainId);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
_core = new WeakMap();
|
|
180
|
+
_requestInterceptor = new WeakMap();
|
|
181
|
+
_accounts = new WeakMap();
|
|
182
|
+
_selectedChainId = new WeakMap();
|
|
183
|
+
|
|
184
|
+
// src/utils/caip.ts
|
|
185
|
+
import {
|
|
186
|
+
getPermittedEthChainIds as _getPermittedEthChainIds,
|
|
187
|
+
getEthAccounts as _getEthAccounts
|
|
188
|
+
} from "@metamask/chain-agnostic-permission";
|
|
189
|
+
var getPermittedEthChainIds = (sessionScopes) => {
|
|
190
|
+
if (!sessionScopes) {
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
return _getPermittedEthChainIds({
|
|
194
|
+
requiredScopes: sessionScopes,
|
|
195
|
+
optionalScopes: sessionScopes
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// src/utils/type-guards.ts
|
|
200
|
+
function isConnectRequest(req) {
|
|
201
|
+
return req.method === "wallet_requestPermissions" || req.method === "eth_requestAccounts";
|
|
202
|
+
}
|
|
203
|
+
function isSwitchChainRequest(req) {
|
|
204
|
+
return req.method === "wallet_switchEthereumChain";
|
|
205
|
+
}
|
|
206
|
+
function isAddChainRequest(req) {
|
|
207
|
+
return req.method === "wallet_addEthereumChain";
|
|
208
|
+
}
|
|
209
|
+
function isAccountsRequest(req) {
|
|
210
|
+
return req.method === "eth_accounts" || req.method === "eth_coinbase";
|
|
211
|
+
}
|
|
212
|
+
function validSupportedChainsUrls(record, recordName) {
|
|
213
|
+
const invalidUrls = [];
|
|
214
|
+
for (const [key, url] of Object.entries(record)) {
|
|
215
|
+
try {
|
|
216
|
+
new URL(url);
|
|
217
|
+
} catch (e) {
|
|
218
|
+
invalidUrls.push(`${key}: ${url}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (invalidUrls.length > 0) {
|
|
222
|
+
throw new Error(
|
|
223
|
+
`${recordName} contains invalid URLs:
|
|
224
|
+
${invalidUrls.join("\n")}`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// src/connect.ts
|
|
230
|
+
var DEFAULT_CHAIN_ID = 1;
|
|
231
|
+
var _core2, _provider, _sessionScopes, _eventHandlers, _sessionChangedHandler, _MetamaskConnectEVM_instances, getCoreOptions_fn, createInvokeOptions_fn, trackWalletActionRequested_fn, trackWalletActionSucceeded_fn, trackWalletActionFailed_fn, requestInterceptor_fn, clearConnectionState_fn, addEthereumChain_fn, request_fn, onChainChanged_fn, onAccountsChanged_fn, onConnect_fn, onDisconnect_fn, attemptSessionRecovery_fn;
|
|
232
|
+
var MetamaskConnectEVM = class {
|
|
233
|
+
/**
|
|
234
|
+
* Creates a new MetamaskConnectEVM instance.
|
|
235
|
+
*
|
|
236
|
+
* @param options - The options for the MetamaskConnectEVM instance
|
|
237
|
+
* @param options.core - The core instance of the Multichain SDK
|
|
238
|
+
* @param options.eventHandlers - Optional event handlers for EIP-1193 provider events
|
|
239
|
+
*/
|
|
240
|
+
constructor({ core, eventHandlers }) {
|
|
241
|
+
__privateAdd(this, _MetamaskConnectEVM_instances);
|
|
242
|
+
/** The core instance of the Multichain SDK */
|
|
243
|
+
__privateAdd(this, _core2);
|
|
244
|
+
/** An instance of the EIP-1193 provider interface */
|
|
245
|
+
__privateAdd(this, _provider);
|
|
246
|
+
/** The session scopes currently permitted */
|
|
247
|
+
__privateAdd(this, _sessionScopes, {});
|
|
248
|
+
/** Optional event handlers for the EIP-1193 provider events. */
|
|
249
|
+
__privateAdd(this, _eventHandlers);
|
|
250
|
+
/** The handler for the wallet_sessionChanged event */
|
|
251
|
+
__privateAdd(this, _sessionChangedHandler);
|
|
252
|
+
__privateSet(this, _core2, core);
|
|
253
|
+
__privateSet(this, _provider, new EIP1193Provider(
|
|
254
|
+
core,
|
|
255
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, requestInterceptor_fn).bind(this)
|
|
256
|
+
));
|
|
257
|
+
__privateSet(this, _eventHandlers, eventHandlers);
|
|
258
|
+
__privateSet(this, _sessionChangedHandler, (session) => {
|
|
259
|
+
var _a;
|
|
260
|
+
logger("event: wallet_sessionChanged", session);
|
|
261
|
+
__privateSet(this, _sessionScopes, (_a = session == null ? void 0 : session.sessionScopes) != null ? _a : {});
|
|
262
|
+
});
|
|
263
|
+
__privateGet(this, _core2).on(
|
|
264
|
+
"wallet_sessionChanged",
|
|
265
|
+
__privateGet(this, _sessionChangedHandler).bind(this)
|
|
266
|
+
);
|
|
267
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, attemptSessionRecovery_fn).call(this).catch((error) => {
|
|
268
|
+
console.error("Error attempting session recovery", error);
|
|
269
|
+
});
|
|
270
|
+
logger("Connect/EVM constructor completed");
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Connects to the wallet with the specified chain ID and optional account.
|
|
274
|
+
*
|
|
275
|
+
* @param options - The connection options
|
|
276
|
+
* @param options.chainId - The chain ID to connect to (defaults to 1 for mainnet)
|
|
277
|
+
* @param options.account - Optional specific account to connect to
|
|
278
|
+
* @param options.forceRequest - Wwhether to force a request regardless of an existing session
|
|
279
|
+
* @returns A promise that resolves with the connected accounts and chain ID
|
|
280
|
+
*/
|
|
281
|
+
connect() {
|
|
282
|
+
return __async(this, arguments, function* ({
|
|
283
|
+
chainId,
|
|
284
|
+
account,
|
|
285
|
+
forceRequest
|
|
286
|
+
} = { chainId: DEFAULT_CHAIN_ID }) {
|
|
287
|
+
logger("request: connect", { chainId, account });
|
|
288
|
+
const caipChainId = chainId ? [`eip155:${chainId}`] : [];
|
|
289
|
+
const caipAccountId = chainId && account ? [`eip155:${chainId}:${account}`] : [];
|
|
290
|
+
yield __privateGet(this, _core2).connect(caipChainId, caipAccountId, forceRequest);
|
|
291
|
+
const hexPermittedChainIds = getPermittedEthChainIds(__privateGet(this, _sessionScopes));
|
|
292
|
+
const initialChainId = hexPermittedChainIds[0];
|
|
293
|
+
const initialAccounts = yield __privateGet(this, _core2).transport.sendEip1193Message({ method: "eth_accounts", params: [] });
|
|
294
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, onConnect_fn).call(this, {
|
|
295
|
+
chainId: initialChainId,
|
|
296
|
+
accounts: initialAccounts.result
|
|
297
|
+
});
|
|
298
|
+
__privateGet(this, _core2).transport.onNotification((notification) => {
|
|
299
|
+
var _a;
|
|
300
|
+
if ((notification == null ? void 0 : notification.method) === "metamask_accountsChanged") {
|
|
301
|
+
const accounts = notification == null ? void 0 : notification.params;
|
|
302
|
+
logger("transport-event: accountsChanged", accounts);
|
|
303
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, onAccountsChanged_fn).call(this, accounts);
|
|
304
|
+
}
|
|
305
|
+
if ((notification == null ? void 0 : notification.method) === "metamask_chainChanged") {
|
|
306
|
+
const notificationChainId = Number((_a = notification == null ? void 0 : notification.params) == null ? void 0 : _a.chainId);
|
|
307
|
+
logger("transport-event: chainChanged", notificationChainId);
|
|
308
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, onChainChanged_fn).call(this, notificationChainId);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
logger("fulfilled-request: connect", {
|
|
312
|
+
chainId,
|
|
313
|
+
accounts: __privateGet(this, _provider).accounts
|
|
314
|
+
});
|
|
315
|
+
return {
|
|
316
|
+
accounts: __privateGet(this, _provider).accounts,
|
|
317
|
+
chainId: hexToNumber2(initialChainId)
|
|
318
|
+
};
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Connects to the wallet and signs a message using personal_sign.
|
|
323
|
+
*
|
|
324
|
+
* @param message - The message to sign
|
|
325
|
+
* @returns A promise that resolves with the signature
|
|
326
|
+
* @throws Error if the selected account is not available after timeout
|
|
327
|
+
*/
|
|
328
|
+
connectAndSign(message) {
|
|
329
|
+
return __async(this, null, function* () {
|
|
330
|
+
var _a, _b;
|
|
331
|
+
const { accounts, chainId } = yield this.connect();
|
|
332
|
+
const result = yield __privateGet(this, _provider).request({
|
|
333
|
+
method: "personal_sign",
|
|
334
|
+
params: [accounts[0], message]
|
|
335
|
+
});
|
|
336
|
+
(_b = (_a = __privateGet(this, _eventHandlers)) == null ? void 0 : _a.connectAndSign) == null ? void 0 : _b.call(_a, {
|
|
337
|
+
accounts,
|
|
338
|
+
chainId,
|
|
339
|
+
signResponse: result
|
|
340
|
+
});
|
|
341
|
+
return result;
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Connects to the wallet and invokes a method with specified parameters.
|
|
346
|
+
*
|
|
347
|
+
* @param options - The options for connecting and invoking the method
|
|
348
|
+
* @param options.method - The method name to invoke
|
|
349
|
+
* @param options.params - The parameters to pass to the method, or a function that receives the account and returns params
|
|
350
|
+
* @param options.chainId - Optional chain ID to connect to (defaults to mainnet)
|
|
351
|
+
* @param options.account - Optional specific account to connect to
|
|
352
|
+
* @param options.forceRequest - Whether to force a request regardless of an existing session
|
|
353
|
+
* @returns A promise that resolves with the result of the method invocation
|
|
354
|
+
* @throws Error if the selected account is not available after timeout (for methods that require an account)
|
|
355
|
+
*/
|
|
356
|
+
connectWith(_0) {
|
|
357
|
+
return __async(this, arguments, function* ({
|
|
358
|
+
method,
|
|
359
|
+
params,
|
|
360
|
+
chainId,
|
|
361
|
+
account,
|
|
362
|
+
forceRequest
|
|
363
|
+
}) {
|
|
364
|
+
var _a, _b;
|
|
365
|
+
const { accounts: connectedAccounts, chainId: connectedChainId } = yield this.connect({
|
|
366
|
+
chainId: chainId != null ? chainId : DEFAULT_CHAIN_ID,
|
|
367
|
+
account,
|
|
368
|
+
forceRequest
|
|
369
|
+
});
|
|
370
|
+
const resolvedParams = typeof params === "function" ? params(connectedAccounts[0]) : params;
|
|
371
|
+
const result = yield __privateGet(this, _provider).request({
|
|
372
|
+
method,
|
|
373
|
+
params: resolvedParams
|
|
374
|
+
});
|
|
375
|
+
(_b = (_a = __privateGet(this, _eventHandlers)) == null ? void 0 : _a.connectWith) == null ? void 0 : _b.call(_a, {
|
|
376
|
+
accounts: connectedAccounts,
|
|
377
|
+
chainId: connectedChainId,
|
|
378
|
+
connectWithResponse: result
|
|
379
|
+
});
|
|
380
|
+
return result;
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Disconnects from the wallet by revoking the session and cleaning up event listeners.
|
|
385
|
+
*
|
|
386
|
+
* @returns A promise that resolves when disconnection is complete
|
|
387
|
+
*/
|
|
388
|
+
disconnect() {
|
|
389
|
+
return __async(this, null, function* () {
|
|
390
|
+
logger("request: disconnect");
|
|
391
|
+
yield __privateGet(this, _core2).disconnect();
|
|
392
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, onDisconnect_fn).call(this);
|
|
393
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, clearConnectionState_fn).call(this);
|
|
394
|
+
__privateGet(this, _core2).off("wallet_sessionChanged", __privateGet(this, _sessionChangedHandler));
|
|
395
|
+
logger("fulfilled-request: disconnect");
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Switches the Ethereum chain. Will track state internally whenever possible.
|
|
400
|
+
*
|
|
401
|
+
* @param options - The options for the switch chain request
|
|
402
|
+
* @param options.chainId - The chain ID to switch to
|
|
403
|
+
* @param options.chainConfiguration - The chain configuration to use in case the chain is not present by the wallet
|
|
404
|
+
* @returns The result of the switch chain request
|
|
405
|
+
*/
|
|
406
|
+
switchChain(_0) {
|
|
407
|
+
return __async(this, arguments, function* ({
|
|
408
|
+
chainId,
|
|
409
|
+
chainConfiguration
|
|
410
|
+
}) {
|
|
411
|
+
const method = "wallet_switchEthereumChain";
|
|
412
|
+
const hexChainId = isHex(chainId) ? chainId : numberToHex2(chainId);
|
|
413
|
+
const scope = `eip155:${isHex(chainId) ? hexToNumber2(chainId) : chainId}`;
|
|
414
|
+
const params = [{ chainId: hexChainId }];
|
|
415
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionRequested_fn).call(this, method, scope, params);
|
|
416
|
+
if (this.selectedChainId === hexChainId) {
|
|
417
|
+
return Promise.resolve();
|
|
418
|
+
}
|
|
419
|
+
const permittedChainIds = getPermittedEthChainIds(__privateGet(this, _sessionScopes));
|
|
420
|
+
if (permittedChainIds.includes(hexChainId) && __privateGet(this, _core2).transportType === TransportType.MWP) {
|
|
421
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, onChainChanged_fn).call(this, hexChainId);
|
|
422
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionSucceeded_fn).call(this, method, scope, params);
|
|
423
|
+
return Promise.resolve();
|
|
424
|
+
}
|
|
425
|
+
try {
|
|
426
|
+
const result = yield __privateMethod(this, _MetamaskConnectEVM_instances, request_fn).call(this, {
|
|
427
|
+
method: "wallet_switchEthereumChain",
|
|
428
|
+
params
|
|
429
|
+
});
|
|
430
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionSucceeded_fn).call(this, method, scope, params);
|
|
431
|
+
return result;
|
|
432
|
+
} catch (error) {
|
|
433
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionFailed_fn).call(this, method, scope, params, error);
|
|
434
|
+
if (error.message.includes("Unrecognized chain ID")) {
|
|
435
|
+
return __privateMethod(this, _MetamaskConnectEVM_instances, addEthereumChain_fn).call(this, chainConfiguration);
|
|
436
|
+
}
|
|
437
|
+
throw error;
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Gets the EIP-1193 provider instance
|
|
443
|
+
*
|
|
444
|
+
* @returns The EIP-1193 provider instance
|
|
445
|
+
*/
|
|
446
|
+
getProvider() {
|
|
447
|
+
return __privateGet(this, _provider);
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Gets the currently selected chain ID on the wallet
|
|
451
|
+
*
|
|
452
|
+
* @returns The currently selected chain ID or undefined if no chain is selected
|
|
453
|
+
*/
|
|
454
|
+
getChainId() {
|
|
455
|
+
return this.selectedChainId;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Gets the currently selected account on the wallet
|
|
459
|
+
*
|
|
460
|
+
* @returns The currently selected account or undefined if no account is selected
|
|
461
|
+
*/
|
|
462
|
+
getAccount() {
|
|
463
|
+
return __privateGet(this, _provider).selectedAccount;
|
|
464
|
+
}
|
|
465
|
+
// Convenience getters for the EIP-1193 provider
|
|
466
|
+
/**
|
|
467
|
+
* Gets the currently permitted accounts
|
|
468
|
+
*
|
|
469
|
+
* @returns The currently permitted accounts
|
|
470
|
+
*/
|
|
471
|
+
get accounts() {
|
|
472
|
+
return __privateGet(this, _provider).accounts;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Gets the currently selected account on the wallet
|
|
476
|
+
*
|
|
477
|
+
* @returns The currently selected account or undefined if no account is selected
|
|
478
|
+
*/
|
|
479
|
+
get selectedAccount() {
|
|
480
|
+
return __privateGet(this, _provider).selectedAccount;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Gets the currently selected chain ID on the wallet
|
|
484
|
+
*
|
|
485
|
+
* @returns The currently selected chain ID or undefined if no chain is selected
|
|
486
|
+
*/
|
|
487
|
+
get selectedChainId() {
|
|
488
|
+
return __privateGet(this, _provider).selectedChainId;
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
_core2 = new WeakMap();
|
|
492
|
+
_provider = new WeakMap();
|
|
493
|
+
_sessionScopes = new WeakMap();
|
|
494
|
+
_eventHandlers = new WeakMap();
|
|
495
|
+
_sessionChangedHandler = new WeakMap();
|
|
496
|
+
_MetamaskConnectEVM_instances = new WeakSet();
|
|
497
|
+
/**
|
|
498
|
+
* Gets the core options for analytics checks.
|
|
499
|
+
*
|
|
500
|
+
* @returns The multichain options from the core instance
|
|
501
|
+
*/
|
|
502
|
+
getCoreOptions_fn = function() {
|
|
503
|
+
return __privateGet(this, _core2).options;
|
|
504
|
+
};
|
|
505
|
+
/**
|
|
506
|
+
* Creates invoke options for analytics tracking.
|
|
507
|
+
*
|
|
508
|
+
* @param method - The RPC method name
|
|
509
|
+
* @param scope - The CAIP chain ID scope
|
|
510
|
+
* @param params - The method parameters
|
|
511
|
+
* @returns Invoke options object for analytics
|
|
512
|
+
*/
|
|
513
|
+
createInvokeOptions_fn = function(method, scope, params) {
|
|
514
|
+
return {
|
|
515
|
+
scope,
|
|
516
|
+
request: { method, params }
|
|
517
|
+
};
|
|
518
|
+
};
|
|
519
|
+
trackWalletActionRequested_fn = function(method, scope, params) {
|
|
520
|
+
return __async(this, null, function* () {
|
|
521
|
+
var _a;
|
|
522
|
+
const coreOptions = __privateMethod(this, _MetamaskConnectEVM_instances, getCoreOptions_fn).call(this);
|
|
523
|
+
if (!((_a = coreOptions.analytics) == null ? void 0 : _a.enabled)) {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
try {
|
|
527
|
+
const invokeOptions = __privateMethod(this, _MetamaskConnectEVM_instances, createInvokeOptions_fn).call(this, method, scope, params);
|
|
528
|
+
const props = yield getWalletActionAnalyticsProperties(
|
|
529
|
+
coreOptions,
|
|
530
|
+
__privateGet(this, _core2).storage,
|
|
531
|
+
invokeOptions
|
|
532
|
+
);
|
|
533
|
+
analytics.track("mmconnect_wallet_action_requested", props);
|
|
534
|
+
} catch (error) {
|
|
535
|
+
logger("Error tracking mmconnect_wallet_action_requested event", error);
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
};
|
|
539
|
+
trackWalletActionSucceeded_fn = function(method, scope, params) {
|
|
540
|
+
return __async(this, null, function* () {
|
|
541
|
+
var _a;
|
|
542
|
+
const coreOptions = __privateMethod(this, _MetamaskConnectEVM_instances, getCoreOptions_fn).call(this);
|
|
543
|
+
if (!((_a = coreOptions.analytics) == null ? void 0 : _a.enabled)) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
try {
|
|
547
|
+
const invokeOptions = __privateMethod(this, _MetamaskConnectEVM_instances, createInvokeOptions_fn).call(this, method, scope, params);
|
|
548
|
+
const props = yield getWalletActionAnalyticsProperties(
|
|
549
|
+
coreOptions,
|
|
550
|
+
__privateGet(this, _core2).storage,
|
|
551
|
+
invokeOptions
|
|
552
|
+
);
|
|
553
|
+
analytics.track("mmconnect_wallet_action_succeeded", props);
|
|
554
|
+
} catch (error) {
|
|
555
|
+
logger("Error tracking mmconnect_wallet_action_succeeded event", error);
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
};
|
|
559
|
+
trackWalletActionFailed_fn = function(method, scope, params, error) {
|
|
560
|
+
return __async(this, null, function* () {
|
|
561
|
+
var _a;
|
|
562
|
+
const coreOptions = __privateMethod(this, _MetamaskConnectEVM_instances, getCoreOptions_fn).call(this);
|
|
563
|
+
if (!((_a = coreOptions.analytics) == null ? void 0 : _a.enabled)) {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
try {
|
|
567
|
+
const invokeOptions = __privateMethod(this, _MetamaskConnectEVM_instances, createInvokeOptions_fn).call(this, method, scope, params);
|
|
568
|
+
const props = yield getWalletActionAnalyticsProperties(
|
|
569
|
+
coreOptions,
|
|
570
|
+
__privateGet(this, _core2).storage,
|
|
571
|
+
invokeOptions
|
|
572
|
+
);
|
|
573
|
+
const isRejection = isRejectionError(error);
|
|
574
|
+
if (isRejection) {
|
|
575
|
+
analytics.track("mmconnect_wallet_action_rejected", props);
|
|
576
|
+
} else {
|
|
577
|
+
analytics.track("mmconnect_wallet_action_failed", props);
|
|
578
|
+
}
|
|
579
|
+
} catch (e) {
|
|
580
|
+
logger("Error tracking wallet action rejected or failed event", error);
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
};
|
|
584
|
+
requestInterceptor_fn = function(request) {
|
|
585
|
+
return __async(this, null, function* () {
|
|
586
|
+
logger(`Intercepting request for method: ${request.method}`);
|
|
587
|
+
if (IGNORED_METHODS.includes(request.method)) {
|
|
588
|
+
return Promise.reject(
|
|
589
|
+
new Error(
|
|
590
|
+
`Method: ${request.method} is not supported by Metamask Connect/EVM`
|
|
591
|
+
)
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
if (request.method === "wallet_revokePermissions") {
|
|
595
|
+
return this.disconnect();
|
|
596
|
+
}
|
|
597
|
+
if (isConnectRequest(request)) {
|
|
598
|
+
const shouldForceConnectionRequest = request.method === "wallet_requestPermissions";
|
|
599
|
+
const { method, params } = request;
|
|
600
|
+
const chainId = DEFAULT_CHAIN_ID;
|
|
601
|
+
const scope = `eip155:${chainId}`;
|
|
602
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionRequested_fn).call(this, method, scope, params);
|
|
603
|
+
try {
|
|
604
|
+
const result = yield this.connect({
|
|
605
|
+
chainId,
|
|
606
|
+
forceRequest: shouldForceConnectionRequest
|
|
607
|
+
});
|
|
608
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionSucceeded_fn).call(this, method, scope, params);
|
|
609
|
+
return result;
|
|
610
|
+
} catch (error) {
|
|
611
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionFailed_fn).call(this, method, scope, params, error);
|
|
612
|
+
throw error;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
if (isSwitchChainRequest(request)) {
|
|
616
|
+
return this.switchChain({
|
|
617
|
+
chainId: parseInt(request.params[0].chainId, 16)
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
if (isAddChainRequest(request)) {
|
|
621
|
+
return __privateMethod(this, _MetamaskConnectEVM_instances, addEthereumChain_fn).call(this, request.params[0]);
|
|
622
|
+
}
|
|
623
|
+
if (isAccountsRequest(request)) {
|
|
624
|
+
const { method } = request;
|
|
625
|
+
const chainId = __privateGet(this, _provider).selectedChainId ? hexToNumber2(__privateGet(this, _provider).selectedChainId) : 1;
|
|
626
|
+
const scope = `eip155:${chainId}`;
|
|
627
|
+
const params = [];
|
|
628
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionRequested_fn).call(this, method, scope, params);
|
|
629
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionSucceeded_fn).call(this, method, scope, params);
|
|
630
|
+
return __privateGet(this, _provider).accounts;
|
|
631
|
+
}
|
|
632
|
+
logger("Request not intercepted, forwarding to default handler", request);
|
|
633
|
+
return Promise.resolve();
|
|
634
|
+
});
|
|
635
|
+
};
|
|
636
|
+
/**
|
|
637
|
+
* Clears the internal connection state: accounts and chainId
|
|
638
|
+
*/
|
|
639
|
+
clearConnectionState_fn = function() {
|
|
640
|
+
__privateGet(this, _provider).accounts = [];
|
|
641
|
+
__privateGet(this, _provider).selectedChainId = void 0;
|
|
642
|
+
};
|
|
643
|
+
addEthereumChain_fn = function(chainConfiguration) {
|
|
644
|
+
return __async(this, null, function* () {
|
|
645
|
+
var _a;
|
|
646
|
+
logger("addEthereumChain called", { chainConfiguration });
|
|
647
|
+
const method = "wallet_addEthereumChain";
|
|
648
|
+
if (!chainConfiguration) {
|
|
649
|
+
throw new Error("No chain configuration found.");
|
|
650
|
+
}
|
|
651
|
+
const chainId = chainConfiguration.chainId ? parseInt(chainConfiguration.chainId, 16) : hexToNumber2((_a = __privateGet(this, _provider).selectedChainId) != null ? _a : "0x1");
|
|
652
|
+
const scope = `eip155:${chainId}`;
|
|
653
|
+
const params = [chainConfiguration];
|
|
654
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionRequested_fn).call(this, method, scope, params);
|
|
655
|
+
try {
|
|
656
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, request_fn).call(this, {
|
|
657
|
+
method: "wallet_addEthereumChain",
|
|
658
|
+
params
|
|
659
|
+
});
|
|
660
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionSucceeded_fn).call(this, method, scope, params);
|
|
661
|
+
} catch (error) {
|
|
662
|
+
yield __privateMethod(this, _MetamaskConnectEVM_instances, trackWalletActionFailed_fn).call(this, method, scope, params, error);
|
|
663
|
+
throw error;
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
};
|
|
667
|
+
request_fn = function(request) {
|
|
668
|
+
return __async(this, null, function* () {
|
|
669
|
+
logger("direct request to metamask-provider called", request);
|
|
670
|
+
const result = __privateGet(this, _core2).transport.sendEip1193Message(request);
|
|
671
|
+
if (request.method === "wallet_addEthereumChain" || request.method === "wallet_switchEthereumChain") {
|
|
672
|
+
__privateGet(this, _core2).openDeeplinkIfNeeded();
|
|
673
|
+
}
|
|
674
|
+
return result;
|
|
675
|
+
});
|
|
676
|
+
};
|
|
677
|
+
/**
|
|
678
|
+
* Handles chain change events and updates the provider's selected chain ID.
|
|
679
|
+
*
|
|
680
|
+
* @param chainId - The new chain ID (can be hex string or number)
|
|
681
|
+
*/
|
|
682
|
+
onChainChanged_fn = function(chainId) {
|
|
683
|
+
var _a, _b;
|
|
684
|
+
const hexChainId = isHex(chainId) ? chainId : numberToHex2(chainId);
|
|
685
|
+
if (hexChainId === __privateGet(this, _provider).selectedChainId) {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
logger("handler: chainChanged", { chainId });
|
|
689
|
+
__privateGet(this, _provider).selectedChainId = chainId;
|
|
690
|
+
(_b = (_a = __privateGet(this, _eventHandlers)) == null ? void 0 : _a.chainChanged) == null ? void 0 : _b.call(_a, hexChainId);
|
|
691
|
+
__privateGet(this, _provider).emit("chainChanged", hexChainId);
|
|
692
|
+
};
|
|
693
|
+
/**
|
|
694
|
+
* Handles accounts change events and updates the provider's accounts list.
|
|
695
|
+
*
|
|
696
|
+
* @param accounts - The new list of permitted accounts
|
|
697
|
+
*/
|
|
698
|
+
onAccountsChanged_fn = function(accounts) {
|
|
699
|
+
var _a, _b;
|
|
700
|
+
logger("handler: accountsChanged", accounts);
|
|
701
|
+
__privateGet(this, _provider).accounts = accounts;
|
|
702
|
+
__privateGet(this, _provider).emit("accountsChanged", accounts);
|
|
703
|
+
(_b = (_a = __privateGet(this, _eventHandlers)) == null ? void 0 : _a.accountsChanged) == null ? void 0 : _b.call(_a, accounts);
|
|
704
|
+
};
|
|
705
|
+
/**
|
|
706
|
+
* Handles connection events and emits the connect event to listeners.
|
|
707
|
+
*
|
|
708
|
+
* @param options - The connection options
|
|
709
|
+
* @param options.chainId - The chain ID of the connection (can be hex string or number)
|
|
710
|
+
* @param options.accounts - The accounts of the connection
|
|
711
|
+
*/
|
|
712
|
+
onConnect_fn = function({
|
|
713
|
+
chainId,
|
|
714
|
+
accounts
|
|
715
|
+
}) {
|
|
716
|
+
var _a, _b;
|
|
717
|
+
logger("handler: connect", { chainId, accounts });
|
|
718
|
+
const data = {
|
|
719
|
+
chainId: isHex(chainId) ? chainId : numberToHex2(chainId),
|
|
720
|
+
accounts
|
|
721
|
+
};
|
|
722
|
+
__privateGet(this, _provider).emit("connect", data);
|
|
723
|
+
(_b = (_a = __privateGet(this, _eventHandlers)) == null ? void 0 : _a.connect) == null ? void 0 : _b.call(_a, data);
|
|
724
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, onChainChanged_fn).call(this, chainId);
|
|
725
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, onAccountsChanged_fn).call(this, accounts);
|
|
726
|
+
};
|
|
727
|
+
/**
|
|
728
|
+
* Handles disconnection events and emits the disconnect event to listeners.
|
|
729
|
+
* Also clears accounts by triggering an accountsChanged event with an empty array.
|
|
730
|
+
*/
|
|
731
|
+
onDisconnect_fn = function() {
|
|
732
|
+
var _a, _b;
|
|
733
|
+
logger("handler: disconnect");
|
|
734
|
+
__privateGet(this, _provider).emit("disconnect");
|
|
735
|
+
(_b = (_a = __privateGet(this, _eventHandlers)) == null ? void 0 : _a.disconnect) == null ? void 0 : _b.call(_a);
|
|
736
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, onAccountsChanged_fn).call(this, []);
|
|
737
|
+
};
|
|
738
|
+
attemptSessionRecovery_fn = function() {
|
|
739
|
+
return __async(this, null, function* () {
|
|
740
|
+
try {
|
|
741
|
+
const response = yield __privateGet(this, _core2).transport.request({
|
|
742
|
+
method: "wallet_getSession"
|
|
743
|
+
});
|
|
744
|
+
const { sessionScopes } = response.result;
|
|
745
|
+
__privateSet(this, _sessionScopes, sessionScopes);
|
|
746
|
+
const permittedChainIds = getPermittedEthChainIds(sessionScopes);
|
|
747
|
+
const permittedAccounts = yield __privateGet(this, _core2).transport.sendEip1193Message({
|
|
748
|
+
method: "eth_accounts",
|
|
749
|
+
params: []
|
|
750
|
+
});
|
|
751
|
+
if (permittedChainIds.length && permittedAccounts.result) {
|
|
752
|
+
__privateMethod(this, _MetamaskConnectEVM_instances, onConnect_fn).call(this, {
|
|
753
|
+
chainId: permittedChainIds[0],
|
|
754
|
+
accounts: permittedAccounts.result
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
} catch (error) {
|
|
758
|
+
console.error("Error attempting session recovery", error);
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
};
|
|
762
|
+
function createMetamaskConnectEVM(options) {
|
|
763
|
+
return __async(this, null, function* () {
|
|
764
|
+
var _a;
|
|
765
|
+
enableDebug(options.debug);
|
|
766
|
+
logger("Creating Metamask Connect/EVM with options:", options);
|
|
767
|
+
if (!((_a = options.api) == null ? void 0 : _a.supportedNetworks) || Object.keys(options.api.supportedNetworks).length === 0) {
|
|
768
|
+
throw new Error(
|
|
769
|
+
"supportedNetworks is required and must contain at least one chain configuration"
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
validSupportedChainsUrls(options.api.supportedNetworks, "supportedNetworks");
|
|
773
|
+
try {
|
|
774
|
+
const core = yield createMetamaskConnect(__spreadProps(__spreadValues({}, options), {
|
|
775
|
+
api: {
|
|
776
|
+
supportedNetworks: options.api.supportedNetworks
|
|
777
|
+
}
|
|
778
|
+
}));
|
|
779
|
+
return new MetamaskConnectEVM({
|
|
780
|
+
core,
|
|
781
|
+
eventHandlers: options.eventHandlers,
|
|
782
|
+
supportedNetworks: options.api.supportedNetworks
|
|
783
|
+
});
|
|
784
|
+
} catch (error) {
|
|
785
|
+
console.error("Error creating Metamask Connect/EVM", error);
|
|
786
|
+
throw error;
|
|
787
|
+
}
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
export {
|
|
791
|
+
createMetamaskConnectEVM,
|
|
792
|
+
getInfuraRpcUrls
|
|
793
|
+
};
|
|
794
|
+
//# sourceMappingURL=connect-evm.mjs.map
|