@metamask-previews/keyring-controller 12.0.0-preview.d357889 → 12.2.0-preview.56c80981
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 +102 -5
- package/dist/KeyringController.d.ts +149 -11
- package/dist/KeyringController.d.ts.map +1 -1
- package/dist/KeyringController.js +567 -110
- package/dist/KeyringController.js.map +1 -1
- package/dist/constants.d.ts +30 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +34 -0
- package/dist/constants.js.map +1 -0
- package/package.json +15 -9
|
@@ -42,15 +42,22 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
42
42
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
43
43
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
44
44
|
};
|
|
45
|
-
var
|
|
45
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
+
};
|
|
48
|
+
var _KeyringController_instances, _KeyringController_keyringBuilders, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_password, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringBuilderForType, _KeyringController_addQRKeyring, _KeyringController_subscribeToQRKeyringEvents, _KeyringController_unsubscribeFromQRKeyringsEvents, _KeyringController_createNewVaultWithKeyring, _KeyringController_updateKeyringsInState, _KeyringController_unlockKeyrings, _KeyringController_createKeyringWithFirstAccount, _KeyringController_newKeyring, _KeyringController_clearKeyrings, _KeyringController_restoreKeyring, _KeyringController_destroyKeyring, _KeyringController_removeEmptyKeyrings, _KeyringController_checkForDuplicate, _KeyringController_setUnlocked, _KeyringController_getMemState;
|
|
46
49
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
-
exports.KeyringController = exports.SignTypedDataVersion = exports.AccountImportStrategy = exports.KeyringTypes = void 0;
|
|
50
|
+
exports.KeyringController = exports.getDefaultKeyringState = exports.keyringBuilderFactory = exports.SignTypedDataVersion = exports.AccountImportStrategy = exports.KeyringTypes = void 0;
|
|
48
51
|
const base_controller_1 = require("@metamask/base-controller");
|
|
49
|
-
const
|
|
52
|
+
const encryptorUtils = __importStar(require("@metamask/browser-passworder"));
|
|
53
|
+
const eth_hd_keyring_1 = __importDefault(require("@metamask/eth-hd-keyring"));
|
|
54
|
+
const eth_sig_util_1 = require("@metamask/eth-sig-util");
|
|
55
|
+
const eth_simple_keyring_1 = __importDefault(require("@metamask/eth-simple-keyring"));
|
|
50
56
|
const utils_1 = require("@metamask/utils");
|
|
51
57
|
const async_mutex_1 = require("async-mutex");
|
|
52
58
|
const ethereumjs_util_1 = require("ethereumjs-util");
|
|
53
59
|
const ethereumjs_wallet_1 = __importStar(require("ethereumjs-wallet"));
|
|
60
|
+
const constants_1 = require("./constants");
|
|
54
61
|
const name = 'KeyringController';
|
|
55
62
|
/**
|
|
56
63
|
* Available keyring types
|
|
@@ -64,7 +71,7 @@ var KeyringTypes;
|
|
|
64
71
|
KeyringTypes["ledger"] = "Ledger Hardware";
|
|
65
72
|
KeyringTypes["lattice"] = "Lattice Hardware";
|
|
66
73
|
KeyringTypes["snap"] = "Snap Keyring";
|
|
67
|
-
KeyringTypes["custody"] = "Custody";
|
|
74
|
+
KeyringTypes["custody"] = "Custody - JSONRPC";
|
|
68
75
|
})(KeyringTypes = exports.KeyringTypes || (exports.KeyringTypes = {}));
|
|
69
76
|
/**
|
|
70
77
|
* A strategy for importing an account
|
|
@@ -85,10 +92,31 @@ var SignTypedDataVersion;
|
|
|
85
92
|
SignTypedDataVersion["V3"] = "V3";
|
|
86
93
|
SignTypedDataVersion["V4"] = "V4";
|
|
87
94
|
})(SignTypedDataVersion = exports.SignTypedDataVersion || (exports.SignTypedDataVersion = {}));
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Get builder function for `Keyring`
|
|
97
|
+
*
|
|
98
|
+
* Returns a builder function for `Keyring` with a `type` property.
|
|
99
|
+
*
|
|
100
|
+
* @param KeyringConstructor - The Keyring class for the builder.
|
|
101
|
+
* @returns A builder function for the given Keyring.
|
|
102
|
+
*/
|
|
103
|
+
function keyringBuilderFactory(KeyringConstructor) {
|
|
104
|
+
const builder = () => new KeyringConstructor();
|
|
105
|
+
builder.type = KeyringConstructor.type;
|
|
106
|
+
return builder;
|
|
107
|
+
}
|
|
108
|
+
exports.keyringBuilderFactory = keyringBuilderFactory;
|
|
109
|
+
const defaultKeyringBuilders = [
|
|
110
|
+
keyringBuilderFactory(eth_simple_keyring_1.default),
|
|
111
|
+
keyringBuilderFactory(eth_hd_keyring_1.default),
|
|
112
|
+
];
|
|
113
|
+
const getDefaultKeyringState = () => {
|
|
114
|
+
return {
|
|
115
|
+
isUnlocked: false,
|
|
116
|
+
keyrings: [],
|
|
117
|
+
};
|
|
91
118
|
};
|
|
119
|
+
exports.getDefaultKeyringState = getDefaultKeyringState;
|
|
92
120
|
/**
|
|
93
121
|
* Assert that the given keyring has an exportable
|
|
94
122
|
* mnemonic.
|
|
@@ -101,6 +129,53 @@ function assertHasUint8ArrayMnemonic(keyring) {
|
|
|
101
129
|
throw new Error("Can't get mnemonic bytes from keyring");
|
|
102
130
|
}
|
|
103
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Assert that the provided encryptor supports
|
|
134
|
+
* encryption and encryption key export.
|
|
135
|
+
*
|
|
136
|
+
* @param encryptor - The encryptor to check.
|
|
137
|
+
* @throws If the encryptor does not support key encryption.
|
|
138
|
+
*/
|
|
139
|
+
function assertIsExportableKeyEncryptor(encryptor) {
|
|
140
|
+
if (!('importKey' in encryptor &&
|
|
141
|
+
typeof encryptor.importKey === 'function' &&
|
|
142
|
+
'decryptWithKey' in encryptor &&
|
|
143
|
+
typeof encryptor.decryptWithKey === 'function' &&
|
|
144
|
+
'encryptWithKey' in encryptor &&
|
|
145
|
+
typeof encryptor.encryptWithKey === 'function')) {
|
|
146
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedEncryptionKeyExport);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Checks if the provided value is a serialized keyrings array.
|
|
151
|
+
*
|
|
152
|
+
* @param array - The value to check.
|
|
153
|
+
* @returns True if the value is a serialized keyrings array.
|
|
154
|
+
*/
|
|
155
|
+
function isSerializedKeyringsArray(array) {
|
|
156
|
+
return (typeof array === 'object' &&
|
|
157
|
+
Array.isArray(array) &&
|
|
158
|
+
array.every((value) => value.type && (0, utils_1.isValidJson)(value.data)));
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Display For Keyring
|
|
162
|
+
*
|
|
163
|
+
* Is used for adding the current keyrings to the state object.
|
|
164
|
+
*
|
|
165
|
+
* @param keyring - The keyring to display.
|
|
166
|
+
* @returns A keyring display object, with type and accounts properties.
|
|
167
|
+
*/
|
|
168
|
+
function displayForKeyring(keyring) {
|
|
169
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
170
|
+
const accounts = yield keyring.getAccounts();
|
|
171
|
+
return {
|
|
172
|
+
type: keyring.type,
|
|
173
|
+
// Cast to `Hex[]` here is safe here because `accounts` has no nullish
|
|
174
|
+
// values, and `normalize` returns `Hex` unless given a nullish value
|
|
175
|
+
accounts: accounts.map(eth_sig_util_1.normalize),
|
|
176
|
+
};
|
|
177
|
+
});
|
|
178
|
+
}
|
|
104
179
|
/**
|
|
105
180
|
* Controller responsible for establishing and managing user identity.
|
|
106
181
|
*
|
|
@@ -126,8 +201,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
126
201
|
* @param options.state - Initial state to set on this controller.
|
|
127
202
|
*/
|
|
128
203
|
constructor(options) {
|
|
129
|
-
|
|
130
|
-
const { syncIdentities, updateIdentities, setSelectedAddress, setAccountLabel, keyringBuilders, messenger, state, } = options;
|
|
204
|
+
const { syncIdentities, updateIdentities, setSelectedAddress, setAccountLabel, encryptor = encryptorUtils, keyringBuilders, messenger, state, } = options;
|
|
131
205
|
super({
|
|
132
206
|
name,
|
|
133
207
|
metadata: {
|
|
@@ -138,32 +212,29 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
138
212
|
encryptionSalt: { persist: false, anonymous: false },
|
|
139
213
|
},
|
|
140
214
|
messenger,
|
|
141
|
-
state: Object.assign(Object.assign({},
|
|
215
|
+
state: Object.assign(Object.assign({}, (0, exports.getDefaultKeyringState)()), state),
|
|
142
216
|
});
|
|
143
217
|
_KeyringController_instances.add(this);
|
|
144
218
|
this.mutex = new async_mutex_1.Mutex();
|
|
145
|
-
|
|
219
|
+
_KeyringController_keyringBuilders.set(this, void 0);
|
|
220
|
+
_KeyringController_keyrings.set(this, void 0);
|
|
221
|
+
_KeyringController_unsupportedKeyrings.set(this, void 0);
|
|
222
|
+
_KeyringController_password.set(this, void 0);
|
|
223
|
+
_KeyringController_encryptor.set(this, void 0);
|
|
224
|
+
_KeyringController_cacheEncryptionKey.set(this, void 0);
|
|
146
225
|
_KeyringController_qrKeyringStateListener.set(this, void 0);
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
encryptor: options.encryptor,
|
|
159
|
-
keyringBuilders,
|
|
160
|
-
cacheEncryptionKey: (_a = options.cacheEncryptionKey) !== null && _a !== void 0 ? _a : false,
|
|
161
|
-
}), "f");
|
|
226
|
+
__classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
|
|
227
|
+
? defaultKeyringBuilders.concat(keyringBuilders)
|
|
228
|
+
: defaultKeyringBuilders, "f");
|
|
229
|
+
__classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
|
|
230
|
+
__classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
|
|
231
|
+
__classPrivateFieldSet(this, _KeyringController_unsupportedKeyrings, [], "f");
|
|
232
|
+
// This option allows the controller to cache an exported key
|
|
233
|
+
// for use in decrypting and encrypting data without password
|
|
234
|
+
__classPrivateFieldSet(this, _KeyringController_cacheEncryptionKey, Boolean(options.cacheEncryptionKey), "f");
|
|
235
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
236
|
+
assertIsExportableKeyEncryptor(encryptor);
|
|
162
237
|
}
|
|
163
|
-
__classPrivateFieldGet(this, _KeyringController_keyring, "f").memStore.subscribe(__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).bind(this));
|
|
164
|
-
__classPrivateFieldGet(this, _KeyringController_keyring, "f").store.subscribe(__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).bind(this));
|
|
165
|
-
__classPrivateFieldGet(this, _KeyringController_keyring, "f").on('lock', __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_handleLock).bind(this));
|
|
166
|
-
__classPrivateFieldGet(this, _KeyringController_keyring, "f").on('unlock', __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_handleUnlock).bind(this));
|
|
167
238
|
this.syncIdentities = syncIdentities;
|
|
168
239
|
this.updateIdentities = updateIdentities;
|
|
169
240
|
this.setSelectedAddress = setSelectedAddress;
|
|
@@ -180,12 +251,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
180
251
|
*/
|
|
181
252
|
addNewAccount(accountCount) {
|
|
182
253
|
return __awaiter(this, void 0, void 0, function* () {
|
|
183
|
-
const primaryKeyring =
|
|
184
|
-
/* istanbul ignore if */
|
|
254
|
+
const primaryKeyring = this.getKeyringsByType('HD Key Tree')[0];
|
|
185
255
|
if (!primaryKeyring) {
|
|
186
256
|
throw new Error('No HD keyring found');
|
|
187
257
|
}
|
|
188
|
-
const oldAccounts = yield
|
|
258
|
+
const oldAccounts = yield this.getAccounts();
|
|
189
259
|
if (accountCount && oldAccounts.length !== accountCount) {
|
|
190
260
|
if (accountCount > oldAccounts.length) {
|
|
191
261
|
throw new Error('Account out of sequence');
|
|
@@ -197,12 +267,9 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
197
267
|
addedAccountAddress: primaryKeyringAccounts[accountCount],
|
|
198
268
|
};
|
|
199
269
|
}
|
|
200
|
-
yield
|
|
201
|
-
const newAccounts = yield __classPrivateFieldGet(this, _KeyringController_keyring, "f").getAccounts();
|
|
270
|
+
const addedAccountAddress = yield this.addNewAccountForKeyring(primaryKeyring);
|
|
202
271
|
yield this.verifySeedPhrase();
|
|
203
|
-
this.updateIdentities(
|
|
204
|
-
const addedAccountAddress = newAccounts.find((selectedAddress) => !oldAccounts.includes(selectedAddress));
|
|
205
|
-
(0, utils_1.assertIsStrictHexString)(addedAccountAddress);
|
|
272
|
+
this.updateIdentities(yield this.getAccounts());
|
|
206
273
|
return {
|
|
207
274
|
keyringState: __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this),
|
|
208
275
|
addedAccountAddress,
|
|
@@ -227,10 +294,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
227
294
|
(0, utils_1.assertIsStrictHexString)(existingAccount);
|
|
228
295
|
return existingAccount;
|
|
229
296
|
}
|
|
230
|
-
yield
|
|
297
|
+
yield keyring.addAccounts(1);
|
|
298
|
+
yield this.persistAllKeyrings();
|
|
231
299
|
const addedAccountAddress = (yield this.getAccounts()).find((selectedAddress) => !oldAccounts.includes(selectedAddress));
|
|
232
300
|
(0, utils_1.assertIsStrictHexString)(addedAccountAddress);
|
|
233
|
-
this.updateIdentities(yield
|
|
301
|
+
this.updateIdentities(yield this.getAccounts());
|
|
234
302
|
return addedAccountAddress;
|
|
235
303
|
});
|
|
236
304
|
}
|
|
@@ -241,12 +309,12 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
241
309
|
*/
|
|
242
310
|
addNewAccountWithoutUpdate() {
|
|
243
311
|
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
-
const primaryKeyring =
|
|
245
|
-
/* istanbul ignore if */
|
|
312
|
+
const primaryKeyring = this.getKeyringsByType('HD Key Tree')[0];
|
|
246
313
|
if (!primaryKeyring) {
|
|
247
314
|
throw new Error('No HD keyring found');
|
|
248
315
|
}
|
|
249
|
-
yield
|
|
316
|
+
yield primaryKeyring.addAccounts(1);
|
|
317
|
+
yield this.persistAllKeyrings();
|
|
250
318
|
yield this.verifySeedPhrase();
|
|
251
319
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
252
320
|
});
|
|
@@ -268,8 +336,14 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
268
336
|
}
|
|
269
337
|
try {
|
|
270
338
|
this.updateIdentities([]);
|
|
271
|
-
yield __classPrivateFieldGet(this,
|
|
272
|
-
|
|
339
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
|
|
340
|
+
type: KeyringTypes.hd,
|
|
341
|
+
opts: {
|
|
342
|
+
mnemonic: seed,
|
|
343
|
+
numberOfAccounts: 1,
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
this.updateIdentities(yield this.getAccounts());
|
|
273
347
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
274
348
|
}
|
|
275
349
|
finally {
|
|
@@ -289,7 +363,9 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
289
363
|
try {
|
|
290
364
|
const accounts = yield this.getAccounts();
|
|
291
365
|
if (!accounts.length) {
|
|
292
|
-
yield __classPrivateFieldGet(this,
|
|
366
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
|
|
367
|
+
type: KeyringTypes.hd,
|
|
368
|
+
});
|
|
293
369
|
this.updateIdentities(yield this.getAccounts());
|
|
294
370
|
}
|
|
295
371
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
@@ -312,7 +388,19 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
312
388
|
if (type === KeyringTypes.qr) {
|
|
313
389
|
return this.getOrAddQRKeyring();
|
|
314
390
|
}
|
|
315
|
-
|
|
391
|
+
const keyring = yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts);
|
|
392
|
+
if (type === KeyringTypes.hd && (!(0, utils_1.isObject)(opts) || !opts.mnemonic)) {
|
|
393
|
+
if (!keyring.generateRandomMnemonic) {
|
|
394
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedGenerateRandomMnemonic);
|
|
395
|
+
}
|
|
396
|
+
keyring.generateRandomMnemonic();
|
|
397
|
+
yield keyring.addAccounts(1);
|
|
398
|
+
}
|
|
399
|
+
const accounts = yield keyring.getAccounts();
|
|
400
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_checkForDuplicate).call(this, type, accounts);
|
|
401
|
+
__classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(keyring);
|
|
402
|
+
yield this.persistAllKeyrings();
|
|
403
|
+
return keyring;
|
|
316
404
|
});
|
|
317
405
|
}
|
|
318
406
|
/**
|
|
@@ -323,7 +411,10 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
323
411
|
*/
|
|
324
412
|
verifyPassword(password) {
|
|
325
413
|
return __awaiter(this, void 0, void 0, function* () {
|
|
326
|
-
|
|
414
|
+
if (!this.state.vault) {
|
|
415
|
+
throw new Error(constants_1.KeyringControllerError.VaultError);
|
|
416
|
+
}
|
|
417
|
+
yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, this.state.vault);
|
|
327
418
|
});
|
|
328
419
|
}
|
|
329
420
|
/**
|
|
@@ -343,8 +434,8 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
343
434
|
exportSeedPhrase(password) {
|
|
344
435
|
return __awaiter(this, void 0, void 0, function* () {
|
|
345
436
|
yield this.verifyPassword(password);
|
|
346
|
-
assertHasUint8ArrayMnemonic(__classPrivateFieldGet(this,
|
|
347
|
-
return __classPrivateFieldGet(this,
|
|
437
|
+
assertHasUint8ArrayMnemonic(__classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0]);
|
|
438
|
+
return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0].mnemonic;
|
|
348
439
|
});
|
|
349
440
|
}
|
|
350
441
|
/**
|
|
@@ -357,7 +448,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
357
448
|
exportAccount(password, address) {
|
|
358
449
|
return __awaiter(this, void 0, void 0, function* () {
|
|
359
450
|
yield this.verifyPassword(password);
|
|
360
|
-
|
|
451
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
452
|
+
if (!keyring.exportAccount) {
|
|
453
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedExportAccount);
|
|
454
|
+
}
|
|
455
|
+
return yield keyring.exportAccount((0, eth_sig_util_1.normalize)(address));
|
|
361
456
|
});
|
|
362
457
|
}
|
|
363
458
|
/**
|
|
@@ -366,7 +461,16 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
366
461
|
* @returns A promise resolving to an array of addresses.
|
|
367
462
|
*/
|
|
368
463
|
getAccounts() {
|
|
369
|
-
return
|
|
464
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
465
|
+
const keyrings = __classPrivateFieldGet(this, _KeyringController_keyrings, "f");
|
|
466
|
+
const keyringArrays = yield Promise.all(keyrings.map((keyring) => __awaiter(this, void 0, void 0, function* () { return keyring.getAccounts(); })));
|
|
467
|
+
const addresses = keyringArrays.reduce((res, arr) => {
|
|
468
|
+
return res.concat(arr);
|
|
469
|
+
}, []);
|
|
470
|
+
// Cast to `Hex[]` here is safe here because `addresses` has no nullish
|
|
471
|
+
// values, and `normalize` returns `Hex` unless given a nullish value
|
|
472
|
+
return addresses.map(eth_sig_util_1.normalize);
|
|
473
|
+
});
|
|
370
474
|
}
|
|
371
475
|
/**
|
|
372
476
|
* Get encryption public key.
|
|
@@ -378,7 +482,12 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
378
482
|
*/
|
|
379
483
|
getEncryptionPublicKey(account, opts) {
|
|
380
484
|
return __awaiter(this, void 0, void 0, function* () {
|
|
381
|
-
|
|
485
|
+
const normalizedAddress = (0, eth_sig_util_1.normalize)(account);
|
|
486
|
+
const keyring = (yield this.getKeyringForAccount(account));
|
|
487
|
+
if (!keyring.getEncryptionPublicKey) {
|
|
488
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedGetEncryptionPublicKey);
|
|
489
|
+
}
|
|
490
|
+
return yield keyring.getEncryptionPublicKey(normalizedAddress, opts);
|
|
382
491
|
});
|
|
383
492
|
}
|
|
384
493
|
/**
|
|
@@ -391,7 +500,12 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
391
500
|
*/
|
|
392
501
|
decryptMessage(messageParams) {
|
|
393
502
|
return __awaiter(this, void 0, void 0, function* () {
|
|
394
|
-
|
|
503
|
+
const address = (0, eth_sig_util_1.normalize)(messageParams.from);
|
|
504
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
505
|
+
if (!keyring.decryptMessage) {
|
|
506
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedDecryptMessage);
|
|
507
|
+
}
|
|
508
|
+
return keyring.decryptMessage(address, messageParams.data);
|
|
395
509
|
});
|
|
396
510
|
}
|
|
397
511
|
/**
|
|
@@ -405,8 +519,33 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
405
519
|
* @returns Promise resolving to keyring of the `account` if one exists.
|
|
406
520
|
*/
|
|
407
521
|
getKeyringForAccount(account) {
|
|
522
|
+
var _a;
|
|
408
523
|
return __awaiter(this, void 0, void 0, function* () {
|
|
409
|
-
|
|
524
|
+
// Cast to `Hex` here is safe here because `address` is not nullish.
|
|
525
|
+
// `normalizeToHex` returns `Hex` unless given a nullish value.
|
|
526
|
+
const hexed = (0, eth_sig_util_1.normalize)(account);
|
|
527
|
+
const candidates = yield Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map((keyring) => __awaiter(this, void 0, void 0, function* () {
|
|
528
|
+
return Promise.all([keyring, keyring.getAccounts()]);
|
|
529
|
+
})));
|
|
530
|
+
const winners = candidates.filter((candidate) => {
|
|
531
|
+
const accounts = candidate[1].map(eth_sig_util_1.normalize);
|
|
532
|
+
return accounts.includes(hexed);
|
|
533
|
+
});
|
|
534
|
+
if (winners.length && ((_a = winners[0]) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
535
|
+
return winners[0][0];
|
|
536
|
+
}
|
|
537
|
+
// Adding more info to the error
|
|
538
|
+
let errorInfo = '';
|
|
539
|
+
if (!(0, utils_1.isValidHexAddress)(hexed)) {
|
|
540
|
+
errorInfo = 'The address passed in is invalid/empty';
|
|
541
|
+
}
|
|
542
|
+
else if (!candidates.length) {
|
|
543
|
+
errorInfo = 'There are no keyrings';
|
|
544
|
+
}
|
|
545
|
+
else if (!winners.length) {
|
|
546
|
+
errorInfo = 'There are keyrings, but none match the address';
|
|
547
|
+
}
|
|
548
|
+
throw new Error(`${constants_1.KeyringControllerError.NoKeyring}. Error info: ${errorInfo}`);
|
|
410
549
|
});
|
|
411
550
|
}
|
|
412
551
|
/**
|
|
@@ -419,7 +558,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
419
558
|
* @returns An array of keyrings of the given type.
|
|
420
559
|
*/
|
|
421
560
|
getKeyringsByType(type) {
|
|
422
|
-
return __classPrivateFieldGet(this,
|
|
561
|
+
return __classPrivateFieldGet(this, _KeyringController_keyrings, "f").filter((keyring) => keyring.type === type);
|
|
423
562
|
}
|
|
424
563
|
/**
|
|
425
564
|
* Persist all serialized keyrings in the vault.
|
|
@@ -429,7 +568,58 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
429
568
|
*/
|
|
430
569
|
persistAllKeyrings() {
|
|
431
570
|
return __awaiter(this, void 0, void 0, function* () {
|
|
432
|
-
|
|
571
|
+
const { encryptionKey, encryptionSalt } = this.state;
|
|
572
|
+
if (!__classPrivateFieldGet(this, _KeyringController_password, "f") && !encryptionKey) {
|
|
573
|
+
throw new Error(constants_1.KeyringControllerError.MissingCredentials);
|
|
574
|
+
}
|
|
575
|
+
const serializedKeyrings = yield Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map((keyring) => __awaiter(this, void 0, void 0, function* () {
|
|
576
|
+
const [type, data] = yield Promise.all([
|
|
577
|
+
keyring.type,
|
|
578
|
+
keyring.serialize(),
|
|
579
|
+
]);
|
|
580
|
+
return { type, data };
|
|
581
|
+
})));
|
|
582
|
+
serializedKeyrings.push(...__classPrivateFieldGet(this, _KeyringController_unsupportedKeyrings, "f"));
|
|
583
|
+
let vault;
|
|
584
|
+
let newEncryptionKey;
|
|
585
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
586
|
+
assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
|
|
587
|
+
if (encryptionKey) {
|
|
588
|
+
const key = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
589
|
+
const vaultJSON = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
|
|
590
|
+
vaultJSON.salt = encryptionSalt;
|
|
591
|
+
vault = JSON.stringify(vaultJSON);
|
|
592
|
+
}
|
|
593
|
+
else if (__classPrivateFieldGet(this, _KeyringController_password, "f")) {
|
|
594
|
+
const { vault: newVault, exportedKeyString } = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithDetail(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
|
|
595
|
+
vault = newVault;
|
|
596
|
+
newEncryptionKey = exportedKeyString;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
else {
|
|
600
|
+
if (typeof __classPrivateFieldGet(this, _KeyringController_password, "f") !== 'string') {
|
|
601
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
602
|
+
}
|
|
603
|
+
vault = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encrypt(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
|
|
604
|
+
}
|
|
605
|
+
if (!vault) {
|
|
606
|
+
throw new Error(constants_1.KeyringControllerError.MissingVaultData);
|
|
607
|
+
}
|
|
608
|
+
this.update((state) => {
|
|
609
|
+
state.vault = vault;
|
|
610
|
+
});
|
|
611
|
+
// The keyring updates need to be announced before updating the encryptionKey
|
|
612
|
+
// so that the updated keyring gets propagated to the extension first.
|
|
613
|
+
// Not calling {@link updateKeyringsInState} results in the wrong account being selected
|
|
614
|
+
// in the extension.
|
|
615
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateKeyringsInState).call(this);
|
|
616
|
+
if (newEncryptionKey) {
|
|
617
|
+
this.update((state) => {
|
|
618
|
+
state.encryptionKey = newEncryptionKey;
|
|
619
|
+
state.encryptionSalt = JSON.parse(vault).salt;
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
return true;
|
|
433
623
|
});
|
|
434
624
|
}
|
|
435
625
|
/**
|
|
@@ -461,7 +651,6 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
461
651
|
catch (_a) {
|
|
462
652
|
throw new Error('Cannot import invalid private key.');
|
|
463
653
|
}
|
|
464
|
-
/* istanbul ignore if */
|
|
465
654
|
if (!(0, ethereumjs_util_1.isValidPrivate)(bufferedPrivateKey) ||
|
|
466
655
|
// ensures that the key is 64 bytes long
|
|
467
656
|
(0, ethereumjs_util_1.getBinarySize)(prefixed) !== 64 + '0x'.length) {
|
|
@@ -483,11 +672,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
483
672
|
default:
|
|
484
673
|
throw new Error(`Unexpected import strategy: '${strategy}'`);
|
|
485
674
|
}
|
|
486
|
-
const newKeyring = yield
|
|
675
|
+
const newKeyring = (yield this.addNewKeyring(KeyringTypes.simple, [
|
|
487
676
|
privateKey,
|
|
488
|
-
]);
|
|
677
|
+
]));
|
|
489
678
|
const accounts = yield newKeyring.getAccounts();
|
|
490
|
-
const allAccounts = yield
|
|
679
|
+
const allAccounts = yield this.getAccounts();
|
|
491
680
|
this.updateIdentities(allAccounts);
|
|
492
681
|
return {
|
|
493
682
|
keyringState: __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this),
|
|
@@ -504,7 +693,21 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
504
693
|
*/
|
|
505
694
|
removeAccount(address) {
|
|
506
695
|
return __awaiter(this, void 0, void 0, function* () {
|
|
507
|
-
yield
|
|
696
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
697
|
+
// Not all the keyrings support this, so we have to check
|
|
698
|
+
if (!keyring.removeAccount) {
|
|
699
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedRemoveAccount);
|
|
700
|
+
}
|
|
701
|
+
// The `removeAccount` method of snaps keyring is async. We have to update
|
|
702
|
+
// the interface of the other keyrings to be async as well.
|
|
703
|
+
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
704
|
+
yield keyring.removeAccount(address);
|
|
705
|
+
const accounts = yield keyring.getAccounts();
|
|
706
|
+
// Check if this was the last/only account
|
|
707
|
+
if (accounts.length === 0) {
|
|
708
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_removeEmptyKeyrings).call(this);
|
|
709
|
+
}
|
|
710
|
+
yield this.persistAllKeyrings();
|
|
508
711
|
this.messagingSystem.publish(`${name}:accountRemoved`, address);
|
|
509
712
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
510
713
|
});
|
|
@@ -517,7 +720,13 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
517
720
|
setLocked() {
|
|
518
721
|
return __awaiter(this, void 0, void 0, function* () {
|
|
519
722
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unsubscribeFromQRKeyringsEvents).call(this);
|
|
520
|
-
|
|
723
|
+
__classPrivateFieldSet(this, _KeyringController_password, undefined, "f");
|
|
724
|
+
this.update((state) => {
|
|
725
|
+
state.isUnlocked = false;
|
|
726
|
+
state.keyrings = [];
|
|
727
|
+
});
|
|
728
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
729
|
+
this.messagingSystem.publish(`${name}:lock`);
|
|
521
730
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
522
731
|
});
|
|
523
732
|
}
|
|
@@ -528,10 +737,17 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
528
737
|
* @returns Promise resolving to a signed message string.
|
|
529
738
|
*/
|
|
530
739
|
signMessage(messageParams) {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
740
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
741
|
+
if (!messageParams.data) {
|
|
742
|
+
throw new Error("Can't sign an empty message");
|
|
743
|
+
}
|
|
744
|
+
const address = (0, eth_sig_util_1.normalize)(messageParams.from);
|
|
745
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
746
|
+
if (!keyring.signMessage) {
|
|
747
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedSignMessage);
|
|
748
|
+
}
|
|
749
|
+
return yield keyring.signMessage(address, messageParams.data);
|
|
750
|
+
});
|
|
535
751
|
}
|
|
536
752
|
/**
|
|
537
753
|
* Signs personal message by calling down into a specific keyring.
|
|
@@ -540,7 +756,15 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
540
756
|
* @returns Promise resolving to a signed message string.
|
|
541
757
|
*/
|
|
542
758
|
signPersonalMessage(messageParams) {
|
|
543
|
-
return
|
|
759
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
760
|
+
const address = (0, eth_sig_util_1.normalize)(messageParams.from);
|
|
761
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
762
|
+
if (!keyring.signPersonalMessage) {
|
|
763
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedSignPersonalMessage);
|
|
764
|
+
}
|
|
765
|
+
const normalizedData = (0, eth_sig_util_1.normalize)(messageParams.data);
|
|
766
|
+
return yield keyring.signPersonalMessage(address, normalizedData);
|
|
767
|
+
});
|
|
544
768
|
}
|
|
545
769
|
/**
|
|
546
770
|
* Signs typed message by calling down into a specific keyring.
|
|
@@ -560,13 +784,17 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
560
784
|
].includes(version)) {
|
|
561
785
|
throw new Error(`Unexpected signTypedMessage version: '${version}'`);
|
|
562
786
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
}
|
|
787
|
+
// Cast to `Hex` here is safe here because `messageParams.from` is not nullish.
|
|
788
|
+
// `normalize` returns `Hex` unless given a nullish value.
|
|
789
|
+
const address = (0, eth_sig_util_1.normalize)(messageParams.from);
|
|
790
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
791
|
+
if (!keyring.signTypedData) {
|
|
792
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedSignTypedMessage);
|
|
793
|
+
}
|
|
794
|
+
return yield keyring.signTypedData(address, version !== SignTypedDataVersion.V1 &&
|
|
795
|
+
typeof messageParams.data === 'string'
|
|
796
|
+
? JSON.parse(messageParams.data)
|
|
797
|
+
: messageParams.data, { version });
|
|
570
798
|
}
|
|
571
799
|
catch (error) {
|
|
572
800
|
throw new Error(`Keyring Controller signTypedMessage: ${error}`);
|
|
@@ -582,7 +810,66 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
582
810
|
* @returns Promise resolving to a signed transaction string.
|
|
583
811
|
*/
|
|
584
812
|
signTransaction(transaction, from, opts) {
|
|
585
|
-
return
|
|
813
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
814
|
+
const address = (0, eth_sig_util_1.normalize)(from);
|
|
815
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
816
|
+
if (!keyring.signTransaction) {
|
|
817
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedSignTransaction);
|
|
818
|
+
}
|
|
819
|
+
return yield keyring.signTransaction(address, transaction, opts);
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Convert a base transaction to a base UserOperation.
|
|
824
|
+
*
|
|
825
|
+
* @param from - Address of the sender.
|
|
826
|
+
* @param transactions - Base transactions to include in the UserOperation.
|
|
827
|
+
* @returns A pseudo-UserOperation that can be used to construct a real.
|
|
828
|
+
*/
|
|
829
|
+
prepareUserOperation(from, transactions) {
|
|
830
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
831
|
+
const address = (0, eth_sig_util_1.normalize)(from);
|
|
832
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
833
|
+
if (!keyring.prepareUserOperation) {
|
|
834
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedPrepareUserOperation);
|
|
835
|
+
}
|
|
836
|
+
return yield keyring.prepareUserOperation(address, transactions);
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* Patches properties of a UserOperation. Currently, only the
|
|
841
|
+
* `paymasterAndData` can be patched.
|
|
842
|
+
*
|
|
843
|
+
* @param from - Address of the sender.
|
|
844
|
+
* @param userOp - UserOperation to patch.
|
|
845
|
+
* @returns A patch to apply to the UserOperation.
|
|
846
|
+
*/
|
|
847
|
+
patchUserOperation(from, userOp) {
|
|
848
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
849
|
+
const address = (0, eth_sig_util_1.normalize)(from);
|
|
850
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
851
|
+
if (!keyring.patchUserOperation) {
|
|
852
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedPatchUserOperation);
|
|
853
|
+
}
|
|
854
|
+
return yield keyring.patchUserOperation(address, userOp);
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Signs an UserOperation.
|
|
859
|
+
*
|
|
860
|
+
* @param from - Address of the sender.
|
|
861
|
+
* @param userOp - UserOperation to sign.
|
|
862
|
+
* @returns The signature of the UserOperation.
|
|
863
|
+
*/
|
|
864
|
+
signUserOperation(from, userOp) {
|
|
865
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
866
|
+
const address = (0, eth_sig_util_1.normalize)(from);
|
|
867
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
868
|
+
if (!keyring.signUserOperation) {
|
|
869
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedSignUserOperation);
|
|
870
|
+
}
|
|
871
|
+
return yield keyring.signUserOperation(address, userOp);
|
|
872
|
+
});
|
|
586
873
|
}
|
|
587
874
|
/**
|
|
588
875
|
* Attempts to decrypt the current vault and load its keyrings,
|
|
@@ -594,7 +881,8 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
594
881
|
*/
|
|
595
882
|
submitEncryptionKey(encryptionKey, encryptionSalt) {
|
|
596
883
|
return __awaiter(this, void 0, void 0, function* () {
|
|
597
|
-
yield __classPrivateFieldGet(this,
|
|
884
|
+
__classPrivateFieldSet(this, _KeyringController_keyrings, yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, undefined, encryptionKey, encryptionSalt), "f");
|
|
885
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
598
886
|
const qrKeyring = this.getQRKeyring();
|
|
599
887
|
if (qrKeyring) {
|
|
600
888
|
// if there is a QR keyring, we need to subscribe
|
|
@@ -613,8 +901,9 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
613
901
|
*/
|
|
614
902
|
submitPassword(password) {
|
|
615
903
|
return __awaiter(this, void 0, void 0, function* () {
|
|
616
|
-
yield __classPrivateFieldGet(this,
|
|
617
|
-
|
|
904
|
+
__classPrivateFieldSet(this, _KeyringController_keyrings, yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, password), "f");
|
|
905
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
906
|
+
const accounts = yield this.getAccounts();
|
|
618
907
|
const qrKeyring = this.getQRKeyring();
|
|
619
908
|
if (qrKeyring) {
|
|
620
909
|
// if there is a QR keyring, we need to subscribe
|
|
@@ -632,8 +921,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
632
921
|
*/
|
|
633
922
|
verifySeedPhrase() {
|
|
634
923
|
return __awaiter(this, void 0, void 0, function* () {
|
|
635
|
-
const primaryKeyring =
|
|
636
|
-
/* istanbul ignore if */
|
|
924
|
+
const primaryKeyring = this.getKeyringsByType(KeyringTypes.hd)[0];
|
|
637
925
|
if (!primaryKeyring) {
|
|
638
926
|
throw new Error('No HD keyring found.');
|
|
639
927
|
}
|
|
@@ -646,11 +934,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
646
934
|
}
|
|
647
935
|
// The HD Keyring Builder is a default keyring builder
|
|
648
936
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
649
|
-
const hdKeyringBuilder = __classPrivateFieldGet(this,
|
|
937
|
+
const hdKeyringBuilder = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringBuilderForType).call(this, KeyringTypes.hd);
|
|
650
938
|
const hdKeyring = hdKeyringBuilder();
|
|
651
939
|
// @ts-expect-error @metamask/eth-hd-keyring correctly handles
|
|
652
940
|
// Uint8Array seed phrases in the `deserialize` method.
|
|
653
|
-
hdKeyring.deserialize({
|
|
941
|
+
yield hdKeyring.deserialize({
|
|
654
942
|
mnemonic: seedWords,
|
|
655
943
|
numberOfAccounts: accounts.length,
|
|
656
944
|
});
|
|
@@ -676,7 +964,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
676
964
|
*/
|
|
677
965
|
getQRKeyring() {
|
|
678
966
|
// QRKeyring is not yet compatible with Keyring type from @metamask/utils
|
|
679
|
-
return
|
|
967
|
+
return this.getKeyringsByType(KeyringTypes.qr)[0];
|
|
680
968
|
}
|
|
681
969
|
/**
|
|
682
970
|
* Get QR hardware keyring. If it doesn't exist, add it.
|
|
@@ -693,8 +981,8 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
693
981
|
restoreQRKeyring(serialized) {
|
|
694
982
|
return __awaiter(this, void 0, void 0, function* () {
|
|
695
983
|
(yield this.getOrAddQRKeyring()).deserialize(serialized);
|
|
696
|
-
yield
|
|
697
|
-
this.updateIdentities(yield
|
|
984
|
+
yield this.persistAllKeyrings();
|
|
985
|
+
this.updateIdentities(yield this.getAccounts());
|
|
698
986
|
});
|
|
699
987
|
}
|
|
700
988
|
resetQRKeyringState() {
|
|
@@ -768,13 +1056,13 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
768
1056
|
return __awaiter(this, void 0, void 0, function* () {
|
|
769
1057
|
const keyring = yield this.getOrAddQRKeyring();
|
|
770
1058
|
keyring.setAccountToUnlock(index);
|
|
771
|
-
const oldAccounts = yield
|
|
1059
|
+
const oldAccounts = yield this.getAccounts();
|
|
772
1060
|
// QRKeyring is not yet compatible with Keyring from
|
|
773
1061
|
// @metamask/utils, but we can use the `addNewAccount` method
|
|
774
1062
|
// as it internally calls `addAccounts` from on the keyring instance,
|
|
775
1063
|
// which is supported by QRKeyring API.
|
|
776
|
-
yield
|
|
777
|
-
const newAccounts = yield
|
|
1064
|
+
yield this.addNewAccountForKeyring(keyring);
|
|
1065
|
+
const newAccounts = yield this.getAccounts();
|
|
778
1066
|
this.updateIdentities(newAccounts);
|
|
779
1067
|
newAccounts.forEach((address) => {
|
|
780
1068
|
if (!oldAccounts.includes(address)) {
|
|
@@ -784,29 +1072,30 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
784
1072
|
this.setSelectedAddress(address);
|
|
785
1073
|
}
|
|
786
1074
|
});
|
|
787
|
-
yield
|
|
1075
|
+
yield this.persistAllKeyrings();
|
|
788
1076
|
});
|
|
789
1077
|
}
|
|
790
1078
|
getAccountKeyringType(account) {
|
|
791
1079
|
return __awaiter(this, void 0, void 0, function* () {
|
|
792
|
-
|
|
1080
|
+
const keyring = (yield this.getKeyringForAccount(account));
|
|
1081
|
+
return keyring.type;
|
|
793
1082
|
});
|
|
794
1083
|
}
|
|
795
1084
|
forgetQRDevice() {
|
|
796
1085
|
return __awaiter(this, void 0, void 0, function* () {
|
|
797
1086
|
const keyring = yield this.getOrAddQRKeyring();
|
|
798
|
-
const allAccounts = (yield
|
|
1087
|
+
const allAccounts = (yield this.getAccounts());
|
|
799
1088
|
keyring.forgetDevice();
|
|
800
|
-
const remainingAccounts = (yield
|
|
1089
|
+
const remainingAccounts = (yield this.getAccounts());
|
|
801
1090
|
const removedAccounts = allAccounts.filter((address) => !remainingAccounts.includes(address));
|
|
802
1091
|
this.updateIdentities(remainingAccounts);
|
|
803
|
-
yield
|
|
1092
|
+
yield this.persistAllKeyrings();
|
|
804
1093
|
return { removedAccounts, remainingAccounts };
|
|
805
1094
|
});
|
|
806
1095
|
}
|
|
807
1096
|
}
|
|
808
1097
|
exports.KeyringController = KeyringController;
|
|
809
|
-
|
|
1098
|
+
_KeyringController_keyringBuilders = new WeakMap(), _KeyringController_keyrings = new WeakMap(), _KeyringController_unsupportedKeyrings = new WeakMap(), _KeyringController_password = new WeakMap(), _KeyringController_encryptor = new WeakMap(), _KeyringController_cacheEncryptionKey = new WeakMap(), _KeyringController_qrKeyringStateListener = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
|
|
810
1099
|
this.messagingSystem.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
|
|
811
1100
|
this.messagingSystem.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
|
|
812
1101
|
this.messagingSystem.registerActionHandler(`${name}:signTypedMessage`, this.signTypedMessage.bind(this));
|
|
@@ -816,10 +1105,21 @@ _KeyringController_keyring = new WeakMap(), _KeyringController_qrKeyringStateLis
|
|
|
816
1105
|
this.messagingSystem.registerActionHandler(`${name}:getKeyringsByType`, this.getKeyringsByType.bind(this));
|
|
817
1106
|
this.messagingSystem.registerActionHandler(`${name}:getKeyringForAccount`, this.getKeyringForAccount.bind(this));
|
|
818
1107
|
this.messagingSystem.registerActionHandler(`${name}:persistAllKeyrings`, this.persistAllKeyrings.bind(this));
|
|
1108
|
+
this.messagingSystem.registerActionHandler(`${name}:prepareUserOperation`, this.prepareUserOperation.bind(this));
|
|
1109
|
+
this.messagingSystem.registerActionHandler(`${name}:patchUserOperation`, this.patchUserOperation.bind(this));
|
|
1110
|
+
this.messagingSystem.registerActionHandler(`${name}:signUserOperation`, this.signUserOperation.bind(this));
|
|
1111
|
+
}, _KeyringController_getKeyringBuilderForType = function _KeyringController_getKeyringBuilderForType(type) {
|
|
1112
|
+
return __classPrivateFieldGet(this, _KeyringController_keyringBuilders, "f").find((keyringBuilder) => keyringBuilder.type === type);
|
|
819
1113
|
}, _KeyringController_addQRKeyring = function _KeyringController_addQRKeyring() {
|
|
820
1114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
821
1115
|
// QRKeyring is not yet compatible with Keyring type from @metamask/utils
|
|
822
|
-
const qrKeyring = (yield __classPrivateFieldGet(this,
|
|
1116
|
+
const qrKeyring = (yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, KeyringTypes.qr, {
|
|
1117
|
+
accounts: [],
|
|
1118
|
+
}));
|
|
1119
|
+
const accounts = yield qrKeyring.getAccounts();
|
|
1120
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_checkForDuplicate).call(this, KeyringTypes.qr, accounts);
|
|
1121
|
+
__classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(qrKeyring);
|
|
1122
|
+
yield this.persistAllKeyrings();
|
|
823
1123
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_subscribeToQRKeyringEvents).call(this, qrKeyring);
|
|
824
1124
|
return qrKeyring;
|
|
825
1125
|
});
|
|
@@ -829,25 +1129,182 @@ _KeyringController_keyring = new WeakMap(), _KeyringController_qrKeyringStateLis
|
|
|
829
1129
|
}, "f");
|
|
830
1130
|
qrKeyring.getMemStore().subscribe(__classPrivateFieldGet(this, _KeyringController_qrKeyringStateListener, "f"));
|
|
831
1131
|
}, _KeyringController_unsubscribeFromQRKeyringsEvents = function _KeyringController_unsubscribeFromQRKeyringsEvents() {
|
|
832
|
-
const qrKeyrings =
|
|
1132
|
+
const qrKeyrings = this.getKeyringsByType(KeyringTypes.qr);
|
|
833
1133
|
qrKeyrings.forEach((qrKeyring) => {
|
|
834
1134
|
if (__classPrivateFieldGet(this, _KeyringController_qrKeyringStateListener, "f")) {
|
|
835
1135
|
qrKeyring.getMemStore().unsubscribe(__classPrivateFieldGet(this, _KeyringController_qrKeyringStateListener, "f"));
|
|
836
1136
|
}
|
|
837
1137
|
});
|
|
838
|
-
},
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
|
|
1138
|
+
}, _KeyringController_createNewVaultWithKeyring = function _KeyringController_createNewVaultWithKeyring(password, keyring) {
|
|
1139
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1140
|
+
if (typeof password !== 'string') {
|
|
1141
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
1142
|
+
}
|
|
1143
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1144
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
1145
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
|
|
1146
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
1147
|
+
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
1148
|
+
});
|
|
1149
|
+
}, _KeyringController_updateKeyringsInState = function _KeyringController_updateKeyringsInState() {
|
|
1150
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1151
|
+
const keyrings = yield Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(displayForKeyring));
|
|
1152
|
+
this.update((state) => {
|
|
1153
|
+
state.keyrings = keyrings;
|
|
1154
|
+
});
|
|
1155
|
+
});
|
|
1156
|
+
}, _KeyringController_unlockKeyrings = function _KeyringController_unlockKeyrings(password, encryptionKey, encryptionSalt) {
|
|
1157
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1158
|
+
const encryptedVault = this.state.vault;
|
|
1159
|
+
if (!encryptedVault) {
|
|
1160
|
+
throw new Error(constants_1.KeyringControllerError.VaultError);
|
|
1161
|
+
}
|
|
1162
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
1163
|
+
let vault;
|
|
1164
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
1165
|
+
assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
|
|
1166
|
+
if (password) {
|
|
1167
|
+
const result = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, encryptedVault);
|
|
1168
|
+
vault = result.vault;
|
|
1169
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1170
|
+
this.update((state) => {
|
|
1171
|
+
state.encryptionKey = result.exportedKeyString;
|
|
1172
|
+
state.encryptionSalt = result.salt;
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
else {
|
|
1176
|
+
const parsedEncryptedVault = JSON.parse(encryptedVault);
|
|
1177
|
+
if (encryptionSalt !== parsedEncryptedVault.salt) {
|
|
1178
|
+
throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
|
|
1179
|
+
}
|
|
1180
|
+
if (typeof encryptionKey !== 'string') {
|
|
1181
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
1182
|
+
}
|
|
1183
|
+
const key = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
1184
|
+
vault = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
|
|
1185
|
+
// This call is required on the first call because encryptionKey
|
|
1186
|
+
// is not yet inside the memStore
|
|
1187
|
+
this.update((state) => {
|
|
1188
|
+
state.encryptionKey = encryptionKey;
|
|
1189
|
+
// we can safely assume that encryptionSalt is defined here
|
|
1190
|
+
// because we compare it with the salt from the vault
|
|
1191
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1192
|
+
state.encryptionSalt = encryptionSalt;
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
else {
|
|
1197
|
+
if (typeof password !== 'string') {
|
|
1198
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
1199
|
+
}
|
|
1200
|
+
vault = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, encryptedVault);
|
|
1201
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1202
|
+
}
|
|
1203
|
+
if (!isSerializedKeyringsArray(vault)) {
|
|
1204
|
+
throw new Error(constants_1.KeyringControllerError.VaultDataError);
|
|
1205
|
+
}
|
|
1206
|
+
yield Promise.all(vault.map(__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).bind(this)));
|
|
1207
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateKeyringsInState).call(this);
|
|
1208
|
+
if (__classPrivateFieldGet(this, _KeyringController_password, "f") &&
|
|
1209
|
+
(!__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f") || !encryptionKey) &&
|
|
1210
|
+
__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated &&
|
|
1211
|
+
!__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(encryptedVault)) {
|
|
1212
|
+
// Re-encrypt the vault with safer method if one is available
|
|
1213
|
+
yield this.persistAllKeyrings();
|
|
1214
|
+
}
|
|
1215
|
+
return __classPrivateFieldGet(this, _KeyringController_keyrings, "f");
|
|
1216
|
+
});
|
|
1217
|
+
}, _KeyringController_createKeyringWithFirstAccount = function _KeyringController_createKeyringWithFirstAccount(type, opts) {
|
|
1218
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1219
|
+
const keyring = (yield this.addNewKeyring(type, opts));
|
|
1220
|
+
const [firstAccount] = yield keyring.getAccounts();
|
|
1221
|
+
if (!firstAccount) {
|
|
1222
|
+
throw new Error(constants_1.KeyringControllerError.NoFirstAccount);
|
|
1223
|
+
}
|
|
1224
|
+
});
|
|
1225
|
+
}, _KeyringController_newKeyring = function _KeyringController_newKeyring(type, data) {
|
|
1226
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1227
|
+
const keyringBuilder = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringBuilderForType).call(this, type);
|
|
1228
|
+
if (!keyringBuilder) {
|
|
1229
|
+
throw new Error(`${constants_1.KeyringControllerError.NoKeyringBuilder}. Keyring type: ${type}`);
|
|
1230
|
+
}
|
|
1231
|
+
const keyring = keyringBuilder();
|
|
1232
|
+
// @ts-expect-error Enforce data type after updating clients
|
|
1233
|
+
yield keyring.deserialize(data);
|
|
1234
|
+
if (keyring.init) {
|
|
1235
|
+
yield keyring.init();
|
|
1236
|
+
}
|
|
1237
|
+
return keyring;
|
|
1238
|
+
});
|
|
1239
|
+
}, _KeyringController_clearKeyrings = function _KeyringController_clearKeyrings() {
|
|
1240
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1241
|
+
for (const keyring of __classPrivateFieldGet(this, _KeyringController_keyrings, "f")) {
|
|
1242
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring);
|
|
1243
|
+
}
|
|
1244
|
+
__classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
|
|
1245
|
+
this.update((state) => {
|
|
1246
|
+
state.keyrings = [];
|
|
1247
|
+
});
|
|
1248
|
+
});
|
|
1249
|
+
}, _KeyringController_restoreKeyring = function _KeyringController_restoreKeyring(serialized) {
|
|
1250
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1251
|
+
try {
|
|
1252
|
+
const { type, data } = serialized;
|
|
1253
|
+
const keyring = yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, data);
|
|
1254
|
+
// getAccounts also validates the accounts for some keyrings
|
|
1255
|
+
yield keyring.getAccounts();
|
|
1256
|
+
__classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(keyring);
|
|
1257
|
+
return keyring;
|
|
1258
|
+
}
|
|
1259
|
+
catch (_) {
|
|
1260
|
+
__classPrivateFieldGet(this, _KeyringController_unsupportedKeyrings, "f").push(serialized);
|
|
1261
|
+
return undefined;
|
|
1262
|
+
}
|
|
1263
|
+
});
|
|
1264
|
+
}, _KeyringController_destroyKeyring = function _KeyringController_destroyKeyring(keyring) {
|
|
1265
|
+
var _a;
|
|
1266
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1267
|
+
yield ((_a = keyring.destroy) === null || _a === void 0 ? void 0 : _a.call(keyring));
|
|
1268
|
+
});
|
|
1269
|
+
}, _KeyringController_removeEmptyKeyrings = function _KeyringController_removeEmptyKeyrings() {
|
|
1270
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1271
|
+
const validKeyrings = [];
|
|
1272
|
+
// Since getAccounts returns a Promise
|
|
1273
|
+
// We need to wait to hear back form each keyring
|
|
1274
|
+
// in order to decide which ones are now valid (accounts.length > 0)
|
|
1275
|
+
yield Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map((keyring) => __awaiter(this, void 0, void 0, function* () {
|
|
1276
|
+
const accounts = yield keyring.getAccounts();
|
|
1277
|
+
if (accounts.length > 0) {
|
|
1278
|
+
validKeyrings.push(keyring);
|
|
1279
|
+
}
|
|
1280
|
+
else {
|
|
1281
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring);
|
|
1282
|
+
}
|
|
1283
|
+
})));
|
|
1284
|
+
__classPrivateFieldSet(this, _KeyringController_keyrings, validKeyrings, "f");
|
|
1285
|
+
});
|
|
1286
|
+
}, _KeyringController_checkForDuplicate = function _KeyringController_checkForDuplicate(type, newAccountArray) {
|
|
1287
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1288
|
+
const accounts = yield this.getAccounts();
|
|
1289
|
+
switch (type) {
|
|
1290
|
+
case KeyringTypes.simple: {
|
|
1291
|
+
const isIncluded = Boolean(accounts.find((key) => newAccountArray[0] &&
|
|
1292
|
+
(key === newAccountArray[0] ||
|
|
1293
|
+
key === (0, utils_1.remove0x)(newAccountArray[0]))));
|
|
1294
|
+
if (isIncluded) {
|
|
1295
|
+
throw new Error(constants_1.KeyringControllerError.DuplicatedAccount);
|
|
1296
|
+
}
|
|
1297
|
+
return newAccountArray;
|
|
1298
|
+
}
|
|
1299
|
+
default: {
|
|
1300
|
+
return newAccountArray;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
});
|
|
1304
|
+
}, _KeyringController_setUnlocked = function _KeyringController_setUnlocked() {
|
|
1305
|
+
this.update((state) => {
|
|
1306
|
+
state.isUnlocked = true;
|
|
1307
|
+
});
|
|
851
1308
|
this.messagingSystem.publish(`${name}:unlock`);
|
|
852
1309
|
}, _KeyringController_getMemState = function _KeyringController_getMemState() {
|
|
853
1310
|
return {
|