@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
@@ -679,17 +679,94 @@ var init_ui = __esm({
679
679
  });
680
680
 
681
681
  // src/multichain/utils/analytics.ts
682
+ function sanitiseErrorMessage(message) {
683
+ if (!message) {
684
+ return void 0;
685
+ }
686
+ let sanitised = message;
687
+ for (const { pattern, replacement } of SANITISE_PATTERNS) {
688
+ sanitised = sanitised.replace(pattern, replacement);
689
+ }
690
+ if (sanitised.length > ERROR_MESSAGE_SAMPLE_MAX_LENGTH) {
691
+ sanitised = `${sanitised.slice(0, ERROR_MESSAGE_SAMPLE_MAX_LENGTH - 1)}\u2026`;
692
+ }
693
+ return sanitised;
694
+ }
695
+ function getUnwrappedErrorDetails(error) {
696
+ var _a3, _b, _c, _d;
697
+ if (typeof error !== "object" || error === null) {
698
+ return { code: void 0, message: "" };
699
+ }
700
+ if (error instanceof RPCInvokeMethodErr) {
701
+ return {
702
+ code: (_a3 = error.rpcCode) != null ? _a3 : error.code,
703
+ message: (_c = (_b = error.rpcMessage) != null ? _b : error.message) != null ? _c : ""
704
+ };
705
+ }
706
+ const errorObj = error;
707
+ return {
708
+ code: errorObj.code,
709
+ message: (_d = errorObj.message) != null ? _d : ""
710
+ };
711
+ }
682
712
  function isRejectionError(error) {
683
- var _a3, _b;
684
713
  if (typeof error !== "object" || error === null) {
685
714
  return false;
686
715
  }
716
+ const { code, message } = getUnwrappedErrorDetails(error);
717
+ const errorMessage = message.toLowerCase();
718
+ return code === 4001 || errorMessage.includes("reject") || errorMessage.includes("denied") || errorMessage.includes("cancel") || // Narrow "user …" matches — bare "user" is too greedy (catches Account
719
+ // Abstraction errors like "user operation reverted").
720
+ errorMessage.includes("user rejected") || errorMessage.includes("user denied") || errorMessage.includes("user cancelled") || errorMessage.includes("user canceled");
721
+ }
722
+ function classifyFailureReason(error) {
723
+ var _a3, _b;
724
+ if (typeof error !== "object" || error === null) {
725
+ return "unknown";
726
+ }
687
727
  const errorObj = error;
688
- const errorCode = errorObj.code;
689
- const errorMessage = (_b = (_a3 = errorObj.message) == null ? void 0 : _a3.toLowerCase()) != null ? _b : "";
690
- return errorCode === 4001 || // User rejected request (common EIP-1193 code)
691
- errorCode === 4100 || // Unauthorized (common rejection code)
692
- errorMessage.includes("reject") || errorMessage.includes("denied") || errorMessage.includes("cancel") || errorMessage.includes("user");
728
+ const errorName = (_a3 = errorObj.name) != null ? _a3 : "";
729
+ const errorMessageRaw = (_b = errorObj.message) != null ? _b : "";
730
+ const errorMessage = errorMessageRaw.toLowerCase();
731
+ const { code } = getUnwrappedErrorDetails(error);
732
+ if (typeof code === "number") {
733
+ if (code === -32601) {
734
+ return "wallet_method_unsupported";
735
+ }
736
+ if (code === -32602) {
737
+ return "wallet_invalid_params";
738
+ }
739
+ if (code === -32603) {
740
+ return "wallet_internal_error";
741
+ }
742
+ if (code <= -32e3 && code >= -32099) {
743
+ return "wallet_internal_error";
744
+ }
745
+ if (code === 4100) {
746
+ return "wallet_unauthorized";
747
+ }
748
+ if (code === 4200) {
749
+ return "wallet_method_unsupported";
750
+ }
751
+ if (code === 4902) {
752
+ return "unrecognized_chain";
753
+ }
754
+ }
755
+ if (errorName === "TransportTimeoutError" || errorMessageRaw === "Request timeout" || errorMessage.includes("timed out") || errorMessage.includes("timeout")) {
756
+ return "transport_timeout";
757
+ }
758
+ if (errorName === "TransportError" || errorMessage.includes("not connected") || errorMessage.includes("transport disconnect") || errorMessage.includes("connection lost") || errorMessage.includes("socket closed")) {
759
+ return "transport_disconnect";
760
+ }
761
+ return "unknown";
762
+ }
763
+ function extractErrorDiagnostics(error) {
764
+ const failureReason = classifyFailureReason(error);
765
+ const { code, message } = getUnwrappedErrorDetails(error);
766
+ const messageSample = sanitiseErrorMessage(message);
767
+ return __spreadValues(__spreadValues({
768
+ failure_reason: failureReason
769
+ }, typeof code === "number" ? { error_code: code } : {}), messageSample ? { error_message_sample: messageSample } : {});
693
770
  }
694
771
  function getBaseAnalyticsProperties(options, storage) {
695
772
  return __async(this, null, function* () {
@@ -705,26 +782,61 @@ function getBaseAnalyticsProperties(options, storage) {
705
782
  };
706
783
  });
707
784
  }
