@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
|
@@ -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
|
|
689
|
-
const
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|