From 37ed96e6ea48622408f17b518a5271e72cfb703d Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Thu, 4 May 2023 18:02:13 -0400 Subject: [PATCH 01/10] Move types directory --- {types => src/types}/@metamask/eth-hd-keyring.d.ts | 0 {types => src/types}/@metamask/eth-sig-util.d.ts | 0 {types => src/types}/@metamask/eth-simple-keyring.d.ts | 0 {types => src/types}/obs-store.d.ts | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {types => src/types}/@metamask/eth-hd-keyring.d.ts (100%) rename {types => src/types}/@metamask/eth-sig-util.d.ts (100%) rename {types => src/types}/@metamask/eth-simple-keyring.d.ts (100%) rename {types => src/types}/obs-store.d.ts (100%) diff --git a/types/@metamask/eth-hd-keyring.d.ts b/src/types/@metamask/eth-hd-keyring.d.ts similarity index 100% rename from types/@metamask/eth-hd-keyring.d.ts rename to src/types/@metamask/eth-hd-keyring.d.ts diff --git a/types/@metamask/eth-sig-util.d.ts b/src/types/@metamask/eth-sig-util.d.ts similarity index 100% rename from types/@metamask/eth-sig-util.d.ts rename to src/types/@metamask/eth-sig-util.d.ts diff --git a/types/@metamask/eth-simple-keyring.d.ts b/src/types/@metamask/eth-simple-keyring.d.ts similarity index 100% rename from types/@metamask/eth-simple-keyring.d.ts rename to src/types/@metamask/eth-simple-keyring.d.ts diff --git a/types/obs-store.d.ts b/src/types/obs-store.d.ts similarity index 100% rename from types/obs-store.d.ts rename to src/types/obs-store.d.ts From bca1de4b6dcea3aead1462da7f924aeb1e7a3fa1 Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Thu, 4 May 2023 18:02:33 -0400 Subject: [PATCH 02/10] Cast typing to override method return type --- src/KeyringController.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/KeyringController.ts b/src/KeyringController.ts index 298dd20d..1f0f25d8 100644 --- a/src/KeyringController.ts +++ b/src/KeyringController.ts @@ -285,7 +285,7 @@ class KeyringController extends EventEmitter { throw new Error(KeyringControllerError.UnsupportedExportAccount); } - return await keyring.exportAccount(normalizeToHex(address)); + return await keyring.exportAccount(normalizeToHex(address) as Hex); } /** @@ -388,7 +388,7 @@ class KeyringController extends EventEmitter { rawAddress: string, opts: Record = {}, ): Promise { - const address = normalizeToHex(rawAddress); + const address = normalizeToHex(rawAddress) as Hex; const keyring = await this.getKeyringForAccount(address); if (!keyring.signTransaction) { throw new Error(KeyringControllerError.UnsupportedSignTransaction); @@ -415,7 +415,7 @@ class KeyringController extends EventEmitter { }, opts: Record = {}, ): Promise { - const address = normalizeToHex(msgParams.from); + const address = normalizeToHex(msgParams.from) as Hex; const keyring = await this.getKeyringForAccount(address); if (!keyring.signMessage) { throw new Error(KeyringControllerError.UnsupportedSignMessage); @@ -443,13 +443,13 @@ class KeyringController extends EventEmitter { }, opts: Record = {}, ): Promise { - const address = normalizeToHex(msgParams.from); + const address = normalizeToHex(msgParams.from) as Hex; const keyring = await this.getKeyringForAccount(address); if (!keyring.signPersonalMessage) { throw new Error(KeyringControllerError.UnsupportedSignPersonalMessage); } - const normalizedData = normalizeToHex(msgParams.data); + const normalizedData = normalizeToHex(msgParams.data) as Hex; return await keyring.signPersonalMessage(address, normalizedData, opts); } @@ -467,7 +467,7 @@ class KeyringController extends EventEmitter { address: string, opts: Record = {}, ): Promise { - const normalizedAddress = normalizeToHex(address); + const normalizedAddress = normalizeToHex(address) as Hex; const keyring = await this.getKeyringForAccount(address); if (!keyring.getEncryptionPublicKey) { throw new Error(KeyringControllerError.UnsupportedGetEncryptionPublicKey); @@ -490,7 +490,7 @@ class KeyringController extends EventEmitter { from: string; data: Eip1024EncryptedData; }): Promise { - const address = normalizeToHex(msgParams.from); + const address = normalizeToHex(msgParams.from) as Hex; const keyring = await this.getKeyringForAccount(address); if (!keyring.decryptMessage) { throw new Error(KeyringControllerError.UnsupportedDecryptMessage); @@ -536,7 +536,7 @@ class KeyringController extends EventEmitter { * @returns The app key address. */ async getAppKeyAddress(rawAddress: string, origin: string): Promise { - const address = normalizeToHex(rawAddress); + const address = normalizeToHex(rawAddress) as Hex; const keyring = await this.getKeyringForAccount(address); if (!keyring.getAppKeyAddress) { throw new Error(KeyringControllerError.UnsupportedGetAppKeyAddress); @@ -556,7 +556,7 @@ class KeyringController extends EventEmitter { rawAddress: string, origin: string, ): Promise { - const address = normalizeToHex(rawAddress); + const address = normalizeToHex(rawAddress) as Hex; const keyring = await this.getKeyringForAccount(address); if (!keyring.exportAccount) { throw new Error(KeyringControllerError.UnsupportedExportAppKeyForAddress); From 887fcb610d27682594bf2ca90914d5cfa31c6894 Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Thu, 4 May 2023 18:05:13 -0400 Subject: [PATCH 03/10] Add dist directory --- .gitignore | 2 +- dist/KeyringController.d.ts | 367 ++++++++++++++ dist/KeyringController.js | 859 ++++++++++++++++++++++++++++++++ dist/KeyringController.js.map | 1 + dist/constants.d.ts | 28 ++ dist/constants.js | 34 ++ dist/constants.js.map | 1 + dist/index.d.ts | 2 + dist/index.js | 10 + dist/index.js.map | 1 + dist/test/encryptor.mock.d.ts | 38 ++ dist/test/encryptor.mock.js | 86 ++++ dist/test/encryptor.mock.js.map | 1 + dist/test/index.d.ts | 3 + dist/test/index.js | 16 + dist/test/index.js.map | 1 + dist/test/keyring.mock.d.ts | 13 + dist/test/keyring.mock.js | 36 ++ dist/test/keyring.mock.js.map | 1 + dist/types.d.ts | 31 ++ dist/types.js | 3 + dist/types.js.map | 1 + tsconfig.build.json | 9 +- 23 files changed, 1536 insertions(+), 8 deletions(-) create mode 100644 dist/KeyringController.d.ts create mode 100644 dist/KeyringController.js create mode 100644 dist/KeyringController.js.map create mode 100644 dist/constants.d.ts create mode 100644 dist/constants.js create mode 100644 dist/constants.js.map create mode 100644 dist/index.d.ts create mode 100644 dist/index.js create mode 100644 dist/index.js.map create mode 100644 dist/test/encryptor.mock.d.ts create mode 100644 dist/test/encryptor.mock.js create mode 100644 dist/test/encryptor.mock.js.map create mode 100644 dist/test/index.d.ts create mode 100644 dist/test/index.js create mode 100644 dist/test/index.js.map create mode 100644 dist/test/keyring.mock.d.ts create mode 100644 dist/test/keyring.mock.js create mode 100644 dist/test/keyring.mock.js.map create mode 100644 dist/types.d.ts create mode 100644 dist/types.js create mode 100644 dist/types.js.map diff --git a/.gitignore b/.gitignore index fbee401d..c242f8c1 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,4 @@ coverage !.yarn/versions # distribution -dist +# dist diff --git a/dist/KeyringController.d.ts b/dist/KeyringController.d.ts new file mode 100644 index 00000000..9d7e1488 --- /dev/null +++ b/dist/KeyringController.d.ts @@ -0,0 +1,367 @@ +/// +import type { TypedTransaction, TxData } from '@ethereumjs/tx'; +import type { Hex, Json, Bytes, Keyring, KeyringClass, Eip1024EncryptedData } from '@metamask/utils'; +import { EventEmitter } from 'events'; +import ObservableStore from 'obs-store'; +import { SerializedKeyring, KeyringControllerArgs, KeyringControllerState } from './types'; +declare class KeyringController extends EventEmitter { + #private; + keyringBuilders: { + (): Keyring; + type: string; + }[]; + store: typeof ObservableStore; + memStore: typeof ObservableStore; + encryptor: any; + keyrings: Keyring[]; + cacheEncryptionKey: boolean; + unsupportedKeyrings: SerializedKeyring[]; + password?: string; + constructor({ keyringBuilders, cacheEncryptionKey, initState, encryptor, }: KeyringControllerArgs); + /** + * ======================================= + * === Public Vault Management Methods === + * ======================================= + */ + /** + * Create New Vault And Keychain + * + * Destroys any old encrypted storage, + * creates a new encrypted store with the given password, + * randomly creates a new HD wallet with 1 account, + * faucets that account on the testnet. + * + * @fires KeyringController#unlock + * @param password - The password to encrypt the vault with. + * @returns A promise that resolves to the state. + */ + createNewVaultAndKeychain(password: string): Promise; + /** + * CreateNewVaultAndRestore + * + * Destroys any old encrypted storage, + * creates a new encrypted store with the given password, + * creates a new HD wallet from the given seed with 1 account. + * + * @fires KeyringController#unlock + * @param password - The password to encrypt the vault with. + * @param seedPhrase - The BIP39-compliant seed phrase, + * either as a string or Uint8Array. + * @returns A promise that resolves to the state. + */ + createNewVaultAndRestore(password: string, seedPhrase: Uint8Array | string | number[]): Promise; + /** + * Set Locked. + * This method deallocates all secrets, and effectively locks MetaMask. + * + * @fires KeyringController#lock + * @returns A promise that resolves to the state. + */ + setLocked(): Promise; + /** + * Submit password. + * + * Attempts to decrypt the current vault and load its keyrings + * into memory. + * + * Temporarily also migrates any old-style vaults first, as well + * (Pre MetaMask 3.0.0). + * + * @fires KeyringController#unlock + * @param password - The keyring controller password. + * @returns A promise that resolves to the state. + */ + submitPassword(password: string): Promise; + /** + * Submit Encryption Key. + * + * Attempts to decrypt the current vault and load its keyrings + * into memory based on the vault and CryptoKey information. + * + * @fires KeyringController#unlock + * @param encryptionKey - The encrypted key information used to decrypt the vault. + * @param encryptionSalt - The salt used to generate the last key. + * @returns A promise that resolves to the state. + */ + submitEncryptionKey(encryptionKey: string, encryptionSalt: string): Promise; + /** + * Verify Password + * + * Attempts to decrypt the current vault with a given password + * to verify its validity. + * + * @param password - The vault password. + */ + verifyPassword(password: string): Promise; + /** + * ========================================= + * === Public Account Management Methods === + * ========================================= + */ + /** + * Add New Account. + * + * Calls the `addAccounts` method on the given keyring, + * and then saves those changes. + * + * @param selectedKeyring - The currently selected keyring. + * @returns A Promise that resolves to the state. + */ + addNewAccount(selectedKeyring: Keyring): Promise; + /** + * Export Account + * + * Requests the private key from the keyring controlling + * the specified address. + * + * Returns a Promise that may resolve with the private key string. + * + * @param address - The address of the account to export. + * @returns The private key of the account. + */ + exportAccount(address: string): Promise; + /** + * Remove Account. + * + * Removes a specific account from a keyring + * If the account is the last/only one then it also removes the keyring. + * + * @param address - The address of the account to remove. + * @returns A promise that resolves if the operation was successful. + */ + removeAccount(address: Hex): Promise; + /** + * Get Accounts + * + * Returns the public addresses of all current accounts + * managed by all currently unlocked keyrings. + * + * @returns The array of accounts. + */ + getAccounts(): Promise; + /** + * Get Keyring Class For Type + * + * Searches the current `keyringBuilders` array + * for a Keyring builder whose unique `type` property + * matches the provided `type`, + * returning it if it exists. + * + * @param type - The type whose class to get. + * @returns The class, if it exists. + */ + getKeyringBuilderForType(type: string): { + (): Keyring; + type: string; + } | undefined; + /** + * Update memStore Keyrings + * + * Updates the in-memory keyrings, without persisting. + */ + updateMemStoreKeyrings(): Promise; + /** + * =========================================== + * === Public RPC Requests Routing Methods === + * =========================================== + */ + /** + * Sign Ethereum Transaction + * + * Signs an Ethereum transaction object. + * + * @param ethTx - The transaction to sign. + * @param rawAddress - The transaction 'from' address. + * @param opts - Signing options. + * @returns The signed transaction object. + */ + signTransaction(ethTx: TypedTransaction, rawAddress: string, opts?: Record): Promise; + /** + * Sign Message + * + * Attempts to sign the provided message parameters. + * + * @param msgParams - The message parameters to sign. + * @param msgParams.from - From address. + * @param msgParams.data - The message to sign. + * @param opts - Additional signing options. + * @returns The raw signature. + */ + signMessage(msgParams: { + from: string; + data: string; + }, opts?: Record): Promise; + /** + * Sign Personal Message + * + * Attempts to sign the provided message parameters. + * Prefixes the hash before signing per the personal sign expectation. + * + * @param msgParams - The message parameters to sign. + * @param msgParams.from - From address. + * @param msgParams.data - The message to sign. + * @param opts - Additional signing options. + * @returns The raw signature. + */ + signPersonalMessage(msgParams: { + from: string; + data: string; + }, opts?: Record): Promise; + /** + * Get encryption public key + * + * Get encryption public key for using in encrypt/decrypt process. + * + * @param address - The address to get the encryption public key for. + * @param opts - Additional encryption options. + * @returns The public key. + */ + getEncryptionPublicKey(address: string, opts?: Record): Promise; + /** + * Decrypt Message + * + * Attempts to decrypt the provided message parameters. + * + * @param msgParams - The decryption message parameters. + * @param msgParams.from - The address of the account you want to use to decrypt the message. + * @param msgParams.data - The encrypted data that you want to decrypt. + * @returns The raw decryption result. + */ + decryptMessage(msgParams: { + from: string; + data: Eip1024EncryptedData; + }): Promise; + /** + * Sign Typed Data. + * + * @see {@link https://github.com/ethereum/EIPs/pull/712#issuecomment-329988454|EIP712}. + * @param msgParams - The message parameters to sign. + * @param msgParams.from - From address. + * @param msgParams.data - The data to sign. + * @param opts - Additional signing options. + * @returns The raw signature. + */ + signTypedMessage(msgParams: { + from: string; + data: Record[]; + }, opts?: Record): Promise; + /** + * Gets the app key address for the given Ethereum address and origin. + * + * @param rawAddress - The Ethereum address for the app key. + * @param origin - The origin for the app key. + * @returns The app key address. + */ + getAppKeyAddress(rawAddress: string, origin: string): Promise; + /** + * Exports an app key private key for the given Ethereum address and origin. + * + * @param rawAddress - The Ethereum address for the app key. + * @param origin - The origin for the app key. + * @returns The app key private key. + */ + exportAppKeyForAddress(rawAddress: string, origin: string): Promise; + /** + * ========================================= + * === Public Keyring Management Methods === + * ========================================= + */ + /** + * Add New Keyring + * + * Adds a new Keyring of the given `type` to the vault + * and the current decrypted Keyrings array. + * + * All Keyring classes implement a unique `type` string, + * and this is used to retrieve them from the keyringBuilders array. + * + * @param type - The type of keyring to add. + * @param opts - The constructor options for the keyring. + * @returns The new keyring. + */ + addNewKeyring(type: string, opts?: Record): Promise>; + /** + * Remove empty keyrings. + * + * Loops through the keyrings and removes the ones with empty accounts + * (usually after removing the last / only account) from a keyring. + */ + removeEmptyKeyrings(): Promise; + /** + * Checks for duplicate keypairs, using the the first account in the given + * array. Rejects if a duplicate is found. + * + * Only supports 'Simple Key Pair'. + * + * @param type - The key pair type to check for. + * @param newAccountArray - Array of new accounts. + * @returns The account, if no duplicate is found. + */ + checkForDuplicate(type: string, newAccountArray: string[]): Promise; + /** + * Get Keyring For Account + * + * Returns the currently initialized keyring that manages + * the specified `address` if one exists. + * + * @param address - An account address. + * @returns The keyring of the account, if it exists. + */ + getKeyringForAccount(address: string): Promise>; + /** + * Restore Keyring + * + * Attempts to initialize a new keyring from the provided serialized payload. + * On success, updates the memStore keyrings and returns the resulting + * keyring instance. + * + * @param serialized - The serialized keyring. + * @returns The deserialized keyring. + */ + restoreKeyring(serialized: SerializedKeyring): Promise | undefined>; + /** + * Get Keyrings by Type + * + * Gets all keyrings of the given type. + * + * @param type - The keyring types to retrieve. + * @returns Keyrings matching the specified type. + */ + getKeyringsByType(type: string): Keyring[]; + /** + * Persist All Keyrings + * + * Iterates the current `keyrings` array, + * serializes each one into a serialized array, + * encrypts that array with the provided `password`, + * and persists that encrypted string to storage. + * + * @returns Resolves to true once keyrings are persisted. + */ + persistAllKeyrings(): Promise; + /** + * Unlock Keyrings. + * + * Attempts to unlock the persisted encrypted storage, + * initializing the persisted keyrings to RAM. + * + * @param password - The keyring controller password. + * @param encryptionKey - An exported key string to unlock keyrings with. + * @param encryptionSalt - The salt used to encrypt the vault. + * @returns The keyrings array. + */ + unlockKeyrings(password: string | undefined, encryptionKey?: string, encryptionSalt?: string): Promise[]>; +} +/** + * Get builder function for `Keyring` + * + * Returns a builder function for `Keyring` with a `type` property. + * + * @param KeyringConstructor - The Keyring class for the builder. + * @returns A builder function for the given Keyring. + */ +declare function keyringBuilderFactory(KeyringConstructor: KeyringClass): { + (): Keyring; + type: string; +}; +export { KeyringController, keyringBuilderFactory }; diff --git a/dist/KeyringController.js b/dist/KeyringController.js new file mode 100644 index 00000000..237bab1e --- /dev/null +++ b/dist/KeyringController.js @@ -0,0 +1,859 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + 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"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _KeyringController_instances, _KeyringController_fullUpdate, _KeyringController_createFirstKeyTree, _KeyringController_restoreKeyring, _KeyringController_clearKeyrings, _KeyringController_setUnlocked, _KeyringController_newKeyring; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.keyringBuilderFactory = exports.KeyringController = void 0; +const encryptorUtils = __importStar(require("@metamask/browser-passworder")); +const eth_hd_keyring_1 = __importDefault(require("@metamask/eth-hd-keyring")); +const eth_sig_util_1 = require("@metamask/eth-sig-util"); +const eth_simple_keyring_1 = __importDefault(require("@metamask/eth-simple-keyring")); +const utils_1 = require("@metamask/utils"); +// TODO: Stop using `events`, and remove the notice about this from the README +// eslint-disable-next-line import/no-nodejs-modules +const events_1 = require("events"); +const obs_store_1 = __importDefault(require("obs-store")); +const constants_1 = require("./constants"); +const defaultKeyringBuilders = [ + keyringBuilderFactory(eth_simple_keyring_1.default), + keyringBuilderFactory(eth_hd_keyring_1.default), +]; +class KeyringController extends events_1.EventEmitter { + constructor({ keyringBuilders, cacheEncryptionKey, initState = {}, encryptor = encryptorUtils, }) { + super(); + _KeyringController_instances.add(this); + this.keyringBuilders = keyringBuilders + ? defaultKeyringBuilders.concat(keyringBuilders) + : defaultKeyringBuilders; + this.store = new obs_store_1.default(initState); + this.memStore = new obs_store_1.default({ + isUnlocked: false, + keyringTypes: this.keyringBuilders.map((keyringBuilder) => keyringBuilder.type), + keyrings: [], + encryptionKey: null, + }); + this.encryptor = encryptor; + this.keyrings = []; + this.unsupportedKeyrings = []; + // This option allows the controller to cache an exported key + // for use in decrypting and encrypting data without password + this.cacheEncryptionKey = Boolean(cacheEncryptionKey); + } + /** + * ======================================= + * === Public Vault Management Methods === + * ======================================= + */ + /** + * Create New Vault And Keychain + * + * Destroys any old encrypted storage, + * creates a new encrypted store with the given password, + * randomly creates a new HD wallet with 1 account, + * faucets that account on the testnet. + * + * @fires KeyringController#unlock + * @param password - The password to encrypt the vault with. + * @returns A promise that resolves to the state. + */ + async createNewVaultAndKeychain(password) { + this.password = password; + await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createFirstKeyTree).call(this); + __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); + return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + } + /** + * CreateNewVaultAndRestore + * + * Destroys any old encrypted storage, + * creates a new encrypted store with the given password, + * creates a new HD wallet from the given seed with 1 account. + * + * @fires KeyringController#unlock + * @param password - The password to encrypt the vault with. + * @param seedPhrase - The BIP39-compliant seed phrase, + * either as a string or Uint8Array. + * @returns A promise that resolves to the state. + */ + async createNewVaultAndRestore(password, seedPhrase) { + if (typeof password !== 'string') { + throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType); + } + this.password = password; + await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this); + const keyring = await this.addNewKeyring(constants_1.KeyringType.HD, { + mnemonic: seedPhrase, + numberOfAccounts: 1, + }); + const [firstAccount] = await keyring.getAccounts(); + if (!firstAccount) { + throw new Error(constants_1.KeyringControllerError.NoFirstAccount); + } + __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); + return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + } + /** + * Set Locked. + * This method deallocates all secrets, and effectively locks MetaMask. + * + * @fires KeyringController#lock + * @returns A promise that resolves to the state. + */ + async setLocked() { + delete this.password; + // set locked + this.memStore.updateState({ + isUnlocked: false, + encryptionKey: null, + encryptionSalt: null, + }); + // remove keyrings + this.keyrings = []; + await this.updateMemStoreKeyrings(); + this.emit('lock'); + return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + } + /** + * Submit password. + * + * Attempts to decrypt the current vault and load its keyrings + * into memory. + * + * Temporarily also migrates any old-style vaults first, as well + * (Pre MetaMask 3.0.0). + * + * @fires KeyringController#unlock + * @param password - The keyring controller password. + * @returns A promise that resolves to the state. + */ + async submitPassword(password) { + this.keyrings = await this.unlockKeyrings(password); + __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); + return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + } + /** + * Submit Encryption Key. + * + * Attempts to decrypt the current vault and load its keyrings + * into memory based on the vault and CryptoKey information. + * + * @fires KeyringController#unlock + * @param encryptionKey - The encrypted key information used to decrypt the vault. + * @param encryptionSalt - The salt used to generate the last key. + * @returns A promise that resolves to the state. + */ + async submitEncryptionKey(encryptionKey, encryptionSalt) { + this.keyrings = await this.unlockKeyrings(undefined, encryptionKey, encryptionSalt); + __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); + return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + } + /** + * Verify Password + * + * Attempts to decrypt the current vault with a given password + * to verify its validity. + * + * @param password - The vault password. + */ + async verifyPassword(password) { + const encryptedVault = this.store.getState().vault; + if (!encryptedVault) { + throw new Error(constants_1.KeyringControllerError.VaultError); + } + await this.encryptor.decrypt(password, encryptedVault); + } + /** + * ========================================= + * === Public Account Management Methods === + * ========================================= + */ + /** + * Add New Account. + * + * Calls the `addAccounts` method on the given keyring, + * and then saves those changes. + * + * @param selectedKeyring - The currently selected keyring. + * @returns A Promise that resolves to the state. + */ + async addNewAccount(selectedKeyring) { + const accounts = await selectedKeyring.addAccounts(1); + accounts.forEach((hexAccount) => { + this.emit('newAccount', hexAccount); + }); + await this.persistAllKeyrings(); + return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + } + /** + * Export Account + * + * Requests the private key from the keyring controlling + * the specified address. + * + * Returns a Promise that may resolve with the private key string. + * + * @param address - The address of the account to export. + * @returns The private key of the account. + */ + async exportAccount(address) { + const keyring = await this.getKeyringForAccount(address); + if (!keyring.exportAccount) { + throw new Error(constants_1.KeyringControllerError.UnsupportedExportAccount); + } + return await keyring.exportAccount((0, eth_sig_util_1.normalize)(address)); + } + /** + * Remove Account. + * + * Removes a specific account from a keyring + * If the account is the last/only one then it also removes the keyring. + * + * @param address - The address of the account to remove. + * @returns A promise that resolves if the operation was successful. + */ + async removeAccount(address) { + const keyring = await this.getKeyringForAccount(address); + // Not all the keyrings support this, so we have to check + if (!keyring.removeAccount) { + throw new Error(constants_1.KeyringControllerError.UnsupportedRemoveAccount); + } + keyring.removeAccount(address); + this.emit('removedAccount', address); + const accounts = await keyring.getAccounts(); + // Check if this was the last/only account + if (accounts.length === 0) { + await this.removeEmptyKeyrings(); + } + await this.persistAllKeyrings(); + return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + } + /** + * Get Accounts + * + * Returns the public addresses of all current accounts + * managed by all currently unlocked keyrings. + * + * @returns The array of accounts. + */ + async getAccounts() { + const keyrings = this.keyrings || []; + const keyringArrays = await Promise.all(keyrings.map(async (keyring) => keyring.getAccounts())); + const addresses = keyringArrays.reduce((res, arr) => { + return res.concat(arr); + }, []); + return addresses.map(eth_sig_util_1.normalize); + } + /** + * Get Keyring Class For Type + * + * Searches the current `keyringBuilders` array + * for a Keyring builder whose unique `type` property + * matches the provided `type`, + * returning it if it exists. + * + * @param type - The type whose class to get. + * @returns The class, if it exists. + */ + getKeyringBuilderForType(type) { + return this.keyringBuilders.find((keyringBuilder) => keyringBuilder.type === type); + } + /** + * Update memStore Keyrings + * + * Updates the in-memory keyrings, without persisting. + */ + async updateMemStoreKeyrings() { + const keyrings = await Promise.all(this.keyrings.map(displayForKeyring)); + return this.memStore.updateState({ keyrings }); + } + /** + * =========================================== + * === Public RPC Requests Routing Methods === + * =========================================== + */ + /** + * Sign Ethereum Transaction + * + * Signs an Ethereum transaction object. + * + * @param ethTx - The transaction to sign. + * @param rawAddress - The transaction 'from' address. + * @param opts - Signing options. + * @returns The signed transaction object. + */ + async signTransaction(ethTx, rawAddress, opts = {}) { + const address = (0, eth_sig_util_1.normalize)(rawAddress); + const keyring = await this.getKeyringForAccount(address); + if (!keyring.signTransaction) { + throw new Error(constants_1.KeyringControllerError.UnsupportedSignTransaction); + } + return await keyring.signTransaction(address, ethTx, opts); + } + /** + * Sign Message + * + * Attempts to sign the provided message parameters. + * + * @param msgParams - The message parameters to sign. + * @param msgParams.from - From address. + * @param msgParams.data - The message to sign. + * @param opts - Additional signing options. + * @returns The raw signature. + */ + async signMessage(msgParams, opts = {}) { + const address = (0, eth_sig_util_1.normalize)(msgParams.from); + const keyring = await this.getKeyringForAccount(address); + if (!keyring.signMessage) { + throw new Error(constants_1.KeyringControllerError.UnsupportedSignMessage); + } + return await keyring.signMessage(address, msgParams.data, opts); + } + /** + * Sign Personal Message + * + * Attempts to sign the provided message parameters. + * Prefixes the hash before signing per the personal sign expectation. + * + * @param msgParams - The message parameters to sign. + * @param msgParams.from - From address. + * @param msgParams.data - The message to sign. + * @param opts - Additional signing options. + * @returns The raw signature. + */ + async signPersonalMessage(msgParams, opts = {}) { + const address = (0, eth_sig_util_1.normalize)(msgParams.from); + const keyring = await this.getKeyringForAccount(address); + if (!keyring.signPersonalMessage) { + throw new Error(constants_1.KeyringControllerError.UnsupportedSignPersonalMessage); + } + const normalizedData = (0, eth_sig_util_1.normalize)(msgParams.data); + return await keyring.signPersonalMessage(address, normalizedData, opts); + } + /** + * Get encryption public key + * + * Get encryption public key for using in encrypt/decrypt process. + * + * @param address - The address to get the encryption public key for. + * @param opts - Additional encryption options. + * @returns The public key. + */ + async getEncryptionPublicKey(address, opts = {}) { + const normalizedAddress = (0, eth_sig_util_1.normalize)(address); + const keyring = await this.getKeyringForAccount(address); + if (!keyring.getEncryptionPublicKey) { + throw new Error(constants_1.KeyringControllerError.UnsupportedGetEncryptionPublicKey); + } + return await keyring.getEncryptionPublicKey(normalizedAddress, opts); + } + /** + * Decrypt Message + * + * Attempts to decrypt the provided message parameters. + * + * @param msgParams - The decryption message parameters. + * @param msgParams.from - The address of the account you want to use to decrypt the message. + * @param msgParams.data - The encrypted data that you want to decrypt. + * @returns The raw decryption result. + */ + async decryptMessage(msgParams) { + const address = (0, eth_sig_util_1.normalize)(msgParams.from); + const keyring = await this.getKeyringForAccount(address); + if (!keyring.decryptMessage) { + throw new Error(constants_1.KeyringControllerError.UnsupportedDecryptMessage); + } + return keyring.decryptMessage(address, msgParams.data); + } + /** + * Sign Typed Data. + * + * @see {@link https://github.com/ethereum/EIPs/pull/712#issuecomment-329988454|EIP712}. + * @param msgParams - The message parameters to sign. + * @param msgParams.from - From address. + * @param msgParams.data - The data to sign. + * @param opts - Additional signing options. + * @returns The raw signature. + */ + async signTypedMessage(msgParams, opts = { version: 'V1' }) { + const address = (0, eth_sig_util_1.normalize)(msgParams.from); + const keyring = await this.getKeyringForAccount(address); + if (!keyring.signTypedData) { + throw new Error(constants_1.KeyringControllerError.UnsupportedSignTypedMessage); + } + // Looks like this is not well defined in the Keyring interface since + // our tests show that we should be able to pass an array. + // @ts-expect-error Missing other required permission types. + return keyring.signTypedData(address, msgParams.data, opts); + } + /** + * Gets the app key address for the given Ethereum address and origin. + * + * @param rawAddress - The Ethereum address for the app key. + * @param origin - The origin for the app key. + * @returns The app key address. + */ + async getAppKeyAddress(rawAddress, origin) { + const address = (0, eth_sig_util_1.normalize)(rawAddress); + const keyring = await this.getKeyringForAccount(address); + if (!keyring.getAppKeyAddress) { + throw new Error(constants_1.KeyringControllerError.UnsupportedGetAppKeyAddress); + } + return keyring.getAppKeyAddress(address, origin); + } + /** + * Exports an app key private key for the given Ethereum address and origin. + * + * @param rawAddress - The Ethereum address for the app key. + * @param origin - The origin for the app key. + * @returns The app key private key. + */ + async exportAppKeyForAddress(rawAddress, origin) { + const address = (0, eth_sig_util_1.normalize)(rawAddress); + const keyring = await this.getKeyringForAccount(address); + if (!keyring.exportAccount) { + throw new Error(constants_1.KeyringControllerError.UnsupportedExportAppKeyForAddress); + } + return keyring.exportAccount(address, { withAppKeyOrigin: origin }); + } + /** + * ========================================= + * === Public Keyring Management Methods === + * ========================================= + */ + /** + * Add New Keyring + * + * Adds a new Keyring of the given `type` to the vault + * and the current decrypted Keyrings array. + * + * All Keyring classes implement a unique `type` string, + * and this is used to retrieve them from the keyringBuilders array. + * + * @param type - The type of keyring to add. + * @param opts - The constructor options for the keyring. + * @returns The new keyring. + */ + async addNewKeyring(type, opts = {}) { + let keyring; + switch (type) { + case constants_1.KeyringType.Simple: + keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts.privateKeys); + break; + default: + keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts); + break; + } + if (!keyring) { + throw new Error(constants_1.KeyringControllerError.NoKeyring); + } + if (!opts.mnemonic && type === constants_1.KeyringType.HD) { + if (!keyring.generateRandomMnemonic) { + throw new Error(constants_1.KeyringControllerError.UnsupportedGenerateRandomMnemonic); + } + keyring.generateRandomMnemonic(); + await keyring.addAccounts(1); + } + const accounts = await keyring.getAccounts(); + await this.checkForDuplicate(type, accounts); + this.keyrings.push(keyring); + await this.persistAllKeyrings(); + __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + return keyring; + } + /** + * Remove empty keyrings. + * + * Loops through the keyrings and removes the ones with empty accounts + * (usually after removing the last / only account) from a keyring. + */ + async removeEmptyKeyrings() { + const validKeyrings = []; + // Since getAccounts returns a Promise + // We need to wait to hear back form each keyring + // in order to decide which ones are now valid (accounts.length > 0) + await Promise.all(this.keyrings.map(async (keyring) => { + const accounts = await keyring.getAccounts(); + if (accounts.length > 0) { + validKeyrings.push(keyring); + } + })); + this.keyrings = validKeyrings; + } + /** + * Checks for duplicate keypairs, using the the first account in the given + * array. Rejects if a duplicate is found. + * + * Only supports 'Simple Key Pair'. + * + * @param type - The key pair type to check for. + * @param newAccountArray - Array of new accounts. + * @returns The account, if no duplicate is found. + */ + async checkForDuplicate(type, newAccountArray) { + const accounts = await this.getAccounts(); + switch (type) { + case constants_1.KeyringType.Simple: { + const isIncluded = Boolean(accounts.find((key) => newAccountArray[0] && + (key === newAccountArray[0] || + key === (0, utils_1.remove0x)(newAccountArray[0])))); + if (isIncluded) { + throw new Error(constants_1.KeyringControllerError.DuplicatedAccount); + } + return newAccountArray; + } + default: { + return newAccountArray; + } + } + } + /** + * Get Keyring For Account + * + * Returns the currently initialized keyring that manages + * the specified `address` if one exists. + * + * @param address - An account address. + * @returns The keyring of the account, if it exists. + */ + async getKeyringForAccount(address) { + var _a; + const hexed = (0, eth_sig_util_1.normalize)(address); + const candidates = await Promise.all(this.keyrings.map(async (keyring) => { + return Promise.all([keyring, keyring.getAccounts()]); + })); + const winners = candidates.filter((candidate) => { + const accounts = candidate[1].map(eth_sig_util_1.normalize); + return accounts.includes(hexed); + }); + if (winners.length && ((_a = winners[0]) === null || _a === void 0 ? void 0 : _a.length)) { + return winners[0][0]; + } + // Adding more info to the error + let errorInfo = ''; + if (!address) { + errorInfo = 'The address passed in is invalid/empty'; + } + else if (!candidates.length) { + errorInfo = 'There are no keyrings'; + } + else if (!winners.length) { + errorInfo = 'There are keyrings, but none match the address'; + } + throw new Error(`${constants_1.KeyringControllerError.NoKeyring}. Error info: ${errorInfo}`); + } + /** + * Restore Keyring + * + * Attempts to initialize a new keyring from the provided serialized payload. + * On success, updates the memStore keyrings and returns the resulting + * keyring instance. + * + * @param serialized - The serialized keyring. + * @returns The deserialized keyring. + */ + async restoreKeyring(serialized) { + const keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).call(this, serialized); + if (keyring) { + await this.updateMemStoreKeyrings(); + } + return keyring; + } + /** + * Get Keyrings by Type + * + * Gets all keyrings of the given type. + * + * @param type - The keyring types to retrieve. + * @returns Keyrings matching the specified type. + */ + getKeyringsByType(type) { + const keyrings = this.keyrings.filter((keyring) => keyring.type === type); + if (!keyrings.length) { + throw new Error(constants_1.KeyringControllerError.NoKeyring); + } + return keyrings; + } + /** + * Persist All Keyrings + * + * Iterates the current `keyrings` array, + * serializes each one into a serialized array, + * encrypts that array with the provided `password`, + * and persists that encrypted string to storage. + * + * @returns Resolves to true once keyrings are persisted. + */ + async persistAllKeyrings() { + const { encryptionKey, encryptionSalt } = this.memStore.getState(); + if (!this.password && !encryptionKey) { + throw new Error(constants_1.KeyringControllerError.MissingCredentials); + } + const serializedKeyrings = await Promise.all(this.keyrings.map(async (keyring) => { + const [type, data] = await Promise.all([ + keyring.type, + keyring.serialize(), + ]); + return { type, data }; + })); + serializedKeyrings.push(...this.unsupportedKeyrings); + let vault; + let newEncryptionKey; + if (this.cacheEncryptionKey) { + if (this.password) { + const { vault: newVault, exportedKeyString } = await this.encryptor.encryptWithDetail(this.password, serializedKeyrings); + vault = newVault; + newEncryptionKey = exportedKeyString; + } + else if (encryptionKey) { + const key = await this.encryptor.importKey(encryptionKey); + const vaultJSON = await this.encryptor.encryptWithKey(key, serializedKeyrings); + vaultJSON.salt = encryptionSalt; + vault = JSON.stringify(vaultJSON); + } + } + else { + if (typeof this.password !== 'string') { + throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType); + } + vault = await this.encryptor.encrypt(this.password, serializedKeyrings); + } + if (!vault) { + throw new Error(constants_1.KeyringControllerError.MissingVaultData); + } + this.store.updateState({ vault }); + // The keyring updates need to be announced before updating the encryptionKey + // so that the updated keyring gets propagated to the extension first. + // Not calling {@link updateMemStoreKeyrings} results in the wrong account being selected + // in the extension. + await this.updateMemStoreKeyrings(); + if (newEncryptionKey) { + this.memStore.updateState({ + encryptionKey: newEncryptionKey, + encryptionSalt: JSON.parse(vault).salt, + }); + } + return true; + } + /** + * Unlock Keyrings. + * + * Attempts to unlock the persisted encrypted storage, + * initializing the persisted keyrings to RAM. + * + * @param password - The keyring controller password. + * @param encryptionKey - An exported key string to unlock keyrings with. + * @param encryptionSalt - The salt used to encrypt the vault. + * @returns The keyrings array. + */ + async unlockKeyrings(password, encryptionKey, encryptionSalt) { + const encryptedVault = this.store.getState().vault; + if (!encryptedVault) { + throw new Error(constants_1.KeyringControllerError.VaultError); + } + await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this); + let vault; + if (this.cacheEncryptionKey) { + if (password) { + const result = await this.encryptor.decryptWithDetail(password, encryptedVault); + vault = result.vault; + this.password = password; + this.memStore.updateState({ + encryptionKey: result.exportedKeyString, + encryptionSalt: result.salt, + }); + } + else { + const parsedEncryptedVault = JSON.parse(encryptedVault); + if (encryptionSalt !== parsedEncryptedVault.salt) { + throw new Error(constants_1.KeyringControllerError.ExpiredCredentials); + } + if (typeof encryptionKey !== 'string') { + throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType); + } + const key = await this.encryptor.importKey(encryptionKey); + vault = await this.encryptor.decryptWithKey(key, parsedEncryptedVault); + // This call is required on the first call because encryptionKey + // is not yet inside the memStore + this.memStore.updateState({ + encryptionKey, + encryptionSalt, + }); + } + } + else { + if (typeof password !== 'string') { + throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType); + } + vault = await this.encryptor.decrypt(password, encryptedVault); + this.password = password; + } + await Promise.all(vault.map(__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).bind(this))); + await this.updateMemStoreKeyrings(); + return this.keyrings; + } +} +exports.KeyringController = KeyringController; +_KeyringController_instances = new WeakSet(), _KeyringController_fullUpdate = function _KeyringController_fullUpdate() { + this.emit('update', this.memStore.getState()); + return this.memStore.getState(); +}, _KeyringController_createFirstKeyTree = +// ======================= +// === Private Methods === +// ======================= +/** + * Create First Key Tree. + * + * - Clears the existing vault. + * - Creates a new vault. + * - Creates a random new HD Keyring with 1 account. + * - Makes that account the selected account. + * - Faucets that account on testnet. + * - Puts the current seed words into the state tree. + * + * @returns A promise that resolves if the operation was successful. + */ +async function _KeyringController_createFirstKeyTree() { + await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this); + const keyring = await this.addNewKeyring(constants_1.KeyringType.HD); + if (!keyring) { + throw new Error(constants_1.KeyringControllerError.NoKeyring); + } + const [firstAccount] = await keyring.getAccounts(); + if (!firstAccount) { + throw new Error(constants_1.KeyringControllerError.NoAccountOnKeychain); + } + const hexAccount = (0, eth_sig_util_1.normalize)(firstAccount); + this.emit('newVault', hexAccount); + return null; +}, _KeyringController_restoreKeyring = +/** + * Restore Keyring Helper + * + * Attempts to initialize a new keyring from the provided serialized payload. + * On success, returns the resulting keyring instance. + * + * @param serialized - The serialized keyring. + * @param serialized.type - Keyring type. + * @param serialized.data - Keyring data. + * @returns The deserialized keyring or undefined if the keyring type is unsupported. + */ +async function _KeyringController_restoreKeyring(serialized) { + const { type, data } = serialized; + let keyring; + try { + keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, data); + } + catch (error) { + // Ignore error. + console.error(error); + } + if (!keyring) { + this.unsupportedKeyrings.push(serialized); + return undefined; + } + // getAccounts also validates the accounts for some keyrings + await keyring.getAccounts(); + this.keyrings.push(keyring); + return keyring; +}, _KeyringController_clearKeyrings = +/** + * Clear Keyrings + * + * Deallocates all currently managed keyrings and accounts. + * Used before initializing a new vault. + */ +async function _KeyringController_clearKeyrings() { + // clear keyrings from memory + this.keyrings = []; + this.memStore.updateState({ + keyrings: [], + }); +}, _KeyringController_setUnlocked = function _KeyringController_setUnlocked() { + this.memStore.updateState({ isUnlocked: true }); + this.emit('unlock'); +}, _KeyringController_newKeyring = +/** + * Instantiate, initialize and return a new keyring + * + * The keyring instantiated is of the given `type`. + * + * @param type - The type of keyring to add. + * @param data - The data to restore a previously serialized keyring. + * @returns The new keyring. + */ +async function _KeyringController_newKeyring(type, data) { + const keyringBuilder = this.getKeyringBuilderForType(type); + if (!keyringBuilder) { + throw new Error(`${constants_1.KeyringControllerError.NoKeyringBuilder}. Keyring type: ${type}`); + } + const keyring = keyringBuilder(); + if (!(0, utils_1.isValidJson)(data)) { + throw new Error(constants_1.KeyringControllerError.DataType); + } + await keyring.deserialize(data); + // @ts-expect-error The method 'init' is not part of the current Keyring type + if (keyring.init) { + // @ts-expect-error The method 'init' is not part of the current Keyring type + await keyring.init(); + } + return keyring; +}; +/** + * Get builder function for `Keyring` + * + * Returns a builder function for `Keyring` with a `type` property. + * + * @param KeyringConstructor - The Keyring class for the builder. + * @returns A builder function for the given Keyring. + */ +function keyringBuilderFactory(KeyringConstructor) { + const builder = () => new KeyringConstructor(); + builder.type = KeyringConstructor.type; + return builder; +} +exports.keyringBuilderFactory = keyringBuilderFactory; +/** + * Display For Keyring + * + * Is used for adding the current keyrings to the state object. + * + * @param keyring - The keyring to display. + * @returns A keyring display object, with type and accounts properties. + */ +async function displayForKeyring(keyring) { + const accounts = await keyring.getAccounts(); + return { + type: keyring.type, + accounts: accounts.map(eth_sig_util_1.normalize), + }; +} +//# sourceMappingURL=KeyringController.js.map \ No newline at end of file diff --git a/dist/KeyringController.js.map b/dist/KeyringController.js.map new file mode 100644 index 00000000..b4b82b9d --- /dev/null +++ b/dist/KeyringController.js.map @@ -0,0 +1 @@ +{"version":3,"file":"KeyringController.js","sourceRoot":"","sources":["../src/KeyringController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TypedTransaction, TxData } from '@ethereumjs/tx';\nimport * as encryptorUtils from '@metamask/browser-passworder';\nimport HDKeyring from '@metamask/eth-hd-keyring';\nimport { normalize as normalizeToHex } from '@metamask/eth-sig-util';\nimport SimpleKeyring from '@metamask/eth-simple-keyring';\nimport { remove0x, isValidJson } from '@metamask/utils';\nimport type {\n Hex,\n Json,\n Bytes,\n Keyring,\n KeyringClass,\n Eip1024EncryptedData,\n} from '@metamask/utils';\n// TODO: Stop using `events`, and remove the notice about this from the README\n// eslint-disable-next-line import/no-nodejs-modules\nimport { EventEmitter } from 'events';\nimport ObservableStore from 'obs-store';\n\nimport { KeyringType, KeyringControllerError } from './constants';\nimport {\n SerializedKeyring,\n KeyringControllerArgs,\n KeyringControllerState,\n} from './types';\n\nconst defaultKeyringBuilders = [\n keyringBuilderFactory(SimpleKeyring),\n keyringBuilderFactory(HDKeyring),\n];\n\nclass KeyringController extends EventEmitter {\n keyringBuilders: { (): Keyring; type: string }[];\n\n public store: typeof ObservableStore;\n\n public memStore: typeof ObservableStore;\n\n public encryptor: any;\n\n public keyrings: Keyring[];\n\n public cacheEncryptionKey: boolean;\n\n public unsupportedKeyrings: SerializedKeyring[];\n\n public password?: string;\n\n constructor({\n keyringBuilders,\n cacheEncryptionKey,\n initState = {},\n encryptor = encryptorUtils,\n }: KeyringControllerArgs) {\n super();\n this.keyringBuilders = keyringBuilders\n ? defaultKeyringBuilders.concat(keyringBuilders)\n : defaultKeyringBuilders;\n this.store = new ObservableStore(initState);\n this.memStore = new ObservableStore({\n isUnlocked: false,\n keyringTypes: this.keyringBuilders.map(\n (keyringBuilder) => keyringBuilder.type,\n ),\n keyrings: [],\n encryptionKey: null,\n });\n\n this.encryptor = encryptor;\n this.keyrings = [];\n this.unsupportedKeyrings = [];\n\n // This option allows the controller to cache an exported key\n // for use in decrypting and encrypting data without password\n this.cacheEncryptionKey = Boolean(cacheEncryptionKey);\n }\n\n /**\n * Full Update\n *\n * Emits the `update` event and @returns a Promise that resolves to\n * the current state.\n *\n * Frequently used to end asynchronous chains in this class,\n * indicating consumers can often either listen for updates,\n * or accept a state-resolving promise to consume their results.\n *\n * @returns The controller state.\n */\n #fullUpdate() {\n this.emit('update', this.memStore.getState());\n return this.memStore.getState();\n }\n\n /**\n * =======================================\n * === Public Vault Management Methods ===\n * =======================================\n */\n\n /**\n * Create New Vault And Keychain\n *\n * Destroys any old encrypted storage,\n * creates a new encrypted store with the given password,\n * randomly creates a new HD wallet with 1 account,\n * faucets that account on the testnet.\n *\n * @fires KeyringController#unlock\n * @param password - The password to encrypt the vault with.\n * @returns A promise that resolves to the state.\n */\n async createNewVaultAndKeychain(\n password: string,\n ): Promise {\n this.password = password;\n\n await this.#createFirstKeyTree();\n this.#setUnlocked();\n return this.#fullUpdate();\n }\n\n /**\n * CreateNewVaultAndRestore\n *\n * Destroys any old encrypted storage,\n * creates a new encrypted store with the given password,\n * creates a new HD wallet from the given seed with 1 account.\n *\n * @fires KeyringController#unlock\n * @param password - The password to encrypt the vault with.\n * @param seedPhrase - The BIP39-compliant seed phrase,\n * either as a string or Uint8Array.\n * @returns A promise that resolves to the state.\n */\n async createNewVaultAndRestore(\n password: string,\n seedPhrase: Uint8Array | string | number[],\n ): Promise {\n if (typeof password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n this.password = password;\n\n await this.#clearKeyrings();\n const keyring = await this.addNewKeyring(KeyringType.HD, {\n mnemonic: seedPhrase,\n numberOfAccounts: 1,\n });\n\n const [firstAccount] = await keyring.getAccounts();\n\n if (!firstAccount) {\n throw new Error(KeyringControllerError.NoFirstAccount);\n }\n this.#setUnlocked();\n return this.#fullUpdate();\n }\n\n /**\n * Set Locked.\n * This method deallocates all secrets, and effectively locks MetaMask.\n *\n * @fires KeyringController#lock\n * @returns A promise that resolves to the state.\n */\n async setLocked(): Promise {\n delete this.password;\n\n // set locked\n this.memStore.updateState({\n isUnlocked: false,\n encryptionKey: null,\n encryptionSalt: null,\n });\n\n // remove keyrings\n this.keyrings = [];\n await this.updateMemStoreKeyrings();\n this.emit('lock');\n return this.#fullUpdate();\n }\n\n /**\n * Submit password.\n *\n * Attempts to decrypt the current vault and load its keyrings\n * into memory.\n *\n * Temporarily also migrates any old-style vaults first, as well\n * (Pre MetaMask 3.0.0).\n *\n * @fires KeyringController#unlock\n * @param password - The keyring controller password.\n * @returns A promise that resolves to the state.\n */\n async submitPassword(password: string): Promise {\n this.keyrings = await this.unlockKeyrings(password);\n\n this.#setUnlocked();\n return this.#fullUpdate();\n }\n\n /**\n * Submit Encryption Key.\n *\n * Attempts to decrypt the current vault and load its keyrings\n * into memory based on the vault and CryptoKey information.\n *\n * @fires KeyringController#unlock\n * @param encryptionKey - The encrypted key information used to decrypt the vault.\n * @param encryptionSalt - The salt used to generate the last key.\n * @returns A promise that resolves to the state.\n */\n async submitEncryptionKey(\n encryptionKey: string,\n encryptionSalt: string,\n ): Promise {\n this.keyrings = await this.unlockKeyrings(\n undefined,\n encryptionKey,\n encryptionSalt,\n );\n this.#setUnlocked();\n return this.#fullUpdate();\n }\n\n /**\n * Verify Password\n *\n * Attempts to decrypt the current vault with a given password\n * to verify its validity.\n *\n * @param password - The vault password.\n */\n async verifyPassword(password: string): Promise {\n const encryptedVault = this.store.getState().vault;\n if (!encryptedVault) {\n throw new Error(KeyringControllerError.VaultError);\n }\n await this.encryptor.decrypt(password, encryptedVault);\n }\n\n /**\n * =========================================\n * === Public Account Management Methods ===\n * =========================================\n */\n\n /**\n * Add New Account.\n *\n * Calls the `addAccounts` method on the given keyring,\n * and then saves those changes.\n *\n * @param selectedKeyring - The currently selected keyring.\n * @returns A Promise that resolves to the state.\n */\n async addNewAccount(\n selectedKeyring: Keyring,\n ): Promise {\n const accounts = await selectedKeyring.addAccounts(1);\n accounts.forEach((hexAccount) => {\n this.emit('newAccount', hexAccount);\n });\n\n await this.persistAllKeyrings();\n return this.#fullUpdate();\n }\n\n /**\n * Export Account\n *\n * Requests the private key from the keyring controlling\n * the specified address.\n *\n * Returns a Promise that may resolve with the private key string.\n *\n * @param address - The address of the account to export.\n * @returns The private key of the account.\n */\n async exportAccount(address: string): Promise {\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.exportAccount) {\n throw new Error(KeyringControllerError.UnsupportedExportAccount);\n }\n\n return await keyring.exportAccount(normalizeToHex(address) as Hex);\n }\n\n /**\n * Remove Account.\n *\n * Removes a specific account from a keyring\n * If the account is the last/only one then it also removes the keyring.\n *\n * @param address - The address of the account to remove.\n * @returns A promise that resolves if the operation was successful.\n */\n async removeAccount(address: Hex): Promise {\n const keyring = await this.getKeyringForAccount(address);\n\n // Not all the keyrings support this, so we have to check\n if (!keyring.removeAccount) {\n throw new Error(KeyringControllerError.UnsupportedRemoveAccount);\n }\n keyring.removeAccount(address);\n this.emit('removedAccount', address);\n\n const accounts = await keyring.getAccounts();\n // Check if this was the last/only account\n if (accounts.length === 0) {\n await this.removeEmptyKeyrings();\n }\n\n await this.persistAllKeyrings();\n return this.#fullUpdate();\n }\n\n /**\n * Get Accounts\n *\n * Returns the public addresses of all current accounts\n * managed by all currently unlocked keyrings.\n *\n * @returns The array of accounts.\n */\n async getAccounts(): Promise {\n const keyrings = this.keyrings || [];\n\n const keyringArrays = await Promise.all(\n keyrings.map(async (keyring) => keyring.getAccounts()),\n );\n const addresses = keyringArrays.reduce((res, arr) => {\n return res.concat(arr);\n }, []);\n\n return addresses.map(normalizeToHex);\n }\n\n /**\n * Get Keyring Class For Type\n *\n * Searches the current `keyringBuilders` array\n * for a Keyring builder whose unique `type` property\n * matches the provided `type`,\n * returning it if it exists.\n *\n * @param type - The type whose class to get.\n * @returns The class, if it exists.\n */\n getKeyringBuilderForType(\n type: string,\n ): { (): Keyring; type: string } | undefined {\n return this.keyringBuilders.find(\n (keyringBuilder) => keyringBuilder.type === type,\n );\n }\n\n /**\n * Update memStore Keyrings\n *\n * Updates the in-memory keyrings, without persisting.\n */\n async updateMemStoreKeyrings(): Promise {\n const keyrings = await Promise.all(this.keyrings.map(displayForKeyring));\n return this.memStore.updateState({ keyrings });\n }\n\n /**\n * ===========================================\n * === Public RPC Requests Routing Methods ===\n * ===========================================\n */\n\n /**\n * Sign Ethereum Transaction\n *\n * Signs an Ethereum transaction object.\n *\n * @param ethTx - The transaction to sign.\n * @param rawAddress - The transaction 'from' address.\n * @param opts - Signing options.\n * @returns The signed transaction object.\n */\n async signTransaction(\n ethTx: TypedTransaction,\n rawAddress: string,\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signTransaction) {\n throw new Error(KeyringControllerError.UnsupportedSignTransaction);\n }\n\n return await keyring.signTransaction(address, ethTx, opts);\n }\n\n /**\n * Sign Message\n *\n * Attempts to sign the provided message parameters.\n *\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The message to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signMessage(\n msgParams: {\n from: string;\n data: string;\n },\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signMessage) {\n throw new Error(KeyringControllerError.UnsupportedSignMessage);\n }\n\n return await keyring.signMessage(address, msgParams.data, opts);\n }\n\n /**\n * Sign Personal Message\n *\n * Attempts to sign the provided message parameters.\n * Prefixes the hash before signing per the personal sign expectation.\n *\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The message to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signPersonalMessage(\n msgParams: {\n from: string;\n data: string;\n },\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signPersonalMessage) {\n throw new Error(KeyringControllerError.UnsupportedSignPersonalMessage);\n }\n\n const normalizedData = normalizeToHex(msgParams.data) as Hex;\n\n return await keyring.signPersonalMessage(address, normalizedData, opts);\n }\n\n /**\n * Get encryption public key\n *\n * Get encryption public key for using in encrypt/decrypt process.\n *\n * @param address - The address to get the encryption public key for.\n * @param opts - Additional encryption options.\n * @returns The public key.\n */\n async getEncryptionPublicKey(\n address: string,\n opts: Record = {},\n ): Promise {\n const normalizedAddress = normalizeToHex(address) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.getEncryptionPublicKey) {\n throw new Error(KeyringControllerError.UnsupportedGetEncryptionPublicKey);\n }\n\n return await keyring.getEncryptionPublicKey(normalizedAddress, opts);\n }\n\n /**\n * Decrypt Message\n *\n * Attempts to decrypt the provided message parameters.\n *\n * @param msgParams - The decryption message parameters.\n * @param msgParams.from - The address of the account you want to use to decrypt the message.\n * @param msgParams.data - The encrypted data that you want to decrypt.\n * @returns The raw decryption result.\n */\n async decryptMessage(msgParams: {\n from: string;\n data: Eip1024EncryptedData;\n }): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.decryptMessage) {\n throw new Error(KeyringControllerError.UnsupportedDecryptMessage);\n }\n\n return keyring.decryptMessage(address, msgParams.data);\n }\n\n /**\n * Sign Typed Data.\n *\n * @see {@link https://github.com/ethereum/EIPs/pull/712#issuecomment-329988454|EIP712}.\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The data to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signTypedMessage(\n msgParams: {\n from: string;\n data: Record[];\n },\n opts: Record = { version: 'V1' },\n ): Promise {\n const address = normalizeToHex(msgParams.from);\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signTypedData) {\n throw new Error(KeyringControllerError.UnsupportedSignTypedMessage);\n }\n\n // Looks like this is not well defined in the Keyring interface since\n // our tests show that we should be able to pass an array.\n // @ts-expect-error Missing other required permission types.\n return keyring.signTypedData(address, msgParams.data, opts);\n }\n\n /**\n * Gets the app key address for the given Ethereum address and origin.\n *\n * @param rawAddress - The Ethereum address for the app key.\n * @param origin - The origin for the app key.\n * @returns The app key address.\n */\n async getAppKeyAddress(rawAddress: string, origin: string): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.getAppKeyAddress) {\n throw new Error(KeyringControllerError.UnsupportedGetAppKeyAddress);\n }\n\n return keyring.getAppKeyAddress(address, origin);\n }\n\n /**\n * Exports an app key private key for the given Ethereum address and origin.\n *\n * @param rawAddress - The Ethereum address for the app key.\n * @param origin - The origin for the app key.\n * @returns The app key private key.\n */\n async exportAppKeyForAddress(\n rawAddress: string,\n origin: string,\n ): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.exportAccount) {\n throw new Error(KeyringControllerError.UnsupportedExportAppKeyForAddress);\n }\n return keyring.exportAccount(address, { withAppKeyOrigin: origin });\n }\n\n /**\n * =========================================\n * === Public Keyring Management Methods ===\n * =========================================\n */\n\n /**\n * Add New Keyring\n *\n * Adds a new Keyring of the given `type` to the vault\n * and the current decrypted Keyrings array.\n *\n * All Keyring classes implement a unique `type` string,\n * and this is used to retrieve them from the keyringBuilders array.\n *\n * @param type - The type of keyring to add.\n * @param opts - The constructor options for the keyring.\n * @returns The new keyring.\n */\n async addNewKeyring(\n type: string,\n opts: Record = {},\n ): Promise> {\n let keyring: Keyring;\n switch (type) {\n case KeyringType.Simple:\n keyring = await this.#newKeyring(type, opts.privateKeys);\n break;\n default:\n keyring = await this.#newKeyring(type, opts);\n break;\n }\n\n if (!keyring) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n\n if (!opts.mnemonic && type === KeyringType.HD) {\n if (!keyring.generateRandomMnemonic) {\n throw new Error(\n KeyringControllerError.UnsupportedGenerateRandomMnemonic,\n );\n }\n\n keyring.generateRandomMnemonic();\n await keyring.addAccounts(1);\n }\n\n const accounts = await keyring.getAccounts();\n await this.checkForDuplicate(type, accounts);\n\n this.keyrings.push(keyring);\n await this.persistAllKeyrings();\n\n this.#fullUpdate();\n\n return keyring;\n }\n\n /**\n * Remove empty keyrings.\n *\n * Loops through the keyrings and removes the ones with empty accounts\n * (usually after removing the last / only account) from a keyring.\n */\n async removeEmptyKeyrings(): Promise {\n const validKeyrings: Keyring[] = [];\n\n // Since getAccounts returns a Promise\n // We need to wait to hear back form each keyring\n // in order to decide which ones are now valid (accounts.length > 0)\n\n await Promise.all(\n this.keyrings.map(async (keyring: Keyring) => {\n const accounts = await keyring.getAccounts();\n if (accounts.length > 0) {\n validKeyrings.push(keyring);\n }\n }),\n );\n this.keyrings = validKeyrings;\n }\n\n /**\n * Checks for duplicate keypairs, using the the first account in the given\n * array. Rejects if a duplicate is found.\n *\n * Only supports 'Simple Key Pair'.\n *\n * @param type - The key pair type to check for.\n * @param newAccountArray - Array of new accounts.\n * @returns The account, if no duplicate is found.\n */\n async checkForDuplicate(\n type: string,\n newAccountArray: string[],\n ): Promise {\n const accounts = await this.getAccounts();\n\n switch (type) {\n case KeyringType.Simple: {\n const isIncluded = Boolean(\n accounts.find(\n (key) =>\n newAccountArray[0] &&\n (key === newAccountArray[0] ||\n key === remove0x(newAccountArray[0])),\n ),\n );\n\n if (isIncluded) {\n throw new Error(KeyringControllerError.DuplicatedAccount);\n }\n return newAccountArray;\n }\n\n default: {\n return newAccountArray;\n }\n }\n }\n\n /**\n * Get Keyring For Account\n *\n * Returns the currently initialized keyring that manages\n * the specified `address` if one exists.\n *\n * @param address - An account address.\n * @returns The keyring of the account, if it exists.\n */\n async getKeyringForAccount(address: string): Promise> {\n const hexed = normalizeToHex(address);\n\n const candidates = await Promise.all(\n this.keyrings.map(async (keyring) => {\n return Promise.all([keyring, keyring.getAccounts()]);\n }),\n );\n\n const winners = candidates.filter((candidate) => {\n const accounts = candidate[1].map(normalizeToHex);\n return accounts.includes(hexed);\n });\n\n if (winners.length && winners[0]?.length) {\n return winners[0][0];\n }\n\n // Adding more info to the error\n let errorInfo = '';\n if (!address) {\n errorInfo = 'The address passed in is invalid/empty';\n } else if (!candidates.length) {\n errorInfo = 'There are no keyrings';\n } else if (!winners.length) {\n errorInfo = 'There are keyrings, but none match the address';\n }\n throw new Error(\n `${KeyringControllerError.NoKeyring}. Error info: ${errorInfo}`,\n );\n }\n\n /**\n * Restore Keyring\n *\n * Attempts to initialize a new keyring from the provided serialized payload.\n * On success, updates the memStore keyrings and returns the resulting\n * keyring instance.\n *\n * @param serialized - The serialized keyring.\n * @returns The deserialized keyring.\n */\n async restoreKeyring(\n serialized: SerializedKeyring,\n ): Promise | undefined> {\n const keyring = await this.#restoreKeyring(serialized);\n if (keyring) {\n await this.updateMemStoreKeyrings();\n }\n return keyring;\n }\n\n /**\n * Get Keyrings by Type\n *\n * Gets all keyrings of the given type.\n *\n * @param type - The keyring types to retrieve.\n * @returns Keyrings matching the specified type.\n */\n getKeyringsByType(type: string): Keyring[] {\n const keyrings = this.keyrings.filter((keyring) => keyring.type === type);\n if (!keyrings.length) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n return keyrings;\n }\n\n /**\n * Persist All Keyrings\n *\n * Iterates the current `keyrings` array,\n * serializes each one into a serialized array,\n * encrypts that array with the provided `password`,\n * and persists that encrypted string to storage.\n *\n * @returns Resolves to true once keyrings are persisted.\n */\n async persistAllKeyrings(): Promise {\n const { encryptionKey, encryptionSalt } = this.memStore.getState();\n\n if (!this.password && !encryptionKey) {\n throw new Error(KeyringControllerError.MissingCredentials);\n }\n\n const serializedKeyrings = await Promise.all(\n this.keyrings.map(async (keyring) => {\n const [type, data] = await Promise.all([\n keyring.type,\n keyring.serialize(),\n ]);\n return { type, data };\n }),\n );\n\n serializedKeyrings.push(...this.unsupportedKeyrings);\n\n let vault;\n let newEncryptionKey;\n\n if (this.cacheEncryptionKey) {\n if (this.password) {\n const { vault: newVault, exportedKeyString } =\n await this.encryptor.encryptWithDetail(\n this.password,\n serializedKeyrings,\n );\n\n vault = newVault;\n newEncryptionKey = exportedKeyString;\n } else if (encryptionKey) {\n const key = await this.encryptor.importKey(encryptionKey);\n const vaultJSON = await this.encryptor.encryptWithKey(\n key,\n serializedKeyrings,\n );\n vaultJSON.salt = encryptionSalt;\n vault = JSON.stringify(vaultJSON);\n }\n } else {\n if (typeof this.password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n vault = await this.encryptor.encrypt(this.password, serializedKeyrings);\n }\n\n if (!vault) {\n throw new Error(KeyringControllerError.MissingVaultData);\n }\n\n this.store.updateState({ vault });\n\n // The keyring updates need to be announced before updating the encryptionKey\n // so that the updated keyring gets propagated to the extension first.\n // Not calling {@link updateMemStoreKeyrings} results in the wrong account being selected\n // in the extension.\n await this.updateMemStoreKeyrings();\n if (newEncryptionKey) {\n this.memStore.updateState({\n encryptionKey: newEncryptionKey,\n encryptionSalt: JSON.parse(vault).salt,\n });\n }\n\n return true;\n }\n\n /**\n * Unlock Keyrings.\n *\n * Attempts to unlock the persisted encrypted storage,\n * initializing the persisted keyrings to RAM.\n *\n * @param password - The keyring controller password.\n * @param encryptionKey - An exported key string to unlock keyrings with.\n * @param encryptionSalt - The salt used to encrypt the vault.\n * @returns The keyrings array.\n */\n async unlockKeyrings(\n password: string | undefined,\n encryptionKey?: string,\n encryptionSalt?: string,\n ): Promise[]> {\n const encryptedVault = this.store.getState().vault;\n if (!encryptedVault) {\n throw new Error(KeyringControllerError.VaultError);\n }\n\n await this.#clearKeyrings();\n\n let vault;\n\n if (this.cacheEncryptionKey) {\n if (password) {\n const result = await this.encryptor.decryptWithDetail(\n password,\n encryptedVault,\n );\n vault = result.vault;\n this.password = password;\n\n this.memStore.updateState({\n encryptionKey: result.exportedKeyString,\n encryptionSalt: result.salt,\n });\n } else {\n const parsedEncryptedVault = JSON.parse(encryptedVault);\n\n if (encryptionSalt !== parsedEncryptedVault.salt) {\n throw new Error(KeyringControllerError.ExpiredCredentials);\n }\n\n if (typeof encryptionKey !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n\n const key = await this.encryptor.importKey(encryptionKey);\n vault = await this.encryptor.decryptWithKey(key, parsedEncryptedVault);\n\n // This call is required on the first call because encryptionKey\n // is not yet inside the memStore\n this.memStore.updateState({\n encryptionKey,\n encryptionSalt,\n });\n }\n } else {\n if (typeof password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n\n vault = await this.encryptor.decrypt(password, encryptedVault);\n this.password = password;\n }\n\n await Promise.all(vault.map(this.#restoreKeyring.bind(this)));\n await this.updateMemStoreKeyrings();\n return this.keyrings;\n }\n\n // =======================\n // === Private Methods ===\n // =======================\n\n /**\n * Create First Key Tree.\n *\n * - Clears the existing vault.\n * - Creates a new vault.\n * - Creates a random new HD Keyring with 1 account.\n * - Makes that account the selected account.\n * - Faucets that account on testnet.\n * - Puts the current seed words into the state tree.\n *\n * @returns A promise that resolves if the operation was successful.\n */\n async #createFirstKeyTree(): Promise {\n await this.#clearKeyrings();\n\n const keyring = await this.addNewKeyring(KeyringType.HD);\n if (!keyring) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n\n const [firstAccount] = await keyring.getAccounts();\n if (!firstAccount) {\n throw new Error(KeyringControllerError.NoAccountOnKeychain);\n }\n\n const hexAccount = normalizeToHex(firstAccount);\n this.emit('newVault', hexAccount);\n return null;\n }\n\n /**\n * Restore Keyring Helper\n *\n * Attempts to initialize a new keyring from the provided serialized payload.\n * On success, returns the resulting keyring instance.\n *\n * @param serialized - The serialized keyring.\n * @param serialized.type - Keyring type.\n * @param serialized.data - Keyring data.\n * @returns The deserialized keyring or undefined if the keyring type is unsupported.\n */\n async #restoreKeyring(\n serialized: SerializedKeyring,\n ): Promise | undefined> {\n const { type, data } = serialized;\n\n let keyring: Keyring | undefined;\n try {\n keyring = await this.#newKeyring(type, data);\n } catch (error) {\n // Ignore error.\n console.error(error);\n }\n\n if (!keyring) {\n this.unsupportedKeyrings.push(serialized);\n return undefined;\n }\n\n // getAccounts also validates the accounts for some keyrings\n await keyring.getAccounts();\n this.keyrings.push(keyring);\n return keyring;\n }\n\n /**\n * Clear Keyrings\n *\n * Deallocates all currently managed keyrings and accounts.\n * Used before initializing a new vault.\n */\n async #clearKeyrings(): Promise {\n // clear keyrings from memory\n this.keyrings = [];\n this.memStore.updateState({\n keyrings: [],\n });\n }\n\n /**\n * Unlock Keyrings\n *\n * Unlocks the keyrings.\n *\n * @fires KeyringController#unlock\n */\n #setUnlocked(): void {\n this.memStore.updateState({ isUnlocked: true });\n this.emit('unlock');\n }\n\n /**\n * Instantiate, initialize and return a new keyring\n *\n * The keyring instantiated is of the given `type`.\n *\n * @param type - The type of keyring to add.\n * @param data - The data to restore a previously serialized keyring.\n * @returns The new keyring.\n */\n async #newKeyring(type: string, data: unknown): Promise> {\n const keyringBuilder = this.getKeyringBuilderForType(type);\n\n if (!keyringBuilder) {\n throw new Error(\n `${KeyringControllerError.NoKeyringBuilder}. Keyring type: ${type}`,\n );\n }\n\n const keyring = keyringBuilder();\n\n if (!isValidJson(data)) {\n throw new Error(KeyringControllerError.DataType);\n }\n\n await keyring.deserialize(data);\n\n // @ts-expect-error The method 'init' is not part of the current Keyring type\n if (keyring.init) {\n // @ts-expect-error The method 'init' is not part of the current Keyring type\n await keyring.init();\n }\n\n return keyring;\n }\n}\n\n/**\n * Get builder function for `Keyring`\n *\n * Returns a builder function for `Keyring` with a `type` property.\n *\n * @param KeyringConstructor - The Keyring class for the builder.\n * @returns A builder function for the given Keyring.\n */\nfunction keyringBuilderFactory(KeyringConstructor: KeyringClass) {\n const builder = () => new KeyringConstructor();\n\n builder.type = KeyringConstructor.type;\n\n return builder;\n}\n\n/**\n * Display For Keyring\n *\n * Is used for adding the current keyrings to the state object.\n *\n * @param keyring - The keyring to display.\n * @returns A keyring display object, with type and accounts properties.\n */\nasync function displayForKeyring(\n keyring: Keyring,\n): Promise<{ type: string; accounts: string[] }> {\n const accounts = await keyring.getAccounts();\n\n return {\n type: keyring.type,\n accounts: accounts.map(normalizeToHex),\n };\n}\n\nexport { KeyringController, keyringBuilderFactory };\n"]} \ No newline at end of file diff --git a/dist/constants.d.ts b/dist/constants.d.ts new file mode 100644 index 00000000..2b89fd0f --- /dev/null +++ b/dist/constants.d.ts @@ -0,0 +1,28 @@ +export declare enum KeyringType { + HD = "HD Key Tree", + Simple = "Simple Key Pair" +} +export declare enum KeyringControllerError { + NoKeyring = "KeyringController - No keyring found", + WrongPasswordType = "KeyringController - Password must be of type string.", + NoFirstAccount = "KeyringController - First Account not found.", + DuplicatedAccount = "KeyringController - The account you are trying to import is a duplicate", + VaultError = "KeyringController - Cannot unlock without a previous vault.", + UnsupportedGenerateRandomMnemonic = "KeyringController - The current keyring does not support the method generateRandomMnemonic.", + UnsupportedExportAccount = "`KeyringController - The keyring for the current address does not support the method exportAccount", + UnsupportedRemoveAccount = "`KeyringController - The keyring for the current address does not support the method removeAccount", + UnsupportedSignTransaction = "KeyringController - The keyring for the current address does not support the method signTransaction.", + UnsupportedSignMessage = "KeyringController - The keyring for the current address does not support the method signMessage.", + UnsupportedSignPersonalMessage = "KeyringController - The keyring for the current address does not support the method signPersonalMessage.", + UnsupportedGetEncryptionPublicKey = "KeyringController - The keyring for the current address does not support the method getEncryptionPublicKey.", + UnsupportedDecryptMessage = "KeyringController - The keyring for the current address does not support the method decryptMessage.", + UnsupportedSignTypedMessage = "KeyringController - The keyring for the current address does not support the method signTypedMessage.", + UnsupportedGetAppKeyAddress = "KeyringController - The keyring for the current address does not support the method getAppKeyAddress.", + UnsupportedExportAppKeyForAddress = "KeyringController - The keyring for the current address does not support the method exportAppKeyForAddress.", + NoAccountOnKeychain = "KeyringController - The keyring for the current address does not support the method decryptMessage.", + MissingCredentials = "KeyringController - Cannot persist vault without password and encryption key", + MissingVaultData = "KeyringController - Cannot persist vault without vault information", + ExpiredCredentials = "KeyringController - Encryption key and salt provided are expired", + NoKeyringBuilder = "KeyringController - No keyringBuilder found for keyring", + DataType = "KeyringController - Incorrect data type provided" +} diff --git a/dist/constants.js b/dist/constants.js new file mode 100644 index 00000000..0658ade9 --- /dev/null +++ b/dist/constants.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.KeyringControllerError = exports.KeyringType = void 0; +var KeyringType; +(function (KeyringType) { + KeyringType["HD"] = "HD Key Tree"; + KeyringType["Simple"] = "Simple Key Pair"; +})(KeyringType = exports.KeyringType || (exports.KeyringType = {})); +var KeyringControllerError; +(function (KeyringControllerError) { + KeyringControllerError["NoKeyring"] = "KeyringController - No keyring found"; + KeyringControllerError["WrongPasswordType"] = "KeyringController - Password must be of type string."; + KeyringControllerError["NoFirstAccount"] = "KeyringController - First Account not found."; + KeyringControllerError["DuplicatedAccount"] = "KeyringController - The account you are trying to import is a duplicate"; + KeyringControllerError["VaultError"] = "KeyringController - Cannot unlock without a previous vault."; + KeyringControllerError["UnsupportedGenerateRandomMnemonic"] = "KeyringController - The current keyring does not support the method generateRandomMnemonic."; + KeyringControllerError["UnsupportedExportAccount"] = "`KeyringController - The keyring for the current address does not support the method exportAccount"; + KeyringControllerError["UnsupportedRemoveAccount"] = "`KeyringController - The keyring for the current address does not support the method removeAccount"; + KeyringControllerError["UnsupportedSignTransaction"] = "KeyringController - The keyring for the current address does not support the method signTransaction."; + KeyringControllerError["UnsupportedSignMessage"] = "KeyringController - The keyring for the current address does not support the method signMessage."; + KeyringControllerError["UnsupportedSignPersonalMessage"] = "KeyringController - The keyring for the current address does not support the method signPersonalMessage."; + KeyringControllerError["UnsupportedGetEncryptionPublicKey"] = "KeyringController - The keyring for the current address does not support the method getEncryptionPublicKey."; + KeyringControllerError["UnsupportedDecryptMessage"] = "KeyringController - The keyring for the current address does not support the method decryptMessage."; + KeyringControllerError["UnsupportedSignTypedMessage"] = "KeyringController - The keyring for the current address does not support the method signTypedMessage."; + KeyringControllerError["UnsupportedGetAppKeyAddress"] = "KeyringController - The keyring for the current address does not support the method getAppKeyAddress."; + KeyringControllerError["UnsupportedExportAppKeyForAddress"] = "KeyringController - The keyring for the current address does not support the method exportAppKeyForAddress."; + KeyringControllerError["NoAccountOnKeychain"] = "KeyringController - The keyring for the current address does not support the method decryptMessage."; + KeyringControllerError["MissingCredentials"] = "KeyringController - Cannot persist vault without password and encryption key"; + KeyringControllerError["MissingVaultData"] = "KeyringController - Cannot persist vault without vault information"; + KeyringControllerError["ExpiredCredentials"] = "KeyringController - Encryption key and salt provided are expired"; + KeyringControllerError["NoKeyringBuilder"] = "KeyringController - No keyringBuilder found for keyring"; + KeyringControllerError["DataType"] = "KeyringController - Incorrect data type provided"; +})(KeyringControllerError = exports.KeyringControllerError || (exports.KeyringControllerError = {})); +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/constants.js.map b/dist/constants.js.map new file mode 100644 index 00000000..33541a79 --- /dev/null +++ b/dist/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAA,IAAY,WAGX;AAHD,WAAY,WAAW;IACrB,iCAAkB,CAAA;IAClB,yCAA0B,CAAA;AAC5B,CAAC,EAHW,WAAW,GAAX,mBAAW,KAAX,mBAAW,QAGtB;AAED,IAAY,sBAuBX;AAvBD,WAAY,sBAAsB;IAChC,4EAAkD,CAAA;IAClD,oGAA0E,CAAA;IAC1E,yFAA+D,CAAA;IAC/D,uHAA6F,CAAA;IAC7F,oGAA0E,CAAA;IAC1E,2JAAiI,CAAA;IACjI,yJAA+H,CAAA;IAC/H,yJAA+H,CAAA;IAC/H,6JAAmI,CAAA;IACnI,qJAA2H,CAAA;IAC3H,qKAA2I,CAAA;IAC3I,2KAAiJ,CAAA;IACjJ,2JAAiI,CAAA;IACjI,+JAAqI,CAAA;IACrI,+JAAqI,CAAA;IACrI,2KAAiJ,CAAA;IACjJ,qJAA2H,CAAA;IAC3H,6HAAmG,CAAA;IACnG,iHAAuF,CAAA;IACvF,iHAAuF,CAAA;IACvF,sGAA4E,CAAA;IAC5E,uFAA6D,CAAA;AAC/D,CAAC,EAvBW,sBAAsB,GAAtB,8BAAsB,KAAtB,8BAAsB,QAuBjC","sourcesContent":["export enum KeyringType {\n HD = 'HD Key Tree',\n Simple = 'Simple Key Pair',\n}\n\nexport enum KeyringControllerError {\n NoKeyring = 'KeyringController - No keyring found',\n WrongPasswordType = 'KeyringController - Password must be of type string.',\n NoFirstAccount = 'KeyringController - First Account not found.',\n DuplicatedAccount = 'KeyringController - The account you are trying to import is a duplicate',\n VaultError = 'KeyringController - Cannot unlock without a previous vault.',\n UnsupportedGenerateRandomMnemonic = 'KeyringController - The current keyring does not support the method generateRandomMnemonic.',\n UnsupportedExportAccount = '`KeyringController - The keyring for the current address does not support the method exportAccount',\n UnsupportedRemoveAccount = '`KeyringController - The keyring for the current address does not support the method removeAccount',\n UnsupportedSignTransaction = 'KeyringController - The keyring for the current address does not support the method signTransaction.',\n UnsupportedSignMessage = 'KeyringController - The keyring for the current address does not support the method signMessage.',\n UnsupportedSignPersonalMessage = 'KeyringController - The keyring for the current address does not support the method signPersonalMessage.',\n UnsupportedGetEncryptionPublicKey = 'KeyringController - The keyring for the current address does not support the method getEncryptionPublicKey.',\n UnsupportedDecryptMessage = 'KeyringController - The keyring for the current address does not support the method decryptMessage.',\n UnsupportedSignTypedMessage = 'KeyringController - The keyring for the current address does not support the method signTypedMessage.',\n UnsupportedGetAppKeyAddress = 'KeyringController - The keyring for the current address does not support the method getAppKeyAddress.',\n UnsupportedExportAppKeyForAddress = 'KeyringController - The keyring for the current address does not support the method exportAppKeyForAddress.',\n NoAccountOnKeychain = 'KeyringController - The keyring for the current address does not support the method decryptMessage.',\n MissingCredentials = 'KeyringController - Cannot persist vault without password and encryption key',\n MissingVaultData = 'KeyringController - Cannot persist vault without vault information',\n ExpiredCredentials = 'KeyringController - Encryption key and salt provided are expired',\n NoKeyringBuilder = 'KeyringController - No keyringBuilder found for keyring',\n DataType = 'KeyringController - Incorrect data type provided',\n}\n"]} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 00000000..17d565c7 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,2 @@ +export { KeyringController, keyringBuilderFactory } from './KeyringController'; +export { KeyringType, KeyringControllerError } from './constants'; diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 00000000..3bdcebe9 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.KeyringControllerError = exports.KeyringType = exports.keyringBuilderFactory = exports.KeyringController = void 0; +var KeyringController_1 = require("./KeyringController"); +Object.defineProperty(exports, "KeyringController", { enumerable: true, get: function () { return KeyringController_1.KeyringController; } }); +Object.defineProperty(exports, "keyringBuilderFactory", { enumerable: true, get: function () { return KeyringController_1.keyringBuilderFactory; } }); +var constants_1 = require("./constants"); +Object.defineProperty(exports, "KeyringType", { enumerable: true, get: function () { return constants_1.KeyringType; } }); +Object.defineProperty(exports, "KeyringControllerError", { enumerable: true, get: function () { return constants_1.KeyringControllerError; } }); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 00000000..ca1edd62 --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yDAA+E;AAAtE,sHAAA,iBAAiB,OAAA;AAAE,0HAAA,qBAAqB,OAAA;AAEjD,yCAAkE;AAAzD,wGAAA,WAAW,OAAA;AAAE,mHAAA,sBAAsB,OAAA","sourcesContent":["export { KeyringController, keyringBuilderFactory } from './KeyringController';\n\nexport { KeyringType, KeyringControllerError } from './constants';\n"]} \ No newline at end of file diff --git a/dist/test/encryptor.mock.d.ts b/dist/test/encryptor.mock.d.ts new file mode 100644 index 00000000..a0752356 --- /dev/null +++ b/dist/test/encryptor.mock.d.ts @@ -0,0 +1,38 @@ +/// +/// +/// +import { Json } from '@metamask/utils'; +declare const PASSWORD = "password123"; +declare const MOCK_ENCRYPTION_KEY: string; +declare const MOCK_HARDCODED_KEY = "key"; +declare const MOCK_HEX = "0xabcdef0123456789"; +declare const MOCK_SALT = "SALT"; +declare const mockEncryptor: { + encrypt: import("sinon").SinonStub; + encryptWithDetail: import("sinon").SinonStub; + decrypt(_password: string, _text: string): Promise; + decryptWithEncryptedKeyString(_keyStr: string): Promise; + decryptWithDetail(_password: string, _text: string): Promise<{ + vault: string | number | true | Json[] | { + [prop: string]: Json; + }; + exportedKeyString: string; + salt: string; + } | { + vault?: never; + exportedKeyString?: never; + salt?: never; + }>; + importKey(keyString: string): null; + encryptWithKey(): any; + decryptWithKey(key: string, text: string): Promise; + keyFromPassword(_password: string): Promise; + generateSalt(): string; +}; +export { mockEncryptor, PASSWORD, MOCK_HARDCODED_KEY, MOCK_HEX, MOCK_ENCRYPTION_KEY, MOCK_SALT, }; diff --git a/dist/test/encryptor.mock.js b/dist/test/encryptor.mock.js new file mode 100644 index 00000000..f80c514a --- /dev/null +++ b/dist/test/encryptor.mock.js @@ -0,0 +1,86 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MOCK_SALT = exports.MOCK_ENCRYPTION_KEY = exports.MOCK_HEX = exports.MOCK_HARDCODED_KEY = exports.PASSWORD = exports.mockEncryptor = void 0; +const sinon_1 = require("sinon"); +const PASSWORD = 'password123'; +exports.PASSWORD = PASSWORD; +const MOCK_ENCRYPTION_KEY = JSON.stringify({ + alg: 'A256GCM', + ext: true, + k: 'wYmxkxOOFBDP6F6VuuYFcRt_Po-tSLFHCWVolsHs4VI', + // eslint-disable-next-line @typescript-eslint/naming-convention + key_ops: ['encrypt', 'decrypt'], + kty: 'oct', +}); +exports.MOCK_ENCRYPTION_KEY = MOCK_ENCRYPTION_KEY; +const MOCK_ENCRYPTION_SALT = 'HQ5sfhsb8XAQRJtD+UqcImT7Ve4n3YMagrh05YTOsjk='; +const MOCK_ENCRYPTION_DATA = `{"data":"2fOOPRKClNrisB+tmqIcETyZvDuL2iIR1Hr1nO7XZHyMqVY1cDBetw2gY5C+cIo1qkpyv3bPp+4buUjp38VBsjbijM0F/FLOqWbcuKM9h9X0uwxsgsZ96uwcIf5I46NiMgoFlhppTTMZT0Nkocz+SnvHM0IgLsFan7JqBU++vSJvx2M1PDljZSunOsqyyL+DKmbYmM4umbouKV42dipUwrCvrQJmpiUZrSkpMJrPJk9ufDQO4CyIVo0qry3aNRdYFJ6rgSyq/k6rXMwGExCMHn8UlhNnAMuMKWPWR/ymK1bzNcNs4VU14iVjEXOZGPvD9cvqVe/VtcnIba6axNEEB4HWDOCdrDh5YNWwMlQVL7vSB2yOhPZByGhnEOloYsj2E5KEb9jFGskt7EKDEYNofr6t83G0c+B72VGYZeCvgtzXzgPwzIbhTtKkP+gdBmt2JNSYrTjLypT0q+v4C9BN1xWTxPmX6TTt0NzkI9pJxgN1VQAfSU9CyWTVpd4CBkgom2cSBsxZ2MNbdKF+qSWz3fQcmJ55hxM0EGJSt9+8eQOTuoJlBapRk4wdZKHR2jdKzPjSF2MAmyVD2kU51IKa/cVsckRFEes+m7dKyHRvlNwgT78W9tBDdZb5PSlfbZXnv8z5q1KtAj2lM2ogJ7brHBdevl4FISdTkObpwcUMcvACOOO0dj6CSYjSKr0ZJ2RLChVruZyPDxEhKGb/8Kv8trLOR3mck/et6d050/NugezycNk4nnzu5iP90gPbSzaqdZI=","iv":"qTGO1afGv3waHN9KoW34Eg==","salt":"${MOCK_ENCRYPTION_SALT}"}`; +const INVALID_PASSWORD_ERROR = 'Incorrect password.'; +const MOCK_HARDCODED_KEY = 'key'; +exports.MOCK_HARDCODED_KEY = MOCK_HARDCODED_KEY; +const MOCK_HEX = '0xabcdef0123456789'; +exports.MOCK_HEX = MOCK_HEX; +const MOCK_SALT = 'SALT'; +exports.MOCK_SALT = MOCK_SALT; +// eslint-disable-next-line no-restricted-globals +const MOCK_KEY = Buffer.alloc(32); +let cacheVal; +const mockEncryptor = { + encrypt: (0, sinon_1.stub)().callsFake(async (_password, dataObj) => { + cacheVal = dataObj; + return Promise.resolve(MOCK_HEX); + }), + encryptWithDetail: (0, sinon_1.stub)().callsFake(async (_password, dataObj) => { + cacheVal = dataObj; + return Promise.resolve({ + vault: JSON.stringify({ salt: MOCK_HEX }), + exportedKeyString: MOCK_HARDCODED_KEY, + }); + }), + async decrypt(_password, _text) { + if (_password && _password !== PASSWORD) { + throw new Error(INVALID_PASSWORD_ERROR); + } + return Promise.resolve(cacheVal !== null && cacheVal !== void 0 ? cacheVal : {}); + }, + async decryptWithEncryptedKeyString(_keyStr) { + const { vault } = await this.decryptWithDetail(_keyStr, 'mock vault'); + return vault; + }, + async decryptWithDetail(_password, _text) { + if (_password && _password !== PASSWORD) { + throw new Error(INVALID_PASSWORD_ERROR); + } + const result = cacheVal + ? { + vault: cacheVal, + exportedKeyString: MOCK_ENCRYPTION_KEY, + salt: MOCK_SALT, + } + : {}; + return Promise.resolve(result); + }, + importKey(keyString) { + if (keyString === '{}') { + throw new TypeError(`Failed to execute 'importKey' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView or JsonWebKey)'.`); + } + return null; + }, + encryptWithKey() { + const data = JSON.parse(MOCK_ENCRYPTION_DATA); + // Salt is not provided from this method + delete data.salt; + return data; + }, + async decryptWithKey(key, text) { + return this.decrypt(key, text); + }, + async keyFromPassword(_password) { + return Promise.resolve(MOCK_KEY); + }, + generateSalt() { + return 'WHADDASALT!'; + }, +}; +exports.mockEncryptor = mockEncryptor; +//# sourceMappingURL=encryptor.mock.js.map \ No newline at end of file diff --git a/dist/test/encryptor.mock.js.map b/dist/test/encryptor.mock.js.map new file mode 100644 index 00000000..57bfed01 --- /dev/null +++ b/dist/test/encryptor.mock.js.map @@ -0,0 +1 @@ +{"version":3,"file":"encryptor.mock.js","sourceRoot":"","sources":["../../src/test/encryptor.mock.ts"],"names":[],"mappings":"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","sourcesContent":["import { Json } from '@metamask/utils';\nimport { stub } from 'sinon';\n\nconst PASSWORD = 'password123';\nconst MOCK_ENCRYPTION_KEY = JSON.stringify({\n alg: 'A256GCM',\n ext: true,\n k: 'wYmxkxOOFBDP6F6VuuYFcRt_Po-tSLFHCWVolsHs4VI',\n // eslint-disable-next-line @typescript-eslint/naming-convention\n key_ops: ['encrypt', 'decrypt'],\n kty: 'oct',\n});\nconst MOCK_ENCRYPTION_SALT = 'HQ5sfhsb8XAQRJtD+UqcImT7Ve4n3YMagrh05YTOsjk=';\nconst MOCK_ENCRYPTION_DATA = `{\"data\":\"2fOOPRKClNrisB+tmqIcETyZvDuL2iIR1Hr1nO7XZHyMqVY1cDBetw2gY5C+cIo1qkpyv3bPp+4buUjp38VBsjbijM0F/FLOqWbcuKM9h9X0uwxsgsZ96uwcIf5I46NiMgoFlhppTTMZT0Nkocz+SnvHM0IgLsFan7JqBU++vSJvx2M1PDljZSunOsqyyL+DKmbYmM4umbouKV42dipUwrCvrQJmpiUZrSkpMJrPJk9ufDQO4CyIVo0qry3aNRdYFJ6rgSyq/k6rXMwGExCMHn8UlhNnAMuMKWPWR/ymK1bzNcNs4VU14iVjEXOZGPvD9cvqVe/VtcnIba6axNEEB4HWDOCdrDh5YNWwMlQVL7vSB2yOhPZByGhnEOloYsj2E5KEb9jFGskt7EKDEYNofr6t83G0c+B72VGYZeCvgtzXzgPwzIbhTtKkP+gdBmt2JNSYrTjLypT0q+v4C9BN1xWTxPmX6TTt0NzkI9pJxgN1VQAfSU9CyWTVpd4CBkgom2cSBsxZ2MNbdKF+qSWz3fQcmJ55hxM0EGJSt9+8eQOTuoJlBapRk4wdZKHR2jdKzPjSF2MAmyVD2kU51IKa/cVsckRFEes+m7dKyHRvlNwgT78W9tBDdZb5PSlfbZXnv8z5q1KtAj2lM2ogJ7brHBdevl4FISdTkObpwcUMcvACOOO0dj6CSYjSKr0ZJ2RLChVruZyPDxEhKGb/8Kv8trLOR3mck/et6d050/NugezycNk4nnzu5iP90gPbSzaqdZI=\",\"iv\":\"qTGO1afGv3waHN9KoW34Eg==\",\"salt\":\"${MOCK_ENCRYPTION_SALT}\"}`;\n\nconst INVALID_PASSWORD_ERROR = 'Incorrect password.';\n\nconst MOCK_HARDCODED_KEY = 'key';\nconst MOCK_HEX = '0xabcdef0123456789';\nconst MOCK_SALT = 'SALT';\n// eslint-disable-next-line no-restricted-globals\nconst MOCK_KEY = Buffer.alloc(32);\nlet cacheVal: Json;\n\nconst mockEncryptor = {\n encrypt: stub().callsFake(async (_password, dataObj) => {\n cacheVal = dataObj;\n\n return Promise.resolve(MOCK_HEX);\n }),\n\n encryptWithDetail: stub().callsFake(async (_password, dataObj) => {\n cacheVal = dataObj;\n\n return Promise.resolve({\n vault: JSON.stringify({ salt: MOCK_HEX }),\n exportedKeyString: MOCK_HARDCODED_KEY,\n });\n }),\n\n async decrypt(_password: string, _text: string) {\n if (_password && _password !== PASSWORD) {\n throw new Error(INVALID_PASSWORD_ERROR);\n }\n\n return Promise.resolve(cacheVal ?? {});\n },\n\n async decryptWithEncryptedKeyString(_keyStr: string) {\n const { vault } = await this.decryptWithDetail(_keyStr, 'mock vault');\n return vault;\n },\n\n async decryptWithDetail(_password: string, _text: string) {\n if (_password && _password !== PASSWORD) {\n throw new Error(INVALID_PASSWORD_ERROR);\n }\n\n const result = cacheVal\n ? {\n vault: cacheVal,\n exportedKeyString: MOCK_ENCRYPTION_KEY,\n salt: MOCK_SALT,\n }\n : {};\n return Promise.resolve(result);\n },\n\n importKey(keyString: string) {\n if (keyString === '{}') {\n throw new TypeError(\n `Failed to execute 'importKey' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView or JsonWebKey)'.`,\n );\n }\n return null;\n },\n\n encryptWithKey() {\n const data = JSON.parse(MOCK_ENCRYPTION_DATA);\n // Salt is not provided from this method\n delete data.salt;\n return data;\n },\n\n async decryptWithKey(key: string, text: string) {\n return this.decrypt(key, text);\n },\n\n async keyFromPassword(_password: string) {\n return Promise.resolve(MOCK_KEY);\n },\n\n generateSalt() {\n return 'WHADDASALT!';\n },\n};\n\nexport {\n mockEncryptor,\n PASSWORD,\n MOCK_HARDCODED_KEY,\n MOCK_HEX,\n MOCK_ENCRYPTION_KEY,\n MOCK_SALT,\n};\n"]} \ No newline at end of file diff --git a/dist/test/index.d.ts b/dist/test/index.d.ts new file mode 100644 index 00000000..455125d3 --- /dev/null +++ b/dist/test/index.d.ts @@ -0,0 +1,3 @@ +import { mockEncryptor, PASSWORD, MOCK_HARDCODED_KEY, MOCK_HEX, MOCK_ENCRYPTION_KEY, MOCK_SALT } from './encryptor.mock'; +import KeyringMockWithInit from './keyring.mock'; +export { mockEncryptor, KeyringMockWithInit, PASSWORD, MOCK_HARDCODED_KEY, MOCK_HEX, MOCK_ENCRYPTION_KEY, MOCK_SALT, }; diff --git a/dist/test/index.js b/dist/test/index.js new file mode 100644 index 00000000..1f5d6ab9 --- /dev/null +++ b/dist/test/index.js @@ -0,0 +1,16 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MOCK_SALT = exports.MOCK_ENCRYPTION_KEY = exports.MOCK_HEX = exports.MOCK_HARDCODED_KEY = exports.PASSWORD = exports.KeyringMockWithInit = exports.mockEncryptor = void 0; +const encryptor_mock_1 = require("./encryptor.mock"); +Object.defineProperty(exports, "mockEncryptor", { enumerable: true, get: function () { return encryptor_mock_1.mockEncryptor; } }); +Object.defineProperty(exports, "PASSWORD", { enumerable: true, get: function () { return encryptor_mock_1.PASSWORD; } }); +Object.defineProperty(exports, "MOCK_HARDCODED_KEY", { enumerable: true, get: function () { return encryptor_mock_1.MOCK_HARDCODED_KEY; } }); +Object.defineProperty(exports, "MOCK_HEX", { enumerable: true, get: function () { return encryptor_mock_1.MOCK_HEX; } }); +Object.defineProperty(exports, "MOCK_ENCRYPTION_KEY", { enumerable: true, get: function () { return encryptor_mock_1.MOCK_ENCRYPTION_KEY; } }); +Object.defineProperty(exports, "MOCK_SALT", { enumerable: true, get: function () { return encryptor_mock_1.MOCK_SALT; } }); +const keyring_mock_1 = __importDefault(require("./keyring.mock")); +exports.KeyringMockWithInit = keyring_mock_1.default; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/test/index.js.map b/dist/test/index.js.map new file mode 100644 index 00000000..de00ba05 --- /dev/null +++ b/dist/test/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":";;;;;;AAAA,qDAO0B;AAIxB,8FAVA,8BAAa,OAUA;AAEb,yFAXA,yBAAQ,OAWA;AACR,mGAXA,mCAAkB,OAWA;AAClB,yFAXA,yBAAQ,OAWA;AACR,oGAXA,oCAAmB,OAWA;AACnB,0FAXA,0BAAS,OAWA;AATX,kEAAiD;AAI/C,8BAJK,sBAAmB,CAIL","sourcesContent":["import {\n mockEncryptor,\n PASSWORD,\n MOCK_HARDCODED_KEY,\n MOCK_HEX,\n MOCK_ENCRYPTION_KEY,\n MOCK_SALT,\n} from './encryptor.mock';\nimport KeyringMockWithInit from './keyring.mock';\n\nexport {\n mockEncryptor,\n KeyringMockWithInit,\n PASSWORD,\n MOCK_HARDCODED_KEY,\n MOCK_HEX,\n MOCK_ENCRYPTION_KEY,\n MOCK_SALT,\n};\n"]} \ No newline at end of file diff --git a/dist/test/keyring.mock.d.ts b/dist/test/keyring.mock.d.ts new file mode 100644 index 00000000..b48e3159 --- /dev/null +++ b/dist/test/keyring.mock.d.ts @@ -0,0 +1,13 @@ +import type { Keyring, Json, Hex } from '@metamask/utils'; +declare class KeyringMockWithInit implements Keyring { + #private; + static type: string; + type: string; + constructor(options?: Record | undefined); + init(): Promise; + addAccounts(_: number): Promise; + getAccounts(): Promise<`0x${string}`[]>; + serialize(): Promise<{}>; + deserialize(_: any): Promise; +} +export default KeyringMockWithInit; diff --git a/dist/test/keyring.mock.js b/dist/test/keyring.mock.js new file mode 100644 index 00000000..ef4454ef --- /dev/null +++ b/dist/test/keyring.mock.js @@ -0,0 +1,36 @@ +"use strict"; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + 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"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _KeyringMockWithInit_accounts; +Object.defineProperty(exports, "__esModule", { value: true }); +const TYPE = 'Keyring Mock With Init'; +class KeyringMockWithInit { + constructor(options = {}) { + this.type = TYPE; + _KeyringMockWithInit_accounts.set(this, []); + // eslint-disable-next-line @typescript-eslint/no-floating-promises, @typescript-eslint/promise-function-async + this.deserialize(options); + } + async init() { + return Promise.resolve(); + } + async addAccounts(_) { + return Promise.resolve(__classPrivateFieldGet(this, _KeyringMockWithInit_accounts, "f")); + } + async getAccounts() { + return Promise.resolve(__classPrivateFieldGet(this, _KeyringMockWithInit_accounts, "f")); + } + async serialize() { + return Promise.resolve({}); + } + async deserialize(_) { + return Promise.resolve(); + } +} +_KeyringMockWithInit_accounts = new WeakMap(); +KeyringMockWithInit.type = TYPE; +exports.default = KeyringMockWithInit; +//# sourceMappingURL=keyring.mock.js.map \ No newline at end of file diff --git a/dist/test/keyring.mock.js.map b/dist/test/keyring.mock.js.map new file mode 100644 index 00000000..6906519f --- /dev/null +++ b/dist/test/keyring.mock.js.map @@ -0,0 +1 @@ +{"version":3,"file":"keyring.mock.js","sourceRoot":"","sources":["../../src/test/keyring.mock.ts"],"names":[],"mappings":";;;;;;;;AAEA,MAAM,IAAI,GAAG,wBAAwB,CAAC;AAEtC,MAAM,mBAAmB;IAOvB,YAAY,UAA+C,EAAE;QAJtD,SAAI,GAAG,IAAI,CAAC;QAEnB,wCAAmB,EAAE,EAAC;QAGpB,8GAA8G;QAC9G,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,CAAS;QACzB,OAAO,OAAO,CAAC,OAAO,CAAC,uBAAA,IAAI,qCAAU,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,OAAO,CAAC,OAAO,CAAC,uBAAA,IAAI,qCAAU,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,CAAM;QACtB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;;;AA7BM,wBAAI,GAAG,IAAI,AAAP,CAAQ;AAgCrB,kBAAe,mBAAmB,CAAC","sourcesContent":["import type { Keyring, Json, Hex } from '@metamask/utils';\n\nconst TYPE = 'Keyring Mock With Init';\n\nclass KeyringMockWithInit implements Keyring {\n static type = TYPE;\n\n public type = TYPE;\n\n #accounts: Hex[] = [];\n\n constructor(options: Record | undefined = {}) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, @typescript-eslint/promise-function-async\n this.deserialize(options);\n }\n\n async init() {\n return Promise.resolve();\n }\n\n async addAccounts(_: number): Promise {\n return Promise.resolve(this.#accounts);\n }\n\n async getAccounts() {\n return Promise.resolve(this.#accounts);\n }\n\n async serialize() {\n return Promise.resolve({});\n }\n\n async deserialize(_: any) {\n return Promise.resolve();\n }\n}\n\nexport default KeyringMockWithInit;\n"]} \ No newline at end of file diff --git a/dist/types.d.ts b/dist/types.d.ts new file mode 100644 index 00000000..5b949990 --- /dev/null +++ b/dist/types.d.ts @@ -0,0 +1,31 @@ +import type { Json, Keyring } from '@metamask/utils'; +import ObservableStore from 'obs-store'; +export type KeyringControllerArgs = { + keyringBuilders: { + (): Keyring; + type: string; + } | ConcatArray<{ + (): Keyring; + type: string; + }>; + cacheEncryptionKey: boolean; + initState?: KeyringControllerState; + encryptor?: any; +}; +export type KeyringControllerState = { + keyringBuilders?: { + (): Keyring; + type: string; + }[]; + store?: typeof ObservableStore; + memStore?: typeof ObservableStore; + keyrings?: Keyring[]; + isUnlocked?: boolean; + encryptionKey?: string; + encryptionSalt?: string; + password?: string; +}; +export type SerializedKeyring = { + type: string; + data: Json; +}; diff --git a/dist/types.js b/dist/types.js new file mode 100644 index 00000000..11e638d1 --- /dev/null +++ b/dist/types.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/dist/types.js.map b/dist/types.js.map new file mode 100644 index 00000000..50c203e8 --- /dev/null +++ b/dist/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Json, Keyring } from '@metamask/utils';\nimport ObservableStore from 'obs-store';\n\nexport type KeyringControllerArgs = {\n keyringBuilders:\n | { (): Keyring; type: string }\n | ConcatArray<{ (): Keyring; type: string }>;\n\n cacheEncryptionKey: boolean;\n initState?: KeyringControllerState;\n encryptor?: any;\n};\n\nexport type KeyringControllerState = {\n keyringBuilders?: { (): Keyring; type: string }[];\n\n store?: typeof ObservableStore;\n\n memStore?: typeof ObservableStore;\n\n keyrings?: Keyring[];\n\n isUnlocked?: boolean;\n\n encryptionKey?: string;\n\n encryptionSalt?: string;\n\n password?: string;\n};\n\nexport type SerializedKeyring = {\n type: string;\n data: Json;\n};\n"]} \ No newline at end of file diff --git a/tsconfig.build.json b/tsconfig.build.json index 43db3a45..c6e00d65 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -8,11 +8,6 @@ "rootDir": "src", "sourceMap": true }, - "include": ["./src/**/*.ts", "./types"], - "exclude": [ - "./src/test/**/*.ts", - "./src/**/*.test.ts", - "./src/**/*.test-d.ts", - "./src/__fixtures__" - ] + "include": ["./src/**/*.ts"], + "exclude": ["./src/**/*.test.ts"] } From fdb8394b6ec42246cd1eb864206029113ac2f3e6 Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Thu, 4 May 2023 18:10:53 -0400 Subject: [PATCH 04/10] Convert fullUpdate to public method --- src/KeyringController.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/KeyringController.ts b/src/KeyringController.ts index 1f0f25d8..073b47a0 100644 --- a/src/KeyringController.ts +++ b/src/KeyringController.ts @@ -87,7 +87,7 @@ class KeyringController extends EventEmitter { * * @returns The controller state. */ - #fullUpdate() { + fullUpdate() { this.emit('update', this.memStore.getState()); return this.memStore.getState(); } @@ -117,7 +117,7 @@ class KeyringController extends EventEmitter { await this.#createFirstKeyTree(); this.#setUnlocked(); - return this.#fullUpdate(); + return this.fullUpdate(); } /** @@ -154,7 +154,7 @@ class KeyringController extends EventEmitter { throw new Error(KeyringControllerError.NoFirstAccount); } this.#setUnlocked(); - return this.#fullUpdate(); + return this.fullUpdate(); } /** @@ -178,7 +178,7 @@ class KeyringController extends EventEmitter { this.keyrings = []; await this.updateMemStoreKeyrings(); this.emit('lock'); - return this.#fullUpdate(); + return this.fullUpdate(); } /** @@ -198,7 +198,7 @@ class KeyringController extends EventEmitter { this.keyrings = await this.unlockKeyrings(password); this.#setUnlocked(); - return this.#fullUpdate(); + return this.fullUpdate(); } /** @@ -222,7 +222,7 @@ class KeyringController extends EventEmitter { encryptionSalt, ); this.#setUnlocked(); - return this.#fullUpdate(); + return this.fullUpdate(); } /** @@ -265,7 +265,7 @@ class KeyringController extends EventEmitter { }); await this.persistAllKeyrings(); - return this.#fullUpdate(); + return this.fullUpdate(); } /** @@ -314,7 +314,7 @@ class KeyringController extends EventEmitter { } await this.persistAllKeyrings(); - return this.#fullUpdate(); + return this.fullUpdate(); } /** @@ -618,7 +618,7 @@ class KeyringController extends EventEmitter { this.keyrings.push(keyring); await this.persistAllKeyrings(); - this.#fullUpdate(); + this.fullUpdate(); return keyring; } From 0e99f5143d5afdec7182ea0a0e6f5dc47b71bcc6 Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Thu, 4 May 2023 18:11:10 -0400 Subject: [PATCH 05/10] Update dist --- dist/KeyringController.d.ts | 13 ++++++++++++ dist/KeyringController.js | 39 +++++++++++++++++++++++------------ dist/KeyringController.js.map | 2 +- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/dist/KeyringController.d.ts b/dist/KeyringController.d.ts index 9d7e1488..8dcd1648 100644 --- a/dist/KeyringController.d.ts +++ b/dist/KeyringController.d.ts @@ -18,6 +18,19 @@ declare class KeyringController extends EventEmitter { unsupportedKeyrings: SerializedKeyring[]; password?: string; constructor({ keyringBuilders, cacheEncryptionKey, initState, encryptor, }: KeyringControllerArgs); + /** + * Full Update + * + * Emits the `update` event and @returns a Promise that resolves to + * the current state. + * + * Frequently used to end asynchronous chains in this class, + * indicating consumers can often either listen for updates, + * or accept a state-resolving promise to consume their results. + * + * @returns The controller state. + */ + fullUpdate(): any; /** * ======================================= * === Public Vault Management Methods === diff --git a/dist/KeyringController.js b/dist/KeyringController.js index 237bab1e..18df95b3 100644 --- a/dist/KeyringController.js +++ b/dist/KeyringController.js @@ -30,7 +30,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function ( var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; -var _KeyringController_instances, _KeyringController_fullUpdate, _KeyringController_createFirstKeyTree, _KeyringController_restoreKeyring, _KeyringController_clearKeyrings, _KeyringController_setUnlocked, _KeyringController_newKeyring; +var _KeyringController_instances, _KeyringController_createFirstKeyTree, _KeyringController_restoreKeyring, _KeyringController_clearKeyrings, _KeyringController_setUnlocked, _KeyringController_newKeyring; Object.defineProperty(exports, "__esModule", { value: true }); exports.keyringBuilderFactory = exports.KeyringController = void 0; const encryptorUtils = __importStar(require("@metamask/browser-passworder")); @@ -68,6 +68,22 @@ class KeyringController extends events_1.EventEmitter { // for use in decrypting and encrypting data without password this.cacheEncryptionKey = Boolean(cacheEncryptionKey); } + /** + * Full Update + * + * Emits the `update` event and @returns a Promise that resolves to + * the current state. + * + * Frequently used to end asynchronous chains in this class, + * indicating consumers can often either listen for updates, + * or accept a state-resolving promise to consume their results. + * + * @returns The controller state. + */ + fullUpdate() { + this.emit('update', this.memStore.getState()); + return this.memStore.getState(); + } /** * ======================================= * === Public Vault Management Methods === @@ -89,7 +105,7 @@ class KeyringController extends events_1.EventEmitter { this.password = password; await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createFirstKeyTree).call(this); __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); - return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + return this.fullUpdate(); } /** * CreateNewVaultAndRestore @@ -119,7 +135,7 @@ class KeyringController extends events_1.EventEmitter { throw new Error(constants_1.KeyringControllerError.NoFirstAccount); } __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); - return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + return this.fullUpdate(); } /** * Set Locked. @@ -140,7 +156,7 @@ class KeyringController extends events_1.EventEmitter { this.keyrings = []; await this.updateMemStoreKeyrings(); this.emit('lock'); - return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + return this.fullUpdate(); } /** * Submit password. @@ -158,7 +174,7 @@ class KeyringController extends events_1.EventEmitter { async submitPassword(password) { this.keyrings = await this.unlockKeyrings(password); __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); - return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + return this.fullUpdate(); } /** * Submit Encryption Key. @@ -174,7 +190,7 @@ class KeyringController extends events_1.EventEmitter { async submitEncryptionKey(encryptionKey, encryptionSalt) { this.keyrings = await this.unlockKeyrings(undefined, encryptionKey, encryptionSalt); __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); - return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + return this.fullUpdate(); } /** * Verify Password @@ -211,7 +227,7 @@ class KeyringController extends events_1.EventEmitter { this.emit('newAccount', hexAccount); }); await this.persistAllKeyrings(); - return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + return this.fullUpdate(); } /** * Export Account @@ -254,7 +270,7 @@ class KeyringController extends events_1.EventEmitter { await this.removeEmptyKeyrings(); } await this.persistAllKeyrings(); - return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + return this.fullUpdate(); } /** * Get Accounts @@ -486,7 +502,7 @@ class KeyringController extends events_1.EventEmitter { await this.checkForDuplicate(type, accounts); this.keyrings.push(keyring); await this.persistAllKeyrings(); - __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_fullUpdate).call(this); + this.fullUpdate(); return keyring; } /** @@ -722,10 +738,7 @@ class KeyringController extends events_1.EventEmitter { } } exports.KeyringController = KeyringController; -_KeyringController_instances = new WeakSet(), _KeyringController_fullUpdate = function _KeyringController_fullUpdate() { - this.emit('update', this.memStore.getState()); - return this.memStore.getState(); -}, _KeyringController_createFirstKeyTree = +_KeyringController_instances = new WeakSet(), _KeyringController_createFirstKeyTree = // ======================= // === Private Methods === // ======================= diff --git a/dist/KeyringController.js.map b/dist/KeyringController.js.map index b4b82b9d..07bafb47 100644 --- a/dist/KeyringController.js.map +++ b/dist/KeyringController.js.map @@ -1 +1 @@ -{"version":3,"file":"KeyringController.js","sourceRoot":"","sources":["../src/KeyringController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TypedTransaction, TxData } from '@ethereumjs/tx';\nimport * as encryptorUtils from '@metamask/browser-passworder';\nimport HDKeyring from '@metamask/eth-hd-keyring';\nimport { normalize as normalizeToHex } from '@metamask/eth-sig-util';\nimport SimpleKeyring from '@metamask/eth-simple-keyring';\nimport { remove0x, isValidJson } from '@metamask/utils';\nimport type {\n Hex,\n Json,\n Bytes,\n Keyring,\n KeyringClass,\n Eip1024EncryptedData,\n} from '@metamask/utils';\n// TODO: Stop using `events`, and remove the notice about this from the README\n// eslint-disable-next-line import/no-nodejs-modules\nimport { EventEmitter } from 'events';\nimport ObservableStore from 'obs-store';\n\nimport { KeyringType, KeyringControllerError } from './constants';\nimport {\n SerializedKeyring,\n KeyringControllerArgs,\n KeyringControllerState,\n} from './types';\n\nconst defaultKeyringBuilders = [\n keyringBuilderFactory(SimpleKeyring),\n keyringBuilderFactory(HDKeyring),\n];\n\nclass KeyringController extends EventEmitter {\n keyringBuilders: { (): Keyring; type: string }[];\n\n public store: typeof ObservableStore;\n\n public memStore: typeof ObservableStore;\n\n public encryptor: any;\n\n public keyrings: Keyring[];\n\n public cacheEncryptionKey: boolean;\n\n public unsupportedKeyrings: SerializedKeyring[];\n\n public password?: string;\n\n constructor({\n keyringBuilders,\n cacheEncryptionKey,\n initState = {},\n encryptor = encryptorUtils,\n }: KeyringControllerArgs) {\n super();\n this.keyringBuilders = keyringBuilders\n ? defaultKeyringBuilders.concat(keyringBuilders)\n : defaultKeyringBuilders;\n this.store = new ObservableStore(initState);\n this.memStore = new ObservableStore({\n isUnlocked: false,\n keyringTypes: this.keyringBuilders.map(\n (keyringBuilder) => keyringBuilder.type,\n ),\n keyrings: [],\n encryptionKey: null,\n });\n\n this.encryptor = encryptor;\n this.keyrings = [];\n this.unsupportedKeyrings = [];\n\n // This option allows the controller to cache an exported key\n // for use in decrypting and encrypting data without password\n this.cacheEncryptionKey = Boolean(cacheEncryptionKey);\n }\n\n /**\n * Full Update\n *\n * Emits the `update` event and @returns a Promise that resolves to\n * the current state.\n *\n * Frequently used to end asynchronous chains in this class,\n * indicating consumers can often either listen for updates,\n * or accept a state-resolving promise to consume their results.\n *\n * @returns The controller state.\n */\n #fullUpdate() {\n this.emit('update', this.memStore.getState());\n return this.memStore.getState();\n }\n\n /**\n * =======================================\n * === Public Vault Management Methods ===\n * =======================================\n */\n\n /**\n * Create New Vault And Keychain\n *\n * Destroys any old encrypted storage,\n * creates a new encrypted store with the given password,\n * randomly creates a new HD wallet with 1 account,\n * faucets that account on the testnet.\n *\n * @fires KeyringController#unlock\n * @param password - The password to encrypt the vault with.\n * @returns A promise that resolves to the state.\n */\n async createNewVaultAndKeychain(\n password: string,\n ): Promise {\n this.password = password;\n\n await this.#createFirstKeyTree();\n this.#setUnlocked();\n return this.#fullUpdate();\n }\n\n /**\n * CreateNewVaultAndRestore\n *\n * Destroys any old encrypted storage,\n * creates a new encrypted store with the given password,\n * creates a new HD wallet from the given seed with 1 account.\n *\n * @fires KeyringController#unlock\n * @param password - The password to encrypt the vault with.\n * @param seedPhrase - The BIP39-compliant seed phrase,\n * either as a string or Uint8Array.\n * @returns A promise that resolves to the state.\n */\n async createNewVaultAndRestore(\n password: string,\n seedPhrase: Uint8Array | string | number[],\n ): Promise {\n if (typeof password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n this.password = password;\n\n await this.#clearKeyrings();\n const keyring = await this.addNewKeyring(KeyringType.HD, {\n mnemonic: seedPhrase,\n numberOfAccounts: 1,\n });\n\n const [firstAccount] = await keyring.getAccounts();\n\n if (!firstAccount) {\n throw new Error(KeyringControllerError.NoFirstAccount);\n }\n this.#setUnlocked();\n return this.#fullUpdate();\n }\n\n /**\n * Set Locked.\n * This method deallocates all secrets, and effectively locks MetaMask.\n *\n * @fires KeyringController#lock\n * @returns A promise that resolves to the state.\n */\n async setLocked(): Promise {\n delete this.password;\n\n // set locked\n this.memStore.updateState({\n isUnlocked: false,\n encryptionKey: null,\n encryptionSalt: null,\n });\n\n // remove keyrings\n this.keyrings = [];\n await this.updateMemStoreKeyrings();\n this.emit('lock');\n return this.#fullUpdate();\n }\n\n /**\n * Submit password.\n *\n * Attempts to decrypt the current vault and load its keyrings\n * into memory.\n *\n * Temporarily also migrates any old-style vaults first, as well\n * (Pre MetaMask 3.0.0).\n *\n * @fires KeyringController#unlock\n * @param password - The keyring controller password.\n * @returns A promise that resolves to the state.\n */\n async submitPassword(password: string): Promise {\n this.keyrings = await this.unlockKeyrings(password);\n\n this.#setUnlocked();\n return this.#fullUpdate();\n }\n\n /**\n * Submit Encryption Key.\n *\n * Attempts to decrypt the current vault and load its keyrings\n * into memory based on the vault and CryptoKey information.\n *\n * @fires KeyringController#unlock\n * @param encryptionKey - The encrypted key information used to decrypt the vault.\n * @param encryptionSalt - The salt used to generate the last key.\n * @returns A promise that resolves to the state.\n */\n async submitEncryptionKey(\n encryptionKey: string,\n encryptionSalt: string,\n ): Promise {\n this.keyrings = await this.unlockKeyrings(\n undefined,\n encryptionKey,\n encryptionSalt,\n );\n this.#setUnlocked();\n return this.#fullUpdate();\n }\n\n /**\n * Verify Password\n *\n * Attempts to decrypt the current vault with a given password\n * to verify its validity.\n *\n * @param password - The vault password.\n */\n async verifyPassword(password: string): Promise {\n const encryptedVault = this.store.getState().vault;\n if (!encryptedVault) {\n throw new Error(KeyringControllerError.VaultError);\n }\n await this.encryptor.decrypt(password, encryptedVault);\n }\n\n /**\n * =========================================\n * === Public Account Management Methods ===\n * =========================================\n */\n\n /**\n * Add New Account.\n *\n * Calls the `addAccounts` method on the given keyring,\n * and then saves those changes.\n *\n * @param selectedKeyring - The currently selected keyring.\n * @returns A Promise that resolves to the state.\n */\n async addNewAccount(\n selectedKeyring: Keyring,\n ): Promise {\n const accounts = await selectedKeyring.addAccounts(1);\n accounts.forEach((hexAccount) => {\n this.emit('newAccount', hexAccount);\n });\n\n await this.persistAllKeyrings();\n return this.#fullUpdate();\n }\n\n /**\n * Export Account\n *\n * Requests the private key from the keyring controlling\n * the specified address.\n *\n * Returns a Promise that may resolve with the private key string.\n *\n * @param address - The address of the account to export.\n * @returns The private key of the account.\n */\n async exportAccount(address: string): Promise {\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.exportAccount) {\n throw new Error(KeyringControllerError.UnsupportedExportAccount);\n }\n\n return await keyring.exportAccount(normalizeToHex(address) as Hex);\n }\n\n /**\n * Remove Account.\n *\n * Removes a specific account from a keyring\n * If the account is the last/only one then it also removes the keyring.\n *\n * @param address - The address of the account to remove.\n * @returns A promise that resolves if the operation was successful.\n */\n async removeAccount(address: Hex): Promise {\n const keyring = await this.getKeyringForAccount(address);\n\n // Not all the keyrings support this, so we have to check\n if (!keyring.removeAccount) {\n throw new Error(KeyringControllerError.UnsupportedRemoveAccount);\n }\n keyring.removeAccount(address);\n this.emit('removedAccount', address);\n\n const accounts = await keyring.getAccounts();\n // Check if this was the last/only account\n if (accounts.length === 0) {\n await this.removeEmptyKeyrings();\n }\n\n await this.persistAllKeyrings();\n return this.#fullUpdate();\n }\n\n /**\n * Get Accounts\n *\n * Returns the public addresses of all current accounts\n * managed by all currently unlocked keyrings.\n *\n * @returns The array of accounts.\n */\n async getAccounts(): Promise {\n const keyrings = this.keyrings || [];\n\n const keyringArrays = await Promise.all(\n keyrings.map(async (keyring) => keyring.getAccounts()),\n );\n const addresses = keyringArrays.reduce((res, arr) => {\n return res.concat(arr);\n }, []);\n\n return addresses.map(normalizeToHex);\n }\n\n /**\n * Get Keyring Class For Type\n *\n * Searches the current `keyringBuilders` array\n * for a Keyring builder whose unique `type` property\n * matches the provided `type`,\n * returning it if it exists.\n *\n * @param type - The type whose class to get.\n * @returns The class, if it exists.\n */\n getKeyringBuilderForType(\n type: string,\n ): { (): Keyring; type: string } | undefined {\n return this.keyringBuilders.find(\n (keyringBuilder) => keyringBuilder.type === type,\n );\n }\n\n /**\n * Update memStore Keyrings\n *\n * Updates the in-memory keyrings, without persisting.\n */\n async updateMemStoreKeyrings(): Promise {\n const keyrings = await Promise.all(this.keyrings.map(displayForKeyring));\n return this.memStore.updateState({ keyrings });\n }\n\n /**\n * ===========================================\n * === Public RPC Requests Routing Methods ===\n * ===========================================\n */\n\n /**\n * Sign Ethereum Transaction\n *\n * Signs an Ethereum transaction object.\n *\n * @param ethTx - The transaction to sign.\n * @param rawAddress - The transaction 'from' address.\n * @param opts - Signing options.\n * @returns The signed transaction object.\n */\n async signTransaction(\n ethTx: TypedTransaction,\n rawAddress: string,\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signTransaction) {\n throw new Error(KeyringControllerError.UnsupportedSignTransaction);\n }\n\n return await keyring.signTransaction(address, ethTx, opts);\n }\n\n /**\n * Sign Message\n *\n * Attempts to sign the provided message parameters.\n *\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The message to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signMessage(\n msgParams: {\n from: string;\n data: string;\n },\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signMessage) {\n throw new Error(KeyringControllerError.UnsupportedSignMessage);\n }\n\n return await keyring.signMessage(address, msgParams.data, opts);\n }\n\n /**\n * Sign Personal Message\n *\n * Attempts to sign the provided message parameters.\n * Prefixes the hash before signing per the personal sign expectation.\n *\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The message to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signPersonalMessage(\n msgParams: {\n from: string;\n data: string;\n },\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signPersonalMessage) {\n throw new Error(KeyringControllerError.UnsupportedSignPersonalMessage);\n }\n\n const normalizedData = normalizeToHex(msgParams.data) as Hex;\n\n return await keyring.signPersonalMessage(address, normalizedData, opts);\n }\n\n /**\n * Get encryption public key\n *\n * Get encryption public key for using in encrypt/decrypt process.\n *\n * @param address - The address to get the encryption public key for.\n * @param opts - Additional encryption options.\n * @returns The public key.\n */\n async getEncryptionPublicKey(\n address: string,\n opts: Record = {},\n ): Promise {\n const normalizedAddress = normalizeToHex(address) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.getEncryptionPublicKey) {\n throw new Error(KeyringControllerError.UnsupportedGetEncryptionPublicKey);\n }\n\n return await keyring.getEncryptionPublicKey(normalizedAddress, opts);\n }\n\n /**\n * Decrypt Message\n *\n * Attempts to decrypt the provided message parameters.\n *\n * @param msgParams - The decryption message parameters.\n * @param msgParams.from - The address of the account you want to use to decrypt the message.\n * @param msgParams.data - The encrypted data that you want to decrypt.\n * @returns The raw decryption result.\n */\n async decryptMessage(msgParams: {\n from: string;\n data: Eip1024EncryptedData;\n }): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.decryptMessage) {\n throw new Error(KeyringControllerError.UnsupportedDecryptMessage);\n }\n\n return keyring.decryptMessage(address, msgParams.data);\n }\n\n /**\n * Sign Typed Data.\n *\n * @see {@link https://github.com/ethereum/EIPs/pull/712#issuecomment-329988454|EIP712}.\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The data to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signTypedMessage(\n msgParams: {\n from: string;\n data: Record[];\n },\n opts: Record = { version: 'V1' },\n ): Promise {\n const address = normalizeToHex(msgParams.from);\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signTypedData) {\n throw new Error(KeyringControllerError.UnsupportedSignTypedMessage);\n }\n\n // Looks like this is not well defined in the Keyring interface since\n // our tests show that we should be able to pass an array.\n // @ts-expect-error Missing other required permission types.\n return keyring.signTypedData(address, msgParams.data, opts);\n }\n\n /**\n * Gets the app key address for the given Ethereum address and origin.\n *\n * @param rawAddress - The Ethereum address for the app key.\n * @param origin - The origin for the app key.\n * @returns The app key address.\n */\n async getAppKeyAddress(rawAddress: string, origin: string): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.getAppKeyAddress) {\n throw new Error(KeyringControllerError.UnsupportedGetAppKeyAddress);\n }\n\n return keyring.getAppKeyAddress(address, origin);\n }\n\n /**\n * Exports an app key private key for the given Ethereum address and origin.\n *\n * @param rawAddress - The Ethereum address for the app key.\n * @param origin - The origin for the app key.\n * @returns The app key private key.\n */\n async exportAppKeyForAddress(\n rawAddress: string,\n origin: string,\n ): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.exportAccount) {\n throw new Error(KeyringControllerError.UnsupportedExportAppKeyForAddress);\n }\n return keyring.exportAccount(address, { withAppKeyOrigin: origin });\n }\n\n /**\n * =========================================\n * === Public Keyring Management Methods ===\n * =========================================\n */\n\n /**\n * Add New Keyring\n *\n * Adds a new Keyring of the given `type` to the vault\n * and the current decrypted Keyrings array.\n *\n * All Keyring classes implement a unique `type` string,\n * and this is used to retrieve them from the keyringBuilders array.\n *\n * @param type - The type of keyring to add.\n * @param opts - The constructor options for the keyring.\n * @returns The new keyring.\n */\n async addNewKeyring(\n type: string,\n opts: Record = {},\n ): Promise> {\n let keyring: Keyring;\n switch (type) {\n case KeyringType.Simple:\n keyring = await this.#newKeyring(type, opts.privateKeys);\n break;\n default:\n keyring = await this.#newKeyring(type, opts);\n break;\n }\n\n if (!keyring) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n\n if (!opts.mnemonic && type === KeyringType.HD) {\n if (!keyring.generateRandomMnemonic) {\n throw new Error(\n KeyringControllerError.UnsupportedGenerateRandomMnemonic,\n );\n }\n\n keyring.generateRandomMnemonic();\n await keyring.addAccounts(1);\n }\n\n const accounts = await keyring.getAccounts();\n await this.checkForDuplicate(type, accounts);\n\n this.keyrings.push(keyring);\n await this.persistAllKeyrings();\n\n this.#fullUpdate();\n\n return keyring;\n }\n\n /**\n * Remove empty keyrings.\n *\n * Loops through the keyrings and removes the ones with empty accounts\n * (usually after removing the last / only account) from a keyring.\n */\n async removeEmptyKeyrings(): Promise {\n const validKeyrings: Keyring[] = [];\n\n // Since getAccounts returns a Promise\n // We need to wait to hear back form each keyring\n // in order to decide which ones are now valid (accounts.length > 0)\n\n await Promise.all(\n this.keyrings.map(async (keyring: Keyring) => {\n const accounts = await keyring.getAccounts();\n if (accounts.length > 0) {\n validKeyrings.push(keyring);\n }\n }),\n );\n this.keyrings = validKeyrings;\n }\n\n /**\n * Checks for duplicate keypairs, using the the first account in the given\n * array. Rejects if a duplicate is found.\n *\n * Only supports 'Simple Key Pair'.\n *\n * @param type - The key pair type to check for.\n * @param newAccountArray - Array of new accounts.\n * @returns The account, if no duplicate is found.\n */\n async checkForDuplicate(\n type: string,\n newAccountArray: string[],\n ): Promise {\n const accounts = await this.getAccounts();\n\n switch (type) {\n case KeyringType.Simple: {\n const isIncluded = Boolean(\n accounts.find(\n (key) =>\n newAccountArray[0] &&\n (key === newAccountArray[0] ||\n key === remove0x(newAccountArray[0])),\n ),\n );\n\n if (isIncluded) {\n throw new Error(KeyringControllerError.DuplicatedAccount);\n }\n return newAccountArray;\n }\n\n default: {\n return newAccountArray;\n }\n }\n }\n\n /**\n * Get Keyring For Account\n *\n * Returns the currently initialized keyring that manages\n * the specified `address` if one exists.\n *\n * @param address - An account address.\n * @returns The keyring of the account, if it exists.\n */\n async getKeyringForAccount(address: string): Promise> {\n const hexed = normalizeToHex(address);\n\n const candidates = await Promise.all(\n this.keyrings.map(async (keyring) => {\n return Promise.all([keyring, keyring.getAccounts()]);\n }),\n );\n\n const winners = candidates.filter((candidate) => {\n const accounts = candidate[1].map(normalizeToHex);\n return accounts.includes(hexed);\n });\n\n if (winners.length && winners[0]?.length) {\n return winners[0][0];\n }\n\n // Adding more info to the error\n let errorInfo = '';\n if (!address) {\n errorInfo = 'The address passed in is invalid/empty';\n } else if (!candidates.length) {\n errorInfo = 'There are no keyrings';\n } else if (!winners.length) {\n errorInfo = 'There are keyrings, but none match the address';\n }\n throw new Error(\n `${KeyringControllerError.NoKeyring}. Error info: ${errorInfo}`,\n );\n }\n\n /**\n * Restore Keyring\n *\n * Attempts to initialize a new keyring from the provided serialized payload.\n * On success, updates the memStore keyrings and returns the resulting\n * keyring instance.\n *\n * @param serialized - The serialized keyring.\n * @returns The deserialized keyring.\n */\n async restoreKeyring(\n serialized: SerializedKeyring,\n ): Promise | undefined> {\n const keyring = await this.#restoreKeyring(serialized);\n if (keyring) {\n await this.updateMemStoreKeyrings();\n }\n return keyring;\n }\n\n /**\n * Get Keyrings by Type\n *\n * Gets all keyrings of the given type.\n *\n * @param type - The keyring types to retrieve.\n * @returns Keyrings matching the specified type.\n */\n getKeyringsByType(type: string): Keyring[] {\n const keyrings = this.keyrings.filter((keyring) => keyring.type === type);\n if (!keyrings.length) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n return keyrings;\n }\n\n /**\n * Persist All Keyrings\n *\n * Iterates the current `keyrings` array,\n * serializes each one into a serialized array,\n * encrypts that array with the provided `password`,\n * and persists that encrypted string to storage.\n *\n * @returns Resolves to true once keyrings are persisted.\n */\n async persistAllKeyrings(): Promise {\n const { encryptionKey, encryptionSalt } = this.memStore.getState();\n\n if (!this.password && !encryptionKey) {\n throw new Error(KeyringControllerError.MissingCredentials);\n }\n\n const serializedKeyrings = await Promise.all(\n this.keyrings.map(async (keyring) => {\n const [type, data] = await Promise.all([\n keyring.type,\n keyring.serialize(),\n ]);\n return { type, data };\n }),\n );\n\n serializedKeyrings.push(...this.unsupportedKeyrings);\n\n let vault;\n let newEncryptionKey;\n\n if (this.cacheEncryptionKey) {\n if (this.password) {\n const { vault: newVault, exportedKeyString } =\n await this.encryptor.encryptWithDetail(\n this.password,\n serializedKeyrings,\n );\n\n vault = newVault;\n newEncryptionKey = exportedKeyString;\n } else if (encryptionKey) {\n const key = await this.encryptor.importKey(encryptionKey);\n const vaultJSON = await this.encryptor.encryptWithKey(\n key,\n serializedKeyrings,\n );\n vaultJSON.salt = encryptionSalt;\n vault = JSON.stringify(vaultJSON);\n }\n } else {\n if (typeof this.password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n vault = await this.encryptor.encrypt(this.password, serializedKeyrings);\n }\n\n if (!vault) {\n throw new Error(KeyringControllerError.MissingVaultData);\n }\n\n this.store.updateState({ vault });\n\n // The keyring updates need to be announced before updating the encryptionKey\n // so that the updated keyring gets propagated to the extension first.\n // Not calling {@link updateMemStoreKeyrings} results in the wrong account being selected\n // in the extension.\n await this.updateMemStoreKeyrings();\n if (newEncryptionKey) {\n this.memStore.updateState({\n encryptionKey: newEncryptionKey,\n encryptionSalt: JSON.parse(vault).salt,\n });\n }\n\n return true;\n }\n\n /**\n * Unlock Keyrings.\n *\n * Attempts to unlock the persisted encrypted storage,\n * initializing the persisted keyrings to RAM.\n *\n * @param password - The keyring controller password.\n * @param encryptionKey - An exported key string to unlock keyrings with.\n * @param encryptionSalt - The salt used to encrypt the vault.\n * @returns The keyrings array.\n */\n async unlockKeyrings(\n password: string | undefined,\n encryptionKey?: string,\n encryptionSalt?: string,\n ): Promise[]> {\n const encryptedVault = this.store.getState().vault;\n if (!encryptedVault) {\n throw new Error(KeyringControllerError.VaultError);\n }\n\n await this.#clearKeyrings();\n\n let vault;\n\n if (this.cacheEncryptionKey) {\n if (password) {\n const result = await this.encryptor.decryptWithDetail(\n password,\n encryptedVault,\n );\n vault = result.vault;\n this.password = password;\n\n this.memStore.updateState({\n encryptionKey: result.exportedKeyString,\n encryptionSalt: result.salt,\n });\n } else {\n const parsedEncryptedVault = JSON.parse(encryptedVault);\n\n if (encryptionSalt !== parsedEncryptedVault.salt) {\n throw new Error(KeyringControllerError.ExpiredCredentials);\n }\n\n if (typeof encryptionKey !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n\n const key = await this.encryptor.importKey(encryptionKey);\n vault = await this.encryptor.decryptWithKey(key, parsedEncryptedVault);\n\n // This call is required on the first call because encryptionKey\n // is not yet inside the memStore\n this.memStore.updateState({\n encryptionKey,\n encryptionSalt,\n });\n }\n } else {\n if (typeof password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n\n vault = await this.encryptor.decrypt(password, encryptedVault);\n this.password = password;\n }\n\n await Promise.all(vault.map(this.#restoreKeyring.bind(this)));\n await this.updateMemStoreKeyrings();\n return this.keyrings;\n }\n\n // =======================\n // === Private Methods ===\n // =======================\n\n /**\n * Create First Key Tree.\n *\n * - Clears the existing vault.\n * - Creates a new vault.\n * - Creates a random new HD Keyring with 1 account.\n * - Makes that account the selected account.\n * - Faucets that account on testnet.\n * - Puts the current seed words into the state tree.\n *\n * @returns A promise that resolves if the operation was successful.\n */\n async #createFirstKeyTree(): Promise {\n await this.#clearKeyrings();\n\n const keyring = await this.addNewKeyring(KeyringType.HD);\n if (!keyring) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n\n const [firstAccount] = await keyring.getAccounts();\n if (!firstAccount) {\n throw new Error(KeyringControllerError.NoAccountOnKeychain);\n }\n\n const hexAccount = normalizeToHex(firstAccount);\n this.emit('newVault', hexAccount);\n return null;\n }\n\n /**\n * Restore Keyring Helper\n *\n * Attempts to initialize a new keyring from the provided serialized payload.\n * On success, returns the resulting keyring instance.\n *\n * @param serialized - The serialized keyring.\n * @param serialized.type - Keyring type.\n * @param serialized.data - Keyring data.\n * @returns The deserialized keyring or undefined if the keyring type is unsupported.\n */\n async #restoreKeyring(\n serialized: SerializedKeyring,\n ): Promise | undefined> {\n const { type, data } = serialized;\n\n let keyring: Keyring | undefined;\n try {\n keyring = await this.#newKeyring(type, data);\n } catch (error) {\n // Ignore error.\n console.error(error);\n }\n\n if (!keyring) {\n this.unsupportedKeyrings.push(serialized);\n return undefined;\n }\n\n // getAccounts also validates the accounts for some keyrings\n await keyring.getAccounts();\n this.keyrings.push(keyring);\n return keyring;\n }\n\n /**\n * Clear Keyrings\n *\n * Deallocates all currently managed keyrings and accounts.\n * Used before initializing a new vault.\n */\n async #clearKeyrings(): Promise {\n // clear keyrings from memory\n this.keyrings = [];\n this.memStore.updateState({\n keyrings: [],\n });\n }\n\n /**\n * Unlock Keyrings\n *\n * Unlocks the keyrings.\n *\n * @fires KeyringController#unlock\n */\n #setUnlocked(): void {\n this.memStore.updateState({ isUnlocked: true });\n this.emit('unlock');\n }\n\n /**\n * Instantiate, initialize and return a new keyring\n *\n * The keyring instantiated is of the given `type`.\n *\n * @param type - The type of keyring to add.\n * @param data - The data to restore a previously serialized keyring.\n * @returns The new keyring.\n */\n async #newKeyring(type: string, data: unknown): Promise> {\n const keyringBuilder = this.getKeyringBuilderForType(type);\n\n if (!keyringBuilder) {\n throw new Error(\n `${KeyringControllerError.NoKeyringBuilder}. Keyring type: ${type}`,\n );\n }\n\n const keyring = keyringBuilder();\n\n if (!isValidJson(data)) {\n throw new Error(KeyringControllerError.DataType);\n }\n\n await keyring.deserialize(data);\n\n // @ts-expect-error The method 'init' is not part of the current Keyring type\n if (keyring.init) {\n // @ts-expect-error The method 'init' is not part of the current Keyring type\n await keyring.init();\n }\n\n return keyring;\n }\n}\n\n/**\n * Get builder function for `Keyring`\n *\n * Returns a builder function for `Keyring` with a `type` property.\n *\n * @param KeyringConstructor - The Keyring class for the builder.\n * @returns A builder function for the given Keyring.\n */\nfunction keyringBuilderFactory(KeyringConstructor: KeyringClass) {\n const builder = () => new KeyringConstructor();\n\n builder.type = KeyringConstructor.type;\n\n return builder;\n}\n\n/**\n * Display For Keyring\n *\n * Is used for adding the current keyrings to the state object.\n *\n * @param keyring - The keyring to display.\n * @returns A keyring display object, with type and accounts properties.\n */\nasync function displayForKeyring(\n keyring: Keyring,\n): Promise<{ type: string; accounts: string[] }> {\n const accounts = await keyring.getAccounts();\n\n return {\n type: keyring.type,\n accounts: accounts.map(normalizeToHex),\n };\n}\n\nexport { KeyringController, keyringBuilderFactory };\n"]} \ No newline at end of file +{"version":3,"file":"KeyringController.js","sourceRoot":"","sources":["../src/KeyringController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TypedTransaction, TxData } from '@ethereumjs/tx';\nimport * as encryptorUtils from '@metamask/browser-passworder';\nimport HDKeyring from '@metamask/eth-hd-keyring';\nimport { normalize as normalizeToHex } from '@metamask/eth-sig-util';\nimport SimpleKeyring from '@metamask/eth-simple-keyring';\nimport { remove0x, isValidJson } from '@metamask/utils';\nimport type {\n Hex,\n Json,\n Bytes,\n Keyring,\n KeyringClass,\n Eip1024EncryptedData,\n} from '@metamask/utils';\n// TODO: Stop using `events`, and remove the notice about this from the README\n// eslint-disable-next-line import/no-nodejs-modules\nimport { EventEmitter } from 'events';\nimport ObservableStore from 'obs-store';\n\nimport { KeyringType, KeyringControllerError } from './constants';\nimport {\n SerializedKeyring,\n KeyringControllerArgs,\n KeyringControllerState,\n} from './types';\n\nconst defaultKeyringBuilders = [\n keyringBuilderFactory(SimpleKeyring),\n keyringBuilderFactory(HDKeyring),\n];\n\nclass KeyringController extends EventEmitter {\n keyringBuilders: { (): Keyring; type: string }[];\n\n public store: typeof ObservableStore;\n\n public memStore: typeof ObservableStore;\n\n public encryptor: any;\n\n public keyrings: Keyring[];\n\n public cacheEncryptionKey: boolean;\n\n public unsupportedKeyrings: SerializedKeyring[];\n\n public password?: string;\n\n constructor({\n keyringBuilders,\n cacheEncryptionKey,\n initState = {},\n encryptor = encryptorUtils,\n }: KeyringControllerArgs) {\n super();\n this.keyringBuilders = keyringBuilders\n ? defaultKeyringBuilders.concat(keyringBuilders)\n : defaultKeyringBuilders;\n this.store = new ObservableStore(initState);\n this.memStore = new ObservableStore({\n isUnlocked: false,\n keyringTypes: this.keyringBuilders.map(\n (keyringBuilder) => keyringBuilder.type,\n ),\n keyrings: [],\n encryptionKey: null,\n });\n\n this.encryptor = encryptor;\n this.keyrings = [];\n this.unsupportedKeyrings = [];\n\n // This option allows the controller to cache an exported key\n // for use in decrypting and encrypting data without password\n this.cacheEncryptionKey = Boolean(cacheEncryptionKey);\n }\n\n /**\n * Full Update\n *\n * Emits the `update` event and @returns a Promise that resolves to\n * the current state.\n *\n * Frequently used to end asynchronous chains in this class,\n * indicating consumers can often either listen for updates,\n * or accept a state-resolving promise to consume their results.\n *\n * @returns The controller state.\n */\n fullUpdate() {\n this.emit('update', this.memStore.getState());\n return this.memStore.getState();\n }\n\n /**\n * =======================================\n * === Public Vault Management Methods ===\n * =======================================\n */\n\n /**\n * Create New Vault And Keychain\n *\n * Destroys any old encrypted storage,\n * creates a new encrypted store with the given password,\n * randomly creates a new HD wallet with 1 account,\n * faucets that account on the testnet.\n *\n * @fires KeyringController#unlock\n * @param password - The password to encrypt the vault with.\n * @returns A promise that resolves to the state.\n */\n async createNewVaultAndKeychain(\n password: string,\n ): Promise {\n this.password = password;\n\n await this.#createFirstKeyTree();\n this.#setUnlocked();\n return this.fullUpdate();\n }\n\n /**\n * CreateNewVaultAndRestore\n *\n * Destroys any old encrypted storage,\n * creates a new encrypted store with the given password,\n * creates a new HD wallet from the given seed with 1 account.\n *\n * @fires KeyringController#unlock\n * @param password - The password to encrypt the vault with.\n * @param seedPhrase - The BIP39-compliant seed phrase,\n * either as a string or Uint8Array.\n * @returns A promise that resolves to the state.\n */\n async createNewVaultAndRestore(\n password: string,\n seedPhrase: Uint8Array | string | number[],\n ): Promise {\n if (typeof password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n this.password = password;\n\n await this.#clearKeyrings();\n const keyring = await this.addNewKeyring(KeyringType.HD, {\n mnemonic: seedPhrase,\n numberOfAccounts: 1,\n });\n\n const [firstAccount] = await keyring.getAccounts();\n\n if (!firstAccount) {\n throw new Error(KeyringControllerError.NoFirstAccount);\n }\n this.#setUnlocked();\n return this.fullUpdate();\n }\n\n /**\n * Set Locked.\n * This method deallocates all secrets, and effectively locks MetaMask.\n *\n * @fires KeyringController#lock\n * @returns A promise that resolves to the state.\n */\n async setLocked(): Promise {\n delete this.password;\n\n // set locked\n this.memStore.updateState({\n isUnlocked: false,\n encryptionKey: null,\n encryptionSalt: null,\n });\n\n // remove keyrings\n this.keyrings = [];\n await this.updateMemStoreKeyrings();\n this.emit('lock');\n return this.fullUpdate();\n }\n\n /**\n * Submit password.\n *\n * Attempts to decrypt the current vault and load its keyrings\n * into memory.\n *\n * Temporarily also migrates any old-style vaults first, as well\n * (Pre MetaMask 3.0.0).\n *\n * @fires KeyringController#unlock\n * @param password - The keyring controller password.\n * @returns A promise that resolves to the state.\n */\n async submitPassword(password: string): Promise {\n this.keyrings = await this.unlockKeyrings(password);\n\n this.#setUnlocked();\n return this.fullUpdate();\n }\n\n /**\n * Submit Encryption Key.\n *\n * Attempts to decrypt the current vault and load its keyrings\n * into memory based on the vault and CryptoKey information.\n *\n * @fires KeyringController#unlock\n * @param encryptionKey - The encrypted key information used to decrypt the vault.\n * @param encryptionSalt - The salt used to generate the last key.\n * @returns A promise that resolves to the state.\n */\n async submitEncryptionKey(\n encryptionKey: string,\n encryptionSalt: string,\n ): Promise {\n this.keyrings = await this.unlockKeyrings(\n undefined,\n encryptionKey,\n encryptionSalt,\n );\n this.#setUnlocked();\n return this.fullUpdate();\n }\n\n /**\n * Verify Password\n *\n * Attempts to decrypt the current vault with a given password\n * to verify its validity.\n *\n * @param password - The vault password.\n */\n async verifyPassword(password: string): Promise {\n const encryptedVault = this.store.getState().vault;\n if (!encryptedVault) {\n throw new Error(KeyringControllerError.VaultError);\n }\n await this.encryptor.decrypt(password, encryptedVault);\n }\n\n /**\n * =========================================\n * === Public Account Management Methods ===\n * =========================================\n */\n\n /**\n * Add New Account.\n *\n * Calls the `addAccounts` method on the given keyring,\n * and then saves those changes.\n *\n * @param selectedKeyring - The currently selected keyring.\n * @returns A Promise that resolves to the state.\n */\n async addNewAccount(\n selectedKeyring: Keyring,\n ): Promise {\n const accounts = await selectedKeyring.addAccounts(1);\n accounts.forEach((hexAccount) => {\n this.emit('newAccount', hexAccount);\n });\n\n await this.persistAllKeyrings();\n return this.fullUpdate();\n }\n\n /**\n * Export Account\n *\n * Requests the private key from the keyring controlling\n * the specified address.\n *\n * Returns a Promise that may resolve with the private key string.\n *\n * @param address - The address of the account to export.\n * @returns The private key of the account.\n */\n async exportAccount(address: string): Promise {\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.exportAccount) {\n throw new Error(KeyringControllerError.UnsupportedExportAccount);\n }\n\n return await keyring.exportAccount(normalizeToHex(address) as Hex);\n }\n\n /**\n * Remove Account.\n *\n * Removes a specific account from a keyring\n * If the account is the last/only one then it also removes the keyring.\n *\n * @param address - The address of the account to remove.\n * @returns A promise that resolves if the operation was successful.\n */\n async removeAccount(address: Hex): Promise {\n const keyring = await this.getKeyringForAccount(address);\n\n // Not all the keyrings support this, so we have to check\n if (!keyring.removeAccount) {\n throw new Error(KeyringControllerError.UnsupportedRemoveAccount);\n }\n keyring.removeAccount(address);\n this.emit('removedAccount', address);\n\n const accounts = await keyring.getAccounts();\n // Check if this was the last/only account\n if (accounts.length === 0) {\n await this.removeEmptyKeyrings();\n }\n\n await this.persistAllKeyrings();\n return this.fullUpdate();\n }\n\n /**\n * Get Accounts\n *\n * Returns the public addresses of all current accounts\n * managed by all currently unlocked keyrings.\n *\n * @returns The array of accounts.\n */\n async getAccounts(): Promise {\n const keyrings = this.keyrings || [];\n\n const keyringArrays = await Promise.all(\n keyrings.map(async (keyring) => keyring.getAccounts()),\n );\n const addresses = keyringArrays.reduce((res, arr) => {\n return res.concat(arr);\n }, []);\n\n return addresses.map(normalizeToHex);\n }\n\n /**\n * Get Keyring Class For Type\n *\n * Searches the current `keyringBuilders` array\n * for a Keyring builder whose unique `type` property\n * matches the provided `type`,\n * returning it if it exists.\n *\n * @param type - The type whose class to get.\n * @returns The class, if it exists.\n */\n getKeyringBuilderForType(\n type: string,\n ): { (): Keyring; type: string } | undefined {\n return this.keyringBuilders.find(\n (keyringBuilder) => keyringBuilder.type === type,\n );\n }\n\n /**\n * Update memStore Keyrings\n *\n * Updates the in-memory keyrings, without persisting.\n */\n async updateMemStoreKeyrings(): Promise {\n const keyrings = await Promise.all(this.keyrings.map(displayForKeyring));\n return this.memStore.updateState({ keyrings });\n }\n\n /**\n * ===========================================\n * === Public RPC Requests Routing Methods ===\n * ===========================================\n */\n\n /**\n * Sign Ethereum Transaction\n *\n * Signs an Ethereum transaction object.\n *\n * @param ethTx - The transaction to sign.\n * @param rawAddress - The transaction 'from' address.\n * @param opts - Signing options.\n * @returns The signed transaction object.\n */\n async signTransaction(\n ethTx: TypedTransaction,\n rawAddress: string,\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signTransaction) {\n throw new Error(KeyringControllerError.UnsupportedSignTransaction);\n }\n\n return await keyring.signTransaction(address, ethTx, opts);\n }\n\n /**\n * Sign Message\n *\n * Attempts to sign the provided message parameters.\n *\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The message to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signMessage(\n msgParams: {\n from: string;\n data: string;\n },\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signMessage) {\n throw new Error(KeyringControllerError.UnsupportedSignMessage);\n }\n\n return await keyring.signMessage(address, msgParams.data, opts);\n }\n\n /**\n * Sign Personal Message\n *\n * Attempts to sign the provided message parameters.\n * Prefixes the hash before signing per the personal sign expectation.\n *\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The message to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signPersonalMessage(\n msgParams: {\n from: string;\n data: string;\n },\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signPersonalMessage) {\n throw new Error(KeyringControllerError.UnsupportedSignPersonalMessage);\n }\n\n const normalizedData = normalizeToHex(msgParams.data) as Hex;\n\n return await keyring.signPersonalMessage(address, normalizedData, opts);\n }\n\n /**\n * Get encryption public key\n *\n * Get encryption public key for using in encrypt/decrypt process.\n *\n * @param address - The address to get the encryption public key for.\n * @param opts - Additional encryption options.\n * @returns The public key.\n */\n async getEncryptionPublicKey(\n address: string,\n opts: Record = {},\n ): Promise {\n const normalizedAddress = normalizeToHex(address) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.getEncryptionPublicKey) {\n throw new Error(KeyringControllerError.UnsupportedGetEncryptionPublicKey);\n }\n\n return await keyring.getEncryptionPublicKey(normalizedAddress, opts);\n }\n\n /**\n * Decrypt Message\n *\n * Attempts to decrypt the provided message parameters.\n *\n * @param msgParams - The decryption message parameters.\n * @param msgParams.from - The address of the account you want to use to decrypt the message.\n * @param msgParams.data - The encrypted data that you want to decrypt.\n * @returns The raw decryption result.\n */\n async decryptMessage(msgParams: {\n from: string;\n data: Eip1024EncryptedData;\n }): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.decryptMessage) {\n throw new Error(KeyringControllerError.UnsupportedDecryptMessage);\n }\n\n return keyring.decryptMessage(address, msgParams.data);\n }\n\n /**\n * Sign Typed Data.\n *\n * @see {@link https://github.com/ethereum/EIPs/pull/712#issuecomment-329988454|EIP712}.\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The data to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signTypedMessage(\n msgParams: {\n from: string;\n data: Record[];\n },\n opts: Record = { version: 'V1' },\n ): Promise {\n const address = normalizeToHex(msgParams.from);\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signTypedData) {\n throw new Error(KeyringControllerError.UnsupportedSignTypedMessage);\n }\n\n // Looks like this is not well defined in the Keyring interface since\n // our tests show that we should be able to pass an array.\n // @ts-expect-error Missing other required permission types.\n return keyring.signTypedData(address, msgParams.data, opts);\n }\n\n /**\n * Gets the app key address for the given Ethereum address and origin.\n *\n * @param rawAddress - The Ethereum address for the app key.\n * @param origin - The origin for the app key.\n * @returns The app key address.\n */\n async getAppKeyAddress(rawAddress: string, origin: string): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.getAppKeyAddress) {\n throw new Error(KeyringControllerError.UnsupportedGetAppKeyAddress);\n }\n\n return keyring.getAppKeyAddress(address, origin);\n }\n\n /**\n * Exports an app key private key for the given Ethereum address and origin.\n *\n * @param rawAddress - The Ethereum address for the app key.\n * @param origin - The origin for the app key.\n * @returns The app key private key.\n */\n async exportAppKeyForAddress(\n rawAddress: string,\n origin: string,\n ): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.exportAccount) {\n throw new Error(KeyringControllerError.UnsupportedExportAppKeyForAddress);\n }\n return keyring.exportAccount(address, { withAppKeyOrigin: origin });\n }\n\n /**\n * =========================================\n * === Public Keyring Management Methods ===\n * =========================================\n */\n\n /**\n * Add New Keyring\n *\n * Adds a new Keyring of the given `type` to the vault\n * and the current decrypted Keyrings array.\n *\n * All Keyring classes implement a unique `type` string,\n * and this is used to retrieve them from the keyringBuilders array.\n *\n * @param type - The type of keyring to add.\n * @param opts - The constructor options for the keyring.\n * @returns The new keyring.\n */\n async addNewKeyring(\n type: string,\n opts: Record = {},\n ): Promise> {\n let keyring: Keyring;\n switch (type) {\n case KeyringType.Simple:\n keyring = await this.#newKeyring(type, opts.privateKeys);\n break;\n default:\n keyring = await this.#newKeyring(type, opts);\n break;\n }\n\n if (!keyring) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n\n if (!opts.mnemonic && type === KeyringType.HD) {\n if (!keyring.generateRandomMnemonic) {\n throw new Error(\n KeyringControllerError.UnsupportedGenerateRandomMnemonic,\n );\n }\n\n keyring.generateRandomMnemonic();\n await keyring.addAccounts(1);\n }\n\n const accounts = await keyring.getAccounts();\n await this.checkForDuplicate(type, accounts);\n\n this.keyrings.push(keyring);\n await this.persistAllKeyrings();\n\n this.fullUpdate();\n\n return keyring;\n }\n\n /**\n * Remove empty keyrings.\n *\n * Loops through the keyrings and removes the ones with empty accounts\n * (usually after removing the last / only account) from a keyring.\n */\n async removeEmptyKeyrings(): Promise {\n const validKeyrings: Keyring[] = [];\n\n // Since getAccounts returns a Promise\n // We need to wait to hear back form each keyring\n // in order to decide which ones are now valid (accounts.length > 0)\n\n await Promise.all(\n this.keyrings.map(async (keyring: Keyring) => {\n const accounts = await keyring.getAccounts();\n if (accounts.length > 0) {\n validKeyrings.push(keyring);\n }\n }),\n );\n this.keyrings = validKeyrings;\n }\n\n /**\n * Checks for duplicate keypairs, using the the first account in the given\n * array. Rejects if a duplicate is found.\n *\n * Only supports 'Simple Key Pair'.\n *\n * @param type - The key pair type to check for.\n * @param newAccountArray - Array of new accounts.\n * @returns The account, if no duplicate is found.\n */\n async checkForDuplicate(\n type: string,\n newAccountArray: string[],\n ): Promise {\n const accounts = await this.getAccounts();\n\n switch (type) {\n case KeyringType.Simple: {\n const isIncluded = Boolean(\n accounts.find(\n (key) =>\n newAccountArray[0] &&\n (key === newAccountArray[0] ||\n key === remove0x(newAccountArray[0])),\n ),\n );\n\n if (isIncluded) {\n throw new Error(KeyringControllerError.DuplicatedAccount);\n }\n return newAccountArray;\n }\n\n default: {\n return newAccountArray;\n }\n }\n }\n\n /**\n * Get Keyring For Account\n *\n * Returns the currently initialized keyring that manages\n * the specified `address` if one exists.\n *\n * @param address - An account address.\n * @returns The keyring of the account, if it exists.\n */\n async getKeyringForAccount(address: string): Promise> {\n const hexed = normalizeToHex(address);\n\n const candidates = await Promise.all(\n this.keyrings.map(async (keyring) => {\n return Promise.all([keyring, keyring.getAccounts()]);\n }),\n );\n\n const winners = candidates.filter((candidate) => {\n const accounts = candidate[1].map(normalizeToHex);\n return accounts.includes(hexed);\n });\n\n if (winners.length && winners[0]?.length) {\n return winners[0][0];\n }\n\n // Adding more info to the error\n let errorInfo = '';\n if (!address) {\n errorInfo = 'The address passed in is invalid/empty';\n } else if (!candidates.length) {\n errorInfo = 'There are no keyrings';\n } else if (!winners.length) {\n errorInfo = 'There are keyrings, but none match the address';\n }\n throw new Error(\n `${KeyringControllerError.NoKeyring}. Error info: ${errorInfo}`,\n );\n }\n\n /**\n * Restore Keyring\n *\n * Attempts to initialize a new keyring from the provided serialized payload.\n * On success, updates the memStore keyrings and returns the resulting\n * keyring instance.\n *\n * @param serialized - The serialized keyring.\n * @returns The deserialized keyring.\n */\n async restoreKeyring(\n serialized: SerializedKeyring,\n ): Promise | undefined> {\n const keyring = await this.#restoreKeyring(serialized);\n if (keyring) {\n await this.updateMemStoreKeyrings();\n }\n return keyring;\n }\n\n /**\n * Get Keyrings by Type\n *\n * Gets all keyrings of the given type.\n *\n * @param type - The keyring types to retrieve.\n * @returns Keyrings matching the specified type.\n */\n getKeyringsByType(type: string): Keyring[] {\n const keyrings = this.keyrings.filter((keyring) => keyring.type === type);\n if (!keyrings.length) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n return keyrings;\n }\n\n /**\n * Persist All Keyrings\n *\n * Iterates the current `keyrings` array,\n * serializes each one into a serialized array,\n * encrypts that array with the provided `password`,\n * and persists that encrypted string to storage.\n *\n * @returns Resolves to true once keyrings are persisted.\n */\n async persistAllKeyrings(): Promise {\n const { encryptionKey, encryptionSalt } = this.memStore.getState();\n\n if (!this.password && !encryptionKey) {\n throw new Error(KeyringControllerError.MissingCredentials);\n }\n\n const serializedKeyrings = await Promise.all(\n this.keyrings.map(async (keyring) => {\n const [type, data] = await Promise.all([\n keyring.type,\n keyring.serialize(),\n ]);\n return { type, data };\n }),\n );\n\n serializedKeyrings.push(...this.unsupportedKeyrings);\n\n let vault;\n let newEncryptionKey;\n\n if (this.cacheEncryptionKey) {\n if (this.password) {\n const { vault: newVault, exportedKeyString } =\n await this.encryptor.encryptWithDetail(\n this.password,\n serializedKeyrings,\n );\n\n vault = newVault;\n newEncryptionKey = exportedKeyString;\n } else if (encryptionKey) {\n const key = await this.encryptor.importKey(encryptionKey);\n const vaultJSON = await this.encryptor.encryptWithKey(\n key,\n serializedKeyrings,\n );\n vaultJSON.salt = encryptionSalt;\n vault = JSON.stringify(vaultJSON);\n }\n } else {\n if (typeof this.password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n vault = await this.encryptor.encrypt(this.password, serializedKeyrings);\n }\n\n if (!vault) {\n throw new Error(KeyringControllerError.MissingVaultData);\n }\n\n this.store.updateState({ vault });\n\n // The keyring updates need to be announced before updating the encryptionKey\n // so that the updated keyring gets propagated to the extension first.\n // Not calling {@link updateMemStoreKeyrings} results in the wrong account being selected\n // in the extension.\n await this.updateMemStoreKeyrings();\n if (newEncryptionKey) {\n this.memStore.updateState({\n encryptionKey: newEncryptionKey,\n encryptionSalt: JSON.parse(vault).salt,\n });\n }\n\n return true;\n }\n\n /**\n * Unlock Keyrings.\n *\n * Attempts to unlock the persisted encrypted storage,\n * initializing the persisted keyrings to RAM.\n *\n * @param password - The keyring controller password.\n * @param encryptionKey - An exported key string to unlock keyrings with.\n * @param encryptionSalt - The salt used to encrypt the vault.\n * @returns The keyrings array.\n */\n async unlockKeyrings(\n password: string | undefined,\n encryptionKey?: string,\n encryptionSalt?: string,\n ): Promise[]> {\n const encryptedVault = this.store.getState().vault;\n if (!encryptedVault) {\n throw new Error(KeyringControllerError.VaultError);\n }\n\n await this.#clearKeyrings();\n\n let vault;\n\n if (this.cacheEncryptionKey) {\n if (password) {\n const result = await this.encryptor.decryptWithDetail(\n password,\n encryptedVault,\n );\n vault = result.vault;\n this.password = password;\n\n this.memStore.updateState({\n encryptionKey: result.exportedKeyString,\n encryptionSalt: result.salt,\n });\n } else {\n const parsedEncryptedVault = JSON.parse(encryptedVault);\n\n if (encryptionSalt !== parsedEncryptedVault.salt) {\n throw new Error(KeyringControllerError.ExpiredCredentials);\n }\n\n if (typeof encryptionKey !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n\n const key = await this.encryptor.importKey(encryptionKey);\n vault = await this.encryptor.decryptWithKey(key, parsedEncryptedVault);\n\n // This call is required on the first call because encryptionKey\n // is not yet inside the memStore\n this.memStore.updateState({\n encryptionKey,\n encryptionSalt,\n });\n }\n } else {\n if (typeof password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n\n vault = await this.encryptor.decrypt(password, encryptedVault);\n this.password = password;\n }\n\n await Promise.all(vault.map(this.#restoreKeyring.bind(this)));\n await this.updateMemStoreKeyrings();\n return this.keyrings;\n }\n\n // =======================\n // === Private Methods ===\n // =======================\n\n /**\n * Create First Key Tree.\n *\n * - Clears the existing vault.\n * - Creates a new vault.\n * - Creates a random new HD Keyring with 1 account.\n * - Makes that account the selected account.\n * - Faucets that account on testnet.\n * - Puts the current seed words into the state tree.\n *\n * @returns A promise that resolves if the operation was successful.\n */\n async #createFirstKeyTree(): Promise {\n await this.#clearKeyrings();\n\n const keyring = await this.addNewKeyring(KeyringType.HD);\n if (!keyring) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n\n const [firstAccount] = await keyring.getAccounts();\n if (!firstAccount) {\n throw new Error(KeyringControllerError.NoAccountOnKeychain);\n }\n\n const hexAccount = normalizeToHex(firstAccount);\n this.emit('newVault', hexAccount);\n return null;\n }\n\n /**\n * Restore Keyring Helper\n *\n * Attempts to initialize a new keyring from the provided serialized payload.\n * On success, returns the resulting keyring instance.\n *\n * @param serialized - The serialized keyring.\n * @param serialized.type - Keyring type.\n * @param serialized.data - Keyring data.\n * @returns The deserialized keyring or undefined if the keyring type is unsupported.\n */\n async #restoreKeyring(\n serialized: SerializedKeyring,\n ): Promise | undefined> {\n const { type, data } = serialized;\n\n let keyring: Keyring | undefined;\n try {\n keyring = await this.#newKeyring(type, data);\n } catch (error) {\n // Ignore error.\n console.error(error);\n }\n\n if (!keyring) {\n this.unsupportedKeyrings.push(serialized);\n return undefined;\n }\n\n // getAccounts also validates the accounts for some keyrings\n await keyring.getAccounts();\n this.keyrings.push(keyring);\n return keyring;\n }\n\n /**\n * Clear Keyrings\n *\n * Deallocates all currently managed keyrings and accounts.\n * Used before initializing a new vault.\n */\n async #clearKeyrings(): Promise {\n // clear keyrings from memory\n this.keyrings = [];\n this.memStore.updateState({\n keyrings: [],\n });\n }\n\n /**\n * Unlock Keyrings\n *\n * Unlocks the keyrings.\n *\n * @fires KeyringController#unlock\n */\n #setUnlocked(): void {\n this.memStore.updateState({ isUnlocked: true });\n this.emit('unlock');\n }\n\n /**\n * Instantiate, initialize and return a new keyring\n *\n * The keyring instantiated is of the given `type`.\n *\n * @param type - The type of keyring to add.\n * @param data - The data to restore a previously serialized keyring.\n * @returns The new keyring.\n */\n async #newKeyring(type: string, data: unknown): Promise> {\n const keyringBuilder = this.getKeyringBuilderForType(type);\n\n if (!keyringBuilder) {\n throw new Error(\n `${KeyringControllerError.NoKeyringBuilder}. Keyring type: ${type}`,\n );\n }\n\n const keyring = keyringBuilder();\n\n if (!isValidJson(data)) {\n throw new Error(KeyringControllerError.DataType);\n }\n\n await keyring.deserialize(data);\n\n // @ts-expect-error The method 'init' is not part of the current Keyring type\n if (keyring.init) {\n // @ts-expect-error The method 'init' is not part of the current Keyring type\n await keyring.init();\n }\n\n return keyring;\n }\n}\n\n/**\n * Get builder function for `Keyring`\n *\n * Returns a builder function for `Keyring` with a `type` property.\n *\n * @param KeyringConstructor - The Keyring class for the builder.\n * @returns A builder function for the given Keyring.\n */\nfunction keyringBuilderFactory(KeyringConstructor: KeyringClass) {\n const builder = () => new KeyringConstructor();\n\n builder.type = KeyringConstructor.type;\n\n return builder;\n}\n\n/**\n * Display For Keyring\n *\n * Is used for adding the current keyrings to the state object.\n *\n * @param keyring - The keyring to display.\n * @returns A keyring display object, with type and accounts properties.\n */\nasync function displayForKeyring(\n keyring: Keyring,\n): Promise<{ type: string; accounts: string[] }> {\n const accounts = await keyring.getAccounts();\n\n return {\n type: keyring.type,\n accounts: accounts.map(normalizeToHex),\n };\n}\n\nexport { KeyringController, keyringBuilderFactory };\n"]} \ No newline at end of file From ac53475836f8b2bbb2729958268715d811ec48bc Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Fri, 12 May 2023 19:06:29 -0400 Subject: [PATCH 06/10] Remove data type check --- src/KeyringController.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/KeyringController.ts b/src/KeyringController.ts index 073b47a0..15a26db3 100644 --- a/src/KeyringController.ts +++ b/src/KeyringController.ts @@ -1030,10 +1030,7 @@ class KeyringController extends EventEmitter { const keyring = keyringBuilder(); - if (!isValidJson(data)) { - throw new Error(KeyringControllerError.DataType); - } - + // @ts-expect-error Enforce data type after updating clients await keyring.deserialize(data); // @ts-expect-error The method 'init' is not part of the current Keyring type From 9c7684f2071dbc0dc079d5f7cf36a5301d5d5110 Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Fri, 12 May 2023 19:07:48 -0400 Subject: [PATCH 07/10] Remove dist --- .gitignore | 2 +- dist/KeyringController.d.ts | 380 -------------- dist/KeyringController.js | 872 -------------------------------- dist/KeyringController.js.map | 1 - dist/constants.d.ts | 28 - dist/constants.js | 34 -- dist/constants.js.map | 1 - dist/index.d.ts | 2 - dist/index.js | 10 - dist/index.js.map | 1 - dist/test/encryptor.mock.d.ts | 38 -- dist/test/encryptor.mock.js | 86 ---- dist/test/encryptor.mock.js.map | 1 - dist/test/index.d.ts | 3 - dist/test/index.js | 16 - dist/test/index.js.map | 1 - dist/test/keyring.mock.d.ts | 13 - dist/test/keyring.mock.js | 36 -- dist/test/keyring.mock.js.map | 1 - dist/types.d.ts | 31 -- dist/types.js | 3 - dist/types.js.map | 1 - 22 files changed, 1 insertion(+), 1560 deletions(-) delete mode 100644 dist/KeyringController.d.ts delete mode 100644 dist/KeyringController.js delete mode 100644 dist/KeyringController.js.map delete mode 100644 dist/constants.d.ts delete mode 100644 dist/constants.js delete mode 100644 dist/constants.js.map delete mode 100644 dist/index.d.ts delete mode 100644 dist/index.js delete mode 100644 dist/index.js.map delete mode 100644 dist/test/encryptor.mock.d.ts delete mode 100644 dist/test/encryptor.mock.js delete mode 100644 dist/test/encryptor.mock.js.map delete mode 100644 dist/test/index.d.ts delete mode 100644 dist/test/index.js delete mode 100644 dist/test/index.js.map delete mode 100644 dist/test/keyring.mock.d.ts delete mode 100644 dist/test/keyring.mock.js delete mode 100644 dist/test/keyring.mock.js.map delete mode 100644 dist/types.d.ts delete mode 100644 dist/types.js delete mode 100644 dist/types.js.map diff --git a/.gitignore b/.gitignore index c242f8c1..fbee401d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,4 @@ coverage !.yarn/versions # distribution -# dist +dist diff --git a/dist/KeyringController.d.ts b/dist/KeyringController.d.ts deleted file mode 100644 index 8dcd1648..00000000 --- a/dist/KeyringController.d.ts +++ /dev/null @@ -1,380 +0,0 @@ -/// -import type { TypedTransaction, TxData } from '@ethereumjs/tx'; -import type { Hex, Json, Bytes, Keyring, KeyringClass, Eip1024EncryptedData } from '@metamask/utils'; -import { EventEmitter } from 'events'; -import ObservableStore from 'obs-store'; -import { SerializedKeyring, KeyringControllerArgs, KeyringControllerState } from './types'; -declare class KeyringController extends EventEmitter { - #private; - keyringBuilders: { - (): Keyring; - type: string; - }[]; - store: typeof ObservableStore; - memStore: typeof ObservableStore; - encryptor: any; - keyrings: Keyring[]; - cacheEncryptionKey: boolean; - unsupportedKeyrings: SerializedKeyring[]; - password?: string; - constructor({ keyringBuilders, cacheEncryptionKey, initState, encryptor, }: KeyringControllerArgs); - /** - * Full Update - * - * Emits the `update` event and @returns a Promise that resolves to - * the current state. - * - * Frequently used to end asynchronous chains in this class, - * indicating consumers can often either listen for updates, - * or accept a state-resolving promise to consume their results. - * - * @returns The controller state. - */ - fullUpdate(): any; - /** - * ======================================= - * === Public Vault Management Methods === - * ======================================= - */ - /** - * Create New Vault And Keychain - * - * Destroys any old encrypted storage, - * creates a new encrypted store with the given password, - * randomly creates a new HD wallet with 1 account, - * faucets that account on the testnet. - * - * @fires KeyringController#unlock - * @param password - The password to encrypt the vault with. - * @returns A promise that resolves to the state. - */ - createNewVaultAndKeychain(password: string): Promise; - /** - * CreateNewVaultAndRestore - * - * Destroys any old encrypted storage, - * creates a new encrypted store with the given password, - * creates a new HD wallet from the given seed with 1 account. - * - * @fires KeyringController#unlock - * @param password - The password to encrypt the vault with. - * @param seedPhrase - The BIP39-compliant seed phrase, - * either as a string or Uint8Array. - * @returns A promise that resolves to the state. - */ - createNewVaultAndRestore(password: string, seedPhrase: Uint8Array | string | number[]): Promise; - /** - * Set Locked. - * This method deallocates all secrets, and effectively locks MetaMask. - * - * @fires KeyringController#lock - * @returns A promise that resolves to the state. - */ - setLocked(): Promise; - /** - * Submit password. - * - * Attempts to decrypt the current vault and load its keyrings - * into memory. - * - * Temporarily also migrates any old-style vaults first, as well - * (Pre MetaMask 3.0.0). - * - * @fires KeyringController#unlock - * @param password - The keyring controller password. - * @returns A promise that resolves to the state. - */ - submitPassword(password: string): Promise; - /** - * Submit Encryption Key. - * - * Attempts to decrypt the current vault and load its keyrings - * into memory based on the vault and CryptoKey information. - * - * @fires KeyringController#unlock - * @param encryptionKey - The encrypted key information used to decrypt the vault. - * @param encryptionSalt - The salt used to generate the last key. - * @returns A promise that resolves to the state. - */ - submitEncryptionKey(encryptionKey: string, encryptionSalt: string): Promise; - /** - * Verify Password - * - * Attempts to decrypt the current vault with a given password - * to verify its validity. - * - * @param password - The vault password. - */ - verifyPassword(password: string): Promise; - /** - * ========================================= - * === Public Account Management Methods === - * ========================================= - */ - /** - * Add New Account. - * - * Calls the `addAccounts` method on the given keyring, - * and then saves those changes. - * - * @param selectedKeyring - The currently selected keyring. - * @returns A Promise that resolves to the state. - */ - addNewAccount(selectedKeyring: Keyring): Promise; - /** - * Export Account - * - * Requests the private key from the keyring controlling - * the specified address. - * - * Returns a Promise that may resolve with the private key string. - * - * @param address - The address of the account to export. - * @returns The private key of the account. - */ - exportAccount(address: string): Promise; - /** - * Remove Account. - * - * Removes a specific account from a keyring - * If the account is the last/only one then it also removes the keyring. - * - * @param address - The address of the account to remove. - * @returns A promise that resolves if the operation was successful. - */ - removeAccount(address: Hex): Promise; - /** - * Get Accounts - * - * Returns the public addresses of all current accounts - * managed by all currently unlocked keyrings. - * - * @returns The array of accounts. - */ - getAccounts(): Promise; - /** - * Get Keyring Class For Type - * - * Searches the current `keyringBuilders` array - * for a Keyring builder whose unique `type` property - * matches the provided `type`, - * returning it if it exists. - * - * @param type - The type whose class to get. - * @returns The class, if it exists. - */ - getKeyringBuilderForType(type: string): { - (): Keyring; - type: string; - } | undefined; - /** - * Update memStore Keyrings - * - * Updates the in-memory keyrings, without persisting. - */ - updateMemStoreKeyrings(): Promise; - /** - * =========================================== - * === Public RPC Requests Routing Methods === - * =========================================== - */ - /** - * Sign Ethereum Transaction - * - * Signs an Ethereum transaction object. - * - * @param ethTx - The transaction to sign. - * @param rawAddress - The transaction 'from' address. - * @param opts - Signing options. - * @returns The signed transaction object. - */ - signTransaction(ethTx: TypedTransaction, rawAddress: string, opts?: Record): Promise; - /** - * Sign Message - * - * Attempts to sign the provided message parameters. - * - * @param msgParams - The message parameters to sign. - * @param msgParams.from - From address. - * @param msgParams.data - The message to sign. - * @param opts - Additional signing options. - * @returns The raw signature. - */ - signMessage(msgParams: { - from: string; - data: string; - }, opts?: Record): Promise; - /** - * Sign Personal Message - * - * Attempts to sign the provided message parameters. - * Prefixes the hash before signing per the personal sign expectation. - * - * @param msgParams - The message parameters to sign. - * @param msgParams.from - From address. - * @param msgParams.data - The message to sign. - * @param opts - Additional signing options. - * @returns The raw signature. - */ - signPersonalMessage(msgParams: { - from: string; - data: string; - }, opts?: Record): Promise; - /** - * Get encryption public key - * - * Get encryption public key for using in encrypt/decrypt process. - * - * @param address - The address to get the encryption public key for. - * @param opts - Additional encryption options. - * @returns The public key. - */ - getEncryptionPublicKey(address: string, opts?: Record): Promise; - /** - * Decrypt Message - * - * Attempts to decrypt the provided message parameters. - * - * @param msgParams - The decryption message parameters. - * @param msgParams.from - The address of the account you want to use to decrypt the message. - * @param msgParams.data - The encrypted data that you want to decrypt. - * @returns The raw decryption result. - */ - decryptMessage(msgParams: { - from: string; - data: Eip1024EncryptedData; - }): Promise; - /** - * Sign Typed Data. - * - * @see {@link https://github.com/ethereum/EIPs/pull/712#issuecomment-329988454|EIP712}. - * @param msgParams - The message parameters to sign. - * @param msgParams.from - From address. - * @param msgParams.data - The data to sign. - * @param opts - Additional signing options. - * @returns The raw signature. - */ - signTypedMessage(msgParams: { - from: string; - data: Record[]; - }, opts?: Record): Promise; - /** - * Gets the app key address for the given Ethereum address and origin. - * - * @param rawAddress - The Ethereum address for the app key. - * @param origin - The origin for the app key. - * @returns The app key address. - */ - getAppKeyAddress(rawAddress: string, origin: string): Promise; - /** - * Exports an app key private key for the given Ethereum address and origin. - * - * @param rawAddress - The Ethereum address for the app key. - * @param origin - The origin for the app key. - * @returns The app key private key. - */ - exportAppKeyForAddress(rawAddress: string, origin: string): Promise; - /** - * ========================================= - * === Public Keyring Management Methods === - * ========================================= - */ - /** - * Add New Keyring - * - * Adds a new Keyring of the given `type` to the vault - * and the current decrypted Keyrings array. - * - * All Keyring classes implement a unique `type` string, - * and this is used to retrieve them from the keyringBuilders array. - * - * @param type - The type of keyring to add. - * @param opts - The constructor options for the keyring. - * @returns The new keyring. - */ - addNewKeyring(type: string, opts?: Record): Promise>; - /** - * Remove empty keyrings. - * - * Loops through the keyrings and removes the ones with empty accounts - * (usually after removing the last / only account) from a keyring. - */ - removeEmptyKeyrings(): Promise; - /** - * Checks for duplicate keypairs, using the the first account in the given - * array. Rejects if a duplicate is found. - * - * Only supports 'Simple Key Pair'. - * - * @param type - The key pair type to check for. - * @param newAccountArray - Array of new accounts. - * @returns The account, if no duplicate is found. - */ - checkForDuplicate(type: string, newAccountArray: string[]): Promise; - /** - * Get Keyring For Account - * - * Returns the currently initialized keyring that manages - * the specified `address` if one exists. - * - * @param address - An account address. - * @returns The keyring of the account, if it exists. - */ - getKeyringForAccount(address: string): Promise>; - /** - * Restore Keyring - * - * Attempts to initialize a new keyring from the provided serialized payload. - * On success, updates the memStore keyrings and returns the resulting - * keyring instance. - * - * @param serialized - The serialized keyring. - * @returns The deserialized keyring. - */ - restoreKeyring(serialized: SerializedKeyring): Promise | undefined>; - /** - * Get Keyrings by Type - * - * Gets all keyrings of the given type. - * - * @param type - The keyring types to retrieve. - * @returns Keyrings matching the specified type. - */ - getKeyringsByType(type: string): Keyring[]; - /** - * Persist All Keyrings - * - * Iterates the current `keyrings` array, - * serializes each one into a serialized array, - * encrypts that array with the provided `password`, - * and persists that encrypted string to storage. - * - * @returns Resolves to true once keyrings are persisted. - */ - persistAllKeyrings(): Promise; - /** - * Unlock Keyrings. - * - * Attempts to unlock the persisted encrypted storage, - * initializing the persisted keyrings to RAM. - * - * @param password - The keyring controller password. - * @param encryptionKey - An exported key string to unlock keyrings with. - * @param encryptionSalt - The salt used to encrypt the vault. - * @returns The keyrings array. - */ - unlockKeyrings(password: string | undefined, encryptionKey?: string, encryptionSalt?: string): Promise[]>; -} -/** - * Get builder function for `Keyring` - * - * Returns a builder function for `Keyring` with a `type` property. - * - * @param KeyringConstructor - The Keyring class for the builder. - * @returns A builder function for the given Keyring. - */ -declare function keyringBuilderFactory(KeyringConstructor: KeyringClass): { - (): Keyring; - type: string; -}; -export { KeyringController, keyringBuilderFactory }; diff --git a/dist/KeyringController.js b/dist/KeyringController.js deleted file mode 100644 index 18df95b3..00000000 --- a/dist/KeyringController.js +++ /dev/null @@ -1,872 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { - if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); - 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"); - return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -var _KeyringController_instances, _KeyringController_createFirstKeyTree, _KeyringController_restoreKeyring, _KeyringController_clearKeyrings, _KeyringController_setUnlocked, _KeyringController_newKeyring; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.keyringBuilderFactory = exports.KeyringController = void 0; -const encryptorUtils = __importStar(require("@metamask/browser-passworder")); -const eth_hd_keyring_1 = __importDefault(require("@metamask/eth-hd-keyring")); -const eth_sig_util_1 = require("@metamask/eth-sig-util"); -const eth_simple_keyring_1 = __importDefault(require("@metamask/eth-simple-keyring")); -const utils_1 = require("@metamask/utils"); -// TODO: Stop using `events`, and remove the notice about this from the README -// eslint-disable-next-line import/no-nodejs-modules -const events_1 = require("events"); -const obs_store_1 = __importDefault(require("obs-store")); -const constants_1 = require("./constants"); -const defaultKeyringBuilders = [ - keyringBuilderFactory(eth_simple_keyring_1.default), - keyringBuilderFactory(eth_hd_keyring_1.default), -]; -class KeyringController extends events_1.EventEmitter { - constructor({ keyringBuilders, cacheEncryptionKey, initState = {}, encryptor = encryptorUtils, }) { - super(); - _KeyringController_instances.add(this); - this.keyringBuilders = keyringBuilders - ? defaultKeyringBuilders.concat(keyringBuilders) - : defaultKeyringBuilders; - this.store = new obs_store_1.default(initState); - this.memStore = new obs_store_1.default({ - isUnlocked: false, - keyringTypes: this.keyringBuilders.map((keyringBuilder) => keyringBuilder.type), - keyrings: [], - encryptionKey: null, - }); - this.encryptor = encryptor; - this.keyrings = []; - this.unsupportedKeyrings = []; - // This option allows the controller to cache an exported key - // for use in decrypting and encrypting data without password - this.cacheEncryptionKey = Boolean(cacheEncryptionKey); - } - /** - * Full Update - * - * Emits the `update` event and @returns a Promise that resolves to - * the current state. - * - * Frequently used to end asynchronous chains in this class, - * indicating consumers can often either listen for updates, - * or accept a state-resolving promise to consume their results. - * - * @returns The controller state. - */ - fullUpdate() { - this.emit('update', this.memStore.getState()); - return this.memStore.getState(); - } - /** - * ======================================= - * === Public Vault Management Methods === - * ======================================= - */ - /** - * Create New Vault And Keychain - * - * Destroys any old encrypted storage, - * creates a new encrypted store with the given password, - * randomly creates a new HD wallet with 1 account, - * faucets that account on the testnet. - * - * @fires KeyringController#unlock - * @param password - The password to encrypt the vault with. - * @returns A promise that resolves to the state. - */ - async createNewVaultAndKeychain(password) { - this.password = password; - await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createFirstKeyTree).call(this); - __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); - return this.fullUpdate(); - } - /** - * CreateNewVaultAndRestore - * - * Destroys any old encrypted storage, - * creates a new encrypted store with the given password, - * creates a new HD wallet from the given seed with 1 account. - * - * @fires KeyringController#unlock - * @param password - The password to encrypt the vault with. - * @param seedPhrase - The BIP39-compliant seed phrase, - * either as a string or Uint8Array. - * @returns A promise that resolves to the state. - */ - async createNewVaultAndRestore(password, seedPhrase) { - if (typeof password !== 'string') { - throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType); - } - this.password = password; - await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this); - const keyring = await this.addNewKeyring(constants_1.KeyringType.HD, { - mnemonic: seedPhrase, - numberOfAccounts: 1, - }); - const [firstAccount] = await keyring.getAccounts(); - if (!firstAccount) { - throw new Error(constants_1.KeyringControllerError.NoFirstAccount); - } - __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); - return this.fullUpdate(); - } - /** - * Set Locked. - * This method deallocates all secrets, and effectively locks MetaMask. - * - * @fires KeyringController#lock - * @returns A promise that resolves to the state. - */ - async setLocked() { - delete this.password; - // set locked - this.memStore.updateState({ - isUnlocked: false, - encryptionKey: null, - encryptionSalt: null, - }); - // remove keyrings - this.keyrings = []; - await this.updateMemStoreKeyrings(); - this.emit('lock'); - return this.fullUpdate(); - } - /** - * Submit password. - * - * Attempts to decrypt the current vault and load its keyrings - * into memory. - * - * Temporarily also migrates any old-style vaults first, as well - * (Pre MetaMask 3.0.0). - * - * @fires KeyringController#unlock - * @param password - The keyring controller password. - * @returns A promise that resolves to the state. - */ - async submitPassword(password) { - this.keyrings = await this.unlockKeyrings(password); - __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); - return this.fullUpdate(); - } - /** - * Submit Encryption Key. - * - * Attempts to decrypt the current vault and load its keyrings - * into memory based on the vault and CryptoKey information. - * - * @fires KeyringController#unlock - * @param encryptionKey - The encrypted key information used to decrypt the vault. - * @param encryptionSalt - The salt used to generate the last key. - * @returns A promise that resolves to the state. - */ - async submitEncryptionKey(encryptionKey, encryptionSalt) { - this.keyrings = await this.unlockKeyrings(undefined, encryptionKey, encryptionSalt); - __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this); - return this.fullUpdate(); - } - /** - * Verify Password - * - * Attempts to decrypt the current vault with a given password - * to verify its validity. - * - * @param password - The vault password. - */ - async verifyPassword(password) { - const encryptedVault = this.store.getState().vault; - if (!encryptedVault) { - throw new Error(constants_1.KeyringControllerError.VaultError); - } - await this.encryptor.decrypt(password, encryptedVault); - } - /** - * ========================================= - * === Public Account Management Methods === - * ========================================= - */ - /** - * Add New Account. - * - * Calls the `addAccounts` method on the given keyring, - * and then saves those changes. - * - * @param selectedKeyring - The currently selected keyring. - * @returns A Promise that resolves to the state. - */ - async addNewAccount(selectedKeyring) { - const accounts = await selectedKeyring.addAccounts(1); - accounts.forEach((hexAccount) => { - this.emit('newAccount', hexAccount); - }); - await this.persistAllKeyrings(); - return this.fullUpdate(); - } - /** - * Export Account - * - * Requests the private key from the keyring controlling - * the specified address. - * - * Returns a Promise that may resolve with the private key string. - * - * @param address - The address of the account to export. - * @returns The private key of the account. - */ - async exportAccount(address) { - const keyring = await this.getKeyringForAccount(address); - if (!keyring.exportAccount) { - throw new Error(constants_1.KeyringControllerError.UnsupportedExportAccount); - } - return await keyring.exportAccount((0, eth_sig_util_1.normalize)(address)); - } - /** - * Remove Account. - * - * Removes a specific account from a keyring - * If the account is the last/only one then it also removes the keyring. - * - * @param address - The address of the account to remove. - * @returns A promise that resolves if the operation was successful. - */ - async removeAccount(address) { - const keyring = await this.getKeyringForAccount(address); - // Not all the keyrings support this, so we have to check - if (!keyring.removeAccount) { - throw new Error(constants_1.KeyringControllerError.UnsupportedRemoveAccount); - } - keyring.removeAccount(address); - this.emit('removedAccount', address); - const accounts = await keyring.getAccounts(); - // Check if this was the last/only account - if (accounts.length === 0) { - await this.removeEmptyKeyrings(); - } - await this.persistAllKeyrings(); - return this.fullUpdate(); - } - /** - * Get Accounts - * - * Returns the public addresses of all current accounts - * managed by all currently unlocked keyrings. - * - * @returns The array of accounts. - */ - async getAccounts() { - const keyrings = this.keyrings || []; - const keyringArrays = await Promise.all(keyrings.map(async (keyring) => keyring.getAccounts())); - const addresses = keyringArrays.reduce((res, arr) => { - return res.concat(arr); - }, []); - return addresses.map(eth_sig_util_1.normalize); - } - /** - * Get Keyring Class For Type - * - * Searches the current `keyringBuilders` array - * for a Keyring builder whose unique `type` property - * matches the provided `type`, - * returning it if it exists. - * - * @param type - The type whose class to get. - * @returns The class, if it exists. - */ - getKeyringBuilderForType(type) { - return this.keyringBuilders.find((keyringBuilder) => keyringBuilder.type === type); - } - /** - * Update memStore Keyrings - * - * Updates the in-memory keyrings, without persisting. - */ - async updateMemStoreKeyrings() { - const keyrings = await Promise.all(this.keyrings.map(displayForKeyring)); - return this.memStore.updateState({ keyrings }); - } - /** - * =========================================== - * === Public RPC Requests Routing Methods === - * =========================================== - */ - /** - * Sign Ethereum Transaction - * - * Signs an Ethereum transaction object. - * - * @param ethTx - The transaction to sign. - * @param rawAddress - The transaction 'from' address. - * @param opts - Signing options. - * @returns The signed transaction object. - */ - async signTransaction(ethTx, rawAddress, opts = {}) { - const address = (0, eth_sig_util_1.normalize)(rawAddress); - const keyring = await this.getKeyringForAccount(address); - if (!keyring.signTransaction) { - throw new Error(constants_1.KeyringControllerError.UnsupportedSignTransaction); - } - return await keyring.signTransaction(address, ethTx, opts); - } - /** - * Sign Message - * - * Attempts to sign the provided message parameters. - * - * @param msgParams - The message parameters to sign. - * @param msgParams.from - From address. - * @param msgParams.data - The message to sign. - * @param opts - Additional signing options. - * @returns The raw signature. - */ - async signMessage(msgParams, opts = {}) { - const address = (0, eth_sig_util_1.normalize)(msgParams.from); - const keyring = await this.getKeyringForAccount(address); - if (!keyring.signMessage) { - throw new Error(constants_1.KeyringControllerError.UnsupportedSignMessage); - } - return await keyring.signMessage(address, msgParams.data, opts); - } - /** - * Sign Personal Message - * - * Attempts to sign the provided message parameters. - * Prefixes the hash before signing per the personal sign expectation. - * - * @param msgParams - The message parameters to sign. - * @param msgParams.from - From address. - * @param msgParams.data - The message to sign. - * @param opts - Additional signing options. - * @returns The raw signature. - */ - async signPersonalMessage(msgParams, opts = {}) { - const address = (0, eth_sig_util_1.normalize)(msgParams.from); - const keyring = await this.getKeyringForAccount(address); - if (!keyring.signPersonalMessage) { - throw new Error(constants_1.KeyringControllerError.UnsupportedSignPersonalMessage); - } - const normalizedData = (0, eth_sig_util_1.normalize)(msgParams.data); - return await keyring.signPersonalMessage(address, normalizedData, opts); - } - /** - * Get encryption public key - * - * Get encryption public key for using in encrypt/decrypt process. - * - * @param address - The address to get the encryption public key for. - * @param opts - Additional encryption options. - * @returns The public key. - */ - async getEncryptionPublicKey(address, opts = {}) { - const normalizedAddress = (0, eth_sig_util_1.normalize)(address); - const keyring = await this.getKeyringForAccount(address); - if (!keyring.getEncryptionPublicKey) { - throw new Error(constants_1.KeyringControllerError.UnsupportedGetEncryptionPublicKey); - } - return await keyring.getEncryptionPublicKey(normalizedAddress, opts); - } - /** - * Decrypt Message - * - * Attempts to decrypt the provided message parameters. - * - * @param msgParams - The decryption message parameters. - * @param msgParams.from - The address of the account you want to use to decrypt the message. - * @param msgParams.data - The encrypted data that you want to decrypt. - * @returns The raw decryption result. - */ - async decryptMessage(msgParams) { - const address = (0, eth_sig_util_1.normalize)(msgParams.from); - const keyring = await this.getKeyringForAccount(address); - if (!keyring.decryptMessage) { - throw new Error(constants_1.KeyringControllerError.UnsupportedDecryptMessage); - } - return keyring.decryptMessage(address, msgParams.data); - } - /** - * Sign Typed Data. - * - * @see {@link https://github.com/ethereum/EIPs/pull/712#issuecomment-329988454|EIP712}. - * @param msgParams - The message parameters to sign. - * @param msgParams.from - From address. - * @param msgParams.data - The data to sign. - * @param opts - Additional signing options. - * @returns The raw signature. - */ - async signTypedMessage(msgParams, opts = { version: 'V1' }) { - const address = (0, eth_sig_util_1.normalize)(msgParams.from); - const keyring = await this.getKeyringForAccount(address); - if (!keyring.signTypedData) { - throw new Error(constants_1.KeyringControllerError.UnsupportedSignTypedMessage); - } - // Looks like this is not well defined in the Keyring interface since - // our tests show that we should be able to pass an array. - // @ts-expect-error Missing other required permission types. - return keyring.signTypedData(address, msgParams.data, opts); - } - /** - * Gets the app key address for the given Ethereum address and origin. - * - * @param rawAddress - The Ethereum address for the app key. - * @param origin - The origin for the app key. - * @returns The app key address. - */ - async getAppKeyAddress(rawAddress, origin) { - const address = (0, eth_sig_util_1.normalize)(rawAddress); - const keyring = await this.getKeyringForAccount(address); - if (!keyring.getAppKeyAddress) { - throw new Error(constants_1.KeyringControllerError.UnsupportedGetAppKeyAddress); - } - return keyring.getAppKeyAddress(address, origin); - } - /** - * Exports an app key private key for the given Ethereum address and origin. - * - * @param rawAddress - The Ethereum address for the app key. - * @param origin - The origin for the app key. - * @returns The app key private key. - */ - async exportAppKeyForAddress(rawAddress, origin) { - const address = (0, eth_sig_util_1.normalize)(rawAddress); - const keyring = await this.getKeyringForAccount(address); - if (!keyring.exportAccount) { - throw new Error(constants_1.KeyringControllerError.UnsupportedExportAppKeyForAddress); - } - return keyring.exportAccount(address, { withAppKeyOrigin: origin }); - } - /** - * ========================================= - * === Public Keyring Management Methods === - * ========================================= - */ - /** - * Add New Keyring - * - * Adds a new Keyring of the given `type` to the vault - * and the current decrypted Keyrings array. - * - * All Keyring classes implement a unique `type` string, - * and this is used to retrieve them from the keyringBuilders array. - * - * @param type - The type of keyring to add. - * @param opts - The constructor options for the keyring. - * @returns The new keyring. - */ - async addNewKeyring(type, opts = {}) { - let keyring; - switch (type) { - case constants_1.KeyringType.Simple: - keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts.privateKeys); - break; - default: - keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts); - break; - } - if (!keyring) { - throw new Error(constants_1.KeyringControllerError.NoKeyring); - } - if (!opts.mnemonic && type === constants_1.KeyringType.HD) { - if (!keyring.generateRandomMnemonic) { - throw new Error(constants_1.KeyringControllerError.UnsupportedGenerateRandomMnemonic); - } - keyring.generateRandomMnemonic(); - await keyring.addAccounts(1); - } - const accounts = await keyring.getAccounts(); - await this.checkForDuplicate(type, accounts); - this.keyrings.push(keyring); - await this.persistAllKeyrings(); - this.fullUpdate(); - return keyring; - } - /** - * Remove empty keyrings. - * - * Loops through the keyrings and removes the ones with empty accounts - * (usually after removing the last / only account) from a keyring. - */ - async removeEmptyKeyrings() { - const validKeyrings = []; - // Since getAccounts returns a Promise - // We need to wait to hear back form each keyring - // in order to decide which ones are now valid (accounts.length > 0) - await Promise.all(this.keyrings.map(async (keyring) => { - const accounts = await keyring.getAccounts(); - if (accounts.length > 0) { - validKeyrings.push(keyring); - } - })); - this.keyrings = validKeyrings; - } - /** - * Checks for duplicate keypairs, using the the first account in the given - * array. Rejects if a duplicate is found. - * - * Only supports 'Simple Key Pair'. - * - * @param type - The key pair type to check for. - * @param newAccountArray - Array of new accounts. - * @returns The account, if no duplicate is found. - */ - async checkForDuplicate(type, newAccountArray) { - const accounts = await this.getAccounts(); - switch (type) { - case constants_1.KeyringType.Simple: { - const isIncluded = Boolean(accounts.find((key) => newAccountArray[0] && - (key === newAccountArray[0] || - key === (0, utils_1.remove0x)(newAccountArray[0])))); - if (isIncluded) { - throw new Error(constants_1.KeyringControllerError.DuplicatedAccount); - } - return newAccountArray; - } - default: { - return newAccountArray; - } - } - } - /** - * Get Keyring For Account - * - * Returns the currently initialized keyring that manages - * the specified `address` if one exists. - * - * @param address - An account address. - * @returns The keyring of the account, if it exists. - */ - async getKeyringForAccount(address) { - var _a; - const hexed = (0, eth_sig_util_1.normalize)(address); - const candidates = await Promise.all(this.keyrings.map(async (keyring) => { - return Promise.all([keyring, keyring.getAccounts()]); - })); - const winners = candidates.filter((candidate) => { - const accounts = candidate[1].map(eth_sig_util_1.normalize); - return accounts.includes(hexed); - }); - if (winners.length && ((_a = winners[0]) === null || _a === void 0 ? void 0 : _a.length)) { - return winners[0][0]; - } - // Adding more info to the error - let errorInfo = ''; - if (!address) { - errorInfo = 'The address passed in is invalid/empty'; - } - else if (!candidates.length) { - errorInfo = 'There are no keyrings'; - } - else if (!winners.length) { - errorInfo = 'There are keyrings, but none match the address'; - } - throw new Error(`${constants_1.KeyringControllerError.NoKeyring}. Error info: ${errorInfo}`); - } - /** - * Restore Keyring - * - * Attempts to initialize a new keyring from the provided serialized payload. - * On success, updates the memStore keyrings and returns the resulting - * keyring instance. - * - * @param serialized - The serialized keyring. - * @returns The deserialized keyring. - */ - async restoreKeyring(serialized) { - const keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).call(this, serialized); - if (keyring) { - await this.updateMemStoreKeyrings(); - } - return keyring; - } - /** - * Get Keyrings by Type - * - * Gets all keyrings of the given type. - * - * @param type - The keyring types to retrieve. - * @returns Keyrings matching the specified type. - */ - getKeyringsByType(type) { - const keyrings = this.keyrings.filter((keyring) => keyring.type === type); - if (!keyrings.length) { - throw new Error(constants_1.KeyringControllerError.NoKeyring); - } - return keyrings; - } - /** - * Persist All Keyrings - * - * Iterates the current `keyrings` array, - * serializes each one into a serialized array, - * encrypts that array with the provided `password`, - * and persists that encrypted string to storage. - * - * @returns Resolves to true once keyrings are persisted. - */ - async persistAllKeyrings() { - const { encryptionKey, encryptionSalt } = this.memStore.getState(); - if (!this.password && !encryptionKey) { - throw new Error(constants_1.KeyringControllerError.MissingCredentials); - } - const serializedKeyrings = await Promise.all(this.keyrings.map(async (keyring) => { - const [type, data] = await Promise.all([ - keyring.type, - keyring.serialize(), - ]); - return { type, data }; - })); - serializedKeyrings.push(...this.unsupportedKeyrings); - let vault; - let newEncryptionKey; - if (this.cacheEncryptionKey) { - if (this.password) { - const { vault: newVault, exportedKeyString } = await this.encryptor.encryptWithDetail(this.password, serializedKeyrings); - vault = newVault; - newEncryptionKey = exportedKeyString; - } - else if (encryptionKey) { - const key = await this.encryptor.importKey(encryptionKey); - const vaultJSON = await this.encryptor.encryptWithKey(key, serializedKeyrings); - vaultJSON.salt = encryptionSalt; - vault = JSON.stringify(vaultJSON); - } - } - else { - if (typeof this.password !== 'string') { - throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType); - } - vault = await this.encryptor.encrypt(this.password, serializedKeyrings); - } - if (!vault) { - throw new Error(constants_1.KeyringControllerError.MissingVaultData); - } - this.store.updateState({ vault }); - // The keyring updates need to be announced before updating the encryptionKey - // so that the updated keyring gets propagated to the extension first. - // Not calling {@link updateMemStoreKeyrings} results in the wrong account being selected - // in the extension. - await this.updateMemStoreKeyrings(); - if (newEncryptionKey) { - this.memStore.updateState({ - encryptionKey: newEncryptionKey, - encryptionSalt: JSON.parse(vault).salt, - }); - } - return true; - } - /** - * Unlock Keyrings. - * - * Attempts to unlock the persisted encrypted storage, - * initializing the persisted keyrings to RAM. - * - * @param password - The keyring controller password. - * @param encryptionKey - An exported key string to unlock keyrings with. - * @param encryptionSalt - The salt used to encrypt the vault. - * @returns The keyrings array. - */ - async unlockKeyrings(password, encryptionKey, encryptionSalt) { - const encryptedVault = this.store.getState().vault; - if (!encryptedVault) { - throw new Error(constants_1.KeyringControllerError.VaultError); - } - await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this); - let vault; - if (this.cacheEncryptionKey) { - if (password) { - const result = await this.encryptor.decryptWithDetail(password, encryptedVault); - vault = result.vault; - this.password = password; - this.memStore.updateState({ - encryptionKey: result.exportedKeyString, - encryptionSalt: result.salt, - }); - } - else { - const parsedEncryptedVault = JSON.parse(encryptedVault); - if (encryptionSalt !== parsedEncryptedVault.salt) { - throw new Error(constants_1.KeyringControllerError.ExpiredCredentials); - } - if (typeof encryptionKey !== 'string') { - throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType); - } - const key = await this.encryptor.importKey(encryptionKey); - vault = await this.encryptor.decryptWithKey(key, parsedEncryptedVault); - // This call is required on the first call because encryptionKey - // is not yet inside the memStore - this.memStore.updateState({ - encryptionKey, - encryptionSalt, - }); - } - } - else { - if (typeof password !== 'string') { - throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType); - } - vault = await this.encryptor.decrypt(password, encryptedVault); - this.password = password; - } - await Promise.all(vault.map(__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).bind(this))); - await this.updateMemStoreKeyrings(); - return this.keyrings; - } -} -exports.KeyringController = KeyringController; -_KeyringController_instances = new WeakSet(), _KeyringController_createFirstKeyTree = -// ======================= -// === Private Methods === -// ======================= -/** - * Create First Key Tree. - * - * - Clears the existing vault. - * - Creates a new vault. - * - Creates a random new HD Keyring with 1 account. - * - Makes that account the selected account. - * - Faucets that account on testnet. - * - Puts the current seed words into the state tree. - * - * @returns A promise that resolves if the operation was successful. - */ -async function _KeyringController_createFirstKeyTree() { - await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this); - const keyring = await this.addNewKeyring(constants_1.KeyringType.HD); - if (!keyring) { - throw new Error(constants_1.KeyringControllerError.NoKeyring); - } - const [firstAccount] = await keyring.getAccounts(); - if (!firstAccount) { - throw new Error(constants_1.KeyringControllerError.NoAccountOnKeychain); - } - const hexAccount = (0, eth_sig_util_1.normalize)(firstAccount); - this.emit('newVault', hexAccount); - return null; -}, _KeyringController_restoreKeyring = -/** - * Restore Keyring Helper - * - * Attempts to initialize a new keyring from the provided serialized payload. - * On success, returns the resulting keyring instance. - * - * @param serialized - The serialized keyring. - * @param serialized.type - Keyring type. - * @param serialized.data - Keyring data. - * @returns The deserialized keyring or undefined if the keyring type is unsupported. - */ -async function _KeyringController_restoreKeyring(serialized) { - const { type, data } = serialized; - let keyring; - try { - keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, data); - } - catch (error) { - // Ignore error. - console.error(error); - } - if (!keyring) { - this.unsupportedKeyrings.push(serialized); - return undefined; - } - // getAccounts also validates the accounts for some keyrings - await keyring.getAccounts(); - this.keyrings.push(keyring); - return keyring; -}, _KeyringController_clearKeyrings = -/** - * Clear Keyrings - * - * Deallocates all currently managed keyrings and accounts. - * Used before initializing a new vault. - */ -async function _KeyringController_clearKeyrings() { - // clear keyrings from memory - this.keyrings = []; - this.memStore.updateState({ - keyrings: [], - }); -}, _KeyringController_setUnlocked = function _KeyringController_setUnlocked() { - this.memStore.updateState({ isUnlocked: true }); - this.emit('unlock'); -}, _KeyringController_newKeyring = -/** - * Instantiate, initialize and return a new keyring - * - * The keyring instantiated is of the given `type`. - * - * @param type - The type of keyring to add. - * @param data - The data to restore a previously serialized keyring. - * @returns The new keyring. - */ -async function _KeyringController_newKeyring(type, data) { - const keyringBuilder = this.getKeyringBuilderForType(type); - if (!keyringBuilder) { - throw new Error(`${constants_1.KeyringControllerError.NoKeyringBuilder}. Keyring type: ${type}`); - } - const keyring = keyringBuilder(); - if (!(0, utils_1.isValidJson)(data)) { - throw new Error(constants_1.KeyringControllerError.DataType); - } - await keyring.deserialize(data); - // @ts-expect-error The method 'init' is not part of the current Keyring type - if (keyring.init) { - // @ts-expect-error The method 'init' is not part of the current Keyring type - await keyring.init(); - } - return keyring; -}; -/** - * Get builder function for `Keyring` - * - * Returns a builder function for `Keyring` with a `type` property. - * - * @param KeyringConstructor - The Keyring class for the builder. - * @returns A builder function for the given Keyring. - */ -function keyringBuilderFactory(KeyringConstructor) { - const builder = () => new KeyringConstructor(); - builder.type = KeyringConstructor.type; - return builder; -} -exports.keyringBuilderFactory = keyringBuilderFactory; -/** - * Display For Keyring - * - * Is used for adding the current keyrings to the state object. - * - * @param keyring - The keyring to display. - * @returns A keyring display object, with type and accounts properties. - */ -async function displayForKeyring(keyring) { - const accounts = await keyring.getAccounts(); - return { - type: keyring.type, - accounts: accounts.map(eth_sig_util_1.normalize), - }; -} -//# sourceMappingURL=KeyringController.js.map \ No newline at end of file diff --git a/dist/KeyringController.js.map b/dist/KeyringController.js.map deleted file mode 100644 index 07bafb47..00000000 --- a/dist/KeyringController.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"KeyringController.js","sourceRoot":"","sources":["../src/KeyringController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TypedTransaction, TxData } from '@ethereumjs/tx';\nimport * as encryptorUtils from '@metamask/browser-passworder';\nimport HDKeyring from '@metamask/eth-hd-keyring';\nimport { normalize as normalizeToHex } from '@metamask/eth-sig-util';\nimport SimpleKeyring from '@metamask/eth-simple-keyring';\nimport { remove0x, isValidJson } from '@metamask/utils';\nimport type {\n Hex,\n Json,\n Bytes,\n Keyring,\n KeyringClass,\n Eip1024EncryptedData,\n} from '@metamask/utils';\n// TODO: Stop using `events`, and remove the notice about this from the README\n// eslint-disable-next-line import/no-nodejs-modules\nimport { EventEmitter } from 'events';\nimport ObservableStore from 'obs-store';\n\nimport { KeyringType, KeyringControllerError } from './constants';\nimport {\n SerializedKeyring,\n KeyringControllerArgs,\n KeyringControllerState,\n} from './types';\n\nconst defaultKeyringBuilders = [\n keyringBuilderFactory(SimpleKeyring),\n keyringBuilderFactory(HDKeyring),\n];\n\nclass KeyringController extends EventEmitter {\n keyringBuilders: { (): Keyring; type: string }[];\n\n public store: typeof ObservableStore;\n\n public memStore: typeof ObservableStore;\n\n public encryptor: any;\n\n public keyrings: Keyring[];\n\n public cacheEncryptionKey: boolean;\n\n public unsupportedKeyrings: SerializedKeyring[];\n\n public password?: string;\n\n constructor({\n keyringBuilders,\n cacheEncryptionKey,\n initState = {},\n encryptor = encryptorUtils,\n }: KeyringControllerArgs) {\n super();\n this.keyringBuilders = keyringBuilders\n ? defaultKeyringBuilders.concat(keyringBuilders)\n : defaultKeyringBuilders;\n this.store = new ObservableStore(initState);\n this.memStore = new ObservableStore({\n isUnlocked: false,\n keyringTypes: this.keyringBuilders.map(\n (keyringBuilder) => keyringBuilder.type,\n ),\n keyrings: [],\n encryptionKey: null,\n });\n\n this.encryptor = encryptor;\n this.keyrings = [];\n this.unsupportedKeyrings = [];\n\n // This option allows the controller to cache an exported key\n // for use in decrypting and encrypting data without password\n this.cacheEncryptionKey = Boolean(cacheEncryptionKey);\n }\n\n /**\n * Full Update\n *\n * Emits the `update` event and @returns a Promise that resolves to\n * the current state.\n *\n * Frequently used to end asynchronous chains in this class,\n * indicating consumers can often either listen for updates,\n * or accept a state-resolving promise to consume their results.\n *\n * @returns The controller state.\n */\n fullUpdate() {\n this.emit('update', this.memStore.getState());\n return this.memStore.getState();\n }\n\n /**\n * =======================================\n * === Public Vault Management Methods ===\n * =======================================\n */\n\n /**\n * Create New Vault And Keychain\n *\n * Destroys any old encrypted storage,\n * creates a new encrypted store with the given password,\n * randomly creates a new HD wallet with 1 account,\n * faucets that account on the testnet.\n *\n * @fires KeyringController#unlock\n * @param password - The password to encrypt the vault with.\n * @returns A promise that resolves to the state.\n */\n async createNewVaultAndKeychain(\n password: string,\n ): Promise {\n this.password = password;\n\n await this.#createFirstKeyTree();\n this.#setUnlocked();\n return this.fullUpdate();\n }\n\n /**\n * CreateNewVaultAndRestore\n *\n * Destroys any old encrypted storage,\n * creates a new encrypted store with the given password,\n * creates a new HD wallet from the given seed with 1 account.\n *\n * @fires KeyringController#unlock\n * @param password - The password to encrypt the vault with.\n * @param seedPhrase - The BIP39-compliant seed phrase,\n * either as a string or Uint8Array.\n * @returns A promise that resolves to the state.\n */\n async createNewVaultAndRestore(\n password: string,\n seedPhrase: Uint8Array | string | number[],\n ): Promise {\n if (typeof password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n this.password = password;\n\n await this.#clearKeyrings();\n const keyring = await this.addNewKeyring(KeyringType.HD, {\n mnemonic: seedPhrase,\n numberOfAccounts: 1,\n });\n\n const [firstAccount] = await keyring.getAccounts();\n\n if (!firstAccount) {\n throw new Error(KeyringControllerError.NoFirstAccount);\n }\n this.#setUnlocked();\n return this.fullUpdate();\n }\n\n /**\n * Set Locked.\n * This method deallocates all secrets, and effectively locks MetaMask.\n *\n * @fires KeyringController#lock\n * @returns A promise that resolves to the state.\n */\n async setLocked(): Promise {\n delete this.password;\n\n // set locked\n this.memStore.updateState({\n isUnlocked: false,\n encryptionKey: null,\n encryptionSalt: null,\n });\n\n // remove keyrings\n this.keyrings = [];\n await this.updateMemStoreKeyrings();\n this.emit('lock');\n return this.fullUpdate();\n }\n\n /**\n * Submit password.\n *\n * Attempts to decrypt the current vault and load its keyrings\n * into memory.\n *\n * Temporarily also migrates any old-style vaults first, as well\n * (Pre MetaMask 3.0.0).\n *\n * @fires KeyringController#unlock\n * @param password - The keyring controller password.\n * @returns A promise that resolves to the state.\n */\n async submitPassword(password: string): Promise {\n this.keyrings = await this.unlockKeyrings(password);\n\n this.#setUnlocked();\n return this.fullUpdate();\n }\n\n /**\n * Submit Encryption Key.\n *\n * Attempts to decrypt the current vault and load its keyrings\n * into memory based on the vault and CryptoKey information.\n *\n * @fires KeyringController#unlock\n * @param encryptionKey - The encrypted key information used to decrypt the vault.\n * @param encryptionSalt - The salt used to generate the last key.\n * @returns A promise that resolves to the state.\n */\n async submitEncryptionKey(\n encryptionKey: string,\n encryptionSalt: string,\n ): Promise {\n this.keyrings = await this.unlockKeyrings(\n undefined,\n encryptionKey,\n encryptionSalt,\n );\n this.#setUnlocked();\n return this.fullUpdate();\n }\n\n /**\n * Verify Password\n *\n * Attempts to decrypt the current vault with a given password\n * to verify its validity.\n *\n * @param password - The vault password.\n */\n async verifyPassword(password: string): Promise {\n const encryptedVault = this.store.getState().vault;\n if (!encryptedVault) {\n throw new Error(KeyringControllerError.VaultError);\n }\n await this.encryptor.decrypt(password, encryptedVault);\n }\n\n /**\n * =========================================\n * === Public Account Management Methods ===\n * =========================================\n */\n\n /**\n * Add New Account.\n *\n * Calls the `addAccounts` method on the given keyring,\n * and then saves those changes.\n *\n * @param selectedKeyring - The currently selected keyring.\n * @returns A Promise that resolves to the state.\n */\n async addNewAccount(\n selectedKeyring: Keyring,\n ): Promise {\n const accounts = await selectedKeyring.addAccounts(1);\n accounts.forEach((hexAccount) => {\n this.emit('newAccount', hexAccount);\n });\n\n await this.persistAllKeyrings();\n return this.fullUpdate();\n }\n\n /**\n * Export Account\n *\n * Requests the private key from the keyring controlling\n * the specified address.\n *\n * Returns a Promise that may resolve with the private key string.\n *\n * @param address - The address of the account to export.\n * @returns The private key of the account.\n */\n async exportAccount(address: string): Promise {\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.exportAccount) {\n throw new Error(KeyringControllerError.UnsupportedExportAccount);\n }\n\n return await keyring.exportAccount(normalizeToHex(address) as Hex);\n }\n\n /**\n * Remove Account.\n *\n * Removes a specific account from a keyring\n * If the account is the last/only one then it also removes the keyring.\n *\n * @param address - The address of the account to remove.\n * @returns A promise that resolves if the operation was successful.\n */\n async removeAccount(address: Hex): Promise {\n const keyring = await this.getKeyringForAccount(address);\n\n // Not all the keyrings support this, so we have to check\n if (!keyring.removeAccount) {\n throw new Error(KeyringControllerError.UnsupportedRemoveAccount);\n }\n keyring.removeAccount(address);\n this.emit('removedAccount', address);\n\n const accounts = await keyring.getAccounts();\n // Check if this was the last/only account\n if (accounts.length === 0) {\n await this.removeEmptyKeyrings();\n }\n\n await this.persistAllKeyrings();\n return this.fullUpdate();\n }\n\n /**\n * Get Accounts\n *\n * Returns the public addresses of all current accounts\n * managed by all currently unlocked keyrings.\n *\n * @returns The array of accounts.\n */\n async getAccounts(): Promise {\n const keyrings = this.keyrings || [];\n\n const keyringArrays = await Promise.all(\n keyrings.map(async (keyring) => keyring.getAccounts()),\n );\n const addresses = keyringArrays.reduce((res, arr) => {\n return res.concat(arr);\n }, []);\n\n return addresses.map(normalizeToHex);\n }\n\n /**\n * Get Keyring Class For Type\n *\n * Searches the current `keyringBuilders` array\n * for a Keyring builder whose unique `type` property\n * matches the provided `type`,\n * returning it if it exists.\n *\n * @param type - The type whose class to get.\n * @returns The class, if it exists.\n */\n getKeyringBuilderForType(\n type: string,\n ): { (): Keyring; type: string } | undefined {\n return this.keyringBuilders.find(\n (keyringBuilder) => keyringBuilder.type === type,\n );\n }\n\n /**\n * Update memStore Keyrings\n *\n * Updates the in-memory keyrings, without persisting.\n */\n async updateMemStoreKeyrings(): Promise {\n const keyrings = await Promise.all(this.keyrings.map(displayForKeyring));\n return this.memStore.updateState({ keyrings });\n }\n\n /**\n * ===========================================\n * === Public RPC Requests Routing Methods ===\n * ===========================================\n */\n\n /**\n * Sign Ethereum Transaction\n *\n * Signs an Ethereum transaction object.\n *\n * @param ethTx - The transaction to sign.\n * @param rawAddress - The transaction 'from' address.\n * @param opts - Signing options.\n * @returns The signed transaction object.\n */\n async signTransaction(\n ethTx: TypedTransaction,\n rawAddress: string,\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signTransaction) {\n throw new Error(KeyringControllerError.UnsupportedSignTransaction);\n }\n\n return await keyring.signTransaction(address, ethTx, opts);\n }\n\n /**\n * Sign Message\n *\n * Attempts to sign the provided message parameters.\n *\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The message to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signMessage(\n msgParams: {\n from: string;\n data: string;\n },\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signMessage) {\n throw new Error(KeyringControllerError.UnsupportedSignMessage);\n }\n\n return await keyring.signMessage(address, msgParams.data, opts);\n }\n\n /**\n * Sign Personal Message\n *\n * Attempts to sign the provided message parameters.\n * Prefixes the hash before signing per the personal sign expectation.\n *\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The message to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signPersonalMessage(\n msgParams: {\n from: string;\n data: string;\n },\n opts: Record = {},\n ): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signPersonalMessage) {\n throw new Error(KeyringControllerError.UnsupportedSignPersonalMessage);\n }\n\n const normalizedData = normalizeToHex(msgParams.data) as Hex;\n\n return await keyring.signPersonalMessage(address, normalizedData, opts);\n }\n\n /**\n * Get encryption public key\n *\n * Get encryption public key for using in encrypt/decrypt process.\n *\n * @param address - The address to get the encryption public key for.\n * @param opts - Additional encryption options.\n * @returns The public key.\n */\n async getEncryptionPublicKey(\n address: string,\n opts: Record = {},\n ): Promise {\n const normalizedAddress = normalizeToHex(address) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.getEncryptionPublicKey) {\n throw new Error(KeyringControllerError.UnsupportedGetEncryptionPublicKey);\n }\n\n return await keyring.getEncryptionPublicKey(normalizedAddress, opts);\n }\n\n /**\n * Decrypt Message\n *\n * Attempts to decrypt the provided message parameters.\n *\n * @param msgParams - The decryption message parameters.\n * @param msgParams.from - The address of the account you want to use to decrypt the message.\n * @param msgParams.data - The encrypted data that you want to decrypt.\n * @returns The raw decryption result.\n */\n async decryptMessage(msgParams: {\n from: string;\n data: Eip1024EncryptedData;\n }): Promise {\n const address = normalizeToHex(msgParams.from) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.decryptMessage) {\n throw new Error(KeyringControllerError.UnsupportedDecryptMessage);\n }\n\n return keyring.decryptMessage(address, msgParams.data);\n }\n\n /**\n * Sign Typed Data.\n *\n * @see {@link https://github.com/ethereum/EIPs/pull/712#issuecomment-329988454|EIP712}.\n * @param msgParams - The message parameters to sign.\n * @param msgParams.from - From address.\n * @param msgParams.data - The data to sign.\n * @param opts - Additional signing options.\n * @returns The raw signature.\n */\n async signTypedMessage(\n msgParams: {\n from: string;\n data: Record[];\n },\n opts: Record = { version: 'V1' },\n ): Promise {\n const address = normalizeToHex(msgParams.from);\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.signTypedData) {\n throw new Error(KeyringControllerError.UnsupportedSignTypedMessage);\n }\n\n // Looks like this is not well defined in the Keyring interface since\n // our tests show that we should be able to pass an array.\n // @ts-expect-error Missing other required permission types.\n return keyring.signTypedData(address, msgParams.data, opts);\n }\n\n /**\n * Gets the app key address for the given Ethereum address and origin.\n *\n * @param rawAddress - The Ethereum address for the app key.\n * @param origin - The origin for the app key.\n * @returns The app key address.\n */\n async getAppKeyAddress(rawAddress: string, origin: string): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.getAppKeyAddress) {\n throw new Error(KeyringControllerError.UnsupportedGetAppKeyAddress);\n }\n\n return keyring.getAppKeyAddress(address, origin);\n }\n\n /**\n * Exports an app key private key for the given Ethereum address and origin.\n *\n * @param rawAddress - The Ethereum address for the app key.\n * @param origin - The origin for the app key.\n * @returns The app key private key.\n */\n async exportAppKeyForAddress(\n rawAddress: string,\n origin: string,\n ): Promise {\n const address = normalizeToHex(rawAddress) as Hex;\n const keyring = await this.getKeyringForAccount(address);\n if (!keyring.exportAccount) {\n throw new Error(KeyringControllerError.UnsupportedExportAppKeyForAddress);\n }\n return keyring.exportAccount(address, { withAppKeyOrigin: origin });\n }\n\n /**\n * =========================================\n * === Public Keyring Management Methods ===\n * =========================================\n */\n\n /**\n * Add New Keyring\n *\n * Adds a new Keyring of the given `type` to the vault\n * and the current decrypted Keyrings array.\n *\n * All Keyring classes implement a unique `type` string,\n * and this is used to retrieve them from the keyringBuilders array.\n *\n * @param type - The type of keyring to add.\n * @param opts - The constructor options for the keyring.\n * @returns The new keyring.\n */\n async addNewKeyring(\n type: string,\n opts: Record = {},\n ): Promise> {\n let keyring: Keyring;\n switch (type) {\n case KeyringType.Simple:\n keyring = await this.#newKeyring(type, opts.privateKeys);\n break;\n default:\n keyring = await this.#newKeyring(type, opts);\n break;\n }\n\n if (!keyring) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n\n if (!opts.mnemonic && type === KeyringType.HD) {\n if (!keyring.generateRandomMnemonic) {\n throw new Error(\n KeyringControllerError.UnsupportedGenerateRandomMnemonic,\n );\n }\n\n keyring.generateRandomMnemonic();\n await keyring.addAccounts(1);\n }\n\n const accounts = await keyring.getAccounts();\n await this.checkForDuplicate(type, accounts);\n\n this.keyrings.push(keyring);\n await this.persistAllKeyrings();\n\n this.fullUpdate();\n\n return keyring;\n }\n\n /**\n * Remove empty keyrings.\n *\n * Loops through the keyrings and removes the ones with empty accounts\n * (usually after removing the last / only account) from a keyring.\n */\n async removeEmptyKeyrings(): Promise {\n const validKeyrings: Keyring[] = [];\n\n // Since getAccounts returns a Promise\n // We need to wait to hear back form each keyring\n // in order to decide which ones are now valid (accounts.length > 0)\n\n await Promise.all(\n this.keyrings.map(async (keyring: Keyring) => {\n const accounts = await keyring.getAccounts();\n if (accounts.length > 0) {\n validKeyrings.push(keyring);\n }\n }),\n );\n this.keyrings = validKeyrings;\n }\n\n /**\n * Checks for duplicate keypairs, using the the first account in the given\n * array. Rejects if a duplicate is found.\n *\n * Only supports 'Simple Key Pair'.\n *\n * @param type - The key pair type to check for.\n * @param newAccountArray - Array of new accounts.\n * @returns The account, if no duplicate is found.\n */\n async checkForDuplicate(\n type: string,\n newAccountArray: string[],\n ): Promise {\n const accounts = await this.getAccounts();\n\n switch (type) {\n case KeyringType.Simple: {\n const isIncluded = Boolean(\n accounts.find(\n (key) =>\n newAccountArray[0] &&\n (key === newAccountArray[0] ||\n key === remove0x(newAccountArray[0])),\n ),\n );\n\n if (isIncluded) {\n throw new Error(KeyringControllerError.DuplicatedAccount);\n }\n return newAccountArray;\n }\n\n default: {\n return newAccountArray;\n }\n }\n }\n\n /**\n * Get Keyring For Account\n *\n * Returns the currently initialized keyring that manages\n * the specified `address` if one exists.\n *\n * @param address - An account address.\n * @returns The keyring of the account, if it exists.\n */\n async getKeyringForAccount(address: string): Promise> {\n const hexed = normalizeToHex(address);\n\n const candidates = await Promise.all(\n this.keyrings.map(async (keyring) => {\n return Promise.all([keyring, keyring.getAccounts()]);\n }),\n );\n\n const winners = candidates.filter((candidate) => {\n const accounts = candidate[1].map(normalizeToHex);\n return accounts.includes(hexed);\n });\n\n if (winners.length && winners[0]?.length) {\n return winners[0][0];\n }\n\n // Adding more info to the error\n let errorInfo = '';\n if (!address) {\n errorInfo = 'The address passed in is invalid/empty';\n } else if (!candidates.length) {\n errorInfo = 'There are no keyrings';\n } else if (!winners.length) {\n errorInfo = 'There are keyrings, but none match the address';\n }\n throw new Error(\n `${KeyringControllerError.NoKeyring}. Error info: ${errorInfo}`,\n );\n }\n\n /**\n * Restore Keyring\n *\n * Attempts to initialize a new keyring from the provided serialized payload.\n * On success, updates the memStore keyrings and returns the resulting\n * keyring instance.\n *\n * @param serialized - The serialized keyring.\n * @returns The deserialized keyring.\n */\n async restoreKeyring(\n serialized: SerializedKeyring,\n ): Promise | undefined> {\n const keyring = await this.#restoreKeyring(serialized);\n if (keyring) {\n await this.updateMemStoreKeyrings();\n }\n return keyring;\n }\n\n /**\n * Get Keyrings by Type\n *\n * Gets all keyrings of the given type.\n *\n * @param type - The keyring types to retrieve.\n * @returns Keyrings matching the specified type.\n */\n getKeyringsByType(type: string): Keyring[] {\n const keyrings = this.keyrings.filter((keyring) => keyring.type === type);\n if (!keyrings.length) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n return keyrings;\n }\n\n /**\n * Persist All Keyrings\n *\n * Iterates the current `keyrings` array,\n * serializes each one into a serialized array,\n * encrypts that array with the provided `password`,\n * and persists that encrypted string to storage.\n *\n * @returns Resolves to true once keyrings are persisted.\n */\n async persistAllKeyrings(): Promise {\n const { encryptionKey, encryptionSalt } = this.memStore.getState();\n\n if (!this.password && !encryptionKey) {\n throw new Error(KeyringControllerError.MissingCredentials);\n }\n\n const serializedKeyrings = await Promise.all(\n this.keyrings.map(async (keyring) => {\n const [type, data] = await Promise.all([\n keyring.type,\n keyring.serialize(),\n ]);\n return { type, data };\n }),\n );\n\n serializedKeyrings.push(...this.unsupportedKeyrings);\n\n let vault;\n let newEncryptionKey;\n\n if (this.cacheEncryptionKey) {\n if (this.password) {\n const { vault: newVault, exportedKeyString } =\n await this.encryptor.encryptWithDetail(\n this.password,\n serializedKeyrings,\n );\n\n vault = newVault;\n newEncryptionKey = exportedKeyString;\n } else if (encryptionKey) {\n const key = await this.encryptor.importKey(encryptionKey);\n const vaultJSON = await this.encryptor.encryptWithKey(\n key,\n serializedKeyrings,\n );\n vaultJSON.salt = encryptionSalt;\n vault = JSON.stringify(vaultJSON);\n }\n } else {\n if (typeof this.password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n vault = await this.encryptor.encrypt(this.password, serializedKeyrings);\n }\n\n if (!vault) {\n throw new Error(KeyringControllerError.MissingVaultData);\n }\n\n this.store.updateState({ vault });\n\n // The keyring updates need to be announced before updating the encryptionKey\n // so that the updated keyring gets propagated to the extension first.\n // Not calling {@link updateMemStoreKeyrings} results in the wrong account being selected\n // in the extension.\n await this.updateMemStoreKeyrings();\n if (newEncryptionKey) {\n this.memStore.updateState({\n encryptionKey: newEncryptionKey,\n encryptionSalt: JSON.parse(vault).salt,\n });\n }\n\n return true;\n }\n\n /**\n * Unlock Keyrings.\n *\n * Attempts to unlock the persisted encrypted storage,\n * initializing the persisted keyrings to RAM.\n *\n * @param password - The keyring controller password.\n * @param encryptionKey - An exported key string to unlock keyrings with.\n * @param encryptionSalt - The salt used to encrypt the vault.\n * @returns The keyrings array.\n */\n async unlockKeyrings(\n password: string | undefined,\n encryptionKey?: string,\n encryptionSalt?: string,\n ): Promise[]> {\n const encryptedVault = this.store.getState().vault;\n if (!encryptedVault) {\n throw new Error(KeyringControllerError.VaultError);\n }\n\n await this.#clearKeyrings();\n\n let vault;\n\n if (this.cacheEncryptionKey) {\n if (password) {\n const result = await this.encryptor.decryptWithDetail(\n password,\n encryptedVault,\n );\n vault = result.vault;\n this.password = password;\n\n this.memStore.updateState({\n encryptionKey: result.exportedKeyString,\n encryptionSalt: result.salt,\n });\n } else {\n const parsedEncryptedVault = JSON.parse(encryptedVault);\n\n if (encryptionSalt !== parsedEncryptedVault.salt) {\n throw new Error(KeyringControllerError.ExpiredCredentials);\n }\n\n if (typeof encryptionKey !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n\n const key = await this.encryptor.importKey(encryptionKey);\n vault = await this.encryptor.decryptWithKey(key, parsedEncryptedVault);\n\n // This call is required on the first call because encryptionKey\n // is not yet inside the memStore\n this.memStore.updateState({\n encryptionKey,\n encryptionSalt,\n });\n }\n } else {\n if (typeof password !== 'string') {\n throw new TypeError(KeyringControllerError.WrongPasswordType);\n }\n\n vault = await this.encryptor.decrypt(password, encryptedVault);\n this.password = password;\n }\n\n await Promise.all(vault.map(this.#restoreKeyring.bind(this)));\n await this.updateMemStoreKeyrings();\n return this.keyrings;\n }\n\n // =======================\n // === Private Methods ===\n // =======================\n\n /**\n * Create First Key Tree.\n *\n * - Clears the existing vault.\n * - Creates a new vault.\n * - Creates a random new HD Keyring with 1 account.\n * - Makes that account the selected account.\n * - Faucets that account on testnet.\n * - Puts the current seed words into the state tree.\n *\n * @returns A promise that resolves if the operation was successful.\n */\n async #createFirstKeyTree(): Promise {\n await this.#clearKeyrings();\n\n const keyring = await this.addNewKeyring(KeyringType.HD);\n if (!keyring) {\n throw new Error(KeyringControllerError.NoKeyring);\n }\n\n const [firstAccount] = await keyring.getAccounts();\n if (!firstAccount) {\n throw new Error(KeyringControllerError.NoAccountOnKeychain);\n }\n\n const hexAccount = normalizeToHex(firstAccount);\n this.emit('newVault', hexAccount);\n return null;\n }\n\n /**\n * Restore Keyring Helper\n *\n * Attempts to initialize a new keyring from the provided serialized payload.\n * On success, returns the resulting keyring instance.\n *\n * @param serialized - The serialized keyring.\n * @param serialized.type - Keyring type.\n * @param serialized.data - Keyring data.\n * @returns The deserialized keyring or undefined if the keyring type is unsupported.\n */\n async #restoreKeyring(\n serialized: SerializedKeyring,\n ): Promise | undefined> {\n const { type, data } = serialized;\n\n let keyring: Keyring | undefined;\n try {\n keyring = await this.#newKeyring(type, data);\n } catch (error) {\n // Ignore error.\n console.error(error);\n }\n\n if (!keyring) {\n this.unsupportedKeyrings.push(serialized);\n return undefined;\n }\n\n // getAccounts also validates the accounts for some keyrings\n await keyring.getAccounts();\n this.keyrings.push(keyring);\n return keyring;\n }\n\n /**\n * Clear Keyrings\n *\n * Deallocates all currently managed keyrings and accounts.\n * Used before initializing a new vault.\n */\n async #clearKeyrings(): Promise {\n // clear keyrings from memory\n this.keyrings = [];\n this.memStore.updateState({\n keyrings: [],\n });\n }\n\n /**\n * Unlock Keyrings\n *\n * Unlocks the keyrings.\n *\n * @fires KeyringController#unlock\n */\n #setUnlocked(): void {\n this.memStore.updateState({ isUnlocked: true });\n this.emit('unlock');\n }\n\n /**\n * Instantiate, initialize and return a new keyring\n *\n * The keyring instantiated is of the given `type`.\n *\n * @param type - The type of keyring to add.\n * @param data - The data to restore a previously serialized keyring.\n * @returns The new keyring.\n */\n async #newKeyring(type: string, data: unknown): Promise> {\n const keyringBuilder = this.getKeyringBuilderForType(type);\n\n if (!keyringBuilder) {\n throw new Error(\n `${KeyringControllerError.NoKeyringBuilder}. Keyring type: ${type}`,\n );\n }\n\n const keyring = keyringBuilder();\n\n if (!isValidJson(data)) {\n throw new Error(KeyringControllerError.DataType);\n }\n\n await keyring.deserialize(data);\n\n // @ts-expect-error The method 'init' is not part of the current Keyring type\n if (keyring.init) {\n // @ts-expect-error The method 'init' is not part of the current Keyring type\n await keyring.init();\n }\n\n return keyring;\n }\n}\n\n/**\n * Get builder function for `Keyring`\n *\n * Returns a builder function for `Keyring` with a `type` property.\n *\n * @param KeyringConstructor - The Keyring class for the builder.\n * @returns A builder function for the given Keyring.\n */\nfunction keyringBuilderFactory(KeyringConstructor: KeyringClass) {\n const builder = () => new KeyringConstructor();\n\n builder.type = KeyringConstructor.type;\n\n return builder;\n}\n\n/**\n * Display For Keyring\n *\n * Is used for adding the current keyrings to the state object.\n *\n * @param keyring - The keyring to display.\n * @returns A keyring display object, with type and accounts properties.\n */\nasync function displayForKeyring(\n keyring: Keyring,\n): Promise<{ type: string; accounts: string[] }> {\n const accounts = await keyring.getAccounts();\n\n return {\n type: keyring.type,\n accounts: accounts.map(normalizeToHex),\n };\n}\n\nexport { KeyringController, keyringBuilderFactory };\n"]} \ No newline at end of file diff --git a/dist/constants.d.ts b/dist/constants.d.ts deleted file mode 100644 index 2b89fd0f..00000000 --- a/dist/constants.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -export declare enum KeyringType { - HD = "HD Key Tree", - Simple = "Simple Key Pair" -} -export declare enum KeyringControllerError { - NoKeyring = "KeyringController - No keyring found", - WrongPasswordType = "KeyringController - Password must be of type string.", - NoFirstAccount = "KeyringController - First Account not found.", - DuplicatedAccount = "KeyringController - The account you are trying to import is a duplicate", - VaultError = "KeyringController - Cannot unlock without a previous vault.", - UnsupportedGenerateRandomMnemonic = "KeyringController - The current keyring does not support the method generateRandomMnemonic.", - UnsupportedExportAccount = "`KeyringController - The keyring for the current address does not support the method exportAccount", - UnsupportedRemoveAccount = "`KeyringController - The keyring for the current address does not support the method removeAccount", - UnsupportedSignTransaction = "KeyringController - The keyring for the current address does not support the method signTransaction.", - UnsupportedSignMessage = "KeyringController - The keyring for the current address does not support the method signMessage.", - UnsupportedSignPersonalMessage = "KeyringController - The keyring for the current address does not support the method signPersonalMessage.", - UnsupportedGetEncryptionPublicKey = "KeyringController - The keyring for the current address does not support the method getEncryptionPublicKey.", - UnsupportedDecryptMessage = "KeyringController - The keyring for the current address does not support the method decryptMessage.", - UnsupportedSignTypedMessage = "KeyringController - The keyring for the current address does not support the method signTypedMessage.", - UnsupportedGetAppKeyAddress = "KeyringController - The keyring for the current address does not support the method getAppKeyAddress.", - UnsupportedExportAppKeyForAddress = "KeyringController - The keyring for the current address does not support the method exportAppKeyForAddress.", - NoAccountOnKeychain = "KeyringController - The keyring for the current address does not support the method decryptMessage.", - MissingCredentials = "KeyringController - Cannot persist vault without password and encryption key", - MissingVaultData = "KeyringController - Cannot persist vault without vault information", - ExpiredCredentials = "KeyringController - Encryption key and salt provided are expired", - NoKeyringBuilder = "KeyringController - No keyringBuilder found for keyring", - DataType = "KeyringController - Incorrect data type provided" -} diff --git a/dist/constants.js b/dist/constants.js deleted file mode 100644 index 0658ade9..00000000 --- a/dist/constants.js +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.KeyringControllerError = exports.KeyringType = void 0; -var KeyringType; -(function (KeyringType) { - KeyringType["HD"] = "HD Key Tree"; - KeyringType["Simple"] = "Simple Key Pair"; -})(KeyringType = exports.KeyringType || (exports.KeyringType = {})); -var KeyringControllerError; -(function (KeyringControllerError) { - KeyringControllerError["NoKeyring"] = "KeyringController - No keyring found"; - KeyringControllerError["WrongPasswordType"] = "KeyringController - Password must be of type string."; - KeyringControllerError["NoFirstAccount"] = "KeyringController - First Account not found."; - KeyringControllerError["DuplicatedAccount"] = "KeyringController - The account you are trying to import is a duplicate"; - KeyringControllerError["VaultError"] = "KeyringController - Cannot unlock without a previous vault."; - KeyringControllerError["UnsupportedGenerateRandomMnemonic"] = "KeyringController - The current keyring does not support the method generateRandomMnemonic."; - KeyringControllerError["UnsupportedExportAccount"] = "`KeyringController - The keyring for the current address does not support the method exportAccount"; - KeyringControllerError["UnsupportedRemoveAccount"] = "`KeyringController - The keyring for the current address does not support the method removeAccount"; - KeyringControllerError["UnsupportedSignTransaction"] = "KeyringController - The keyring for the current address does not support the method signTransaction."; - KeyringControllerError["UnsupportedSignMessage"] = "KeyringController - The keyring for the current address does not support the method signMessage."; - KeyringControllerError["UnsupportedSignPersonalMessage"] = "KeyringController - The keyring for the current address does not support the method signPersonalMessage."; - KeyringControllerError["UnsupportedGetEncryptionPublicKey"] = "KeyringController - The keyring for the current address does not support the method getEncryptionPublicKey."; - KeyringControllerError["UnsupportedDecryptMessage"] = "KeyringController - The keyring for the current address does not support the method decryptMessage."; - KeyringControllerError["UnsupportedSignTypedMessage"] = "KeyringController - The keyring for the current address does not support the method signTypedMessage."; - KeyringControllerError["UnsupportedGetAppKeyAddress"] = "KeyringController - The keyring for the current address does not support the method getAppKeyAddress."; - KeyringControllerError["UnsupportedExportAppKeyForAddress"] = "KeyringController - The keyring for the current address does not support the method exportAppKeyForAddress."; - KeyringControllerError["NoAccountOnKeychain"] = "KeyringController - The keyring for the current address does not support the method decryptMessage."; - KeyringControllerError["MissingCredentials"] = "KeyringController - Cannot persist vault without password and encryption key"; - KeyringControllerError["MissingVaultData"] = "KeyringController - Cannot persist vault without vault information"; - KeyringControllerError["ExpiredCredentials"] = "KeyringController - Encryption key and salt provided are expired"; - KeyringControllerError["NoKeyringBuilder"] = "KeyringController - No keyringBuilder found for keyring"; - KeyringControllerError["DataType"] = "KeyringController - Incorrect data type provided"; -})(KeyringControllerError = exports.KeyringControllerError || (exports.KeyringControllerError = {})); -//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/constants.js.map b/dist/constants.js.map deleted file mode 100644 index 33541a79..00000000 --- a/dist/constants.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAA,IAAY,WAGX;AAHD,WAAY,WAAW;IACrB,iCAAkB,CAAA;IAClB,yCAA0B,CAAA;AAC5B,CAAC,EAHW,WAAW,GAAX,mBAAW,KAAX,mBAAW,QAGtB;AAED,IAAY,sBAuBX;AAvBD,WAAY,sBAAsB;IAChC,4EAAkD,CAAA;IAClD,oGAA0E,CAAA;IAC1E,yFAA+D,CAAA;IAC/D,uHAA6F,CAAA;IAC7F,oGAA0E,CAAA;IAC1E,2JAAiI,CAAA;IACjI,yJAA+H,CAAA;IAC/H,yJAA+H,CAAA;IAC/H,6JAAmI,CAAA;IACnI,qJAA2H,CAAA;IAC3H,qKAA2I,CAAA;IAC3I,2KAAiJ,CAAA;IACjJ,2JAAiI,CAAA;IACjI,+JAAqI,CAAA;IACrI,+JAAqI,CAAA;IACrI,2KAAiJ,CAAA;IACjJ,qJAA2H,CAAA;IAC3H,6HAAmG,CAAA;IACnG,iHAAuF,CAAA;IACvF,iHAAuF,CAAA;IACvF,sGAA4E,CAAA;IAC5E,uFAA6D,CAAA;AAC/D,CAAC,EAvBW,sBAAsB,GAAtB,8BAAsB,KAAtB,8BAAsB,QAuBjC","sourcesContent":["export enum KeyringType {\n HD = 'HD Key Tree',\n Simple = 'Simple Key Pair',\n}\n\nexport enum KeyringControllerError {\n NoKeyring = 'KeyringController - No keyring found',\n WrongPasswordType = 'KeyringController - Password must be of type string.',\n NoFirstAccount = 'KeyringController - First Account not found.',\n DuplicatedAccount = 'KeyringController - The account you are trying to import is a duplicate',\n VaultError = 'KeyringController - Cannot unlock without a previous vault.',\n UnsupportedGenerateRandomMnemonic = 'KeyringController - The current keyring does not support the method generateRandomMnemonic.',\n UnsupportedExportAccount = '`KeyringController - The keyring for the current address does not support the method exportAccount',\n UnsupportedRemoveAccount = '`KeyringController - The keyring for the current address does not support the method removeAccount',\n UnsupportedSignTransaction = 'KeyringController - The keyring for the current address does not support the method signTransaction.',\n UnsupportedSignMessage = 'KeyringController - The keyring for the current address does not support the method signMessage.',\n UnsupportedSignPersonalMessage = 'KeyringController - The keyring for the current address does not support the method signPersonalMessage.',\n UnsupportedGetEncryptionPublicKey = 'KeyringController - The keyring for the current address does not support the method getEncryptionPublicKey.',\n UnsupportedDecryptMessage = 'KeyringController - The keyring for the current address does not support the method decryptMessage.',\n UnsupportedSignTypedMessage = 'KeyringController - The keyring for the current address does not support the method signTypedMessage.',\n UnsupportedGetAppKeyAddress = 'KeyringController - The keyring for the current address does not support the method getAppKeyAddress.',\n UnsupportedExportAppKeyForAddress = 'KeyringController - The keyring for the current address does not support the method exportAppKeyForAddress.',\n NoAccountOnKeychain = 'KeyringController - The keyring for the current address does not support the method decryptMessage.',\n MissingCredentials = 'KeyringController - Cannot persist vault without password and encryption key',\n MissingVaultData = 'KeyringController - Cannot persist vault without vault information',\n ExpiredCredentials = 'KeyringController - Encryption key and salt provided are expired',\n NoKeyringBuilder = 'KeyringController - No keyringBuilder found for keyring',\n DataType = 'KeyringController - Incorrect data type provided',\n}\n"]} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts deleted file mode 100644 index 17d565c7..00000000 --- a/dist/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { KeyringController, keyringBuilderFactory } from './KeyringController'; -export { KeyringType, KeyringControllerError } from './constants'; diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index 3bdcebe9..00000000 --- a/dist/index.js +++ /dev/null @@ -1,10 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.KeyringControllerError = exports.KeyringType = exports.keyringBuilderFactory = exports.KeyringController = void 0; -var KeyringController_1 = require("./KeyringController"); -Object.defineProperty(exports, "KeyringController", { enumerable: true, get: function () { return KeyringController_1.KeyringController; } }); -Object.defineProperty(exports, "keyringBuilderFactory", { enumerable: true, get: function () { return KeyringController_1.keyringBuilderFactory; } }); -var constants_1 = require("./constants"); -Object.defineProperty(exports, "KeyringType", { enumerable: true, get: function () { return constants_1.KeyringType; } }); -Object.defineProperty(exports, "KeyringControllerError", { enumerable: true, get: function () { return constants_1.KeyringControllerError; } }); -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map deleted file mode 100644 index ca1edd62..00000000 --- a/dist/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yDAA+E;AAAtE,sHAAA,iBAAiB,OAAA;AAAE,0HAAA,qBAAqB,OAAA;AAEjD,yCAAkE;AAAzD,wGAAA,WAAW,OAAA;AAAE,mHAAA,sBAAsB,OAAA","sourcesContent":["export { KeyringController, keyringBuilderFactory } from './KeyringController';\n\nexport { KeyringType, KeyringControllerError } from './constants';\n"]} \ No newline at end of file diff --git a/dist/test/encryptor.mock.d.ts b/dist/test/encryptor.mock.d.ts deleted file mode 100644 index a0752356..00000000 --- a/dist/test/encryptor.mock.d.ts +++ /dev/null @@ -1,38 +0,0 @@ -/// -/// -/// -import { Json } from '@metamask/utils'; -declare const PASSWORD = "password123"; -declare const MOCK_ENCRYPTION_KEY: string; -declare const MOCK_HARDCODED_KEY = "key"; -declare const MOCK_HEX = "0xabcdef0123456789"; -declare const MOCK_SALT = "SALT"; -declare const mockEncryptor: { - encrypt: import("sinon").SinonStub; - encryptWithDetail: import("sinon").SinonStub; - decrypt(_password: string, _text: string): Promise; - decryptWithEncryptedKeyString(_keyStr: string): Promise; - decryptWithDetail(_password: string, _text: string): Promise<{ - vault: string | number | true | Json[] | { - [prop: string]: Json; - }; - exportedKeyString: string; - salt: string; - } | { - vault?: never; - exportedKeyString?: never; - salt?: never; - }>; - importKey(keyString: string): null; - encryptWithKey(): any; - decryptWithKey(key: string, text: string): Promise; - keyFromPassword(_password: string): Promise; - generateSalt(): string; -}; -export { mockEncryptor, PASSWORD, MOCK_HARDCODED_KEY, MOCK_HEX, MOCK_ENCRYPTION_KEY, MOCK_SALT, }; diff --git a/dist/test/encryptor.mock.js b/dist/test/encryptor.mock.js deleted file mode 100644 index f80c514a..00000000 --- a/dist/test/encryptor.mock.js +++ /dev/null @@ -1,86 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.MOCK_SALT = exports.MOCK_ENCRYPTION_KEY = exports.MOCK_HEX = exports.MOCK_HARDCODED_KEY = exports.PASSWORD = exports.mockEncryptor = void 0; -const sinon_1 = require("sinon"); -const PASSWORD = 'password123'; -exports.PASSWORD = PASSWORD; -const MOCK_ENCRYPTION_KEY = JSON.stringify({ - alg: 'A256GCM', - ext: true, - k: 'wYmxkxOOFBDP6F6VuuYFcRt_Po-tSLFHCWVolsHs4VI', - // eslint-disable-next-line @typescript-eslint/naming-convention - key_ops: ['encrypt', 'decrypt'], - kty: 'oct', -}); -exports.MOCK_ENCRYPTION_KEY = MOCK_ENCRYPTION_KEY; -const MOCK_ENCRYPTION_SALT = 'HQ5sfhsb8XAQRJtD+UqcImT7Ve4n3YMagrh05YTOsjk='; -const MOCK_ENCRYPTION_DATA = `{"data":"2fOOPRKClNrisB+tmqIcETyZvDuL2iIR1Hr1nO7XZHyMqVY1cDBetw2gY5C+cIo1qkpyv3bPp+4buUjp38VBsjbijM0F/FLOqWbcuKM9h9X0uwxsgsZ96uwcIf5I46NiMgoFlhppTTMZT0Nkocz+SnvHM0IgLsFan7JqBU++vSJvx2M1PDljZSunOsqyyL+DKmbYmM4umbouKV42dipUwrCvrQJmpiUZrSkpMJrPJk9ufDQO4CyIVo0qry3aNRdYFJ6rgSyq/k6rXMwGExCMHn8UlhNnAMuMKWPWR/ymK1bzNcNs4VU14iVjEXOZGPvD9cvqVe/VtcnIba6axNEEB4HWDOCdrDh5YNWwMlQVL7vSB2yOhPZByGhnEOloYsj2E5KEb9jFGskt7EKDEYNofr6t83G0c+B72VGYZeCvgtzXzgPwzIbhTtKkP+gdBmt2JNSYrTjLypT0q+v4C9BN1xWTxPmX6TTt0NzkI9pJxgN1VQAfSU9CyWTVpd4CBkgom2cSBsxZ2MNbdKF+qSWz3fQcmJ55hxM0EGJSt9+8eQOTuoJlBapRk4wdZKHR2jdKzPjSF2MAmyVD2kU51IKa/cVsckRFEes+m7dKyHRvlNwgT78W9tBDdZb5PSlfbZXnv8z5q1KtAj2lM2ogJ7brHBdevl4FISdTkObpwcUMcvACOOO0dj6CSYjSKr0ZJ2RLChVruZyPDxEhKGb/8Kv8trLOR3mck/et6d050/NugezycNk4nnzu5iP90gPbSzaqdZI=","iv":"qTGO1afGv3waHN9KoW34Eg==","salt":"${MOCK_ENCRYPTION_SALT}"}`; -const INVALID_PASSWORD_ERROR = 'Incorrect password.'; -const MOCK_HARDCODED_KEY = 'key'; -exports.MOCK_HARDCODED_KEY = MOCK_HARDCODED_KEY; -const MOCK_HEX = '0xabcdef0123456789'; -exports.MOCK_HEX = MOCK_HEX; -const MOCK_SALT = 'SALT'; -exports.MOCK_SALT = MOCK_SALT; -// eslint-disable-next-line no-restricted-globals -const MOCK_KEY = Buffer.alloc(32); -let cacheVal; -const mockEncryptor = { - encrypt: (0, sinon_1.stub)().callsFake(async (_password, dataObj) => { - cacheVal = dataObj; - return Promise.resolve(MOCK_HEX); - }), - encryptWithDetail: (0, sinon_1.stub)().callsFake(async (_password, dataObj) => { - cacheVal = dataObj; - return Promise.resolve({ - vault: JSON.stringify({ salt: MOCK_HEX }), - exportedKeyString: MOCK_HARDCODED_KEY, - }); - }), - async decrypt(_password, _text) { - if (_password && _password !== PASSWORD) { - throw new Error(INVALID_PASSWORD_ERROR); - } - return Promise.resolve(cacheVal !== null && cacheVal !== void 0 ? cacheVal : {}); - }, - async decryptWithEncryptedKeyString(_keyStr) { - const { vault } = await this.decryptWithDetail(_keyStr, 'mock vault'); - return vault; - }, - async decryptWithDetail(_password, _text) { - if (_password && _password !== PASSWORD) { - throw new Error(INVALID_PASSWORD_ERROR); - } - const result = cacheVal - ? { - vault: cacheVal, - exportedKeyString: MOCK_ENCRYPTION_KEY, - salt: MOCK_SALT, - } - : {}; - return Promise.resolve(result); - }, - importKey(keyString) { - if (keyString === '{}') { - throw new TypeError(`Failed to execute 'importKey' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView or JsonWebKey)'.`); - } - return null; - }, - encryptWithKey() { - const data = JSON.parse(MOCK_ENCRYPTION_DATA); - // Salt is not provided from this method - delete data.salt; - return data; - }, - async decryptWithKey(key, text) { - return this.decrypt(key, text); - }, - async keyFromPassword(_password) { - return Promise.resolve(MOCK_KEY); - }, - generateSalt() { - return 'WHADDASALT!'; - }, -}; -exports.mockEncryptor = mockEncryptor; -//# sourceMappingURL=encryptor.mock.js.map \ No newline at end of file diff --git a/dist/test/encryptor.mock.js.map b/dist/test/encryptor.mock.js.map deleted file mode 100644 index 57bfed01..00000000 --- a/dist/test/encryptor.mock.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"encryptor.mock.js","sourceRoot":"","sources":["../../src/test/encryptor.mock.ts"],"names":[],"mappings":"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","sourcesContent":["import { Json } from '@metamask/utils';\nimport { stub } from 'sinon';\n\nconst PASSWORD = 'password123';\nconst MOCK_ENCRYPTION_KEY = JSON.stringify({\n alg: 'A256GCM',\n ext: true,\n k: 'wYmxkxOOFBDP6F6VuuYFcRt_Po-tSLFHCWVolsHs4VI',\n // eslint-disable-next-line @typescript-eslint/naming-convention\n key_ops: ['encrypt', 'decrypt'],\n kty: 'oct',\n});\nconst MOCK_ENCRYPTION_SALT = 'HQ5sfhsb8XAQRJtD+UqcImT7Ve4n3YMagrh05YTOsjk=';\nconst MOCK_ENCRYPTION_DATA = `{\"data\":\"2fOOPRKClNrisB+tmqIcETyZvDuL2iIR1Hr1nO7XZHyMqVY1cDBetw2gY5C+cIo1qkpyv3bPp+4buUjp38VBsjbijM0F/FLOqWbcuKM9h9X0uwxsgsZ96uwcIf5I46NiMgoFlhppTTMZT0Nkocz+SnvHM0IgLsFan7JqBU++vSJvx2M1PDljZSunOsqyyL+DKmbYmM4umbouKV42dipUwrCvrQJmpiUZrSkpMJrPJk9ufDQO4CyIVo0qry3aNRdYFJ6rgSyq/k6rXMwGExCMHn8UlhNnAMuMKWPWR/ymK1bzNcNs4VU14iVjEXOZGPvD9cvqVe/VtcnIba6axNEEB4HWDOCdrDh5YNWwMlQVL7vSB2yOhPZByGhnEOloYsj2E5KEb9jFGskt7EKDEYNofr6t83G0c+B72VGYZeCvgtzXzgPwzIbhTtKkP+gdBmt2JNSYrTjLypT0q+v4C9BN1xWTxPmX6TTt0NzkI9pJxgN1VQAfSU9CyWTVpd4CBkgom2cSBsxZ2MNbdKF+qSWz3fQcmJ55hxM0EGJSt9+8eQOTuoJlBapRk4wdZKHR2jdKzPjSF2MAmyVD2kU51IKa/cVsckRFEes+m7dKyHRvlNwgT78W9tBDdZb5PSlfbZXnv8z5q1KtAj2lM2ogJ7brHBdevl4FISdTkObpwcUMcvACOOO0dj6CSYjSKr0ZJ2RLChVruZyPDxEhKGb/8Kv8trLOR3mck/et6d050/NugezycNk4nnzu5iP90gPbSzaqdZI=\",\"iv\":\"qTGO1afGv3waHN9KoW34Eg==\",\"salt\":\"${MOCK_ENCRYPTION_SALT}\"}`;\n\nconst INVALID_PASSWORD_ERROR = 'Incorrect password.';\n\nconst MOCK_HARDCODED_KEY = 'key';\nconst MOCK_HEX = '0xabcdef0123456789';\nconst MOCK_SALT = 'SALT';\n// eslint-disable-next-line no-restricted-globals\nconst MOCK_KEY = Buffer.alloc(32);\nlet cacheVal: Json;\n\nconst mockEncryptor = {\n encrypt: stub().callsFake(async (_password, dataObj) => {\n cacheVal = dataObj;\n\n return Promise.resolve(MOCK_HEX);\n }),\n\n encryptWithDetail: stub().callsFake(async (_password, dataObj) => {\n cacheVal = dataObj;\n\n return Promise.resolve({\n vault: JSON.stringify({ salt: MOCK_HEX }),\n exportedKeyString: MOCK_HARDCODED_KEY,\n });\n }),\n\n async decrypt(_password: string, _text: string) {\n if (_password && _password !== PASSWORD) {\n throw new Error(INVALID_PASSWORD_ERROR);\n }\n\n return Promise.resolve(cacheVal ?? {});\n },\n\n async decryptWithEncryptedKeyString(_keyStr: string) {\n const { vault } = await this.decryptWithDetail(_keyStr, 'mock vault');\n return vault;\n },\n\n async decryptWithDetail(_password: string, _text: string) {\n if (_password && _password !== PASSWORD) {\n throw new Error(INVALID_PASSWORD_ERROR);\n }\n\n const result = cacheVal\n ? {\n vault: cacheVal,\n exportedKeyString: MOCK_ENCRYPTION_KEY,\n salt: MOCK_SALT,\n }\n : {};\n return Promise.resolve(result);\n },\n\n importKey(keyString: string) {\n if (keyString === '{}') {\n throw new TypeError(\n `Failed to execute 'importKey' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView or JsonWebKey)'.`,\n );\n }\n return null;\n },\n\n encryptWithKey() {\n const data = JSON.parse(MOCK_ENCRYPTION_DATA);\n // Salt is not provided from this method\n delete data.salt;\n return data;\n },\n\n async decryptWithKey(key: string, text: string) {\n return this.decrypt(key, text);\n },\n\n async keyFromPassword(_password: string) {\n return Promise.resolve(MOCK_KEY);\n },\n\n generateSalt() {\n return 'WHADDASALT!';\n },\n};\n\nexport {\n mockEncryptor,\n PASSWORD,\n MOCK_HARDCODED_KEY,\n MOCK_HEX,\n MOCK_ENCRYPTION_KEY,\n MOCK_SALT,\n};\n"]} \ No newline at end of file diff --git a/dist/test/index.d.ts b/dist/test/index.d.ts deleted file mode 100644 index 455125d3..00000000 --- a/dist/test/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { mockEncryptor, PASSWORD, MOCK_HARDCODED_KEY, MOCK_HEX, MOCK_ENCRYPTION_KEY, MOCK_SALT } from './encryptor.mock'; -import KeyringMockWithInit from './keyring.mock'; -export { mockEncryptor, KeyringMockWithInit, PASSWORD, MOCK_HARDCODED_KEY, MOCK_HEX, MOCK_ENCRYPTION_KEY, MOCK_SALT, }; diff --git a/dist/test/index.js b/dist/test/index.js deleted file mode 100644 index 1f5d6ab9..00000000 --- a/dist/test/index.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.MOCK_SALT = exports.MOCK_ENCRYPTION_KEY = exports.MOCK_HEX = exports.MOCK_HARDCODED_KEY = exports.PASSWORD = exports.KeyringMockWithInit = exports.mockEncryptor = void 0; -const encryptor_mock_1 = require("./encryptor.mock"); -Object.defineProperty(exports, "mockEncryptor", { enumerable: true, get: function () { return encryptor_mock_1.mockEncryptor; } }); -Object.defineProperty(exports, "PASSWORD", { enumerable: true, get: function () { return encryptor_mock_1.PASSWORD; } }); -Object.defineProperty(exports, "MOCK_HARDCODED_KEY", { enumerable: true, get: function () { return encryptor_mock_1.MOCK_HARDCODED_KEY; } }); -Object.defineProperty(exports, "MOCK_HEX", { enumerable: true, get: function () { return encryptor_mock_1.MOCK_HEX; } }); -Object.defineProperty(exports, "MOCK_ENCRYPTION_KEY", { enumerable: true, get: function () { return encryptor_mock_1.MOCK_ENCRYPTION_KEY; } }); -Object.defineProperty(exports, "MOCK_SALT", { enumerable: true, get: function () { return encryptor_mock_1.MOCK_SALT; } }); -const keyring_mock_1 = __importDefault(require("./keyring.mock")); -exports.KeyringMockWithInit = keyring_mock_1.default; -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/test/index.js.map b/dist/test/index.js.map deleted file mode 100644 index de00ba05..00000000 --- a/dist/test/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":";;;;;;AAAA,qDAO0B;AAIxB,8FAVA,8BAAa,OAUA;AAEb,yFAXA,yBAAQ,OAWA;AACR,mGAXA,mCAAkB,OAWA;AAClB,yFAXA,yBAAQ,OAWA;AACR,oGAXA,oCAAmB,OAWA;AACnB,0FAXA,0BAAS,OAWA;AATX,kEAAiD;AAI/C,8BAJK,sBAAmB,CAIL","sourcesContent":["import {\n mockEncryptor,\n PASSWORD,\n MOCK_HARDCODED_KEY,\n MOCK_HEX,\n MOCK_ENCRYPTION_KEY,\n MOCK_SALT,\n} from './encryptor.mock';\nimport KeyringMockWithInit from './keyring.mock';\n\nexport {\n mockEncryptor,\n KeyringMockWithInit,\n PASSWORD,\n MOCK_HARDCODED_KEY,\n MOCK_HEX,\n MOCK_ENCRYPTION_KEY,\n MOCK_SALT,\n};\n"]} \ No newline at end of file diff --git a/dist/test/keyring.mock.d.ts b/dist/test/keyring.mock.d.ts deleted file mode 100644 index b48e3159..00000000 --- a/dist/test/keyring.mock.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Keyring, Json, Hex } from '@metamask/utils'; -declare class KeyringMockWithInit implements Keyring { - #private; - static type: string; - type: string; - constructor(options?: Record | undefined); - init(): Promise; - addAccounts(_: number): Promise; - getAccounts(): Promise<`0x${string}`[]>; - serialize(): Promise<{}>; - deserialize(_: any): Promise; -} -export default KeyringMockWithInit; diff --git a/dist/test/keyring.mock.js b/dist/test/keyring.mock.js deleted file mode 100644 index ef4454ef..00000000 --- a/dist/test/keyring.mock.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { - if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); - 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"); - return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); -}; -var _KeyringMockWithInit_accounts; -Object.defineProperty(exports, "__esModule", { value: true }); -const TYPE = 'Keyring Mock With Init'; -class KeyringMockWithInit { - constructor(options = {}) { - this.type = TYPE; - _KeyringMockWithInit_accounts.set(this, []); - // eslint-disable-next-line @typescript-eslint/no-floating-promises, @typescript-eslint/promise-function-async - this.deserialize(options); - } - async init() { - return Promise.resolve(); - } - async addAccounts(_) { - return Promise.resolve(__classPrivateFieldGet(this, _KeyringMockWithInit_accounts, "f")); - } - async getAccounts() { - return Promise.resolve(__classPrivateFieldGet(this, _KeyringMockWithInit_accounts, "f")); - } - async serialize() { - return Promise.resolve({}); - } - async deserialize(_) { - return Promise.resolve(); - } -} -_KeyringMockWithInit_accounts = new WeakMap(); -KeyringMockWithInit.type = TYPE; -exports.default = KeyringMockWithInit; -//# sourceMappingURL=keyring.mock.js.map \ No newline at end of file diff --git a/dist/test/keyring.mock.js.map b/dist/test/keyring.mock.js.map deleted file mode 100644 index 6906519f..00000000 --- a/dist/test/keyring.mock.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"keyring.mock.js","sourceRoot":"","sources":["../../src/test/keyring.mock.ts"],"names":[],"mappings":";;;;;;;;AAEA,MAAM,IAAI,GAAG,wBAAwB,CAAC;AAEtC,MAAM,mBAAmB;IAOvB,YAAY,UAA+C,EAAE;QAJtD,SAAI,GAAG,IAAI,CAAC;QAEnB,wCAAmB,EAAE,EAAC;QAGpB,8GAA8G;QAC9G,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,CAAS;QACzB,OAAO,OAAO,CAAC,OAAO,CAAC,uBAAA,IAAI,qCAAU,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,OAAO,CAAC,OAAO,CAAC,uBAAA,IAAI,qCAAU,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,CAAM;QACtB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;;;AA7BM,wBAAI,GAAG,IAAI,AAAP,CAAQ;AAgCrB,kBAAe,mBAAmB,CAAC","sourcesContent":["import type { Keyring, Json, Hex } from '@metamask/utils';\n\nconst TYPE = 'Keyring Mock With Init';\n\nclass KeyringMockWithInit implements Keyring {\n static type = TYPE;\n\n public type = TYPE;\n\n #accounts: Hex[] = [];\n\n constructor(options: Record | undefined = {}) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, @typescript-eslint/promise-function-async\n this.deserialize(options);\n }\n\n async init() {\n return Promise.resolve();\n }\n\n async addAccounts(_: number): Promise {\n return Promise.resolve(this.#accounts);\n }\n\n async getAccounts() {\n return Promise.resolve(this.#accounts);\n }\n\n async serialize() {\n return Promise.resolve({});\n }\n\n async deserialize(_: any) {\n return Promise.resolve();\n }\n}\n\nexport default KeyringMockWithInit;\n"]} \ No newline at end of file diff --git a/dist/types.d.ts b/dist/types.d.ts deleted file mode 100644 index 5b949990..00000000 --- a/dist/types.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { Json, Keyring } from '@metamask/utils'; -import ObservableStore from 'obs-store'; -export type KeyringControllerArgs = { - keyringBuilders: { - (): Keyring; - type: string; - } | ConcatArray<{ - (): Keyring; - type: string; - }>; - cacheEncryptionKey: boolean; - initState?: KeyringControllerState; - encryptor?: any; -}; -export type KeyringControllerState = { - keyringBuilders?: { - (): Keyring; - type: string; - }[]; - store?: typeof ObservableStore; - memStore?: typeof ObservableStore; - keyrings?: Keyring[]; - isUnlocked?: boolean; - encryptionKey?: string; - encryptionSalt?: string; - password?: string; -}; -export type SerializedKeyring = { - type: string; - data: Json; -}; diff --git a/dist/types.js b/dist/types.js deleted file mode 100644 index 11e638d1..00000000 --- a/dist/types.js +++ /dev/null @@ -1,3 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/dist/types.js.map b/dist/types.js.map deleted file mode 100644 index 50c203e8..00000000 --- a/dist/types.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Json, Keyring } from '@metamask/utils';\nimport ObservableStore from 'obs-store';\n\nexport type KeyringControllerArgs = {\n keyringBuilders:\n | { (): Keyring; type: string }\n | ConcatArray<{ (): Keyring; type: string }>;\n\n cacheEncryptionKey: boolean;\n initState?: KeyringControllerState;\n encryptor?: any;\n};\n\nexport type KeyringControllerState = {\n keyringBuilders?: { (): Keyring; type: string }[];\n\n store?: typeof ObservableStore;\n\n memStore?: typeof ObservableStore;\n\n keyrings?: Keyring[];\n\n isUnlocked?: boolean;\n\n encryptionKey?: string;\n\n encryptionSalt?: string;\n\n password?: string;\n};\n\nexport type SerializedKeyring = {\n type: string;\n data: Json;\n};\n"]} \ No newline at end of file From 6a1ed26fe203cbfc09243ff37f73d18c28859d7a Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Fri, 12 May 2023 19:17:54 -0400 Subject: [PATCH 08/10] Lint --- src/KeyringController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KeyringController.ts b/src/KeyringController.ts index 15a26db3..a8f767c0 100644 --- a/src/KeyringController.ts +++ b/src/KeyringController.ts @@ -3,7 +3,7 @@ import * as encryptorUtils from '@metamask/browser-passworder'; import HDKeyring from '@metamask/eth-hd-keyring'; import { normalize as normalizeToHex } from '@metamask/eth-sig-util'; import SimpleKeyring from '@metamask/eth-simple-keyring'; -import { remove0x, isValidJson } from '@metamask/utils'; +import { remove0x } from '@metamask/utils'; import type { Hex, Json, From 410814dbb17e674af9c1ddba2e9a493221fb3815 Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Fri, 19 May 2023 17:38:03 -0400 Subject: [PATCH 09/10] Update coverage --- jest.config.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jest.config.js b/jest.config.js index 701b3064..badd36db 100644 --- a/jest.config.js +++ b/jest.config.js @@ -41,10 +41,10 @@ module.exports = { // An object that configures minimum threshold enforcement for coverage results coverageThreshold: { global: { - branches: 68.67, - functions: 92.59, - lines: 90.2, - statements: 90.42, + branches: 69.51, + functions: 92.72, + lines: 90.47, + statements: 90.69, }, }, preset: 'ts-jest', From a844bfb0ed7a50daf14a6b9c072fa26fe6bd3d91 Mon Sep 17 00:00:00 2001 From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> Date: Wed, 24 May 2023 15:22:19 -0400 Subject: [PATCH 10/10] Remove error and update coverage --- jest.config.js | 6 +++--- src/KeyringController.ts | 6 +----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/jest.config.js b/jest.config.js index badd36db..322de793 100644 --- a/jest.config.js +++ b/jest.config.js @@ -41,10 +41,10 @@ module.exports = { // An object that configures minimum threshold enforcement for coverage results coverageThreshold: { global: { - branches: 69.51, + branches: 70.37, functions: 92.72, - lines: 90.47, - statements: 90.69, + lines: 90.72, + statements: 90.93, }, }, preset: 'ts-jest', diff --git a/src/KeyringController.ts b/src/KeyringController.ts index 0de8a462..a70017f8 100644 --- a/src/KeyringController.ts +++ b/src/KeyringController.ts @@ -756,11 +756,7 @@ class KeyringController extends EventEmitter { * @returns Keyrings matching the specified type. */ getKeyringsByType(type: string): Keyring[] { - const keyrings = this.keyrings.filter((keyring) => keyring.type === type); - if (!keyrings.length) { - throw new Error(KeyringControllerError.NoKeyring); - } - return keyrings; + return this.keyrings.filter((keyring) => keyring.type === type); } /**