@metamask/connect-multichain 0.12.1 → 0.14.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/dist/browser/es/connect-multichain.d.mts +46 -2
  3. package/dist/browser/es/connect-multichain.mjs +1733 -1566
  4. package/dist/browser/es/connect-multichain.mjs.map +1 -1
  5. package/dist/browser/es/metafile-esm.json +1 -1
  6. package/dist/browser/iife/connect-multichain.d.ts +46 -2
  7. package/dist/browser/iife/connect-multichain.js +6279 -5413
  8. package/dist/browser/iife/connect-multichain.js.map +1 -1
  9. package/dist/browser/iife/metafile-iife.json +1 -1
  10. package/dist/browser/umd/connect-multichain.d.ts +46 -2
  11. package/dist/browser/umd/connect-multichain.js +1761 -1589
  12. package/dist/browser/umd/connect-multichain.js.map +1 -1
  13. package/dist/browser/umd/metafile-cjs.json +1 -1
  14. package/dist/node/cjs/connect-multichain.d.ts +46 -2
  15. package/dist/node/cjs/connect-multichain.js +892 -719
  16. package/dist/node/cjs/connect-multichain.js.map +1 -1
  17. package/dist/node/cjs/metafile-cjs.json +1 -1
  18. package/dist/node/es/connect-multichain.d.mts +46 -2
  19. package/dist/node/es/connect-multichain.mjs +890 -723
  20. package/dist/node/es/connect-multichain.mjs.map +1 -1
  21. package/dist/node/es/metafile-esm.json +1 -1
  22. package/dist/react-native/es/connect-multichain.d.mts +46 -2
  23. package/dist/react-native/es/connect-multichain.mjs +890 -723
  24. package/dist/react-native/es/connect-multichain.mjs.map +1 -1
  25. package/dist/react-native/es/metafile-esm.json +1 -1
  26. package/dist/src/domain/multichain/index.d.ts +1 -1
  27. package/dist/src/domain/multichain/index.d.ts.map +1 -1
  28. package/dist/src/domain/utils/index.d.ts +2 -1
  29. package/dist/src/domain/utils/index.d.ts.map +1 -1
  30. package/dist/src/domain/utils/index.js +1 -1
  31. package/dist/src/domain/utils/index.js.map +1 -1
  32. package/dist/src/multichain/index.d.ts +2 -2
  33. package/dist/src/multichain/index.d.ts.map +1 -1
  34. package/dist/src/multichain/index.js +39 -25
  35. package/dist/src/multichain/index.js.map +1 -1
  36. package/dist/src/multichain/rpc/requestRouter.d.ts.map +1 -1
  37. package/dist/src/multichain/rpc/requestRouter.js +4 -4
  38. package/dist/src/multichain/rpc/requestRouter.js.map +1 -1
  39. package/dist/src/multichain/transports/multichainApiClientWrapper/index.d.ts +1 -0
  40. package/dist/src/multichain/transports/multichainApiClientWrapper/index.d.ts.map +1 -1
  41. package/dist/src/multichain/transports/multichainApiClientWrapper/index.js +10 -10
  42. package/dist/src/multichain/transports/multichainApiClientWrapper/index.js.map +1 -1
  43. package/dist/src/multichain/transports/mwp/KeyManager.d.ts +12 -9
  44. package/dist/src/multichain/transports/mwp/KeyManager.d.ts.map +1 -1
  45. package/dist/src/multichain/transports/mwp/KeyManager.js +38 -25
  46. package/dist/src/multichain/transports/mwp/KeyManager.js.map +1 -1
  47. package/dist/src/multichain/transports/mwp/index.d.ts.map +1 -1
  48. package/dist/src/multichain/transports/mwp/index.js +18 -6
  49. package/dist/src/multichain/transports/mwp/index.js.map +1 -1
  50. package/dist/src/multichain/utils/analytics.d.ts +82 -1
  51. package/dist/src/multichain/utils/analytics.d.ts.map +1 -1
  52. package/dist/src/multichain/utils/analytics.js +252 -17
  53. package/dist/src/multichain/utils/analytics.js.map +1 -1
  54. package/dist/types/connect-multichain.d.ts +46 -2
  55. package/package.json +2 -2
@@ -967,17 +967,94 @@ var init_utils = __esm({
967
967
  });
968
968
 
969
969
  // src/multichain/utils/analytics.ts
970
+ function sanitiseErrorMessage(message) {
971
+ if (!message) {
972
+ return void 0;
973
+ }
974
+ let sanitised = message;
975
+ for (const { pattern, replacement } of SANITISE_PATTERNS) {
976
+ sanitised = sanitised.replace(pattern, replacement);
977
+ }
978
+ if (sanitised.length > ERROR_MESSAGE_SAMPLE_MAX_LENGTH) {
979
+ sanitised = `${sanitised.slice(0, ERROR_MESSAGE_SAMPLE_MAX_LENGTH - 1)}\u2026`;
980
+ }
981
+ return sanitised;
982
+ }
983
+ function getUnwrappedErrorDetails(error) {
984
+ var _a2, _b, _c, _d;
985
+ if (typeof error !== "object" || error === null) {
986
+ return { code: void 0, message: "" };
987
+ }
988
+ if (error instanceof RPCInvokeMethodErr) {
989
+ return {
990
+ code: (_a2 = error.rpcCode) != null ? _a2 : error.code,
991
+ message: (_c = (_b = error.rpcMessage) != null ? _b : error.message) != null ? _c : ""
992
+ };
993
+ }
994
+ const errorObj = error;
995
+ return {
996
+ code: errorObj.code,
997
+ message: (_d = errorObj.message) != null ? _d : ""
998
+ };
999
+ }
970
1000
  function isRejectionError(error) {
971
- var _a2, _b;
972
1001
  if (typeof error !== "object" || error === null) {
973
1002
  return false;
974
1003
  }
1004
+ const { code, message } = getUnwrappedErrorDetails(error);
1005
+ const errorMessage = message.toLowerCase();
1006
+ return code === 4001 || errorMessage.includes("reject") || errorMessage.includes("denied") || errorMessage.includes("cancel") || // Narrow "user …" matches — bare "user" is too greedy (catches Account
1007
+ // Abstraction errors like "user operation reverted").
1008
+ errorMessage.includes("user rejected") || errorMessage.includes("user denied") || errorMessage.includes("user cancelled") || errorMessage.includes("user canceled");
1009
+ }
1010
+ function classifyFailureReason(error) {
1011
+ var _a2, _b;
1012
+ if (typeof error !== "object" || error === null) {
1013
+ return "unknown";
1014
+ }
975
1015
  const errorObj = error;
976
- const errorCode = errorObj.code;
977
- const errorMessage = (_b = (_a2 = errorObj.message) == null ? void 0 : _a2.toLowerCase()) != null ? _b : "";
978
- return errorCode === 4001 || // User rejected request (common EIP-1193 code)
979
- errorCode === 4100 || // Unauthorized (common rejection code)
980
- errorMessage.includes("reject") || errorMessage.includes("denied") || errorMessage.includes("cancel") || errorMessage.includes("user");
1016
+ const errorName = (_a2 = errorObj.name) != null ? _a2 : "";
1017
+ const errorMessageRaw = (_b = errorObj.message) != null ? _b : "";
1018
+ const errorMessage = errorMessageRaw.toLowerCase();
1019
+ const { code } = getUnwrappedErrorDetails(error);
1020
+ if (typeof code === "number") {
1021
+ if (code === -32601) {
1022
+ return "wallet_method_unsupported";
1023
+ }
1024
+ if (code === -32602) {
1025
+ return "wallet_invalid_params";
1026
+ }
1027
+ if (code === -32603) {
1028
+ return "wallet_internal_error";
1029
+ }
1030
+ if (code <= -32e3 && code >= -32099) {
1031
+ return "wallet_internal_error";
1032
+ }
1033
+ if (code === 4100) {
1034
+ return "wallet_unauthorized";
1035
+ }
1036
+ if (code === 4200) {
1037
+ return "wallet_method_unsupported";
1038
+ }
1039
+ if (code === 4902) {
1040
+ return "unrecognized_chain";
1041
+ }
1042
+ }
1043
+ if (errorName === "TransportTimeoutError" || errorMessageRaw === "Request timeout" || errorMessage.includes("timed out") || errorMessage.includes("timeout")) {
1044
+ return "transport_timeout";
1045
+ }
1046
+ if (errorName === "TransportError" || errorMessage.includes("not connected") || errorMessage.includes("transport disconnect") || errorMessage.includes("connection lost") || errorMessage.includes("socket closed")) {
1047
+ return "transport_disconnect";
1048
+ }
1049
+ return "unknown";
1050
+ }
1051
+ function extractErrorDiagnostics(error) {
1052
+ const failureReason = classifyFailureReason(error);
1053
+ const { code, message } = getUnwrappedErrorDetails(error);
1054
+ const messageSample = sanitiseErrorMessage(message);
1055
+ return __spreadValues(__spreadValues({
1056
+ failure_reason: failureReason
1057
+ }, typeof code === "number" ? { error_code: code } : {}), messageSample ? { error_message_sample: messageSample } : {});
981
1058
  }
982
1059
  function getBaseAnalyticsProperties(options, storage) {
983
1060
  return __async(this, null, function* () {
@@ -993,26 +1070,61 @@ function getBaseAnalyticsProperties(options, storage) {
993
1070
  };
994
1071
  });
995
1072
  }
