@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.
- package/CHANGELOG.md +29 -1
- package/dist/browser/es/connect-multichain.d.mts +46 -2
- package/dist/browser/es/connect-multichain.mjs +1733 -1566
- package/dist/browser/es/connect-multichain.mjs.map +1 -1
- package/dist/browser/es/metafile-esm.json +1 -1
- package/dist/browser/iife/connect-multichain.d.ts +46 -2
- package/dist/browser/iife/connect-multichain.js +6279 -5413
- package/dist/browser/iife/connect-multichain.js.map +1 -1
- package/dist/browser/iife/metafile-iife.json +1 -1
- package/dist/browser/umd/connect-multichain.d.ts +46 -2
- package/dist/browser/umd/connect-multichain.js +1761 -1589
- package/dist/browser/umd/connect-multichain.js.map +1 -1
- package/dist/browser/umd/metafile-cjs.json +1 -1
- package/dist/node/cjs/connect-multichain.d.ts +46 -2
- package/dist/node/cjs/connect-multichain.js +892 -719
- package/dist/node/cjs/connect-multichain.js.map +1 -1
- package/dist/node/cjs/metafile-cjs.json +1 -1
- package/dist/node/es/connect-multichain.d.mts +46 -2
- package/dist/node/es/connect-multichain.mjs +890 -723
- package/dist/node/es/connect-multichain.mjs.map +1 -1
- package/dist/node/es/metafile-esm.json +1 -1
- package/dist/react-native/es/connect-multichain.d.mts +46 -2
- package/dist/react-native/es/connect-multichain.mjs +890 -723
- package/dist/react-native/es/connect-multichain.mjs.map +1 -1
- package/dist/react-native/es/metafile-esm.json +1 -1
- package/dist/src/domain/multichain/index.d.ts +1 -1
- package/dist/src/domain/multichain/index.d.ts.map +1 -1
- package/dist/src/domain/utils/index.d.ts +2 -1
- package/dist/src/domain/utils/index.d.ts.map +1 -1
- package/dist/src/domain/utils/index.js +1 -1
- package/dist/src/domain/utils/index.js.map +1 -1
- package/dist/src/multichain/index.d.ts +2 -2
- package/dist/src/multichain/index.d.ts.map +1 -1
- package/dist/src/multichain/index.js +39 -25
- package/dist/src/multichain/index.js.map +1 -1
- package/dist/src/multichain/rpc/requestRouter.d.ts.map +1 -1
- package/dist/src/multichain/rpc/requestRouter.js +4 -4
- package/dist/src/multichain/rpc/requestRouter.js.map +1 -1
- package/dist/src/multichain/transports/multichainApiClientWrapper/index.d.ts +1 -0
- package/dist/src/multichain/transports/multichainApiClientWrapper/index.d.ts.map +1 -1
- package/dist/src/multichain/transports/multichainApiClientWrapper/index.js +10 -10
- package/dist/src/multichain/transports/multichainApiClientWrapper/index.js.map +1 -1
- package/dist/src/multichain/transports/mwp/KeyManager.d.ts +12 -9
- package/dist/src/multichain/transports/mwp/KeyManager.d.ts.map +1 -1
- package/dist/src/multichain/transports/mwp/KeyManager.js +38 -25
- package/dist/src/multichain/transports/mwp/KeyManager.js.map +1 -1
- package/dist/src/multichain/transports/mwp/index.d.ts.map +1 -1
- package/dist/src/multichain/transports/mwp/index.js +18 -6
- package/dist/src/multichain/transports/mwp/index.js.map +1 -1
- package/dist/src/multichain/utils/analytics.d.ts +82 -1
- package/dist/src/multichain/utils/analytics.d.ts.map +1 -1
- package/dist/src/multichain/utils/analytics.js +252 -17
- package/dist/src/multichain/utils/analytics.js.map +1 -1
- package/dist/types/connect-multichain.d.ts +46 -2
- 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
|
|
959
|
-
const
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|