708
- function getWalletActionAnalyticsProperties(options, storage, invokeOptions, transportType) {
785
+ function getWalletActionAnalyticsProperties(options, storage, invokeOptions, transportType, extra) {
709
786
  return __async(this, null, function* () {
710
787
  var _a3;
711
788
  const dappId = getDappId(options.dapp);
712
789
  const anonId = yield storage.getAnonId();
713
- return {
790
+ return __spreadValues(__spreadValues(__spreadValues({
714
791
  mmconnect_versions: (_a3 = options.versions) != null ? _a3 : {},
715
792
  dapp_id: dappId,
716
793
  method: invokeOptions.request.method,
717
794
  caip_chain_id: invokeOptions.scope,
718
795
  anon_id: anonId,
719
796
  transport_type: transportType
720
- };
797
+ }, (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 } : {});
721
798
  });
722
799
  }
800
+ var ERROR_MESSAGE_SAMPLE_MAX_LENGTH, SANITISE_PATTERNS;
723
801
  var init_analytics = __esm({
724
802
  "src/multichain/utils/analytics.ts"() {
725
803
  "use strict";
726
804
  init_utils2();
727
805
  init_domain();
806
+ ERROR_MESSAGE_SAMPLE_MAX_LENGTH = 200;
807
+ SANITISE_PATTERNS = [
808
+ // EVM-style 20-byte hex addresses (e.g. `0x` + 40 hex chars).
809
+ { pattern: /0x[a-fA-F0-9]{40}/gu, replacement: "<addr>" },
810
+ // Other long hex blobs: tx hashes, signatures, raw byte strings, large
811
+ // hex amounts. 16+ hex chars catches 32-byte hashes/signatures without
812
+ // snagging EVM method selectors (8 chars) or short hex codes.
813
+ { pattern: /(?:0x)?[a-fA-F0-9]{16,}/gu, replacement: "<hex>" },
814
+ // URLs of any scheme up to the first whitespace / quote / closing paren.
815
+ // Catches RPC endpoints, dapp deeplinks, query strings with secrets.
816
+ { pattern: /https?:\/\/[^\s"')]+/gu, replacement: "<url>" },
817
+ // Bech32 addresses: short HRP (1-10 lowercase chars) + `1` separator +
818
+ // ≥38 chars of Bech32 data alphabet `[ac-hj-np-z02-9]` (excludes the
819
+ // look-alike chars `b`, `i`, `o`, `1`). Covers Bitcoin SegWit
820
+ // (`bc1…`/`tb1…`) and Cosmos-SDK chains (`cosmos1…`, `osmo1…`,
821
+ // `juno1…`, `inj1…`, etc.) without enumerating every HRP. Runs before
822
+ // the Base58 pattern below — see header comment for why.
823
+ {
824
+ pattern: /\b[a-z]{1,10}1[ac-hj-np-z02-9]{38,}\b/gu,
825
+ replacement: "<addr>"
826
+ },
827
+ // Base58 tokens (32+ chars, Base58 alphabet `[1-9A-HJ-NP-Za-km-z]`).
828
+ // Covers Solana pubkeys (32-44 chars), Solana tx signatures (~88 chars),
829
+ // and Bitcoin Base58 addresses ≥32 chars. The 32-char floor and `\b`
830
+ // word boundary keep English words and shorter alphanumerics safe.
831
+ {
832
+ pattern: /\b[1-9A-HJ-NP-Za-km-z]{32,}\b/gu,
833
+ replacement: "<addr>"
834
+ },
835
+ // Long decimal numbers — token amounts, gas units, timestamps, lamports.
836
+ // 10+ digits catches typical chain quantities without affecting JSON-RPC
837
+ // codes (-32601, 4001, etc.) or short numeric IDs.
838
+ { pattern: /\d{10,}/gu, replacement: "<num>" }
839
+ ];
728
840
  }
729
841
  });
730
842
 
@@ -1024,6 +1136,719 @@ var init_utils2 = __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_utils2();
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 _a3, _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
+ (_a3 = walletSession == null ? void 0 : walletSession.sessionScopes) != null ? _a3 : {}
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 _a3;
1408
+ const timeout = setTimeout(() => {
1409
+ this.rejectRequest(request.id, new TransportTimeoutError());
1410
+ }, (_a3 = options == null ? void 0 : options.timeout) != null ? _a3 : 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 _a3;
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((_a3 = session == null ? void 0 : session.id) != null ? _a3 : "");
1454
+ }
1455
+ });
1456
+ } else {
1457
+ connection = new Promise(
1458
+ (resolveConnection, rejectConnection) => {
1459
+ var _a3, _b;
1460
+ const optionalScopes = addValidAccounts(
1461
+ getOptionalScopes((_a3 = options == null ? void 0 : options.scopes) != null ? _a3 : []),
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 _a3, _b;
1562
+ const cachedSession = yield this.getCachedResponse({
1563
+ jsonrpc: "2.0",
1564
+ id: "0",
1565
+ method: "wallet_getSession"
1566
+ });
1567
+ const cachedSessionScopes = (_b = (_a3 = cachedSession == null ? void 0 : cachedSession.result) == null ? void 0 : _a3.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 _a3;
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: (_a3 = walletSession.params) != null ? _a3 : 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 _a3;
1728
+ const timeout = setTimeout(() => {
1729
+ this.rejectRequest(request.id, new TransportTimeoutError());
1730
+ }, (_a3 = options == null ? void 0 : options.timeout) != null ? _a3 : 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) {
@@ -1255,13 +2080,6 @@ init_domain();
1255
2080
 
1256
2081
  // src/multichain/index.ts
1257
2082
  import { analytics as analytics2 } from "@metamask/analytics";
1258
- import {
1259
- ErrorCode,
1260
- ProtocolError,
1261
- SessionStore as SessionStore2,
1262
- WebSocketTransport
1263
- } from "@metamask/mobile-wallet-protocol-core";
1264
- import { DappClient } from "@metamask/mobile-wallet-protocol-dapp-client";
1265
2083
  import {
1266
2084
  getMultichainClient
1267
2085
  } from "@metamask/multichain-api-client";
@@ -1504,7 +2322,7 @@ withAnalyticsTracking_fn = function(options, execute) {
1504
2322
  if (isRejection) {
1505
2323
  yield __privateMethod(this, _RequestRouter_instances, trackWalletActionRejected_fn).call(this, options);
1506
2324
  } else {
1507
- yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options);
2325
+ yield __privateMethod(this, _RequestRouter_instances, trackWalletActionFailed_fn).call(this, options, error);
1508
2326
  }
1509
2327
  if (error instanceof RPCInvokeMethodErr) {
1510
2328
  throw error;
@@ -1539,13 +2357,14 @@ trackWalletActionSucceeded_fn = function(options) {
1539
2357
  analytics.track("mmconnect_wallet_action_succeeded", props);
1540
2358
  });
1541
2359
  };
1542
- trackWalletActionFailed_fn = function(options) {
2360
+ trackWalletActionFailed_fn = function(options, error) {
1543
2361
  return __async(this, null, function* () {
1544
2362
  const props = yield getWalletActionAnalyticsProperties(
1545
2363
  this.config,
1546
2364
  this.config.storage,
1547
2365
  options,
1548
- this.transportType
2366
+ this.transportType,
2367
+ extractErrorDiagnostics(error)
1549
2368
  );
1550
2369
  analytics.track("mmconnect_wallet_action_failed", props);
1551
2370
  });
@@ -1828,6 +2647,9 @@ var MultichainApiClientWrapperTransport = class {
1828
2647
  return false;
1829
2648
  }
1830
2649
  }
2650
+ isTransportConnected() {
2651
+ return this.isTransportDefined() && this.metamaskConnectMultichain.transport.isConnected();
2652
+ }
1831
2653
  clearNotificationCallbacks() {
1832
2654
  __privateGet(this, _notificationCallbacks2).clear();
1833
2655
  }
@@ -1849,17 +2671,19 @@ var MultichainApiClientWrapperTransport = class {
1849
2671
  this.notifyCallbacks.bind(this)
1850
2672
  );
1851
2673
  }
2674
+ // Purposely noop, resolves successfully. Actual connection is handled by the underlying client/transport.
1852
2675
  connect() {
1853
2676
  return __async(this, null, function* () {
1854
- console.log("\u{1F4DA} connect");
1855
- yield this.metamaskConnectMultichain.emitSessionChanged();
2677
+ return Promise.resolve();
1856
2678
  });
1857
2679
  }
2680
+ // Purposely noop, resolves successfully. Actual connection is handled by the underlying client/transport.
1858
2681
  disconnect() {
1859
2682
  return __async(this, null, function* () {
1860
2683
  return Promise.resolve();
1861
2684
  });
1862
2685
  }
2686
+ // Purposely hardcoded to true. Actual connection is handled by the underlying client/transport.
1863
2687
  isConnected() {
1864
2688
  return true;
1865
2689
  }
@@ -1882,7 +2706,6 @@ var MultichainApiClientWrapperTransport = class {
1882
2706
  default:
1883
2707
  throw new Error(`Unsupported method: ${requestPayload.method}`);
1884
2708
  }
1885
- throw new Error(`Unknown method: ${requestPayload.method}`);
1886
2709
  });
1887
2710
  }
1888
2711
  onNotification(callback) {
@@ -1912,13 +2735,11 @@ walletCreateSession_fn = function(request) {
1912
2735
  }
1913
2736
  });
1914
2737
  const accounts = [...new Set(scopeAccounts)];
1915
- console.log("\u{1F4DA} SDK connect");
1916
2738
  yield this.metamaskConnectMultichain.connect(
1917
2739
  scopes,
1918
2740
  accounts,
1919
2741
  createSessionParams.sessionProperties
1920
2742
  );
1921
- console.log("\u{1F4DA} SDK connected");
1922
2743
  return this.metamaskConnectMultichain.transport.request({
1923
2744
  method: "wallet_getSession"
1924
2745
  });
@@ -1926,7 +2747,7 @@ walletCreateSession_fn = function(request) {
1926
2747
  };
1927
2748
  walletGetSession_fn = function(request) {
1928
2749
  return __async(this, null, function* () {
1929
- if (!this.isTransportDefined()) {
2750
+ if (!this.isTransportConnected()) {
1930
2751
  return {
1931
2752
  jsonrpc: "2.0",
1932
2753
  id: request.id,
@@ -1943,9 +2764,6 @@ walletGetSession_fn = function(request) {
1943
2764
  walletRevokeSession_fn = function(request) {
1944
2765
  return __async(this, null, function* () {
1945
2766
  var _a3;
1946
- if (!this.isTransportDefined()) {
1947
- return { jsonrpc: "2.0", id: request.id, result: true };
1948
- }
1949
2767
  const revokeSessionParams = request.params;
1950
2768
  const scopes = (_a3 = revokeSessionParams == null ? void 0 : revokeSessionParams.scopes) != null ? _a3 : [];
1951
2769
  try {
@@ -1958,7 +2776,7 @@ walletRevokeSession_fn = function(request) {
1958
2776
  };
1959
2777
  walletInvokeMethod_fn = function(request) {
1960
2778
  return __async(this, null, function* () {
1961
- if (!this.isTransportDefined()) {
2779
+ if (!this.isTransportConnected()) {
1962
2780
  return { error: providerErrors.unauthorized() };
1963
2781
  }
1964
2782
  const result = this.metamaskConnectMultichain.invokeMethod(
@@ -1970,686 +2788,11 @@ walletInvokeMethod_fn = function(request) {
1970
2788
  });
1971
2789
  };
1972
2790
 
1973
- // src/multichain/transports/mwp/index.ts
1974
- init_domain();
1975
- init_utils2();
1976
- import { SessionStore } from "@metamask/mobile-wallet-protocol-core";
1977
- import {
1978
- TransportTimeoutError
1979
- } from "@metamask/multichain-api-client";
1980
- import { JsonRpcError, providerErrors as providerErrors2, rpcErrors } from "@metamask/rpc-errors";
1981
-
1982
- // src/multichain/transports/constants.ts
1983
- var MULTICHAIN_PROVIDER_STREAM_NAME = "metamask-multichain-provider";
1984
-
1985
- // src/multichain/transports/mwp/index.ts
1986
- var DEFAULT_REQUEST_TIMEOUT2 = 60 * 1e3;
1987
- var CONNECTION_GRACE_PERIOD = 60 * 1e3;
1988
- var DEFAULT_CONNECTION_TIMEOUT = DEFAULT_REQUEST_TIMEOUT2 + CONNECTION_GRACE_PERIOD;
1989
- var DEFAULT_RESUME_TIMEOUT = 10 * 1e3;
1990
- var SESSION_STORE_KEY = "cache_wallet_getSession";
1991
- var ACCOUNTS_STORE_KEY = "cache_eth_accounts";
1992
- var CHAIN_STORE_KEY = "cache_eth_chainId";
1993
- var PENDING_SESSION_REQUEST_KEY = "pending_session_request";
1994
- var CACHED_METHOD_LIST = [
1995
- "wallet_getSession",
1996
- "wallet_createSession",
1997
- "wallet_sessionChanged"
1998
- ];
1999
- var CACHED_RESET_METHOD_LIST = [
2000
- "wallet_revokeSession",
2001
- "wallet_revokePermissions"
2002
- ];
2003
- var logger = createLogger("metamask-sdk:transport");
2004
- var MWPTransport = class {
2005
- constructor(dappClient, kvstore, options = {
2006
- requestTimeout: DEFAULT_REQUEST_TIMEOUT2,
2007
- connectionTimeout: DEFAULT_CONNECTION_TIMEOUT,
2008
- resumeTimeout: DEFAULT_RESUME_TIMEOUT
2009
- }) {
2010
- this.dappClient = dappClient;
2011
- this.kvstore = kvstore;
2012
- this.options = options;
2013
- this.__pendingRequests = /* @__PURE__ */ new Map();
2014
- this.notificationCallbacks = /* @__PURE__ */ new Set();
2015
- this.dappClient.on("message", this.handleMessage.bind(this));
2016
- this.dappClient.on("session_request", (sessionRequest) => {
2017
- this.currentSessionRequest = sessionRequest;
2018
- this.kvstore.set(PENDING_SESSION_REQUEST_KEY, JSON.stringify(sessionRequest)).catch((err) => {
2019
- logger("Failed to store pending session request", err);
2020
- });
2021
- });
2022
- if (typeof window !== "undefined" && typeof window.addEventListener !== "undefined") {
2023
- this.windowFocusHandler = this.onWindowFocus.bind(this);
2024
- window.addEventListener("focus", this.windowFocusHandler);
2025
- }
2026
- }
2027
- get pendingRequests() {
2028
- return this.__pendingRequests;
2029
- }
2030
- set pendingRequests(pendingRequests) {
2031
- this.__pendingRequests = pendingRequests;
2032
- }
2033
- get sessionRequest() {
2034
- return this.currentSessionRequest;
2035
- }
2036
- /**
2037
- * Returns the stored pending session request from the dappClient session_request event, if any.
2038
- *
2039
- * @returns The stored SessionRequest, or null if none or invalid.
2040
- */
2041
- getStoredPendingSessionRequest() {
2042
- return __async(this, null, function* () {
2043
- try {
2044
- const raw = yield this.kvstore.get(PENDING_SESSION_REQUEST_KEY);
2045
- if (!raw) {
2046
- return null;
2047
- }
2048
- return JSON.parse(raw);
2049
- } catch (e) {
2050
- return null;
2051
- }
2052
- });
2053
- }
2054
- /**
2055
- * Removes the stored pending session request from the KVStore.
2056
- * This is necessary to ensure that ConnectMultichain is able to correctly
2057
- * infer the MWP Transport connection attempt status.
2058
- */
2059
- removeStoredPendingSessionRequest() {
2060
- return __async(this, null, function* () {
2061
- yield this.kvstore.delete(PENDING_SESSION_REQUEST_KEY);
2062
- });
2063
- }
2064
- onWindowFocus() {
2065
- if (!this.isConnected()) {
2066
- this.dappClient.reconnect();
2067
- }
2068
- }
2069
- notifyCallbacks(data) {
2070
- this.notificationCallbacks.forEach((callback) => callback(data));
2071
- }
2072
- rejectRequest(id, error = new Error("Request rejected")) {
2073
- const request = this.pendingRequests.get(id);
2074
- if (request) {
2075
- this.pendingRequests.delete(id);
2076
- clearTimeout(request.timeout);
2077
- request.reject(error);
2078
- }
2079
- }
2080
- parseWalletError(errorPayload) {
2081
- const errorData = errorPayload;
2082
- if (typeof errorData.code === "number" && typeof errorData.message === "string") {
2083
- const { code, message: message2 } = errorData;
2084
- if (code >= 1e3 && code <= 4999) {
2085
- return providerErrors2.custom({ code, message: message2 });
2086
- }
2087
- return new JsonRpcError(code, message2);
2088
- }
2089
- const message = errorPayload instanceof Error ? errorPayload.message : JSON.stringify(errorPayload);
2090
- return rpcErrors.internal({ message });
2091
- }
2092
- handleMessage(message) {
2093
- if (typeof message === "object" && message !== null) {
2094
- if ("data" in message) {
2095
- const messagePayload = message.data;
2096
- if ("id" in messagePayload && typeof messagePayload.id === "string") {
2097
- const request = this.pendingRequests.get(messagePayload.id);
2098
- if (request) {
2099
- clearTimeout(request.timeout);
2100
- if ("error" in messagePayload && messagePayload.error) {
2101
- this.pendingRequests.delete(messagePayload.id);
2102
- request.reject(this.parseWalletError(messagePayload.error));
2103
- return;
2104
- }
2105
- const requestWithName = __spreadProps(__spreadValues({}, messagePayload), {
2106
- method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method
2107
- });
2108
- const notification = __spreadProps(__spreadValues({}, messagePayload), {
2109
- method: request.method === "wallet_getSession" || request.method === "wallet_createSession" ? "wallet_sessionChanged" : request.method,
2110
- params: requestWithName.result
2111
- });
2112
- this.notifyCallbacks(notification);
2113
- request.resolve(requestWithName);
2114
- this.pendingRequests.delete(messagePayload.id);
2115
- }
2116
- } else {
2117
- if (message.data.method === "metamask_chainChanged") {
2118
- this.kvstore.set(
2119
- CHAIN_STORE_KEY,
2120
- JSON.stringify(
2121
- message.data.params.chainId
2122
- )
2123
- );
2124
- }
2125
- if (message.data.method === "metamask_accountsChanged") {
2126
- this.kvstore.set(
2127
- ACCOUNTS_STORE_KEY,
2128
- JSON.stringify(
2129
- message.data.params
2130
- )
2131
- );
2132
- }
2133
- if (message.data.method === "wallet_sessionChanged") {
2134
- const notification = message.data;
2135
- const response = {
2136
- result: notification.params
2137
- };
2138
- this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
2139
- }
2140
- this.notifyCallbacks(message.data);
2141
- }
2142
- }
2143
- }
2144
- }
2145
- onResumeSuccess(resumeResolve, resumeReject, options) {
2146
- return __async(this, null, function* () {
2147
- var _a3, _b, _c, _d, _e, _f, _g;
2148
- try {
2149
- yield this.waitForWalletSessionIfNotCached();
2150
- const sessionRequest = yield this.request({
2151
- method: "wallet_getSession"
2152
- });
2153
- if (sessionRequest.error) {
2154
- return resumeReject(new Error(sessionRequest.error.message));
2155
- }
2156
- let walletSession = sessionRequest.result;
2157
- if (walletSession && options) {
2158
- const currentScopes = Object.keys(
2159
- (_a3 = walletSession == null ? void 0 : walletSession.sessionScopes) != null ? _a3 : {}
2160
- );
2161
- const proposedScopes = (_b = options == null ? void 0 : options.scopes) != null ? _b : [];
2162
- const proposedCaipAccountIds = (_c = options == null ? void 0 : options.caipAccountIds) != null ? _c : [];
2163
- const hasSameScopesAndAccounts = isSameScopesAndAccounts(
2164
- currentScopes,
2165
- proposedScopes,
2166
- walletSession,
2167
- proposedCaipAccountIds
2168
- );
2169
- if (options.forceRequest || !hasSameScopesAndAccounts) {
2170
- const optionalScopes = addValidAccounts(
2171
- getOptionalScopes((_d = options == null ? void 0 : options.scopes) != null ? _d : []),
2172
- getValidAccounts((_e = options == null ? void 0 : options.caipAccountIds) != null ? _e : [])
2173
- );
2174
- const sessionRequest2 = {
2175
- optionalScopes
2176
- };
2177
- const response = yield this.request({
2178
- method: "wallet_createSession",
2179
- params: sessionRequest2
2180
- });
2181
- if (response.error) {
2182
- return resumeReject(new Error(response.error.message));
2183
- }
2184
- walletSession = response.result;
2185
- }
2186
- } else if (!walletSession) {
2187
- const optionalScopes = addValidAccounts(
2188
- getOptionalScopes((_f = options == null ? void 0 : options.scopes) != null ? _f : []),
2189
- getValidAccounts((_g = options == null ? void 0 : options.caipAccountIds) != null ? _g : [])
2190
- );
2191
- const sessionRequest2 = { optionalScopes };
2192
- const response = yield this.request({
2193
- method: "wallet_createSession",
2194
- params: sessionRequest2
2195
- });
2196
- if (response.error) {
2197
- return resumeReject(new Error(response.error.message));
2198
- }
2199
- walletSession = response.result;
2200
- }
2201
- yield this.removeStoredPendingSessionRequest();
2202
- this.notifyCallbacks({
2203
- method: "wallet_sessionChanged",
2204
- params: walletSession
2205
- });
2206
- return resumeResolve();
2207
- } catch (err) {
2208
- return resumeReject(err);
2209
- }
2210
- });
2211
- }
2212
- init() {
2213
- return __async(this, null, function* () {
2214
- });
2215
- }
2216
- // TODO: Rename this
2217
- sendEip1193Message(payload, options) {
2218
- return __async(this, null, function* () {
2219
- const request = __spreadValues({
2220
- jsonrpc: "2.0",
2221
- id: String(getUniqueRequestId())
2222
- }, payload);
2223
- const cachedWalletSession = yield this.getCachedResponse(request);
2224
- if (cachedWalletSession) {
2225
- this.notifyCallbacks(cachedWalletSession);
2226
- return cachedWalletSession;
2227
- }
2228
- return new Promise((resolve, reject) => {
2229
- var _a3;
2230
- const timeout = setTimeout(() => {
2231
- this.rejectRequest(request.id, new TransportTimeoutError());
2232
- }, (_a3 = options == null ? void 0 : options.timeout) != null ? _a3 : this.options.requestTimeout);
2233
- this.pendingRequests.set(request.id, {
2234
- request,
2235
- method: request.method,
2236
- resolve: (response) => __async(this, null, function* () {
2237
- yield this.storeWalletSession(request, response);
2238
- return resolve(response);
2239
- }),
2240
- reject,
2241
- timeout
2242
- });
2243
- this.dappClient.sendRequest({
2244
- name: "metamask-provider",
2245
- data: request
2246
- }).catch(reject);
2247
- });
2248
- });
2249
- }
2250
- connect(options) {
2251
- return __async(this, null, function* () {
2252
- const { dappClient } = this;
2253
- const session = yield this.getActiveSession();
2254
- if (session) {
2255
- logger("active session found", {
2256
- id: session.id,
2257
- channel: session.channel,
2258
- expiresAt: session.expiresAt
2259
- });
2260
- }
2261
- const storedSessionRequestBeforeConnectionAttempt = yield this.getStoredPendingSessionRequest();
2262
- let timeout;
2263
- let initialConnectionMessageHandler;
2264
- const connectionPromise = new Promise((resolve, reject) => __async(this, null, function* () {
2265
- let connection;
2266
- if (session) {
2267
- connection = new Promise((resumeResolve, resumeReject) => {
2268
- var _a3;
2269
- if (this.dappClient.state === "CONNECTED") {
2270
- this.onResumeSuccess(resumeResolve, resumeReject, options);
2271
- } else {
2272
- this.dappClient.once("connected", () => __async(this, null, function* () {
2273
- this.onResumeSuccess(resumeResolve, resumeReject, options);
2274
- }));
2275
- dappClient.resume((_a3 = session == null ? void 0 : session.id) != null ? _a3 : "");
2276
- }
2277
- });
2278
- } else {
2279
- connection = new Promise(
2280
- (resolveConnection, rejectConnection) => {
2281
- var _a3, _b;
2282
- const optionalScopes = addValidAccounts(
2283
- getOptionalScopes((_a3 = options == null ? void 0 : options.scopes) != null ? _a3 : []),
2284
- getValidAccounts((_b = options == null ? void 0 : options.caipAccountIds) != null ? _b : [])
2285
- );
2286
- const sessionRequest = {
2287
- optionalScopes,
2288
- sessionProperties: options == null ? void 0 : options.sessionProperties
2289
- };
2290
- const request = {
2291
- jsonrpc: "2.0",
2292
- id: String(getUniqueRequestId()),
2293
- method: "wallet_createSession",
2294
- params: sessionRequest
2295
- };
2296
- initialConnectionMessageHandler = (message) => __async(this, null, function* () {
2297
- if (typeof message !== "object" || message === null) {
2298
- return;
2299
- }
2300
- if (!("data" in message)) {
2301
- return;
2302
- }
2303
- const messagePayload = message.data;
2304
- const isMatchingId = messagePayload.id === request.id;
2305
- const isMatchingMethod = messagePayload.method === "wallet_createSession" || messagePayload.method === "wallet_sessionChanged";
2306
- if (!isMatchingId && !isMatchingMethod) {
2307
- return;
2308
- }
2309
- if (messagePayload.error) {
2310
- return rejectConnection(
2311
- this.parseWalletError(messagePayload.error)
2312
- );
2313
- }
2314
- yield this.storeWalletSession(
2315
- request,
2316
- messagePayload
2317
- );
2318
- yield this.removeStoredPendingSessionRequest();
2319
- this.notifyCallbacks(messagePayload);
2320
- return resolveConnection();
2321
- });
2322
- this.dappClient.on("message", initialConnectionMessageHandler);
2323
- dappClient.connect({
2324
- mode: "trusted",
2325
- initialPayload: {
2326
- name: MULTICHAIN_PROVIDER_STREAM_NAME,
2327
- data: request
2328
- }
2329
- }).catch((error) => {
2330
- if (initialConnectionMessageHandler) {
2331
- this.dappClient.off(
2332
- "message",
2333
- initialConnectionMessageHandler
2334
- );
2335
- }
2336
- rejectConnection(error);
2337
- });
2338
- }
2339
- );
2340
- }
2341
- timeout = setTimeout(
2342
- () => {
2343
- reject(new TransportTimeoutError());
2344
- },
2345
- storedSessionRequestBeforeConnectionAttempt ? this.options.resumeTimeout : this.options.connectionTimeout
2346
- );
2347
- connection.then(resolve).catch(reject);
2348
- }));
2349
- return connectionPromise.catch((error) => __async(this, null, function* () {
2350
- yield this.dappClient.disconnect();
2351
- throw error;
2352
- })).finally(() => {
2353
- if (timeout) {
2354
- clearTimeout(timeout);
2355
- }
2356
- if (initialConnectionMessageHandler) {
2357
- this.dappClient.off("message", initialConnectionMessageHandler);
2358
- initialConnectionMessageHandler = void 0;
2359
- }
2360
- this.removeStoredPendingSessionRequest();
2361
- });
2362
- });
2363
- }
2364
- /**
2365
- * Disconnects from the Mobile Wallet Protocol
2366
- *
2367
- * @param [scopes] - The scopes to revoke. If not provided or empty, all scopes will be revoked.
2368
- * @returns Nothing
2369
- */
2370
- disconnect() {
2371
- return __async(this, arguments, function* (scopes = []) {
2372
- var _a3, _b;
2373
- const cachedSession = yield this.getCachedResponse({
2374
- jsonrpc: "2.0",
2375
- id: "0",
2376
- method: "wallet_getSession"
2377
- });
2378
- const cachedSessionScopes = (_b = (_a3 = cachedSession == null ? void 0 : cachedSession.result) == null ? void 0 : _a3.sessionScopes) != null ? _b : {};
2379
- const remainingScopes = scopes.length === 0 ? [] : Object.keys(cachedSessionScopes).filter(
2380
- (scope) => !scopes.includes(scope)
2381
- );
2382
- const newSessionScopes = Object.fromEntries(
2383
- Object.entries(cachedSessionScopes).filter(
2384
- ([key]) => remainingScopes.includes(key)
2385
- )
2386
- );
2387
- this.request({ method: "wallet_revokeSession", params: { scopes } }).catch(
2388
- (err) => {
2389
- console.error("error revoking session", err);
2390
- }
2391
- );
2392
- const remainingScopesIncludeEip155 = remainingScopes.some(
2393
- (scope) => scope.includes("eip155")
2394
- );
2395
- if (!remainingScopesIncludeEip155) {
2396
- this.kvstore.delete(ACCOUNTS_STORE_KEY);
2397
- this.kvstore.delete(CHAIN_STORE_KEY);
2398
- }
2399
- if (remainingScopes.length > 0) {
2400
- this.kvstore.set(
2401
- SESSION_STORE_KEY,
2402
- JSON.stringify({
2403
- result: {
2404
- sessionScopes: newSessionScopes
2405
- }
2406
- })
2407
- );
2408
- } else {
2409
- this.kvstore.delete(SESSION_STORE_KEY);
2410
- if (typeof window !== "undefined" && typeof window.removeEventListener !== "undefined" && this.windowFocusHandler) {
2411
- window.removeEventListener("focus", this.windowFocusHandler);
2412
- this.windowFocusHandler = void 0;
2413
- }
2414
- yield this.dappClient.disconnect();
2415
- }
2416
- this.notifyCallbacks({
2417
- method: "wallet_sessionChanged",
2418
- params: {
2419
- sessionScopes: newSessionScopes
2420
- }
2421
- });
2422
- });
2423
- }
2424
- /**
2425
- * Checks if the transport is connected
2426
- *
2427
- * @returns True if transport is connected, false otherwise
2428
- */
2429
- isConnected() {
2430
- return this.dappClient.state === "CONNECTED";
2431
- }
2432
- /**
2433
- * Attempts to re-establish a connection via DappClient
2434
- *
2435
- * @returns Nothing
2436
- */
2437
- // TODO: We should re-evaluate adding this to the WebSocketTransport layer from `@metamask/mobile-wallet-protocol-core`
2438
- // ticket: https://consensyssoftware.atlassian.net/browse/WAPI-862
2439
- attemptResumeSession() {
2440
- return __async(this, null, function* () {
2441
- try {
2442
- yield this.dappClient.reconnect();
2443
- yield new Promise((resolve, reject) => {
2444
- const timeout = setTimeout(() => {
2445
- reject(new Error("Resume timeout"));
2446
- }, 2e3);
2447
- if (this.isConnected()) {
2448
- clearTimeout(timeout);
2449
- resolve();
2450
- } else {
2451
- this.dappClient.once("connected", () => {
2452
- clearTimeout(timeout);
2453
- resolve();
2454
- });
2455
- }
2456
- });
2457
- } catch (error) {
2458
- return Promise.reject(
2459
- new Error(`Failed to resume session: ${error.message}`)
2460
- );
2461
- }
2462
- });
2463
- }
2464
- getCachedResponse(request) {
2465
- return __async(this, null, function* () {
2466
- var _a3;
2467
- if (request.method === "wallet_getSession") {
2468
- const walletGetSession = yield this.kvstore.get(SESSION_STORE_KEY);
2469
- if (walletGetSession) {
2470
- const walletSession = JSON.parse(walletGetSession);
2471
- return {
2472
- id: request.id,
2473
- jsonrpc: "2.0",
2474
- result: (_a3 = walletSession.params) != null ? _a3 : walletSession.result,
2475
- // "what?... why walletSession.params?.."
2476
- method: request.method
2477
- };
2478
- }
2479
- } else if (request.method === "eth_accounts") {
2480
- const ethAccounts = yield this.kvstore.get(ACCOUNTS_STORE_KEY);
2481
- if (ethAccounts) {
2482
- return {
2483
- id: request.id,
2484
- jsonrpc: "2.0",
2485
- result: JSON.parse(ethAccounts),
2486
- method: request.method
2487
- };
2488
- }
2489
- } else if (request.method === "eth_chainId") {
2490
- const ethChainId = yield this.kvstore.get(CHAIN_STORE_KEY);
2491
- if (ethChainId) {
2492
- return {
2493
- id: request.id,
2494
- jsonrpc: "2.0",
2495
- result: JSON.parse(ethChainId),
2496
- method: request.method
2497
- };
2498
- }
2499
- }
2500
- });
2501
- }
2502
- storeWalletSession(request, response) {
2503
- return __async(this, null, function* () {
2504
- if (response.error) {
2505
- return;
2506
- }
2507
- if (CACHED_METHOD_LIST.includes(request.method)) {
2508
- yield this.kvstore.set(SESSION_STORE_KEY, JSON.stringify(response));
2509
- } else if (request.method === "eth_accounts") {
2510
- yield this.kvstore.set(
2511
- ACCOUNTS_STORE_KEY,
2512
- JSON.stringify(response.result)
2513
- );
2514
- } else if (request.method === "eth_chainId") {
2515
- yield this.kvstore.set(CHAIN_STORE_KEY, JSON.stringify(response.result));
2516
- } else if (CACHED_RESET_METHOD_LIST.includes(request.method)) {
2517
- yield this.kvstore.delete(SESSION_STORE_KEY);
2518
- yield this.kvstore.delete(ACCOUNTS_STORE_KEY);
2519
- yield this.kvstore.delete(CHAIN_STORE_KEY);
2520
- }
2521
- });
2522
- }
2523
- request(payload, options) {
2524
- return __async(this, null, function* () {
2525
- const request = __spreadValues({
2526
- jsonrpc: "2.0",
2527
- id: String(getUniqueRequestId())
2528
- }, payload);
2529
- const cachedWalletSession = yield this.getCachedResponse(request);
2530
- if (cachedWalletSession) {
2531
- this.notifyCallbacks(cachedWalletSession);
2532
- return cachedWalletSession;
2533
- }
2534
- if (!this.isConnected()) {
2535
- yield this.attemptResumeSession();
2536
- }
2537
- return new Promise((resolve, reject) => {
2538
- var _a3;
2539
- const timeout = setTimeout(() => {
2540
- this.rejectRequest(request.id, new TransportTimeoutError());
2541
- }, (_a3 = options == null ? void 0 : options.timeout) != null ? _a3 : this.options.requestTimeout);
2542
- this.pendingRequests.set(request.id, {
2543
- request,
2544
- method: request.method,
2545
- resolve: (response) => __async(this, null, function* () {
2546
- yield this.storeWalletSession(request, response);
2547
- return resolve(response);
2548
- }),
2549
- reject,
2550
- timeout
2551
- });
2552
- this.dappClient.sendRequest({
2553
- name: MULTICHAIN_PROVIDER_STREAM_NAME,
2554
- data: request
2555
- }).catch(reject);
2556
- });
2557
- });
2558
- }
2559
- onNotification(callback) {
2560
- this.notificationCallbacks.add(callback);
2561
- return () => {
2562
- this.notificationCallbacks.delete(callback);
2563
- };
2564
- }
2565
- getActiveSession() {
2566
- return __async(this, null, function* () {
2567
- const { kvstore } = this;
2568
- const sessionStore = yield SessionStore.create(kvstore);
2569
- try {
2570
- const [activeSession] = yield sessionStore.list();
2571
- return activeSession;
2572
- } catch (error) {
2573
- logger("error getting active session", error);
2574
- return void 0;
2575
- }
2576
- });
2577
- }
2578
- // This method checks if an existing CAIP session response is cached or waits for one
2579
- // to be received from the wallet if not cached. This is necessary because there is an edge
2580
- // case during the initial connection flow where after the user has accepted the permission approval
2581
- // and returned back to the dapp from the wallet, the dapp page may have gotten unloaded and refreshed.
2582
- // When it is unloaded and refreshed, it will try to resume the session by making a request for wallet_getSession
2583
- // which should resolve from cache, but because a race condition makes it possible for the response from the wallet
2584
- // for the initial wallet_createSession connection request to not have been handled and cached yet. This results
2585
- // in the wallet_getSession request never resolving unless we wait for it explicitly as done in this method.
2586
- waitForWalletSessionIfNotCached() {
2587
- return __async(this, null, function* () {
2588
- const cachedWalletGetSessionResponse = yield this.kvstore.get(SESSION_STORE_KEY);
2589
- if (cachedWalletGetSessionResponse) {
2590
- return;
2591
- }
2592
- let unsubscribe;
2593
- const responsePromise = new Promise((resolve) => {
2594
- unsubscribe = this.onNotification((message) => {
2595
- if (typeof message === "object" && message !== null) {
2596
- if ("data" in message) {
2597
- const messagePayload = message.data;
2598
- if (messagePayload.method === "wallet_getSession" || messagePayload.method === "wallet_sessionChanged") {
2599
- unsubscribe();
2600
- resolve();
2601
- }
2602
- }
2603
- }
2604
- });
2605
- });
2606
- const timeoutPromise = new Promise((_resolve, reject) => {
2607
- setTimeout(() => {
2608
- unsubscribe();
2609
- this.removeStoredPendingSessionRequest();
2610
- reject(new TransportTimeoutError());
2611
- }, this.options.resumeTimeout);
2612
- });
2613
- return Promise.race([responsePromise, timeoutPromise]);
2614
- });
2615
- }
2616
- };
2617
-
2618
- // src/multichain/transports/mwp/KeyManager.ts
2619
- import { decrypt, encrypt, PrivateKey, PublicKey } from "eciesjs";
2620
- var KeyManager = class {
2621
- generateKeyPair() {
2622
- const privateKey = new PrivateKey();
2623
- return {
2624
- privateKey: new Uint8Array(privateKey.secret),
2625
- publicKey: privateKey.publicKey.toBytes(true)
2626
- };
2627
- }
2628
- encrypt(plaintext, theirPublicKey) {
2629
- return __async(this, null, function* () {
2630
- const plaintextBuffer = Buffer.from(plaintext, "utf8");
2631
- const encryptedBuffer = encrypt(theirPublicKey, plaintextBuffer);
2632
- return encryptedBuffer.toString("base64");
2633
- });
2634
- }
2635
- decrypt(encryptedB64, myPrivateKey) {
2636
- return __async(this, null, function* () {
2637
- const encryptedBuffer = Buffer.from(encryptedB64, "base64");
2638
- const decryptedBuffer = yield decrypt(myPrivateKey, encryptedBuffer);
2639
- return Buffer.from(decryptedBuffer).toString("utf8");
2640
- });
2641
- }
2642
- validatePeerKey(key) {
2643
- PublicKey.fromHex(Buffer.from(key).toString("hex"));
2644
- }
2645
- };
2646
- var keymanager = new KeyManager();
2647
-
2648
2791
  // src/multichain/index.ts
2649
2792
  init_utils2();
2650
2793
  var logger2 = createLogger("metamask-sdk:core");
2651
2794
  var SINGLETON_KEY = "__METAMASK_CONNECT_MULTICHAIN_SINGLETON__";
2652
- var _a2, _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;
2795
+ var _a2, _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;
2653
2796
  var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends MultichainCore {
2654
2797
  constructor(options) {
2655
2798
  var _a3, _b, _c, _d, _e, _f;
@@ -2667,7 +2810,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2667
2810
  versions: __spreadValues({
2668
2811
  // typeof guard needed: Metro (React Native) bundles TS source directly,
2669
2812
  // bypassing the tsup build that substitutes __PACKAGE_VERSION__.
2670
- "connect-multichain": false ? "unknown" : "0.12.1"
2813
+ "connect-multichain": false ? "unknown" : "0.14.0"
2671
2814
  }, (_f = options.versions) != null ? _f : {})
2672
2815
  });
2673
2816
  super(allOptions);
@@ -2677,6 +2820,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2677
2820
  __privateAdd(this, _transport2);
2678
2821
  __privateAdd(this, _dappClient);
2679
2822
  __privateAdd(this, _beforeUnloadListener);
2823
+ __privateAdd(this, _transportType);
2680
2824
  this._status = "pending";
2681
2825
  __privateAdd(this, _listener);
2682
2826
  __privateAdd(this, _anonId);
@@ -2713,12 +2857,13 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2713
2857
  }
2714
2858
  return __privateGet(this, _dappClient);
2715
2859
  }
2860
+ get transportType() {
2861
+ var _a3;
2862
+ return (_a3 = __privateGet(this, _transportType)) != null ? _a3 : "unknown" /* UNKNOWN */;
2863
+ }
2716
2864
  get storage() {
2717
2865
  return this.options.storage;
2718
2866
  }
2719
- get transportType() {
2720
- return __privateGet(this, _transport2) instanceof MWPTransport ? "mwp" /* MWP */ : "browser" /* Browser */;
2721
- }
2722
2867
  // Creates a singleton instance of MetaMaskConnectMultichain.
2723
2868
  // If the singleton already exists, it merges the incoming options with the
2724
2869
  // existing singleton options for the following keys: `api.supportedNetworks`,
@@ -2772,7 +2917,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2772
2917
  connect(scopes, caipAccountIds, sessionProperties, forceRequest) {
2773
2918
  return __async(this, null, function* () {
2774
2919
  var _a3;
2775
- if (this.status === "connecting" && this.transportType === "mwp" /* MWP */) {
2920
+ if (this.status === "connecting" && __privateGet(this, _transportType) === "mwp" /* MWP */) {
2776
2921
  yield __privateMethod(this, _MetaMaskConnectMultichain_instances, openConnectDeeplinkIfNeeded_fn).call(this);
2777
2922
  throw new Error(
2778
2923
  "Existing connection is pending. Please check your MetaMask Mobile app to continue."
@@ -2821,7 +2966,7 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2821
2966
  sessionProperties: nonEmptySessionProperties,
2822
2967
  forceRequest
2823
2968
  }).then(() => __async(this, null, function* () {
2824
- if (__privateGet(this, _transport2) instanceof MWPTransport) {
2969
+ if (__privateGet(this, _transportType) === "mwp" /* MWP */) {
2825
2970
  return this.storage.setTransport("mwp" /* MWP */);
2826
2971
  }
2827
2972
  return this.storage.setTransport("browser" /* Browser */);
@@ -2868,12 +3013,13 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2868
3013
  yield (_a3 = __privateGet(this, _transport2)) == null ? void 0 : _a3.disconnect(scopes);
2869
3014
  if (remainingScopes.length === 0) {
2870
3015
  yield this.storage.removeTransport();
2871
- if (this.transportType !== "browser" /* Browser */) {
3016
+ if (__privateGet(this, _transportType) !== "browser" /* Browser */) {
2872
3017
  yield (_b = __privateGet(this, _listener)) == null ? void 0 : _b.call(this);
2873
3018
  (_c = __privateGet(this, _beforeUnloadListener)) == null ? void 0 : _c.call(this);
2874
3019
  __privateSet(this, _listener, void 0);
2875
3020
  __privateSet(this, _beforeUnloadListener, void 0);
2876
3021
  __privateSet(this, _transport2, void 0);
3022
+ __privateSet(this, _transportType, void 0);
2877
3023
  __privateGet(this, _providerTransportWrapper).clearTransportNotificationListener();
2878
3024
  __privateSet(this, _dappClient, void 0);
2879
3025
  }
@@ -2883,13 +3029,14 @@ var _MetaMaskConnectMultichain = class _MetaMaskConnectMultichain extends Multic
2883
3029
  }
2884
3030
  invokeMethod(request) {
2885
3031
  return __async(this, null, function* () {
3032
+ var _a3;
2886
3033
  const { transport, options } = this;
2887
3034
  const rpcClient = new RpcClient(options, __privateGet(this, _sdkInfo));
2888
3035
  const requestRouter = new RequestRouter(
2889
3036
  transport,
2890
3037
  rpcClient,
2891
3038
  options,
2892
- this.transportType
3039
+ (_a3 = __privateGet(this, _transportType)) != null ? _a3 : "unknown" /* UNKNOWN */
2893
3040
  );
2894
3041
  return requestRouter.invokeMethod(request);
2895
3042
  });
@@ -2938,6 +3085,7 @@ _providerTransportWrapper = new WeakMap();
2938
3085
  _transport2 = new WeakMap();
2939
3086
  _dappClient = new WeakMap();
2940
3087
  _beforeUnloadListener = new WeakMap();
3088
+ _transportType = new WeakMap();
2941
3089
  _listener = new WeakMap();
2942
3090
  _anonId = new WeakMap();
2943
3091
  _sdkInfo = new WeakMap();
@@ -2995,6 +3143,7 @@ getStoredTransport_fn = function() {
2995
3143
  if (hasExtensionInstalled) {
2996
3144
  const apiTransport = new DefaultTransport();
2997
3145
  __privateSet(this, _transport2, apiTransport);
3146
+ __privateSet(this, _transportType, "browser" /* Browser */);
2998
3147
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
2999
3148
  __privateSet(this, _listener, apiTransport.onNotification(
3000
3149
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
@@ -3004,9 +3153,11 @@ getStoredTransport_fn = function() {
3004
3153
  } else if (transportType === "mwp" /* MWP */) {
3005
3154
  const { adapter: kvstore } = this.options.storage;
3006
3155
  const dappClient = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, createDappClient_fn).call(this);
3007
- const apiTransport = new MWPTransport(dappClient, kvstore);
3156
+ const { MWPTransport: MWPTransport2 } = yield Promise.resolve().then(() => (init_mwp(), mwp_exports));
3157
+ const apiTransport = new MWPTransport2(dappClient, kvstore);
3008
3158
  __privateSet(this, _dappClient, dappClient);
3009
3159
  __privateSet(this, _transport2, apiTransport);
3160
+ __privateSet(this, _transportType, "mwp" /* MWP */);
3010
3161
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3011
3162
  __privateSet(this, _listener, apiTransport.onNotification(
3012
3163
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
@@ -3028,7 +3179,7 @@ setupTransport_fn = function() {
3028
3179
  yield this.transport.connect();
3029
3180
  }
3030
3181
  this.status = "connected";
3031
- if (this.transport instanceof MWPTransport) {
3182
+ if (__privateGet(this, _transportType) === "mwp" /* MWP */) {
3032
3183
  yield this.storage.setTransport("mwp" /* MWP */);
3033
3184
  } else {
3034
3185
  yield this.storage.setTransport("browser" /* Browser */);
@@ -3072,31 +3223,43 @@ init_fn2 = function() {
3072
3223
  };
3073
3224
  createDappClient_fn = function() {
3074
3225
  return __async(this, null, function* () {
3226
+ const [mwpCore, { DappClient: DappClientClass }, { createKeyManager: createKeyManager2 }] = yield Promise.all([
3227
+ import("@metamask/mobile-wallet-protocol-core"),
3228
+ import("@metamask/mobile-wallet-protocol-dapp-client"),
3229
+ Promise.resolve().then(() => (init_KeyManager(), KeyManager_exports))
3230
+ ]);
3231
+ const keymanager = yield createKeyManager2();
3075
3232
  const { adapter: kvstore } = this.options.storage;
3076
- const sessionstore = yield SessionStore2.create(kvstore);
3233
+ const sessionstore = yield mwpCore.SessionStore.create(kvstore);
3077
3234
  const websocket = (
3078
3235
  // eslint-disable-next-line no-negated-condition
3079
3236
  typeof window !== "undefined" ? WebSocket : (yield import("ws")).WebSocket
3080
3237
  );
3081
- const transport = yield WebSocketTransport.create({
3238
+ const transport = yield mwpCore.WebSocketTransport.create({
3082
3239
  url: MWP_RELAY_URL,
3083
3240
  kvstore,
3084
3241
  websocket
3085
3242
  });
3086
- const dappClient = new DappClient({ transport, sessionstore, keymanager });
3243
+ const dappClient = new DappClientClass({
3244
+ transport,
3245
+ sessionstore,
3246
+ keymanager
3247
+ });
3087
3248
  return dappClient;
3088
3249
  });
3089
3250
  };
3090
3251
  setupMWP_fn = function() {
3091
3252
  return __async(this, null, function* () {
3092
- if (__privateGet(this, _transport2) instanceof MWPTransport) {
3253
+ if (__privateGet(this, _transportType) === "mwp" /* MWP */) {
3093
3254
  return;
3094
3255
  }
3095
3256
  const { adapter: kvstore } = this.options.storage;
3096
3257
  const dappClient = yield __privateMethod(this, _MetaMaskConnectMultichain_instances, createDappClient_fn).call(this);
3097
3258
  __privateSet(this, _dappClient, dappClient);
3098
- const apiTransport = new MWPTransport(dappClient, kvstore);
3259
+ const { MWPTransport: MWPTransport2 } = yield Promise.resolve().then(() => (init_mwp(), mwp_exports));
3260
+ const apiTransport = new MWPTransport2(dappClient, kvstore);
3099
3261
  __privateSet(this, _transport2, apiTransport);
3262
+ __privateSet(this, _transportType, "mwp" /* MWP */);
3100
3263
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3101
3264
  __privateSet(this, _listener, this.transport.onNotification(
3102
3265
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
@@ -3155,6 +3318,7 @@ renderInstallModalAsync_fn = function(desktopPreferred, scopes, caipAccountIds,
3155
3318
  this.status = "connected";
3156
3319
  yield this.storage.setTransport("mwp" /* MWP */);
3157
3320
  } catch (error) {
3321
+ const { ProtocolError, ErrorCode } = yield import("@metamask/mobile-wallet-protocol-core");
3158
3322
  if (error instanceof ProtocolError) {
3159
3323
  if (error.code !== ErrorCode.REQUEST_EXPIRED) {
3160
3324
  this.status = "disconnected";
@@ -3224,6 +3388,7 @@ headlessConnect_fn = function(scopes, caipAccountIds, sessionProperties) {
3224
3388
  yield this.storage.setTransport("mwp" /* MWP */);
3225
3389
  resolve();
3226
3390
  })).catch((error) => __async(this, null, function* () {
3391
+ const { ProtocolError } = yield import("@metamask/mobile-wallet-protocol-core");
3227
3392
  if (error instanceof ProtocolError) {
3228
3393
  this.status = "disconnected";
3229
3394
  yield this.storage.removeTransport();
@@ -3239,7 +3404,7 @@ headlessConnect_fn = function(scopes, caipAccountIds, sessionProperties) {
3239
3404
  };
3240
3405
  setupDefaultTransport_fn = function() {
3241
3406
  return __async(this, arguments, function* (options = { persist: true }) {
3242
- if (__privateGet(this, _transport2) instanceof DefaultTransport) {
3407
+ if (__privateGet(this, _transportType) === "browser" /* Browser */) {
3243
3408
  return __privateGet(this, _transport2);
3244
3409
  }
3245
3410
  if (options == null ? void 0 : options.persist) {
@@ -3250,6 +3415,7 @@ setupDefaultTransport_fn = function() {
3250
3415
  __privateMethod(this, _MetaMaskConnectMultichain_instances, onTransportNotification_fn).bind(this)
3251
3416
  ));
3252
3417
  __privateSet(this, _transport2, transport);
3418
+ __privateSet(this, _transportType, "browser" /* Browser */);
3253
3419
  __privateGet(this, _providerTransportWrapper).setupTransportNotificationListener();
3254
3420
  return transport;
3255
3421
  });
@@ -3346,9 +3512,9 @@ handleConnection_fn = function(promise, scopes, transportType) {
3346
3512
  transport_type: transportType
3347
3513
  }));
3348
3514
  } else {
3349
- analytics2.track("mmconnect_connection_failed", __spreadProps(__spreadValues({}, baseProps), {
3515
+ analytics2.track("mmconnect_connection_failed", __spreadValues(__spreadProps(__spreadValues({}, baseProps), {
3350
3516
  transport_type: transportType
3351
- }));
3517
+ }), extractErrorDiagnostics(error)));
3352
3518
  }
3353
3519
  } catch (e) {
3354
3520
  logger2("Error tracking connection failed/rejected event", error);
@@ -3788,6 +3954,7 @@ export {
3788
3954
  StoreAdapter,
3789
3955
  StoreClient,
3790
3956
  TransportType,
3957
+ classifyFailureReason,
3791
3958
  createLogger,
3792
3959
  createMultichainClient,
3793
3960
  enableDebug,