From 02e94a34c472fc29b9bde3dce15cc1f26ce1122e Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Fri, 6 Feb 2026 13:28:55 +0100 Subject: [PATCH 1/7] feat(keyring-api): add assertCreateAccountOptionTypeIsSupported helper (for createAccounts) --- .../src/api/v2/create-account/index.test.ts | 148 +++++++++++++++++- .../src/api/v2/create-account/index.ts | 20 +++ 2 files changed, 167 insertions(+), 1 deletion(-) diff --git a/packages/keyring-api/src/api/v2/create-account/index.test.ts b/packages/keyring-api/src/api/v2/create-account/index.test.ts index e5228ad06..5c1d13f61 100644 --- a/packages/keyring-api/src/api/v2/create-account/index.test.ts +++ b/packages/keyring-api/src/api/v2/create-account/index.test.ts @@ -1,6 +1,10 @@ import { assert, is } from '@metamask/superstruct'; -import { AccountCreationType, CreateAccountOptionsStruct } from '.'; +import { + AccountCreationType, + assertCreateAccountOptionTypeIsSupported, + CreateAccountOptionsStruct, +} from '.'; describe('CreateAccountOptionsStruct', () => { describe('valid account creation types', () => { @@ -195,3 +199,145 @@ describe('CreateAccountOptionsStruct', () => { }); }); }); + +describe('assertCreateAccountOptionTypeIsSupported', () => { + describe('when type is supported', () => { + it('does not throw when type is in supportedTypes array', () => { + const type = AccountCreationType.Bip44DerivePath; + const supportedTypes = [ + AccountCreationType.Bip44DerivePath, + AccountCreationType.Bip44DeriveIndex, + ]; + + expect(() => + assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + ).not.toThrow(); + }); + + it('does not throw when type is the only supported type', () => { + const type = AccountCreationType.PrivateKeyImport; + const supportedTypes = [AccountCreationType.PrivateKeyImport]; + + expect(() => + assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + ).not.toThrow(); + }); + + it('does not throw when all types are supported', () => { + const type = AccountCreationType.Custom; + const supportedTypes = [ + AccountCreationType.Bip44DerivePath, + AccountCreationType.Bip44DeriveIndex, + AccountCreationType.Bip44DeriveIndexRange, + AccountCreationType.Bip44Discover, + AccountCreationType.PrivateKeyImport, + AccountCreationType.Custom, + ]; + + expect(() => + assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + ).not.toThrow(); + }); + + it('does not throw for each supported BIP-44 type', () => { + const supportedTypes = [ + AccountCreationType.Bip44DerivePath, + AccountCreationType.Bip44DeriveIndex, + AccountCreationType.Bip44DeriveIndexRange, + AccountCreationType.Bip44Discover, + ]; + + supportedTypes.forEach((type) => { + expect(() => + assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + ).not.toThrow(); + }); + }); + }); + + describe('when type is not supported', () => { + it('throws error with correct message when type is not in supportedTypes', () => { + const type = AccountCreationType.Custom; + const supportedTypes = [ + AccountCreationType.Bip44DerivePath, + AccountCreationType.Bip44DeriveIndex, + ]; + + expect(() => + assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + ).toThrow('Unsupported create account option type: custom'); + }); + + it('throws error when supportedTypes is empty', () => { + const type = AccountCreationType.Bip44DerivePath; + const supportedTypes: AccountCreationType[] = []; + + expect(() => + assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + ).toThrow('Unsupported create account option type: bip44:derive-path'); + }); + + it('throws error for PrivateKeyImport when only BIP-44 types are supported', () => { + const type = AccountCreationType.PrivateKeyImport; + const supportedTypes = [ + AccountCreationType.Bip44DerivePath, + AccountCreationType.Bip44DeriveIndex, + ]; + + expect(() => + assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + ).toThrow('Unsupported create account option type: private-key:import'); + }); + + it('throws error for Bip44Discover when not in supportedTypes', () => { + const type = AccountCreationType.Bip44Discover; + const supportedTypes = [ + AccountCreationType.Bip44DerivePath, + AccountCreationType.Custom, + ]; + + expect(() => + assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + ).toThrow('Unsupported create account option type: bip44:discover'); + }); + + it('includes the unsupported type value in error message', () => { + const type = AccountCreationType.Bip44DeriveIndexRange; + const supportedTypes = [AccountCreationType.PrivateKeyImport]; + + expect(() => + assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + ).toThrow(/bip44:derive-index-range/u); + }); + }); + + describe('type narrowing behavior', () => { + it('narrows type correctly after assertion passes', () => { + const type: AccountCreationType = AccountCreationType.Bip44DerivePath; + const supportedTypes = [AccountCreationType.Bip44DerivePath] as const; + + assertCreateAccountOptionTypeIsSupported(type, supportedTypes); + + // After the assertion, TypeScript should narrow the type. + const narrowedType: (typeof supportedTypes)[number] = type; // Compile-time check. + expect(narrowedType).toBe(AccountCreationType.Bip44DerivePath); + }); + + it('works with const arrays for type narrowing', () => { + const supportedTypes = [ + AccountCreationType.Bip44DeriveIndex, + AccountCreationType.Custom, + ] as const; + + const type1: AccountCreationType = AccountCreationType.Bip44DeriveIndex; + assertCreateAccountOptionTypeIsSupported(type1, supportedTypes); + const narrowedType1: AccountCreationType.Bip44DeriveIndex = type1; // Compile-time check. + expect(narrowedType1).toBe(AccountCreationType.Bip44DeriveIndex); + + const type2: AccountCreationType = AccountCreationType.Custom; + assertCreateAccountOptionTypeIsSupported(type2, supportedTypes); + const narrowedType2: AccountCreationType.Custom = type2; // Compile-time check. + expect(narrowedType2).toBe(AccountCreationType.Bip44DeriveIndex); + }); + }); +}); diff --git a/packages/keyring-api/src/api/v2/create-account/index.ts b/packages/keyring-api/src/api/v2/create-account/index.ts index e37c7b8aa..384852f05 100644 --- a/packages/keyring-api/src/api/v2/create-account/index.ts +++ b/packages/keyring-api/src/api/v2/create-account/index.ts @@ -92,3 +92,23 @@ export const CreateAccountOptionsStruct = selectiveUnion((value: any) => { * Represents the available options for creating a new account. */ export type CreateAccountOptions = Infer; + +/** + * Asserts that a given create account option type is supported by the keyring. + * + * @param type - The create account option type to check. + * @param supportedTypes - The list of supported create account option types for this keyring. + * @throws Will throw an error if the provided type is not supported. + */ +export function assertCreateAccountOptionTypeIsSupported< + Type extends CreateAccountOptions['type'], +>( + type: CreateAccountOptions['type'], + supportedTypes: readonly Type[], +): asserts type is Type { + const types: readonly CreateAccountOptions['type'][] = supportedTypes; + + if (!types.includes(type)) { + throw new Error(`Unsupported create account option type: ${type}`); + } +} From a8497af6987ab7451f2605e148db7489712b0958 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Fri, 6 Feb 2026 13:36:28 +0100 Subject: [PATCH 2/7] feat: add test + example --- .../src/api/v2/create-account/index.test.ts | 19 +++++++++++++++++++ .../src/api/v2/create-account/index.ts | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/packages/keyring-api/src/api/v2/create-account/index.test.ts b/packages/keyring-api/src/api/v2/create-account/index.test.ts index 5c1d13f61..ca8463b0d 100644 --- a/packages/keyring-api/src/api/v2/create-account/index.test.ts +++ b/packages/keyring-api/src/api/v2/create-account/index.test.ts @@ -1,5 +1,9 @@ import { assert, is } from '@metamask/superstruct'; +import type { + CreateAccountBip44DeriveIndexOptions, + CreateAccountOptions, +} from '.'; import { AccountCreationType, assertCreateAccountOptionTypeIsSupported, @@ -339,5 +343,20 @@ describe('assertCreateAccountOptionTypeIsSupported', () => { const narrowedType2: AccountCreationType.Custom = type2; // Compile-time check. expect(narrowedType2).toBe(AccountCreationType.Bip44DeriveIndex); }); + + it('narrows CreateAccountOptions type based on supported type', () => { + const options = { + type: AccountCreationType.Bip44DeriveIndex, + entropySource: 'mock-entropy-source', + groupIndex: 0, + } as CreateAccountOptions; + + const supportedTypes = [AccountCreationType.Bip44DeriveIndex] as const; + assertCreateAccountOptionTypeIsSupported(options.type, supportedTypes); + + // After assertion, options should be narrowed to CreateAccountBip44DeriveIndexOptions + const narrowedOptions: CreateAccountBip44DeriveIndexOptions = options; // Compile-time check. + expect(narrowedOptions.type).toBe(AccountCreationType.Bip44DeriveIndex); + }); }); }); diff --git a/packages/keyring-api/src/api/v2/create-account/index.ts b/packages/keyring-api/src/api/v2/create-account/index.ts index 384852f05..423495c26 100644 --- a/packages/keyring-api/src/api/v2/create-account/index.ts +++ b/packages/keyring-api/src/api/v2/create-account/index.ts @@ -96,6 +96,25 @@ export type CreateAccountOptions = Infer; /** * Asserts that a given create account option type is supported by the keyring. * + * @example + * ```ts + * createAccounts(options: CreateAccountOptions) { + * assertCreateAccountOptionTypeIsSupported(options.type, [ + * AccountCreationType.Bip44DeriveIndex, + * AccountCreationType.Bip44DeriveIndexRange, + * ] as const); + * + * // At this point, TypeScript knows that options.type is either Bip44DeriveIndex or Bip44DeriveIndexRange. + * if (options.type === AccountCreationType.Bip44DeriveIndex) { + * ... // Handle Bip44DeriveIndex case. + * } else { + * ... // Handle Bip44DeriveIndexRange case. + * } + * ... + * return accounts; + * } + * ``` + * * @param type - The create account option type to check. * @param supportedTypes - The list of supported create account option types for this keyring. * @throws Will throw an error if the provided type is not supported. From e645716480590d42ecf09fa00561c0d5722c14b5 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Fri, 6 Feb 2026 13:53:54 +0100 Subject: [PATCH 3/7] test: fix test --- packages/keyring-api/src/api/v2/create-account/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/keyring-api/src/api/v2/create-account/index.test.ts b/packages/keyring-api/src/api/v2/create-account/index.test.ts index ca8463b0d..989b2f9d3 100644 --- a/packages/keyring-api/src/api/v2/create-account/index.test.ts +++ b/packages/keyring-api/src/api/v2/create-account/index.test.ts @@ -341,7 +341,7 @@ describe('assertCreateAccountOptionTypeIsSupported', () => { const type2: AccountCreationType = AccountCreationType.Custom; assertCreateAccountOptionTypeIsSupported(type2, supportedTypes); const narrowedType2: AccountCreationType.Custom = type2; // Compile-time check. - expect(narrowedType2).toBe(AccountCreationType.Bip44DeriveIndex); + expect(narrowedType2).toBe(AccountCreationType.Custom); }); it('narrows CreateAccountOptions type based on supported type', () => { From cb9e019383b4ae5eaca3ff8e38f1179bfa01ee47 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Fri, 6 Feb 2026 16:28:27 +0100 Subject: [PATCH 4/7] chore: update changelog --- packages/keyring-api/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/keyring-api/CHANGELOG.md b/packages/keyring-api/CHANGELOG.md index d5a27d9c6..0134d4b3c 100644 --- a/packages/keyring-api/CHANGELOG.md +++ b/packages/keyring-api/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add `assertCreateAccountOptionTypeIsSupported` helper ([#464](https://github.com/MetaMask/accounts/pull/464)) + - This helper can be used to implement `createAccounts` and now down the `options` to the supported types based on the keyring capabilities. + ## [21.4.0] ### Added From da0262f47a5aff5d8b5aec9cf80886423e7ee5eb Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Mon, 9 Feb 2026 10:52:00 +0100 Subject: [PATCH 5/7] chore: rename + lint --- .../src/api/v2/create-account/index.test.ts | 150 ++++++++++++------ .../src/api/v2/create-account/index.ts | 22 +-- 2 files changed, 118 insertions(+), 54 deletions(-) diff --git a/packages/keyring-api/src/api/v2/create-account/index.test.ts b/packages/keyring-api/src/api/v2/create-account/index.test.ts index 989b2f9d3..69ce5c93f 100644 --- a/packages/keyring-api/src/api/v2/create-account/index.test.ts +++ b/packages/keyring-api/src/api/v2/create-account/index.test.ts @@ -1,13 +1,11 @@ import { assert, is } from '@metamask/superstruct'; -import type { - CreateAccountBip44DeriveIndexOptions, - CreateAccountOptions, -} from '.'; import { AccountCreationType, - assertCreateAccountOptionTypeIsSupported, + assertCreateAccountOptionIsSupported, CreateAccountOptionsStruct, + type CreateAccountBip44DeriveIndexOptions, + type CreateAccountOptions, } from '.'; describe('CreateAccountOptionsStruct', () => { @@ -204,31 +202,42 @@ describe('CreateAccountOptionsStruct', () => { }); }); -describe('assertCreateAccountOptionTypeIsSupported', () => { +describe('assertCreateAccountOptionIsSupported', () => { describe('when type is supported', () => { it('does not throw when type is in supportedTypes array', () => { - const type = AccountCreationType.Bip44DerivePath; + const options = { + type: AccountCreationType.Bip44DerivePath, + entropySource: 'user-input', + derivationPath: "m/44'/0'/0'/0/0", + } as CreateAccountOptions; const supportedTypes = [ AccountCreationType.Bip44DerivePath, AccountCreationType.Bip44DeriveIndex, ]; expect(() => - assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + assertCreateAccountOptionIsSupported(options, supportedTypes), ).not.toThrow(); }); it('does not throw when type is the only supported type', () => { - const type = AccountCreationType.PrivateKeyImport; + const options = { + type: AccountCreationType.PrivateKeyImport, + privateKey: '0x1234567890abcdef', + encoding: 'hexadecimal', + } as CreateAccountOptions; const supportedTypes = [AccountCreationType.PrivateKeyImport]; expect(() => - assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + assertCreateAccountOptionIsSupported(options, supportedTypes), ).not.toThrow(); }); it('does not throw when all types are supported', () => { - const type = AccountCreationType.Custom; + const options = { + type: AccountCreationType.Custom, + scope: 'scope', + } as CreateAccountOptions; const supportedTypes = [ AccountCreationType.Bip44DerivePath, AccountCreationType.Bip44DeriveIndex, @@ -239,7 +248,7 @@ describe('assertCreateAccountOptionTypeIsSupported', () => { ]; expect(() => - assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + assertCreateAccountOptionIsSupported(options, supportedTypes), ).not.toThrow(); }); @@ -251,9 +260,49 @@ describe('assertCreateAccountOptionTypeIsSupported', () => { AccountCreationType.Bip44Discover, ]; + const optionsMap: Record = { + [AccountCreationType.Bip44DerivePath]: { + type: AccountCreationType.Bip44DerivePath, + entropySource: 'user-input', + derivationPath: "m/44'/0'/0'/0/0", + }, + [AccountCreationType.Bip44DeriveIndex]: { + type: AccountCreationType.Bip44DeriveIndex, + entropySource: 'user-input', + groupIndex: 0, + }, + [AccountCreationType.Bip44DeriveIndexRange]: { + type: AccountCreationType.Bip44DeriveIndexRange, + entropySource: 'user-input', + range: { + from: 0, + to: 1, + }, + }, + [AccountCreationType.Bip44Discover]: { + type: AccountCreationType.Bip44Discover, + entropySource: 'user-input', + groupIndex: 0, + }, + [AccountCreationType.PrivateKeyImport]: { + type: AccountCreationType.PrivateKeyImport, + privateKey: '0x1234567890abcdef', + encoding: 'hexadecimal', + }, + [AccountCreationType.Custom]: { + type: AccountCreationType.Custom, + // FIXME: We cannot use custom fields currently with `CreateAccountOptions` type. + // We need to define a struct manually to open up the type for custom options to + // allow additional fields. + }, + }; + supportedTypes.forEach((type) => { expect(() => - assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + assertCreateAccountOptionIsSupported( + optionsMap[type], + supportedTypes, + ), ).not.toThrow(); }); }); @@ -261,87 +310,98 @@ describe('assertCreateAccountOptionTypeIsSupported', () => { describe('when type is not supported', () => { it('throws error with correct message when type is not in supportedTypes', () => { - const type = AccountCreationType.Custom; + const options = { + type: AccountCreationType.Custom, + scope: 'scope', + } as CreateAccountOptions; const supportedTypes = [ AccountCreationType.Bip44DerivePath, AccountCreationType.Bip44DeriveIndex, ]; expect(() => - assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + assertCreateAccountOptionIsSupported(options, supportedTypes), ).toThrow('Unsupported create account option type: custom'); }); it('throws error when supportedTypes is empty', () => { - const type = AccountCreationType.Bip44DerivePath; + const options = { + type: AccountCreationType.Bip44DerivePath, + entropySource: 'user-input', + derivationPath: "m/44'/0'/0'/0/0", + } as CreateAccountOptions; const supportedTypes: AccountCreationType[] = []; expect(() => - assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + assertCreateAccountOptionIsSupported(options, supportedTypes), ).toThrow('Unsupported create account option type: bip44:derive-path'); }); it('throws error for PrivateKeyImport when only BIP-44 types are supported', () => { - const type = AccountCreationType.PrivateKeyImport; + const options = { + type: AccountCreationType.PrivateKeyImport, + privateKey: '0x1234567890abcdef', + encoding: 'hexadecimal', + } as CreateAccountOptions; const supportedTypes = [ AccountCreationType.Bip44DerivePath, AccountCreationType.Bip44DeriveIndex, ]; expect(() => - assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + assertCreateAccountOptionIsSupported(options, supportedTypes), ).toThrow('Unsupported create account option type: private-key:import'); }); it('throws error for Bip44Discover when not in supportedTypes', () => { - const type = AccountCreationType.Bip44Discover; + const options = { + type: AccountCreationType.Bip44Discover, + entropySource: 'user-input', + groupIndex: 0, + } as CreateAccountOptions; const supportedTypes = [ AccountCreationType.Bip44DerivePath, AccountCreationType.Custom, ]; expect(() => - assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + assertCreateAccountOptionIsSupported(options, supportedTypes), ).toThrow('Unsupported create account option type: bip44:discover'); }); it('includes the unsupported type value in error message', () => { - const type = AccountCreationType.Bip44DeriveIndexRange; + const options = { + type: AccountCreationType.Bip44DeriveIndexRange, + entropySource: 'user-input', + range: { + from: 0, + to: 1, + }, + } as CreateAccountOptions; const supportedTypes = [AccountCreationType.PrivateKeyImport]; expect(() => - assertCreateAccountOptionTypeIsSupported(type, supportedTypes), + assertCreateAccountOptionIsSupported(options, supportedTypes), ).toThrow(/bip44:derive-index-range/u); }); }); describe('type narrowing behavior', () => { it('narrows type correctly after assertion passes', () => { - const type: AccountCreationType = AccountCreationType.Bip44DerivePath; - const supportedTypes = [AccountCreationType.Bip44DerivePath] as const; - - assertCreateAccountOptionTypeIsSupported(type, supportedTypes); - - // After the assertion, TypeScript should narrow the type. - const narrowedType: (typeof supportedTypes)[number] = type; // Compile-time check. - expect(narrowedType).toBe(AccountCreationType.Bip44DerivePath); - }); - - it('works with const arrays for type narrowing', () => { + const options = { + type: AccountCreationType.Bip44DerivePath, + entropySource: 'user-input', + derivationPath: "m/44'/0'/0'/0/0", + } as CreateAccountOptions; const supportedTypes = [ - AccountCreationType.Bip44DeriveIndex, - AccountCreationType.Custom, + `${AccountCreationType.Bip44DerivePath}`, ] as const; - const type1: AccountCreationType = AccountCreationType.Bip44DeriveIndex; - assertCreateAccountOptionTypeIsSupported(type1, supportedTypes); - const narrowedType1: AccountCreationType.Bip44DeriveIndex = type1; // Compile-time check. - expect(narrowedType1).toBe(AccountCreationType.Bip44DeriveIndex); + assertCreateAccountOptionIsSupported(options, supportedTypes); - const type2: AccountCreationType = AccountCreationType.Custom; - assertCreateAccountOptionTypeIsSupported(type2, supportedTypes); - const narrowedType2: AccountCreationType.Custom = type2; // Compile-time check. - expect(narrowedType2).toBe(AccountCreationType.Custom); + // After the assertion, TypeScript should narrow the type. + const narrowedType: (typeof supportedTypes)[number] = options.type; // Compile-time check. + expect(narrowedType).toBe(AccountCreationType.Bip44DerivePath); }); it('narrows CreateAccountOptions type based on supported type', () => { @@ -352,7 +412,7 @@ describe('assertCreateAccountOptionTypeIsSupported', () => { } as CreateAccountOptions; const supportedTypes = [AccountCreationType.Bip44DeriveIndex] as const; - assertCreateAccountOptionTypeIsSupported(options.type, supportedTypes); + assertCreateAccountOptionIsSupported(options, supportedTypes); // After assertion, options should be narrowed to CreateAccountBip44DeriveIndexOptions const narrowedOptions: CreateAccountBip44DeriveIndexOptions = options; // Compile-time check. diff --git a/packages/keyring-api/src/api/v2/create-account/index.ts b/packages/keyring-api/src/api/v2/create-account/index.ts index 423495c26..9d9a8ec90 100644 --- a/packages/keyring-api/src/api/v2/create-account/index.ts +++ b/packages/keyring-api/src/api/v2/create-account/index.ts @@ -99,9 +99,9 @@ export type CreateAccountOptions = Infer; * @example * ```ts * createAccounts(options: CreateAccountOptions) { - * assertCreateAccountOptionTypeIsSupported(options.type, [ - * AccountCreationType.Bip44DeriveIndex, - * AccountCreationType.Bip44DeriveIndexRange, + * assertCreateAccountOptionIsSupported(options, [ + * ${AccountCreationType.Bip44DeriveIndex}, + * ${AccountCreationType.Bip44DeriveIndexRange}, * ] as const); * * // At this point, TypeScript knows that options.type is either Bip44DeriveIndex or Bip44DeriveIndexRange. @@ -115,16 +115,20 @@ export type CreateAccountOptions = Infer; * } * ``` * - * @param type - The create account option type to check. + * @param options - The create account option object to check. * @param supportedTypes - The list of supported create account option types for this keyring. * @throws Will throw an error if the provided type is not supported. */ -export function assertCreateAccountOptionTypeIsSupported< - Type extends CreateAccountOptions['type'], +export function assertCreateAccountOptionIsSupported< + Options extends CreateAccountOptions, + // We use template literal types to enforce string-literal over strict enum values. + Type extends `${CreateAccountOptions['type']}`, >( - type: CreateAccountOptions['type'], - supportedTypes: readonly Type[], -): asserts type is Type { + options: Options, + supportedTypes: readonly `${Type}`[], + // Use intersection to narrow the `type` based on the the static `Options['type']` field. +): asserts options is Options & { type: `${Type}` & `${Options['type']}` } { + const { type } = options; const types: readonly CreateAccountOptions['type'][] = supportedTypes; if (!types.includes(type)) { From 4bb5345e8ea5ad8a31d1ccb1ade50895055fe93c Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Mon, 9 Feb 2026 11:22:32 +0100 Subject: [PATCH 6/7] chore: update changelog --- packages/keyring-api/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/keyring-api/CHANGELOG.md b/packages/keyring-api/CHANGELOG.md index 0134d4b3c..7ffa4a3fd 100644 --- a/packages/keyring-api/CHANGELOG.md +++ b/packages/keyring-api/CHANGELOG.md @@ -9,8 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Add `assertCreateAccountOptionTypeIsSupported` helper ([#464](https://github.com/MetaMask/accounts/pull/464)) - - This helper can be used to implement `createAccounts` and now down the `options` to the supported types based on the keyring capabilities. +- Add `assertCreateAccountOptionIsSupported` helper ([#464](https://github.com/MetaMask/accounts/pull/464)) + - This helper can be used to implement `createAccounts` and narrow down the `options` to the supported types (based on the keyring capabilities). ## [21.4.0] From 5239735c172125724ea9a986b56a01bb1e6f2774 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Mon, 9 Feb 2026 11:25:07 +0100 Subject: [PATCH 7/7] chore: better docs --- packages/keyring-api/src/api/v2/create-account/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/keyring-api/src/api/v2/create-account/index.ts b/packages/keyring-api/src/api/v2/create-account/index.ts index 9d9a8ec90..767e43d9c 100644 --- a/packages/keyring-api/src/api/v2/create-account/index.ts +++ b/packages/keyring-api/src/api/v2/create-account/index.ts @@ -117,7 +117,7 @@ export type CreateAccountOptions = Infer; * * @param options - The create account option object to check. * @param supportedTypes - The list of supported create account option types for this keyring. - * @throws Will throw an error if the provided type is not supported. + * @throws Will throw an error if the provided options are not supported. */ export function assertCreateAccountOptionIsSupported< Options extends CreateAccountOptions, @@ -126,7 +126,7 @@ export function assertCreateAccountOptionIsSupported< >( options: Options, supportedTypes: readonly `${Type}`[], - // Use intersection to narrow the `type` based on the the static `Options['type']` field. + // Use intersection to avoid widening `type` beyond `Options['type']`. ): asserts options is Options & { type: `${Type}` & `${Options['type']}` } { const { type } = options; const types: readonly CreateAccountOptions['type'][] = supportedTypes;