Skip to content

Commit 6180102

Browse files
committed
fix: manually address PR feedback
1 parent 34a7e9e commit 6180102

File tree

3 files changed

+57
-19
lines changed

3 files changed

+57
-19
lines changed

packages/keyring-eth-trezor/jest.config.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ module.exports = merge(baseConfig, {
2323
// An object that configures minimum threshold enforcement for coverage results
2424
coverageThreshold: {
2525
global: {
26-
branches: 61.18,
27-
functions: 93.24,
28-
lines: 93.59,
29-
statements: 93.68,
26+
branches: 62.65,
27+
functions: 93.15,
28+
lines: 93.57,
29+
statements: 93.66,
3030
},
3131
},
3232
});

packages/keyring-eth-trezor/src/trezor-keyring-v2.test.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -519,15 +519,25 @@ describe('TrezorKeyringV2', () => {
519519
).rejects.toThrow(/Invalid derivation path/u);
520520
});
521521

522-
it('throws error for unsupported HD path', async () => {
522+
it('throws error for unsupported HD path prefix', async () => {
523523
const { wrapper } = createEmptyWrapper();
524524

525-
// Valid format but unsupported base path for Trezor
525+
// Valid format but unsupported base path (coin type 100 instead of 60 or 1)
526526
await expect(
527527
wrapper.createAccounts(derivePathOptions(`m/44'/100'/0'/0/0`)),
528528
).rejects.toThrow(/Invalid derivation path/u);
529529
});
530530

531+
it('throws error for valid format but disallowed HD path', async () => {
532+
const { wrapper } = createEmptyWrapper();
533+
534+
// Path matches the regex (starts with m/44'/60') but the base path
535+
// m/44'/60'/1'/0 is not in ALLOWED_HD_PATHS
536+
await expect(
537+
wrapper.createAccounts(derivePathOptions(`m/44'/60'/1'/0/0`)),
538+
).rejects.toThrow(/Invalid derivation path/u);
539+
});
540+
531541
it('throws error for entropy source mismatch with derive-path', async () => {
532542
const { wrapper } = createEmptyWrapper();
533543

packages/keyring-eth-trezor/src/trezor-keyring-v2.ts

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,40 @@ const trezorKeyringV2Capabilities: KeyringCapabilities = {
4343
*/
4444
const BIP44_HD_PATH_PREFIX = `m/44'/60'/0'/0`;
4545

46+
/**
47+
* SLIP-0044 testnet HD path prefix constant.
48+
*/
49+
const SLIP0044_TESTNET_PATH = `m/44'/1'/0'/0`;
50+
51+
/**
52+
* Legacy MEW (MyEtherWallet) HD path prefix constant.
53+
*/
54+
const LEGACY_MEW_PATH = `m/44'/60'/0'`;
55+
4656
/**
4757
* Allowed HD paths for Trezor keyring.
4858
* These must match the keys in ALLOWED_HD_PATHS from trezor-keyring.ts.
4959
*/
50-
type AllowedHdPath = `m/44'/60'/0'/0` | `m/44'/60'/0'` | `m/44'/1'/0'/0`;
60+
const ALLOWED_HD_PATHS = [
61+
BIP44_HD_PATH_PREFIX,
62+
SLIP0044_TESTNET_PATH,
63+
LEGACY_MEW_PATH,
64+
] as const;
65+
66+
/**
67+
* Type representing one of the allowed Trezor HD paths.
68+
* Used by inner.setHdPath which expects one of these specific paths.
69+
*/
70+
type AllowedHdPath = (typeof ALLOWED_HD_PATHS)[number];
5171

5272
/**
5373
* Regex pattern for validating and parsing Trezor derivation paths.
54-
* Only matches the allowed Trezor HD paths from the legacy keyring:
55-
* - m/44'/60'/0'/0/{index} (BIP44 standard)
56-
* - m/44'/60'/0'/{index} (legacy MEW)
57-
* - m/44'/1'/0'/0/{index} (SLIP0044 testnet)
58-
*
74+
* Matches BIP-44 style paths: m/44'/{coin}'/{segments}/{index}
75+
* where coin is 60' (Ethereum) or 1' (testnet).
5976
* Captures: [1] = base path prefix, [2] = index
77+
* The prefix is then validated against ALLOWED_HD_PATHS.
6078
*/
61-
const DERIVATION_PATH_PATTERN =
62-
/^(m\/44'\/60'\/0'\/0|m\/44'\/60'\/0'|m\/44'\/1'\/0'\/0)\/(\d+)$/u;
79+
const DERIVATION_PATH_PATTERN = /^(m\/44'\/(?:60'|1')(?:\/\d+'?)*)\/(\d+)$/u;
6380

6481
/**
6582
* Concrete {@link KeyringV2} adapter for {@link TrezorKeyring}.
@@ -144,18 +161,29 @@ export class TrezorKeyringV2
144161
index: number;
145162
} {
146163
const match = derivationPath.match(DERIVATION_PATH_PATTERN);
147-
if (!match) {
164+
if (!match?.[1] || !match[2]) {
165+
throw new Error(
166+
`Invalid derivation path: ${derivationPath}. ` +
167+
`Expected format: {base}/{index} where base is one of: ` +
168+
`${ALLOWED_HD_PATHS.join(', ')}.`,
169+
);
170+
}
171+
172+
const basePath = match[1];
173+
const index = parseInt(match[2], 10);
174+
175+
// Validate the base path is one of the allowed paths
176+
if (!ALLOWED_HD_PATHS.includes(basePath as AllowedHdPath)) {
148177
throw new Error(
149178
`Invalid derivation path: ${derivationPath}. ` +
150179
`Expected format: {base}/{index} where base is one of: ` +
151-
`m/44'/60'/0'/0, m/44'/60'/0', m/44'/1'/0'/0.`,
180+
`${ALLOWED_HD_PATHS.join(', ')}.`,
152181
);
153182
}
154183

155-
// The regex guarantees match[1] is one of the allowed HD paths and match[2] is an index
156184
return {
157-
basePath: match[1] as AllowedHdPath,
158-
index: parseInt(match[2] as string, 10),
185+
basePath: basePath as AllowedHdPath,
186+
index,
159187
};
160188
}
161189

0 commit comments

Comments
 (0)