Skip to content

Commit 1bae05a

Browse files
authored
feat(account-api): add isBip44Account helper (#319)
Add `isBip44Account` which can be used to detect if an `Account` type (`KeyringAcccount` compatible) is compatible with BIP-44 (according to the new typed options).
1 parent 79a10e2 commit 1bae05a

5 files changed

Lines changed: 108 additions & 1 deletion

File tree

packages/account-api/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
},
4848
"dependencies": {
4949
"@metamask/keyring-api": "workspace:^",
50-
"@metamask/keyring-utils": "workspace:^"
50+
"@metamask/keyring-utils": "workspace:^",
51+
"@metamask/superstruct": "^3.1.0"
5152
},
5253
"devDependencies": {
5354
"@lavamoat/allow-scripts": "^3.2.1",
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type {
2+
KeyringAccount,
3+
KeyringAccountEntropyMnemonicOptions,
4+
} from '@metamask/keyring-api';
5+
import { KeyringAccountEntropyMnemonicOptionsStruct } from '@metamask/keyring-api';
6+
import { is } from '@metamask/superstruct';
7+
8+
/**
9+
* BIP-44 compatible account type.
10+
*/
11+
export type Bip44Account<Account extends KeyringAccount> = Account & {
12+
// We force the option type for those accounts. (That's how we identify
13+
// if an account is BIP-44 compatible).
14+
options: {
15+
entropy: KeyringAccountEntropyMnemonicOptions;
16+
};
17+
};
18+
19+
/**
20+
* Checks if an account is BIP-44 compatible.
21+
*
22+
* @param account - The account to be tested.
23+
* @returns True if the account is BIP-44 compatible.
24+
*/
25+
export function isBip44Account<Account extends KeyringAccount>(
26+
account: Account,
27+
): account is Bip44Account<Account> {
28+
// To be BIP-44 compatible, you just need to use this set of options:
29+
return is(
30+
account.options.entropy,
31+
KeyringAccountEntropyMnemonicOptionsStruct,
32+
);
33+
}

packages/account-api/src/api/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './bip44';
12
export * from './group';
23
export * from './wallet';
34
export type * from './provider';

packages/account-api/src/index.test.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import type {
44
EntropySourceId,
5+
KeyringAccountEntropyMnemonicOptions,
56
KeyringAccountOptions,
67
} from '@metamask/keyring-api';
78
import {
@@ -37,6 +38,7 @@ import {
3738
MultichainAccount,
3839
MultichainAccountWallet,
3940
getGroupIndexFromMultichainAccountId,
41+
isBip44Account,
4042
} from './api';
4143

4244
const mockEntropySource = 'mock-entropy-source';
@@ -651,4 +653,73 @@ describe('index', () => {
651653
).toThrow('Unable to extract group index');
652654
});
653655
});
656+
657+
describe('bip44', () => {
658+
describe('isBip44Account', () => {
659+
it('returns true if the account is BIP-44 compatible', () => {
660+
expect(isBip44Account(mockEvmAccount)).toBe(true);
661+
});
662+
663+
it.each([
664+
{
665+
tc: 'missing type',
666+
options: {
667+
entropy: {
668+
// Missing type.
669+
id: mockEntropySource,
670+
groupIndex: 0,
671+
derivationPath: '',
672+
},
673+
},
674+
},
675+
{
676+
tc: 'missing id',
677+
options: {
678+
entropy: {
679+
type: KeyringAccountEntropyTypeOption.Mnemonic,
680+
// Missing id.
681+
groupIndex: 0,
682+
derivationPath: '',
683+
},
684+
},
685+
},
686+
{
687+
tc: 'missing groupIndex',
688+
options: {
689+
entropy: {
690+
type: 'mnemonic',
691+
id: mockEntropySource,
692+
// Missing groupIndex.
693+
derivationPath: '',
694+
},
695+
},
696+
},
697+
{
698+
tc: 'missing derivationPath',
699+
options: {
700+
entropy: {
701+
type: 'mnemonic',
702+
id: mockEntropySource,
703+
groupIndex: 0,
704+
// Missing derivationPath.
705+
},
706+
},
707+
},
708+
])(
709+
'returns false if the account is not BIP-44 compatible with: $tc',
710+
({ options }) => {
711+
const account = {
712+
...mockEvmAccount,
713+
options: {
714+
entropy:
715+
// Force the error case here.
716+
options as unknown as KeyringAccountEntropyMnemonicOptions,
717+
},
718+
};
719+
720+
expect(isBip44Account(account)).toBe(false);
721+
},
722+
);
723+
});
724+
});
654725
});

yarn.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,7 @@ __metadata:
13651365
"@metamask/keyring-api": "workspace:^"
13661366
"@metamask/keyring-internal-api": "workspace:^"
13671367
"@metamask/keyring-utils": "workspace:^"
1368+
"@metamask/superstruct": "npm:^3.1.0"
13681369
"@ts-bridge/cli": "npm:^0.6.3"
13691370
"@types/jest": "npm:^29.5.12"
13701371
"@types/node": "npm:^20.12.12"

0 commit comments

Comments
 (0)