From 985c4c0a17a3217b038461bab98268a1df0bba03 Mon Sep 17 00:00:00 2001 From: ieow <4881057+ieow@users.noreply.github.com> Date: Thu, 9 Apr 2026 15:21:36 +0800 Subject: [PATCH 1/6] feat: generic encryptor type for seedless controller --- .../src/SeedlessOnboardingController.test.ts | 14 ++++++----- .../src/SeedlessOnboardingController.ts | 25 +++++++++++++------ .../src/types.ts | 7 ------ .../tests/mocks/vaultEncryptor.ts | 13 +++++----- 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts index db91ff5246c..53de80fadd2 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts @@ -61,7 +61,6 @@ import { } from './SeedlessOnboardingController'; import type { SeedlessOnboardingControllerState, - VaultEncryptor, } from './types'; import type { MockKeyringControllerMessenger, @@ -81,6 +80,7 @@ import { import { MockToprfEncryptorDecryptor } from '../tests/mocks/toprfEncryptor'; import { createMockJWTToken } from '../tests/mocks/utils'; import MockVaultEncryptor from '../tests/mocks/vaultEncryptor'; +import { DefaultEncryptionResult, Encryptor } from '@metamask/keyring-controller'; const authConnection = AuthConnection.Google; const socialLoginEmail = 'user-test@gmail.com'; @@ -132,9 +132,10 @@ type WithControllerCallback = }: { controller: SeedlessOnboardingController< EKey, - SupportedKeyDerivationOptions + SupportedKeyDerivationOptions, + DefaultEncryptionResult >; - encryptor: VaultEncryptor; + encryptor: Encryptor>; initialState: SeedlessOnboardingControllerState; messenger: SeedlessOnboardingControllerMessenger; baseMessenger: RootMessenger; @@ -146,7 +147,7 @@ type WithControllerCallback = }) => Promise | ReturnValue; type WithControllerOptions = Partial< - SeedlessOnboardingControllerOptions + SeedlessOnboardingControllerOptions> >; type WithControllerArgs = @@ -163,9 +164,10 @@ type WithControllerArgs = * * @returns The default vault encryptor for the Seedless Onboarding Controller. */ -function getDefaultSeedlessOnboardingVaultEncryptor(): VaultEncryptor< +function getDefaultSeedlessOnboardingVaultEncryptor(): Encryptor< EncryptionKey | webcrypto.CryptoKey, - KeyDerivationOptions + KeyDerivationOptions, + DefaultEncryptionResult > { return { encrypt, diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts index 12401bd3deb..16ef46467e2 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts @@ -60,7 +60,6 @@ import type { SeedlessOnboardingControllerState, AuthenticatedUserDetails, SocialBackupsMetadata, - VaultEncryptor, RefreshJWTToken, RevokeRefreshToken, RenewRefreshToken, @@ -75,6 +74,11 @@ import { deserializeVaultData, serializeVaultData, } from './utils'; +import type { + DefaultEncryptionResult, + EncryptionResultConstraint, + Encryptor, +} from '@metamask/keyring-controller'; const log = createModuleLogger(projectLogger, controllerName); @@ -134,7 +138,8 @@ type AllowedEvents = never; // Messenger export type SeedlessOnboardingControllerMessenger = Messenger< typeof controllerName, - SeedlessOnboardingControllerActions | AllowedActions, + | SeedlessOnboardingControllerActions + | AllowedActions, SeedlessOnboardingControllerEvents | AllowedEvents >; @@ -146,8 +151,9 @@ export type SeedlessOnboardingControllerMessenger = Messenger< * @param encryptor - The encryptor to use for encrypting and decrypting seedless onboarding vault. */ export type SeedlessOnboardingControllerOptions< - EncryptionKey = encryptionUtils.EncryptionKey, - SupportedKeyDerivationParams = encryptionUtils.KeyDerivationOptions, + EncryptionKey, + SupportedKeyDerivationParams, + EncryptionResult extends EncryptionResultConstraint = DefaultEncryptionResult, > = { messenger: SeedlessOnboardingControllerMessenger; @@ -161,7 +167,7 @@ export type SeedlessOnboardingControllerOptions< * * @default browser-passworder @link https://github.com/MetaMask/browser-passworder */ - encryptor: VaultEncryptor; + encryptor: Encryptor; /** * A function to get a new jwt token using refresh token. @@ -377,14 +383,16 @@ const seedlessOnboardingMetadata: StateMetadata = DefaultEncryptionResult, > extends BaseController< typeof controllerName, SeedlessOnboardingControllerState, SeedlessOnboardingControllerMessenger > { - readonly #vaultEncryptor: VaultEncryptor< + readonly #vaultEncryptor: Encryptor< EncryptionKey, - SupportedKeyDerivationOptions + SupportedKeyDerivationOptions, + EncryptionResult >; readonly #controllerOperationMutex = new Mutex(); @@ -451,7 +459,8 @@ export class SeedlessOnboardingController< passwordOutdatedCacheTTL = PASSWORD_OUTDATED_CACHE_TTL_MS, }: SeedlessOnboardingControllerOptions< EncryptionKey, - SupportedKeyDerivationOptions + SupportedKeyDerivationOptions, + EncryptionResult >) { super({ name: controllerName, diff --git a/packages/seedless-onboarding-controller/src/types.ts b/packages/seedless-onboarding-controller/src/types.ts index 763deb5b88e..39033b6feef 100644 --- a/packages/seedless-onboarding-controller/src/types.ts +++ b/packages/seedless-onboarding-controller/src/types.ts @@ -1,4 +1,3 @@ -import type { Encryptor } from '@metamask/keyring-controller'; import type { KeyPair, NodeAuthTokens } from '@metamask/toprf-secure-backup'; import type { MutexInterface } from 'async-mutex'; @@ -179,12 +178,6 @@ export type SeedlessOnboardingControllerState = migrationVersion: number; }; -/** - * Encryptor interface for encrypting and decrypting seedless onboarding vault. - */ -export type VaultEncryptor = - Encryptor; - /** * Additional key deriver for the TOPRF client. * diff --git a/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts b/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts index 8b607eb2d1c..fe948b44e7a 100644 --- a/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts +++ b/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts @@ -1,16 +1,15 @@ import type { EncryptionKey, - EncryptionResult, KeyDerivationOptions, } from '@metamask/browser-passworder'; +import { DefaultEncryptionResult, Encryptor } from '@metamask/keyring-controller'; import type { Json } from '@metamask/utils'; import { webcrypto } from 'node:crypto'; -import type { VaultEncryptor } from '../../src/types'; export default class MockVaultEncryptor implements - VaultEncryptor + Encryptor> { defaultDerivationParams: KeyDerivationOptions = { algorithm: 'PBKDF2', @@ -123,7 +122,7 @@ export default class MockVaultEncryptor async encryptWithKey( encryptionKey: EncryptionKey | webcrypto.CryptoKey, data: unknown, - ): Promise { + ): Promise> { const dataString = JSON.stringify(data); const dataBuffer = Buffer.from(dataString); const vector = webcrypto.getRandomValues(new Uint8Array(16)); @@ -141,7 +140,7 @@ export default class MockVaultEncryptor const buffer = new Uint8Array(encBuff); const vectorStr = Buffer.from(vector).toString('base64'); const vaultStr = Buffer.from(buffer).toString('base64'); - const encryptionResult: EncryptionResult = { + const encryptionResult: DefaultEncryptionResult = { data: vaultStr, iv: vectorStr, }; @@ -155,9 +154,9 @@ export default class MockVaultEncryptor async decryptWithKey( encryptionKey: EncryptionKey | webcrypto.CryptoKey, - payload: EncryptionResult, + payload: DefaultEncryptionResult, ): Promise { - let encData: EncryptionResult; + let encData: DefaultEncryptionResult; if (typeof payload === 'string') { encData = JSON.parse(payload); } else { From 26cb9fc5a2c3f152df905174c6b1b3179a213125 Mon Sep 17 00:00:00 2001 From: ieow <4881057+ieow@users.noreply.github.com> Date: Thu, 9 Apr 2026 15:28:09 +0800 Subject: [PATCH 2/6] chore: changelog update --- packages/seedless-onboarding-controller/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/seedless-onboarding-controller/CHANGELOG.md b/packages/seedless-onboarding-controller/CHANGELOG.md index 42c836905c9..c8f111d13ca 100644 --- a/packages/seedless-onboarding-controller/CHANGELOG.md +++ b/packages/seedless-onboarding-controller/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `SecretMetadata.compareByTimestamp` static method for comparing metadata by timestamp ([#7284](https://github.com/MetaMask/core/pull/7284)) - Add `SecretMetadata.matchesType` static method for checking if metadata matches a given type ([#7284](https://github.com/MetaMask/core/pull/7284)) - Re-export `EncAccountDataType` from `@metamask/toprf-secure-backup` ([#7284](https://github.com/MetaMask/core/pull/7284)) +- Add third generic type parameter `EncryptionResult` to `SeedlessOnboardingController` and `SeedlessOnboardingControllerOptions`, constrained by `EncryptionResultConstraint` and defaulting to `DefaultEncryptionResult`, so the vault `encryptor` matches the full `Encryptor` typing from `@metamask/keyring-controller` ([#8411](https://github.com/MetaMask/core/pull/8411)) ### Changed @@ -32,6 +33,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Use `SecretMetadata.matchesType` for filtering - **BREAKING:** Change `SecretMetadata.fromRawMetadata` signature to require `storageMetadata` parameter ([#7284](https://github.com/MetaMask/core/pull/7284)) - **BREAKING:** Remove `version` getter from `SecretMetadata`; use `storageVersion` instead ([#7284](https://github.com/MetaMask/core/pull/7284)) +- **BREAKING:** Remove `VaultEncryptor` type alias; use `Encryptor` from `@metamask/keyring-controller` with encryption key, key derivation params, and encryption result types ([#8411](https://github.com/MetaMask/core/pull/8411)) +- **BREAKING:** `SeedlessOnboardingControllerOptions` no longer supplies default type parameters for `EncryptionKey` and `SupportedKeyDerivationParams`; pass both explicitly when referencing the type ([#8411](https://github.com/MetaMask/core/pull/8411)) ### Fixed From 6de2e9e5601d35a520f7eeb777506376f8e8fcfa Mon Sep 17 00:00:00 2001 From: ieow <4881057+ieow@users.noreply.github.com> Date: Thu, 9 Apr 2026 15:41:04 +0800 Subject: [PATCH 3/6] fix: linting --- .../src/SeedlessOnboardingController.test.ts | 21 +++++++++++----- .../src/SeedlessOnboardingController.ts | 25 +++++++++++-------- .../tests/mocks/vaultEncryptor.ts | 12 ++++++--- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts index 53de80fadd2..afed752a698 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts @@ -16,6 +16,10 @@ import { keyFromPassword as keyFromPasswordBrowserPassworder, encryptWithKey as encryptWithKeyBrowserPassworder, } from '@metamask/browser-passworder'; +import { + DefaultEncryptionResult, + Encryptor, +} from '@metamask/keyring-controller'; import { EncAccountDataType, TOPRFError, @@ -59,9 +63,7 @@ import { getInitialSeedlessOnboardingControllerStateWithDefaults, SeedlessOnboardingController, } from './SeedlessOnboardingController'; -import type { - SeedlessOnboardingControllerState, -} from './types'; +import type { SeedlessOnboardingControllerState } from './types'; import type { MockKeyringControllerMessenger, RootMessenger, @@ -80,7 +82,6 @@ import { import { MockToprfEncryptorDecryptor } from '../tests/mocks/toprfEncryptor'; import { createMockJWTToken } from '../tests/mocks/utils'; import MockVaultEncryptor from '../tests/mocks/vaultEncryptor'; -import { DefaultEncryptionResult, Encryptor } from '@metamask/keyring-controller'; const authConnection = AuthConnection.Google; const socialLoginEmail = 'user-test@gmail.com'; @@ -135,7 +136,11 @@ type WithControllerCallback = SupportedKeyDerivationOptions, DefaultEncryptionResult >; - encryptor: Encryptor>; + encryptor: Encryptor< + EKey, + SupportedKeyDerivationOptions, + DefaultEncryptionResult + >; initialState: SeedlessOnboardingControllerState; messenger: SeedlessOnboardingControllerMessenger; baseMessenger: RootMessenger; @@ -147,7 +152,11 @@ type WithControllerCallback = }) => Promise | ReturnValue; type WithControllerOptions = Partial< - SeedlessOnboardingControllerOptions> + SeedlessOnboardingControllerOptions< + EKey, + SupportedKeyDerivationParams, + DefaultEncryptionResult + > >; type WithControllerArgs = diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts index 16ef46467e2..3d6c6a1c5d7 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts @@ -6,6 +6,11 @@ import type { StateMetadata, } from '@metamask/base-controller'; import type * as encryptionUtils from '@metamask/browser-passworder'; +import type { + DefaultEncryptionResult, + EncryptionResultConstraint, + Encryptor, +} from '@metamask/keyring-controller'; import type { Messenger } from '@metamask/messenger'; import type { AuthenticateResult, @@ -74,11 +79,6 @@ import { deserializeVaultData, serializeVaultData, } from './utils'; -import type { - DefaultEncryptionResult, - EncryptionResultConstraint, - Encryptor, -} from '@metamask/keyring-controller'; const log = createModuleLogger(projectLogger, controllerName); @@ -138,8 +138,7 @@ type AllowedEvents = never; // Messenger export type SeedlessOnboardingControllerMessenger = Messenger< typeof controllerName, - | SeedlessOnboardingControllerActions - | AllowedActions, + SeedlessOnboardingControllerActions | AllowedActions, SeedlessOnboardingControllerEvents | AllowedEvents >; @@ -153,7 +152,8 @@ export type SeedlessOnboardingControllerMessenger = Messenger< export type SeedlessOnboardingControllerOptions< EncryptionKey, SupportedKeyDerivationParams, - EncryptionResult extends EncryptionResultConstraint = DefaultEncryptionResult, + EncryptionResult extends + EncryptionResultConstraint = DefaultEncryptionResult, > = { messenger: SeedlessOnboardingControllerMessenger; @@ -167,7 +167,11 @@ export type SeedlessOnboardingControllerOptions< * * @default browser-passworder @link https://github.com/MetaMask/browser-passworder */ - encryptor: Encryptor; + encryptor: Encryptor< + EncryptionKey, + SupportedKeyDerivationParams, + EncryptionResult + >; /** * A function to get a new jwt token using refresh token. @@ -383,7 +387,8 @@ const seedlessOnboardingMetadata: StateMetadata = DefaultEncryptionResult, + EncryptionResult extends + EncryptionResultConstraint = DefaultEncryptionResult, > extends BaseController< typeof controllerName, SeedlessOnboardingControllerState, diff --git a/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts b/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts index fe948b44e7a..8e6d0f53e7c 100644 --- a/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts +++ b/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts @@ -2,14 +2,20 @@ import type { EncryptionKey, KeyDerivationOptions, } from '@metamask/browser-passworder'; -import { DefaultEncryptionResult, Encryptor } from '@metamask/keyring-controller'; +import { + DefaultEncryptionResult, + Encryptor, +} from '@metamask/keyring-controller'; import type { Json } from '@metamask/utils'; import { webcrypto } from 'node:crypto'; - export default class MockVaultEncryptor implements - Encryptor> + Encryptor< + EncryptionKey | webcrypto.CryptoKey, + KeyDerivationOptions, + DefaultEncryptionResult + > { defaultDerivationParams: KeyDerivationOptions = { algorithm: 'PBKDF2', From 64b880775237feb97d0b5be93229ba037a77c10f Mon Sep 17 00:00:00 2001 From: ieow <4881057+ieow@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:44:36 +0800 Subject: [PATCH 4/6] fix: addrss commenrts --- .../src/SeedlessOnboardingController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts index 3d6c6a1c5d7..3a6890d1355 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts @@ -150,8 +150,8 @@ export type SeedlessOnboardingControllerMessenger = Messenger< * @param encryptor - The encryptor to use for encrypting and decrypting seedless onboarding vault. */ export type SeedlessOnboardingControllerOptions< - EncryptionKey, - SupportedKeyDerivationParams, + EncryptionKey = encryptionUtils.EncryptionKey, + SupportedKeyDerivationParams = encryptionUtils.KeyDerivationOptions, EncryptionResult extends EncryptionResultConstraint = DefaultEncryptionResult, > = { From a36bca269763c866ac19508feac4abb51a3ec3c0 Mon Sep 17 00:00:00 2001 From: ieow <4881057+ieow@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:37:28 +0800 Subject: [PATCH 5/6] fix: linting --- .../src/SeedlessOnboardingController.test.ts | 1 - .../src/SeedlessOnboardingController.ts | 6 ++++-- .../tests/mocks/vaultEncryptor.ts | 13 +++++-------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts index 69655a19456..84440c42fef 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts @@ -79,7 +79,6 @@ import type { getInitialSeedlessOnboardingControllerStateWithDefaults, SeedlessOnboardingController, } from './SeedlessOnboardingController'; - import type { SeedlessOnboardingControllerState } from './types'; const authConnection = AuthConnection.Google; diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts index 3a6890d1355..a28fbce5343 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.ts @@ -153,7 +153,8 @@ export type SeedlessOnboardingControllerOptions< EncryptionKey = encryptionUtils.EncryptionKey, SupportedKeyDerivationParams = encryptionUtils.KeyDerivationOptions, EncryptionResult extends - EncryptionResultConstraint = DefaultEncryptionResult, + EncryptionResultConstraint = + DefaultEncryptionResult, > = { messenger: SeedlessOnboardingControllerMessenger; @@ -388,7 +389,8 @@ export class SeedlessOnboardingController< EncryptionKey = encryptionUtils.EncryptionKey, SupportedKeyDerivationOptions = encryptionUtils.KeyDerivationOptions, EncryptionResult extends - EncryptionResultConstraint = DefaultEncryptionResult, + EncryptionResultConstraint = + DefaultEncryptionResult, > extends BaseController< typeof controllerName, SeedlessOnboardingControllerState, diff --git a/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts b/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts index 8e6d0f53e7c..8e2bd7631b9 100644 --- a/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts +++ b/packages/seedless-onboarding-controller/tests/mocks/vaultEncryptor.ts @@ -9,14 +9,11 @@ import { import type { Json } from '@metamask/utils'; import { webcrypto } from 'node:crypto'; -export default class MockVaultEncryptor - implements - Encryptor< - EncryptionKey | webcrypto.CryptoKey, - KeyDerivationOptions, - DefaultEncryptionResult - > -{ +export default class MockVaultEncryptor implements Encryptor< + EncryptionKey | webcrypto.CryptoKey, + KeyDerivationOptions, + DefaultEncryptionResult +> { defaultDerivationParams: KeyDerivationOptions = { algorithm: 'PBKDF2', params: { From 5f5149c2162e0939747f7bc54da4e97391341802 Mon Sep 17 00:00:00 2001 From: ieow <4881057+ieow@users.noreply.github.com> Date: Wed, 15 Apr 2026 10:48:30 +0800 Subject: [PATCH 6/6] fix: lint --- .../src/SeedlessOnboardingController.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts index 84440c42fef..bc1406e3e6a 100644 --- a/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts +++ b/packages/seedless-onboarding-controller/src/SeedlessOnboardingController.test.ts @@ -73,11 +73,13 @@ import { } from './constants'; import { PasswordSyncError, RecoveryError } from './errors'; import { SecretMetadata } from './SecretMetadata'; +import { + SeedlessOnboardingController, + getInitialSeedlessOnboardingControllerStateWithDefaults, +} from './SeedlessOnboardingController'; import type { SeedlessOnboardingControllerMessenger, SeedlessOnboardingControllerOptions, - getInitialSeedlessOnboardingControllerStateWithDefaults, - SeedlessOnboardingController, } from './SeedlessOnboardingController'; import type { SeedlessOnboardingControllerState } from './types';