@metamask/eth-hd-keyring 13.1.1 → 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 +19 -1
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +0 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +0 -1
- package/dist/index.mjs.map +1 -1
- package/dist/{hd-keyring-v2.cjs → v2/hd-keyring.cjs} +26 -25
- package/dist/v2/hd-keyring.cjs.map +1 -0
- package/dist/{hd-keyring-v2.d.mts → v2/hd-keyring.d.cts} +10 -9
- package/dist/v2/hd-keyring.d.cts.map +1 -0
- package/dist/{hd-keyring-v2.d.cts → v2/hd-keyring.d.mts} +10 -9
- package/dist/v2/hd-keyring.d.mts.map +1 -0
- package/dist/{hd-keyring-v2.mjs → v2/hd-keyring.mjs} +15 -14
- package/dist/v2/hd-keyring.mjs.map +1 -0
- package/dist/v2/index.cjs +6 -0
- package/dist/v2/index.cjs.map +1 -0
- package/dist/v2/index.d.cts +2 -0
- package/dist/v2/index.d.cts.map +1 -0
- package/dist/v2/index.d.mts +2 -0
- package/dist/v2/index.d.mts.map +1 -0
- package/dist/v2/index.mjs +2 -0
- package/dist/v2/index.mjs.map +1 -0
- package/package.json +34 -16
- package/dist/hd-keyring-v2.cjs.map +0 -1
- package/dist/hd-keyring-v2.d.cts.map +0 -1
- package/dist/hd-keyring-v2.d.mts.map +0 -1
- package/dist/hd-keyring-v2.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,23 @@ 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
|
+
|
|
10
27
|
## [13.1.1]
|
|
11
28
|
|
|
12
29
|
### Changed
|
|
@@ -246,7 +263,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
246
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`.
|
|
247
264
|
- Package name changed from `eth-hd-keyring` to `@metamask/eth-hd-keyring`.
|
|
248
265
|
|
|
249
|
-
[Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@
|
|
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
|
|
250
268
|
[13.1.1]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@13.1.0...@metamask/eth-hd-keyring@13.1.1
|
|
251
269
|
[13.1.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@13.0.0...@metamask/eth-hd-keyring@13.1.0
|
|
252
270
|
[13.0.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-hd-keyring@12.1.0...@metamask/eth-hd-keyring@13.0.0
|
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
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
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+CAAyC;AAAhC,uGAAA,SAAS,OAAA
|
|
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
|
package/dist/index.d.cts.map
CHANGED
|
@@ -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
|
|
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
|
package/dist/index.d.mts.map
CHANGED
|
@@ -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
|
|
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
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,yBAAqB
|
|
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,11 +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
|
|
7
|
+
var _HdKeyring_instances, _HdKeyring_isLastAccount, _HdKeyring_createKeyringAccount;
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.
|
|
9
|
+
exports.HdKeyring = void 0;
|
|
10
10
|
const keyring_api_1 = require("@metamask/keyring-api");
|
|
11
|
-
const
|
|
11
|
+
const v2_1 = require("@metamask/keyring-api/v2");
|
|
12
|
+
const v2_2 = require("@metamask/keyring-sdk/v2");
|
|
12
13
|
const utils_1 = require("@metamask/utils");
|
|
13
14
|
/**
|
|
14
15
|
* Methods supported by HD keyring EOA accounts.
|
|
@@ -21,28 +22,28 @@ const HD_KEYRING_METHODS = [
|
|
|
21
22
|
keyring_api_1.EthMethod.SignTypedDataV1,
|
|
22
23
|
keyring_api_1.EthMethod.SignTypedDataV3,
|
|
23
24
|
keyring_api_1.EthMethod.SignTypedDataV4,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
v2_2.EthKeyringMethod.Decrypt,
|
|
26
|
+
v2_2.EthKeyringMethod.GetEncryptionPublicKey,
|
|
27
|
+
v2_2.EthKeyringMethod.GetAppKeyAddress,
|
|
28
|
+
v2_2.EthKeyringMethod.SignEip7702Authorization,
|
|
28
29
|
];
|
|
29
|
-
const
|
|
30
|
+
const hdKeyringCapabilities = {
|
|
30
31
|
scopes: [keyring_api_1.EthScope.Eoa],
|
|
31
32
|
bip44: {
|
|
32
33
|
deriveIndex: true,
|
|
33
34
|
},
|
|
34
35
|
privateKey: {
|
|
35
|
-
exportFormats: [{ encoding:
|
|
36
|
+
exportFormats: [{ encoding: v2_1.PrivateKeyEncoding.Hexadecimal }],
|
|
36
37
|
},
|
|
37
38
|
};
|
|
38
|
-
class
|
|
39
|
+
class HdKeyring extends v2_2.EthKeyringWrapper {
|
|
39
40
|
constructor(options) {
|
|
40
41
|
super({
|
|
41
|
-
type:
|
|
42
|
+
type: v2_1.KeyringType.Hd,
|
|
42
43
|
inner: options.legacyKeyring,
|
|
43
|
-
capabilities:
|
|
44
|
+
capabilities: hdKeyringCapabilities,
|
|
44
45
|
});
|
|
45
|
-
|
|
46
|
+
_HdKeyring_instances.add(this);
|
|
46
47
|
this.entropySource = options.entropySource;
|
|
47
48
|
}
|
|
48
49
|
async getAccounts() {
|
|
@@ -57,7 +58,7 @@ class HdKeyringV2 extends keyring_sdk_1.EthKeyringWrapper {
|
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
// Create and register the account if not already cached
|
|
60
|
-
return __classPrivateFieldGet(this,
|
|
61
|
+
return __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_createKeyringAccount).call(this, address, addressIndex);
|
|
61
62
|
});
|
|
62
63
|
}
|
|
63
64
|
async createAccounts(options) {
|
|
@@ -91,7 +92,7 @@ class HdKeyringV2 extends keyring_sdk_1.EthKeyringWrapper {
|
|
|
91
92
|
if (!newAddress) {
|
|
92
93
|
throw new Error('Failed to create new account');
|
|
93
94
|
}
|
|
94
|
-
const newAccount = __classPrivateFieldGet(this,
|
|
95
|
+
const newAccount = __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_createKeyringAccount).call(this, newAddress, targetIndex);
|
|
95
96
|
return [newAccount];
|
|
96
97
|
});
|
|
97
98
|
}
|
|
@@ -109,7 +110,7 @@ class HdKeyringV2 extends keyring_sdk_1.EthKeyringWrapper {
|
|
|
109
110
|
const hexAddress = this.toHexAddress(address);
|
|
110
111
|
// Assert that the account to delete is the last one in the inner keyring
|
|
111
112
|
// We check against the inner keyring directly to avoid stale registry issues
|
|
112
|
-
if (!(await __classPrivateFieldGet(this,
|
|
113
|
+
if (!(await __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_isLastAccount).call(this, address))) {
|
|
113
114
|
throw new Error('Can only delete the last account in the HD keyring due to derivation index constraints.');
|
|
114
115
|
}
|
|
115
116
|
// Remove from the legacy keyring
|
|
@@ -128,9 +129,9 @@ class HdKeyringV2 extends keyring_sdk_1.EthKeyringWrapper {
|
|
|
128
129
|
async exportAccount(accountId, options) {
|
|
129
130
|
const account = await this.getAccount(accountId);
|
|
130
131
|
// Validate encoding - we only support hexadecimal for Ethereum keys
|
|
131
|
-
const requestedEncoding = options?.encoding ??
|
|
132
|
-
if (requestedEncoding !==
|
|
133
|
-
throw new Error(`Unsupported encoding for Ethereum HD keyring: ${requestedEncoding}. Only '${
|
|
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.`);
|
|
134
135
|
}
|
|
135
136
|
// The legacy HdKeyring returns a hex string without 0x prefix.
|
|
136
137
|
const privateKeyWithout0x = await this.inner.exportAccount(this.toHexAddress(account.address));
|
|
@@ -138,12 +139,12 @@ class HdKeyringV2 extends keyring_sdk_1.EthKeyringWrapper {
|
|
|
138
139
|
return {
|
|
139
140
|
type: 'private-key',
|
|
140
141
|
privateKey,
|
|
141
|
-
encoding:
|
|
142
|
+
encoding: v2_1.PrivateKeyEncoding.Hexadecimal,
|
|
142
143
|
};
|
|
143
144
|
}
|
|
144
145
|
}
|
|
145
|
-
exports.
|
|
146
|
-
|
|
146
|
+
exports.HdKeyring = HdKeyring;
|
|
147
|
+
_HdKeyring_instances = new WeakSet(), _HdKeyring_isLastAccount =
|
|
147
148
|
/**
|
|
148
149
|
* Checks if the given address is the last account in the inner keyring.
|
|
149
150
|
* This compares against the actual inner keyring state, not the registry,
|
|
@@ -152,11 +153,11 @@ _HdKeyringV2_instances = new WeakSet(), _HdKeyringV2_isLastAccount =
|
|
|
152
153
|
* @param address - The address to check.
|
|
153
154
|
* @returns True if this is the last account in the inner keyring.
|
|
154
155
|
*/
|
|
155
|
-
async function
|
|
156
|
+
async function _HdKeyring_isLastAccount(address) {
|
|
156
157
|
const innerAddresses = await this.inner.getAccounts();
|
|
157
158
|
const lastAddress = innerAddresses[innerAddresses.length - 1];
|
|
158
159
|
return address === lastAddress;
|
|
159
|
-
},
|
|
160
|
+
}, _HdKeyring_createKeyringAccount = function _HdKeyring_createKeyringAccount(address, addressIndex) {
|
|
160
161
|
const id = this.registry.register(address);
|
|
161
162
|
const account = {
|
|
162
163
|
id,
|
|
@@ -178,4 +179,4 @@ async function _HdKeyringV2_isLastAccount(address) {
|
|
|
178
179
|
this.registry.set(account);
|
|
179
180
|
return account;
|
|
180
181
|
};
|
|
181
|
-
//# sourceMappingURL=hd-keyring
|
|
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,22 +1,23 @@
|
|
|
1
1
|
import type { Bip44Account } from "@metamask/account-api";
|
|
2
|
-
import { type
|
|
3
|
-
import {
|
|
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";
|
|
4
5
|
import type { AccountId } from "@metamask/keyring-utils";
|
|
5
|
-
import type { HdKeyring } from "
|
|
6
|
+
import type { HdKeyring as LegacyHdKeyring } from "../hd-keyring.cjs";
|
|
6
7
|
/**
|
|
7
|
-
* Concrete {@link
|
|
8
|
+
* Concrete {@link Keyring} adapter for {@link HdKeyring}.
|
|
8
9
|
*
|
|
9
10
|
* This wrapper exposes the accounts and signing capabilities of the legacy
|
|
10
11
|
* HD keyring via the unified V2 interface.
|
|
11
12
|
*/
|
|
12
|
-
export type
|
|
13
|
-
legacyKeyring:
|
|
13
|
+
export type HdKeyringOptions = {
|
|
14
|
+
legacyKeyring: LegacyHdKeyring;
|
|
14
15
|
entropySource: EntropySourceId;
|
|
15
16
|
};
|
|
16
|
-
export declare class
|
|
17
|
+
export declare class HdKeyring extends EthKeyringWrapper<LegacyHdKeyring, Bip44Account<KeyringAccount>> implements Keyring {
|
|
17
18
|
#private;
|
|
18
19
|
protected readonly entropySource: EntropySourceId;
|
|
19
|
-
constructor(options:
|
|
20
|
+
constructor(options: HdKeyringOptions);
|
|
20
21
|
getAccounts(): Promise<Bip44Account<KeyringAccount>[]>;
|
|
21
22
|
createAccounts(options: CreateAccountOptions): Promise<Bip44Account<KeyringAccount>[]>;
|
|
22
23
|
/**
|
|
@@ -36,4 +37,4 @@ export declare class HdKeyringV2 extends EthKeyringWrapper<HdKeyring, Bip44Accou
|
|
|
36
37
|
*/
|
|
37
38
|
exportAccount(accountId: AccountId, options?: ExportAccountOptions): Promise<ExportedAccount>;
|
|
38
39
|
}
|
|
39
|
-
//# sourceMappingURL=hd-keyring
|
|
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,22 +1,23 @@
|
|
|
1
1
|
import type { Bip44Account } from "@metamask/account-api";
|
|
2
|
-
import { type
|
|
3
|
-
import {
|
|
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";
|
|
4
5
|
import type { AccountId } from "@metamask/keyring-utils";
|
|
5
|
-
import type { HdKeyring } from "
|
|
6
|
+
import type { HdKeyring as LegacyHdKeyring } from "../hd-keyring.mjs";
|
|
6
7
|
/**
|
|
7
|
-
* Concrete {@link
|
|
8
|
+
* Concrete {@link Keyring} adapter for {@link HdKeyring}.
|
|
8
9
|
*
|
|
9
10
|
* This wrapper exposes the accounts and signing capabilities of the legacy
|
|
10
11
|
* HD keyring via the unified V2 interface.
|
|
11
12
|
*/
|
|
12
|
-
export type
|
|
13
|
-
legacyKeyring:
|
|
13
|
+
export type HdKeyringOptions = {
|
|
14
|
+
legacyKeyring: LegacyHdKeyring;
|
|
14
15
|
entropySource: EntropySourceId;
|
|
15
16
|
};
|
|
16
|
-
export declare class
|
|
17
|
+
export declare class HdKeyring extends EthKeyringWrapper<LegacyHdKeyring, Bip44Account<KeyringAccount>> implements Keyring {
|
|
17
18
|
#private;
|
|
18
19
|
protected readonly entropySource: EntropySourceId;
|
|
19
|
-
constructor(options:
|
|
20
|
+
constructor(options: HdKeyringOptions);
|
|
20
21
|
getAccounts(): Promise<Bip44Account<KeyringAccount>[]>;
|
|
21
22
|
createAccounts(options: CreateAccountOptions): Promise<Bip44Account<KeyringAccount>[]>;
|
|
22
23
|
/**
|
|
@@ -36,4 +37,4 @@ export declare class HdKeyringV2 extends EthKeyringWrapper<HdKeyring, Bip44Accou
|
|
|
36
37
|
*/
|
|
37
38
|
exportAccount(accountId: AccountId, options?: ExportAccountOptions): Promise<ExportedAccount>;
|
|
38
39
|
}
|
|
39
|
-
//# sourceMappingURL=hd-keyring
|
|
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,9 +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
|
|
7
|
-
import { EthAccountType, EthMethod, EthScope, KeyringAccountEntropyTypeOption
|
|
8
|
-
import {
|
|
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";
|
|
9
10
|
import { add0x } from "@metamask/utils";
|
|
10
11
|
/**
|
|
11
12
|
* Methods supported by HD keyring EOA accounts.
|
|
@@ -23,7 +24,7 @@ const HD_KEYRING_METHODS = [
|
|
|
23
24
|
EthKeyringMethod.GetAppKeyAddress,
|
|
24
25
|
EthKeyringMethod.SignEip7702Authorization,
|
|
25
26
|
];
|
|
26
|
-
const
|
|
27
|
+
const hdKeyringCapabilities = {
|
|
27
28
|
scopes: [EthScope.Eoa],
|
|
28
29
|
bip44: {
|
|
29
30
|
deriveIndex: true,
|
|
@@ -32,14 +33,14 @@ const hdKeyringV2Capabilities = {
|
|
|
32
33
|
exportFormats: [{ encoding: PrivateKeyEncoding.Hexadecimal }],
|
|
33
34
|
},
|
|
34
35
|
};
|
|
35
|
-
export class
|
|
36
|
+
export class HdKeyring extends EthKeyringWrapper {
|
|
36
37
|
constructor(options) {
|
|
37
38
|
super({
|
|
38
39
|
type: KeyringType.Hd,
|
|
39
40
|
inner: options.legacyKeyring,
|
|
40
|
-
capabilities:
|
|
41
|
+
capabilities: hdKeyringCapabilities,
|
|
41
42
|
});
|
|
42
|
-
|
|
43
|
+
_HdKeyring_instances.add(this);
|
|
43
44
|
this.entropySource = options.entropySource;
|
|
44
45
|
}
|
|
45
46
|
async getAccounts() {
|
|
@@ -54,7 +55,7 @@ export class HdKeyringV2 extends EthKeyringWrapper {
|
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
// Create and register the account if not already cached
|
|
57
|
-
return __classPrivateFieldGet(this,
|
|
58
|
+
return __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_createKeyringAccount).call(this, address, addressIndex);
|
|
58
59
|
});
|
|
59
60
|
}
|
|
60
61
|
async createAccounts(options) {
|
|
@@ -88,7 +89,7 @@ export class HdKeyringV2 extends EthKeyringWrapper {
|
|
|
88
89
|
if (!newAddress) {
|
|
89
90
|
throw new Error('Failed to create new account');
|
|
90
91
|
}
|
|
91
|
-
const newAccount = __classPrivateFieldGet(this,
|
|
92
|
+
const newAccount = __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_createKeyringAccount).call(this, newAddress, targetIndex);
|
|
92
93
|
return [newAccount];
|
|
93
94
|
});
|
|
94
95
|
}
|
|
@@ -106,7 +107,7 @@ export class HdKeyringV2 extends EthKeyringWrapper {
|
|
|
106
107
|
const hexAddress = this.toHexAddress(address);
|
|
107
108
|
// Assert that the account to delete is the last one in the inner keyring
|
|
108
109
|
// We check against the inner keyring directly to avoid stale registry issues
|
|
109
|
-
if (!(await __classPrivateFieldGet(this,
|
|
110
|
+
if (!(await __classPrivateFieldGet(this, _HdKeyring_instances, "m", _HdKeyring_isLastAccount).call(this, address))) {
|
|
110
111
|
throw new Error('Can only delete the last account in the HD keyring due to derivation index constraints.');
|
|
111
112
|
}
|
|
112
113
|
// Remove from the legacy keyring
|
|
@@ -139,7 +140,7 @@ export class HdKeyringV2 extends EthKeyringWrapper {
|
|
|
139
140
|
};
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
|
-
|
|
143
|
+
_HdKeyring_instances = new WeakSet(), _HdKeyring_isLastAccount =
|
|
143
144
|
/**
|
|
144
145
|
* Checks if the given address is the last account in the inner keyring.
|
|
145
146
|
* This compares against the actual inner keyring state, not the registry,
|
|
@@ -148,11 +149,11 @@ _HdKeyringV2_instances = new WeakSet(), _HdKeyringV2_isLastAccount =
|
|
|
148
149
|
* @param address - The address to check.
|
|
149
150
|
* @returns True if this is the last account in the inner keyring.
|
|
150
151
|
*/
|
|
151
|
-
async function
|
|
152
|
+
async function _HdKeyring_isLastAccount(address) {
|
|
152
153
|
const innerAddresses = await this.inner.getAccounts();
|
|
153
154
|
const lastAddress = innerAddresses[innerAddresses.length - 1];
|
|
154
155
|
return address === lastAddress;
|
|
155
|
-
},
|
|
156
|
+
}, _HdKeyring_createKeyringAccount = function _HdKeyring_createKeyringAccount(address, addressIndex) {
|
|
156
157
|
const id = this.registry.register(address);
|
|
157
158
|
const account = {
|
|
158
159
|
id,
|
|
@@ -174,4 +175,4 @@ async function _HdKeyringV2_isLastAccount(address) {
|
|
|
174
175
|
this.registry.set(account);
|
|
175
176
|
return account;
|
|
176
177
|
};
|
|
177
|
-
//# sourceMappingURL=hd-keyring
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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": "
|
|
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
|
|
9
|
+
"homepage": "https://github.com/MetaMask/accounts/tree/main/packages/keyring-eth-hd#readme",
|
|
10
10
|
"bugs": {
|
|
11
|
-
"url": "https://github.com/MetaMask/
|
|
11
|
+
"url": "https://github.com/MetaMask/accounts/issues"
|
|
12
12
|
},
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "https://github.com/MetaMask/
|
|
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,39 +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
|
-
"
|
|
43
|
-
"test
|
|
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": "^
|
|
51
|
-
"@metamask/keyring-sdk": "^
|
|
68
|
+
"@metamask/keyring-api": "^23.0.0",
|
|
69
|
+
"@metamask/keyring-sdk": "^2.0.0",
|
|
52
70
|
"@metamask/keyring-utils": "^3.2.0",
|
|
53
71
|
"@metamask/scure-bip39": "^2.1.1",
|
|
54
72
|
"@metamask/superstruct": "^3.1.0",
|
|
55
|
-
"@metamask/utils": "^11.
|
|
56
|
-
"ethereum-cryptography": "^2.1
|
|
73
|
+
"@metamask/utils": "^11.11.0",
|
|
74
|
+
"ethereum-cryptography": "^2.2.1"
|
|
57
75
|
},
|
|
58
76
|
"devDependencies": {
|
|
59
77
|
"@lavamoat/allow-scripts": "^3.2.1",
|
|
60
78
|
"@lavamoat/preinstall-always-fail": "^2.1.0",
|
|
61
|
-
"@metamask/account-api": "^1.0.
|
|
79
|
+
"@metamask/account-api": "^1.0.2",
|
|
62
80
|
"@metamask/auto-changelog": "^3.4.4",
|
|
63
81
|
"@metamask/bip39": "^4.0.0",
|
|
82
|
+
"@metamask/old-hd-keyring": "npm:@metamask/eth-hd-keyring@^4.0.1",
|
|
64
83
|
"@ts-bridge/cli": "^0.6.3",
|
|
65
84
|
"@types/jest": "^29.5.12",
|
|
66
85
|
"deepmerge": "^4.2.2",
|
|
67
|
-
"jest": "^29.5.0"
|
|
68
|
-
"old-hd-keyring": "npm:@metamask/eth-hd-keyring@^4.0.1"
|
|
86
|
+
"jest": "^29.5.0"
|
|
69
87
|
},
|
|
70
88
|
"engines": {
|
|
71
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 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 { EthKeyringMethod, EthKeyringWrapper } from '@metamask/keyring-sdk';\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,EAIzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,cAAc,EAGnB,KAAK,SAAS,EAGd,KAAK,eAAe,EACrB,8BAA8B;AAC/B,OAAO,EAAoB,iBAAiB,EAAE,8BAA8B;AAC5E,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,EAIzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,cAAc,EAGnB,KAAK,SAAS,EAGd,KAAK,eAAe,EACrB,8BAA8B;AAC/B,OAAO,EAAoB,iBAAiB,EAAE,8BAA8B;AAC5E,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":";;;;;;AACA,OAAO,EAEL,cAAc,EACd,SAAS,EACT,QAAQ,EAIR,+BAA+B,EAG/B,WAAW,EACX,kBAAkB,EAEnB,8BAA8B;AAC/B,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,8BAA8B;AAE5E,OAAO,EAAE,KAAK,EAAY,wBAAwB;AAIlD;;;GAGG;AACH,MAAM,kBAAkB,GAAG;IACzB,SAAS,CAAC,eAAe;IACzB,SAAS,CAAC,IAAI;IACd,SAAS,CAAC,YAAY;IACtB,SAAS,CAAC,eAAe;IACzB,SAAS,CAAC,eAAe;IACzB,SAAS,CAAC,eAAe;IACzB,gBAAgB,CAAC,OAAO;IACxB,gBAAgB,CAAC,sBAAsB;IACvC,gBAAgB,CAAC,gBAAgB;IACjC,gBAAgB,CAAC,wBAAwB;CAC1C,CAAC;AAEF,MAAM,uBAAuB,GAAwB;IACnD,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;IACtB,KAAK,EAAE;QACL,WAAW,EAAE,IAAI;KAClB;IACD,UAAU,EAAE;QACV,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC,WAAW,EAAE,CAAC;KAC9D;CACF,CAAC;AAaF,MAAM,OAAO,WACX,SAAQ,iBAA0D;IAKlE,YAAY,OAA2B;QACrC,KAAK,CAAC;YACJ,IAAI,EAAE,WAAW,CAAC,EAAE;YACpB,KAAK,EAAE,OAAO,CAAC,aAAa;YAC5B,YAAY,EAAE,uBAAuB;SACtC,CAAC,CAAC;;QACH,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAC7C,CAAC;IAoDD,KAAK,CAAC,WAAW;QACf,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAEjD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE;YAC7C,wDAAwD;YACxD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBAC7C,IAAI,MAAM,EAAE,CAAC;oBACX,OAAO,MAAM,CAAC;gBAChB,CAAC;YACH,CAAC;YAED,wDAAwD;YACxD,OAAO,uBAAA,IAAI,iEAAsB,MAA1B,IAAI,EAAuB,OAAO,EAAE,YAAY,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,OAA6B;QAE7B,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC9B,sDAAsD;YACtD,IAAI,OAAO,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CACb,oDAAoD,OAAO,CAAC,IAAI,EAAE,CACnE,CAAC;YACJ,CAAC;YAED,yEAAyE;YACzE,IAAI,OAAO,CAAC,aAAa,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;gBACjD,MAAM,IAAI,KAAK,CACb,sCAAsC,IAAI,CAAC,aAAa,WAAW,OAAO,CAAC,aAAa,GAAG,CAC5F,CAAC;YACJ,CAAC;YAED,uEAAuE;YACvE,8DAA8D;YAC9D,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YACjD,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC;YAC5C,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;YAEvC,mDAAmD;YACnD,sFAAsF;YACtF,MAAM,eAAe,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;YACrD,IAAI,eAAe,EAAE,CAAC;gBACpB,OAAO,CAAC,eAAe,CAAC,CAAC;YAC3B,CAAC;YAED,wDAAwD;YACxD,IAAI,WAAW,KAAK,YAAY,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CACb,gDAAgD;oBAC9C,uBAAuB,YAAY,SAAS,WAAW,GAAG,CAC7D,CAAC;YACJ,CAAC;YAED,uBAAuB;YACvB,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAErD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAClD,CAAC;YAED,MAAM,UAAU,GAAG,uBAAA,IAAI,iEAAsB,MAA1B,IAAI,EAAuB,UAAU,EAAE,WAAW,CAAC,CAAC;YAEvE,OAAO,CAAC,UAAU,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,aAAa,CAAC,SAAoB;QACtC,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC7B,wDAAwD;YACxD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YACrD,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAE9C,yEAAyE;YACzE,6EAA6E;YAC7E,IAAI,CAAC,CAAC,MAAM,uBAAA,IAAI,0DAAe,MAAnB,IAAI,EAAgB,OAAO,CAAC,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;YACJ,CAAC;YAED,iCAAiC;YACjC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YAErC,2BAA2B;YAC3B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,aAAa,CACjB,SAAoB,EACpB,OAA8B;QAE9B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAEjD,oEAAoE;QACpE,MAAM,iBAAiB,GACrB,OAAO,EAAE,QAAQ,IAAI,kBAAkB,CAAC,WAAW,CAAC;QAEtD,IAAI,iBAAiB,KAAK,kBAAkB,CAAC,WAAW,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CACb,iDAAiD,iBAAiB,WAAW,kBAAkB,CAAC,WAAW,iBAAiB,CAC7H,CAAC;QACJ,CAAC;QAED,+DAA+D;QAC/D,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CACxD,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CACnC,CAAC;QACF,MAAM,UAAU,GAAG,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAE9C,OAAO;YACL,IAAI,EAAE,aAAa;YACnB,UAAU;YACV,QAAQ,EAAE,kBAAkB,CAAC,WAAW;SACzC,CAAC;IACJ,CAAC;CACF;;AAxLC;;;;;;;GAOG;AACH,KAAK,qCAAgB,OAAe;IAClC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IACtD,MAAM,WAAW,GAAG,cAAc,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9D,OAAO,OAAO,KAAK,WAAW,CAAC;AACjC,CAAC,iFAUC,OAAY,EACZ,YAAoB;IAEpB,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE3C,MAAM,OAAO,GAAiC;QAC5C,EAAE;QACF,IAAI,EAAE,cAAc,CAAC,GAAG;QACxB,OAAO;QACP,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QACrC,OAAO,EAAE,CAAC,GAAG,kBAAkB,CAAC;QAChC,OAAO,EAAE;YACP,OAAO,EAAE;gBACP,IAAI,EAAE,+BAA+B,CAAC,QAAQ;gBAC9C,EAAE,EAAE,IAAI,CAAC,aAAa;gBACtB,UAAU,EAAE,YAAY;gBACxB,cAAc,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,YAAY,EAAE;aACvD;YACD,UAAU,EAAE,IAAI;SACjB;KACF,CAAC;IAEF,kCAAkC;IAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAE3B,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import type { Bip44Account } from '@metamask/account-api';\nimport {\n type CreateAccountOptions,\n EthAccountType,\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 { EthKeyringMethod, EthKeyringWrapper } from '@metamask/keyring-sdk';\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"]}
|