996
- function getWalletActionAnalyticsProperties(options, storage, invokeOptions, transportType) {
1073
+ function getWalletActionAnalyticsProperties(options, storage, invokeOptions, transportType, extra) {
997
1074
  return __async(this, null, function* () {
998
1075
  var _a2;
999
1076
  const dappId = getDappId(options.dapp);
1000
1077
  const anonId = yield storage.getAnonId();
1001
- return {
1078
+ return __spreadValues(__spreadValues(__spreadValues({
1002
1079
  mmconnect_versions: (_a2 = options.versions) != null ? _a2 : {},
1003
1080
  dapp_id: dappId,
1004
1081
  method: invokeOptions.request.method,
1005
1082
  caip_chain_id: invokeOptions.scope,
1006
1083
  anon_id: anonId,
1007
1084
  transport_type: transportType
1008
- };
1085
+ }, (extra == null ? void 0 : extra.failure_reason) ? { failure_reason: extra.failure_reason } : {}), typeof (extra == null ? void 0 : extra.error_code) === "number" ? { error_code: extra.error_code } : {}), (extra == null ? void 0 : extra.error_message_sample) ? { error_message_sample: extra.error_message_sample } : {});
1009
1086
  });
1010
1087
  }
1088
+ var ERROR_MESSAGE_SAMPLE_MAX_LENGTH, SANITISE_PATTERNS;
1011
1089
  var init_analytics = __esm({
1012
1090
  "src/multichain/utils/analytics.ts"() {
1013
1091
  "use strict";
1014
1092
  init_utils();
1015
1093
  init_domain();
1094
+ ERROR_MESSAGE_SAMPLE_MAX_LENGTH = 200;
1095
+ SANITISE_PATTERNS = [
1096
+ // EVM-style 20-byte hex addresses (e.g. `0x` + 40 hex chars).
1097
+ { pattern: /0x[a-fA-F0-9]{40}/gu, replacement: "<addr>" },
1098
+ // Other long hex blobs: tx hashes, signatures, raw byte strings, large
1099
+ // hex amounts. 16+ hex chars catches 32-byte hashes/signatures without
1100
+ // snagging EVM method selectors (8 chars) or short hex codes.
1101
+ { pattern: /(?:0x)?[a-fA-F0-9]{16,}/gu, replacement: "<hex>" },
1102
+ // URLs of any scheme up to the first whitespace / quote / closing paren.
1103
+ // Catches RPC endpoints, dapp deeplinks, query strings with secrets.
1104
+ { pattern: /https?:\/\/[^\s"')]+/gu, replacement: "<url>" },
1105
+ // Bech32 addresses: short HRP (1-10 lowercase chars) + `1` separator +
1106
+ // ≥38 chars of Bech32 data alphabet `[ac-hj-np-z02-9]` (excludes the
1107
+ // look-alike chars `b`, `i`, `o`, `1`). Covers Bitcoin SegWit
1108
+ // (`bc1…`/`tb1…`) and Cosmos-SDK chains (`cosmos1…`, `osmo1…`,
1109
+ // `juno1…`, `inj1…`, etc.) without enumerating every HRP. Runs before
1110
+ // the Base58 pattern below — see header comment for why.
1111
+ {
1112
+ pattern: /\b[a-z]{1,10}1[ac-hj-np-z02-9]{38,}\b/gu,
1113
+ replacement: "<addr>"
1114
+ },
1115
+ // Base58 tokens (32+ chars, Base58 alphabet `[1-9A-HJ-NP-Za-km-z]`).
1116
+ // Covers Solana pubkeys (32-44 chars), Solana tx signatures (~88 chars),
1117
+ // and Bitcoin Base58 addresses ≥32 chars. The 32-char floor and `\b`
1118
+ // word boundary keep English words and shorter alphanumerics safe.
1119
+ {
1120
+ pattern: /\b[1-9A-HJ-NP-Za-km-z]{32,}\b/gu,
1121
+ replacement: "<addr>"
1122
+ },
1123
+ // Long decimal numbers — token amounts, gas units, timestamps, lamports.
1124
+ // 10+ digits catches typical chain quantities without affecting JSON-RPC
1125
+ // codes (-32601, 4001, etc.) or short numeric IDs.
1126
+ { pattern: /\d{10,}/gu, replacement: "<num>" }
1127
+ ];
1016
1128
  }
1017
1129
  });
1018
1130
 
@@ -1042,6 +1154,717 @@ var init_domain = __esm({
1042
1154
  }
1043
1155
  });
1044
1156
 
1157
+ // src/multichain/transports/constants.ts
1158
+ var MULTICHAIN_PROVIDER_STREAM_NAME;
1159
+ var init_constants2 = __esm({
1160
+ "src/multichain/transports/constants.ts"() {
1161
+ "use strict";
1162
+ MULTICHAIN_PROVIDER_STREAM_NAME = "metamask-multichain-provider";
1163
+ }
1164
+ });
1165
+
1166
+ // src/multichain/transports/mwp/index.ts
1167
+ var mwp_exports = {};
1168
+ __export(mwp_exports, {
1169
+ MWPTransport: () => MWPTransport
1170
+ });
1171
+ var import_multichain_api_client2, import_rpc_errors2, DEFAULT_REQUEST_TIMEOUT2, CONNECTION_GRACE_PERIOD, DEFAULT_CONNECTION_TIMEOUT, DEFAULT_RESUME_TIMEOUT, SESSION_STORE_KEY, ACCOUNTS_STORE_KEY, CHAIN_STORE_KEY, PENDING_SESSION_REQUEST_KEY, CACHED_METHOD_LIST, CACHED_RESET_METHOD_LIST, logger, MWPTransport;
1172
+ var init_mwp = __esm({
1173
+ "src/multichain/transports/mwp/index.ts"() {
1174
+ "use strict";
1175
+ import_multichain_api_client2 = require("@metamask/multichain-api-client");
1176
+ import_rpc_errors2 = require("@metamask/rpc-errors");
1177
+ init_domain();
1178
+ init_utils();
1179
+ init_constants2();
1180
+ DEFAULT_REQUEST_TIMEOUT2 = 60 * 1e3;
1181
+ CONNECTION_GRACE_PERIOD = 60 * 1e3;
1182
+ DEFAULT_CONNECTION_TIMEOUT = DEFAULT_REQUEST_TIMEOUT2 + CONNECTION_GRACE_PERIOD;
1183
+ DEFAULT_RESUME_TIMEOUT = 10 * 1e3;
1184
+ SESSION_STORE_KEY = "cache_wallet_getSession";
1185
+ ACCOUNTS_STORE_KEY = "cache_eth_accounts";
1186
+ CHAIN_STORE_KEY = "cache_eth_chainId";
1187
+ PENDING_SESSION_REQUEST_KEY = "pending_session_request";
1188
+ CACHED_METHOD_LIST = [
1189
+ "wallet_getSession",
1190
+ "wallet_createSession",
1191
+ "wallet_sessionChanged"
1192
+ ];
1193
+ CACHED_RESET_METHOD_LIST = [
1194
+ "wallet_revokeSession",
1195
+ "wallet_revokePermissions"
1196
+ ];
1197
+ logger = createLogger("metamask-sdk:transport");
1198
+ MWPTransport = class {
1199
+ constructor(dappClient, kvstore, options = {
1200
+ requestTimeout: DEFAULT_REQUEST_TIMEOUT2,
1201
+ connectionTimeout: DEFAULT_CONNECTION_TIMEOUT,
1202
+ resumeTimeout: DEFAULT_RESUME_TIMEOUT
1203
+ }) {
1204
+ this.dappClient = dappClient;
1205
+ this.kvstore = kvstore;
1206
+ this.options = options;
1207
+ this.__pendingRequests = /* @__PURE__ */ new Map();
1208
+ this.notificationCallbacks = /* @__PURE__ */ new Set();
1209
+ this.dappClient.on("message", this.handleMessage.bind(this));
1210
+ this.dappClient.on("session_request", (sessionRequest) => {
1211
+ this.currentSessionRequest = sessionRequest;
1212
+ this.kvstore.set(PENDING_SESSION_REQUEST_KEY, JSON.stringify(sessionRequest)).catch((err) => {
1213
+ logger("Failed to store pending session request", err);
1214
+ });
1215
+ });
1216
+ if (typeof window !== "undefined" && typeof window.addEventListener !== "undefined") {
1217
+ this.windowFocusHandler = this.onWindowFocus.bind(this);
1218
+ window.addEventListener("focus", this.windowFocusHandler);
1219
+ }
1220
+ }
1221
+ get pendingRequests() {
1222
+ return this.__pendingRequests;
1223
+ }
1224
+ set pendingRequests(pendingRequests) {
1225
+ this.__pendingRequests = pendingRequests;
1226
+ }
1227
+ get sessionRequest() {
1228
+ return this.currentSessionRequest;
1229
+ }
1230
+ /**
1231
+ * Returns the stored pending session request from the dappClient session_request event, if any.
1232
+ *
1233
+ * @returns The stored SessionRequest, or null if none or invalid.
1234
+ */
1235
+ getStoredPendingSessionRequest() {
1236
+ return __async(this, null, function* () {
1237
+ try {
1238
+ const raw = yield this.kvstore.get(PENDING_SESSION_REQUEST_KEY);
1239
+ if (!raw) {
1240
+ return null;
1241
+ }
1242
+ return JSON.parse(raw);
1243
+ } catch (e) {
1244
+ return null;
1245
+ }
1246
+ });
1247
+ }
1248
+ /**
1249
+ * Removes the stored pending session request from the KVStore.
1250
+ * This is necessary to ensure that ConnectMultichain is able to correctly
1251
+ * infer the MWP Transport connection attempt status.
1252
+ */
1253
+ removeStoredPendingSessionRequest() {
1254
+ return __async(this, null, function* () {
1255
+ yield this.kvstore.delete(PENDING_SESSION_REQUEST_KEY);
1256
+ });
1257
+ }
1258
+ onWindowFocus() {
1259
+ if (!this.isConnected()) {
1260
+ this.dappClient.reconnect();
1261
+ }
1262
+ }
1263
+ notifyCallbacks(data) {
1264
+ this.notificationCallbacks.forEach((callback) => callback(data));
1265
+ }
1266
+ rejectRequest(id, error = new Error("Request rejected")) {
1267
+ const request = this.pendingRequests.get(id);
1268
+ if (request) {
1269
+ this.pendingRequests.delete(id);
1270
+ clearTimeout(request.timeout);
1271
+ request.reject(error);
1272
+ }
1273
+ }
1274
+ parseWalletError(errorPayload) {
1275
+ const errorData = errorPayload;
1276
+ if (typeof errorData.code === "number" && typeof errorData.message === "string") {
1277
+ const { code, message: message2 } = errorData;
1278
+ if (code >= 1e3 && code <= 4999) {
1279
+ return import_rpc_errors2.providerErrors.custom({ code, message: message2 });
1280
+ }
1281
+ return new import_rpc_errors2.JsonRpcError(code, message2);
1282
+ }
1283
+ const message = errorPayload instanceof Error ? errorPayload.message : JSON.stringify(errorPayload);
1284
+ return import_rpc_errors2.rpcErrors.internal({ message });
1285
+ }
1286
+ handleMessage(message) {
1287
+ if (typeof message === "object" && message !== null) {
1288
+ if ("data" in message) {
1289
+ const messagePayload = message.data;
1290
+ if ("id" in messagePayload && typeof messagePayload.id === "string") {
1291
+ const request = this.pendingRequests.get(messagePayload.id);
1292
+ if (request) {
1293
+ clearTimeout(request.timeout);
1294
+ if ("error" in messagePayload && messagePayload.error) {
1295
+ this.pendingRequests.delete(messagePayload.id);
1296
+ request.reject(this.parseWalletError(messagePayload.error));
1297
+ return;
1298
+ }
1299
+ const requestWithName = __spreadProps(__spreadValues({}, messagePayload), {
1300
+ method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method
1301
+ });
1302
+ const notification = __spreadProps(__spreadValues({}, messagePayload), {
1303
+ method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method,
1304
+ params: requestWithName.result
1305
+ });
1306
+ this.notifyCallbacks(notification);
1307
+ request.resolve(requestWithName);
1308
+ this.pendingRequests.delete(messagePayload.id);
1309
+ }
1310
+ } else {
1311
+ if (message.data.method === "metamask_chainChanged") {
1312
+ this.kvstore.set(
1313
+ CHAIN_STORE_KEY,
1314
+ JSON.stringify(
1315
+ message.data.params.chainId
1316
+ )
1317
+ );
1318
+ }
1319
+ if (message.data.method === "metamask_accountsChanged") {
1320
+ this.kvstore.set(
1321
+ ACCOUNTS_STORE_KEY,
1322
+ JSON.stringify(
1323
+ message.data.params
1324
+ )
1325
+ );
1326
+ }
1327
+ if (message.data.method === "wallet_sessionChanged") {
1328
+ const notification = message.data;
1329
+ const response = {
1330
+ result: notification.params
1331
+ };
1332
+ this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
1333
+ }
1334
+ this.notifyCallbacks(message.data);
1335
+ }
1336
+ }
1337
+ }
1338
+ }
1339
+ onResumeSuccess(resumeResolve, resumeReject, options) {
1340
+ return __async(this, null, function* () {
1341
+ var _a2, _b, _c, _d, _e, _f, _g;
1342
+ try {
1343
+ yield this.waitForWalletSessionIfNotCached();
1344
+ const sessionRequest = yield this.request({
1345
+ method: "wallet_getSession"
1346
+ });
1347
+ if (sessionRequest.error) {
1348
+ return resumeReject(new Error(sessionRequest.error.message));
1349
+ }
1350
+ let walletSession = sessionRequest.result;
1351
+ if (walletSession && options) {
1352
+ const currentScopes = Object.keys(
1353
+ (_a2 = walletSession == null ? void 0 : walletSession.sessionScopes) != null ? _a2 : {}
1354
+ );
1355
+ const proposedScopes = (_b = options == null ? void 0 : options.scopes) != null ? _b : [];
1356
+ const proposedCaipAccountIds = (_c = options == null ? void 0 : options.caipAccountIds) != null ? _c : [];
1357
+ const hasSameScopesAndAccounts = isSameScopesAndAccounts(
1358
+ currentScopes,
1359
+ proposedScopes,
1360
+ walletSession,
1361
+ proposedCaipAccountIds
1362
+ );
1363
+ if (options.forceRequest || !hasSameScopesAndAccounts) {
1364
+ const optionalScopes = addValidAccounts(
1365
+ getOptionalScopes((_d = options == null ? void 0 : options.scopes) != null ? _d : []),
1366
+ getValidAccounts((_e = options == null ? void 0 : options.caipAccountIds) != null ? _e : [])
1367
+ );
1368
+ const sessionRequest2 = {
1369
+ optionalScopes
1370
+ };
1371
+ const response = yield this.request({
1372
+ method: "wallet_createSession",
1373
+ params: sessionRequest2
1374
+ });
1375
+ if (response.error) {
1376
+ return resumeReject(new Error(response.error.message));
1377
+ }
1378
+ walletSession = response.result;
1379
+ }
1380
+ } else if (!walletSession) {
1381
+ const optionalScopes = addValidAccounts(
1382
+ getOptionalScopes((_f = options == null ? void 0 : options.scopes) != null ? _f : []),
1383
+ getValidAccounts((_g = options == null ? void 0 : options.caipAccountIds) != null ? _g : [])
1384
+ );
1385
+ const sessionRequest2 = { optionalScopes };
1386
+ const response = yield this.request({
1387
+ method: "wallet_createSession",
1388
+ params: sessionRequest2
1389
+ });
1390
+ if (response.error) {
1391
+ return resumeReject(new Error(response.error.message));
1392
+ }
1393
+ walletSession = response.result;
1394
+ }
1395
+ yield this.removeStoredPendingSessionRequest();
1396
+ this.notifyCallbacks({
1397
+ method: "wallet_sessionChanged",
1398
+ params: walletSession
1399
+ });
1400
+ return resumeResolve();
1401
+ } catch (err) {
1402
+ return resumeReject(err);
1403
+ }
1404
+ });
1405
+ }
1406
+ init() {
1407
+ return __async(this, null, function* () {
1408
+ });
1409
+ }
1410
+ // TODO: Rename this
1411
+ sendEip1193Message(payload, options) {
1412
+ return __async(this, null, function* () {
1413
+ const request = __spreadValues({
1414
+ jsonrpc: "2.0",
1415
+ id: String(getUniqueRequestId())
1416
+ }, payload);
1417
+ const cachedWalletSession = yield this.getCachedResponse(request);
1418
+ if (cachedWalletSession) {
1419
+ this.notifyCallbacks(cachedWalletSession);
1420
+ return cachedWalletSession;
1421
+ }
1422
+ return new Promise((resolve, reject) => {
1423
+ var _a2;
1424
+ const timeout = setTimeout(() => {
1425
+ this.rejectRequest(request.id, new import_multichain_api_client2.TransportTimeoutError());
1426
+ }, (_a2 = options == null ? void 0 : options.timeout) != null ? _a2 : this.options.requestTimeout);
1427
+ this.pendingRequests.set(request.id, {
1428
+ request,
1429
+ method: request.method,
1430
+ resolve: (response) => __async(this, null, function* () {
1431
+ yield this.storeWalletSession(request, response);
1432
+ return resolve(response);
1433
+ }),
1434
+ reject,
1435
+ timeout
1436
+ });
1437
+ this.dappClient.sendRequest({
1438
+ name: "metamask-provider",
1439
+ data: request
1440
+ }).catch(reject);
1441
+ });
1442
+ });
1443
+ }
1444
+ connect(options) {
1445
+ return __async(this, null, function* () {
1446
+ const { dappClient } = this;
1447
+ const session = yield this.getActiveSession();
1448
+ if (session) {
1449
+ logger("active session found", {
1450
+ id: session.id,
1451
+ channel: session.channel,
1452
+ expiresAt: session.expiresAt
1453
+ });
1454
+ }
1455
+ const storedSessionRequestBeforeConnectionAttempt = yield this.getStoredPendingSessionRequest();
1456
+ let timeout;
1457
+ let initialConnectionMessageHandler;
1458
+ const connectionPromise = new Promise((resolve, reject) => __async(this, null, function* () {
1459
+ let connection;
1460
+ if (session) {
1461
+ connection = new Promise((resumeResolve, resumeReject) => {
1462
+ var _a2;
1463
+ if (this.dappClient.state === "CONNECTED") {
1464
+ this.onResumeSuccess(resumeResolve, resumeReject, options);
1465
+ } else {
1466
+ this.dappClient.once("connected", () => __async(this, null, function* () {
1467
+ this.onResumeSuccess(resumeResolve, resumeReject, options);
1468
+ }));
1469
+ dappClient.resume((_a2 = session == null ? void 0 : session.id) != null ? _a2 : "");
1470
+ }
1471
+ });
1472
+ } else {
1473
+ connection = new Promise(
1474
+ (resolveConnection, rejectConnection) => {
1475
+ var _a2, _b;
1476
+ const optionalScopes = addValidAccounts(
1477
+ getOptionalScopes((_a2 = options == null ? void 0 : options.scopes) != null ? _a2 : []),
1478
+ getValidAccounts((_b = options == null ? void 0 : options.caipAccountIds) != null ? _b : [])
1479
+ );
1480
+ const sessionRequest = {
1481
+ optionalScopes,
1482
+ sessionProperties: options == null ? void 0 : options.sessionProperties
1483
+ };
1484
+ const request = {
1485
+ jsonrpc: "2.0",
1486
+ id: String(getUniqueRequestId()),
1487
+ method: "wallet_createSession",
1488
+ params: sessionRequest
1489
+ };
1490
+ initialConnectionMessageHandler = (message) => __async(this, null, function* () {
1491
+ if (typeof message !== "object" || message === null) {
1492
+ return;
1493
+ }
1494
+ if (!("data" in message)) {
1495
+ return;
1496
+ }
1497
+ const messagePayload = message.data;
1498
+ const isMatchingId = messagePayload.id === request.id;
1499
+ const isMatchingMethod = messagePayload.method === "wallet_createSession" || messagePayload.method === "wallet_sessionChanged";
1500
+ if (!isMatchingId && !isMatchingMethod) {
1501
+ return;
1502
+ }
1503
+ if (messagePayload.error) {
1504
+ return rejectConnection(
1505
+ this.parseWalletError(messagePayload.error)
1506
+ );
1507
+ }
1508
+ yield this.storeWalletSession(
1509
+ request,
1510
+ messagePayload
1511
+ );
1512
+ yield this.removeStoredPendingSessionRequest();
1513
+ this.notifyCallbacks(messagePayload);
1514
+ return resolveConnection();
1515
+ });
1516
+ this.dappClient.on("message", initialConnectionMessageHandler);
1517
+ const platformType = getPlatformType();
1518
+ const isQRCodeFlow = [
1519
+ "web-desktop" /* DesktopWeb */,
1520
+ "nodejs" /* NonBrowser */
1521
+ ].includes(platformType);
1522
+ const initialPayload = {
1523
+ name: MULTICHAIN_PROVIDER_STREAM_NAME,
1524
+ data: request
1525
+ };
1526
+ dappClient.connect({
1527
+ mode: "trusted",
1528
+ initialPayload: isQRCodeFlow ? void 0 : initialPayload
1529
+ }).then(() => __async(this, null, function* () {
1530
+ if (isQRCodeFlow) {
1531
+ return dappClient.sendRequest(initialPayload);
1532
+ }
1533
+ return void 0;
1534
+ })).catch((error) => {
1535
+ if (initialConnectionMessageHandler) {
1536
+ this.dappClient.off(
1537
+ "message",
1538
+ initialConnectionMessageHandler
1539
+ );
1540
+ }
1541
+ rejectConnection(error);
1542
+ });
1543
+ }
1544
+ );
1545
+ }
1546
+ timeout = setTimeout(
1547
+ () => {
1548
+ reject(new import_multichain_api_client2.TransportTimeoutError());
1549
+ },
1550
+ storedSessionRequestBeforeConnectionAttempt ? this.options.resumeTimeout : this.options.connectionTimeout
1551
+ );
1552
+ connection.then(resolve).catch(reject);
1553
+ }));
1554
+ return connectionPromise.catch((error) => __async(this, null, function* () {
1555
+ yield this.dappClient.disconnect();
1556
+ throw error;
1557
+ })).finally(() => {
1558
+ if (timeout) {
1559
+ clearTimeout(timeout);
1560
+ }
1561
+ if (initialConnectionMessageHandler) {
1562
+ this.dappClient.off("message", initialConnectionMessageHandler);
1563
+ initialConnectionMessageHandler = void 0;
1564
+ }
1565
+ this.removeStoredPendingSessionRequest();
1566
+ });
1567
+ });
1568
+ }
1569
+ /**
1570
+ * Disconnects from the Mobile Wallet Protocol
1571
+ *
1572
+ * @param [scopes] - The scopes to revoke. If not provided or empty, all scopes will be revoked.
1573
+ * @returns Nothing
1574
+ */
1575
+ disconnect() {
1576
+ return __async(this, arguments, function* (scopes = []) {
1577
+ var _a2, _b;
1578
+ const cachedSession = yield this.getCachedResponse({
1579
+ jsonrpc: "2.0",
1580
+ id: "0",
1581
+ method: "wallet_getSession"
1582
+ });
1583
+ const cachedSessionScopes = (_b = (_a2 = cachedSession == null ? void 0 : cachedSession.result) == null ? void 0 : _a2.sessionScopes) != null ? _b : {};
1584
+ const remainingScopes = scopes.length === 0 ? [] : Object.keys(cachedSessionScopes).filter(
1585
+ (scope) => !scopes.includes(scope)
1586
+ );
1587
+ const newSessionScopes = Object.fromEntries(
1588
+ Object.entries(cachedSessionScopes).filter(
1589
+ ([key]) => remainingScopes.includes(key)
1590
+ )
1591
+ );
1592
+ this.request({ method: "wallet_revokeSession", params: { scopes } }).catch(
1593
+ (err) => {
1594
+ console.error("error revoking session", err);
1595
+ }
1596
+ );
1597
+ const remainingScopesIncludeEip155 = remainingScopes.some(
1598
+ (scope) => scope.includes("eip155")
1599
+ );
1600
+ if (!remainingScopesIncludeEip155) {
1601
+ this.kvstore.delete(ACCOUNTS_STORE_KEY);
1602
+ this.kvstore.delete(CHAIN_STORE_KEY);
1603
+ }
1604
+ if (remainingScopes.length > 0) {
1605
+ this.kvstore.set(
1606
+ SESSION_STORE_KEY,
1607
+ JSON.stringify({
1608
+ result: {
1609
+ sessionScopes: newSessionScopes
1610
+ }
1611
+ })
1612
+ );
1613
+ } else {
1614
+ this.kvstore.delete(SESSION_STORE_KEY);
1615
+ if (typeof window !== "undefined" && typeof window.removeEventListener !== "undefined" && this.windowFocusHandler) {
1616
+ window.removeEventListener("focus", this.windowFocusHandler);
1617
+ this.windowFocusHandler = void 0;
1618
+ }
1619
+ yield this.dappClient.disconnect();
1620
+ }
1621
+ this.notifyCallbacks({
1622
+ method: "wallet_sessionChanged",
1623
+ params: {
1624
+ sessionScopes: newSessionScopes
1625
+ }
1626
+ });
1627
+ });
1628
+ }
1629
+ /**
1630
+ * Checks if the transport is connected
1631
+ *
1632
+ * @returns True if transport is connected, false otherwise
1633
+ */
1634
+ isConnected() {
1635
+ return this.dappClient.state === "CONNECTED";
1636
+ }
1637
+ /**
1638
+ * Attempts to re-establish a connection via DappClient
1639
+ *
1640
+ * @returns Nothing
1641
+ */
1642
+ // TODO: We should re-evaluate adding this to the WebSocketTransport layer from `@metamask/mobile-wallet-protocol-core`
1643
+ // ticket: https://consensyssoftware.atlassian.net/browse/WAPI-862
1644
+ attemptResumeSession() {
1645
+ return __async(this, null, function* () {
1646
+ try {
1647
+ yield this.dappClient.reconnect();
1648
+ yield new Promise((resolve, reject) => {
1649
+ const timeout = setTimeout(() => {
1650
+ reject(new Error("Resume timeout"));
1651
+ }, 2e3);
1652
+ if (this.isConnected()) {
1653
+ clearTimeout(timeout);
1654
+ resolve();
1655
+ } else {
1656
+ this.dappClient.once("connected", () => {
1657
+ clearTimeout(timeout);
1658
+ resolve();
1659
+ });
1660
+ }
1661
+ });
1662
+ } catch (error) {
1663
+ return Promise.reject(
1664
+ new Error(`Failed to resume session: ${error.message}`)
1665
+ );
1666
+ }
1667
+ });
1668
+ }
1669
+ getCachedResponse(request) {
1670
+ return __async(this, null, function* () {
1671
+ var _a2;
1672
+ if (request.method === "wallet_getSession") {
1673
+ const walletGetSession = yield this.kvstore.get(SESSION_STORE_KEY);
1674
+ if (walletGetSession) {
1675
+ const walletSession = JSON.parse(walletGetSession);
1676
+ return {
1677
+ id: request.id,
1678
+ jsonrpc: "2.0",
1679
+ result: (_a2 = walletSession.params) != null ? _a2 : walletSession.result,
1680
+ // "what?... why walletSession.params?.."
1681
+ method: request.method
1682
+ };
1683
+ }
1684
+ } else if (request.method === "eth_accounts") {
1685
+ const ethAccounts = yield this.kvstore.get(ACCOUNTS_STORE_KEY);
1686
+ if (ethAccounts) {
1687
+ return {
1688
+ id: request.id,
1689
+ jsonrpc: "2.0",
1690
+ result: JSON.parse(ethAccounts),
1691
+ method: request.method
1692
+ };
1693
+ }
1694
+ } else if (request.method === "eth_chainId") {
1695
+ const ethChainId = yield this.kvstore.get(CHAIN_STORE_KEY);
1696
+ if (ethChainId) {
1697
+ return {
1698
+ id: request.id,
1699
+ jsonrpc: "2.0",
1700
+ result: JSON.parse(ethChainId),
1701
+ method: request.method
1702
+ };
1703
+ }
1704
+ }
1705
+ });
1706
+ }
1707
+ storeWalletSession(request, response) {
1708
+ return __async(this, null, function* () {
1709
+ if (response.error) {
1710
+ return;
1711
+ }
1712
+ if (CACHED_METHOD_LIST.includes(request.method)) {
1713
+ yield this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
1714
+ } else if (request.method === "eth_accounts") {
1715
+ yield this.kvstore.set(
1716
+ ACCOUNTS_STORE_KEY,
1717
+ JSON.stringify(response.result)
1718
+ );
1719
+ } else if (request.method === "eth_chainId") {
1720
+ yield this.kvstore.set(CHAIN_STORE_KEY, JSON.stringify(response.result));
1721
+ } else if (CACHED_RESET_METHOD_LIST.includes(request.method)) {
1722
+ yield this.kvstore.delete(SESSION_STORE_KEY);
1723
+ yield this.kvstore.delete(ACCOUNTS_STORE_KEY);
1724
+ yield this.kvstore.delete(CHAIN_STORE_KEY);
1725
+ }
1726
+ });
1727
+ }
1728
+ request(payload, options) {
1729
+ return __async(this, null, function* () {
1730
+ const request = __spreadValues({
1731
+ jsonrpc: "2.0",
1732
+ id: String(getUniqueRequestId())
1733
+ }, payload);
1734
+ const cachedWalletSession = yield this.getCachedResponse(request);
1735
+ if (cachedWalletSession) {
1736
+ this.notifyCallbacks(cachedWalletSession);
1737
+ return cachedWalletSession;
1738
+ }
1739
+ if (!this.isConnected()) {
1740
+ yield this.attemptResumeSession();
1741
+ }
1742
+ return new Promise((resolve, reject) => {
1743
+ var _a2;
1744
+ const timeout = setTimeout(() => {
1745
+ this.rejectRequest(request.id, new import_multichain_api_client2.TransportTimeoutError());
1746
+ }, (_a2 = options == null ? void 0 : options.timeout) != null ? _a2 : this.options.requestTimeout);
1747
+ this.pendingRequests.set(request.id, {
1748
+ request,
1749
+ method: request.method,
1750
+ resolve: (response) => __async(this, null, function* () {
1751
+ yield this.storeWalletSession(request, response);
1752
+ return resolve(response);
1753
+ }),
1754
+ reject,
1755
+ timeout
1756
+ });
1757
+ this.dappClient.sendRequest({
1758
+ name: MULTICHAIN_PROVIDER_STREAM_NAME,
1759
+ data: request
1760
+ }).catch(reject);
1761
+ });
1762
+ });
1763
+ }
1764
+ onNotification(callback) {
1765
+ this.notificationCallbacks.add(callback);
1766
+ return () => {
1767
+ this.notificationCallbacks.delete(callback);
1768
+ };
1769
+ }
1770
+ getActiveSession() {
1771
+ return __async(this, null, function* () {
1772
+ const { kvstore } = this;
1773
+ const { SessionStore } = yield import("@metamask/mobile-wallet-protocol-core");
1774
+ const sessionStore = yield SessionStore.create(kvstore);
1775
+ try {
1776
+ const [activeSession] = yield sessionStore.list();
1777
+ return activeSession;
1778
+ } catch (error) {
1779
+ logger("error getting active session", error);
1780
+ return void 0;
1781
+ }
1782
+ });
1783
+ }
1784
+ // This method checks if an existing CAIP session response is cached or waits for one
1785
+ // to be received from the wallet if not cached. This is necessary because there is an edge
1786
+ // case during the initial connection flow where after the user has accepted the permission approval
1787
+ // and returned back to the dapp from the wallet, the dapp page may have gotten unloaded and refreshed.
1788
+ // When it is unloaded and refreshed, it will try to resume the session by making a request for wallet_getSession
1789
+ // which should resolve from cache, but because a race condition makes it possible for the response from the wallet
1790
+ // for the initial wallet_createSession connection request to not have been handled and cached yet. This results
1791
+ // in the wallet_getSession request never resolving unless we wait for it explicitly as done in this method.
1792
+ waitForWalletSessionIfNotCached() {
1793
+ return __async(this, null, function* () {
1794
+ const cachedWalletGetSessionResponse = yield this.kvstore.get(SESSION_STORE_KEY);
1795
+ if (cachedWalletGetSessionResponse) {
1796
+ return;
1797
+ }
1798
+ let unsubscribe;
1799
+ const responsePromise = new Promise((resolve) => {
1800
+ unsubscribe = this.onNotification((message) => {
1801
+ if (typeof message === "object" && message !== null) {
1802
+ if ("data" in message) {
1803
+ const messagePayload = message.data;
1804
+ if (messagePayload.method === "wallet_getSession" || messagePayload.method === "wallet_sessionChanged") {
1805
+ unsubscribe();
1806
+ resolve();
1807
+ }
1808
+ }
1809
+ }
1810
+ });
1811
+ });
1812
+ const timeoutPromise = new Promise((_resolve, reject) => {
1813
+ setTimeout(() => {
1814
+ unsubscribe();
1815
+ this.removeStoredPendingSessionRequest();
1816
+ reject(new import_multichain_api_client2.TransportTimeoutError());
1817
+ }, this.options.resumeTimeout);
1818
+ });
1819
+ return Promise.race([responsePromise, timeoutPromise]);
1820
+ });
1821
+ }
1822
+ };
1823
+ }
1824
+ });
1825
+
1826
+ // src/multichain/transports/mwp/KeyManager.ts
1827
+ var KeyManager_exports = {};
1828
+ __export(KeyManager_exports, {
1829
+ createKeyManager: () => createKeyManager
1830
+ });
1831
+ function createKeyManager() {
1832
+ return __async(this, null, function* () {
1833
+ const { decrypt, encrypt, PrivateKey, PublicKey } = yield import("eciesjs");
1834
+ return {
1835
+ generateKeyPair() {
1836
+ const privateKey = new PrivateKey();
1837
+ return {
1838
+ privateKey: new Uint8Array(privateKey.secret),
1839
+ publicKey: privateKey.publicKey.toBytes(true)
1840
+ };
1841
+ },
1842
+ encrypt(plaintext, theirPublicKey) {
1843
+ return __async(this, null, function* () {
1844
+ const plaintextBuffer = Buffer.from(plaintext, "utf8");
1845
+ const encryptedBuffer = encrypt(theirPublicKey, plaintextBuffer);
1846
+ return encryptedBuffer.toString("base64");
1847
+ });
1848
+ },
1849
+ decrypt(encryptedB64, myPrivateKey) {
1850
+ return __async(this, null, function* () {
1851
+ const encryptedBuffer = Buffer.from(encryptedB64, "base64");
1852
+ const decryptedBuffer = yield decrypt(myPrivateKey, encryptedBuffer);
1853
+ return Buffer.from(decryptedBuffer).toString("utf8");
1854
+ });
1855
+ },
1856
+ validatePeerKey(key) {
1857
+ PublicKey.fromHex(Buffer.from(key).toString("hex"));
1858
+ }
1859
+ };
1860
+ });
1861
+ }
1862
+ var init_KeyManager = __esm({
1863
+ "src/multichain/transports/mwp/KeyManager.ts"() {
1864
+ "use strict";
1865
+ }
1866
+ });
1867
+
1045
1868
  // src/ui/modals/base/utils.ts
1046
1869
  function formatRemainingTime(milliseconds) {
1047
1870
  if (milliseconds <= 0) {
@@ -1314,6 +2137,7 @@ __export(index_node_exports, {
1314
2137
  StoreAdapter: () => StoreAdapter,
1315
2138
  StoreClient: () => StoreClient,
1316
2139
  TransportType: () => TransportType,
2140
+ classifyFailureReason: () => classifyFailureReason,
1317
2141
  createLogger: () => createLogger,
1318
2142
  createMultichainClient: () => createMultichainClient,
1319
2143
  enableDebug: () => enableDebug,
@@ -1334,8 +2158,6 @@ init_domain();
1334
2158
 
1335
2159
  // src/multichain/index.ts
1336
2160
  var import_analytics4 = require("@metamask/analytics");
1337
- var import_mobile_wallet_protocol_core2 = require("@metamask/mobile-wallet-protocol-core");
1338
- var import_mobile_wallet_protocol_dapp_client = require("@metamask/mobile-wallet-protocol-dapp-client");
1339
2161
  var import_multichain_api_client3 = require("@metamask/multichain-api-client");
1340
2162
 
1341
2163
  // src/config/index.ts
@@ -1576,7 +2398,7 @@ withAnalyticsTracking_fn = function(options, execute) {
1576
2398
  if (isRejection) {
1577
2399
  yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRejected_fn).call(this, options);
1578
2400
  } else {
1579
- yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options);
2401
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options, error);
1580
2402
  }
1581
2403
  if (error instanceof RPCInvokeMethodErr) {
1582
2404
  throw error;
@@ -1611,13 +2433,14 @@ trackWalletActionSucceeded_fn = function(options) {
1611
2433
  import_analytics2.analytics.track("mmconnect_wallet_action_succeeded", props);
1612
2434
  });
1613
2435
  };
1614
- trackWalletActionFailed_fn = function(options) {
2436
+ trackWalletActionFailed_fn = function(options, error) {
1615
2437
  return __async(this, null, function* () {
1616
2438
  const props = yield getWalletActionAnalyticsProperties(
1617
2439
  this.config,
1618
2440
  this.config.storage,
1619
2441
  options,
1620
- this.transportType
2442
+ this.transportType,
2443
+ extractErrorDiagnostics(error)
1621
2444
  );
1622
2445
  import_analytics2.analytics.track("mmconnect_wallet_action_failed", props);
1623
2446
  });
@@ -1898,6 +2721,9 @@ var MultichainApiClientWrapperTransport = class {
1898
2721
  return false;
1899
2722
  }
1900
2723
  }
2724
+ isTransportConnected() {
2725
+ return this.isTransportDefined() && this.metamaskConnectMultichain.transport.isConnected();
2726
+ }
1901
2727
  clearNotificationCallbacks() {
1902
2728
  __privateGet(this, _notificationCallbacks2).clear();
1903
2729
  }
@@ -1919,17 +2745,19 @@ var MultichainApiClientWrapperTransport = class {
1919
2745
  this.notifyCallbacks.bind(this)
1920
2746
  );
1921
2747
  }
2748
+ // Purposely noop, resolves successfully. Actual connection is handled by the underlying client/transport.
1922
2749
  connect() {
1923
2750
  return __async(this, null, function* () {
1924
- console.log("\u{1F4DA} connect");
1925
- yield this.metamaskConnectMultichain.emitSessionChanged();
2751
+ return Promise.resolve();
1926
2752
  });
1927
2753
  }
2754
+ // Purposely noop, resolves successfully. Actual connection is handled by the underlying client/transport.
1928
2755
  disconnect() {
1929
2756
  return __async(this, null, function* () {
1930
2757
  return Promise.resolve();
1931
2758
  });
1932
2759
  }
2760
+ // Purposely hardcoded to true. Actual connection is handled by the underlying client/transport.
1933
2761
  isConnected() {
1934
2762
  return true;
1935
2763
  }
@@ -1952,7 +2780,6 @@ var MultichainApiClientWrapperTransport = class {
1952
2780
  default:
1953
2781
  throw new Error(`Unsupported method: ${requestPayload.method}`);
1954
2782
  }
1955
- throw new Error(`Unknown method: ${requestPayload.method}`);
1956
2783
  });
1957
2784
  }
