@metamask-previews/money-account-controller 2.0.0-preview-ff2ab0583 → 2.0.0-preview-a2f6118d2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,10 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ### Changed
11
-
12
- - Bump `@metamask/keyring-controller` from `^28.0.0` to `^28.1.0` ([#10418](https://github.com/MetaMask/core/pull/10418))
13
-
14
10
  ## [2.0.0]
15
11
 
16
12
  ### Changed
@@ -1 +1 @@
1
- {"version":3,"file":"MoneyAccountController.js","sourceRoot":"","sources":["../src/MoneyAccountController.ts"],"names":[],"mappings":"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","sourcesContent":["import { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n MoneyKeyring,\n MoneyKeyringSerializedState,\n} from '@metamask/eth-money-keyring';\nimport { MONEY_DERIVATION_PATH } from '@metamask/eth-money-keyring';\nimport { EthAccountType, EthMethod, EthScope } from '@metamask/keyring-api';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport type {\n KeyringControllerAddNewKeyringAction,\n KeyringControllerGetStateAction,\n KeyringControllerWithKeyringAction,\n KeyringMetadata,\n KeyringSelector,\n} from '@metamask/keyring-controller';\nimport {\n isKeyringNotFoundError,\n KeyringTypes,\n} from '@metamask/keyring-controller';\nimport { EthKeyring } from '@metamask/keyring-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport { Mutex } from 'async-mutex';\n\nimport { projectLogger as log } from './logger.js';\nimport type { MoneyAccountControllerMethodActions } from './MoneyAccountController-method-action-types.js';\nimport type { MoneyAccount } from './types.js';\nimport { isMoneyKeyring } from './utils.js';\n\nexport const controllerName = 'MoneyAccountController';\n\nexport type MoneyAccountControllerState = {\n moneyAccounts: {\n [id: MoneyAccount['id']]: MoneyAccount;\n };\n};\n\nconst moneyAccountControllerMetadata = {\n moneyAccounts: {\n includeInDebugSnapshot: false,\n includeInStateLogs: true,\n persist: true,\n usedInUi: true,\n },\n} satisfies StateMetadata<MoneyAccountControllerState>;\n\nexport function getDefaultMoneyAccountControllerState(): MoneyAccountControllerState {\n return {\n moneyAccounts: {},\n };\n}\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'createMoneyAccount',\n 'getMoneyAccount',\n 'clearState',\n 'init',\n] as const;\n\nexport type MoneyAccountControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n MoneyAccountControllerState\n>;\n\nexport type MoneyAccountControllerActions =\n | MoneyAccountControllerGetStateAction\n | MoneyAccountControllerMethodActions;\n\ntype AllowedActions =\n | KeyringControllerGetStateAction\n | KeyringControllerAddNewKeyringAction\n | KeyringControllerWithKeyringAction;\n\nexport type MoneyAccountControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n MoneyAccountControllerState\n>;\n\nexport type MoneyAccountControllerEvents =\n MoneyAccountControllerStateChangeEvent;\n\ntype AllowedEvents = never;\n\nexport type MoneyAccountControllerMessenger = Messenger<\n typeof controllerName,\n MoneyAccountControllerActions | AllowedActions,\n MoneyAccountControllerEvents | AllowedEvents\n>;\n\n/**\n * Controller for managing money accounts.\n */\nexport class MoneyAccountController extends BaseController<\n typeof controllerName,\n MoneyAccountControllerState,\n MoneyAccountControllerMessenger\n> {\n readonly #lock: Mutex;\n\n /**\n * Constructor for the MoneyAccountController.\n *\n * @param options - The options for constructing the controller.\n * @param options.messenger - The messenger to use for inter-controller communication.\n * @param options.state - The initial state of the controller. If not provided, the default state will be used.\n */\n constructor({\n messenger,\n state,\n }: {\n messenger: MoneyAccountControllerMessenger;\n state?: Partial<MoneyAccountControllerState>;\n }) {\n super({\n messenger,\n metadata: moneyAccountControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultMoneyAccountControllerState(),\n ...state,\n },\n });\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.#lock = new Mutex();\n }\n\n /**\n * Initializes the controller by creating a money account for the primary\n * entropy source if one does not already exist.\n */\n async init(): Promise<void> {\n this.#assertIsUnlocked();\n\n const primaryEntropySource = this.#getPrimaryEntropySource();\n if (primaryEntropySource) {\n const { id, address } =\n await this.createMoneyAccount(primaryEntropySource);\n log(\n `Money keyring (entropy:${primaryEntropySource} - primary) account is: ${address} (${id})`,\n );\n } else {\n const message =\n 'No primary HD keyring found, skipping default Money account creation!';\n\n console.warn(message);\n log(`WARNING -- ${message}`);\n }\n }\n\n /**\n * Creates a money account for the given entropy source. If an account\n * already exists for that entropy source, it is returned as-is (idempotent).\n *\n * @param entropySource - The entropy source ID to create the money account for.\n * @returns The money account.\n */\n async createMoneyAccount(\n entropySource: EntropySourceId,\n ): Promise<MoneyAccount> {\n this.#assertIsUnlocked();\n\n // Idempotent: return existing account if already in state.\n const existingAccount = this.getMoneyAccount({ entropySource });\n if (existingAccount) {\n return existingAccount;\n }\n\n const address = await this.#withKeyring(entropySource, async (keyring) => {\n // We're adding this logic to be defensive against the possibility of a money keyring\n // existing without any accounts, which shouldn't normally happen but we want to be\n // sure we can handle it if it does.\n // If there are no accounts, we'll add one and then get the address.\n const accounts = await keyring.getAccounts();\n if (accounts.length > 0) {\n const [moneyAddress] = accounts;\n return moneyAddress;\n }\n\n log(\n `Money keyring (entropy:${entropySource}) has no accounts, creating one...`,\n );\n const [moneyAddress] = await keyring.addAccounts(1);\n return moneyAddress;\n });\n\n const account: MoneyAccount = {\n // This is an EVM account, so let's re-use the deterministic ID generation logic of\n // EVM accounts.\n id: getUUIDFromAddressOfNormalAccount(address),\n type: EthAccountType.Eoa,\n address,\n scopes: [EthScope.Eoa],\n options: {\n entropy: {\n type: 'mnemonic',\n id: entropySource,\n groupIndex: 0,\n derivationPath: MONEY_DERIVATION_PATH,\n },\n exportable: false,\n },\n methods: [\n EthMethod.PersonalSign,\n EthMethod.SignTypedDataV1,\n EthMethod.SignTypedDataV3,\n EthMethod.SignTypedDataV4,\n // TODO: Update this once the `keyring-api` package supports `SignEip7702Authorization` method.\n ],\n };\n\n // Store the account in state.\n this.update((state) => {\n state.moneyAccounts[account.id] = account;\n });\n\n log(\n `Money keyring (entropy:${account.options.entropy.id}) account created: ${account.address} (${account.id})`,\n );\n return account;\n }\n\n /**\n * Gets a money account by its associated entropy source ID. If no ID is\n * provided, the primary entropy source will be used.\n *\n * @param selector - Selector options for getting the money account.\n * @param selector.entropySource - The entropy source ID to get the money account for. If not provided, the primary entropy source will be used.\n * @returns The money account, or `undefined` if no account exists for the given entropy source.\n */\n getMoneyAccount(\n selector: { entropySource?: EntropySourceId } = {},\n ): MoneyAccount | undefined {\n const entropySource =\n selector.entropySource ?? this.#getPrimaryEntropySource();\n if (entropySource === undefined) {\n return undefined;\n }\n\n // We should never have more than one money account per entropy source, but if we\n // do, just return the first one we find.\n return Object.values(this.state.moneyAccounts).find(\n (account) => account.options.entropy.id === entropySource,\n );\n }\n\n /**\n * Resets the controller state to its default, removing all money accounts.\n *\n * Intended for use during a full app reset (e.g. when the user wipes all\n * wallet data). Does not interact with the keyring — the caller is\n * responsible for ensuring the associated keyring state is also cleared.\n */\n clearState(): void {\n this.update((state) => {\n state.moneyAccounts = {};\n });\n }\n\n /**\n * Calls `KeyringController:withKeyring` for the `MoneyKeyring` associated with the\n * given entropy source, creating one first if it does not yet exist.\n *\n * @param entropySource - The entropy source ID identifying the target keyring.\n * @param operation - Callback invoked with the resolved `MoneyKeyring`.\n * @returns The value returned by `operation`.\n */\n async #withKeyring<Result>(\n entropySource: EntropySourceId,\n operation: (keyring: MoneyKeyring) => Promise<Result>,\n ): Promise<Result> {\n // Filter to find a specific `MoneyKeyring` for the given entropy source.\n const isMoneyKeyringForEntropySource = (\n keyring: EthKeyring,\n ): keyring is MoneyKeyring =>\n isMoneyKeyring(keyring) && keyring.entropySource === entropySource;\n\n // We cannot use proper generic-type inference using the messenger\n // here, so we have to use a type casts for `keyring` and the return type.\n const withKeyring = async (\n selector: KeyringSelector<MoneyKeyring>,\n callback: (keyring: MoneyKeyring) => Promise<Result>,\n ): Promise<Result> =>\n this.messenger.call(\n 'KeyringController:withKeyring',\n selector,\n async ({ keyring }) => callback(keyring as MoneyKeyring),\n ) as Promise<Result>;\n\n // We have an extra lock here to avoid a race-condition where 2 calls to\n // `#withKeyring` for the same entropy source happen at the same time, and\n // both don't find an existing keyring, so they both try to create a new\n // one, which creates multiple keyrings for the same entropy source.\n // NOTE: We cannot use `createIfMissing` here either, since it's only supported\n // for selectors by type (and we want to deprecate this option).\n // TODO: Move this new pattern in the `KeyringController`.\n return await this.#lock.runExclusive(async () => {\n try {\n return await withKeyring(\n {\n filter: isMoneyKeyringForEntropySource,\n },\n operation,\n );\n } catch (error) {\n // Forward any unexpected errors, but if the error is that\n // the keyring wasn't found, we'll create it below.\n if (!isKeyringNotFoundError(error)) {\n throw error;\n }\n\n // Create the keyring so we can use `withKeyring` to operate on it in the\n // retry below.\n log(\n `Money keyring (entropy:${entropySource}) not found, creating one...`,\n );\n const { id } = await this.#createMoneyKeyring(entropySource);\n\n // Use the ID directly on the retry (we just created this keyring so we\n // know exactly which one to target).\n return await withKeyring({ id }, operation);\n }\n });\n }\n\n /**\n * Adds a new money keyring for the given entropy source and returns its metadata.\n *\n * NOTE: This function won't check if a money keyring for the given entropy source already\n * exists!\n *\n * @param entropySource - The entropy source ID to create the money keyring for.\n * @returns The metadata of the newly created money keyring.\n */\n #createMoneyKeyring(\n entropySource: EntropySourceId,\n ): Promise<KeyringMetadata> {\n return this.messenger.call(\n 'KeyringController:addNewKeyring',\n KeyringTypes.money,\n {\n entropySource,\n },\n );\n }\n\n /**\n * Gets the primary entropy source ID.\n *\n * @returns The primary entropy source ID, or `undefined` if no HD keyring exists.\n */\n #getPrimaryEntropySource(): EntropySourceId | undefined {\n const { keyrings } = this.messenger.call('KeyringController:getState');\n const primaryHdKeyring = keyrings.find(\n (keyring) => keyring.type === KeyringTypes.hd,\n );\n return primaryHdKeyring?.metadata.id;\n }\n\n /**\n * Throws if the keyring is currently locked.\n */\n #assertIsUnlocked(): void {\n const { isUnlocked } = this.messenger.call('KeyringController:getState');\n if (!isUnlocked) {\n throw new Error(\n 'Cannot create a money account while the keyring is locked',\n );\n }\n }\n}\n"]}
1
+ {"version":3,"file":"MoneyAccountController.js","sourceRoot":"","sources":["../src/MoneyAccountController.ts"],"names":[],"mappings":"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","sourcesContent":["import { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n MoneyKeyring,\n MoneyKeyringSerializedState,\n} from '@metamask/eth-money-keyring';\nimport { MONEY_DERIVATION_PATH } from '@metamask/eth-money-keyring';\nimport { EthAccountType, EthMethod, EthScope } from '@metamask/keyring-api';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport type {\n KeyringControllerAddNewKeyringAction,\n KeyringControllerGetStateAction,\n KeyringControllerWithKeyringAction,\n KeyringMetadata,\n KeyringSelector,\n} from '@metamask/keyring-controller';\nimport {\n isKeyringNotFoundError,\n KeyringTypes,\n} from '@metamask/keyring-controller';\nimport { EthKeyring } from '@metamask/keyring-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport { Mutex } from 'async-mutex';\n\nimport { projectLogger as log } from './logger.js';\nimport type { MoneyAccountControllerMethodActions } from './MoneyAccountController-method-action-types.js';\nimport type { MoneyAccount } from './types.js';\nimport { isMoneyKeyring } from './utils.js';\n\nexport const controllerName = 'MoneyAccountController';\n\nexport type MoneyAccountControllerState = {\n moneyAccounts: {\n [id: MoneyAccount['id']]: MoneyAccount;\n };\n};\n\nconst moneyAccountControllerMetadata = {\n moneyAccounts: {\n includeInDebugSnapshot: false,\n includeInStateLogs: true,\n persist: true,\n usedInUi: true,\n },\n} satisfies StateMetadata<MoneyAccountControllerState>;\n\nexport function getDefaultMoneyAccountControllerState(): MoneyAccountControllerState {\n return {\n moneyAccounts: {},\n };\n}\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'createMoneyAccount',\n 'getMoneyAccount',\n 'clearState',\n 'init',\n] as const;\n\nexport type MoneyAccountControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n MoneyAccountControllerState\n>;\n\nexport type MoneyAccountControllerActions =\n | MoneyAccountControllerGetStateAction\n | MoneyAccountControllerMethodActions;\n\ntype AllowedActions =\n | KeyringControllerGetStateAction\n | KeyringControllerAddNewKeyringAction\n | KeyringControllerWithKeyringAction;\n\nexport type MoneyAccountControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n MoneyAccountControllerState\n>;\n\nexport type MoneyAccountControllerEvents =\n MoneyAccountControllerStateChangeEvent;\n\ntype AllowedEvents = never;\n\nexport type MoneyAccountControllerMessenger = Messenger<\n typeof controllerName,\n MoneyAccountControllerActions | AllowedActions,\n MoneyAccountControllerEvents | AllowedEvents\n>;\n\n/**\n * Controller for managing money accounts.\n */\nexport class MoneyAccountController extends BaseController<\n typeof controllerName,\n MoneyAccountControllerState,\n MoneyAccountControllerMessenger\n> {\n readonly #lock: Mutex;\n\n /**\n * Constructor for the MoneyAccountController.\n *\n * @param options - The options for constructing the controller.\n * @param options.messenger - The messenger to use for inter-controller communication.\n * @param options.state - The initial state of the controller. If not provided, the default state will be used.\n */\n constructor({\n messenger,\n state,\n }: {\n messenger: MoneyAccountControllerMessenger;\n state?: Partial<MoneyAccountControllerState>;\n }) {\n super({\n messenger,\n metadata: moneyAccountControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultMoneyAccountControllerState(),\n ...state,\n },\n });\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.#lock = new Mutex();\n }\n\n /**\n * Initializes the controller by creating a money account for the primary\n * entropy source if one does not already exist.\n */\n async init(): Promise<void> {\n this.#assertIsUnlocked();\n\n const primaryEntropySource = this.#getPrimaryEntropySource();\n if (primaryEntropySource) {\n const { id, address } =\n await this.createMoneyAccount(primaryEntropySource);\n log(\n `Money keyring (entropy:${primaryEntropySource} - primary) account is: ${address} (${id})`,\n );\n } else {\n const message =\n 'No primary HD keyring found, skipping default Money account creation!';\n\n console.warn(message);\n log(`WARNING -- ${message}`);\n }\n }\n\n /**\n * Creates a money account for the given entropy source. If an account\n * already exists for that entropy source, it is returned as-is (idempotent).\n *\n * @param entropySource - The entropy source ID to create the money account for.\n * @returns The money account.\n */\n async createMoneyAccount(\n entropySource: EntropySourceId,\n ): Promise<MoneyAccount> {\n this.#assertIsUnlocked();\n\n // Idempotent: return existing account if already in state.\n const existingAccount = this.getMoneyAccount({ entropySource });\n if (existingAccount) {\n return existingAccount;\n }\n\n const address = await this.#withKeyring(entropySource, async (keyring) => {\n // We're adding this logic to be defensive against the possibility of a money keyring\n // existing without any accounts, which shouldn't normally happen but we want to be\n // sure we can handle it if it does.\n // If there are no accounts, we'll add one and then get the address.\n const accounts = await keyring.getAccounts();\n if (accounts.length > 0) {\n const [moneyAddress] = accounts;\n return moneyAddress;\n }\n\n log(\n `Money keyring (entropy:${entropySource}) has no accounts, creating one...`,\n );\n const [moneyAddress] = await keyring.addAccounts(1);\n return moneyAddress;\n });\n\n const account: MoneyAccount = {\n // This is an EVM account, so let's re-use the deterministic ID generation logic of\n // EVM accounts.\n id: getUUIDFromAddressOfNormalAccount(address),\n type: EthAccountType.Eoa,\n address,\n scopes: [EthScope.Eoa],\n options: {\n entropy: {\n type: 'mnemonic',\n id: entropySource,\n groupIndex: 0,\n derivationPath: MONEY_DERIVATION_PATH,\n },\n exportable: false,\n },\n methods: [\n EthMethod.PersonalSign,\n EthMethod.SignTypedDataV1,\n EthMethod.SignTypedDataV3,\n EthMethod.SignTypedDataV4,\n // TODO: Update this once the `keyring-api` package supports `SignEip7702Authorization` method.\n ],\n };\n\n // Store the account in state.\n this.update((state) => {\n state.moneyAccounts[account.id] = account;\n });\n\n log(\n `Money keyring (entropy:${account.options.entropy.id}) account created: ${account.address} (${account.id})`,\n );\n return account;\n }\n\n /**\n * Gets a money account by its associated entropy source ID. If no ID is\n * provided, the primary entropy source will be used.\n *\n * @param selector - Selector options for getting the money account.\n * @param selector.entropySource - The entropy source ID to get the money account for. If not provided, the primary entropy source will be used.\n * @returns The money account, or `undefined` if no account exists for the given entropy source.\n */\n getMoneyAccount(\n selector: { entropySource?: EntropySourceId } = {},\n ): MoneyAccount | undefined {\n const entropySource =\n selector.entropySource ?? this.#getPrimaryEntropySource();\n if (entropySource === undefined) {\n return undefined;\n }\n\n // We should never have more than one money account per entropy source, but if we\n // do, just return the first one we find.\n return Object.values(this.state.moneyAccounts).find(\n (account) => account.options.entropy.id === entropySource,\n );\n }\n\n /**\n * Resets the controller state to its default, removing all money accounts.\n *\n * Intended for use during a full app reset (e.g. when the user wipes all\n * wallet data). Does not interact with the keyring — the caller is\n * responsible for ensuring the associated keyring state is also cleared.\n */\n clearState(): void {\n this.update((state) => {\n state.moneyAccounts = {};\n });\n }\n\n /**\n * Calls `KeyringController:withKeyring` for the `MoneyKeyring` associated with the\n * given entropy source, creating one first if it does not yet exist.\n *\n * @param entropySource - The entropy source ID identifying the target keyring.\n * @param operation - Callback invoked with the resolved `MoneyKeyring`.\n * @returns The value returned by `operation`.\n */\n async #withKeyring<Result>(\n entropySource: EntropySourceId,\n operation: (keyring: MoneyKeyring) => Promise<Result>,\n ): Promise<Result> {\n // Filter to find a specific `MoneyKeyring` for the given entropy source.\n const isMoneyKeyringForEntropySource = (\n keyring: EthKeyring,\n ): keyring is MoneyKeyring =>\n isMoneyKeyring(keyring) && keyring.entropySource === entropySource;\n\n // We cannot use proper generic-type inference using the messenger\n // here, so we have to use a type casts for `keyring` and the return type.\n const withKeyring = async (\n selector: KeyringSelector<MoneyKeyring>,\n callback: (keyring: MoneyKeyring) => Promise<Result>,\n ): Promise<Result> =>\n this.messenger.call(\n 'KeyringController:withKeyring',\n selector,\n async ({ keyring }) => callback(keyring as MoneyKeyring),\n ) as Promise<Result>;\n\n // We have an extra lock here to avoid a race-condition where 2 calls to\n // `#withKeyring` for the same entropy source happen at the same time, and\n // both don't find an existing keyring, so they both try to create a new\n // one, which creates multiple keyrings for the same entropy source.\n // NOTE: We cannot use `createIfMissing` here either, since it's only supported\n // for selectors by type (and we want to deprecate this option).\n // TODO: Move this new pattern in the `KeyringController`.\n return await this.#lock.runExclusive(async () => {\n try {\n return await withKeyring(\n {\n filter: isMoneyKeyringForEntropySource,\n },\n operation,\n );\n } catch (error) {\n // Forward any unexpected errors, but if the error is that\n // the keyring wasn't found, we'll create it below.\n if (!isKeyringNotFoundError(error)) {\n throw error;\n }\n\n // Create the keyring so we can use `withKeyring` to operate on it in the\n // retry below.\n log(\n `Money keyring (entropy:${entropySource}) not found, creating one...`,\n );\n const { id } = await this.#createMoneyKeyring(entropySource);\n\n // Use the ID directly on the retry (we just created this keyring so we\n // know exactly which one to target).\n return await withKeyring({ id }, operation);\n }\n });\n }\n\n /**\n * Adds a new money keyring for the given entropy source and returns its metadata.\n *\n * NOTE: This function won't check if a money keyring for the given entropy source already\n * exists!\n *\n * @param entropySource - The entropy source ID to create the money keyring for.\n * @returns The metadata of the newly created money keyring.\n */\n #createMoneyKeyring(\n entropySource: EntropySourceId,\n ): Promise<KeyringMetadata> {\n return this.messenger.call(\n 'KeyringController:addNewKeyring',\n KeyringTypes.money,\n {\n entropySource,\n } as MoneyKeyringSerializedState,\n );\n }\n\n /**\n * Gets the primary entropy source ID.\n *\n * @returns The primary entropy source ID, or `undefined` if no HD keyring exists.\n */\n #getPrimaryEntropySource(): EntropySourceId | undefined {\n const { keyrings } = this.messenger.call('KeyringController:getState');\n const primaryHdKeyring = keyrings.find(\n (keyring) => keyring.type === KeyringTypes.hd,\n );\n return primaryHdKeyring?.metadata.id;\n }\n\n /**\n * Throws if the keyring is currently locked.\n */\n #assertIsUnlocked(): void {\n const { isUnlocked } = this.messenger.call('KeyringController:getState');\n if (!isUnlocked) {\n throw new Error(\n 'Cannot create a money account while the keyring is locked',\n );\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/money-account-controller",
3
- "version": "2.0.0-preview-ff2ab0583",
3
+ "version": "2.0.0-preview-a2f6118d2",
4
4
  "description": "MetaMask Money account controller",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -54,21 +54,21 @@
54
54
  "@metamask/base-controller": "^10.0.0",
55
55
  "@metamask/eth-money-keyring": "^4.0.0",
56
56
  "@metamask/keyring-api": "^24.0.0",
57
- "@metamask/keyring-controller": "^28.1.0",
57
+ "@metamask/keyring-controller": "^28.0.0",
58
58
  "@metamask/messenger": "^3.0.0",
59
59
  "async-mutex": "^0.5.0"
60
60
  },
61
61
  "devDependencies": {
62
- "@metamask/auto-changelog": "^6.2.1",
62
+ "@metamask/auto-changelog": "^6.1.0",
63
63
  "@metamask/keyring-utils": "^5.0.0",
64
64
  "@metamask/utils": "^12.0.0",
65
65
  "@types/jest": "^30.0.0",
66
66
  "@typescript/native": "npm:typescript@^7.0.2",
67
- "deepmerge": "^4.3.1",
67
+ "deepmerge": "^4.2.2",
68
68
  "jest": "^30.4.2",
69
- "rimraf": "^6.1.3",
70
- "ts-jest": "^29.4.12",
71
- "tsx": "^4.23.15",
69
+ "rimraf": "^5.0.5",
70
+ "ts-jest": "^29.4.11",
71
+ "tsx": "^4.20.5",
72
72
  "typedoc": "^0.25.13",
73
73
  "typedoc-plugin-missing-exports": "^2.0.0",
74
74
  "typescript": "npm:@typescript/typescript6@^6.0.2"