@metamask/eth-hd-keyring 13.1.0 → 14.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [14.0.0]
11
+
12
+ ### Added
13
+
14
+ - Add `./v2` subpath export for keyring v2 implementation ([#513](https://github.com/MetaMask/accounts/pull/513))
15
+ - `HdKeyring` and `HdKeyringOptions` are now available from `@metamask/eth-hd-keyring/v2`.
16
+
17
+ ### Changed
18
+
19
+ - **BREAKING:** Move and rename `HdKeyringV2` and `HdKeyringV2Options` to the new `./v2` subpath export ([#513](https://github.com/MetaMask/accounts/pull/513))
20
+ - `HdKeyringV2` is now `HdKeyring` from `@metamask/eth-hd-keyring/v2`.
21
+ - `HdKeyringV2Options` is now `HdKeyringOptions` from `@metamask/eth-hd-keyring/v2`.
22
+ - Bump `@metamask/utils` from `^11.10.0` to `^11.11.0` ([#483](https://github.com/MetaMask/accounts/pull/483))
23
+ - Bump `@metamask/account-api` from `^1.0.1` to `^1.0.2` ([#515](https://github.com/MetaMask/accounts/pull/515))
24
+ - Bump `@metamask/keyring-api` from `^22.0.0` to `^23.0.0` ([#515](https://github.com/MetaMask/accounts/pull/515))
25
+ - Bump `@metamask/keyring-sdk` from `^1.2.0` to `^2.0.0` ([#515](https://github.com/MetaMask/accounts/pull/515))
26
+
27
+ ## [13.1.1]
28
+
29
+ ### Changed
30
+
31
+ - Add new dependency `@metamask/keyring-sdk@1.2.0` ([#478](https://github.com/MetaMask/accounts/pull/478)), ([#482](https://github.com/MetaMask/accounts/pull/482)), ([#496](https://github.com/MetaMask/accounts/pull/496)), ([#509](https://github.com/MetaMask/accounts/pull/509))
32
+ - This package now contains the keyring v2 wrapper helpers (`EthKeyringWrapper`, `EthKeyringMethod`).
33
+ - The account ID (generated by `KeyringAccountRegistry`) are now deterministic for EVM addresses.
34
+ - Bump `@metamask/keyring-api` from `^21.6.0` to `^22.0.0` ([#482](https://github.com/MetaMask/accounts/pull/482))
35
+ - Bump `@metamask/account-api` from `^1.0.0` to `^1.0.1` ([#487](https://github.com/MetaMask/accounts/pull/487))
36
+ - Bump `@metamask/utils` from `^11.1.0` to `^11.10.0` ([#489](https://github.com/MetaMask/accounts/pull/489))
37
+
10
38
  ## [13.1.0]
11
39
 
12
40
  ### Added
@@ -235,7 +263,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
235
263
  - Deserialize method (and `HdKeyring` constructor by extension) can no longer be passed an options object containing a value for `numberOfAccounts` if it is not also containing a value for `mnemonic`.
236
264
  - Package name changed from `eth-hd-keyring` to `@metamask/eth-hd-keyring`.
237
265
 
238
- [Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@13.1.0...HEAD
266
+ [Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@14.0.0...HEAD
267
+ [14.0.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@13.1.1...@metamask/eth-hd-keyring@14.0.0
268
+ [13.1.1]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@13.1.0...@metamask/eth-hd-keyring@13.1.1
239
269
  [13.1.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@13.0.0...@metamask/eth-hd-keyring@13.1.0
240
270
  [13.0.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@12.1.0...@metamask/eth-hd-keyring@13.0.0
241
271
  [12.1.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@12.0.0...@metamask/eth-hd-keyring@12.1.0
package/dist/index.cjs CHANGED
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HdKeyringV2 = exports.HdKeyring = void 0;
3
+ exports.HdKeyring = void 0;
4
4
  var hd_keyring_1 = require("./hd-keyring.cjs");
5
5
  Object.defineProperty(exports, "HdKeyring", { enumerable: true, get: function () { return hd_keyring_1.HdKeyring; } });
6
- var hd_keyring_v2_1 = require("./hd-keyring-v2.cjs");
7
- Object.defineProperty(exports, "HdKeyringV2", { enumerable: true, get: function () { return hd_keyring_v2_1.HdKeyringV2; } });
8
6
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+CAAyC;AAAhC,uGAAA,SAAS,OAAA;AAOlB,qDAAuE;AAA9D,4GAAA,WAAW,OAAA","sourcesContent":["export { HdKeyring } from './hd-keyring';\nexport type {\n SerializedHDKeyringState,\n DeserializableHDKeyringState,\n HDKeyringOptions,\n HDKeyringAccountSelectionOptions,\n} from './hd-keyring';\nexport { HdKeyringV2, type HdKeyringV2Options } from './hd-keyring-v2';\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+CAAyC;AAAhC,uGAAA,SAAS,OAAA","sourcesContent":["export { HdKeyring } from './hd-keyring';\nexport type {\n SerializedHDKeyringState,\n DeserializableHDKeyringState,\n HDKeyringOptions,\n HDKeyringAccountSelectionOptions,\n} from './hd-keyring';\n"]}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,3 @@
1
1
  export { HdKeyring } from "./hd-keyring.cjs";
2
2
  export type { SerializedHDKeyringState, DeserializableHDKeyringState, HDKeyringOptions, HDKeyringAccountSelectionOptions, } from "./hd-keyring.cjs";
3
- export { HdKeyringV2, type HdKeyringV2Options } from "./hd-keyring-v2.cjs";
4
3
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,yBAAqB;AACzC,YAAY,EACV,wBAAwB,EACxB,4BAA4B,EAC5B,gBAAgB,EAChB,gCAAgC,GACjC,yBAAqB;AACtB,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,4BAAwB"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,yBAAqB;AACzC,YAAY,EACV,wBAAwB,EACxB,4BAA4B,EAC5B,gBAAgB,EAChB,gCAAgC,GACjC,yBAAqB"}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,3 @@
1
1
  export { HdKeyring } from "./hd-keyring.mjs";
2
2
  export type { SerializedHDKeyringState, DeserializableHDKeyringState, HDKeyringOptions, HDKeyringAccountSelectionOptions, } from "./hd-keyring.mjs";
3
- export { HdKeyringV2, type HdKeyringV2Options } from "./hd-keyring-v2.mjs";
4
3
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,yBAAqB;AACzC,YAAY,EACV,wBAAwB,EACxB,4BAA4B,EAC5B,gBAAgB,EAChB,gCAAgC,GACjC,yBAAqB;AACtB,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,4BAAwB"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,yBAAqB;AACzC,YAAY,EACV,wBAAwB,EACxB,4BAA4B,EAC5B,gBAAgB,EAChB,gCAAgC,GACjC,yBAAqB"}
package/dist/index.mjs CHANGED
@@ -1,3 +1,2 @@
1
1
  export { HdKeyring } from "./hd-keyring.mjs";
2
- export { HdKeyringV2 } from "./hd-keyring-v2.mjs";
3
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,yBAAqB;AAOzC,OAAO,EAAE,WAAW,EAA2B,4BAAwB","sourcesContent":["export { HdKeyring } from './hd-keyring';\nexport type {\n SerializedHDKeyringState,\n DeserializableHDKeyringState,\n HDKeyringOptions,\n HDKeyringAccountSelectionOptions,\n} from './hd-keyring';\nexport { HdKeyringV2, type HdKeyringV2Options } from './hd-keyring-v2';\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,yBAAqB","sourcesContent":["export { HdKeyring } from './hd-keyring';\nexport type {\n SerializedHDKeyringState,\n DeserializableHDKeyringState,\n HDKeyringOptions,\n HDKeyringAccountSelectionOptions,\n} from './hd-keyring';\n"]}
@@ -4,10 +4,12 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
4
4
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
5
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
6
  };
7
- var _HdKeyringV2_instances, _HdKeyringV2_isLastAccount, _HdKeyringV2_createKeyringAccount;
7
+ var _HdKeyring_instances, _HdKeyring_isLastAccount, _HdKeyring_createKeyringAccount;
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.HdKeyringV2 = void 0;
9
+ exports.HdKeyring = void 0;
10
10
  const keyring_api_1 = require("@metamask/keyring-api");
11
+ const v2_1 = require("@metamask/keyring-api/v2");
12
+ const v2_2 = require("@metamask/keyring-sdk/v2");
11
13
  const utils_1 = require("@metamask/utils");
12
14
  /**
13
15
  * Methods supported by HD keyring EOA accounts.
@@ -20,28 +22,28 @@ const HD_KEYRING_METHODS = [
20
22
  keyring_api_1.EthMethod.SignTypedDataV1,
21
23
  keyring_api_1.EthMethod.SignTypedDataV3,
22
24
  keyring_api_1.EthMethod.SignTypedDataV4,
23
- keyring_api_1.EthKeyringMethod.Decrypt,
24
- keyring_api_1.EthKeyringMethod.GetEncryptionPublicKey,
25
- keyring_api_1.EthKeyringMethod.GetAppKeyAddress,
26
- keyring_api_1.EthKeyringMethod.SignEip7702Authorization,
25
+ v2_2.EthKeyringMethod.Decrypt,
26
+ v2_2.EthKeyringMethod.GetEncryptionPublicKey,
27
+ v2_2.EthKeyringMethod.GetAppKeyAddress,
28
+ v2_2.EthKeyringMethod.SignEip7702Authorization,
27
29
  ];
28
- const hdKeyringV2Capabilities = {
30
+ const hdKeyringCapabilities = {
29
31
  scopes: [keyring_api_1.EthScope.Eoa],
30
32
  bip44: {
31
33
  deriveIndex: true,
32
34
  },
33
35
  privateKey: {
34
- exportFormats: [{ encoding: keyring_api_1.PrivateKeyEncoding.Hexadecimal }],
36
+ exportFormats: [{ encoding: v2_1.PrivateKeyEncoding.Hexadecimal }],
35
37
  },
36
38
  };
37
- class HdKeyringV2 extends keyring_api_1.EthKeyringWrapper {
39
+ class HdKeyring extends v2_2.EthKeyringWrapper {
38
40
  constructor(options) {
39
41
  super({
40
- type: keyring_api_1.KeyringType.Hd,
42
+ type: v2_1.KeyringType.Hd,
41
43
  inner: options.legacyKeyring,
42
- capabilities: hdKeyringV2Capabilities,
44
+ capabilities: hdKeyringCapabilities,
43
45
  });
44
- _HdKeyringV2_instances.add(this);
46
+ _HdKeyring_instances.add(this);
45
47
  this.entropySource = options.entropySource;
46
48
  }
47
49
  async getAccounts() {
@@ -56,7 +58,7 @@ class HdKeyringV2 extends keyring_api_1.EthKeyringWrapper {
56
58
  }
57
59
  }
58
60
  // Create and register the account if not already cached
59
- return __classPrivateFieldGet(this, _HdKeyringV2_instances, "m", _HdKeyringV2_createKeyringAccount).call(this, address, addressIndex);
61
+ return __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_createKeyringAccount).call(this, address, addressIndex);
60
62
  });
61
63
  }
62
64
  async createAccounts(options) {
@@ -90,7 +92,7 @@ class HdKeyringV2 extends keyring_api_1.EthKeyringWrapper {
90
92
  if (!newAddress) {
91
93
  throw new Error('Failed to create new account');
92
94
  }
93
- const newAccount = __classPrivateFieldGet(this, _HdKeyringV2_instances, "m", _HdKeyringV2_createKeyringAccount).call(this, newAddress, targetIndex);
95
+ const newAccount = __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_createKeyringAccount).call(this, newAddress, targetIndex);
94
96
  return [newAccount];
95
97
  });
96
98
  }
@@ -108,7 +110,7 @@ class HdKeyringV2 extends keyring_api_1.EthKeyringWrapper {
108
110
  const hexAddress = this.toHexAddress(address);
109
111
  // Assert that the account to delete is the last one in the inner keyring
110
112
  // We check against the inner keyring directly to avoid stale registry issues
111
- if (!(await __classPrivateFieldGet(this, _HdKeyringV2_instances, "m", _HdKeyringV2_isLastAccount).call(this, address))) {
113
+ if (!(await __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_isLastAccount).call(this, address))) {
112
114
  throw new Error('Can only delete the last account in the HD keyring due to derivation index constraints.');
113
115
  }
114
116
  // Remove from the legacy keyring
@@ -127,9 +129,9 @@ class HdKeyringV2 extends keyring_api_1.EthKeyringWrapper {
127
129
  async exportAccount(accountId, options) {
128
130
  const account = await this.getAccount(accountId);
129
131
  // Validate encoding - we only support hexadecimal for Ethereum keys
130
- const requestedEncoding = options?.encoding ?? keyring_api_1.PrivateKeyEncoding.Hexadecimal;
131
- if (requestedEncoding !== keyring_api_1.PrivateKeyEncoding.Hexadecimal) {
132
- throw new Error(`Unsupported encoding for Ethereum HD keyring: ${requestedEncoding}. Only '${keyring_api_1.PrivateKeyEncoding.Hexadecimal}' is supported.`);
132
+ const requestedEncoding = options?.encoding ?? v2_1.PrivateKeyEncoding.Hexadecimal;
133
+ if (requestedEncoding !== v2_1.PrivateKeyEncoding.Hexadecimal) {
134
+ throw new Error(`Unsupported encoding for Ethereum HD keyring: ${requestedEncoding}. Only '${v2_1.PrivateKeyEncoding.Hexadecimal}' is supported.`);
133
135
  }
134
136
  // The legacy HdKeyring returns a hex string without 0x prefix.
135
137
  const privateKeyWithout0x = await this.inner.exportAccount(this.toHexAddress(account.address));
@@ -137,12 +139,12 @@ class HdKeyringV2 extends keyring_api_1.EthKeyringWrapper {
137
139
  return {
138
140
  type: 'private-key',
139
141
  privateKey,
140
- encoding: keyring_api_1.PrivateKeyEncoding.Hexadecimal,
142
+ encoding: v2_1.PrivateKeyEncoding.Hexadecimal,
141
143
  };
142
144
  }
143
145
  }
144
- exports.HdKeyringV2 = HdKeyringV2;
145
- _HdKeyringV2_instances = new WeakSet(), _HdKeyringV2_isLastAccount =
146
+ exports.HdKeyring = HdKeyring;
147
+ _HdKeyring_instances = new WeakSet(), _HdKeyring_isLastAccount =
146
148
  /**
147
149
  * Checks if the given address is the last account in the inner keyring.
148
150
  * This compares against the actual inner keyring state, not the registry,
@@ -151,11 +153,11 @@ _HdKeyringV2_instances = new WeakSet(), _HdKeyringV2_isLastAccount =
151
153
  * @param address - The address to check.
152
154
  * @returns True if this is the last account in the inner keyring.
153
155
  */
154
- async function _HdKeyringV2_isLastAccount(address) {
156
+ async function _HdKeyring_isLastAccount(address) {
155
157
  const innerAddresses = await this.inner.getAccounts();
156
158
  const lastAddress = innerAddresses[innerAddresses.length - 1];
157
159
  return address === lastAddress;
158
- }, _HdKeyringV2_createKeyringAccount = function _HdKeyringV2_createKeyringAccount(address, addressIndex) {
160
+ }, _HdKeyring_createKeyringAccount = function _HdKeyring_createKeyringAccount(address, addressIndex) {
159
161
  const id = this.registry.register(address);
160
162
  const account = {
161
163
  id,
@@ -177,4 +179,4 @@ async function _HdKeyringV2_isLastAccount(address) {
177
179
  this.registry.set(account);
178
180
  return account;
179
181
  };
180
- //# sourceMappingURL=hd-keyring-v2.cjs.map
182
+ //# sourceMappingURL=hd-keyring.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hd-keyring.cjs","sourceRoot":"","sources":["../../src/v2/hd-keyring.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Bip44Account } from '@metamask/account-api';\nimport {\n EthAccountType,\n EthMethod,\n EthScope,\n type KeyringAccount,\n KeyringAccountEntropyTypeOption,\n type EntropySourceId,\n} from '@metamask/keyring-api';\nimport {\n type CreateAccountOptions,\n type ExportAccountOptions,\n type ExportedAccount,\n type KeyringCapabilities,\n type Keyring,\n KeyringType,\n PrivateKeyEncoding,\n} from '@metamask/keyring-api/v2';\nimport { EthKeyringMethod, EthKeyringWrapper } from '@metamask/keyring-sdk/v2';\nimport type { AccountId } from '@metamask/keyring-utils';\nimport { add0x, type Hex } from '@metamask/utils';\n\nimport type { HdKeyring as LegacyHdKeyring } from '../hd-keyring';\n\n/**\n * Methods supported by HD keyring EOA accounts.\n * HD keyrings support all standard signing methods plus encryption and app keys.\n */\nconst HD_KEYRING_METHODS = [\n EthMethod.SignTransaction,\n EthMethod.Sign,\n EthMethod.PersonalSign,\n EthMethod.SignTypedDataV1,\n EthMethod.SignTypedDataV3,\n EthMethod.SignTypedDataV4,\n EthKeyringMethod.Decrypt,\n EthKeyringMethod.GetEncryptionPublicKey,\n EthKeyringMethod.GetAppKeyAddress,\n EthKeyringMethod.SignEip7702Authorization,\n];\n\nconst hdKeyringCapabilities: KeyringCapabilities = {\n scopes: [EthScope.Eoa],\n bip44: {\n deriveIndex: true,\n },\n privateKey: {\n exportFormats: [{ encoding: PrivateKeyEncoding.Hexadecimal }],\n },\n};\n\n/**\n * Concrete {@link Keyring} adapter for {@link HdKeyring}.\n *\n * This wrapper exposes the accounts and signing capabilities of the legacy\n * HD keyring via the unified V2 interface.\n */\nexport type HdKeyringOptions = {\n legacyKeyring: LegacyHdKeyring;\n entropySource: EntropySourceId;\n};\n\nexport class HdKeyring\n extends EthKeyringWrapper<LegacyHdKeyring, Bip44Account<KeyringAccount>>\n implements Keyring\n{\n protected readonly entropySource: EntropySourceId;\n\n constructor(options: HdKeyringOptions) {\n super({\n type: KeyringType.Hd,\n inner: options.legacyKeyring,\n capabilities: hdKeyringCapabilities,\n });\n this.entropySource = options.entropySource;\n }\n\n /**\n * Checks if the given address is the last account in the inner keyring.\n * This compares against the actual inner keyring state, not the registry,\n * to avoid issues with stale registry entries.\n *\n * @param address - The address to check.\n * @returns True if this is the last account in the inner keyring.\n */\n async #isLastAccount(address: string): Promise<boolean> {\n const innerAddresses = await this.inner.getAccounts();\n const lastAddress = innerAddresses[innerAddresses.length - 1];\n return address === lastAddress;\n }\n\n /**\n * Creates a KeyringAccount object for the given address and index.\n *\n * @param address - The account address.\n * @param addressIndex - The account index in the HD path.\n * @returns The created KeyringAccount.\n */\n #createKeyringAccount(\n address: Hex,\n addressIndex: number,\n ): Bip44Account<KeyringAccount> {\n const id = this.registry.register(address);\n\n const account: Bip44Account<KeyringAccount> = {\n id,\n type: EthAccountType.Eoa,\n address,\n scopes: [...this.capabilities.scopes],\n methods: [...HD_KEYRING_METHODS],\n options: {\n entropy: {\n type: KeyringAccountEntropyTypeOption.Mnemonic,\n id: this.entropySource,\n groupIndex: addressIndex,\n derivationPath: `${this.inner.hdPath}/${addressIndex}`,\n },\n exportable: true,\n },\n };\n\n // Add the account to the registry\n this.registry.set(account);\n\n return account;\n }\n\n async getAccounts(): Promise<Bip44Account<KeyringAccount>[]> {\n const addresses = await this.inner.getAccounts();\n\n return addresses.map((address, addressIndex) => {\n // Check if we already have this account in the registry\n const existingId = this.registry.getAccountId(address);\n if (existingId) {\n const cached = this.registry.get(existingId);\n if (cached) {\n return cached;\n }\n }\n\n // Create and register the account if not already cached\n return this.#createKeyringAccount(address, addressIndex);\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withLock(async () => {\n // For HD keyring, we only support BIP-44 derive index\n if (options.type !== 'bip44:derive-index') {\n throw new Error(\n `Unsupported account creation type for HdKeyring: ${options.type}`,\n );\n }\n\n // Validate that the entropy source matches this keyring's entropy source\n if (options.entropySource !== this.entropySource) {\n throw new Error(\n `Entropy source mismatch: expected '${this.entropySource}', got '${options.entropySource}'`,\n );\n }\n\n // Sync with the inner keyring state in case it was modified externally\n // This ensures our cache is up-to-date before we make changes\n const currentAccounts = await this.getAccounts();\n const currentCount = currentAccounts.length;\n const targetIndex = options.groupIndex;\n\n // Check if an account at this index already exists\n // Since only the last account can be deleted, array position always equals groupIndex\n const existingAccount = currentAccounts[targetIndex];\n if (existingAccount) {\n return [existingAccount];\n }\n\n // Only allow derivation of the next account in sequence\n if (targetIndex !== currentCount) {\n throw new Error(\n `Can only create the next account in sequence. ` +\n `Expected groupIndex ${currentCount}, got ${targetIndex}.`,\n );\n }\n\n // Add the next account\n const [newAddress] = await this.inner.addAccounts(1);\n\n if (!newAddress) {\n throw new Error('Failed to create new account');\n }\n\n const newAccount = this.#createKeyringAccount(newAddress, targetIndex);\n\n return [newAccount];\n });\n }\n\n /**\n * Delete an account from the keyring.\n *\n * ⚠️ Warning: Only deleting the last account is possible.\n *\n * @param accountId - The account ID to delete.\n */\n async deleteAccount(accountId: AccountId): Promise<void> {\n await this.withLock(async () => {\n // Get the account first, before any registry operations\n const { address } = await this.getAccount(accountId);\n const hexAddress = this.toHexAddress(address);\n\n // Assert that the account to delete is the last one in the inner keyring\n // We check against the inner keyring directly to avoid stale registry issues\n if (!(await this.#isLastAccount(address))) {\n throw new Error(\n 'Can only delete the last account in the HD keyring due to derivation index constraints.',\n );\n }\n\n // Remove from the legacy keyring\n this.inner.removeAccount(hexAddress);\n\n // Remove from the registry\n this.registry.delete(accountId);\n });\n }\n\n /**\n * Export the private key for an account in hexadecimal format.\n *\n * @param accountId - The ID of the account to export.\n * @param options - Export options (only hexadecimal encoding is supported).\n * @returns The exported account with private key.\n */\n async exportAccount(\n accountId: AccountId,\n options?: ExportAccountOptions,\n ): Promise<ExportedAccount> {\n const account = await this.getAccount(accountId);\n\n // Validate encoding - we only support hexadecimal for Ethereum keys\n const requestedEncoding =\n options?.encoding ?? PrivateKeyEncoding.Hexadecimal;\n\n if (requestedEncoding !== PrivateKeyEncoding.Hexadecimal) {\n throw new Error(\n `Unsupported encoding for Ethereum HD keyring: ${requestedEncoding}. Only '${PrivateKeyEncoding.Hexadecimal}' is supported.`,\n );\n }\n\n // The legacy HdKeyring returns a hex string without 0x prefix.\n const privateKeyWithout0x = await this.inner.exportAccount(\n this.toHexAddress(account.address),\n );\n const privateKey = add0x(privateKeyWithout0x);\n\n return {\n type: 'private-key',\n privateKey,\n encoding: PrivateKeyEncoding.Hexadecimal,\n };\n }\n}\n"]}
@@ -1,21 +1,23 @@
1
1
  import type { Bip44Account } from "@metamask/account-api";
2
- import { type CreateAccountOptions, EthKeyringWrapper, type ExportAccountOptions, type ExportedAccount, type KeyringAccount, type KeyringV2, type EntropySourceId } from "@metamask/keyring-api";
2
+ import { type KeyringAccount, type EntropySourceId } from "@metamask/keyring-api";
3
+ import { type CreateAccountOptions, type ExportAccountOptions, type ExportedAccount, type Keyring } from "@metamask/keyring-api/v2";
4
+ import { EthKeyringWrapper } from "@metamask/keyring-sdk/v2";
3
5
  import type { AccountId } from "@metamask/keyring-utils";
4
- import type { HdKeyring } from "./hd-keyring.mjs";
6
+ import type { HdKeyring as LegacyHdKeyring } from "../hd-keyring.cjs";
5
7
  /**
6
- * Concrete {@link KeyringV2} adapter for {@link HdKeyring}.
8
+ * Concrete {@link Keyring} adapter for {@link HdKeyring}.
7
9
  *
8
10
  * This wrapper exposes the accounts and signing capabilities of the legacy
9
11
  * HD keyring via the unified V2 interface.
10
12
  */
11
- export type HdKeyringV2Options = {
12
- legacyKeyring: HdKeyring;
13
+ export type HdKeyringOptions = {
14
+ legacyKeyring: LegacyHdKeyring;
13
15
  entropySource: EntropySourceId;
14
16
  };
15
- export declare class HdKeyringV2 extends EthKeyringWrapper<HdKeyring, Bip44Account<KeyringAccount>> implements KeyringV2 {
17
+ export declare class HdKeyring extends EthKeyringWrapper<LegacyHdKeyring, Bip44Account<KeyringAccount>> implements Keyring {
16
18
  #private;
17
19
  protected readonly entropySource: EntropySourceId;
18
- constructor(options: HdKeyringV2Options);
20
+ constructor(options: HdKeyringOptions);
19
21
  getAccounts(): Promise<Bip44Account<KeyringAccount>[]>;
20
22
  createAccounts(options: CreateAccountOptions): Promise<Bip44Account<KeyringAccount>[]>;
21
23
  /**
@@ -35,4 +37,4 @@ export declare class HdKeyringV2 extends EthKeyringWrapper<HdKeyring, Bip44Accou
35
37
  */
36
38
  exportAccount(accountId: AccountId, options?: ExportAccountOptions): Promise<ExportedAccount>;
37
39
  }
38
- //# sourceMappingURL=hd-keyring-v2.d.mts.map
40
+ //# sourceMappingURL=hd-keyring.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hd-keyring.d.cts","sourceRoot":"","sources":["../../src/v2/hd-keyring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,EAIL,KAAK,cAAc,EAEnB,KAAK,eAAe,EACrB,8BAA8B;AAC/B,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EAEpB,KAAK,OAAO,EAGb,iCAAiC;AAClC,OAAO,EAAoB,iBAAiB,EAAE,iCAAiC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,gCAAgC;AAGzD,OAAO,KAAK,EAAE,SAAS,IAAI,eAAe,EAAE,0BAAsB;AA6BlE;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,eAAe,CAAC;IAC/B,aAAa,EAAE,eAAe,CAAC;CAChC,CAAC;AAEF,qBAAa,SACX,SAAQ,iBAAiB,CAAC,eAAe,EAAE,YAAY,CAAC,cAAc,CAAC,CACvE,YAAW,OAAO;;IAElB,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,eAAe,CAAC;gBAEtC,OAAO,EAAE,gBAAgB;IA2D/B,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAkBtD,cAAc,CAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAkD1C;;;;;;OAMG;IACG,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBxD;;;;;;OAMG;IACG,aAAa,CACjB,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,eAAe,CAAC;CAyB5B"}
@@ -1,21 +1,23 @@
1
1
  import type { Bip44Account } from "@metamask/account-api";
2
- import { type CreateAccountOptions, EthKeyringWrapper, type ExportAccountOptions, type ExportedAccount, type KeyringAccount, type KeyringV2, type EntropySourceId } from "@metamask/keyring-api";
2
+ import { type KeyringAccount, type EntropySourceId } from "@metamask/keyring-api";
3
+ import { type CreateAccountOptions, type ExportAccountOptions, type ExportedAccount, type Keyring } from "@metamask/keyring-api/v2";
4
+ import { EthKeyringWrapper } from "@metamask/keyring-sdk/v2";
3
5
  import type { AccountId } from "@metamask/keyring-utils";
4
- import type { HdKeyring } from "./hd-keyring.cjs";
6
+ import type { HdKeyring as LegacyHdKeyring } from "../hd-keyring.mjs";
5
7
  /**
6
- * Concrete {@link KeyringV2} adapter for {@link HdKeyring}.
8
+ * Concrete {@link Keyring} adapter for {@link HdKeyring}.
7
9
  *
8
10
  * This wrapper exposes the accounts and signing capabilities of the legacy
9
11
  * HD keyring via the unified V2 interface.
10
12
  */
11
- export type HdKeyringV2Options = {
12
- legacyKeyring: HdKeyring;
13
+ export type HdKeyringOptions = {
14
+ legacyKeyring: LegacyHdKeyring;
13
15
  entropySource: EntropySourceId;
14
16
  };
15
- export declare class HdKeyringV2 extends EthKeyringWrapper<HdKeyring, Bip44Account<KeyringAccount>> implements KeyringV2 {
17
+ export declare class HdKeyring extends EthKeyringWrapper<LegacyHdKeyring, Bip44Account<KeyringAccount>> implements Keyring {
16
18
  #private;
17
19
  protected readonly entropySource: EntropySourceId;
18
- constructor(options: HdKeyringV2Options);
20
+ constructor(options: HdKeyringOptions);
19
21
  getAccounts(): Promise<Bip44Account<KeyringAccount>[]>;
20
22
  createAccounts(options: CreateAccountOptions): Promise<Bip44Account<KeyringAccount>[]>;
21
23
  /**
@@ -35,4 +37,4 @@ export declare class HdKeyringV2 extends EthKeyringWrapper<HdKeyring, Bip44Accou
35
37
  */
36
38
  exportAccount(accountId: AccountId, options?: ExportAccountOptions): Promise<ExportedAccount>;
37
39
  }
38
- //# sourceMappingURL=hd-keyring-v2.d.cts.map
40
+ //# sourceMappingURL=hd-keyring.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hd-keyring.d.mts","sourceRoot":"","sources":["../../src/v2/hd-keyring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,EAIL,KAAK,cAAc,EAEnB,KAAK,eAAe,EACrB,8BAA8B;AAC/B,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EAEpB,KAAK,OAAO,EAGb,iCAAiC;AAClC,OAAO,EAAoB,iBAAiB,EAAE,iCAAiC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,gCAAgC;AAGzD,OAAO,KAAK,EAAE,SAAS,IAAI,eAAe,EAAE,0BAAsB;AA6BlE;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,eAAe,CAAC;IAC/B,aAAa,EAAE,eAAe,CAAC;CAChC,CAAC;AAEF,qBAAa,SACX,SAAQ,iBAAiB,CAAC,eAAe,EAAE,YAAY,CAAC,cAAc,CAAC,CACvE,YAAW,OAAO;;IAElB,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,eAAe,CAAC;gBAEtC,OAAO,EAAE,gBAAgB;IA2D/B,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAkBtD,cAAc,CAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAkD1C;;;;;;OAMG;IACG,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBxD;;;;;;OAMG;IACG,aAAa,CACjB,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,eAAe,CAAC;CAyB5B"}
@@ -3,8 +3,10 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
3
3
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
4
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
5
  };
6
- var _HdKeyringV2_instances, _HdKeyringV2_isLastAccount, _HdKeyringV2_createKeyringAccount;
7
- import { EthAccountType, EthKeyringMethod, EthKeyringWrapper, EthMethod, EthScope, KeyringAccountEntropyTypeOption, KeyringType, PrivateKeyEncoding } from "@metamask/keyring-api";
6
+ var _HdKeyring_instances, _HdKeyring_isLastAccount, _HdKeyring_createKeyringAccount;
7
+ import { EthAccountType, EthMethod, EthScope, KeyringAccountEntropyTypeOption } from "@metamask/keyring-api";
8
+ import { KeyringType, PrivateKeyEncoding } from "@metamask/keyring-api/v2";
9
+ import { EthKeyringMethod, EthKeyringWrapper } from "@metamask/keyring-sdk/v2";
8
10
  import { add0x } from "@metamask/utils";
9
11
  /**
10
12
  * Methods supported by HD keyring EOA accounts.
@@ -22,7 +24,7 @@ const HD_KEYRING_METHODS = [
22
24
  EthKeyringMethod.GetAppKeyAddress,
23
25
  EthKeyringMethod.SignEip7702Authorization,
24
26
  ];
25
- const hdKeyringV2Capabilities = {
27
+ const hdKeyringCapabilities = {
26
28
  scopes: [EthScope.Eoa],
27
29
  bip44: {
28
30
  deriveIndex: true,
@@ -31,14 +33,14 @@ const hdKeyringV2Capabilities = {
31
33
  exportFormats: [{ encoding: PrivateKeyEncoding.Hexadecimal }],
32
34
  },
33
35
  };
34
- export class HdKeyringV2 extends EthKeyringWrapper {
36
+ export class HdKeyring extends EthKeyringWrapper {
35
37
  constructor(options) {
36
38
  super({
37
39
  type: KeyringType.Hd,
38
40
  inner: options.legacyKeyring,
39
- capabilities: hdKeyringV2Capabilities,
41
+ capabilities: hdKeyringCapabilities,
40
42
  });
41
- _HdKeyringV2_instances.add(this);
43
+ _HdKeyring_instances.add(this);
42
44
  this.entropySource = options.entropySource;
43
45
  }
44
46
  async getAccounts() {
@@ -53,7 +55,7 @@ export class HdKeyringV2 extends EthKeyringWrapper {
53
55
  }
54
56
  }
55
57
  // Create and register the account if not already cached
56
- return __classPrivateFieldGet(this, _HdKeyringV2_instances, "m", _HdKeyringV2_createKeyringAccount).call(this, address, addressIndex);
58
+ return __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_createKeyringAccount).call(this, address, addressIndex);
57
59
  });
58
60
  }
59
61
  async createAccounts(options) {
@@ -87,7 +89,7 @@ export class HdKeyringV2 extends EthKeyringWrapper {
87
89
  if (!newAddress) {
88
90
  throw new Error('Failed to create new account');
89
91
  }
90
- const newAccount = __classPrivateFieldGet(this, _HdKeyringV2_instances, "m", _HdKeyringV2_createKeyringAccount).call(this, newAddress, targetIndex);
92
+ const newAccount = __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_createKeyringAccount).call(this, newAddress, targetIndex);
91
93
  return [newAccount];
92
94
  });
93
95
  }
@@ -105,7 +107,7 @@ export class HdKeyringV2 extends EthKeyringWrapper {
105
107
  const hexAddress = this.toHexAddress(address);
106
108
  // Assert that the account to delete is the last one in the inner keyring
107
109
  // We check against the inner keyring directly to avoid stale registry issues
108
- if (!(await __classPrivateFieldGet(this, _HdKeyringV2_instances, "m", _HdKeyringV2_isLastAccount).call(this, address))) {
110
+ if (!(await __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_isLastAccount).call(this, address))) {
109
111
  throw new Error('Can only delete the last account in the HD keyring due to derivation index constraints.');
110
112
  }
111
113
  // Remove from the legacy keyring
@@ -138,7 +140,7 @@ export class HdKeyringV2 extends EthKeyringWrapper {
138
140
  };
139
141
  }
140
142
  }
141
- _HdKeyringV2_instances = new WeakSet(), _HdKeyringV2_isLastAccount =
143
+ _HdKeyring_instances = new WeakSet(), _HdKeyring_isLastAccount =
142
144
  /**
143
145
  * Checks if the given address is the last account in the inner keyring.
144
146
  * This compares against the actual inner keyring state, not the registry,
@@ -147,11 +149,11 @@ _HdKeyringV2_instances = new WeakSet(), _HdKeyringV2_isLastAccount =
147
149
  * @param address - The address to check.
148
150
  * @returns True if this is the last account in the inner keyring.
149
151
  */
150
- async function _HdKeyringV2_isLastAccount(address) {
152
+ async function _HdKeyring_isLastAccount(address) {
151
153
  const innerAddresses = await this.inner.getAccounts();
152
154
  const lastAddress = innerAddresses[innerAddresses.length - 1];
153
155
  return address === lastAddress;
154
- }, _HdKeyringV2_createKeyringAccount = function _HdKeyringV2_createKeyringAccount(address, addressIndex) {
156
+ }, _HdKeyring_createKeyringAccount = function _HdKeyring_createKeyringAccount(address, addressIndex) {
155
157
  const id = this.registry.register(address);
156
158
  const account = {
157
159
  id,
@@ -173,4 +175,4 @@ async function _HdKeyringV2_isLastAccount(address) {
173
175
  this.registry.set(account);
174
176
  return account;
175
177
  };
176
- //# sourceMappingURL=hd-keyring-v2.mjs.map
178
+ //# sourceMappingURL=hd-keyring.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hd-keyring.mjs","sourceRoot":"","sources":["../../src/v2/hd-keyring.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Bip44Account } from '@metamask/account-api';\nimport {\n EthAccountType,\n EthMethod,\n EthScope,\n type KeyringAccount,\n KeyringAccountEntropyTypeOption,\n type EntropySourceId,\n} from '@metamask/keyring-api';\nimport {\n type CreateAccountOptions,\n type ExportAccountOptions,\n type ExportedAccount,\n type KeyringCapabilities,\n type Keyring,\n KeyringType,\n PrivateKeyEncoding,\n} from '@metamask/keyring-api/v2';\nimport { EthKeyringMethod, EthKeyringWrapper } from '@metamask/keyring-sdk/v2';\nimport type { AccountId } from '@metamask/keyring-utils';\nimport { add0x, type Hex } from '@metamask/utils';\n\nimport type { HdKeyring as LegacyHdKeyring } from '../hd-keyring';\n\n/**\n * Methods supported by HD keyring EOA accounts.\n * HD keyrings support all standard signing methods plus encryption and app keys.\n */\nconst HD_KEYRING_METHODS = [\n EthMethod.SignTransaction,\n EthMethod.Sign,\n EthMethod.PersonalSign,\n EthMethod.SignTypedDataV1,\n EthMethod.SignTypedDataV3,\n EthMethod.SignTypedDataV4,\n EthKeyringMethod.Decrypt,\n EthKeyringMethod.GetEncryptionPublicKey,\n EthKeyringMethod.GetAppKeyAddress,\n EthKeyringMethod.SignEip7702Authorization,\n];\n\nconst hdKeyringCapabilities: KeyringCapabilities = {\n scopes: [EthScope.Eoa],\n bip44: {\n deriveIndex: true,\n },\n privateKey: {\n exportFormats: [{ encoding: PrivateKeyEncoding.Hexadecimal }],\n },\n};\n\n/**\n * Concrete {@link Keyring} adapter for {@link HdKeyring}.\n *\n * This wrapper exposes the accounts and signing capabilities of the legacy\n * HD keyring via the unified V2 interface.\n */\nexport type HdKeyringOptions = {\n legacyKeyring: LegacyHdKeyring;\n entropySource: EntropySourceId;\n};\n\nexport class HdKeyring\n extends EthKeyringWrapper<LegacyHdKeyring, Bip44Account<KeyringAccount>>\n implements Keyring\n{\n protected readonly entropySource: EntropySourceId;\n\n constructor(options: HdKeyringOptions) {\n super({\n type: KeyringType.Hd,\n inner: options.legacyKeyring,\n capabilities: hdKeyringCapabilities,\n });\n this.entropySource = options.entropySource;\n }\n\n /**\n * Checks if the given address is the last account in the inner keyring.\n * This compares against the actual inner keyring state, not the registry,\n * to avoid issues with stale registry entries.\n *\n * @param address - The address to check.\n * @returns True if this is the last account in the inner keyring.\n */\n async #isLastAccount(address: string): Promise<boolean> {\n const innerAddresses = await this.inner.getAccounts();\n const lastAddress = innerAddresses[innerAddresses.length - 1];\n return address === lastAddress;\n }\n\n /**\n * Creates a KeyringAccount object for the given address and index.\n *\n * @param address - The account address.\n * @param addressIndex - The account index in the HD path.\n * @returns The created KeyringAccount.\n */\n #createKeyringAccount(\n address: Hex,\n addressIndex: number,\n ): Bip44Account<KeyringAccount> {\n const id = this.registry.register(address);\n\n const account: Bip44Account<KeyringAccount> = {\n id,\n type: EthAccountType.Eoa,\n address,\n scopes: [...this.capabilities.scopes],\n methods: [...HD_KEYRING_METHODS],\n options: {\n entropy: {\n type: KeyringAccountEntropyTypeOption.Mnemonic,\n id: this.entropySource,\n groupIndex: addressIndex,\n derivationPath: `${this.inner.hdPath}/${addressIndex}`,\n },\n exportable: true,\n },\n };\n\n // Add the account to the registry\n this.registry.set(account);\n\n return account;\n }\n\n async getAccounts(): Promise<Bip44Account<KeyringAccount>[]> {\n const addresses = await this.inner.getAccounts();\n\n return addresses.map((address, addressIndex) => {\n // Check if we already have this account in the registry\n const existingId = this.registry.getAccountId(address);\n if (existingId) {\n const cached = this.registry.get(existingId);\n if (cached) {\n return cached;\n }\n }\n\n // Create and register the account if not already cached\n return this.#createKeyringAccount(address, addressIndex);\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withLock(async () => {\n // For HD keyring, we only support BIP-44 derive index\n if (options.type !== 'bip44:derive-index') {\n throw new Error(\n `Unsupported account creation type for HdKeyring: ${options.type}`,\n );\n }\n\n // Validate that the entropy source matches this keyring's entropy source\n if (options.entropySource !== this.entropySource) {\n throw new Error(\n `Entropy source mismatch: expected '${this.entropySource}', got '${options.entropySource}'`,\n );\n }\n\n // Sync with the inner keyring state in case it was modified externally\n // This ensures our cache is up-to-date before we make changes\n const currentAccounts = await this.getAccounts();\n const currentCount = currentAccounts.length;\n const targetIndex = options.groupIndex;\n\n // Check if an account at this index already exists\n // Since only the last account can be deleted, array position always equals groupIndex\n const existingAccount = currentAccounts[targetIndex];\n if (existingAccount) {\n return [existingAccount];\n }\n\n // Only allow derivation of the next account in sequence\n if (targetIndex !== currentCount) {\n throw new Error(\n `Can only create the next account in sequence. ` +\n `Expected groupIndex ${currentCount}, got ${targetIndex}.`,\n );\n }\n\n // Add the next account\n const [newAddress] = await this.inner.addAccounts(1);\n\n if (!newAddress) {\n throw new Error('Failed to create new account');\n }\n\n const newAccount = this.#createKeyringAccount(newAddress, targetIndex);\n\n return [newAccount];\n });\n }\n\n /**\n * Delete an account from the keyring.\n *\n * ⚠️ Warning: Only deleting the last account is possible.\n *\n * @param accountId - The account ID to delete.\n */\n async deleteAccount(accountId: AccountId): Promise<void> {\n await this.withLock(async () => {\n // Get the account first, before any registry operations\n const { address } = await this.getAccount(accountId);\n const hexAddress = this.toHexAddress(address);\n\n // Assert that the account to delete is the last one in the inner keyring\n // We check against the inner keyring directly to avoid stale registry issues\n if (!(await this.#isLastAccount(address))) {\n throw new Error(\n 'Can only delete the last account in the HD keyring due to derivation index constraints.',\n );\n }\n\n // Remove from the legacy keyring\n this.inner.removeAccount(hexAddress);\n\n // Remove from the registry\n this.registry.delete(accountId);\n });\n }\n\n /**\n * Export the private key for an account in hexadecimal format.\n *\n * @param accountId - The ID of the account to export.\n * @param options - Export options (only hexadecimal encoding is supported).\n * @returns The exported account with private key.\n */\n async exportAccount(\n accountId: AccountId,\n options?: ExportAccountOptions,\n ): Promise<ExportedAccount> {\n const account = await this.getAccount(accountId);\n\n // Validate encoding - we only support hexadecimal for Ethereum keys\n const requestedEncoding =\n options?.encoding ?? PrivateKeyEncoding.Hexadecimal;\n\n if (requestedEncoding !== PrivateKeyEncoding.Hexadecimal) {\n throw new Error(\n `Unsupported encoding for Ethereum HD keyring: ${requestedEncoding}. Only '${PrivateKeyEncoding.Hexadecimal}' is supported.`,\n );\n }\n\n // The legacy HdKeyring returns a hex string without 0x prefix.\n const privateKeyWithout0x = await this.inner.exportAccount(\n this.toHexAddress(account.address),\n );\n const privateKey = add0x(privateKeyWithout0x);\n\n return {\n type: 'private-key',\n privateKey,\n encoding: PrivateKeyEncoding.Hexadecimal,\n };\n }\n}\n"]}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HdKeyring = void 0;
4
+ var hd_keyring_1 = require("./hd-keyring.cjs");
5
+ Object.defineProperty(exports, "HdKeyring", { enumerable: true, get: function () { return hd_keyring_1.HdKeyring; } });
6
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../src/v2/index.ts"],"names":[],"mappings":";;;AAAA,+CAAgE;AAAvD,uGAAA,SAAS,OAAA","sourcesContent":["export { HdKeyring, type HdKeyringOptions } from './hd-keyring';\n"]}
@@ -0,0 +1,2 @@
1
+ export { HdKeyring, type HdKeyringOptions } from "./hd-keyring.cjs";
2
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,yBAAqB"}
@@ -0,0 +1,2 @@
1
+ export { HdKeyring, type HdKeyringOptions } from "./hd-keyring.mjs";
2
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,yBAAqB"}
@@ -0,0 +1,2 @@
1
+ export { HdKeyring } from "./hd-keyring.mjs";
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../src/v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAyB,yBAAqB","sourcesContent":["export { HdKeyring, type HdKeyringOptions } from './hd-keyring';\n"]}
package/package.json CHANGED
@@ -1,20 +1,21 @@
1
1
  {
2
2
  "name": "@metamask/eth-hd-keyring",
3
- "version": "13.1.0",
4
- "description": "A simple standard interface for a seed phrase generated set of Ethereum accounts.",
3
+ "version": "14.0.0",
4
+ "description": "A simple standard interface for a seed phrase generated set of Ethereum accounts",
5
5
  "keywords": [
6
6
  "ethereum",
7
7
  "keyring"
8
8
  ],
9
- "homepage": "https://github.com/MetaMask/eth-hd-keyring#readme",
9
+ "homepage": "https://github.com/MetaMask/accounts/tree/main/packages/keyring-eth-hd#readme",
10
10
  "bugs": {
11
- "url": "https://github.com/MetaMask/eth-hd-keyring/issues"
11
+ "url": "https://github.com/MetaMask/accounts/issues"
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",
15
- "url": "https://github.com/MetaMask/eth-hd-keyring.git"
15
+ "url": "https://github.com/MetaMask/accounts.git"
16
16
  },
17
17
  "license": "ISC",
18
+ "sideEffects": false,
18
19
  "exports": {
19
20
  ".": {
20
21
  "import": {
@@ -25,7 +26,18 @@
25
26
  "types": "./dist/index.d.cts",
26
27
  "default": "./dist/index.cjs"
27
28
  }
28
- }
29
+ },
30
+ "./v2": {
31
+ "import": {
32
+ "types": "./dist/v2/index.d.mts",
33
+ "default": "./dist/v2/index.mjs"
34
+ },
35
+ "require": {
36
+ "types": "./dist/v2/index.d.cts",
37
+ "default": "./dist/v2/index.cjs"
38
+ }
39
+ },
40
+ "./package.json": "./package.json"
29
41
  },
30
42
  "main": "./dist/index.cjs",
31
43
  "types": "./dist/index.d.cts",
@@ -33,38 +45,45 @@
33
45
  "dist/"
34
46
  ],
35
47
  "scripts": {
36
- "build": "ts-bridge --project tsconfig.build.json --no-references",
48
+ "build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
49
+ "build:all": "ts-bridge --project tsconfig.build.json --verbose --clean",
37
50
  "build:clean": "yarn build --clean",
38
51
  "build:docs": "typedoc",
39
52
  "changelog:update": "../../scripts/update-changelog.sh @metamask/eth-hd-keyring",
40
53
  "changelog:validate": "../../scripts/validate-changelog.sh @metamask/eth-hd-keyring",
41
54
  "publish:preview": "yarn npm publish --tag preview",
42
- "test": "jest",
43
- "test:clean": "jest --clearCache"
55
+ "since-latest-release": "../../scripts/since-latest-release.sh",
56
+ "test": "yarn test:source && yarn test:types",
57
+ "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache",
58
+ "test:source": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter",
59
+ "test:types": "../../scripts/tsd-test.sh ./src",
60
+ "test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
61
+ "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
44
62
  },
45
63
  "dependencies": {
46
64
  "@ethereumjs/tx": "^5.4.0",
47
65
  "@ethereumjs/util": "^9.1.0",
48
66
  "@metamask/eth-sig-util": "^8.2.0",
49
67
  "@metamask/key-tree": "^10.0.2",
50
- "@metamask/keyring-api": "^21.3.0",
51
- "@metamask/keyring-utils": "^3.1.0",
68
+ "@metamask/keyring-api": "^23.0.0",
69
+ "@metamask/keyring-sdk": "^2.0.0",
70
+ "@metamask/keyring-utils": "^3.2.0",
52
71
  "@metamask/scure-bip39": "^2.1.1",
53
72
  "@metamask/superstruct": "^3.1.0",
54
- "@metamask/utils": "^11.1.0",
55
- "ethereum-cryptography": "^2.1.2"
73
+ "@metamask/utils": "^11.11.0",
74
+ "ethereum-cryptography": "^2.2.1"
56
75
  },
57
76
  "devDependencies": {
58
77
  "@lavamoat/allow-scripts": "^3.2.1",
59
78
  "@lavamoat/preinstall-always-fail": "^2.1.0",
60
- "@metamask/account-api": "^0.12.0",
79
+ "@metamask/account-api": "^1.0.2",
61
80
  "@metamask/auto-changelog": "^3.4.4",
62
81
  "@metamask/bip39": "^4.0.0",
82
+ "@metamask/old-hd-keyring": "npm:@metamask/eth-hd-keyring@^4.0.1",
63
83
  "@ts-bridge/cli": "^0.6.3",
64
84
  "@types/jest": "^29.5.12",
65
85
  "deepmerge": "^4.2.2",
66
- "jest": "^29.5.0",
67
- "old-hd-keyring": "npm:@metamask/eth-hd-keyring@^4.0.1"
86
+ "jest": "^29.5.0"
68
87
  },
69
88
  "engines": {
70
89
  "node": "^18.18 || >=20"
@@ -1 +0,0 @@
1
- {"version":3,"file":"hd-keyring-v2.cjs","sourceRoot":"","sources":["../src/hd-keyring-v2.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Bip44Account } from '@metamask/account-api';\nimport {\n type CreateAccountOptions,\n EthAccountType,\n EthKeyringMethod,\n EthKeyringWrapper,\n EthMethod,\n EthScope,\n type ExportAccountOptions,\n type ExportedAccount,\n type KeyringAccount,\n KeyringAccountEntropyTypeOption,\n type KeyringCapabilities,\n type KeyringV2,\n KeyringType,\n PrivateKeyEncoding,\n type EntropySourceId,\n} from '@metamask/keyring-api';\nimport type { AccountId } from '@metamask/keyring-utils';\nimport { add0x, type Hex } from '@metamask/utils';\n\nimport type { HdKeyring } from './hd-keyring';\n\n/**\n * Methods supported by HD keyring EOA accounts.\n * HD keyrings support all standard signing methods plus encryption and app keys.\n */\nconst HD_KEYRING_METHODS = [\n EthMethod.SignTransaction,\n EthMethod.Sign,\n EthMethod.PersonalSign,\n EthMethod.SignTypedDataV1,\n EthMethod.SignTypedDataV3,\n EthMethod.SignTypedDataV4,\n EthKeyringMethod.Decrypt,\n EthKeyringMethod.GetEncryptionPublicKey,\n EthKeyringMethod.GetAppKeyAddress,\n EthKeyringMethod.SignEip7702Authorization,\n];\n\nconst hdKeyringV2Capabilities: KeyringCapabilities = {\n scopes: [EthScope.Eoa],\n bip44: {\n deriveIndex: true,\n },\n privateKey: {\n exportFormats: [{ encoding: PrivateKeyEncoding.Hexadecimal }],\n },\n};\n\n/**\n * Concrete {@link KeyringV2} adapter for {@link HdKeyring}.\n *\n * This wrapper exposes the accounts and signing capabilities of the legacy\n * HD keyring via the unified V2 interface.\n */\nexport type HdKeyringV2Options = {\n legacyKeyring: HdKeyring;\n entropySource: EntropySourceId;\n};\n\nexport class HdKeyringV2\n extends EthKeyringWrapper<HdKeyring, Bip44Account<KeyringAccount>>\n implements KeyringV2\n{\n protected readonly entropySource: EntropySourceId;\n\n constructor(options: HdKeyringV2Options) {\n super({\n type: KeyringType.Hd,\n inner: options.legacyKeyring,\n capabilities: hdKeyringV2Capabilities,\n });\n this.entropySource = options.entropySource;\n }\n\n /**\n * Checks if the given address is the last account in the inner keyring.\n * This compares against the actual inner keyring state, not the registry,\n * to avoid issues with stale registry entries.\n *\n * @param address - The address to check.\n * @returns True if this is the last account in the inner keyring.\n */\n async #isLastAccount(address: string): Promise<boolean> {\n const innerAddresses = await this.inner.getAccounts();\n const lastAddress = innerAddresses[innerAddresses.length - 1];\n return address === lastAddress;\n }\n\n /**\n * Creates a KeyringAccount object for the given address and index.\n *\n * @param address - The account address.\n * @param addressIndex - The account index in the HD path.\n * @returns The created KeyringAccount.\n */\n #createKeyringAccount(\n address: Hex,\n addressIndex: number,\n ): Bip44Account<KeyringAccount> {\n const id = this.registry.register(address);\n\n const account: Bip44Account<KeyringAccount> = {\n id,\n type: EthAccountType.Eoa,\n address,\n scopes: [...this.capabilities.scopes],\n methods: [...HD_KEYRING_METHODS],\n options: {\n entropy: {\n type: KeyringAccountEntropyTypeOption.Mnemonic,\n id: this.entropySource,\n groupIndex: addressIndex,\n derivationPath: `${this.inner.hdPath}/${addressIndex}`,\n },\n exportable: true,\n },\n };\n\n // Add the account to the registry\n this.registry.set(account);\n\n return account;\n }\n\n async getAccounts(): Promise<Bip44Account<KeyringAccount>[]> {\n const addresses = await this.inner.getAccounts();\n\n return addresses.map((address, addressIndex) => {\n // Check if we already have this account in the registry\n const existingId = this.registry.getAccountId(address);\n if (existingId) {\n const cached = this.registry.get(existingId);\n if (cached) {\n return cached;\n }\n }\n\n // Create and register the account if not already cached\n return this.#createKeyringAccount(address, addressIndex);\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withLock(async () => {\n // For HD keyring, we only support BIP-44 derive index\n if (options.type !== 'bip44:derive-index') {\n throw new Error(\n `Unsupported account creation type for HdKeyring: ${options.type}`,\n );\n }\n\n // Validate that the entropy source matches this keyring's entropy source\n if (options.entropySource !== this.entropySource) {\n throw new Error(\n `Entropy source mismatch: expected '${this.entropySource}', got '${options.entropySource}'`,\n );\n }\n\n // Sync with the inner keyring state in case it was modified externally\n // This ensures our cache is up-to-date before we make changes\n const currentAccounts = await this.getAccounts();\n const currentCount = currentAccounts.length;\n const targetIndex = options.groupIndex;\n\n // Check if an account at this index already exists\n // Since only the last account can be deleted, array position always equals groupIndex\n const existingAccount = currentAccounts[targetIndex];\n if (existingAccount) {\n return [existingAccount];\n }\n\n // Only allow derivation of the next account in sequence\n if (targetIndex !== currentCount) {\n throw new Error(\n `Can only create the next account in sequence. ` +\n `Expected groupIndex ${currentCount}, got ${targetIndex}.`,\n );\n }\n\n // Add the next account\n const [newAddress] = await this.inner.addAccounts(1);\n\n if (!newAddress) {\n throw new Error('Failed to create new account');\n }\n\n const newAccount = this.#createKeyringAccount(newAddress, targetIndex);\n\n return [newAccount];\n });\n }\n\n /**\n * Delete an account from the keyring.\n *\n * ⚠️ Warning: Only deleting the last account is possible.\n *\n * @param accountId - The account ID to delete.\n */\n async deleteAccount(accountId: AccountId): Promise<void> {\n await this.withLock(async () => {\n // Get the account first, before any registry operations\n const { address } = await this.getAccount(accountId);\n const hexAddress = this.toHexAddress(address);\n\n // Assert that the account to delete is the last one in the inner keyring\n // We check against the inner keyring directly to avoid stale registry issues\n if (!(await this.#isLastAccount(address))) {\n throw new Error(\n 'Can only delete the last account in the HD keyring due to derivation index constraints.',\n );\n }\n\n // Remove from the legacy keyring\n this.inner.removeAccount(hexAddress);\n\n // Remove from the registry\n this.registry.delete(accountId);\n });\n }\n\n /**\n * Export the private key for an account in hexadecimal format.\n *\n * @param accountId - The ID of the account to export.\n * @param options - Export options (only hexadecimal encoding is supported).\n * @returns The exported account with private key.\n */\n async exportAccount(\n accountId: AccountId,\n options?: ExportAccountOptions,\n ): Promise<ExportedAccount> {\n const account = await this.getAccount(accountId);\n\n // Validate encoding - we only support hexadecimal for Ethereum keys\n const requestedEncoding =\n options?.encoding ?? PrivateKeyEncoding.Hexadecimal;\n\n if (requestedEncoding !== PrivateKeyEncoding.Hexadecimal) {\n throw new Error(\n `Unsupported encoding for Ethereum HD keyring: ${requestedEncoding}. Only '${PrivateKeyEncoding.Hexadecimal}' is supported.`,\n );\n }\n\n // The legacy HdKeyring returns a hex string without 0x prefix.\n const privateKeyWithout0x = await this.inner.exportAccount(\n this.toHexAddress(account.address),\n );\n const privateKey = add0x(privateKeyWithout0x);\n\n return {\n type: 'private-key',\n privateKey,\n encoding: PrivateKeyEncoding.Hexadecimal,\n };\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"hd-keyring-v2.d.cts","sourceRoot":"","sources":["../src/hd-keyring-v2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,EACL,KAAK,oBAAoB,EAGzB,iBAAiB,EAGjB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,cAAc,EAGnB,KAAK,SAAS,EAGd,KAAK,eAAe,EACrB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,gCAAgC;AAGzD,OAAO,KAAK,EAAE,SAAS,EAAE,yBAAqB;AA6B9C;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,SAAS,CAAC;IACzB,aAAa,EAAE,eAAe,CAAC;CAChC,CAAC;AAEF,qBAAa,WACX,SAAQ,iBAAiB,CAAC,SAAS,EAAE,YAAY,CAAC,cAAc,CAAC,CACjE,YAAW,SAAS;;IAEpB,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,eAAe,CAAC;gBAEtC,OAAO,EAAE,kBAAkB;IA2DjC,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAkBtD,cAAc,CAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAkD1C;;;;;;OAMG;IACG,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBxD;;;;;;OAMG;IACG,aAAa,CACjB,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,eAAe,CAAC;CAyB5B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"hd-keyring-v2.d.mts","sourceRoot":"","sources":["../src/hd-keyring-v2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B;AAC1D,OAAO,EACL,KAAK,oBAAoB,EAGzB,iBAAiB,EAGjB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,cAAc,EAGnB,KAAK,SAAS,EAGd,KAAK,eAAe,EACrB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,gCAAgC;AAGzD,OAAO,KAAK,EAAE,SAAS,EAAE,yBAAqB;AA6B9C;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,SAAS,CAAC;IACzB,aAAa,EAAE,eAAe,CAAC;CAChC,CAAC;AAEF,qBAAa,WACX,SAAQ,iBAAiB,CAAC,SAAS,EAAE,YAAY,CAAC,cAAc,CAAC,CACjE,YAAW,SAAS;;IAEpB,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,eAAe,CAAC;gBAEtC,OAAO,EAAE,kBAAkB;IA2DjC,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAkBtD,cAAc,CAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;IAkD1C;;;;;;OAMG;IACG,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBxD;;;;;;OAMG;IACG,aAAa,CACjB,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,eAAe,CAAC;CAyB5B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"hd-keyring-v2.mjs","sourceRoot":"","sources":["../src/hd-keyring-v2.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Bip44Account } from '@metamask/account-api';\nimport {\n type CreateAccountOptions,\n EthAccountType,\n EthKeyringMethod,\n EthKeyringWrapper,\n EthMethod,\n EthScope,\n type ExportAccountOptions,\n type ExportedAccount,\n type KeyringAccount,\n KeyringAccountEntropyTypeOption,\n type KeyringCapabilities,\n type KeyringV2,\n KeyringType,\n PrivateKeyEncoding,\n type EntropySourceId,\n} from '@metamask/keyring-api';\nimport type { AccountId } from '@metamask/keyring-utils';\nimport { add0x, type Hex } from '@metamask/utils';\n\nimport type { HdKeyring } from './hd-keyring';\n\n/**\n * Methods supported by HD keyring EOA accounts.\n * HD keyrings support all standard signing methods plus encryption and app keys.\n */\nconst HD_KEYRING_METHODS = [\n EthMethod.SignTransaction,\n EthMethod.Sign,\n EthMethod.PersonalSign,\n EthMethod.SignTypedDataV1,\n EthMethod.SignTypedDataV3,\n EthMethod.SignTypedDataV4,\n EthKeyringMethod.Decrypt,\n EthKeyringMethod.GetEncryptionPublicKey,\n EthKeyringMethod.GetAppKeyAddress,\n EthKeyringMethod.SignEip7702Authorization,\n];\n\nconst hdKeyringV2Capabilities: KeyringCapabilities = {\n scopes: [EthScope.Eoa],\n bip44: {\n deriveIndex: true,\n },\n privateKey: {\n exportFormats: [{ encoding: PrivateKeyEncoding.Hexadecimal }],\n },\n};\n\n/**\n * Concrete {@link KeyringV2} adapter for {@link HdKeyring}.\n *\n * This wrapper exposes the accounts and signing capabilities of the legacy\n * HD keyring via the unified V2 interface.\n */\nexport type HdKeyringV2Options = {\n legacyKeyring: HdKeyring;\n entropySource: EntropySourceId;\n};\n\nexport class HdKeyringV2\n extends EthKeyringWrapper<HdKeyring, Bip44Account<KeyringAccount>>\n implements KeyringV2\n{\n protected readonly entropySource: EntropySourceId;\n\n constructor(options: HdKeyringV2Options) {\n super({\n type: KeyringType.Hd,\n inner: options.legacyKeyring,\n capabilities: hdKeyringV2Capabilities,\n });\n this.entropySource = options.entropySource;\n }\n\n /**\n * Checks if the given address is the last account in the inner keyring.\n * This compares against the actual inner keyring state, not the registry,\n * to avoid issues with stale registry entries.\n *\n * @param address - The address to check.\n * @returns True if this is the last account in the inner keyring.\n */\n async #isLastAccount(address: string): Promise<boolean> {\n const innerAddresses = await this.inner.getAccounts();\n const lastAddress = innerAddresses[innerAddresses.length - 1];\n return address === lastAddress;\n }\n\n /**\n * Creates a KeyringAccount object for the given address and index.\n *\n * @param address - The account address.\n * @param addressIndex - The account index in the HD path.\n * @returns The created KeyringAccount.\n */\n #createKeyringAccount(\n address: Hex,\n addressIndex: number,\n ): Bip44Account<KeyringAccount> {\n const id = this.registry.register(address);\n\n const account: Bip44Account<KeyringAccount> = {\n id,\n type: EthAccountType.Eoa,\n address,\n scopes: [...this.capabilities.scopes],\n methods: [...HD_KEYRING_METHODS],\n options: {\n entropy: {\n type: KeyringAccountEntropyTypeOption.Mnemonic,\n id: this.entropySource,\n groupIndex: addressIndex,\n derivationPath: `${this.inner.hdPath}/${addressIndex}`,\n },\n exportable: true,\n },\n };\n\n // Add the account to the registry\n this.registry.set(account);\n\n return account;\n }\n\n async getAccounts(): Promise<Bip44Account<KeyringAccount>[]> {\n const addresses = await this.inner.getAccounts();\n\n return addresses.map((address, addressIndex) => {\n // Check if we already have this account in the registry\n const existingId = this.registry.getAccountId(address);\n if (existingId) {\n const cached = this.registry.get(existingId);\n if (cached) {\n return cached;\n }\n }\n\n // Create and register the account if not already cached\n return this.#createKeyringAccount(address, addressIndex);\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withLock(async () => {\n // For HD keyring, we only support BIP-44 derive index\n if (options.type !== 'bip44:derive-index') {\n throw new Error(\n `Unsupported account creation type for HdKeyring: ${options.type}`,\n );\n }\n\n // Validate that the entropy source matches this keyring's entropy source\n if (options.entropySource !== this.entropySource) {\n throw new Error(\n `Entropy source mismatch: expected '${this.entropySource}', got '${options.entropySource}'`,\n );\n }\n\n // Sync with the inner keyring state in case it was modified externally\n // This ensures our cache is up-to-date before we make changes\n const currentAccounts = await this.getAccounts();\n const currentCount = currentAccounts.length;\n const targetIndex = options.groupIndex;\n\n // Check if an account at this index already exists\n // Since only the last account can be deleted, array position always equals groupIndex\n const existingAccount = currentAccounts[targetIndex];\n if (existingAccount) {\n return [existingAccount];\n }\n\n // Only allow derivation of the next account in sequence\n if (targetIndex !== currentCount) {\n throw new Error(\n `Can only create the next account in sequence. ` +\n `Expected groupIndex ${currentCount}, got ${targetIndex}.`,\n );\n }\n\n // Add the next account\n const [newAddress] = await this.inner.addAccounts(1);\n\n if (!newAddress) {\n throw new Error('Failed to create new account');\n }\n\n const newAccount = this.#createKeyringAccount(newAddress, targetIndex);\n\n return [newAccount];\n });\n }\n\n /**\n * Delete an account from the keyring.\n *\n * ⚠️ Warning: Only deleting the last account is possible.\n *\n * @param accountId - The account ID to delete.\n */\n async deleteAccount(accountId: AccountId): Promise<void> {\n await this.withLock(async () => {\n // Get the account first, before any registry operations\n const { address } = await this.getAccount(accountId);\n const hexAddress = this.toHexAddress(address);\n\n // Assert that the account to delete is the last one in the inner keyring\n // We check against the inner keyring directly to avoid stale registry issues\n if (!(await this.#isLastAccount(address))) {\n throw new Error(\n 'Can only delete the last account in the HD keyring due to derivation index constraints.',\n );\n }\n\n // Remove from the legacy keyring\n this.inner.removeAccount(hexAddress);\n\n // Remove from the registry\n this.registry.delete(accountId);\n });\n }\n\n /**\n * Export the private key for an account in hexadecimal format.\n *\n * @param accountId - The ID of the account to export.\n * @param options - Export options (only hexadecimal encoding is supported).\n * @returns The exported account with private key.\n */\n async exportAccount(\n accountId: AccountId,\n options?: ExportAccountOptions,\n ): Promise<ExportedAccount> {\n const account = await this.getAccount(accountId);\n\n // Validate encoding - we only support hexadecimal for Ethereum keys\n const requestedEncoding =\n options?.encoding ?? PrivateKeyEncoding.Hexadecimal;\n\n if (requestedEncoding !== PrivateKeyEncoding.Hexadecimal) {\n throw new Error(\n `Unsupported encoding for Ethereum HD keyring: ${requestedEncoding}. Only '${PrivateKeyEncoding.Hexadecimal}' is supported.`,\n );\n }\n\n // The legacy HdKeyring returns a hex string without 0x prefix.\n const privateKeyWithout0x = await this.inner.exportAccount(\n this.toHexAddress(account.address),\n );\n const privateKey = add0x(privateKeyWithout0x);\n\n return {\n type: 'private-key',\n privateKey,\n encoding: PrivateKeyEncoding.Hexadecimal,\n };\n }\n}\n"]}