1958
2785
  onNotification(callback) {
@@ -1982,13 +2809,11 @@ walletCreateSession_fn = function(request) {
1982
2809
  }
1983
2810
  });
1984
2811
  const accounts = [...new Set(scopeAccounts)];
1985
- console.log("\u{1F4DA} SDK connect");
1986
2812
  yield this.metamaskConnectMultichain.connect(
1987
2813
  scopes,
1988
2814
  accounts,
1989
2815
  createSessionParams.sessionProperties
1990
2816
  );
1991
- console.log("\u{1F4DA} SDK connected");
1992
2817
  return this.metamaskConnectMultichain.transport.request({
1993
2818
  method: "wallet_getSession"
1994
2819
  });
@@ -1996,7 +2821,7 @@ walletCreateSession_fn = function(request) {
1996
2821
  };
1997
2822
  walletGetSession_fn = function(request) {
1998
2823
  return __async(this, null, function* () {
1999
- if (!this.isTransportDefined()) {
2824
+ if (!this.isTransportConnected()) {
2000
2825
  return {
2001
2826
  jsonrpc: "2.0",
2002
2827
  id: request.id,
@@ -2013,9 +2838,6 @@ walletGetSession_fn = function(request) {
2013
2838
  walletRevokeSession_fn = function(request) {
2014
2839
  return __async(this, null, function* () {
2015
2840
  var _a2;
2016
- if (!this.isTransportDefined()) {
2017
- return { jsonrpc: "2.0", id: request.id, result: true };
2018
- }
2019
2841
  const revokeSessionParams = request.params;
2020
2842
  const scopes = (_a2 = revokeSessionParams == null ? void 0 : revokeSessionParams.scopes) != null ? _a2 : [];
2021
2843
  try {
@@ -2028,7 +2850,7 @@ walletRevokeSession_fn = function(request) {
2028
2850
  };
2029
2851
  walletInvokeMethod_fn = function(request) {
2030
2852
  return __async(this, null, function* () {
2031
- if (!this.isTransportDefined()) {
2853
+ if (!this.isTransportConnected()) {
2032
2854
  return { error: import_rpc_errors.providerErrors.unauthorized() };
2033
2855
  }
2034
2856
  const result = this.metamaskConnectMultichain.invokeMethod(
@@ -2040,684 +2862,11 @@ walletInvokeMethod_fn = function(request) {
2040
2862
  });
2041
2863
  };
2042
2864
 
2043
- // src/multichain/transports/mwp/index.ts
2044
- var import_mobile_wallet_protocol_core = require("@metamask/mobile-wallet-protocol-core");
2045
- var import_multichain_api_client2 = require("@metamask/multichain-api-client");
2046
- var import_rpc_errors2 = require("@metamask/rpc-errors");
2047
- init_domain();
2048
- init_utils();
2049
-
2050
- // src/multichain/transports/constants.ts
2051
- var MULTICHAIN_PROVIDER_STREAM_NAME = "metamask-multichain-provider";
2052
-
2053
- // src/multichain/transports/mwp/index.ts
2054
- var DEFAULT_REQUEST_TIMEOUT2 = 60 * 1e3;
2055
- var CONNECTION_GRACE_PERIOD = 60 * 1e3;
2056
- var DEFAULT_CONNECTION_TIMEOUT = DEFAULT_REQUEST_TIMEOUT2 + CONNECTION_GRACE_PERIOD;
2057
- var DEFAULT_RESUME_TIMEOUT = 10 * 1e3;
2058
- var SESSION_STORE_KEY = "cache_wallet_getSession";
2059
- var ACCOUNTS_STORE_KEY = "cache_eth_accounts";
2060
- var CHAIN_STORE_KEY = "cache_eth_chainId";
2061
- var PENDING_SESSION_REQUEST_KEY = "pending_session_request";
2062
- var CACHED_METHOD_LIST = [
2063
- "wallet_getSession",
2064
- "wallet_createSession",
2065
- "wallet_sessionChanged"
2066
- ];
2067
- var CACHED_RESET_METHOD_LIST = [
2068
- "wallet_revokeSession",
2069
- "wallet_revokePermissions"
2070
- ];
2071
- var logger = createLogger("metamask-sdk:transport");
2072
- var MWPTransport = class {
2073
- constructor(dappClient, kvstore, options = {
2074
- requestTimeout: DEFAULT_REQUEST_TIMEOUT2,
2075
- connectionTimeout: DEFAULT_CONNECTION_TIMEOUT,
2076
- resumeTimeout: DEFAULT_RESUME_TIMEOUT
2077
- }) {
2078
- this.dappClient = dappClient;
2079
- this.kvstore = kvstore;
2080
- this.options = options;
2081
- this.__pendingRequests = /* @__PURE__ */ new Map();
2082
- this.notificationCallbacks = /* @__PURE__ */ new Set();
2083
- this.dappClient.on("message", this.handleMessage.bind(this));
2084
- this.dappClient.on("session_request", (sessionRequest) => {
2085
- this.currentSessionRequest = sessionRequest;
2086
- this.kvstore.set(PENDING_SESSION_REQUEST_KEY, JSON.stringify(sessionRequest)).catch((err) => {
2087
- logger("Failed to store pending session request", err);
2088
- });
2089
- });
2090
- if (typeof window !== "undefined" && typeof window.addEventListener !== "undefined") {
2091
- this.windowFocusHandler = this.onWindowFocus.bind(this);
2092
- window.addEventListener("focus", this.windowFocusHandler);
2093
- }
2094
- }
2095
- get pendingRequests() {
2096
- return this.__pendingRequests;
2097
- }
2098
- set pendingRequests(pendingRequests) {
2099
- this.__pendingRequests = pendingRequests;
2100
- }
2101
- get sessionRequest() {
2102
- return this.currentSessionRequest;
2103
- }
2104
- /**
2105
- * Returns the stored pending session request from the dappClient session_request event, if any.
2106
- *
2107
- * @returns The stored SessionRequest, or null if none or invalid.
2108
- */
2109
- getStoredPendingSessionRequest() {
2110
- return __async(this, null, function* () {
2111
- try {
2112
- const raw = yield this.kvstore.get(PENDING_SESSION_REQUEST_KEY);
2113
- if (!raw) {
2114
- return null;
2115
- }
2116
- return JSON.parse(raw);
2117
- } catch (e) {
2118
- return null;
2119
- }
2120
- });
2121
- }
2122
- /**
2123
- * Removes the stored pending session request from the KVStore.
2124
- * This is necessary to ensure that ConnectMultichain is able to correctly
2125
- * infer the MWP Transport connection attempt status.
2126
- */
2127
- removeStoredPendingSessionRequest() {
2128
- return __async(this, null, function* () {
2129
- yield this.kvstore.delete(PENDING_SESSION_REQUEST_KEY);
2130
- });
2131
- }
2132
- onWindowFocus() {
2133
- if (!this.isConnected()) {
2134
- this.dappClient.reconnect();
2135
- }
2136
- }
2137
- notifyCallbacks(data) {
2138
- this.notificationCallbacks.forEach((callback) => callback(data));
2139
- }
2140
- rejectRequest(id, error = new Error("Request rejected")) {
2141
- const request = this.pendingRequests.get(id);
2142
- if (request) {
2143
- this.pendingRequests.delete(id);
2144
- clearTimeout(request.timeout);
2145
- request.reject(error);
2146
- }
2147
- }
2148
- parseWalletError(errorPayload) {
2149
- const errorData = errorPayload;
2150
- if (typeof errorData.code === "number" && typeof errorData.message === "string") {
2151
- const { code, message: message2 } = errorData;
2152
- if (code >= 1e3 && code <= 4999) {
2153
- return import_rpc_errors2.providerErrors.custom({ code, message: message2 });
2154
- }
2155
- return new import_rpc_errors2.JsonRpcError(code, message2);
2156
- }
2157
- const message = errorPayload instanceof Error ? errorPayload.message : JSON.stringify(errorPayload);
2158
- return import_rpc_errors2.rpcErrors.internal({ message });
2159
- }
2160
- handleMessage(message) {
2161
- if (typeof message === "object" && message !== null) {
2162
- if ("data" in message) {
2163
- const messagePayload = message.data;
2164
- if ("id" in messagePayload && typeof messagePayload.id === "string") {
2165
- const request = this.pendingRequests.get(messagePayload.id);
2166
- if (request) {
2167
- clearTimeout(request.timeout);
2168
- if ("error" in messagePayload && messagePayload.error) {
2169
- this.pendingRequests.delete(messagePayload.id);
2170
- request.reject(this.parseWalletError(messagePayload.error));
2171
- return;
2172
- }
2173
- const requestWithName = __spreadProps(__spreadValues({}, messagePayload), {
2174
- method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method
2175
- });
2176
- const notification = __spreadProps(__spreadValues({}, messagePayload), {
2177
- method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method,
2178
- params: requestWithName.result
2179
- });
2180
- this.notifyCallbacks(notification);
2181
- request.resolve(requestWithName);
2182
- this.pendingRequests.delete(messagePayload.id);
2183
- }
2184
- } else {
2185
- if (message.data.method === "metamask_chainChanged") {
2186
- this.kvstore.set(
2187
- CHAIN_STORE_KEY,
2188
- JSON.stringify(
2189
- message.data.params.chainId
2190
- )
2191
- );
2192
- }
2193
- if (message.data.method === "metamask_accountsChanged") {
2194
- this.kvstore.set(
2195
- ACCOUNTS_STORE_KEY,
2196
- JSON.stringify(
2197
- message.data.params
2198
- )
2199
- );
2200
- }
2201
- if (message.data.method === "wallet_sessionChanged") {
2202
- const notification = message.data;
2203
- const response = {
2204
- result: notification.params
2205
- };
2206
- this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
2207
- }
2208
- this.notifyCallbacks(message.data);
2209
- }
2210
- }
2211
- }
2212
- }
2213
- onResumeSuccess(resumeResolve, resumeReject, options) {
2214
- return __async(this, null, function* () {
2215
- var _a2, _b, _c, _d, _e, _f, _g;
2216
- try {
2217
- yield this.waitForWalletSessionIfNotCached();
2218
- const sessionRequest = yield this.request({
2219
- method: "wallet_getSession"
2220
- });
2221
- if (sessionRequest.error) {
2222
- return resumeReject(new Error(sessionRequest.error.message));
2223
- }
2224
- let walletSession = sessionRequest.result;
2225
- if (walletSession && options) {
2226
- const currentScopes = Object.keys(
2227
- (_a2 = walletSession == null ? void 0 : walletSession.sessionScopes) != null ? _a2 : {}
2228
- );
2229
- const proposedScopes = (_b = options == null ? void 0 : options.scopes) != null ? _b : [];
2230
- const proposedCaipAccountIds = (_c = options == null ? void 0 : options.caipAccountIds) != null ? _c : [];
2231
- const hasSameScopesAndAccounts = isSameScopesAndAccounts(
2232
- currentScopes,
2233
- proposedScopes,
2234
- walletSession,
2235
- proposedCaipAccountIds
2236
- );
2237
- if (options.forceRequest || !hasSameScopesAndAccounts) {
2238
- const optionalScopes = addValidAccounts(
2239
- getOptionalScopes((_d = options == null ? void 0 : options.scopes) != null ? _d : []),
2240
- getValidAccounts((_e = options == null ? void 0 : options.caipAccountIds) != null ? _e : [])
2241
- );
2242
- const sessionRequest2 = {
2243
- optionalScopes
2244
- };
2245
- const response = yield this.request({
2246
- method: "wallet_createSession",
2247
- params: sessionRequest2
2248
- });
2249
- if (response.error) {
2250
- return resumeReject(new Error(response.error.message));
2251
- }
2252
- walletSession = response.result;
2253
- }
2254
- } else if (!walletSession) {
2255
- const optionalScopes = addValidAccounts(
2256
- getOptionalScopes((_f = options == null ? void 0 : options.scopes) != null ? _f : []),
2257
- getValidAccounts((_g = options == null ? void 0 : options.caipAccountIds) != null ? _g : [])
2258
- );
2259
- const sessionRequest2 = { optionalScopes };
2260
- const response = yield this.request({
2261
- method: "wallet_createSession",
2262
- params: sessionRequest2
2263
- });
2264
- if (response.error) {
2265
- return resumeReject(new Error(response.error.message));
2266
- }
2267
- walletSession = response.result;
2268
- }
2269
- yield this.removeStoredPendingSessionRequest();
2270
- this.notifyCallbacks({
2271
- method: "wallet_sessionChanged",
2272
- params: walletSession
2273
- });
2274
- return resumeResolve();
2275
- } catch (err) {
2276
- return resumeReject(err);
2277
- }
2278
- });
2279
- }
2280
- init() {
2281
- return __async(this, null, function* () {
2282
- });
2283
- }
2284
- // TODO: Rename this
2285
- sendEip1193Message(payload, options) {
2286
- return __async(this, null, function* () {
2287
- const request = __spreadValues({
2288
- jsonrpc: "2.0",
2289
- id: String(getUniqueRequestId())
2290
- }, payload);
2291
- const cachedWalletSession = yield this.getCachedResponse(request);
2292
- if (cachedWalletSession) {
2293
- this.notifyCallbacks(cachedWalletSession);
2294
- return cachedWalletSession;
2295
- }
2296
- return new Promise((resolve, reject) => {
2297
- var _a2;
2298
- const timeout = setTimeout(() => {
2299
- this.rejectRequest(request.id, new import_multichain_api_client2.TransportTimeoutError());
2300
- }, (_a2 = options == null ? void 0 : options.timeout) != null ? _a2 : this.options.requestTimeout);
2301
- this.pendingRequests.set(request.id, {
2302
- request,
2303
- method: request.method,
2304
- resolve: (response) => __async(this, null, function* () {
2305
- yield this.storeWalletSession(request, response);
2306
- return resolve(response);
2307
- }),
2308
- reject,
2309
- timeout
2310
- });
2311
- this.dappClient.sendRequest({
2312
- name: "metamask-provider",
2313
- data: request
2314
- }).catch(reject);
2315
- });
2316
- });
2317
- }
2318
- connect(options) {
2319
- return __async(this, null, function* () {
2320
- const { dappClient } = this;
2321
- const session = yield this.getActiveSession();
2322
- if (session) {
2323
- logger("active session found", {
2324
- id: session.id,
2325
- channel: session.channel,
2326
- expiresAt: session.expiresAt
2327
- });
2328
- }
2329
- const storedSessionRequestBeforeConnectionAttempt = yield this.getStoredPendingSessionRequest();
2330
- let timeout;
2331
- let initialConnectionMessageHandler;
2332
- const connectionPromise = new Promise((resolve, reject) => __async(this, null, function* () {
2333
- let connection;
2334
- if (session) {
2335
- connection = new Promise((resumeResolve, resumeReject) => {
2336
- var _a2;
2337
- if (this.dappClient.state === "CONNECTED") {
2338
- this.onResumeSuccess(resumeResolve, resumeReject, options);
2339
- } else {
2340
- this.dappClient.once("connected", () => __async(this, null, function* () {
2341
- this.onResumeSuccess(resumeResolve, resumeReject, options);
2342
- }));
2343
- dappClient.resume((_a2 = session == null ? void 0 : session.id) != null ? _a2 : "");
2344
- }
2345
- });
2346
- } else {
2347
- connection = new Promise(
2348
- (resolveConnection, rejectConnection) => {
2349
- var _a2, _b;
2350
- const optionalScopes = addValidAccounts(
2351
- getOptionalScopes((_a2 = options == null ? void 0 : options.scopes) != null ? _a2 : []),
2352
- getValidAccounts((_b = options == null ? void 0 : options.caipAccountIds) != null ? _b : [])
2353
- );
2354
- const sessionRequest = {
2355
- optionalScopes,
2356
- sessionProperties: options == null ? void 0 : options.sessionProperties
2357
- };
2358
- const request = {
2359
- jsonrpc: "2.0",
2360
- id: String(getUniqueRequestId()),
2361
- method: "wallet_createSession",
2362
- params: sessionRequest
2363
- };
2364
- initialConnectionMessageHandler = (message) => __async(this, null, function* () {
2365
- if (typeof message !== "object" || message === null) {
2366
- return;
2367
- }
2368
- if (!("data" in message)) {
2369
- return;
2370
- }
2371
- const messagePayload = message.data;
2372
- const isMatchingId = messagePayload.id === request.id;
2373
- const isMatchingMethod = messagePayload.method === "wallet_createSession" || messagePayload.method === "wallet_sessionChanged";
2374
- if (!isMatchingId && !isMatchingMethod) {
2375
- return;
2376
- }
2377
- if (messagePayload.error) {
2378
- return rejectConnection(
2379
- this.parseWalletError(messagePayload.error)
2380
- );
2381
- }
2382
- yield this.storeWalletSession(
2383
- request,
2384
- messagePayload
2385
- );
2386
- yield this.removeStoredPendingSessionRequest();
2387
- this.notifyCallbacks(messagePayload);
2388
- return resolveConnection();
2389
- });
2390
- this.dappClient.on("message", initialConnectionMessageHandler);
2391
- dappClient.connect({
2392
- mode: "trusted",
2393
- initialPayload: {
2394
- name: MULTICHAIN_PROVIDER_STREAM_NAME,
2395
- data: request
2396
- }
2397
- }).catch((error) => {
2398
- if (initialConnectionMessageHandler) {
2399
- this.dappClient.off(
2400
- "message",
2401
- initialConnectionMessageHandler
2402
- );
2403
- }
2404
- rejectConnection(error);
2405
- });
2406
- }
2407
- );
2408
- }
2409
- timeout = setTimeout(
2410
- () => {
2411
- reject(new import_multichain_api_client2.TransportTimeoutError());
2412
- },
2413
- storedSessionRequestBeforeConnectionAttempt ? this.options.resumeTimeout : this.options.connectionTimeout
2414
- );
2415
- connection.then(resolve).catch(reject);
2416
- }));
2417
- return connectionPromise.catch((error) => __async(this, null, function* () {
2418
- yield this.dappClient.disconnect();
2419
- throw error;
2420
- })).finally(() => {
2421
- if (timeout) {
2422
- clearTimeout(timeout);
2423
- }
2424
- if (initialConnectionMessageHandler) {
2425
- this.dappClient.off("message", initialConnectionMessageHandler);
2426
- initialConnectionMessageHandler = void 0;
2427
- }
2428
- this.removeStoredPendingSessionRequest();
2429
- });
2430
- });
2431
- }
2432
- /**
2433
- * Disconnects from the Mobile Wallet Protocol
2434
- *
2435
- * @param [scopes] - The scopes to revoke. If not provided or empty, all scopes will be revoked.
2436
- * @returns Nothing
2437
- */
2438
- disconnect() {
2439
- return __async(this, arguments, function* (scopes = []) {
2440
- var _a2, _b;
2441
- const cachedSession = yield this.getCachedResponse({
2442
- jsonrpc: "2.0",
2443
- id: "0",
2444
- method: "wallet_getSession"
2445
- });
2446
- const cachedSessionScopes = (_b = (_a2 = cachedSession == null ? void 0 : cachedSession.result) == null ? void 0 : _a2.sessionScopes) != null ? _b : {};
2447
- const remainingScopes = scopes.length === 0 ? [] : Object.keys(cachedSessionScopes).filter(
2448
- (scope) => !scopes.includes(scope)
2449
- );
2450
- const newSessionScopes = Object.fromEntries(
2451
- Object.entries(cachedSessionScopes).filter(
2452
- ([key]) => remainingScopes.includes(key)
2453
- )
2454
- );
2455
- this.request({ method: "wallet_revokeSession", params: { scopes } }).catch(
2456
- (err) => {
2457
- console.error("error revoking session", err);
2458
- }
2459
- );
2460
- const remainingScopesIncludeEip155 = remainingScopes.some(
2461
- (scope) => scope.includes("eip155")
2462
- );
2463
- if (!remainingScopesIncludeEip155) {
2464
- this.kvstore.delete(ACCOUNTS_STORE_KEY);
2465
- this.kvstore.delete(CHAIN_STORE_KEY);
2466
- }
2467
- if (remainingScopes.length > 0) {
2468
- this.kvstore.set(
2469
- SESSION_STORE_KEY,
2470
- JSON.stringify({
2471
- result: {
2472
- sessionScopes: newSessionScopes
2473
- }
2474
- })
2475
- );
2476
- } else {
2477
- this.kvstore.delete(SESSION_STORE_KEY);
2478
- if (typeof window !== "undefined" && typeof window.removeEventListener !== "undefined" && this.windowFocusHandler) {
2479
- window.removeEventListener("focus", this.windowFocusHandler);
2480
- this.windowFocusHandler = void 0;
2481
- }
2482
- yield this.dappClient.disconnect();
2483
- }
2484
- this.notifyCallbacks({
2485
- method: "wallet_sessionChanged",
2486
- params: {
2487
- sessionScopes: newSessionScopes
2488
- }
2489
- });
2490
- });
2491
- }
2492
- /**
2493
- * Checks if the transport is connected
2494
- *
2495
- * @returns True if transport is connected, false otherwise
2496
- */
2497
- isConnected() {
2498
- return this.dappClient.state === "CONNECTED";
2499
- }
2500
- /**
2501
- * Attempts to re-establish a connection via DappClient
2502
- *
2503
- * @returns Nothing
2504
- */
2505
- // TODO: We should re-evaluate adding this to the WebSocketTransport layer from `@metamask/mobile-wallet-protocol-core`
2506
- // ticket: https://consensyssoftware.atlassian.net/browse/WAPI-862
2507
- attemptResumeSession() {
2508
- return __async(this, null, function* () {
2509
- try {
2510
- yield this.dappClient.reconnect();
2511
- yield new Promise((resolve, reject) => {
2512
- const timeout = setTimeout(() => {
2513
- reject(new Error("Resume timeout"));
2514
- }, 2e3);
2515
- if (this.isConnected()) {
2516
- clearTimeout(timeout);
2517
- resolve();
2518
- } else {
2519
- this.dappClient.once("connected", () => {
2520
- clearTimeout(timeout);
2521
- resolve();
2522
- });
2523
- }
2524
- });
2525
- } catch (error) {
2526
- return Promise.reject(
2527
- new Error(`Failed to resume session: ${error.message}`)
2528
- );
2529
- }
2530
- });
2531
- }
2532
- getCachedResponse(request) {
2533
- return __async(this, null, function* () {
2534
- var _a2;
2535
- if (request.method === "wallet_getSession") {
2536
- const walletGetSession = yield this.kvstore.get(SESSION_STORE_KEY);
2537
- if (walletGetSession) {
2538
- const walletSession = JSON.parse(walletGetSession);
2539
- return {
2540
- id: request.id,
2541
- jsonrpc: "2.0",
2542
- result: (_a2 = walletSession.params) != null ? _a2 : walletSession.result,
2543
- // "what?... why walletSession.params?.."
2544
- method: request.method
2545
- };
2546
- }
2547
- } else if (request.method === "eth_accounts") {
2548
- const ethAccounts = yield this.kvstore.get(ACCOUNTS_STORE_KEY);
2549
- if (ethAccounts) {
2550
- return {
2551
- id: request.id,
2552
- jsonrpc: "2.0",
2553
- result: JSON.parse(ethAccounts),
2554
- method: request.method
2555
- };
2556
- }
2557
- } else if (request.method === "eth_chainId") {
2558
- const ethChainId = yield this.kvstore.get(CHAIN_STORE_KEY);
2559
- if (ethChainId) {
2560
- return {
2561
- id: request.id,
2562
- jsonrpc: "2.0",
2563
- result: JSON.parse(ethChainId),
2564
- method: request.method
2565
- };
2566
- }
2567
- }
2568
- });
2569
- }
2570
- storeWalletSession(request, response) {
2571
- return __async(this, null, function* () {
2572
- if (response.error) {
2573
- return;
2574
- }
2575
- if (CACHED_METHOD_LIST.includes(request.method)) {
2576
- yield this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
2577
- } else if (request.method === "eth_accounts") {
2578
- yield this.kvstore.set(
2579
- ACCOUNTS_STORE_KEY,
2580
- JSON.stringify(response.result)
2581
- );
2582
- } else if (request.method === "eth_chainId") {
2583
- yield this.kvstore.set(CHAIN_STORE_KEY, JSON.stringify(response.result));
2584
- } else if (CACHED_RESET_METHOD_LIST.includes(request.method)) {
2585
- yield this.kvstore.delete(SESSION_STORE_KEY);
2586
- yield this.kvstore.delete(ACCOUNTS_STORE_KEY);
2587
- yield this.kvstore.delete(CHAIN_STORE_KEY);
2588
- }
2589
- });
2590
- }
2591
- request(payload, options) {
2592
- return __async(this, null, function* () {
2593
- const request = __spreadValues({
2594
- jsonrpc: "2.0",
2595
- id: String(getUniqueRequestId())
2596
- }, payload);
2597
- const cachedWalletSession = yield this.getCachedResponse(request);
2598
- if (cachedWalletSession) {
2599
- this.notifyCallbacks(cachedWalletSession);
2600
- return cachedWalletSession;
2601
- }
2602
- if (!this.isConnected()) {
2603
- yield this.attemptResumeSession();
2604
- }
2605
- return new Promise((resolve, reject) => {
2606
- var _a2;
2607
- const timeout = setTimeout(() => {
2608
- this.rejectRequest(request.id, new import_multichain_api_client2.TransportTimeoutError());
2609
- }, (_a2 = options == null ? void 0 : options.timeout) != null ? _a2 : this.options.requestTimeout);
2610
- this.pendingRequests.set(request.id, {
2611
- request,
2612
- method: request.method,
2613
- resolve: (response) => __async(this, null, function* () {
2614
- yield this.storeWalletSession(request, response);
2615
- return resolve(response);
2616
- }),
2617
- reject,
2618
- timeout
2619
- });
2620
- this.dappClient.sendRequest({
2621
- name: MULTICHAIN_PROVIDER_STREAM_NAME,
2622
- data: request
2623
- }).catch(reject);
2624
- });
2625
- });
2626
- }
2627
- onNotification(callback) {
2628
- this.notificationCallbacks.add(callback);
2629
- return () => {
2630
- this.notificationCallbacks.delete(callback);
2631
- };
2632
- }
2633
- getActiveSession() {
2634
- return __async(this, null, function* () {
2635
- const { kvstore } = this;
2636
- const sessionStore = yield import_mobile_wallet_protocol_core.SessionStore.create(kvstore);
2637
- try {
2638
- const [activeSession] = yield sessionStore.list();
2639
- return activeSession;
2640
- } catch (error) {
2641
- logger("error getting active session", error);
2642
- return void 0;
2643
- }
2644
- });
2645
- }
2646
- // This method checks if an existing CAIP session response is cached or waits for one
2647
- // to be received from the wallet if not cached. This is necessary because there is an edge
2648
- // case during the initial connection flow where after the user has accepted the permission approval
2649
- // and returned back to the dapp from the wallet, the dapp page may have gotten unloaded and refreshed.
2650
- // When it is unloaded and refreshed, it will try to resume the session by making a request for wallet_getSession
2651
- // which should resolve from cache, but because a race condition makes it possible for the response from the wallet
2652
- // for the initial wallet_createSession connection request to not have been handled and cached yet. This results
2653
- // in the wallet_getSession request never resolving unless we wait for it explicitly as done in this method.
2654
- waitForWalletSessionIfNotCached() {
2655
- return __async(this, null, function* () {
2656
- const cachedWalletGetSessionResponse = yield this.kvstore.get(SESSION_STORE_KEY);
2657
- if (cachedWalletGetSessionResponse) {
2658
- return;
2659
- }
2660
- let unsubscribe;
2661
- const responsePromise = new Promise((resolve) => {
2662
- unsubscribe = this.onNotification((message) => {
2663
- if (typeof message === "object" && message !== null) {
2664
- if ("data" in message) {
2665
- const messagePayload = message.data;
2666
- if (messagePayload.method === "wallet_getSession" || messagePayload.method === "wallet_sessionChanged") {
2667
- unsubscribe();
2668
- resolve();
2669
- }
2670
- }
2671
- }
2672
- });
2673
- });
2674
- const timeoutPromise = new Promise((_resolve, reject) => {
2675
- setTimeout(() => {
2676
- unsubscribe();
2677
- this.removeStoredPendingSessionRequest();
2678
- reject(new import_multichain_api_client2.TransportTimeoutError());
2679
- }, this.options.resumeTimeout);
2680
- });
2681
- return Promise.race([responsePromise, timeoutPromise]);
2682
- });
2683
- }
2684
- };
2685
-
2686
- // src/multichain/transports/mwp/KeyManager.ts
2687
- var import_eciesjs = require("eciesjs");
2688
- var KeyManager = class {
2689
- generateKeyPair() {
2690
- const privateKey = new import_eciesjs.PrivateKey();
2691
- return {
2692
- privateKey: new Uint8Array(privateKey.secret),
2693
- publicKey: privateKey.publicKey.toBytes(true)
2694
- };
2695
- }
2696
- encrypt(plaintext, theirPublicKey) {
2697
- return __async(this, null, function* () {
2698
- const plaintextBuffer = Buffer.from(plaintext, "utf8");
2699
- const encryptedBuffer = (0, import_eciesjs.encrypt)(theirPublicKey, plaintextBuffer);
2700
- return encryptedBuffer.toString("base64");
2701
- });
2702
- }
2703
- decrypt(encryptedB64, myPrivateKey) {
2704
- return __async(this, null, function* () {
2705
- const encryptedBuffer = Buffer.from(encryptedB64, "base64");
2706
- const decryptedBuffer = yield (0, import_eciesjs.decrypt)(myPrivateKey, encryptedBuffer);
2707
- return Buffer.from(decryptedBuffer).toString("utf8");
2708
- });
2709
- }
2710
- validatePeerKey(key) {
2711
- import_eciesjs.PublicKey.fromHex(Buffer.from(key).toString("hex"));
2712
- }
2713
- };
2714
- var keymanager = new KeyManager();
2715
-
2716
2865
  // src/multichain/index.ts
2717
2866
  init_utils();
2718
2867
  var logger2 = createLogger("metamask-sdk:core");
2719
2868
  var SINGLETON_KEY = "__METAMASK_CONNECT_MULTICHAIN_SINGLETON__";
2720
- var _a, _provider, _providerTransportWrapper, _transport2, _dappClient, _beforeUnloadListener, _listener, _anonId, _sdkInfo, _MetaMaskConnectMultichain_instances, setupAnalytics_fn, onTransportNotification_fn, getStoredTransport_fn, setupTransport_fn, buildConnectionMetadata_fn, init_fn2, createDappClient_fn, setupMWP_fn, onBeforeUnload_fn, createBeforeUnloadListener_fn, renderInstallModalAsync_fn, showInstallModal_fn, headlessConnect_fn, setupDefaultTransport_fn, deeplinkConnect_fn, handleConnection_fn, getCaipSession_fn, openConnectDeeplinkIfNeeded_fn;
2869
+ var _a, _provider, _providerTransportWrapper, _transport2, _dappClient, _beforeUnloadListener, _transportType, _listener, _anonId, _sdkInfo, _MetaMaskConnectMultichain_instances, setupAnalytics_fn, onTransportNotification_fn, getStoredTransport_fn, setupTransport_fn, buildConnectionMetadata_fn, init_fn2, createDappClient_fn, setupMWP_fn, onBeforeUnload_fn, createBeforeUnloadListener_fn, renderInstallModalAsync_fn, showInstallModal_fn, headlessConnect_fn, setupDefaultTransport_fn, deeplinkConnect_fn, handleConnection_fn, getCaipSession_fn, openConnectDeeplinkIfNeeded_fn;
2721
2870
  var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends MultichainCore {
2722
2871
  constructor(options) {
2723
2872
  var _a2, _b, _c, _d, _e, _f;
@@ -2735,7 +2884,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2735
2884
  versions: __spreadValues({
2736
2885
  // typeof guard needed: Metro (React Native) bundles TS source directly,
2737
2886
  // bypassing the tsup build that substitutes __PACKAGE_VERSION__.
2738
- "connect-multichain": false ? "unknown" : "0.12.1"
2887
+ "connect-multichain": false ? "unknown" : "0.14.0"
2739
2888
  }, (_f = options.versions) != null ? _f : {})
2740
2889
  });
2741
2890
  super(allOptions);
@@ -2745,6 +2894,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2745
2894
  __privateAdd(this, _transport2);
2746
2895
  __privateAdd(this, _dappClient);
2747
2896
  __privateAdd(this, _beforeUnloadListener);
2897
+ __privateAdd(this, _transportType);
2748
2898
  this._status = "pending";
2749
2899
  __privateAdd(this, _listener);
2750
2900
  __privateAdd(this, _anonId);
@@ -2781,12 +2931,13 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2781
2931
  }
2782
2932
  return __privateGet(this, _dappClient);
2783
2933
  }
2934
+ get transportType() {
2935
+ var _a2;
2936
+ return (_a2 = __privateGet(this, _transportType)) != null ? _a2 : "unknown" /* UNKNOWN */;
2937
+ }
2784
2938
  get storage() {
2785
2939
  return this.options.storage;
2786
2940
  }
2787
- get transportType() {
2788
- return __privateGet(this, _transport2) instanceof MWPTransport ? "mwp" /* MWP */ : "browser" /* Browser */;
2789
- }
2790
2941
  // Creates a singleton instance of MetaMaskConnectMultichain.
2791
2942
  // If the singleton already exists, it merges the incoming options with the
2792
2943
  // existing singleton options for the following keys: `api.supportedNetworks`,
@@ -2840,7 +2991,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2840
2991
  connect(scopes, caipAccountIds, sessionProperties, forceRequest) {
2841
2992
  return __async(this, null, function* () {
2842
2993
  var _a2;
2843
- if (this.status === "connecting" && this.transportType === "mwp" /* MWP */) {
2994
+ if (this.status === "connecting" && __privateGet(this, _transportType) === "mwp" /* MWP */) {
2844
2995
  yield __privateMethod(this, _MetaMaskConnectMultichain_instances, openConnectDeeplinkIfNeeded_fn).call(this);
2845
2996
  throw new Error(
2846
2997
  "Existing connection is pending. Please check your MetaMask Mobile app to continue."
@@ -2889,7 +3040,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2889
3040
  sessionProperties: nonEmptySessionProperties,
2890
3041
  forceRequest
2891
3042
  }).then(() => __async(this, null, function* () {
2892
- if (__privateGet(this, _transport2) instanceof MWPTransport) {
3043
+ if (__privateGet(this, _transportType) === "mwp" /* MWP */) {
2893
3044
  return this.storage.setTransport("mwp" /* MWP */);
2894
3045
  }
2895
3046
  return this.storage.setTransport("browser" /* Browser */);
@@ -2936,12 +3087,13 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2936
3087
  yield (_a2 = __privateGet(this, _transport2)) == null ? void 0 : _a2.disconnect(scopes);
2937
3088
  if (remainingScopes.length === 0) {
2938
3089
  yield this.storage.removeTransport();
2939
- if (this.transportType !== "browser" /* Browser */) {
3090
+ if (__privateGet(this, _transportType) !== "browser" /* Browser */) {
2940
3091
  yield (_b = __privateGet(this, _listener)) == null ? void 0 : _b.call(this);
2941
3092
  (_c = __privateGet(this, _beforeUnloadListener)) == null ? void 0 : _c.call(this);
2942
3093
  __privateSet(this, _listener, void 0);
2943
3094
  __privateSet(this, _beforeUnloadListener, void 0);
2944
3095
  __privateSet(this, _transport2, void 0);
3096
+ __privateSet(this, _transportType, void 0);
2945
3097
  __privateGet(this, _providerTransportWrapper).clearTransportNotificationListener();
2946
3098
  __privateSet(this, _dappClient, void 0);
2947
3099
  }
@@ -2951,13 +3103,14 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2951
3103
  }
2952
3104
  invokeMethod(request) {
2953
3105
  return __async(this, null, function* () {
3106
+ var _a2;
2954
3107
  const { transport, options } = this;
2955
3108
  const rpcClient = new RpcClient(options, __privateGet(this, _sdkInfo));
2956
3109
  const requestRouter = new RequestRouter(
2957
3110
  transport,
2958
3111
  rpcClient,
2959
3112
  options,
2960
- this.transportType
3113
+ (_a2 = __privateGet(this, _transportType)) != null ? _a2 : "unknown" /* UNKNOWN */
2961
3114
  );
2962
3115
  return requestRouter.invokeMethod(request);
2963
3116
  });
@@ -3006,6 +3159,7 @@ _providerTransportWrapper = new WeakMap();
3006
3159
  _transport2 = new WeakMap();
3007
3160
  _dappClient = new WeakMap();
3008
3161
  _beforeUnloadListener = new WeakMap();
3162
+ _transportType = new WeakMap();
3009
3163
  _listener = new WeakMap();
3010
3164
  _anonId = new WeakMap();
3011
3165
  _sdkInfo = new WeakMap();
@@ -3063,6 +3217,7 @@ getStoredTransport_fn = function() {
3063
3217
  if (hasExtensionInstalled) {
3064
3218
  const apiTransport = new DefaultTransport();
3065
3219
  __privateSet(this, _transport2, apiTransport);
3220
+ __privateSet(this, _transportType, "browser" /* Browser */);
3066
3221
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3067
3222
  __privateSet(this, _listener, apiTransport.onNotification(
3068
3223
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
@@ -3072,9 +3227,11 @@ getStoredTransport_fn = function() {
3072
3227
  } else if (transportType === "mwp" /* MWP */) {
3073
3228
  const { adapter: kvstore } = this.options.storage;
3074
3229
  const dappClient = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, createDappClient_fn).call(this);
3075
- const apiTransport = new MWPTransport(dappClient, kvstore);
3230
+ const { MWPTransport: MWPTransport2 } = yield Promise.resolve().then(() => (init_mwp(), mwp_exports));
3231
+ const apiTransport = new MWPTransport2(dappClient, kvstore);
3076
3232
  __privateSet(this, _dappClient, dappClient);
3077
3233
  __privateSet(this, _transport2, apiTransport);
3234
+ __privateSet(this, _transportType, "mwp" /* MWP */);
3078
3235
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3079
3236
  __privateSet(this, _listener, apiTransport.onNotification(
3080
3237
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
@@ -3096,7 +3253,7 @@ setupTransport_fn = function() {
3096
3253
  yield this.transport.connect();
3097
3254
  }
3098
3255
  this.status = "connected";
3099
- if (this.transport instanceof MWPTransport) {
3256
+ if (__privateGet(this, _transportType) === "mwp" /* MWP */) {
3100
3257
  yield this.storage.setTransport("mwp" /* MWP */);
3101
3258
  } else {
3102
3259
  yield this.storage.setTransport("browser" /* Browser */);
@@ -3140,31 +3297,43 @@ init_fn2 = function() {
3140
3297
  };
3141
3298
  createDappClient_fn = function() {
3142
3299
  return __async(this, null, function* () {
3300
+ const [mwpCore, { DappClient: DappClientClass }, { createKeyManager: createKeyManager2 }] = yield Promise.all([
3301
+ import("@metamask/mobile-wallet-protocol-core"),
3302
+ import("@metamask/mobile-wallet-protocol-dapp-client"),
3303
+ Promise.resolve().then(() => (init_KeyManager(), KeyManager_exports))
3304
+ ]);
3305
+ const keymanager = yield createKeyManager2();
3143
3306
  const { adapter: kvstore } = this.options.storage;
3144
- const sessionstore = yield import_mobile_wallet_protocol_core2.SessionStore.create(kvstore);
3307
+ const sessionstore = yield mwpCore.SessionStore.create(kvstore);
3145
3308
  const websocket = (
3146
3309
  // eslint-disable-next-line no-negated-condition
3147
3310
  typeof window !== "undefined" ? WebSocket : (yield import("ws")).WebSocket
3148
3311
  );
3149
- const transport = yield import_mobile_wallet_protocol_core2.WebSocketTransport.create({
3312
+ const transport = yield mwpCore.WebSocketTransport.create({
3150
3313
  url: MWP_RELAY_URL,
3151
3314
  kvstore,
3152
3315
  websocket
3153
3316
  });
3154
- const dappClient = new import_mobile_wallet_protocol_dapp_client.DappClient({ transport, sessionstore, keymanager });
3317
+ const dappClient = new DappClientClass({
3318
+ transport,
3319
+ sessionstore,
3320
+ keymanager
3321
+ });
3155
3322
  return dappClient;
3156
3323
  });
3157
3324
  };
3158
3325
  setupMWP_fn = function() {
3159
3326
  return __async(this, null, function* () {
3160
- if (__privateGet(this, _transport2) instanceof MWPTransport) {
3327
+ if (__privateGet(this, _transportType) === "mwp" /* MWP */) {
3161
3328
  return;
3162
3329
  }
3163
3330
  const { adapter: kvstore } = this.options.storage;
3164
3331
  const dappClient = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, createDappClient_fn).call(this);
3165
3332
  __privateSet(this, _dappClient, dappClient);
3166
- const apiTransport = new MWPTransport(dappClient, kvstore);
3333
+ const { MWPTransport: MWPTransport2 } = yield Promise.resolve().then(() => (init_mwp(), mwp_exports));
3334
+ const apiTransport = new MWPTransport2(dappClient, kvstore);
3167
3335
  __privateSet(this, _transport2, apiTransport);
3336
+ __privateSet(this, _transportType, "mwp" /* MWP */);
3168
3337
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3169
3338
  __privateSet(this, _listener, this.transport.onNotification(
3170
3339
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
@@ -3223,8 +3392,9 @@ renderInstallModalAsync_fn = function(desktopPreferred, scopes, caipAccountIds,
3223
3392
  this.status = "connected";
3224
3393
  yield this.storage.setTransport("mwp" /* MWP */);
3225
3394
  } catch (error) {
3226
- if (error instanceof import_mobile_wallet_protocol_core2.ProtocolError) {
3227
- if (error.code !== import_mobile_wallet_protocol_core2.ErrorCode.REQUEST_EXPIRED) {
3395
+ const { ProtocolError, ErrorCode } = yield import("@metamask/mobile-wallet-protocol-core");
3396
+ if (error instanceof ProtocolError) {
3397
+ if (error.code !== ErrorCode.REQUEST_EXPIRED) {
3228
3398
  this.status = "disconnected";
3229
3399
  yield this.options.ui.factory.unload(error);
3230
3400
  reject(error);
@@ -3292,7 +3462,8 @@ headlessConnect_fn = function(scopes, caipAccountIds, sessionProperties) {
3292
3462
  yield this.storage.setTransport("mwp" /* MWP */);
3293
3463
  resolve();
3294
3464
  })).catch((error) => __async(this, null, function* () {
3295
- if (error instanceof import_mobile_wallet_protocol_core2.ProtocolError) {
3465
+ const { ProtocolError } = yield import("@metamask/mobile-wallet-protocol-core");
3466
+ if (error instanceof ProtocolError) {
3296
3467
  this.status = "disconnected";
3297
3468
  yield this.storage.removeTransport();
3298
3469
  reject(error);
@@ -3307,7 +3478,7 @@ headlessConnect_fn = function(scopes, caipAccountIds, sessionProperties) {
3307
3478
  };
3308
3479
  setupDefaultTransport_fn = function() {
3309
3480
  return __async(this, arguments, function* (options = { persist: true }) {
3310
- if (__privateGet(this, _transport2) instanceof DefaultTransport) {
3481
+ if (__privateGet(this, _transportType) === "browser" /* Browser */) {
3311
3482
  return __privateGet(this, _transport2);
3312
3483
  }
3313
3484
  if (options == null ? void 0 : options.persist) {
@@ -3318,6 +3489,7 @@ setupDefaultTransport_fn = function() {
3318
3489
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
3319
3490
  ));
3320
3491
  __privateSet(this, _transport2, transport);
3492
+ __privateSet(this, _transportType, "browser" /* Browser */);
3321
3493
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3322
3494
  return transport;
3323
3495
  });
@@ -3414,9 +3586,9 @@ handleConnection_fn = function(promise, scopes, transportType) {
3414
3586
  transport_type: transportType
3415
3587
  }));
3416
3588
  } else {
3417
- import_analytics4.analytics.track("mmconnect_connection_failed", __spreadProps(__spreadValues({}, baseProps), {
3589
+ import_analytics4.analytics.track("mmconnect_connection_failed", __spreadValues(__spreadProps(__spreadValues({}, baseProps), {
3418
3590
  transport_type: transportType
3419
- }));
3591
+ }), extractErrorDiagnostics(error)));
3420
3592
  }
3421
3593
  } catch (e) {
3422
3594
  logger2("Error tracking connection failed/rejected event", error);
@@ -3862,6 +4034,7 @@ var createMultichainClient = (options) => __async(null, null, function* () {
3862
4034
  StoreAdapter,
3863
4035
  StoreClient,
3864
4036
  TransportType,
4037
+ classifyFailureReason,
3865
4038
  createLogger,
3866
4039
  createMultichainClient,
3867
4040
  enableDebug,