@metamask-previews/keyring-controller 12.0.0-preview.d357889 → 12.2.0-preview.0dea691a
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 +156 -12
- package/dist/KeyringController.d.ts.map +1 -1
- package/dist/KeyringController.js +576 -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.isCustodyKeyring = 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,8 +71,17 @@ var KeyringTypes;
|
|
|
64
71
|
KeyringTypes["ledger"] = "Ledger Hardware";
|
|
65
72
|
KeyringTypes["lattice"] = "Lattice Hardware";
|
|
66
73
|
KeyringTypes["snap"] = "Snap Keyring";
|
|
67
|
-
KeyringTypes["custody"] = "Custody";
|
|
68
74
|
})(KeyringTypes = exports.KeyringTypes || (exports.KeyringTypes = {}));
|
|
75
|
+
/**
|
|
76
|
+
* Custody keyring types are a special case, as they are not a single type
|
|
77
|
+
* but they all start with the prefix "Custody".
|
|
78
|
+
* @param keyringType - The type of the keyring.
|
|
79
|
+
* @returns Whether the keyring type is a custody keyring.
|
|
80
|
+
*/
|
|
81
|
+
const isCustodyKeyring = (keyringType) => {
|
|
82
|
+
return keyringType.startsWith('Custody');
|
|
83
|
+
};
|
|
84
|
+
exports.isCustodyKeyring = isCustodyKeyring;
|
|
69
85
|
/**
|
|
70
86
|
* A strategy for importing an account
|
|
71
87
|
*/
|
|
@@ -85,10 +101,31 @@ var SignTypedDataVersion;
|
|
|
85
101
|
SignTypedDataVersion["V3"] = "V3";
|
|
86
102
|
SignTypedDataVersion["V4"] = "V4";
|
|
87
103
|
})(SignTypedDataVersion = exports.SignTypedDataVersion || (exports.SignTypedDataVersion = {}));
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Get builder function for `Keyring`
|
|
106
|
+
*
|
|
107
|
+
* Returns a builder function for `Keyring` with a `type` property.
|
|
108
|
+
*
|
|
109
|
+
* @param KeyringConstructor - The Keyring class for the builder.
|
|
110
|
+
* @returns A builder function for the given Keyring.
|
|
111
|
+
*/
|
|
112
|
+
function keyringBuilderFactory(KeyringConstructor) {
|
|
113
|
+
const builder = () => new KeyringConstructor();
|
|
114
|
+
builder.type = KeyringConstructor.type;
|
|
115
|
+
return builder;
|
|
116
|
+
}
|
|
117
|
+
exports.keyringBuilderFactory = keyringBuilderFactory;
|
|
118
|
+
const defaultKeyringBuilders = [
|
|
119
|
+
keyringBuilderFactory(eth_simple_keyring_1.default),
|
|
120
|
+
keyringBuilderFactory(eth_hd_keyring_1.default),
|
|
121
|
+
];
|
|
122
|
+
const getDefaultKeyringState = () => {
|
|
123
|
+
return {
|
|
124
|
+
isUnlocked: false,
|
|
125
|
+
keyrings: [],
|
|
126
|
+
};
|
|
91
127
|
};
|
|
128
|
+
exports.getDefaultKeyringState = getDefaultKeyringState;
|
|
92
129
|
/**
|
|
93
130
|
* Assert that the given keyring has an exportable
|
|
94
131
|
* mnemonic.
|
|
@@ -101,6 +138,53 @@ function assertHasUint8ArrayMnemonic(keyring) {
|
|
|
101
138
|
throw new Error("Can't get mnemonic bytes from keyring");
|
|
102
139
|
}
|
|
103
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Assert that the provided encryptor supports
|
|
143
|
+
* encryption and encryption key export.
|
|
144
|
+
*
|
|
145
|
+
* @param encryptor - The encryptor to check.
|
|
146
|
+
* @throws If the encryptor does not support key encryption.
|
|
147
|
+
*/
|
|
148
|
+
function assertIsExportableKeyEncryptor(encryptor) {
|
|
149
|
+
if (!('importKey' in encryptor &&
|
|
150
|
+
typeof encryptor.importKey === 'function' &&
|
|
151
|
+
'decryptWithKey' in encryptor &&
|
|
152
|
+
typeof encryptor.decryptWithKey === 'function' &&
|
|
153
|
+
'encryptWithKey' in encryptor &&
|
|
154
|
+
typeof encryptor.encryptWithKey === 'function')) {
|
|
155
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedEncryptionKeyExport);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Checks if the provided value is a serialized keyrings array.
|
|
160
|
+
*
|
|
161
|
+
* @param array - The value to check.
|
|
162
|
+
* @returns True if the value is a serialized keyrings array.
|
|
163
|
+
*/
|
|
164
|
+
function isSerializedKeyringsArray(array) {
|
|
165
|
+
return (typeof array === 'object' &&
|
|
166
|
+
Array.isArray(array) &&
|
|
167
|
+
array.every((value) => value.type && (0, utils_1.isValidJson)(value.data)));
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Display For Keyring
|
|
171
|
+
*
|
|
172
|
+
* Is used for adding the current keyrings to the state object.
|
|
173
|
+
*
|
|
174
|
+
* @param keyring - The keyring to display.
|
|
175
|
+
* @returns A keyring display object, with type and accounts properties.
|
|
176
|
+
*/
|
|
177
|
+
function displayForKeyring(keyring) {
|
|
178
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
const accounts = yield keyring.getAccounts();
|
|
180
|
+
return {
|
|
181
|
+
type: keyring.type,
|
|
182
|
+
// Cast to `Hex[]` here is safe here because `accounts` has no nullish
|
|
183
|
+
// values, and `normalize` returns `Hex` unless given a nullish value
|
|
184
|
+
accounts: accounts.map(eth_sig_util_1.normalize),
|
|
185
|
+
};
|
|
186
|
+
});
|
|
187
|
+
}
|
|
104
188
|
/**
|
|
105
189
|
* Controller responsible for establishing and managing user identity.
|
|
106
190
|
*
|
|
@@ -126,8 +210,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
126
210
|
* @param options.state - Initial state to set on this controller.
|
|
127
211
|
*/
|
|
128
212
|
constructor(options) {
|
|
129
|
-
|
|
130
|
-
const { syncIdentities, updateIdentities, setSelectedAddress, setAccountLabel, keyringBuilders, messenger, state, } = options;
|
|
213
|
+
const { syncIdentities, updateIdentities, setSelectedAddress, setAccountLabel, encryptor = encryptorUtils, keyringBuilders, messenger, state, } = options;
|
|
131
214
|
super({
|
|
132
215
|
name,
|
|
133
216
|
metadata: {
|
|
@@ -138,32 +221,29 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
138
221
|
encryptionSalt: { persist: false, anonymous: false },
|
|
139
222
|
},
|
|
140
223
|
messenger,
|
|
141
|
-
state: Object.assign(Object.assign({},
|
|
224
|
+
state: Object.assign(Object.assign({}, (0, exports.getDefaultKeyringState)()), state),
|
|
142
225
|
});
|
|
143
226
|
_KeyringController_instances.add(this);
|
|
144
227
|
this.mutex = new async_mutex_1.Mutex();
|
|
145
|
-
|
|
228
|
+
_KeyringController_keyringBuilders.set(this, void 0);
|
|
229
|
+
_KeyringController_keyrings.set(this, void 0);
|
|
230
|
+
_KeyringController_unsupportedKeyrings.set(this, void 0);
|
|
231
|
+
_KeyringController_password.set(this, void 0);
|
|
232
|
+
_KeyringController_encryptor.set(this, void 0);
|
|
233
|
+
_KeyringController_cacheEncryptionKey.set(this, void 0);
|
|
146
234
|
_KeyringController_qrKeyringStateListener.set(this, void 0);
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
235
|
+
__classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
|
|
236
|
+
? defaultKeyringBuilders.concat(keyringBuilders)
|
|
237
|
+
: defaultKeyringBuilders, "f");
|
|
238
|
+
__classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
|
|
239
|
+
__classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
|
|
240
|
+
__classPrivateFieldSet(this, _KeyringController_unsupportedKeyrings, [], "f");
|
|
241
|
+
// This option allows the controller to cache an exported key
|
|
242
|
+
// for use in decrypting and encrypting data without password
|
|
243
|
+
__classPrivateFieldSet(this, _KeyringController_cacheEncryptionKey, Boolean(options.cacheEncryptionKey), "f");
|
|
244
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
245
|
+
assertIsExportableKeyEncryptor(encryptor);
|
|
154
246
|
}
|
|
155
|
-
else {
|
|
156
|
-
__classPrivateFieldSet(this, _KeyringController_keyring, new eth_keyring_controller_1.KeyringController({
|
|
157
|
-
initState: state,
|
|
158
|
-
encryptor: options.encryptor,
|
|
159
|
-
keyringBuilders,
|
|
160
|
-
cacheEncryptionKey: (_a = options.cacheEncryptionKey) !== null && _a !== void 0 ? _a : false,
|
|
161
|
-
}), "f");
|
|
162
|
-
}
|
|
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
247
|
this.syncIdentities = syncIdentities;
|
|
168
248
|
this.updateIdentities = updateIdentities;
|
|
169
249
|
this.setSelectedAddress = setSelectedAddress;
|
|
@@ -180,12 +260,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
180
260
|
*/
|
|
181
261
|
addNewAccount(accountCount) {
|
|
182
262
|
return __awaiter(this, void 0, void 0, function* () {
|
|
183
|
-
const primaryKeyring =
|
|
184
|
-
/* istanbul ignore if */
|
|
263
|
+
const primaryKeyring = this.getKeyringsByType('HD Key Tree')[0];
|
|
185
264
|
if (!primaryKeyring) {
|
|
186
265
|
throw new Error('No HD keyring found');
|
|
187
266
|
}
|
|
188
|
-
const oldAccounts = yield
|
|
267
|
+
const oldAccounts = yield this.getAccounts();
|
|
189
268
|
if (accountCount && oldAccounts.length !== accountCount) {
|
|
190
269
|
if (accountCount > oldAccounts.length) {
|
|
191
270
|
throw new Error('Account out of sequence');
|
|
@@ -197,12 +276,9 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
197
276
|
addedAccountAddress: primaryKeyringAccounts[accountCount],
|
|
198
277
|
};
|
|
199
278
|
}
|
|
200
|
-
yield
|
|
201
|
-
const newAccounts = yield __classPrivateFieldGet(this, _KeyringController_keyring, "f").getAccounts();
|
|
279
|
+
const addedAccountAddress = yield this.addNewAccountForKeyring(primaryKeyring);
|
|
202
280
|
yield this.verifySeedPhrase();
|
|
203
|
-
this.updateIdentities(
|
|
204
|
-
const addedAccountAddress = newAccounts.find((selectedAddress) => !oldAccounts.includes(selectedAddress));
|
|
205
|
-
(0, utils_1.assertIsStrictHexString)(addedAccountAddress);
|
|
281
|
+
this.updateIdentities(yield this.getAccounts());
|
|
206
282
|
return {
|
|
207
283
|
keyringState: __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this),
|
|
208
284
|
addedAccountAddress,
|
|
@@ -227,10 +303,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
227
303
|
(0, utils_1.assertIsStrictHexString)(existingAccount);
|
|
228
304
|
return existingAccount;
|
|
229
305
|
}
|
|
230
|
-
yield
|
|
306
|
+
yield keyring.addAccounts(1);
|
|
307
|
+
yield this.persistAllKeyrings();
|
|
231
308
|
const addedAccountAddress = (yield this.getAccounts()).find((selectedAddress) => !oldAccounts.includes(selectedAddress));
|
|
232
309
|
(0, utils_1.assertIsStrictHexString)(addedAccountAddress);
|
|
233
|
-
this.updateIdentities(yield
|
|
310
|
+
this.updateIdentities(yield this.getAccounts());
|
|
234
311
|
return addedAccountAddress;
|
|
235
312
|
});
|
|
236
313
|
}
|
|
@@ -241,12 +318,12 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
241
318
|
*/
|
|
242
319
|
addNewAccountWithoutUpdate() {
|
|
243
320
|
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
-
const primaryKeyring =
|
|
245
|
-
/* istanbul ignore if */
|
|
321
|
+
const primaryKeyring = this.getKeyringsByType('HD Key Tree')[0];
|
|
246
322
|
if (!primaryKeyring) {
|
|
247
323
|
throw new Error('No HD keyring found');
|
|
248
324
|
}
|
|
249
|
-
yield
|
|
325
|
+
yield primaryKeyring.addAccounts(1);
|
|
326
|
+
yield this.persistAllKeyrings();
|
|
250
327
|
yield this.verifySeedPhrase();
|
|
251
328
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
252
329
|
});
|
|
@@ -268,8 +345,14 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
268
345
|
}
|
|
269
346
|
try {
|
|
270
347
|
this.updateIdentities([]);
|
|
271
|
-
yield __classPrivateFieldGet(this,
|
|
272
|
-
|
|
348
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
|
|
349
|
+
type: KeyringTypes.hd,
|
|
350
|
+
opts: {
|
|
351
|
+
mnemonic: seed,
|
|
352
|
+
numberOfAccounts: 1,
|
|
353
|
+
},
|
|
354
|
+
});
|
|
355
|
+
this.updateIdentities(yield this.getAccounts());
|
|
273
356
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
274
357
|
}
|
|
275
358
|
finally {
|
|
@@ -289,7 +372,9 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
289
372
|
try {
|
|
290
373
|
const accounts = yield this.getAccounts();
|
|
291
374
|
if (!accounts.length) {
|
|
292
|
-
yield __classPrivateFieldGet(this,
|
|
375
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
|
|
376
|
+
type: KeyringTypes.hd,
|
|
377
|
+
});
|
|
293
378
|
this.updateIdentities(yield this.getAccounts());
|
|
294
379
|
}
|
|
295
380
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
@@ -312,7 +397,19 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
312
397
|
if (type === KeyringTypes.qr) {
|
|
313
398
|
return this.getOrAddQRKeyring();
|
|
314
399
|
}
|
|
315
|
-
|
|
400
|
+
const keyring = yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts);
|
|
401
|
+
if (type === KeyringTypes.hd && (!(0, utils_1.isObject)(opts) || !opts.mnemonic)) {
|
|
402
|
+
if (!keyring.generateRandomMnemonic) {
|
|
403
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedGenerateRandomMnemonic);
|
|
404
|
+
}
|
|
405
|
+
keyring.generateRandomMnemonic();
|
|
406
|
+
yield keyring.addAccounts(1);
|
|
407
|
+
}
|
|
408
|
+
const accounts = yield keyring.getAccounts();
|
|
409
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_checkForDuplicate).call(this, type, accounts);
|
|
410
|
+
__classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(keyring);
|
|
411
|
+
yield this.persistAllKeyrings();
|
|
412
|
+
return keyring;
|
|
316
413
|
});
|
|
317
414
|
}
|
|
318
415
|
/**
|
|
@@ -323,7 +420,10 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
323
420
|
*/
|
|
324
421
|
verifyPassword(password) {
|
|
325
422
|
return __awaiter(this, void 0, void 0, function* () {
|
|
326
|
-
|
|
423
|
+
if (!this.state.vault) {
|
|
424
|
+
throw new Error(constants_1.KeyringControllerError.VaultError);
|
|
425
|
+
}
|
|
426
|
+
yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, this.state.vault);
|
|
327
427
|
});
|
|
328
428
|
}
|
|
329
429
|
/**
|
|
@@ -343,8 +443,8 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
343
443
|
exportSeedPhrase(password) {
|
|
344
444
|
return __awaiter(this, void 0, void 0, function* () {
|
|
345
445
|
yield this.verifyPassword(password);
|
|
346
|
-
assertHasUint8ArrayMnemonic(__classPrivateFieldGet(this,
|
|
347
|
-
return __classPrivateFieldGet(this,
|
|
446
|
+
assertHasUint8ArrayMnemonic(__classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0]);
|
|
447
|
+
return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0].mnemonic;
|
|
348
448
|
});
|
|
349
449
|
}
|
|
350
450
|
/**
|
|
@@ -357,7 +457,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
357
457
|
exportAccount(password, address) {
|
|
358
458
|
return __awaiter(this, void 0, void 0, function* () {
|
|
359
459
|
yield this.verifyPassword(password);
|
|
360
|
-
|
|
460
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
461
|
+
if (!keyring.exportAccount) {
|
|
462
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedExportAccount);
|
|
463
|
+
}
|
|
464
|
+
return yield keyring.exportAccount((0, eth_sig_util_1.normalize)(address));
|
|
361
465
|
});
|
|
362
466
|
}
|
|
363
467
|
/**
|
|
@@ -366,7 +470,16 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
366
470
|
* @returns A promise resolving to an array of addresses.
|
|
367
471
|
*/
|
|
368
472
|
getAccounts() {
|
|
369
|
-
return
|
|
473
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
474
|
+
const keyrings = __classPrivateFieldGet(this, _KeyringController_keyrings, "f");
|
|
475
|
+
const keyringArrays = yield Promise.all(keyrings.map((keyring) => __awaiter(this, void 0, void 0, function* () { return keyring.getAccounts(); })));
|
|
476
|
+
const addresses = keyringArrays.reduce((res, arr) => {
|
|
477
|
+
return res.concat(arr);
|
|
478
|
+
}, []);
|
|
479
|
+
// Cast to `Hex[]` here is safe here because `addresses` has no nullish
|
|
480
|
+
// values, and `normalize` returns `Hex` unless given a nullish value
|
|
481
|
+
return addresses.map(eth_sig_util_1.normalize);
|
|
482
|
+
});
|
|
370
483
|
}
|
|
371
484
|
/**
|
|
372
485
|
* Get encryption public key.
|
|
@@ -378,7 +491,12 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
378
491
|
*/
|
|
379
492
|
getEncryptionPublicKey(account, opts) {
|
|
380
493
|
return __awaiter(this, void 0, void 0, function* () {
|
|
381
|
-
|
|
494
|
+
const normalizedAddress = (0, eth_sig_util_1.normalize)(account);
|
|
495
|
+
const keyring = (yield this.getKeyringForAccount(account));
|
|
496
|
+
if (!keyring.getEncryptionPublicKey) {
|
|
497
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedGetEncryptionPublicKey);
|
|
498
|
+
}
|
|
499
|
+
return yield keyring.getEncryptionPublicKey(normalizedAddress, opts);
|
|
382
500
|
});
|
|
383
501
|
}
|
|
384
502
|
/**
|
|
@@ -391,7 +509,12 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
391
509
|
*/
|
|
392
510
|
decryptMessage(messageParams) {
|
|
393
511
|
return __awaiter(this, void 0, void 0, function* () {
|
|
394
|
-
|
|
512
|
+
const address = (0, eth_sig_util_1.normalize)(messageParams.from);
|
|
513
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
514
|
+
if (!keyring.decryptMessage) {
|
|
515
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedDecryptMessage);
|
|
516
|
+
}
|
|
517
|
+
return keyring.decryptMessage(address, messageParams.data);
|
|
395
518
|
});
|
|
396
519
|
}
|
|
397
520
|
/**
|
|
@@ -405,8 +528,33 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
405
528
|
* @returns Promise resolving to keyring of the `account` if one exists.
|
|
406
529
|
*/
|
|
407
530
|
getKeyringForAccount(account) {
|
|
531
|
+
var _a;
|
|
408
532
|
return __awaiter(this, void 0, void 0, function* () {
|
|
409
|
-
|
|
533
|
+
// Cast to `Hex` here is safe here because `address` is not nullish.
|
|
534
|
+
// `normalizeToHex` returns `Hex` unless given a nullish value.
|
|
535
|
+
const hexed = (0, eth_sig_util_1.normalize)(account);
|
|
536
|
+
const candidates = yield Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map((keyring) => __awaiter(this, void 0, void 0, function* () {
|
|
537
|
+
return Promise.all([keyring, keyring.getAccounts()]);
|
|
538
|
+
})));
|
|
539
|
+
const winners = candidates.filter((candidate) => {
|
|
540
|
+
const accounts = candidate[1].map(eth_sig_util_1.normalize);
|
|
541
|
+
return accounts.includes(hexed);
|
|
542
|
+
});
|
|
543
|
+
if (winners.length && ((_a = winners[0]) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
544
|
+
return winners[0][0];
|
|
545
|
+
}
|
|
546
|
+
// Adding more info to the error
|
|
547
|
+
let errorInfo = '';
|
|
548
|
+
if (!(0, utils_1.isValidHexAddress)(hexed)) {
|
|
549
|
+
errorInfo = 'The address passed in is invalid/empty';
|
|
550
|
+
}
|
|
551
|
+
else if (!candidates.length) {
|
|
552
|
+
errorInfo = 'There are no keyrings';
|
|
553
|
+
}
|
|
554
|
+
else if (!winners.length) {
|
|
555
|
+
errorInfo = 'There are keyrings, but none match the address';
|
|
556
|
+
}
|
|
557
|
+
throw new Error(`${constants_1.KeyringControllerError.NoKeyring}. Error info: ${errorInfo}`);
|
|
410
558
|
});
|
|
411
559
|
}
|
|
412
560
|
/**
|
|
@@ -419,7 +567,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
419
567
|
* @returns An array of keyrings of the given type.
|
|
420
568
|
*/
|
|
421
569
|
getKeyringsByType(type) {
|
|
422
|
-
return __classPrivateFieldGet(this,
|
|
570
|
+
return __classPrivateFieldGet(this, _KeyringController_keyrings, "f").filter((keyring) => keyring.type === type);
|
|
423
571
|
}
|
|
424
572
|
/**
|
|
425
573
|
* Persist all serialized keyrings in the vault.
|
|
@@ -429,7 +577,58 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
429
577
|
*/
|
|
430
578
|
persistAllKeyrings() {
|
|
431
579
|
return __awaiter(this, void 0, void 0, function* () {
|
|
432
|
-
|
|
580
|
+
const { encryptionKey, encryptionSalt } = this.state;
|
|
581
|
+
if (!__classPrivateFieldGet(this, _KeyringController_password, "f") && !encryptionKey) {
|
|
582
|
+
throw new Error(constants_1.KeyringControllerError.MissingCredentials);
|
|
583
|
+
}
|
|
584
|
+
const serializedKeyrings = yield Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map((keyring) => __awaiter(this, void 0, void 0, function* () {
|
|
585
|
+
const [type, data] = yield Promise.all([
|
|
586
|
+
keyring.type,
|
|
587
|
+
keyring.serialize(),
|
|
588
|
+
]);
|
|
589
|
+
return { type, data };
|
|
590
|
+
})));
|
|
591
|
+
serializedKeyrings.push(...__classPrivateFieldGet(this, _KeyringController_unsupportedKeyrings, "f"));
|
|
592
|
+
let vault;
|
|
593
|
+
let newEncryptionKey;
|
|
594
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
595
|
+
assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
|
|
596
|
+
if (encryptionKey) {
|
|
597
|
+
const key = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
598
|
+
const vaultJSON = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
|
|
599
|
+
vaultJSON.salt = encryptionSalt;
|
|
600
|
+
vault = JSON.stringify(vaultJSON);
|
|
601
|
+
}
|
|
602
|
+
else if (__classPrivateFieldGet(this, _KeyringController_password, "f")) {
|
|
603
|
+
const { vault: newVault, exportedKeyString } = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithDetail(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
|
|
604
|
+
vault = newVault;
|
|
605
|
+
newEncryptionKey = exportedKeyString;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
if (typeof __classPrivateFieldGet(this, _KeyringController_password, "f") !== 'string') {
|
|
610
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
611
|
+
}
|
|
612
|
+
vault = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encrypt(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
|
|
613
|
+
}
|
|
614
|
+
if (!vault) {
|
|
615
|
+
throw new Error(constants_1.KeyringControllerError.MissingVaultData);
|
|
616
|
+
}
|
|
617
|
+
this.update((state) => {
|
|
618
|
+
state.vault = vault;
|
|
619
|
+
});
|
|
620
|
+
// The keyring updates need to be announced before updating the encryptionKey
|
|
621
|
+
// so that the updated keyring gets propagated to the extension first.
|
|
622
|
+
// Not calling {@link updateKeyringsInState} results in the wrong account being selected
|
|
623
|
+
// in the extension.
|
|
624
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateKeyringsInState).call(this);
|
|
625
|
+
if (newEncryptionKey) {
|
|
626
|
+
this.update((state) => {
|
|
627
|
+
state.encryptionKey = newEncryptionKey;
|
|
628
|
+
state.encryptionSalt = JSON.parse(vault).salt;
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
return true;
|
|
433
632
|
});
|
|
434
633
|
}
|
|
435
634
|
/**
|
|
@@ -461,7 +660,6 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
461
660
|
catch (_a) {
|
|
462
661
|
throw new Error('Cannot import invalid private key.');
|
|
463
662
|
}
|
|
464
|
-
/* istanbul ignore if */
|
|
465
663
|
if (!(0, ethereumjs_util_1.isValidPrivate)(bufferedPrivateKey) ||
|
|
466
664
|
// ensures that the key is 64 bytes long
|
|
467
665
|
(0, ethereumjs_util_1.getBinarySize)(prefixed) !== 64 + '0x'.length) {
|
|
@@ -483,11 +681,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
483
681
|
default:
|
|
484
682
|
throw new Error(`Unexpected import strategy: '${strategy}'`);
|
|
485
683
|
}
|
|
486
|
-
const newKeyring = yield
|
|
684
|
+
const newKeyring = (yield this.addNewKeyring(KeyringTypes.simple, [
|
|
487
685
|
privateKey,
|
|
488
|
-
]);
|
|
686
|
+
]));
|
|
489
687
|
const accounts = yield newKeyring.getAccounts();
|
|
490
|
-
const allAccounts = yield
|
|
688
|
+
const allAccounts = yield this.getAccounts();
|
|
491
689
|
this.updateIdentities(allAccounts);
|
|
492
690
|
return {
|
|
493
691
|
keyringState: __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this),
|
|
@@ -504,7 +702,21 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
504
702
|
*/
|
|
505
703
|
removeAccount(address) {
|
|
506
704
|
return __awaiter(this, void 0, void 0, function* () {
|
|
507
|
-
yield
|
|
705
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
706
|
+
// Not all the keyrings support this, so we have to check
|
|
707
|
+
if (!keyring.removeAccount) {
|
|
708
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedRemoveAccount);
|
|
709
|
+
}
|
|
710
|
+
// The `removeAccount` method of snaps keyring is async. We have to update
|
|
711
|
+
// the interface of the other keyrings to be async as well.
|
|
712
|
+
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
713
|
+
yield keyring.removeAccount(address);
|
|
714
|
+
const accounts = yield keyring.getAccounts();
|
|
715
|
+
// Check if this was the last/only account
|
|
716
|
+
if (accounts.length === 0) {
|
|
717
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_removeEmptyKeyrings).call(this);
|
|
718
|
+
}
|
|
719
|
+
yield this.persistAllKeyrings();
|
|
508
720
|
this.messagingSystem.publish(`${name}:accountRemoved`, address);
|
|
509
721
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
510
722
|
});
|
|
@@ -517,7 +729,13 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
517
729
|
setLocked() {
|
|
518
730
|
return __awaiter(this, void 0, void 0, function* () {
|
|
519
731
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unsubscribeFromQRKeyringsEvents).call(this);
|
|
520
|
-
|
|
732
|
+
__classPrivateFieldSet(this, _KeyringController_password, undefined, "f");
|
|
733
|
+
this.update((state) => {
|
|
734
|
+
state.isUnlocked = false;
|
|
735
|
+
state.keyrings = [];
|
|
736
|
+
});
|
|
737
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
738
|
+
this.messagingSystem.publish(`${name}:lock`);
|
|
521
739
|
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
522
740
|
});
|
|
523
741
|
}
|
|
@@ -528,10 +746,17 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
528
746
|
* @returns Promise resolving to a signed message string.
|
|
529
747
|
*/
|
|
530
748
|
signMessage(messageParams) {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
749
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
750
|
+
if (!messageParams.data) {
|
|
751
|
+
throw new Error("Can't sign an empty message");
|
|
752
|
+
}
|
|
753
|
+
const address = (0, eth_sig_util_1.normalize)(messageParams.from);
|
|
754
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
755
|
+
if (!keyring.signMessage) {
|
|
756
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedSignMessage);
|
|
757
|
+
}
|
|
758
|
+
return yield keyring.signMessage(address, messageParams.data);
|
|
759
|
+
});
|
|
535
760
|
}
|
|
536
761
|
/**
|
|
537
762
|
* Signs personal message by calling down into a specific keyring.
|
|
@@ -540,7 +765,15 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
540
765
|
* @returns Promise resolving to a signed message string.
|
|
541
766
|
*/
|
|
542
767
|
signPersonalMessage(messageParams) {
|
|
543
|
-
return
|
|
768
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
769
|
+
const address = (0, eth_sig_util_1.normalize)(messageParams.from);
|
|
770
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
771
|
+
if (!keyring.signPersonalMessage) {
|
|
772
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedSignPersonalMessage);
|
|
773
|
+
}
|
|
774
|
+
const normalizedData = (0, eth_sig_util_1.normalize)(messageParams.data);
|
|
775
|
+
return yield keyring.signPersonalMessage(address, normalizedData);
|
|
776
|
+
});
|
|
544
777
|
}
|
|
545
778
|
/**
|
|
546
779
|
* Signs typed message by calling down into a specific keyring.
|
|
@@ -560,13 +793,17 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
560
793
|
].includes(version)) {
|
|
561
794
|
throw new Error(`Unexpected signTypedMessage version: '${version}'`);
|
|
562
795
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
}
|
|
796
|
+
// Cast to `Hex` here is safe here because `messageParams.from` is not nullish.
|
|
797
|
+
// `normalize` returns `Hex` unless given a nullish value.
|
|
798
|
+
const address = (0, eth_sig_util_1.normalize)(messageParams.from);
|
|
799
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
800
|
+
if (!keyring.signTypedData) {
|
|
801
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedSignTypedMessage);
|
|
802
|
+
}
|
|
803
|
+
return yield keyring.signTypedData(address, version !== SignTypedDataVersion.V1 &&
|
|
804
|
+
typeof messageParams.data === 'string'
|
|
805
|
+
? JSON.parse(messageParams.data)
|
|
806
|
+
: messageParams.data, { version });
|
|
570
807
|
}
|
|
571
808
|
catch (error) {
|
|
572
809
|
throw new Error(`Keyring Controller signTypedMessage: ${error}`);
|
|
@@ -582,7 +819,66 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
582
819
|
* @returns Promise resolving to a signed transaction string.
|
|
583
820
|
*/
|
|
584
821
|
signTransaction(transaction, from, opts) {
|
|
585
|
-
return
|
|
822
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
823
|
+
const address = (0, eth_sig_util_1.normalize)(from);
|
|
824
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
825
|
+
if (!keyring.signTransaction) {
|
|
826
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedSignTransaction);
|
|
827
|
+
}
|
|
828
|
+
return yield keyring.signTransaction(address, transaction, opts);
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Convert a base transaction to a base UserOperation.
|
|
833
|
+
*
|
|
834
|
+
* @param from - Address of the sender.
|
|
835
|
+
* @param transactions - Base transactions to include in the UserOperation.
|
|
836
|
+
* @returns A pseudo-UserOperation that can be used to construct a real.
|
|
837
|
+
*/
|
|
838
|
+
prepareUserOperation(from, transactions) {
|
|
839
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
840
|
+
const address = (0, eth_sig_util_1.normalize)(from);
|
|
841
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
842
|
+
if (!keyring.prepareUserOperation) {
|
|
843
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedPrepareUserOperation);
|
|
844
|
+
}
|
|
845
|
+
return yield keyring.prepareUserOperation(address, transactions);
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Patches properties of a UserOperation. Currently, only the
|
|
850
|
+
* `paymasterAndData` can be patched.
|
|
851
|
+
*
|
|
852
|
+
* @param from - Address of the sender.
|
|
853
|
+
* @param userOp - UserOperation to patch.
|
|
854
|
+
* @returns A patch to apply to the UserOperation.
|
|
855
|
+
*/
|
|
856
|
+
patchUserOperation(from, userOp) {
|
|
857
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
858
|
+
const address = (0, eth_sig_util_1.normalize)(from);
|
|
859
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
860
|
+
if (!keyring.patchUserOperation) {
|
|
861
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedPatchUserOperation);
|
|
862
|
+
}
|
|
863
|
+
return yield keyring.patchUserOperation(address, userOp);
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Signs an UserOperation.
|
|
868
|
+
*
|
|
869
|
+
* @param from - Address of the sender.
|
|
870
|
+
* @param userOp - UserOperation to sign.
|
|
871
|
+
* @returns The signature of the UserOperation.
|
|
872
|
+
*/
|
|
873
|
+
signUserOperation(from, userOp) {
|
|
874
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
875
|
+
const address = (0, eth_sig_util_1.normalize)(from);
|
|
876
|
+
const keyring = (yield this.getKeyringForAccount(address));
|
|
877
|
+
if (!keyring.signUserOperation) {
|
|
878
|
+
throw new Error(constants_1.KeyringControllerError.UnsupportedSignUserOperation);
|
|
879
|
+
}
|
|
880
|
+
return yield keyring.signUserOperation(address, userOp);
|
|
881
|
+
});
|
|
586
882
|
}
|
|
587
883
|
/**
|
|
588
884
|
* Attempts to decrypt the current vault and load its keyrings,
|
|
@@ -594,7 +890,8 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
594
890
|
*/
|
|
595
891
|
submitEncryptionKey(encryptionKey, encryptionSalt) {
|
|
596
892
|
return __awaiter(this, void 0, void 0, function* () {
|
|
597
|
-
yield __classPrivateFieldGet(this,
|
|
893
|
+
__classPrivateFieldSet(this, _KeyringController_keyrings, yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, undefined, encryptionKey, encryptionSalt), "f");
|
|
894
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
598
895
|
const qrKeyring = this.getQRKeyring();
|
|
599
896
|
if (qrKeyring) {
|
|
600
897
|
// if there is a QR keyring, we need to subscribe
|
|
@@ -613,8 +910,9 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
613
910
|
*/
|
|
614
911
|
submitPassword(password) {
|
|
615
912
|
return __awaiter(this, void 0, void 0, function* () {
|
|
616
|
-
yield __classPrivateFieldGet(this,
|
|
617
|
-
|
|
913
|
+
__classPrivateFieldSet(this, _KeyringController_keyrings, yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, password), "f");
|
|
914
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
915
|
+
const accounts = yield this.getAccounts();
|
|
618
916
|
const qrKeyring = this.getQRKeyring();
|
|
619
917
|
if (qrKeyring) {
|
|
620
918
|
// if there is a QR keyring, we need to subscribe
|
|
@@ -632,8 +930,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
632
930
|
*/
|
|
633
931
|
verifySeedPhrase() {
|
|
634
932
|
return __awaiter(this, void 0, void 0, function* () {
|
|
635
|
-
const primaryKeyring =
|
|
636
|
-
/* istanbul ignore if */
|
|
933
|
+
const primaryKeyring = this.getKeyringsByType(KeyringTypes.hd)[0];
|
|
637
934
|
if (!primaryKeyring) {
|
|
638
935
|
throw new Error('No HD keyring found.');
|
|
639
936
|
}
|
|
@@ -646,11 +943,11 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
646
943
|
}
|
|
647
944
|
// The HD Keyring Builder is a default keyring builder
|
|
648
945
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
649
|
-
const hdKeyringBuilder = __classPrivateFieldGet(this,
|
|
946
|
+
const hdKeyringBuilder = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringBuilderForType).call(this, KeyringTypes.hd);
|
|
650
947
|
const hdKeyring = hdKeyringBuilder();
|
|
651
948
|
// @ts-expect-error @metamask/eth-hd-keyring correctly handles
|
|
652
949
|
// Uint8Array seed phrases in the `deserialize` method.
|
|
653
|
-
hdKeyring.deserialize({
|
|
950
|
+
yield hdKeyring.deserialize({
|
|
654
951
|
mnemonic: seedWords,
|
|
655
952
|
numberOfAccounts: accounts.length,
|
|
656
953
|
});
|
|
@@ -676,7 +973,7 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
676
973
|
*/
|
|
677
974
|
getQRKeyring() {
|
|
678
975
|
// QRKeyring is not yet compatible with Keyring type from @metamask/utils
|
|
679
|
-
return
|
|
976
|
+
return this.getKeyringsByType(KeyringTypes.qr)[0];
|
|
680
977
|
}
|
|
681
978
|
/**
|
|
682
979
|
* Get QR hardware keyring. If it doesn't exist, add it.
|
|
@@ -693,8 +990,8 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
693
990
|
restoreQRKeyring(serialized) {
|
|
694
991
|
return __awaiter(this, void 0, void 0, function* () {
|
|
695
992
|
(yield this.getOrAddQRKeyring()).deserialize(serialized);
|
|
696
|
-
yield
|
|
697
|
-
this.updateIdentities(yield
|
|
993
|
+
yield this.persistAllKeyrings();
|
|
994
|
+
this.updateIdentities(yield this.getAccounts());
|
|
698
995
|
});
|
|
699
996
|
}
|
|
700
997
|
resetQRKeyringState() {
|
|
@@ -768,13 +1065,13 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
768
1065
|
return __awaiter(this, void 0, void 0, function* () {
|
|
769
1066
|
const keyring = yield this.getOrAddQRKeyring();
|
|
770
1067
|
keyring.setAccountToUnlock(index);
|
|
771
|
-
const oldAccounts = yield
|
|
1068
|
+
const oldAccounts = yield this.getAccounts();
|
|
772
1069
|
// QRKeyring is not yet compatible with Keyring from
|
|
773
1070
|
// @metamask/utils, but we can use the `addNewAccount` method
|
|
774
1071
|
// as it internally calls `addAccounts` from on the keyring instance,
|
|
775
1072
|
// which is supported by QRKeyring API.
|
|
776
|
-
yield
|
|
777
|
-
const newAccounts = yield
|
|
1073
|
+
yield this.addNewAccountForKeyring(keyring);
|
|
1074
|
+
const newAccounts = yield this.getAccounts();
|
|
778
1075
|
this.updateIdentities(newAccounts);
|
|
779
1076
|
newAccounts.forEach((address) => {
|
|
780
1077
|
if (!oldAccounts.includes(address)) {
|
|
@@ -784,29 +1081,30 @@ class KeyringController extends base_controller_1.BaseController {
|
|
|
784
1081
|
this.setSelectedAddress(address);
|
|
785
1082
|
}
|
|
786
1083
|
});
|
|
787
|
-
yield
|
|
1084
|
+
yield this.persistAllKeyrings();
|
|
788
1085
|
});
|
|
789
1086
|
}
|
|
790
1087
|
getAccountKeyringType(account) {
|
|
791
1088
|
return __awaiter(this, void 0, void 0, function* () {
|
|
792
|
-
|
|
1089
|
+
const keyring = (yield this.getKeyringForAccount(account));
|
|
1090
|
+
return keyring.type;
|
|
793
1091
|
});
|
|
794
1092
|
}
|
|
795
1093
|
forgetQRDevice() {
|
|
796
1094
|
return __awaiter(this, void 0, void 0, function* () {
|
|
797
1095
|
const keyring = yield this.getOrAddQRKeyring();
|
|
798
|
-
const allAccounts = (yield
|
|
1096
|
+
const allAccounts = (yield this.getAccounts());
|
|
799
1097
|
keyring.forgetDevice();
|
|
800
|
-
const remainingAccounts = (yield
|
|
1098
|
+
const remainingAccounts = (yield this.getAccounts());
|
|
801
1099
|
const removedAccounts = allAccounts.filter((address) => !remainingAccounts.includes(address));
|
|
802
1100
|
this.updateIdentities(remainingAccounts);
|
|
803
|
-
yield
|
|
1101
|
+
yield this.persistAllKeyrings();
|
|
804
1102
|
return { removedAccounts, remainingAccounts };
|
|
805
1103
|
});
|
|
806
1104
|
}
|
|
807
1105
|
}
|
|
808
1106
|
exports.KeyringController = KeyringController;
|
|
809
|
-
|
|
1107
|
+
_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
1108
|
this.messagingSystem.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
|
|
811
1109
|
this.messagingSystem.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
|
|
812
1110
|
this.messagingSystem.registerActionHandler(`${name}:signTypedMessage`, this.signTypedMessage.bind(this));
|
|
@@ -816,10 +1114,21 @@ _KeyringController_keyring = new WeakMap(), _KeyringController_qrKeyringStateLis
|
|
|
816
1114
|
this.messagingSystem.registerActionHandler(`${name}:getKeyringsByType`, this.getKeyringsByType.bind(this));
|
|
817
1115
|
this.messagingSystem.registerActionHandler(`${name}:getKeyringForAccount`, this.getKeyringForAccount.bind(this));
|
|
818
1116
|
this.messagingSystem.registerActionHandler(`${name}:persistAllKeyrings`, this.persistAllKeyrings.bind(this));
|
|
1117
|
+
this.messagingSystem.registerActionHandler(`${name}:prepareUserOperation`, this.prepareUserOperation.bind(this));
|
|
1118
|
+
this.messagingSystem.registerActionHandler(`${name}:patchUserOperation`, this.patchUserOperation.bind(this));
|
|
1119
|
+
this.messagingSystem.registerActionHandler(`${name}:signUserOperation`, this.signUserOperation.bind(this));
|
|
1120
|
+
}, _KeyringController_getKeyringBuilderForType = function _KeyringController_getKeyringBuilderForType(type) {
|
|
1121
|
+
return __classPrivateFieldGet(this, _KeyringController_keyringBuilders, "f").find((keyringBuilder) => keyringBuilder.type === type);
|
|
819
1122
|
}, _KeyringController_addQRKeyring = function _KeyringController_addQRKeyring() {
|
|
820
1123
|
return __awaiter(this, void 0, void 0, function* () {
|
|
821
1124
|
// QRKeyring is not yet compatible with Keyring type from @metamask/utils
|
|
822
|
-
const qrKeyring = (yield __classPrivateFieldGet(this,
|
|
1125
|
+
const qrKeyring = (yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, KeyringTypes.qr, {
|
|
1126
|
+
accounts: [],
|
|
1127
|
+
}));
|
|
1128
|
+
const accounts = yield qrKeyring.getAccounts();
|
|
1129
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_checkForDuplicate).call(this, KeyringTypes.qr, accounts);
|
|
1130
|
+
__classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(qrKeyring);
|
|
1131
|
+
yield this.persistAllKeyrings();
|
|
823
1132
|
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_subscribeToQRKeyringEvents).call(this, qrKeyring);
|
|
824
1133
|
return qrKeyring;
|
|
825
1134
|
});
|
|
@@ -829,25 +1138,182 @@ _KeyringController_keyring = new WeakMap(), _KeyringController_qrKeyringStateLis
|
|
|
829
1138
|
}, "f");
|
|
830
1139
|
qrKeyring.getMemStore().subscribe(__classPrivateFieldGet(this, _KeyringController_qrKeyringStateListener, "f"));
|
|
831
1140
|
}, _KeyringController_unsubscribeFromQRKeyringsEvents = function _KeyringController_unsubscribeFromQRKeyringsEvents() {
|
|
832
|
-
const qrKeyrings =
|
|
1141
|
+
const qrKeyrings = this.getKeyringsByType(KeyringTypes.qr);
|
|
833
1142
|
qrKeyrings.forEach((qrKeyring) => {
|
|
834
1143
|
if (__classPrivateFieldGet(this, _KeyringController_qrKeyringStateListener, "f")) {
|
|
835
1144
|
qrKeyring.getMemStore().unsubscribe(__classPrivateFieldGet(this, _KeyringController_qrKeyringStateListener, "f"));
|
|
836
1145
|
}
|
|
837
1146
|
});
|
|
838
|
-
},
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
|
|
1147
|
+
}, _KeyringController_createNewVaultWithKeyring = function _KeyringController_createNewVaultWithKeyring(password, keyring) {
|
|
1148
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1149
|
+
if (typeof password !== 'string') {
|
|
1150
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
1151
|
+
}
|
|
1152
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1153
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
1154
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
|
|
1155
|
+
__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
|
|
1156
|
+
return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getMemState).call(this);
|
|
1157
|
+
});
|
|
1158
|
+
}, _KeyringController_updateKeyringsInState = function _KeyringController_updateKeyringsInState() {
|
|
1159
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1160
|
+
const keyrings = yield Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(displayForKeyring));
|
|
1161
|
+
this.update((state) => {
|
|
1162
|
+
state.keyrings = keyrings;
|
|
1163
|
+
});
|
|
1164
|
+
});
|
|
1165
|
+
}, _KeyringController_unlockKeyrings = function _KeyringController_unlockKeyrings(password, encryptionKey, encryptionSalt) {
|
|
1166
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1167
|
+
const encryptedVault = this.state.vault;
|
|
1168
|
+
if (!encryptedVault) {
|
|
1169
|
+
throw new Error(constants_1.KeyringControllerError.VaultError);
|
|
1170
|
+
}
|
|
1171
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
|
|
1172
|
+
let vault;
|
|
1173
|
+
if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
|
|
1174
|
+
assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
|
|
1175
|
+
if (password) {
|
|
1176
|
+
const result = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, encryptedVault);
|
|
1177
|
+
vault = result.vault;
|
|
1178
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1179
|
+
this.update((state) => {
|
|
1180
|
+
state.encryptionKey = result.exportedKeyString;
|
|
1181
|
+
state.encryptionSalt = result.salt;
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
else {
|
|
1185
|
+
const parsedEncryptedVault = JSON.parse(encryptedVault);
|
|
1186
|
+
if (encryptionSalt !== parsedEncryptedVault.salt) {
|
|
1187
|
+
throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
|
|
1188
|
+
}
|
|
1189
|
+
if (typeof encryptionKey !== 'string') {
|
|
1190
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
1191
|
+
}
|
|
1192
|
+
const key = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
|
|
1193
|
+
vault = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
|
|
1194
|
+
// This call is required on the first call because encryptionKey
|
|
1195
|
+
// is not yet inside the memStore
|
|
1196
|
+
this.update((state) => {
|
|
1197
|
+
state.encryptionKey = encryptionKey;
|
|
1198
|
+
// we can safely assume that encryptionSalt is defined here
|
|
1199
|
+
// because we compare it with the salt from the vault
|
|
1200
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1201
|
+
state.encryptionSalt = encryptionSalt;
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
else {
|
|
1206
|
+
if (typeof password !== 'string') {
|
|
1207
|
+
throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
|
|
1208
|
+
}
|
|
1209
|
+
vault = yield __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, encryptedVault);
|
|
1210
|
+
__classPrivateFieldSet(this, _KeyringController_password, password, "f");
|
|
1211
|
+
}
|
|
1212
|
+
if (!isSerializedKeyringsArray(vault)) {
|
|
1213
|
+
throw new Error(constants_1.KeyringControllerError.VaultDataError);
|
|
1214
|
+
}
|
|
1215
|
+
yield Promise.all(vault.map(__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).bind(this)));
|
|
1216
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateKeyringsInState).call(this);
|
|
1217
|
+
if (__classPrivateFieldGet(this, _KeyringController_password, "f") &&
|
|
1218
|
+
(!__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f") || !encryptionKey) &&
|
|
1219
|
+
__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated &&
|
|
1220
|
+
!__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(encryptedVault)) {
|
|
1221
|
+
// Re-encrypt the vault with safer method if one is available
|
|
1222
|
+
yield this.persistAllKeyrings();
|
|
1223
|
+
}
|
|
1224
|
+
return __classPrivateFieldGet(this, _KeyringController_keyrings, "f");
|
|
1225
|
+
});
|
|
1226
|
+
}, _KeyringController_createKeyringWithFirstAccount = function _KeyringController_createKeyringWithFirstAccount(type, opts) {
|
|
1227
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1228
|
+
const keyring = (yield this.addNewKeyring(type, opts));
|
|
1229
|
+
const [firstAccount] = yield keyring.getAccounts();
|
|
1230
|
+
if (!firstAccount) {
|
|
1231
|
+
throw new Error(constants_1.KeyringControllerError.NoFirstAccount);
|
|
1232
|
+
}
|
|
1233
|
+
});
|
|
1234
|
+
}, _KeyringController_newKeyring = function _KeyringController_newKeyring(type, data) {
|
|
1235
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1236
|
+
const keyringBuilder = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringBuilderForType).call(this, type);
|
|
1237
|
+
if (!keyringBuilder) {
|
|
1238
|
+
throw new Error(`${constants_1.KeyringControllerError.NoKeyringBuilder}. Keyring type: ${type}`);
|
|
1239
|
+
}
|
|
1240
|
+
const keyring = keyringBuilder();
|
|
1241
|
+
// @ts-expect-error Enforce data type after updating clients
|
|
1242
|
+
yield keyring.deserialize(data);
|
|
1243
|
+
if (keyring.init) {
|
|
1244
|
+
yield keyring.init();
|
|
1245
|
+
}
|
|
1246
|
+
return keyring;
|
|
1247
|
+
});
|
|
1248
|
+
}, _KeyringController_clearKeyrings = function _KeyringController_clearKeyrings() {
|
|
1249
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1250
|
+
for (const keyring of __classPrivateFieldGet(this, _KeyringController_keyrings, "f")) {
|
|
1251
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring);
|
|
1252
|
+
}
|
|
1253
|
+
__classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
|
|
1254
|
+
this.update((state) => {
|
|
1255
|
+
state.keyrings = [];
|
|
1256
|
+
});
|
|
1257
|
+
});
|
|
1258
|
+
}, _KeyringController_restoreKeyring = function _KeyringController_restoreKeyring(serialized) {
|
|
1259
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1260
|
+
try {
|
|
1261
|
+
const { type, data } = serialized;
|
|
1262
|
+
const keyring = yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, data);
|
|
1263
|
+
// getAccounts also validates the accounts for some keyrings
|
|
1264
|
+
yield keyring.getAccounts();
|
|
1265
|
+
__classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(keyring);
|
|
1266
|
+
return keyring;
|
|
1267
|
+
}
|
|
1268
|
+
catch (_) {
|
|
1269
|
+
__classPrivateFieldGet(this, _KeyringController_unsupportedKeyrings, "f").push(serialized);
|
|
1270
|
+
return undefined;
|
|
1271
|
+
}
|
|
1272
|
+
});
|
|
1273
|
+
}, _KeyringController_destroyKeyring = function _KeyringController_destroyKeyring(keyring) {
|
|
1274
|
+
var _a;
|
|
1275
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1276
|
+
yield ((_a = keyring.destroy) === null || _a === void 0 ? void 0 : _a.call(keyring));
|
|
1277
|
+
});
|
|
1278
|
+
}, _KeyringController_removeEmptyKeyrings = function _KeyringController_removeEmptyKeyrings() {
|
|
1279
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1280
|
+
const validKeyrings = [];
|
|
1281
|
+
// Since getAccounts returns a Promise
|
|
1282
|
+
// We need to wait to hear back form each keyring
|
|
1283
|
+
// in order to decide which ones are now valid (accounts.length > 0)
|
|
1284
|
+
yield Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map((keyring) => __awaiter(this, void 0, void 0, function* () {
|
|
1285
|
+
const accounts = yield keyring.getAccounts();
|
|
1286
|
+
if (accounts.length > 0) {
|
|
1287
|
+
validKeyrings.push(keyring);
|
|
1288
|
+
}
|
|
1289
|
+
else {
|
|
1290
|
+
yield __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring);
|
|
1291
|
+
}
|
|
1292
|
+
})));
|
|
1293
|
+
__classPrivateFieldSet(this, _KeyringController_keyrings, validKeyrings, "f");
|
|
1294
|
+
});
|
|
1295
|
+
}, _KeyringController_checkForDuplicate = function _KeyringController_checkForDuplicate(type, newAccountArray) {
|
|
1296
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1297
|
+
const accounts = yield this.getAccounts();
|
|
1298
|
+
switch (type) {
|
|
1299
|
+
case KeyringTypes.simple: {
|
|
1300
|
+
const isIncluded = Boolean(accounts.find((key) => newAccountArray[0] &&
|
|
1301
|
+
(key === newAccountArray[0] ||
|
|
1302
|
+
key === (0, utils_1.remove0x)(newAccountArray[0]))));
|
|
1303
|
+
if (isIncluded) {
|
|
1304
|
+
throw new Error(constants_1.KeyringControllerError.DuplicatedAccount);
|
|
1305
|
+
}
|
|
1306
|
+
return newAccountArray;
|
|
1307
|
+
}
|
|
1308
|
+
default: {
|
|
1309
|
+
return newAccountArray;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
});
|
|
1313
|
+
}, _KeyringController_setUnlocked = function _KeyringController_setUnlocked() {
|
|
1314
|
+
this.update((state) => {
|
|
1315
|
+
state.isUnlocked = true;
|
|
1316
|
+
});
|
|
851
1317
|
this.messagingSystem.publish(`${name}:unlock`);
|
|
852
1318
|
}, _KeyringController_getMemState = function _KeyringController_getMemState() {
|
|
853
1319
|
return {
|