From 9d1b73206280acbeec9ae044ff85e5264bf20452 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Mon, 13 Apr 2026 11:25:40 +0200 Subject: [PATCH 1/5] fix(wallet): Improve default messenger, state and instance types --- packages/wallet/src/Wallet.ts | 13 +++-- .../wallet/src/initialization/defaults.ts | 48 +++++++++++++++++++ packages/wallet/src/initialization/index.ts | 7 +++ .../src/initialization/initialization.ts | 11 +++-- packages/wallet/src/types.ts | 12 ----- 5 files changed, 70 insertions(+), 21 deletions(-) create mode 100644 packages/wallet/src/initialization/defaults.ts diff --git a/packages/wallet/src/Wallet.ts b/packages/wallet/src/Wallet.ts index 9ddb9dc4b70..d993c370c80 100644 --- a/packages/wallet/src/Wallet.ts +++ b/packages/wallet/src/Wallet.ts @@ -1,8 +1,13 @@ import { Messenger } from '@metamask/messenger'; import type { Json } from '@metamask/utils'; +import type { + DefaultInstances, + DefaultState, + RootMessenger, +} from './initialization'; import { initialize } from './initialization'; -import { RootMessenger, WalletOptions } from './types'; +import type { WalletOptions } from './types'; export type WalletConstructorArgs = { state?: Record; @@ -12,7 +17,7 @@ export type WalletConstructorArgs = { export class Wallet { public messenger: RootMessenger; - readonly #instances: Record>; + readonly #instances: DefaultInstances; constructor({ state = {}, options }: WalletConstructorArgs) { this.messenger = new Messenger({ @@ -22,14 +27,14 @@ export class Wallet { this.#instances = initialize({ state, messenger: this.messenger, options }); } - get state(): Record { + get state(): DefaultState { return Object.entries(this.#instances).reduce>( (totalState, [name, instance]) => { totalState[name] = instance.state ?? null; return totalState; }, {}, - ); + ) as DefaultState; } async destroy(): Promise { diff --git a/packages/wallet/src/initialization/defaults.ts b/packages/wallet/src/initialization/defaults.ts new file mode 100644 index 00000000000..b1a061fad7e --- /dev/null +++ b/packages/wallet/src/initialization/defaults.ts @@ -0,0 +1,48 @@ +import type { + Messenger, + MessengerActions, + MessengerEvents, +} from '@metamask/messenger'; + +import * as defaultConfigurations from './instances'; +import type { InitializationConfiguration, InstanceState } from './types'; + +export { defaultConfigurations }; + +type ExtractInstance = + Config extends InitializationConfiguration + ? Instance + : never; + +type ExtractInstanceMessenger = + Config extends InitializationConfiguration + ? InferredMessenger + : never; + +type ExtractName = + ExtractInstance extends { name: infer Name extends string } + ? Name + : never; + +type Configs = typeof defaultConfigurations; + +type AllMessengers = ExtractInstanceMessenger; + +export type DefaultInstances = { + [Key in keyof Configs as ExtractName]: ExtractInstance< + Configs[Key] + >; +}; + +export type DefaultActions = MessengerActions; + +export type DefaultEvents = MessengerEvents; + +export type RootMessenger< + AllowedActions extends DefaultActions = DefaultActions, + AllowedEvents extends DefaultEvents = DefaultEvents, +> = Messenger<'Root', AllowedActions, AllowedEvents>; + +export type DefaultState = { + [Key in keyof DefaultInstances]: InstanceState; +}; diff --git a/packages/wallet/src/initialization/index.ts b/packages/wallet/src/initialization/index.ts index 5f1b4048d67..5d17e1a18fa 100644 --- a/packages/wallet/src/initialization/index.ts +++ b/packages/wallet/src/initialization/index.ts @@ -1 +1,8 @@ +export type { + DefaultActions, + DefaultEvents, + DefaultInstances, + DefaultState, + RootMessenger, +} from './defaults'; export { initialize } from './initialization'; diff --git a/packages/wallet/src/initialization/initialization.ts b/packages/wallet/src/initialization/initialization.ts index 70ff75db8ab..22fd3bbc8dd 100644 --- a/packages/wallet/src/initialization/initialization.ts +++ b/packages/wallet/src/initialization/initialization.ts @@ -1,8 +1,9 @@ import { Json } from '@metamask/utils'; -import * as defaultConfigurations from './instances'; +import type { DefaultInstances } from './defaults'; +import { defaultConfigurations, RootMessenger } from './defaults'; import { InitializationConfiguration } from './types'; -import { RootMessenger, WalletOptions } from '../types'; +import { WalletOptions } from '../types'; export type InitializeArgs = { state: Record; @@ -19,7 +20,7 @@ export function initialize({ messenger, initializationConfigurations = [], options, -}: InitializeArgs): Record> { +}: InitializeArgs): DefaultInstances { const overriddenConfiguration = initializationConfigurations.map( (config) => config.name, ); @@ -30,7 +31,7 @@ export function initialize({ ), ); - const instances: Record> = {}; + const instances: Record = {}; for (const config of configurationEntries) { const { name } = config; @@ -48,5 +49,5 @@ export function initialize({ instances[name] = instance as Record; } - return instances; + return instances as DefaultInstances; } diff --git a/packages/wallet/src/types.ts b/packages/wallet/src/types.ts index 590a1461298..e808637e474 100644 --- a/packages/wallet/src/types.ts +++ b/packages/wallet/src/types.ts @@ -1,17 +1,5 @@ -import { - ActionConstraint, - EventConstraint, - Messenger, -} from '@metamask/messenger'; import type { ClientConfigApiService } from '@metamask/remote-feature-flag-controller'; -export type RootMessenger< - // eslint-disable-next-line @typescript-eslint/no-explicit-any - AllowedActions extends ActionConstraint = any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - AllowedEvents extends EventConstraint = any, -> = Messenger<'Root', AllowedActions, AllowedEvents>; - export type WalletOptions = { infuraProjectId: string; clientVersion: string; From a2cb299d389588d98dde2383279dc7b0fc0e17cc Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Mon, 13 Apr 2026 11:30:52 +0200 Subject: [PATCH 2/5] Remove cast --- packages/wallet/src/utilities.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/wallet/src/utilities.ts b/packages/wallet/src/utilities.ts index 3d5de362765..edd281f968b 100644 --- a/packages/wallet/src/utilities.ts +++ b/packages/wallet/src/utilities.ts @@ -61,11 +61,11 @@ export async function sendTransaction( transaction: TransactionParams, options: AddTransactionOptions, ): Promise<{ transactionMeta: TransactionMeta; result: Promise }> { - const { transactionMeta, result } = (await wallet.messenger.call( + const { transactionMeta, result } = await wallet.messenger.call( 'TransactionController:addTransaction', transaction, options, - )) as { transactionMeta: TransactionMeta; result: Promise }; + ); const approvalId = transactionMeta.id; From b177ea293b67301eb4bb87a7688a82c55c3bd860 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Mon, 13 Apr 2026 11:32:16 +0200 Subject: [PATCH 3/5] Use same utils version as everywhere else --- packages/wallet/package.json | 2 +- yarn.lock | 21 +-------------------- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/packages/wallet/package.json b/packages/wallet/package.json index c00cb2635f4..3f11bbed70b 100644 --- a/packages/wallet/package.json +++ b/packages/wallet/package.json @@ -60,7 +60,7 @@ "@metamask/remote-feature-flag-controller": "^4.2.0", "@metamask/scure-bip39": "^2.1.1", "@metamask/transaction-controller": "^64.0.0", - "@metamask/utils": "^11.11.0" + "@metamask/utils": "^11.9.0" }, "devDependencies": { "@metamask/auto-changelog": "^3.4.4", diff --git a/yarn.lock b/yarn.lock index a3dbc5c393b..60655666277 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5660,25 +5660,6 @@ __metadata: languageName: node linkType: hard -"@metamask/utils@npm:^11.11.0": - version: 11.11.0 - resolution: "@metamask/utils@npm:11.11.0" - dependencies: - "@ethereumjs/tx": "npm:^4.2.0" - "@metamask/superstruct": "npm:^3.1.0" - "@noble/hashes": "npm:^1.3.1" - "@scure/base": "npm:^1.1.3" - "@types/debug": "npm:^4.1.7" - "@types/lodash": "npm:^4.17.20" - debug: "npm:^4.3.4" - lodash: "npm:^4.17.21" - pony-cause: "npm:^2.1.10" - semver: "npm:^7.5.4" - uuid: "npm:^9.0.1" - checksum: 10/c4381b9e451a9616bde84ac659bc0d1848ef06b6e605f877bfa065b78c8ed5015706683ea88a3387de5eaeb3a50d1af9af0994f04f9e06258d992598fe2be3bf - languageName: node - linkType: hard - "@metamask/utils@npm:^9.0.0": version: 9.3.0 resolution: "@metamask/utils@npm:9.3.0" @@ -5712,7 +5693,7 @@ __metadata: "@metamask/remote-feature-flag-controller": "npm:^4.2.0" "@metamask/scure-bip39": "npm:^2.1.1" "@metamask/transaction-controller": "npm:^64.0.0" - "@metamask/utils": "npm:^11.11.0" + "@metamask/utils": "npm:^11.9.0" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^29.5.14" deepmerge: "npm:^4.2.2" From c31eba30cbedbcc0002191fda29d75c7b0c1fd0d Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Mon, 13 Apr 2026 11:57:01 +0200 Subject: [PATCH 4/5] Fix type errors --- packages/wallet/src/Wallet.ts | 4 +++- packages/wallet/src/initialization/types.ts | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/wallet/src/Wallet.ts b/packages/wallet/src/Wallet.ts index d993c370c80..fa7b1215623 100644 --- a/packages/wallet/src/Wallet.ts +++ b/packages/wallet/src/Wallet.ts @@ -1,5 +1,5 @@ import { Messenger } from '@metamask/messenger'; -import type { Json } from '@metamask/utils'; +import { hasProperty, type Json } from '@metamask/utils'; import type { DefaultInstances, @@ -40,7 +40,9 @@ export class Wallet { async destroy(): Promise { await Promise.all( Object.values(this.#instances).map((instance) => { + // @ts-expect-error Accessing protected property. if (typeof instance.destroy === 'function') { + // @ts-expect-error Accessing protected property. return instance.destroy(); } return undefined; diff --git a/packages/wallet/src/initialization/types.ts b/packages/wallet/src/initialization/types.ts index a08b1934c99..b8c1af09541 100644 --- a/packages/wallet/src/initialization/types.ts +++ b/packages/wallet/src/initialization/types.ts @@ -7,7 +7,8 @@ import type { MessengerActions, } from '@metamask/messenger'; -import { RootMessenger, WalletOptions } from '../types'; +import type { WalletOptions } from '../types'; +import type { RootMessenger } from './defaults'; export type InstanceState = Instance extends { state: unknown } ? Instance['state'] From e130704b5f196d9850f9c80891d70aeec19bfb2c Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Mon, 13 Apr 2026 13:07:14 +0200 Subject: [PATCH 5/5] Fix build --- packages/wallet/src/Wallet.ts | 7 +++++-- packages/wallet/src/initialization/defaults.ts | 6 ++++-- packages/wallet/src/initialization/types.ts | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/wallet/src/Wallet.ts b/packages/wallet/src/Wallet.ts index fa7b1215623..69eb108f04e 100644 --- a/packages/wallet/src/Wallet.ts +++ b/packages/wallet/src/Wallet.ts @@ -1,7 +1,9 @@ import { Messenger } from '@metamask/messenger'; -import { hasProperty, type Json } from '@metamask/utils'; +import type { Json } from '@metamask/utils'; import type { + DefaultActions, + DefaultEvents, DefaultInstances, DefaultState, RootMessenger, @@ -15,7 +17,8 @@ export type WalletConstructorArgs = { }; export class Wallet { - public messenger: RootMessenger; + // TODO: Expand types when passing additionalConfigurations. + public readonly messenger: RootMessenger; readonly #instances: DefaultInstances; diff --git a/packages/wallet/src/initialization/defaults.ts b/packages/wallet/src/initialization/defaults.ts index b1a061fad7e..b3b8a463553 100644 --- a/packages/wallet/src/initialization/defaults.ts +++ b/packages/wallet/src/initialization/defaults.ts @@ -1,4 +1,6 @@ import type { + ActionConstraint, + EventConstraint, Messenger, MessengerActions, MessengerEvents, @@ -39,8 +41,8 @@ export type DefaultActions = MessengerActions; export type DefaultEvents = MessengerEvents; export type RootMessenger< - AllowedActions extends DefaultActions = DefaultActions, - AllowedEvents extends DefaultEvents = DefaultEvents, + AllowedActions extends ActionConstraint = ActionConstraint, + AllowedEvents extends EventConstraint = EventConstraint, > = Messenger<'Root', AllowedActions, AllowedEvents>; export type DefaultState = { diff --git a/packages/wallet/src/initialization/types.ts b/packages/wallet/src/initialization/types.ts index b8c1af09541..24a88988f6d 100644 --- a/packages/wallet/src/initialization/types.ts +++ b/packages/wallet/src/initialization/types.ts @@ -7,8 +7,8 @@ import type { MessengerActions, } from '@metamask/messenger'; -import type { WalletOptions } from '../types'; import type { RootMessenger } from './defaults'; +import type { WalletOptions } from '../types'; export type InstanceState = Instance extends { state: unknown } ? Instance['state']