@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
@@ -949,17 +949,94 @@ var init_utils = __esm({
949
949
  });
950
950
 
951
951
  // src/multichain/utils/analytics.ts
952
+ function sanitiseErrorMessage(message) {
953
+ if (!message) {
954
+ return void 0;
955
+ }
956
+ let sanitised = message;
957
+ for (const { pattern, replacement } of SANITISE_PATTERNS) {
958
+ sanitised = sanitised.replace(pattern, replacement);
959
+ }
960
+ if (sanitised.length > ERROR_MESSAGE_SAMPLE_MAX_LENGTH) {
961
+ sanitised = `${sanitised.slice(0, ERROR_MESSAGE_SAMPLE_MAX_LENGTH - 1)}\u2026`;
962
+ }
963
+ return sanitised;
964
+ }
965
+ function getUnwrappedErrorDetails(error) {
966
+ var _a2, _b, _c, _d;
967
+ if (typeof error !== "object" || error === null) {
968
+ return { code: void 0, message: "" };
969
+ }
970
+ if (error instanceof RPCInvokeMethodErr) {
971
+ return {
972
+ code: (_a2 = error.rpcCode) != null ? _a2 : error.code,
973
+ message: (_c = (_b = error.rpcMessage) != null ? _b : error.message) != null ? _c : ""
974
+ };
975
+ }
976
+ const errorObj = error;
977
+ return {
978
+ code: errorObj.code,
979
+ message: (_d = errorObj.message) != null ? _d : ""
980
+ };
981
+ }
952
982
  function isRejectionError(error) {
953
- var _a2, _b;
954
983
  if (typeof error !== "object" || error === null) {
955
984
  return false;
956
985
  }
986
+ const { code, message } = getUnwrappedErrorDetails(error);
987
+ const errorMessage = message.toLowerCase();
988
+ return code === 4001 || errorMessage.includes("reject") || errorMessage.includes("denied") || errorMessage.includes("cancel") || // Narrow "user …" matches — bare "user" is too greedy (catches Account
989
+ // Abstraction errors like "user operation reverted").
990
+ errorMessage.includes("user rejected") || errorMessage.includes("user denied") || errorMessage.includes("user cancelled") || errorMessage.includes("user canceled");
991
+ }
992
+ function classifyFailureReason(error) {
993
+ var _a2, _b;
994
+ if (typeof error !== "object" || error === null) {
995
+ return "unknown";
996
+ }
957
997
  const errorObj = error;
958
- const errorCode = errorObj.code;
959
- const errorMessage = (_b = (_a2 = errorObj.message) == null ? void 0 : _a2.toLowerCase()) != null ? _b : "";
960
- return errorCode === 4001 || // User rejected request (common EIP-1193 code)
961
- errorCode === 4100 || // Unauthorized (common rejection code)
962
- errorMessage.includes("reject") || errorMessage.includes("denied") || errorMessage.includes("cancel") || errorMessage.includes("user");
998
+ const errorName = (_a2 = errorObj.name) != null ? _a2 : "";
999
+ const errorMessageRaw = (_b = errorObj.message) != null ? _b : "";
1000
+ const errorMessage = errorMessageRaw.toLowerCase();
1001
+ const { code } = getUnwrappedErrorDetails(error);
1002
+ if (typeof code === "number") {
1003
+ if (code === -32601) {
1004
+ return "wallet_method_unsupported";
1005
+ }
1006
+ if (code === -32602) {
1007
+ return "wallet_invalid_params";
1008
+ }
1009
+ if (code === -32603) {
1010
+ return "wallet_internal_error";
1011
+ }
1012
+ if (code <= -32e3 && code >= -32099) {
1013
+ return "wallet_internal_error";
1014
+ }
1015
+ if (code === 4100) {
1016
+ return "wallet_unauthorized";
1017
+ }
1018
+ if (code === 4200) {
1019
+ return "wallet_method_unsupported";
1020
+ }
1021
+ if (code === 4902) {
1022
+ return "unrecognized_chain";
1023
+ }
1024
+ }
1025
+ if (errorName === "TransportTimeoutError" || errorMessageRaw === "Request timeout" || errorMessage.includes("timed out") || errorMessage.includes("timeout")) {
1026
+ return "transport_timeout";
1027
+ }
1028
+ if (errorName === "TransportError" || errorMessage.includes("not connected") || errorMessage.includes("transport disconnect") || errorMessage.includes("connection lost") || errorMessage.includes("socket closed")) {
1029
+ return "transport_disconnect";
1030
+ }
1031
+ return "unknown";
1032
+ }
1033
+ function extractErrorDiagnostics(error) {
1034
+ const failureReason = classifyFailureReason(error);
1035
+ const { code, message } = getUnwrappedErrorDetails(error);
1036
+ const messageSample = sanitiseErrorMessage(message);
1037
+ return __spreadValues(__spreadValues({
1038
+ failure_reason: failureReason
1039
+ }, typeof code === "number" ? { error_code: code } : {}), messageSample ? { error_message_sample: messageSample } : {});
963
1040
  }
964
1041
  function getBaseAnalyticsProperties(options, storage) {
965
1042
  return __async(this, null, function* () {
@@ -975,26 +1052,61 @@ function getBaseAnalyticsProperties(options, storage) {
975
1052
  };
976
1053
  });
977
1054
  }
978
- function getWalletActionAnalyticsProperties(options, storage, invokeOptions, transportType) {
1055
+ function getWalletActionAnalyticsProperties(options, storage, invokeOptions, transportType, extra) {
979
1056
  return __async(this, null, function* () {
980
1057
  var _a2;
981
1058
  const dappId = getDappId(options.dapp);
982
1059
  const anonId = yield storage.getAnonId();
983
- return {
1060
+ return __spreadValues(__spreadValues(__spreadValues({
984
1061
  mmconnect_versions: (_a2 = options.versions) != null ? _a2 : {},
985
1062
  dapp_id: dappId,
986
1063
  method: invokeOptions.request.method,
987
1064
  caip_chain_id: invokeOptions.scope,
988
1065
  anon_id: anonId,
989
1066
  transport_type: transportType
990
- };
1067
+ }, (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 } : {});
991
1068
  });
992
1069
  }
1070
+ var ERROR_MESSAGE_SAMPLE_MAX_LENGTH, SANITISE_PATTERNS;
993
1071
  var init_analytics = __esm({
994
1072
  "src/multichain/utils/analytics.ts"() {
995
1073
  "use strict";
996
1074
  init_utils();
997
1075
  init_domain();
1076
+ ERROR_MESSAGE_SAMPLE_MAX_LENGTH = 200;
1077
+ SANITISE_PATTERNS = [
1078
+ // EVM-style 20-byte hex addresses (e.g. `0x` + 40 hex chars).
1079
+ { pattern: /0x[a-fA-F0-9]{40}/gu, replacement: "<addr>" },
1080
+ // Other long hex blobs: tx hashes, signatures, raw byte strings, large
1081
+ // hex amounts. 16+ hex chars catches 32-byte hashes/signatures without
1082
+ // snagging EVM method selectors (8 chars) or short hex codes.
1083
+ { pattern: /(?:0x)?[a-fA-F0-9]{16,}/gu, replacement: "<hex>" },
1084
+ // URLs of any scheme up to the first whitespace / quote / closing paren.
1085
+ // Catches RPC endpoints, dapp deeplinks, query strings with secrets.
1086
+ { pattern: /https?:\/\/[^\s"')]+/gu, replacement: "<url>" },
1087
+ // Bech32 addresses: short HRP (1-10 lowercase chars) + `1` separator +
1088
+ // ≥38 chars of Bech32 data alphabet `[ac-hj-np-z02-9]` (excludes the
1089
+ // look-alike chars `b`, `i`, `o`, `1`). Covers Bitcoin SegWit
1090
+ // (`bc1…`/`tb1…`) and Cosmos-SDK chains (`cosmos1…`, `osmo1…`,
1091
+ // `juno1…`, `inj1…`, etc.) without enumerating every HRP. Runs before
1092
+ // the Base58 pattern below — see header comment for why.
1093
+ {
1094
+ pattern: /\b[a-z]{1,10}1[ac-hj-np-z02-9]{38,}\b/gu,
1095
+ replacement: "<addr>"
1096
+ },
1097
+ // Base58 tokens (32+ chars, Base58 alphabet `[1-9A-HJ-NP-Za-km-z]`).
1098
+ // Covers Solana pubkeys (32-44 chars), Solana tx signatures (~88 chars),
1099
+ // and Bitcoin Base58 addresses ≥32 chars. The 32-char floor and `\b`
1100
+ // word boundary keep English words and shorter alphanumerics safe.
1101
+ {
1102
+ pattern: /\b[1-9A-HJ-NP-Za-km-z]{32,}\b/gu,
1103
+ replacement: "<addr>"
1104
+ },
1105
+ // Long decimal numbers — token amounts, gas units, timestamps, lamports.
1106
+ // 10+ digits catches typical chain quantities without affecting JSON-RPC
1107
+ // codes (-32601, 4001, etc.) or short numeric IDs.
1108
+ { pattern: /\d{10,}/gu, replacement: "<num>" }
1109
+ ];
998
1110
  }
999
1111
  });
1000
1112
 
@@ -1024,6 +1136,719 @@ var init_domain = __esm({
1024
1136
  }
1025
1137
  });
1026
1138
 
1139
+ // src/multichain/transports/constants.ts
1140
+ var MULTICHAIN_PROVIDER_STREAM_NAME;
1141
+ var init_constants2 = __esm({
1142
+ "src/multichain/transports/constants.ts"() {
1143
+ "use strict";
1144
+ MULTICHAIN_PROVIDER_STREAM_NAME = "metamask-multichain-provider";
1145
+ }
1146
+ });
1147
+
1148
+ // src/multichain/transports/mwp/index.ts
1149
+ var mwp_exports = {};
1150
+ __export(mwp_exports, {
1151
+ MWPTransport: () => MWPTransport
1152
+ });
1153
+ import {
1154
+ TransportTimeoutError
1155
+ } from "@metamask/multichain-api-client";
1156
+ import { JsonRpcError, providerErrors as providerErrors2, rpcErrors } from "@metamask/rpc-errors";
1157
+ var 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;
1158
+ var init_mwp = __esm({
1159
+ "src/multichain/transports/mwp/index.ts"() {
1160
+ "use strict";
1161
+ init_domain();
1162
+ init_utils();
1163
+ init_constants2();
1164
+ DEFAULT_REQUEST_TIMEOUT2 = 60 * 1e3;
1165
+ CONNECTION_GRACE_PERIOD = 60 * 1e3;
1166
+ DEFAULT_CONNECTION_TIMEOUT = DEFAULT_REQUEST_TIMEOUT2 + CONNECTION_GRACE_PERIOD;
1167
+ DEFAULT_RESUME_TIMEOUT = 10 * 1e3;
1168
+ SESSION_STORE_KEY = "cache_wallet_getSession";
1169
+ ACCOUNTS_STORE_KEY = "cache_eth_accounts";
1170
+ CHAIN_STORE_KEY = "cache_eth_chainId";
1171
+ PENDING_SESSION_REQUEST_KEY = "pending_session_request";
1172
+ CACHED_METHOD_LIST = [
1173
+ "wallet_getSession",
1174
+ "wallet_createSession",
1175
+ "wallet_sessionChanged"
1176
+ ];
1177
+ CACHED_RESET_METHOD_LIST = [
1178
+ "wallet_revokeSession",
1179
+ "wallet_revokePermissions"
1180
+ ];
1181
+ logger = createLogger("metamask-sdk:transport");
1182
+ MWPTransport = class {
1183
+ constructor(dappClient, kvstore, options = {
1184
+ requestTimeout: DEFAULT_REQUEST_TIMEOUT2,
1185
+ connectionTimeout: DEFAULT_CONNECTION_TIMEOUT,
1186
+ resumeTimeout: DEFAULT_RESUME_TIMEOUT
1187
+ }) {
1188
+ this.dappClient = dappClient;
1189
+ this.kvstore = kvstore;
1190
+ this.options = options;
1191
+ this.__pendingRequests = /* @__PURE__ */ new Map();
1192
+ this.notificationCallbacks = /* @__PURE__ */ new Set();
1193
+ this.dappClient.on("message", this.handleMessage.bind(this));
1194
+ this.dappClient.on("session_request", (sessionRequest) => {
1195
+ this.currentSessionRequest = sessionRequest;
1196
+ this.kvstore.set(PENDING_SESSION_REQUEST_KEY, JSON.stringify(sessionRequest)).catch((err) => {
1197
+ logger("Failed to store pending session request", err);
1198
+ });
1199
+ });
1200
+ if (typeof window !== "undefined" && typeof window.addEventListener !== "undefined") {
1201
+ this.windowFocusHandler = this.onWindowFocus.bind(this);
1202
+ window.addEventListener("focus", this.windowFocusHandler);
1203
+ }
1204
+ }
1205
+ get pendingRequests() {
1206
+ return this.__pendingRequests;
1207
+ }
1208
+ set pendingRequests(pendingRequests) {
1209
+ this.__pendingRequests = pendingRequests;
1210
+ }
1211
+ get sessionRequest() {
1212
+ return this.currentSessionRequest;
1213
+ }
1214
+ /**
1215
+ * Returns the stored pending session request from the dappClient session_request event, if any.
1216
+ *
1217
+ * @returns The stored SessionRequest, or null if none or invalid.
1218
+ */
1219
+ getStoredPendingSessionRequest() {
1220
+ return __async(this, null, function* () {
1221
+ try {
1222
+ const raw = yield this.kvstore.get(PENDING_SESSION_REQUEST_KEY);
1223
+ if (!raw) {
1224
+ return null;
1225
+ }
1226
+ return JSON.parse(raw);
1227
+ } catch (e) {
1228
+ return null;
1229
+ }
1230
+ });
1231
+ }
1232
+ /**
1233
+ * Removes the stored pending session request from the KVStore.
1234
+ * This is necessary to ensure that ConnectMultichain is able to correctly
1235
+ * infer the MWP Transport connection attempt status.
1236
+ */
1237
+ removeStoredPendingSessionRequest() {
1238
+ return __async(this, null, function* () {
1239
+ yield this.kvstore.delete(PENDING_SESSION_REQUEST_KEY);
1240
+ });
1241
+ }
1242
+ onWindowFocus() {
1243
+ if (!this.isConnected()) {
1244
+ this.dappClient.reconnect();
1245
+ }
1246
+ }
1247
+ notifyCallbacks(data) {
1248
+ this.notificationCallbacks.forEach((callback) => callback(data));
1249
+ }
1250
+ rejectRequest(id, error = new Error("Request rejected")) {
1251
+ const request = this.pendingRequests.get(id);
1252
+ if (request) {
1253
+ this.pendingRequests.delete(id);
1254
+ clearTimeout(request.timeout);
1255
+ request.reject(error);
1256
+ }
1257
+ }
1258
+ parseWalletError(errorPayload) {
1259
+ const errorData = errorPayload;
1260
+ if (typeof errorData.code === "number" && typeof errorData.message === "string") {
1261
+ const { code, message: message2 } = errorData;
1262
+ if (code >= 1e3 && code <= 4999) {
1263
+ return providerErrors2.custom({ code, message: message2 });
1264
+ }
1265
+ return new JsonRpcError(code, message2);
1266
+ }
1267
+ const message = errorPayload instanceof Error ? errorPayload.message : JSON.stringify(errorPayload);
1268
+ return rpcErrors.internal({ message });
1269
+ }
1270
+ handleMessage(message) {
1271
+ if (typeof message === "object" && message !== null) {
1272
+ if ("data" in message) {
1273
+ const messagePayload = message.data;
1274
+ if ("id" in messagePayload && typeof messagePayload.id === "string") {
1275
+ const request = this.pendingRequests.get(messagePayload.id);
1276
+ if (request) {
1277
+ clearTimeout(request.timeout);
1278
+ if ("error" in messagePayload && messagePayload.error) {
1279
+ this.pendingRequests.delete(messagePayload.id);
1280
+ request.reject(this.parseWalletError(messagePayload.error));
1281
+ return;
1282
+ }
1283
+ const requestWithName = __spreadProps(__spreadValues({}, messagePayload), {
1284
+ method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method
1285
+ });
1286
+ const notification = __spreadProps(__spreadValues({}, messagePayload), {
1287
+ method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method,
1288
+ params: requestWithName.result
1289
+ });
1290
+ this.notifyCallbacks(notification);
1291
+ request.resolve(requestWithName);
1292
+ this.pendingRequests.delete(messagePayload.id);
1293
+ }
1294
+ } else {
1295
+ if (message.data.method === "metamask_chainChanged") {
1296
+ this.kvstore.set(
1297
+ CHAIN_STORE_KEY,
1298
+ JSON.stringify(
1299
+ message.data.params.chainId
1300
+ )
1301
+ );
1302
+ }
1303
+ if (message.data.method === "metamask_accountsChanged") {
1304
+ this.kvstore.set(
1305
+ ACCOUNTS_STORE_KEY,
1306
+ JSON.stringify(
1307
+ message.data.params
1308
+ )
1309
+ );
1310
+ }
1311
+ if (message.data.method === "wallet_sessionChanged") {
1312
+ const notification = message.data;
1313
+ const response = {
1314
+ result: notification.params
1315
+ };
1316
+ this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
1317
+ }
1318
+ this.notifyCallbacks(message.data);
1319
+ }
1320
+ }
1321
+ }
1322
+ }
1323
+ onResumeSuccess(resumeResolve, resumeReject, options) {
1324
+ return __async(this, null, function* () {
1325
+ var _a2, _b, _c, _d, _e, _f, _g;
1326
+ try {
1327
+ yield this.waitForWalletSessionIfNotCached();
1328
+ const sessionRequest = yield this.request({
1329
+ method: "wallet_getSession"
1330
+ });
1331
+ if (sessionRequest.error) {
1332
+ return resumeReject(new Error(sessionRequest.error.message));
1333
+ }
1334
+ let walletSession = sessionRequest.result;
1335
+ if (walletSession && options) {
1336
+ const currentScopes = Object.keys(
1337
+ (_a2 = walletSession == null ? void 0 : walletSession.sessionScopes) != null ? _a2 : {}
1338
+ );
1339
+ const proposedScopes = (_b = options == null ? void 0 : options.scopes) != null ? _b : [];
1340
+ const proposedCaipAccountIds = (_c = options == null ? void 0 : options.caipAccountIds) != null ? _c : [];
1341
+ const hasSameScopesAndAccounts = isSameScopesAndAccounts(
1342
+ currentScopes,
1343
+ proposedScopes,
1344
+ walletSession,
1345
+ proposedCaipAccountIds
1346
+ );
1347
+ if (options.forceRequest || !hasSameScopesAndAccounts) {
1348
+ const optionalScopes = addValidAccounts(
1349
+ getOptionalScopes((_d = options == null ? void 0 : options.scopes) != null ? _d : []),
1350
+ getValidAccounts((_e = options == null ? void 0 : options.caipAccountIds) != null ? _e : [])
1351
+ );
1352
+ const sessionRequest2 = {
1353
+ optionalScopes
1354
+ };
1355
+ const response = yield this.request({
1356
+ method: "wallet_createSession",
1357
+ params: sessionRequest2
1358
+ });
1359
+ if (response.error) {
1360
+ return resumeReject(new Error(response.error.message));
1361
+ }
1362
+ walletSession = response.result;
1363
+ }
1364
+ } else if (!walletSession) {
1365
+ const optionalScopes = addValidAccounts(
1366
+ getOptionalScopes((_f = options == null ? void 0 : options.scopes) != null ? _f : []),
1367
+ getValidAccounts((_g = options == null ? void 0 : options.caipAccountIds) != null ? _g : [])
1368
+ );
1369
+ const sessionRequest2 = { optionalScopes };
1370
+ const response = yield this.request({
1371
+ method: "wallet_createSession",
1372
+ params: sessionRequest2
1373
+ });
1374
+ if (response.error) {
1375
+ return resumeReject(new Error(response.error.message));
1376
+ }
1377
+ walletSession = response.result;
1378
+ }
1379
+ yield this.removeStoredPendingSessionRequest();
1380
+ this.notifyCallbacks({
1381
+ method: "wallet_sessionChanged",
1382
+ params: walletSession
1383
+ });
1384
+ return resumeResolve();
1385
+ } catch (err) {
1386
+ return resumeReject(err);
1387
+ }
1388
+ });
1389
+ }
1390
+ init() {
1391
+ return __async(this, null, function* () {
1392
+ });
1393
+ }
1394
+ // TODO: Rename this
1395
+ sendEip1193Message(payload, options) {
1396
+ return __async(this, null, function* () {
1397
+ const request = __spreadValues({
1398
+ jsonrpc: "2.0",
1399
+ id: String(getUniqueRequestId())
1400
+ }, payload);
1401
+ const cachedWalletSession = yield this.getCachedResponse(request);
1402
+ if (cachedWalletSession) {
1403
+ this.notifyCallbacks(cachedWalletSession);
1404
+ return cachedWalletSession;
1405
+ }
1406
+ return new Promise((resolve, reject) => {
1407
+ var _a2;
1408
+ const timeout = setTimeout(() => {
1409
+ this.rejectRequest(request.id, new TransportTimeoutError());
1410
+ }, (_a2 = options == null ? void 0 : options.timeout) != null ? _a2 : this.options.requestTimeout);
1411
+ this.pendingRequests.set(request.id, {
1412
+ request,
1413
+ method: request.method,
1414
+ resolve: (response) => __async(this, null, function* () {
1415
+ yield this.storeWalletSession(request, response);
1416
+ return resolve(response);
1417
+ }),
1418
+ reject,
1419
+ timeout
1420
+ });
1421
+ this.dappClient.sendRequest({
1422
+ name: "metamask-provider",
1423
+ data: request
1424
+ }).catch(reject);
1425
+ });
1426
+ });
1427
+ }
1428
+ connect(options) {
1429
+ return __async(this, null, function* () {
1430
+ const { dappClient } = this;
1431
+ const session = yield this.getActiveSession();
1432
+ if (session) {
1433
+ logger("active session found", {
1434
+ id: session.id,
1435
+ channel: session.channel,
1436
+ expiresAt: session.expiresAt
1437
+ });
1438
+ }
1439
+ const storedSessionRequestBeforeConnectionAttempt = yield this.getStoredPendingSessionRequest();
1440
+ let timeout;
1441
+ let initialConnectionMessageHandler;
1442
+ const connectionPromise = new Promise((resolve, reject) => __async(this, null, function* () {
1443
+ let connection;
1444
+ if (session) {
1445
+ connection = new Promise((resumeResolve, resumeReject) => {
1446
+ var _a2;
1447
+ if (this.dappClient.state === "CONNECTED") {
1448
+ this.onResumeSuccess(resumeResolve, resumeReject, options);
1449
+ } else {
1450
+ this.dappClient.once("connected", () => __async(this, null, function* () {
1451
+ this.onResumeSuccess(resumeResolve, resumeReject, options);
1452
+ }));
1453
+ dappClient.resume((_a2 = session == null ? void 0 : session.id) != null ? _a2 : "");
1454
+ }
1455
+ });
1456
+ } else {
1457
+ connection = new Promise(
1458
+ (resolveConnection, rejectConnection) => {
1459
+ var _a2, _b;
1460
+ const optionalScopes = addValidAccounts(
1461
+ getOptionalScopes((_a2 = options == null ? void 0 : options.scopes) != null ? _a2 : []),
1462
+ getValidAccounts((_b = options == null ? void 0 : options.caipAccountIds) != null ? _b : [])
1463
+ );
1464
+ const sessionRequest = {
1465
+ optionalScopes,
1466
+ sessionProperties: options == null ? void 0 : options.sessionProperties
1467
+ };
1468
+ const request = {
1469
+ jsonrpc: "2.0",
1470
+ id: String(getUniqueRequestId()),
1471
+ method: "wallet_createSession",
1472
+ params: sessionRequest
1473
+ };
1474
+ initialConnectionMessageHandler = (message) => __async(this, null, function* () {
1475
+ if (typeof message !== "object" || message === null) {
1476
+ return;
1477
+ }
1478
+ if (!("data" in message)) {
1479
+ return;
1480
+ }
1481
+ const messagePayload = message.data;
1482
+ const isMatchingId = messagePayload.id === request.id;
1483
+ const isMatchingMethod = messagePayload.method === "wallet_createSession" || messagePayload.method === "wallet_sessionChanged";
1484
+ if (!isMatchingId && !isMatchingMethod) {
1485
+ return;
1486
+ }
1487
+ if (messagePayload.error) {
1488
+ return rejectConnection(
1489
+ this.parseWalletError(messagePayload.error)
1490
+ );
1491
+ }
1492
+ yield this.storeWalletSession(
1493
+ request,
1494
+ messagePayload
1495
+ );
1496
+ yield this.removeStoredPendingSessionRequest();
1497
+ this.notifyCallbacks(messagePayload);
1498
+ return resolveConnection();
1499
+ });
1500
+ this.dappClient.on("message", initialConnectionMessageHandler);
1501
+ const platformType = getPlatformType();
1502
+ const isQRCodeFlow = [
1503
+ "web-desktop" /* DesktopWeb */,
1504
+ "nodejs" /* NonBrowser */
1505
+ ].includes(platformType);
1506
+ const initialPayload = {
1507
+ name: MULTICHAIN_PROVIDER_STREAM_NAME,
1508
+ data: request
1509
+ };
1510
+ dappClient.connect({
1511
+ mode: "trusted",
1512
+ initialPayload: isQRCodeFlow ? void 0 : initialPayload
1513
+ }).then(() => __async(this, null, function* () {
1514
+ if (isQRCodeFlow) {
1515
+ return dappClient.sendRequest(initialPayload);
1516
+ }
1517
+ return void 0;
1518
+ })).catch((error) => {
1519
+ if (initialConnectionMessageHandler) {
1520
+ this.dappClient.off(
1521
+ "message",
1522
+ initialConnectionMessageHandler
1523
+ );
1524
+ }
1525
+ rejectConnection(error);
1526
+ });
1527
+ }
1528
+ );
1529
+ }
1530
+ timeout = setTimeout(
1531
+ () => {
1532
+ reject(new TransportTimeoutError());
1533
+ },
1534
+ storedSessionRequestBeforeConnectionAttempt ? this.options.resumeTimeout : this.options.connectionTimeout
1535
+ );
1536
+ connection.then(resolve).catch(reject);
1537
+ }));
1538
+ return connectionPromise.catch((error) => __async(this, null, function* () {
1539
+ yield this.dappClient.disconnect();
1540
+ throw error;
1541
+ })).finally(() => {
1542
+ if (timeout) {
1543
+ clearTimeout(timeout);
1544
+ }
1545
+ if (initialConnectionMessageHandler) {
1546
+ this.dappClient.off("message", initialConnectionMessageHandler);
1547
+ initialConnectionMessageHandler = void 0;
1548
+ }
1549
+ this.removeStoredPendingSessionRequest();
1550
+ });
1551
+ });
1552
+ }
1553
+ /**
1554
+ * Disconnects from the Mobile Wallet Protocol
1555
+ *
1556
+ * @param [scopes] - The scopes to revoke. If not provided or empty, all scopes will be revoked.
1557
+ * @returns Nothing
1558
+ */
1559
+ disconnect() {
1560
+ return __async(this, arguments, function* (scopes = []) {
1561
+ var _a2, _b;
1562
+ const cachedSession = yield this.getCachedResponse({
1563
+ jsonrpc: "2.0",
1564
+ id: "0",
1565
+ method: "wallet_getSession"
1566
+ });
1567
+ const cachedSessionScopes = (_b = (_a2 = cachedSession == null ? void 0 : cachedSession.result) == null ? void 0 : _a2.sessionScopes) != null ? _b : {};
1568
+ const remainingScopes = scopes.length === 0 ? [] : Object.keys(cachedSessionScopes).filter(
1569
+ (scope) => !scopes.includes(scope)
1570
+ );
1571
+ const newSessionScopes = Object.fromEntries(
1572
+ Object.entries(cachedSessionScopes).filter(
1573
+ ([key]) => remainingScopes.includes(key)
1574
+ )
1575
+ );
1576
+ this.request({ method: "wallet_revokeSession", params: { scopes } }).catch(
1577
+ (err) => {
1578
+ console.error("error revoking session", err);
1579
+ }
1580
+ );
1581
+ const remainingScopesIncludeEip155 = remainingScopes.some(
1582
+ (scope) => scope.includes("eip155")
1583
+ );
1584
+ if (!remainingScopesIncludeEip155) {
1585
+ this.kvstore.delete(ACCOUNTS_STORE_KEY);
1586
+ this.kvstore.delete(CHAIN_STORE_KEY);
1587
+ }
1588
+ if (remainingScopes.length > 0) {
1589
+ this.kvstore.set(
1590
+ SESSION_STORE_KEY,
1591
+ JSON.stringify({
1592
+ result: {
1593
+ sessionScopes: newSessionScopes
1594
+ }
1595
+ })
1596
+ );
1597
+ } else {
1598
+ this.kvstore.delete(SESSION_STORE_KEY);
1599
+ if (typeof window !== "undefined" && typeof window.removeEventListener !== "undefined" && this.windowFocusHandler) {
1600
+ window.removeEventListener("focus", this.windowFocusHandler);
1601
+ this.windowFocusHandler = void 0;
1602
+ }
1603
+ yield this.dappClient.disconnect();
1604
+ }
1605
+ this.notifyCallbacks({
1606
+ method: "wallet_sessionChanged",
1607
+ params: {
1608
+ sessionScopes: newSessionScopes
1609
+ }
1610
+ });
1611
+ });
1612
+ }
1613
+ /**
1614
+ * Checks if the transport is connected
1615
+ *
1616
+ * @returns True if transport is connected, false otherwise
1617
+ */
1618
+ isConnected() {
1619
+ return this.dappClient.state === "CONNECTED";
1620
+ }
1621
+ /**
1622
+ * Attempts to re-establish a connection via DappClient
1623
+ *
1624
+ * @returns Nothing
1625
+ */
1626
+ // TODO: We should re-evaluate adding this to the WebSocketTransport layer from `@metamask/mobile-wallet-protocol-core`
1627
+ // ticket: https://consensyssoftware.atlassian.net/browse/WAPI-862
1628
+ attemptResumeSession() {
1629
+ return __async(this, null, function* () {
1630
+ try {
1631
+ yield this.dappClient.reconnect();
1632
+ yield new Promise((resolve, reject) => {
1633
+ const timeout = setTimeout(() => {
1634
+ reject(new Error("Resume timeout"));
1635
+ }, 2e3);
1636
+ if (this.isConnected()) {
1637
+ clearTimeout(timeout);
1638
+ resolve();
1639
+ } else {
1640
+ this.dappClient.once("connected", () => {
1641
+ clearTimeout(timeout);
1642
+ resolve();
1643
+ });
1644
+ }
1645
+ });
1646
+ } catch (error) {
1647
+ return Promise.reject(
1648
+ new Error(`Failed to resume session: ${error.message}`)
1649
+ );
1650
+ }
1651
+ });
1652
+ }
1653
+ getCachedResponse(request) {
1654
+ return __async(this, null, function* () {
1655
+ var _a2;
1656
+ if (request.method === "wallet_getSession") {
1657
+ const walletGetSession = yield this.kvstore.get(SESSION_STORE_KEY);
1658
+ if (walletGetSession) {
1659
+ const walletSession = JSON.parse(walletGetSession);
1660
+ return {
1661
+ id: request.id,
1662
+ jsonrpc: "2.0",
1663
+ result: (_a2 = walletSession.params) != null ? _a2 : walletSession.result,
1664
+ // "what?... why walletSession.params?.."
1665
+ method: request.method
1666
+ };
1667
+ }
1668
+ } else if (request.method === "eth_accounts") {
1669
+ const ethAccounts = yield this.kvstore.get(ACCOUNTS_STORE_KEY);
1670
+ if (ethAccounts) {
1671
+ return {
1672
+ id: request.id,
1673
+ jsonrpc: "2.0",
1674
+ result: JSON.parse(ethAccounts),
1675
+ method: request.method
1676
+ };
1677
+ }
1678
+ } else if (request.method === "eth_chainId") {
1679
+ const ethChainId = yield this.kvstore.get(CHAIN_STORE_KEY);
1680
+ if (ethChainId) {
1681
+ return {
1682
+ id: request.id,
1683
+ jsonrpc: "2.0",
1684
+ result: JSON.parse(ethChainId),
1685
+ method: request.method
1686
+ };
1687
+ }
1688
+ }
1689
+ });
1690
+ }
1691
+ storeWalletSession(request, response) {
1692
+ return __async(this, null, function* () {
1693
+ if (response.error) {
1694
+ return;
1695
+ }
1696
+ if (CACHED_METHOD_LIST.includes(request.method)) {
1697
+ yield this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
1698
+ } else if (request.method === "eth_accounts") {
1699
+ yield this.kvstore.set(
1700
+ ACCOUNTS_STORE_KEY,
1701
+ JSON.stringify(response.result)
1702
+ );
1703
+ } else if (request.method === "eth_chainId") {
1704
+ yield this.kvstore.set(CHAIN_STORE_KEY, JSON.stringify(response.result));
1705
+ } else if (CACHED_RESET_METHOD_LIST.includes(request.method)) {
1706
+ yield this.kvstore.delete(SESSION_STORE_KEY);
1707
+ yield this.kvstore.delete(ACCOUNTS_STORE_KEY);
1708
+ yield this.kvstore.delete(CHAIN_STORE_KEY);
1709
+ }
1710
+ });
1711
+ }
1712
+ request(payload, options) {
1713
+ return __async(this, null, function* () {
1714
+ const request = __spreadValues({
1715
+ jsonrpc: "2.0",
1716
+ id: String(getUniqueRequestId())
1717
+ }, payload);
1718
+ const cachedWalletSession = yield this.getCachedResponse(request);
1719
+ if (cachedWalletSession) {
1720
+ this.notifyCallbacks(cachedWalletSession);
1721
+ return cachedWalletSession;
1722
+ }
1723
+ if (!this.isConnected()) {
1724
+ yield this.attemptResumeSession();
1725
+ }
1726
+ return new Promise((resolve, reject) => {
1727
+ var _a2;
1728
+ const timeout = setTimeout(() => {
1729
+ this.rejectRequest(request.id, new TransportTimeoutError());
1730
+ }, (_a2 = options == null ? void 0 : options.timeout) != null ? _a2 : this.options.requestTimeout);
1731
+ this.pendingRequests.set(request.id, {
1732
+ request,
1733
+ method: request.method,
1734
+ resolve: (response) => __async(this, null, function* () {
1735
+ yield this.storeWalletSession(request, response);
1736
+ return resolve(response);
1737
+ }),
1738
+ reject,
1739
+ timeout
1740
+ });
1741
+ this.dappClient.sendRequest({
1742
+ name: MULTICHAIN_PROVIDER_STREAM_NAME,
1743
+ data: request
1744
+ }).catch(reject);
1745
+ });
1746
+ });
1747
+ }
1748
+ onNotification(callback) {
1749
+ this.notificationCallbacks.add(callback);
1750
+ return () => {
1751
+ this.notificationCallbacks.delete(callback);
1752
+ };
1753
+ }
1754
+ getActiveSession() {
1755
+ return __async(this, null, function* () {
1756
+ const { kvstore } = this;
1757
+ const { SessionStore } = yield import("@metamask/mobile-wallet-protocol-core");
1758
+ const sessionStore = yield SessionStore.create(kvstore);
1759
+ try {
1760
+ const [activeSession] = yield sessionStore.list();
1761
+ return activeSession;
1762
+ } catch (error) {
1763
+ logger("error getting active session", error);
1764
+ return void 0;
1765
+ }
1766
+ });
1767
+ }
1768
+ // This method checks if an existing CAIP session response is cached or waits for one
1769
+ // to be received from the wallet if not cached. This is necessary because there is an edge
1770
+ // case during the initial connection flow where after the user has accepted the permission approval
1771
+ // and returned back to the dapp from the wallet, the dapp page may have gotten unloaded and refreshed.
1772
+ // When it is unloaded and refreshed, it will try to resume the session by making a request for wallet_getSession
1773
+ // which should resolve from cache, but because a race condition makes it possible for the response from the wallet
1774
+ // for the initial wallet_createSession connection request to not have been handled and cached yet. This results
1775
+ // in the wallet_getSession request never resolving unless we wait for it explicitly as done in this method.
1776
+ waitForWalletSessionIfNotCached() {
1777
+ return __async(this, null, function* () {
1778
+ const cachedWalletGetSessionResponse = yield this.kvstore.get(SESSION_STORE_KEY);
1779
+ if (cachedWalletGetSessionResponse) {
1780
+ return;
1781
+ }
1782
+ let unsubscribe;
1783
+ const responsePromise = new Promise((resolve) => {
1784
+ unsubscribe = this.onNotification((message) => {
1785
+ if (typeof message === "object" && message !== null) {
1786
+ if ("data" in message) {
1787
+ const messagePayload = message.data;
1788
+ if (messagePayload.method === "wallet_getSession" || messagePayload.method === "wallet_sessionChanged") {
1789
+ unsubscribe();
1790
+ resolve();
1791
+ }
1792
+ }
1793
+ }
1794
+ });
1795
+ });
1796
+ const timeoutPromise = new Promise((_resolve, reject) => {
1797
+ setTimeout(() => {
1798
+ unsubscribe();
1799
+ this.removeStoredPendingSessionRequest();
1800
+ reject(new TransportTimeoutError());
1801
+ }, this.options.resumeTimeout);
1802
+ });
1803
+ return Promise.race([responsePromise, timeoutPromise]);
1804
+ });
1805
+ }
1806
+ };
1807
+ }
1808
+ });
1809
+
1810
+ // src/multichain/transports/mwp/KeyManager.ts
1811
+ var KeyManager_exports = {};
1812
+ __export(KeyManager_exports, {
1813
+ createKeyManager: () => createKeyManager
1814
+ });
1815
+ function createKeyManager() {
1816
+ return __async(this, null, function* () {
1817
+ const { decrypt, encrypt, PrivateKey, PublicKey } = yield import("eciesjs");
1818
+ return {
1819
+ generateKeyPair() {
1820
+ const privateKey = new PrivateKey();
1821
+ return {
1822
+ privateKey: new Uint8Array(privateKey.secret),
1823
+ publicKey: privateKey.publicKey.toBytes(true)
1824
+ };
1825
+ },
1826
+ encrypt(plaintext, theirPublicKey) {
1827
+ return __async(this, null, function* () {
1828
+ const plaintextBuffer = Buffer.from(plaintext, "utf8");
1829
+ const encryptedBuffer = encrypt(theirPublicKey, plaintextBuffer);
1830
+ return encryptedBuffer.toString("base64");
1831
+ });
1832
+ },
1833
+ decrypt(encryptedB64, myPrivateKey) {
1834
+ return __async(this, null, function* () {
1835
+ const encryptedBuffer = Buffer.from(encryptedB64, "base64");
1836
+ const decryptedBuffer = yield decrypt(myPrivateKey, encryptedBuffer);
1837
+ return Buffer.from(decryptedBuffer).toString("utf8");
1838
+ });
1839
+ },
1840
+ validatePeerKey(key) {
1841
+ PublicKey.fromHex(Buffer.from(key).toString("hex"));
1842
+ }
1843
+ };
1844
+ });
1845
+ }
1846
+ var init_KeyManager = __esm({
1847
+ "src/multichain/transports/mwp/KeyManager.ts"() {
1848
+ "use strict";
1849
+ }
1850
+ });
1851
+
1027
1852
  // src/ui/modals/base/utils.ts
1028
1853
  function formatRemainingTime(milliseconds) {
1029
1854
  if (milliseconds <= 0) {
@@ -1285,13 +2110,6 @@ init_domain();
1285
2110
 
1286
2111
  // src/multichain/index.ts
1287
2112
  import { analytics as analytics2 } from "@metamask/analytics";
1288
- import {
1289
- ErrorCode,
1290
- ProtocolError,
1291
- SessionStore as SessionStore2,
1292
- WebSocketTransport
1293
- } from "@metamask/mobile-wallet-protocol-core";
1294
- import { DappClient } from "@metamask/mobile-wallet-protocol-dapp-client";
1295
2113
  import {
1296
2114
  getMultichainClient
1297
2115
  } from "@metamask/multichain-api-client";
@@ -1534,7 +2352,7 @@ withAnalyticsTracking_fn = function(options, execute) {
1534
2352
  if (isRejection) {
1535
2353
  yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRejected_fn).call(this, options);
1536
2354
  } else {
1537
- yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options);
2355
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options, error);
1538
2356
  }
1539
2357
  if (error instanceof RPCInvokeMethodErr) {
1540
2358
  throw error;
@@ -1569,13 +2387,14 @@ trackWalletActionSucceeded_fn = function(options) {
1569
2387
  analytics.track("mmconnect_wallet_action_succeeded", props);
1570
2388
  });
1571
2389
  };
1572
- trackWalletActionFailed_fn = function(options) {
2390
+ trackWalletActionFailed_fn = function(options, error) {
1573
2391
  return __async(this, null, function* () {
1574
2392
  const props = yield getWalletActionAnalyticsProperties(
1575
2393
  this.config,
1576
2394
  this.config.storage,
1577
2395
  options,
1578
- this.transportType
2396
+ this.transportType,
2397
+ extractErrorDiagnostics(error)
1579
2398
  );
1580
2399
  analytics.track("mmconnect_wallet_action_failed", props);
1581
2400
  });
@@ -1858,6 +2677,9 @@ var MultichainApiClientWrapperTransport = class {
1858
2677
  return false;
1859
2678
  }
1860
2679
  }
2680
+ isTransportConnected() {
2681
+ return this.isTransportDefined() && this.metamaskConnectMultichain.transport.isConnected();
2682
+ }
1861
2683
  clearNotificationCallbacks() {
1862
2684
  __privateGet(this, _notificationCallbacks2).clear();
1863
2685
  }
@@ -1879,17 +2701,19 @@ var MultichainApiClientWrapperTransport = class {
1879
2701
  this.notifyCallbacks.bind(this)
1880
2702
  );
1881
2703
  }
2704
+ // Purposely noop, resolves successfully. Actual connection is handled by the underlying client/transport.
1882
2705
  connect() {
1883
2706
  return __async(this, null, function* () {
1884
- console.log("\u{1F4DA} connect");
1885
- yield this.metamaskConnectMultichain.emitSessionChanged();
2707
+ return Promise.resolve();
1886
2708
  });
1887
2709
  }
2710
+ // Purposely noop, resolves successfully. Actual connection is handled by the underlying client/transport.
1888
2711
  disconnect() {
1889
2712
  return __async(this, null, function* () {
1890
2713
  return Promise.resolve();
1891
2714
  });
1892
2715
  }
2716
+ // Purposely hardcoded to true. Actual connection is handled by the underlying client/transport.
1893
2717
  isConnected() {
1894
2718
  return true;
1895
2719
  }
@@ -1912,7 +2736,6 @@ var MultichainApiClientWrapperTransport = class {
1912
2736
  default:
1913
2737
  throw new Error(`Unsupported method: ${requestPayload.method}`);
1914
2738
  }
1915
- throw new Error(`Unknown method: ${requestPayload.method}`);
1916
2739
  });
1917
2740
  }
1918
2741
  onNotification(callback) {
@@ -1942,13 +2765,11 @@ walletCreateSession_fn = function(request) {
1942
2765
  }
1943
2766
  });
1944
2767
  const accounts = [...new Set(scopeAccounts)];
1945
- console.log("\u{1F4DA} SDK connect");
1946
2768
  yield this.metamaskConnectMultichain.connect(
1947
2769
  scopes,
1948
2770
  accounts,
1949
2771
  createSessionParams.sessionProperties
1950
2772
  );
1951
- console.log("\u{1F4DA} SDK connected");
1952
2773
  return this.metamaskConnectMultichain.transport.request({
1953
2774
  method: "wallet_getSession"
1954
2775
  });
@@ -1956,7 +2777,7 @@ walletCreateSession_fn = function(request) {
1956
2777
  };
1957
2778
  walletGetSession_fn = function(request) {
1958
2779
  return __async(this, null, function* () {
1959
- if (!this.isTransportDefined()) {
2780
+ if (!this.isTransportConnected()) {
1960
2781
  return {
1961
2782
  jsonrpc: "2.0",
1962
2783
  id: request.id,
@@ -1973,9 +2794,6 @@ walletGetSession_fn = function(request) {
1973
2794
  walletRevokeSession_fn = function(request) {
1974
2795
  return __async(this, null, function* () {
1975
2796
  var _a2;
1976
- if (!this.isTransportDefined()) {
1977
- return { jsonrpc: "2.0", id: request.id, result: true };
1978
- }
1979
2797
  const revokeSessionParams = request.params;
1980
2798
  const scopes = (_a2 = revokeSessionParams == null ? void 0 : revokeSessionParams.scopes) != null ? _a2 : [];
1981
2799
  try {
@@ -1988,7 +2806,7 @@ walletRevokeSession_fn = function(request) {
1988
2806
  };
1989
2807
  walletInvokeMethod_fn = function(request) {
1990
2808
  return __async(this, null, function* () {
1991
- if (!this.isTransportDefined()) {
2809
+ if (!this.isTransportConnected()) {
1992
2810
  return { error: providerErrors.unauthorized() };
1993
2811
  }
1994
2812
  const result = this.metamaskConnectMultichain.invokeMethod(
@@ -2000,686 +2818,11 @@ walletInvokeMethod_fn = function(request) {
2000
2818
  });
2001
2819
  };
2002
2820
 
2003
- // src/multichain/transports/mwp/index.ts
2004
- init_domain();
2005
- init_utils();
2006
- import { SessionStore } from "@metamask/mobile-wallet-protocol-core";
2007
- import {
2008
- TransportTimeoutError
2009
- } from "@metamask/multichain-api-client";
2010
- import { JsonRpcError, providerErrors as providerErrors2, rpcErrors } from "@metamask/rpc-errors";
2011
-
2012
- // src/multichain/transports/constants.ts
2013
- var MULTICHAIN_PROVIDER_STREAM_NAME = "metamask-multichain-provider";
2014
-
2015
- // src/multichain/transports/mwp/index.ts
2016
- var DEFAULT_REQUEST_TIMEOUT2 = 60 * 1e3;
2017
- var CONNECTION_GRACE_PERIOD = 60 * 1e3;
2018
- var DEFAULT_CONNECTION_TIMEOUT = DEFAULT_REQUEST_TIMEOUT2 + CONNECTION_GRACE_PERIOD;
2019
- var DEFAULT_RESUME_TIMEOUT = 10 * 1e3;
2020
- var SESSION_STORE_KEY = "cache_wallet_getSession";
2021
- var ACCOUNTS_STORE_KEY = "cache_eth_accounts";
2022
- var CHAIN_STORE_KEY = "cache_eth_chainId";
2023
- var PENDING_SESSION_REQUEST_KEY = "pending_session_request";
2024
- var CACHED_METHOD_LIST = [
2025
- "wallet_getSession",
2026
- "wallet_createSession",
2027
- "wallet_sessionChanged"
2028
- ];
2029
- var CACHED_RESET_METHOD_LIST = [
2030
- "wallet_revokeSession",
2031
- "wallet_revokePermissions"
2032
- ];
2033
- var logger = createLogger("metamask-sdk:transport");
2034
- var MWPTransport = class {
2035
- constructor(dappClient, kvstore, options = {
2036
- requestTimeout: DEFAULT_REQUEST_TIMEOUT2,
2037
- connectionTimeout: DEFAULT_CONNECTION_TIMEOUT,
2038
- resumeTimeout: DEFAULT_RESUME_TIMEOUT
2039
- }) {
2040
- this.dappClient = dappClient;
2041
- this.kvstore = kvstore;
2042
- this.options = options;
2043
- this.__pendingRequests = /* @__PURE__ */ new Map();
2044
- this.notificationCallbacks = /* @__PURE__ */ new Set();
2045
- this.dappClient.on("message", this.handleMessage.bind(this));
2046
- this.dappClient.on("session_request", (sessionRequest) => {
2047
- this.currentSessionRequest = sessionRequest;
2048
- this.kvstore.set(PENDING_SESSION_REQUEST_KEY, JSON.stringify(sessionRequest)).catch((err) => {
2049
- logger("Failed to store pending session request", err);
2050
- });
2051
- });
2052
- if (typeof window !== "undefined" && typeof window.addEventListener !== "undefined") {
2053
- this.windowFocusHandler = this.onWindowFocus.bind(this);
2054
- window.addEventListener("focus", this.windowFocusHandler);
2055
- }
2056
- }
2057
- get pendingRequests() {
2058
- return this.__pendingRequests;
2059
- }
2060
- set pendingRequests(pendingRequests) {
2061
- this.__pendingRequests = pendingRequests;
2062
- }
2063
- get sessionRequest() {
2064
- return this.currentSessionRequest;
2065
- }
2066
- /**
2067
- * Returns the stored pending session request from the dappClient session_request event, if any.
2068
- *
2069
- * @returns The stored SessionRequest, or null if none or invalid.
2070
- */
2071
- getStoredPendingSessionRequest() {
2072
- return __async(this, null, function* () {
2073
- try {
2074
- const raw = yield this.kvstore.get(PENDING_SESSION_REQUEST_KEY);
2075
- if (!raw) {
2076
- return null;
2077
- }
2078
- return JSON.parse(raw);
2079
- } catch (e) {
2080
- return null;
2081
- }
2082
- });
2083
- }
2084
- /**
2085
- * Removes the stored pending session request from the KVStore.
2086
- * This is necessary to ensure that ConnectMultichain is able to correctly
2087
- * infer the MWP Transport connection attempt status.
2088
- */
2089
- removeStoredPendingSessionRequest() {
2090
- return __async(this, null, function* () {
2091
- yield this.kvstore.delete(PENDING_SESSION_REQUEST_KEY);
2092
- });
2093
- }
2094
- onWindowFocus() {
2095
- if (!this.isConnected()) {
2096
- this.dappClient.reconnect();
2097
- }
2098
- }
2099
- notifyCallbacks(data) {
2100
- this.notificationCallbacks.forEach((callback) => callback(data));
2101
- }
2102
- rejectRequest(id, error = new Error("Request rejected")) {
2103
- const request = this.pendingRequests.get(id);
2104
- if (request) {
2105
- this.pendingRequests.delete(id);
2106
- clearTimeout(request.timeout);
2107
- request.reject(error);
2108
- }
2109
- }
2110
- parseWalletError(errorPayload) {
2111
- const errorData = errorPayload;
2112
- if (typeof errorData.code === "number" && typeof errorData.message === "string") {
2113
- const { code, message: message2 } = errorData;
2114
- if (code >= 1e3 && code <= 4999) {
2115
- return providerErrors2.custom({ code, message: message2 });
2116
- }
2117
- return new JsonRpcError(code, message2);
2118
- }
2119
- const message = errorPayload instanceof Error ? errorPayload.message : JSON.stringify(errorPayload);
2120
- return rpcErrors.internal({ message });
2121
- }
2122
- handleMessage(message) {
2123
- if (typeof message === "object" && message !== null) {
2124
- if ("data" in message) {
2125
- const messagePayload = message.data;
2126
- if ("id" in messagePayload && typeof messagePayload.id === "string") {
2127
- const request = this.pendingRequests.get(messagePayload.id);
2128
- if (request) {
2129
- clearTimeout(request.timeout);
2130
- if ("error" in messagePayload && messagePayload.error) {
2131
- this.pendingRequests.delete(messagePayload.id);
2132
- request.reject(this.parseWalletError(messagePayload.error));
2133
- return;
2134
- }
2135
- const requestWithName = __spreadProps(__spreadValues({}, messagePayload), {
2136
- method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method
2137
- });
2138
- const notification = __spreadProps(__spreadValues({}, messagePayload), {
2139
- method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method,
2140
- params: requestWithName.result
2141
- });
2142
- this.notifyCallbacks(notification);
2143
- request.resolve(requestWithName);
2144
- this.pendingRequests.delete(messagePayload.id);
2145
- }
2146
- } else {
2147
- if (message.data.method === "metamask_chainChanged") {
2148
- this.kvstore.set(
2149
- CHAIN_STORE_KEY,
2150
- JSON.stringify(
2151
- message.data.params.chainId
2152
- )
2153
- );
2154
- }
2155
- if (message.data.method === "metamask_accountsChanged") {
2156
- this.kvstore.set(
2157
- ACCOUNTS_STORE_KEY,
2158
- JSON.stringify(
2159
- message.data.params
2160
- )
2161
- );
2162
- }
2163
- if (message.data.method === "wallet_sessionChanged") {
2164
- const notification = message.data;
2165
- const response = {
2166
- result: notification.params
2167
- };
2168
- this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
2169
- }
2170
- this.notifyCallbacks(message.data);
2171
- }
2172
- }
2173
- }
2174
- }
2175
- onResumeSuccess(resumeResolve, resumeReject, options) {
2176
- return __async(this, null, function* () {
2177
- var _a2, _b, _c, _d, _e, _f, _g;
2178
- try {
2179
- yield this.waitForWalletSessionIfNotCached();
2180
- const sessionRequest = yield this.request({
2181
- method: "wallet_getSession"
2182
- });
2183
- if (sessionRequest.error) {
2184
- return resumeReject(new Error(sessionRequest.error.message));
2185
- }
2186
- let walletSession = sessionRequest.result;
2187
- if (walletSession && options) {
2188
- const currentScopes = Object.keys(
2189
- (_a2 = walletSession == null ? void 0 : walletSession.sessionScopes) != null ? _a2 : {}
2190
- );
2191
- const proposedScopes = (_b = options == null ? void 0 : options.scopes) != null ? _b : [];
2192
- const proposedCaipAccountIds = (_c = options == null ? void 0 : options.caipAccountIds) != null ? _c : [];
2193
- const hasSameScopesAndAccounts = isSameScopesAndAccounts(
2194
- currentScopes,
2195
- proposedScopes,
2196
- walletSession,
2197
- proposedCaipAccountIds
2198
- );
2199
- if (options.forceRequest || !hasSameScopesAndAccounts) {
2200
- const optionalScopes = addValidAccounts(
2201
- getOptionalScopes((_d = options == null ? void 0 : options.scopes) != null ? _d : []),
2202
- getValidAccounts((_e = options == null ? void 0 : options.caipAccountIds) != null ? _e : [])
2203
- );
2204
- const sessionRequest2 = {
2205
- optionalScopes
2206
- };
2207
- const response = yield this.request({
2208
- method: "wallet_createSession",
2209
- params: sessionRequest2
2210
- });
2211
- if (response.error) {
2212
- return resumeReject(new Error(response.error.message));
2213
- }
2214
- walletSession = response.result;
2215
- }
2216
- } else if (!walletSession) {
2217
- const optionalScopes = addValidAccounts(
2218
- getOptionalScopes((_f = options == null ? void 0 : options.scopes) != null ? _f : []),
2219
- getValidAccounts((_g = options == null ? void 0 : options.caipAccountIds) != null ? _g : [])
2220
- );
2221
- const sessionRequest2 = { optionalScopes };
2222
- const response = yield this.request({
2223
- method: "wallet_createSession",
2224
- params: sessionRequest2
2225
- });
2226
- if (response.error) {
2227
- return resumeReject(new Error(response.error.message));
2228
- }
2229
- walletSession = response.result;
2230
- }
2231
- yield this.removeStoredPendingSessionRequest();
2232
- this.notifyCallbacks({
2233
- method: "wallet_sessionChanged",
2234
- params: walletSession
2235
- });
2236
- return resumeResolve();
2237
- } catch (err) {
2238
- return resumeReject(err);
2239
- }
2240
- });
2241
- }
2242
- init() {
2243
- return __async(this, null, function* () {
2244
- });
2245
- }
2246
- // TODO: Rename this
2247
- sendEip1193Message(payload, options) {
2248
- return __async(this, null, function* () {
2249
- const request = __spreadValues({
2250
- jsonrpc: "2.0",
2251
- id: String(getUniqueRequestId())
2252
- }, payload);
2253
- const cachedWalletSession = yield this.getCachedResponse(request);
2254
- if (cachedWalletSession) {
2255
- this.notifyCallbacks(cachedWalletSession);
2256
- return cachedWalletSession;
2257
- }
2258
- return new Promise((resolve, reject) => {
2259
- var _a2;
2260
- const timeout = setTimeout(() => {
2261
- this.rejectRequest(request.id, new TransportTimeoutError());
2262
- }, (_a2 = options == null ? void 0 : options.timeout) != null ? _a2 : this.options.requestTimeout);
2263
- this.pendingRequests.set(request.id, {
2264
- request,
2265
- method: request.method,
2266
- resolve: (response) => __async(this, null, function* () {
2267
- yield this.storeWalletSession(request, response);
2268
- return resolve(response);
2269
- }),
2270
- reject,
2271
- timeout
2272
- });
2273
- this.dappClient.sendRequest({
2274
- name: "metamask-provider",
2275
- data: request
2276
- }).catch(reject);
2277
- });
2278
- });
2279
- }
2280
- connect(options) {
2281
- return __async(this, null, function* () {
2282
- const { dappClient } = this;
2283
- const session = yield this.getActiveSession();
2284
- if (session) {
2285
- logger("active session found", {
2286
- id: session.id,
2287
- channel: session.channel,
2288
- expiresAt: session.expiresAt
2289
- });
2290
- }
2291
- const storedSessionRequestBeforeConnectionAttempt = yield this.getStoredPendingSessionRequest();
2292
- let timeout;
2293
- let initialConnectionMessageHandler;
2294
- const connectionPromise = new Promise((resolve, reject) => __async(this, null, function* () {
2295
- let connection;
2296
- if (session) {
2297
- connection = new Promise((resumeResolve, resumeReject) => {
2298
- var _a2;
2299
- if (this.dappClient.state === "CONNECTED") {
2300
- this.onResumeSuccess(resumeResolve, resumeReject, options);
2301
- } else {
2302
- this.dappClient.once("connected", () => __async(this, null, function* () {
2303
- this.onResumeSuccess(resumeResolve, resumeReject, options);
2304
- }));
2305
- dappClient.resume((_a2 = session == null ? void 0 : session.id) != null ? _a2 : "");
2306
- }
2307
- });
2308
- } else {
2309
- connection = new Promise(
2310
- (resolveConnection, rejectConnection) => {
2311
- var _a2, _b;
2312
- const optionalScopes = addValidAccounts(
2313
- getOptionalScopes((_a2 = options == null ? void 0 : options.scopes) != null ? _a2 : []),
2314
- getValidAccounts((_b = options == null ? void 0 : options.caipAccountIds) != null ? _b : [])
2315
- );
2316
- const sessionRequest = {
2317
- optionalScopes,
2318
- sessionProperties: options == null ? void 0 : options.sessionProperties
2319
- };
2320
- const request = {
2321
- jsonrpc: "2.0",
2322
- id: String(getUniqueRequestId()),
2323
- method: "wallet_createSession",
2324
- params: sessionRequest
2325
- };
2326
- initialConnectionMessageHandler = (message) => __async(this, null, function* () {
2327
- if (typeof message !== "object" || message === null) {
2328
- return;
2329
- }
2330
- if (!("data" in message)) {
2331
- return;
2332
- }
2333
- const messagePayload = message.data;
2334
- const isMatchingId = messagePayload.id === request.id;
2335
- const isMatchingMethod = messagePayload.method === "wallet_createSession" || messagePayload.method === "wallet_sessionChanged";
2336
- if (!isMatchingId && !isMatchingMethod) {
2337
- return;
2338
- }
2339
- if (messagePayload.error) {
2340
- return rejectConnection(
2341
- this.parseWalletError(messagePayload.error)
2342
- );
2343
- }
2344
- yield this.storeWalletSession(
2345
- request,
2346
- messagePayload
2347
- );
2348
- yield this.removeStoredPendingSessionRequest();
2349
- this.notifyCallbacks(messagePayload);
2350
- return resolveConnection();
2351
- });
2352
- this.dappClient.on("message", initialConnectionMessageHandler);
2353
- dappClient.connect({
2354
- mode: "trusted",
2355
- initialPayload: {
2356
- name: MULTICHAIN_PROVIDER_STREAM_NAME,
2357
- data: request
2358
- }
2359
- }).catch((error) => {
2360
- if (initialConnectionMessageHandler) {
2361
- this.dappClient.off(
2362
- "message",
2363
- initialConnectionMessageHandler
2364
- );
2365
- }
2366
- rejectConnection(error);
2367
- });
2368
- }
2369
- );
2370
- }
2371
- timeout = setTimeout(
2372
- () => {
2373
- reject(new TransportTimeoutError());
2374
- },
2375
- storedSessionRequestBeforeConnectionAttempt ? this.options.resumeTimeout : this.options.connectionTimeout
2376
- );
2377
- connection.then(resolve).catch(reject);
2378
- }));
2379
- return connectionPromise.catch((error) => __async(this, null, function* () {
2380
- yield this.dappClient.disconnect();
2381
- throw error;
2382
- })).finally(() => {
2383
- if (timeout) {
2384
- clearTimeout(timeout);
2385
- }
2386
- if (initialConnectionMessageHandler) {
2387
- this.dappClient.off("message", initialConnectionMessageHandler);
2388
- initialConnectionMessageHandler = void 0;
2389
- }
2390
- this.removeStoredPendingSessionRequest();
2391
- });
2392
- });
2393
- }
2394
- /**
2395
- * Disconnects from the Mobile Wallet Protocol
2396
- *
2397
- * @param [scopes] - The scopes to revoke. If not provided or empty, all scopes will be revoked.
2398
- * @returns Nothing
2399
- */
2400
- disconnect() {
2401
- return __async(this, arguments, function* (scopes = []) {
2402
- var _a2, _b;
2403
- const cachedSession = yield this.getCachedResponse({
2404
- jsonrpc: "2.0",
2405
- id: "0",
2406
- method: "wallet_getSession"
2407
- });
2408
- const cachedSessionScopes = (_b = (_a2 = cachedSession == null ? void 0 : cachedSession.result) == null ? void 0 : _a2.sessionScopes) != null ? _b : {};
2409
- const remainingScopes = scopes.length === 0 ? [] : Object.keys(cachedSessionScopes).filter(
2410
- (scope) => !scopes.includes(scope)
2411
- );
2412
- const newSessionScopes = Object.fromEntries(
2413
- Object.entries(cachedSessionScopes).filter(
2414
- ([key]) => remainingScopes.includes(key)
2415
- )
2416
- );
2417
- this.request({ method: "wallet_revokeSession", params: { scopes } }).catch(
2418
- (err) => {
2419
- console.error("error revoking session", err);
2420
- }
2421
- );
2422
- const remainingScopesIncludeEip155 = remainingScopes.some(
2423
- (scope) => scope.includes("eip155")
2424
- );
2425
- if (!remainingScopesIncludeEip155) {
2426
- this.kvstore.delete(ACCOUNTS_STORE_KEY);
2427
- this.kvstore.delete(CHAIN_STORE_KEY);
2428
- }
2429
- if (remainingScopes.length > 0) {
2430
- this.kvstore.set(
2431
- SESSION_STORE_KEY,
2432
- JSON.stringify({
2433
- result: {
2434
- sessionScopes: newSessionScopes
2435
- }
2436
- })
2437
- );
2438
- } else {
2439
- this.kvstore.delete(SESSION_STORE_KEY);
2440
- if (typeof window !== "undefined" && typeof window.removeEventListener !== "undefined" && this.windowFocusHandler) {
2441
- window.removeEventListener("focus", this.windowFocusHandler);
2442
- this.windowFocusHandler = void 0;
2443
- }
2444
- yield this.dappClient.disconnect();
2445
- }
2446
- this.notifyCallbacks({
2447
- method: "wallet_sessionChanged",
2448
- params: {
2449
- sessionScopes: newSessionScopes
2450
- }
2451
- });
2452
- });
2453
- }
2454
- /**
2455
- * Checks if the transport is connected
2456
- *
2457
- * @returns True if transport is connected, false otherwise
2458
- */
2459
- isConnected() {
2460
- return this.dappClient.state === "CONNECTED";
2461
- }
2462
- /**
2463
- * Attempts to re-establish a connection via DappClient
2464
- *
2465
- * @returns Nothing
2466
- */
2467
- // TODO: We should re-evaluate adding this to the WebSocketTransport layer from `@metamask/mobile-wallet-protocol-core`
2468
- // ticket: https://consensyssoftware.atlassian.net/browse/WAPI-862
2469
- attemptResumeSession() {
2470
- return __async(this, null, function* () {
2471
- try {
2472
- yield this.dappClient.reconnect();
2473
- yield new Promise((resolve, reject) => {
2474
- const timeout = setTimeout(() => {
2475
- reject(new Error("Resume timeout"));
2476
- }, 2e3);
2477
- if (this.isConnected()) {
2478
- clearTimeout(timeout);
2479
- resolve();
2480
- } else {
2481
- this.dappClient.once("connected", () => {
2482
- clearTimeout(timeout);
2483
- resolve();
2484
- });
2485
- }
2486
- });
2487
- } catch (error) {
2488
- return Promise.reject(
2489
- new Error(`Failed to resume session: ${error.message}`)
2490
- );
2491
- }
2492
- });
2493
- }
2494
- getCachedResponse(request) {
2495
- return __async(this, null, function* () {
2496
- var _a2;
2497
- if (request.method === "wallet_getSession") {
2498
- const walletGetSession = yield this.kvstore.get(SESSION_STORE_KEY);
2499
- if (walletGetSession) {
2500
- const walletSession = JSON.parse(walletGetSession);
2501
- return {
2502
- id: request.id,
2503
- jsonrpc: "2.0",
2504
- result: (_a2 = walletSession.params) != null ? _a2 : walletSession.result,
2505
- // "what?... why walletSession.params?.."
2506
- method: request.method
2507
- };
2508
- }
2509
- } else if (request.method === "eth_accounts") {
2510
- const ethAccounts = yield this.kvstore.get(ACCOUNTS_STORE_KEY);
2511
- if (ethAccounts) {
2512
- return {
2513
- id: request.id,
2514
- jsonrpc: "2.0",
2515
- result: JSON.parse(ethAccounts),
2516
- method: request.method
2517
- };
2518
- }
2519
- } else if (request.method === "eth_chainId") {
2520
- const ethChainId = yield this.kvstore.get(CHAIN_STORE_KEY);
2521
- if (ethChainId) {
2522
- return {
2523
- id: request.id,
2524
- jsonrpc: "2.0",
2525
- result: JSON.parse(ethChainId),
2526
- method: request.method
2527
- };
2528
- }
2529
- }
2530
- });
2531
- }
2532
- storeWalletSession(request, response) {
2533
- return __async(this, null, function* () {
2534
- if (response.error) {
2535
- return;
2536
- }
2537
- if (CACHED_METHOD_LIST.includes(request.method)) {
2538
- yield this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
2539
- } else if (request.method === "eth_accounts") {
2540
- yield this.kvstore.set(
2541
- ACCOUNTS_STORE_KEY,
2542
- JSON.stringify(response.result)
2543
- );
2544
- } else if (request.method === "eth_chainId") {
2545
- yield this.kvstore.set(CHAIN_STORE_KEY, JSON.stringify(response.result));
2546
- } else if (CACHED_RESET_METHOD_LIST.includes(request.method)) {
2547
- yield this.kvstore.delete(SESSION_STORE_KEY);
2548
- yield this.kvstore.delete(ACCOUNTS_STORE_KEY);
2549
- yield this.kvstore.delete(CHAIN_STORE_KEY);
2550
- }
2551
- });
2552
- }
2553
- request(payload, options) {
2554
- return __async(this, null, function* () {
2555
- const request = __spreadValues({
2556
- jsonrpc: "2.0",
2557
- id: String(getUniqueRequestId())
2558
- }, payload);
2559
- const cachedWalletSession = yield this.getCachedResponse(request);
2560
- if (cachedWalletSession) {
2561
- this.notifyCallbacks(cachedWalletSession);
2562
- return cachedWalletSession;
2563
- }
2564
- if (!this.isConnected()) {
2565
- yield this.attemptResumeSession();
2566
- }
2567
- return new Promise((resolve, reject) => {
2568
- var _a2;
2569
- const timeout = setTimeout(() => {
2570
- this.rejectRequest(request.id, new TransportTimeoutError());
2571
- }, (_a2 = options == null ? void 0 : options.timeout) != null ? _a2 : this.options.requestTimeout);
2572
- this.pendingRequests.set(request.id, {
2573
- request,
2574
- method: request.method,
2575
- resolve: (response) => __async(this, null, function* () {
2576
- yield this.storeWalletSession(request, response);
2577
- return resolve(response);
2578
- }),
2579
- reject,
2580
- timeout
2581
- });
2582
- this.dappClient.sendRequest({
2583
- name: MULTICHAIN_PROVIDER_STREAM_NAME,
2584
- data: request
2585
- }).catch(reject);
2586
- });
2587
- });
2588
- }
2589
- onNotification(callback) {
2590
- this.notificationCallbacks.add(callback);
2591
- return () => {
2592
- this.notificationCallbacks.delete(callback);
2593
- };
2594
- }
2595
- getActiveSession() {
2596
- return __async(this, null, function* () {
2597
- const { kvstore } = this;
2598
- const sessionStore = yield SessionStore.create(kvstore);
2599
- try {
2600
- const [activeSession] = yield sessionStore.list();
2601
- return activeSession;
2602
- } catch (error) {
2603
- logger("error getting active session", error);
2604
- return void 0;
2605
- }
2606
- });
2607
- }
2608
- // This method checks if an existing CAIP session response is cached or waits for one
2609
- // to be received from the wallet if not cached. This is necessary because there is an edge
2610
- // case during the initial connection flow where after the user has accepted the permission approval
2611
- // and returned back to the dapp from the wallet, the dapp page may have gotten unloaded and refreshed.
2612
- // When it is unloaded and refreshed, it will try to resume the session by making a request for wallet_getSession
2613
- // which should resolve from cache, but because a race condition makes it possible for the response from the wallet
2614
- // for the initial wallet_createSession connection request to not have been handled and cached yet. This results
2615
- // in the wallet_getSession request never resolving unless we wait for it explicitly as done in this method.
2616
- waitForWalletSessionIfNotCached() {
2617
- return __async(this, null, function* () {
2618
- const cachedWalletGetSessionResponse = yield this.kvstore.get(SESSION_STORE_KEY);
2619
- if (cachedWalletGetSessionResponse) {
2620
- return;
2621
- }
2622
- let unsubscribe;
2623
- const responsePromise = new Promise((resolve) => {
2624
- unsubscribe = this.onNotification((message) => {
2625
- if (typeof message === "object" && message !== null) {
2626
- if ("data" in message) {
2627
- const messagePayload = message.data;
2628
- if (messagePayload.method === "wallet_getSession" || messagePayload.method === "wallet_sessionChanged") {
2629
- unsubscribe();
2630
- resolve();
2631
- }
2632
- }
2633
- }
2634
- });
2635
- });
2636
- const timeoutPromise = new Promise((_resolve, reject) => {
2637
- setTimeout(() => {
2638
- unsubscribe();
2639
- this.removeStoredPendingSessionRequest();
2640
- reject(new TransportTimeoutError());
2641
- }, this.options.resumeTimeout);
2642
- });
2643
- return Promise.race([responsePromise, timeoutPromise]);
2644
- });
2645
- }
2646
- };
2647
-
2648
- // src/multichain/transports/mwp/KeyManager.ts
2649
- import { decrypt, encrypt, PrivateKey, PublicKey } from "eciesjs";
2650
- var KeyManager = class {
2651
- generateKeyPair() {
2652
- const privateKey = new PrivateKey();
2653
- return {
2654
- privateKey: new Uint8Array(privateKey.secret),
2655
- publicKey: privateKey.publicKey.toBytes(true)
2656
- };
2657
- }
2658
- encrypt(plaintext, theirPublicKey) {
2659
- return __async(this, null, function* () {
2660
- const plaintextBuffer = Buffer.from(plaintext, "utf8");
2661
- const encryptedBuffer = encrypt(theirPublicKey, plaintextBuffer);
2662
- return encryptedBuffer.toString("base64");
2663
- });
2664
- }
2665
- decrypt(encryptedB64, myPrivateKey) {
2666
- return __async(this, null, function* () {
2667
- const encryptedBuffer = Buffer.from(encryptedB64, "base64");
2668
- const decryptedBuffer = yield decrypt(myPrivateKey, encryptedBuffer);
2669
- return Buffer.from(decryptedBuffer).toString("utf8");
2670
- });
2671
- }
2672
- validatePeerKey(key) {
2673
- PublicKey.fromHex(Buffer.from(key).toString("hex"));
2674
- }
2675
- };
2676
- var keymanager = new KeyManager();
2677
-
2678
2821
  // src/multichain/index.ts
2679
2822
  init_utils();
2680
2823
  var logger2 = createLogger("metamask-sdk:core");
2681
2824
  var SINGLETON_KEY = "__METAMASK_CONNECT_MULTICHAIN_SINGLETON__";
2682
- 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;
2825
+ 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;
2683
2826
  var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends MultichainCore {
2684
2827
  constructor(options) {
2685
2828
  var _a2, _b, _c, _d, _e, _f;
@@ -2697,7 +2840,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2697
2840
  versions: __spreadValues({
2698
2841
  // typeof guard needed: Metro (React Native) bundles TS source directly,
2699
2842
  // bypassing the tsup build that substitutes __PACKAGE_VERSION__.
2700
- "connect-multichain": false ? "unknown" : "0.12.1"
2843
+ "connect-multichain": false ? "unknown" : "0.14.0"
2701
2844
  }, (_f = options.versions) != null ? _f : {})
2702
2845
  });
2703
2846
  super(allOptions);
@@ -2707,6 +2850,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2707
2850
  __privateAdd(this, _transport2);
2708
2851
  __privateAdd(this, _dappClient);
2709
2852
  __privateAdd(this, _beforeUnloadListener);
2853
+ __privateAdd(this, _transportType);
2710
2854
  this._status = "pending";
2711
2855
  __privateAdd(this, _listener);
2712
2856
  __privateAdd(this, _anonId);
@@ -2743,12 +2887,13 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2743
2887
  }
2744
2888
  return __privateGet(this, _dappClient);
2745
2889
  }
2890
+ get transportType() {
2891
+ var _a2;
2892
+ return (_a2 = __privateGet(this, _transportType)) != null ? _a2 : "unknown" /* UNKNOWN */;
2893
+ }
2746
2894
  get storage() {
2747
2895
  return this.options.storage;
2748
2896
  }
2749
- get transportType() {
2750
- return __privateGet(this, _transport2) instanceof MWPTransport ? "mwp" /* MWP */ : "browser" /* Browser */;
2751
- }
2752
2897
  // Creates a singleton instance of MetaMaskConnectMultichain.
2753
2898
  // If the singleton already exists, it merges the incoming options with the
2754
2899
  // existing singleton options for the following keys: `api.supportedNetworks`,
@@ -2802,7 +2947,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2802
2947
  connect(scopes, caipAccountIds, sessionProperties, forceRequest) {
2803
2948
  return __async(this, null, function* () {
2804
2949
  var _a2;
2805
- if (this.status === "connecting" && this.transportType === "mwp" /* MWP */) {
2950
+ if (this.status === "connecting" && __privateGet(this, _transportType) === "mwp" /* MWP */) {
2806
2951
  yield __privateMethod(this, _MetaMaskConnectMultichain_instances, openConnectDeeplinkIfNeeded_fn).call(this);
2807
2952
  throw new Error(
2808
2953
  "Existing connection is pending. Please check your MetaMask Mobile app to continue."
@@ -2851,7 +2996,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2851
2996
  sessionProperties: nonEmptySessionProperties,
2852
2997
  forceRequest
2853
2998
  }).then(() => __async(this, null, function* () {
2854
- if (__privateGet(this, _transport2) instanceof MWPTransport) {
2999
+ if (__privateGet(this, _transportType) === "mwp" /* MWP */) {
2855
3000
  return this.storage.setTransport("mwp" /* MWP */);
2856
3001
  }
2857
3002
  return this.storage.setTransport("browser" /* Browser */);
@@ -2898,12 +3043,13 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2898
3043
  yield (_a2 = __privateGet(this, _transport2)) == null ? void 0 : _a2.disconnect(scopes);
2899
3044
  if (remainingScopes.length === 0) {
2900
3045
  yield this.storage.removeTransport();
2901
- if (this.transportType !== "browser" /* Browser */) {
3046
+ if (__privateGet(this, _transportType) !== "browser" /* Browser */) {
2902
3047
  yield (_b = __privateGet(this, _listener)) == null ? void 0 : _b.call(this);
2903
3048
  (_c = __privateGet(this, _beforeUnloadListener)) == null ? void 0 : _c.call(this);
2904
3049
  __privateSet(this, _listener, void 0);
2905
3050
  __privateSet(this, _beforeUnloadListener, void 0);
2906
3051
  __privateSet(this, _transport2, void 0);
3052
+ __privateSet(this, _transportType, void 0);
2907
3053
  __privateGet(this, _providerTransportWrapper).clearTransportNotificationListener();
2908
3054
  __privateSet(this, _dappClient, void 0);
2909
3055
  }
@@ -2913,13 +3059,14 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2913
3059
  }
2914
3060
  invokeMethod(request) {
2915
3061
  return __async(this, null, function* () {
3062
+ var _a2;
2916
3063
  const { transport, options } = this;
2917
3064
  const rpcClient = new RpcClient(options, __privateGet(this, _sdkInfo));
2918
3065
  const requestRouter = new RequestRouter(
2919
3066
  transport,
2920
3067
  rpcClient,
2921
3068
  options,
2922
- this.transportType
3069
+ (_a2 = __privateGet(this, _transportType)) != null ? _a2 : "unknown" /* UNKNOWN */
2923
3070
  );
2924
3071
  return requestRouter.invokeMethod(request);
2925
3072
  });
@@ -2968,6 +3115,7 @@ _providerTransportWrapper = new WeakMap();
2968
3115
  _transport2 = new WeakMap();
2969
3116
  _dappClient = new WeakMap();
2970
3117
  _beforeUnloadListener = new WeakMap();
3118
+ _transportType = new WeakMap();
2971
3119
  _listener = new WeakMap();
2972
3120
  _anonId = new WeakMap();
2973
3121
  _sdkInfo = new WeakMap();
@@ -3025,6 +3173,7 @@ getStoredTransport_fn = function() {
3025
3173
  if (hasExtensionInstalled) {
3026
3174
  const apiTransport = new DefaultTransport();
3027
3175
  __privateSet(this, _transport2, apiTransport);
3176
+ __privateSet(this, _transportType, "browser" /* Browser */);
3028
3177
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3029
3178
  __privateSet(this, _listener, apiTransport.onNotification(
3030
3179
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
@@ -3034,9 +3183,11 @@ getStoredTransport_fn = function() {
3034
3183
  } else if (transportType === "mwp" /* MWP */) {
3035
3184
  const { adapter: kvstore } = this.options.storage;
3036
3185
  const dappClient = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, createDappClient_fn).call(this);
3037
- const apiTransport = new MWPTransport(dappClient, kvstore);
3186
+ const { MWPTransport: MWPTransport2 } = yield Promise.resolve().then(() => (init_mwp(), mwp_exports));
3187
+ const apiTransport = new MWPTransport2(dappClient, kvstore);
3038
3188
  __privateSet(this, _dappClient, dappClient);
3039
3189
  __privateSet(this, _transport2, apiTransport);
3190
+ __privateSet(this, _transportType, "mwp" /* MWP */);
3040
3191
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3041
3192
  __privateSet(this, _listener, apiTransport.onNotification(
3042
3193
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
@@ -3058,7 +3209,7 @@ setupTransport_fn = function() {
3058
3209
  yield this.transport.connect();
3059
3210
  }
3060
3211
  this.status = "connected";
3061
- if (this.transport instanceof MWPTransport) {
3212
+ if (__privateGet(this, _transportType) === "mwp" /* MWP */) {
3062
3213
  yield this.storage.setTransport("mwp" /* MWP */);
3063
3214
  } else {
3064
3215
  yield this.storage.setTransport("browser" /* Browser */);
@@ -3102,31 +3253,43 @@ init_fn2 = function() {
3102
3253
  };
3103
3254
  createDappClient_fn = function() {
3104
3255
  return __async(this, null, function* () {
3256
+ const [mwpCore, { DappClient: DappClientClass }, { createKeyManager: createKeyManager2 }] = yield Promise.all([
3257
+ import("@metamask/mobile-wallet-protocol-core"),
3258
+ import("@metamask/mobile-wallet-protocol-dapp-client"),
3259
+ Promise.resolve().then(() => (init_KeyManager(), KeyManager_exports))
3260
+ ]);
3261
+ const keymanager = yield createKeyManager2();
3105
3262
  const { adapter: kvstore } = this.options.storage;
3106
- const sessionstore = yield SessionStore2.create(kvstore);
3263
+ const sessionstore = yield mwpCore.SessionStore.create(kvstore);
3107
3264
  const websocket = (
3108
3265
  // eslint-disable-next-line no-negated-condition
3109
3266
  typeof window !== "undefined" ? WebSocket : (yield import("ws")).WebSocket
3110
3267
  );
3111
- const transport = yield WebSocketTransport.create({
3268
+ const transport = yield mwpCore.WebSocketTransport.create({
3112
3269
  url: MWP_RELAY_URL,
3113
3270
  kvstore,
3114
3271
  websocket
3115
3272
  });
3116
- const dappClient = new DappClient({ transport, sessionstore, keymanager });
3273
+ const dappClient = new DappClientClass({
3274
+ transport,
3275
+ sessionstore,
3276
+ keymanager
3277
+ });
3117
3278
  return dappClient;
3118
3279
  });
3119
3280
  };
3120
3281
  setupMWP_fn = function() {
3121
3282
  return __async(this, null, function* () {
3122
- if (__privateGet(this, _transport2) instanceof MWPTransport) {
3283
+ if (__privateGet(this, _transportType) === "mwp" /* MWP */) {
3123
3284
  return;
3124
3285
  }
3125
3286
  const { adapter: kvstore } = this.options.storage;
3126
3287
  const dappClient = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, createDappClient_fn).call(this);
3127
3288
  __privateSet(this, _dappClient, dappClient);
3128
- const apiTransport = new MWPTransport(dappClient, kvstore);
3289
+ const { MWPTransport: MWPTransport2 } = yield Promise.resolve().then(() => (init_mwp(), mwp_exports));
3290
+ const apiTransport = new MWPTransport2(dappClient, kvstore);
3129
3291
  __privateSet(this, _transport2, apiTransport);
3292
+ __privateSet(this, _transportType, "mwp" /* MWP */);
3130
3293
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3131
3294
  __privateSet(this, _listener, this.transport.onNotification(
3132
3295
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
@@ -3185,6 +3348,7 @@ renderInstallModalAsync_fn = function(desktopPreferred, scopes, caipAccountIds,
3185
3348
  this.status = "connected";
3186
3349
  yield this.storage.setTransport("mwp" /* MWP */);
3187
3350
  } catch (error) {
3351
+ const { ProtocolError, ErrorCode } = yield import("@metamask/mobile-wallet-protocol-core");
3188
3352
  if (error instanceof ProtocolError) {
3189
3353
  if (error.code !== ErrorCode.REQUEST_EXPIRED) {
3190
3354
  this.status = "disconnected";
@@ -3254,6 +3418,7 @@ headlessConnect_fn = function(scopes, caipAccountIds, sessionProperties) {
3254
3418
  yield this.storage.setTransport("mwp" /* MWP */);
3255
3419
  resolve();
3256
3420
  })).catch((error) => __async(this, null, function* () {
3421
+ const { ProtocolError } = yield import("@metamask/mobile-wallet-protocol-core");
3257
3422
  if (error instanceof ProtocolError) {
3258
3423
  this.status = "disconnected";
3259
3424
  yield this.storage.removeTransport();
@@ -3269,7 +3434,7 @@ headlessConnect_fn = function(scopes, caipAccountIds, sessionProperties) {
3269
3434
  };
3270
3435
  setupDefaultTransport_fn = function() {
3271
3436
  return __async(this, arguments, function* (options = { persist: true }) {
3272
- if (__privateGet(this, _transport2) instanceof DefaultTransport) {
3437
+ if (__privateGet(this, _transportType) === "browser" /* Browser */) {
3273
3438
  return __privateGet(this, _transport2);
3274
3439
  }
3275
3440
  if (options == null ? void 0 : options.persist) {
@@ -3280,6 +3445,7 @@ setupDefaultTransport_fn = function() {
3280
3445
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
3281
3446
  ));
3282
3447
  __privateSet(this, _transport2, transport);
3448
+ __privateSet(this, _transportType, "browser" /* Browser */);
3283
3449
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3284
3450
  return transport;
3285
3451
  });
@@ -3376,9 +3542,9 @@ handleConnection_fn = function(promise, scopes, transportType) {
3376
3542
  transport_type: transportType
3377
3543
  }));
3378
3544
  } else {
3379
- analytics2.track("mmconnect_connection_failed", __spreadProps(__spreadValues({}, baseProps), {
3545
+ analytics2.track("mmconnect_connection_failed", __spreadValues(__spreadProps(__spreadValues({}, baseProps), {
3380
3546
  transport_type: transportType
3381
- }));
3547
+ }), extractErrorDiagnostics(error)));
3382
3548
  }
3383
3549
  } catch (e) {
3384
3550
  logger2("Error tracking connection failed/rejected event", error);
@@ -3823,6 +3989,7 @@ export {
3823
3989
  StoreAdapter,
3824
3990
  StoreClient,
3825
3991
  TransportType,
3992
+ classifyFailureReason,
3826
3993
  createLogger,
3827
3994
  createMultichainClient,
3828
3995
  enableDebug,