@metamask/eth-simple-keyring 11.0.0 → 11.1.1
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 +24 -1
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/dist/simple-keyring-v2.cjs +202 -0
- package/dist/simple-keyring-v2.cjs.map +1 -0
- package/dist/simple-keyring-v2.d.cts +34 -0
- package/dist/simple-keyring-v2.d.cts.map +1 -0
- package/dist/simple-keyring-v2.d.mts +34 -0
- package/dist/simple-keyring-v2.d.mts.map +1 -0
- package/dist/simple-keyring-v2.mjs +198 -0
- package/dist/simple-keyring-v2.mjs.map +1 -0
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [11.1.1]
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Add missing exports for `SimpleKeyringV2` and type `SimpleKeyringV2Options` ([#498](https://github.com/MetaMask/accounts/pull/498))
|
|
15
|
+
- Bump `@metamask/keyring-sdk` from `^1.0.0` to `^1.1.0` ([#496](https://github.com/MetaMask/accounts/pull/496))
|
|
16
|
+
|
|
17
|
+
## [11.1.0]
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Add `SimpleKeyringV2` class implementing `KeyringV2` interface ([#409](https://github.com/MetaMask/accounts/pull/409)), ([#410](https://github.com/MetaMask/accounts/pull/410)), ([#413](https://github.com/MetaMask/accounts/pull/413)), ([#451](https://github.com/MetaMask/accounts/pull/451)), ([#478](https://github.com/MetaMask/accounts/pull/478)), ([#482](https://github.com/MetaMask/accounts/pull/482))
|
|
22
|
+
- Add new dependency `@metamask/keyring-api@22.0.0`.
|
|
23
|
+
- Add new dependency `@metamask/keyring-sdk@1.0.0`.
|
|
24
|
+
- Wraps legacy `SimpleKeyring` to expose accounts via the unified `KeyringV2` API and the `KeyringAccount` type.
|
|
25
|
+
- Extends `EthKeyringWrapper` for common Ethereum logic.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Bump `@metamask/utils` from `^11.1.0` to `^11.10.0` ([#489](https://github.com/MetaMask/accounts/pull/489))
|
|
30
|
+
|
|
10
31
|
## [11.0.0]
|
|
11
32
|
|
|
12
33
|
### Changed
|
|
@@ -150,7 +171,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
150
171
|
- **BREAKING:** Remove redundant `newGethSignMessage` method ([#72](https://github.com/MetaMask/eth-simple-keyring/pull/72))
|
|
151
172
|
- Consumers can use `signPersonalMessage` method as a replacement for `newGethSignMessage`.
|
|
152
173
|
|
|
153
|
-
[Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-simple-keyring@11.
|
|
174
|
+
[Unreleased]: https://github.com/MetaMask/accounts/compare/@metamask/eth-simple-keyring@11.1.1...HEAD
|
|
175
|
+
[11.1.1]: https://github.com/MetaMask/accounts/compare/@metamask/eth-simple-keyring@11.1.0...@metamask/eth-simple-keyring@11.1.1
|
|
176
|
+
[11.1.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-simple-keyring@11.0.0...@metamask/eth-simple-keyring@11.1.0
|
|
154
177
|
[11.0.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-simple-keyring@10.0.0...@metamask/eth-simple-keyring@11.0.0
|
|
155
178
|
[10.0.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-simple-keyring@9.0.0...@metamask/eth-simple-keyring@10.0.0
|
|
156
179
|
[9.0.0]: https://github.com/MetaMask/accounts/compare/@metamask/eth-simple-keyring@8.1.1...@metamask/eth-simple-keyring@9.0.0
|
package/dist/index.cjs
CHANGED
|
@@ -3,7 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.default = void 0;
|
|
6
|
+
exports.SimpleKeyringV2 = exports.default = void 0;
|
|
7
7
|
var simple_keyring_1 = require("./simple-keyring.cjs");
|
|
8
8
|
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(simple_keyring_1).default; } });
|
|
9
|
+
var simple_keyring_v2_1 = require("./simple-keyring-v2.cjs");
|
|
10
|
+
Object.defineProperty(exports, "SimpleKeyringV2", { enumerable: true, get: function () { return simple_keyring_v2_1.SimpleKeyringV2; } });
|
|
9
11
|
//# 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,uDAA2C;AAAlC,0HAAA,OAAO,OAAA","sourcesContent":["export { default } from './simple-keyring';\n"]}
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,uDAA2C;AAAlC,0HAAA,OAAO,OAAA;AAChB,6DAG6B;AAF3B,oHAAA,eAAe,OAAA","sourcesContent":["export { default } from './simple-keyring';\nexport {\n SimpleKeyringV2,\n type SimpleKeyringV2Options,\n} from './simple-keyring-v2';\n"]}
|
package/dist/index.d.cts
CHANGED
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,OAAO,EAAE,6BAAyB"}
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,6BAAyB;AAC3C,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,GAC5B,gCAA4B"}
|
package/dist/index.d.mts
CHANGED
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,OAAO,EAAE,6BAAyB"}
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,6BAAyB;AAC3C,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,GAC5B,gCAA4B"}
|
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,OAAO,EAAE,6BAAyB","sourcesContent":["export { default } from './simple-keyring';\n"]}
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,6BAAyB;AAC3C,OAAO,EACL,eAAe,EAEhB,gCAA4B","sourcesContent":["export { default } from './simple-keyring';\nexport {\n SimpleKeyringV2,\n type SimpleKeyringV2Options,\n} from './simple-keyring-v2';\n"]}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
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
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var _SimpleKeyringV2_instances, _SimpleKeyringV2_createKeyringAccount, _SimpleKeyringV2_getPrivateKeys, _SimpleKeyringV2_setPrivateKeys, _SimpleKeyringV2_withRollback, _SimpleKeyringV2_importPrivateKeyOrRollback;
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.SimpleKeyringV2 = void 0;
|
|
10
|
+
const keyring_api_1 = require("@metamask/keyring-api");
|
|
11
|
+
const keyring_sdk_1 = require("@metamask/keyring-sdk");
|
|
12
|
+
const utils_1 = require("@metamask/utils");
|
|
13
|
+
/**
|
|
14
|
+
* Methods supported by SimpleKeyring EOA accounts.
|
|
15
|
+
* SimpleKeyring supports all standard signing methods plus encryption and app keys.
|
|
16
|
+
*/
|
|
17
|
+
const SIMPLE_KEYRING_METHODS = [
|
|
18
|
+
keyring_api_1.EthMethod.SignTransaction,
|
|
19
|
+
keyring_api_1.EthMethod.Sign,
|
|
20
|
+
keyring_api_1.EthMethod.PersonalSign,
|
|
21
|
+
keyring_api_1.EthMethod.SignTypedDataV1,
|
|
22
|
+
keyring_api_1.EthMethod.SignTypedDataV3,
|
|
23
|
+
keyring_api_1.EthMethod.SignTypedDataV4,
|
|
24
|
+
keyring_sdk_1.EthKeyringMethod.Decrypt,
|
|
25
|
+
keyring_sdk_1.EthKeyringMethod.GetEncryptionPublicKey,
|
|
26
|
+
keyring_sdk_1.EthKeyringMethod.GetAppKeyAddress,
|
|
27
|
+
keyring_sdk_1.EthKeyringMethod.SignEip7702Authorization,
|
|
28
|
+
];
|
|
29
|
+
const simpleKeyringV2Capabilities = {
|
|
30
|
+
scopes: [keyring_api_1.EthScope.Eoa],
|
|
31
|
+
privateKey: {
|
|
32
|
+
importFormats: [
|
|
33
|
+
{ encoding: keyring_api_1.PrivateKeyEncoding.Hexadecimal, type: keyring_api_1.EthAccountType.Eoa },
|
|
34
|
+
],
|
|
35
|
+
exportFormats: [{ encoding: keyring_api_1.PrivateKeyEncoding.Hexadecimal }],
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
class SimpleKeyringV2 extends keyring_sdk_1.EthKeyringWrapper {
|
|
39
|
+
constructor(options) {
|
|
40
|
+
super({
|
|
41
|
+
type: keyring_api_1.KeyringType.PrivateKey,
|
|
42
|
+
inner: options.legacyKeyring,
|
|
43
|
+
capabilities: simpleKeyringV2Capabilities,
|
|
44
|
+
});
|
|
45
|
+
_SimpleKeyringV2_instances.add(this);
|
|
46
|
+
}
|
|
47
|
+
async getAccounts() {
|
|
48
|
+
const addresses = await this.inner.getAccounts();
|
|
49
|
+
return addresses.map((address) => {
|
|
50
|
+
// Check if we already have this account in the registry
|
|
51
|
+
const existingId = this.registry.getAccountId(address);
|
|
52
|
+
if (existingId) {
|
|
53
|
+
const cached = this.registry.get(existingId);
|
|
54
|
+
if (cached) {
|
|
55
|
+
return cached;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Create and register the account if not already cached
|
|
59
|
+
return __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_createKeyringAccount).call(this, address);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async createAccounts(options) {
|
|
63
|
+
return this.withLock(async () => {
|
|
64
|
+
// For SimpleKeyring, we only support private key import
|
|
65
|
+
if (options.type !== 'private-key:import') {
|
|
66
|
+
throw new Error(`Unsupported account creation type for SimpleKeyring: ${options.type}`);
|
|
67
|
+
}
|
|
68
|
+
// Validate account type
|
|
69
|
+
if (options.accountType !== keyring_api_1.EthAccountType.Eoa) {
|
|
70
|
+
throw new Error(`Unsupported account type for SimpleKeyring: ${options.accountType}. Only '${keyring_api_1.EthAccountType.Eoa}' is supported.`);
|
|
71
|
+
}
|
|
72
|
+
const { encoding, privateKey } = options;
|
|
73
|
+
// Validate encoding
|
|
74
|
+
if (encoding !== keyring_api_1.PrivateKeyEncoding.Hexadecimal) {
|
|
75
|
+
throw new Error(`Unsupported encoding for SimpleKeyring: ${encoding}. Only '${keyring_api_1.PrivateKeyEncoding.Hexadecimal}' is supported.`);
|
|
76
|
+
}
|
|
77
|
+
// Import the private key (with automatic rollback on failure)
|
|
78
|
+
const newAddress = await __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_importPrivateKeyOrRollback).call(this, privateKey);
|
|
79
|
+
// Create and return the new KeyringAccount
|
|
80
|
+
const newAccount = __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_createKeyringAccount).call(this, newAddress);
|
|
81
|
+
return [newAccount];
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Delete an account from the keyring.
|
|
86
|
+
*
|
|
87
|
+
* @param accountId - The account ID to delete.
|
|
88
|
+
*/
|
|
89
|
+
async deleteAccount(accountId) {
|
|
90
|
+
await this.withLock(async () => {
|
|
91
|
+
const account = await this.getAccount(accountId);
|
|
92
|
+
// Remove from the legacy keyring
|
|
93
|
+
this.inner.removeAccount(account.address);
|
|
94
|
+
// Remove from the registry
|
|
95
|
+
this.registry.delete(accountId);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Export the private key for an account in hexadecimal format.
|
|
100
|
+
*
|
|
101
|
+
* @param accountId - The ID of the account to export.
|
|
102
|
+
* @param options - Export options (only hexadecimal encoding is supported).
|
|
103
|
+
* @returns The exported account with private key.
|
|
104
|
+
*/
|
|
105
|
+
async exportAccount(accountId, options) {
|
|
106
|
+
const account = await this.getAccount(accountId);
|
|
107
|
+
const requestedEncoding = options?.encoding ?? keyring_api_1.PrivateKeyEncoding.Hexadecimal;
|
|
108
|
+
if (requestedEncoding !== keyring_api_1.PrivateKeyEncoding.Hexadecimal) {
|
|
109
|
+
throw new Error(`Unsupported encoding for SimpleKeyring: ${requestedEncoding}. Only '${keyring_api_1.PrivateKeyEncoding.Hexadecimal}' is supported.`);
|
|
110
|
+
}
|
|
111
|
+
const privateKeyHex = await this.inner.exportAccount(this.toHexAddress(account.address));
|
|
112
|
+
// Sanitize private key format
|
|
113
|
+
const privateKey = (0, utils_1.add0x)(privateKeyHex);
|
|
114
|
+
const exported = {
|
|
115
|
+
type: 'private-key',
|
|
116
|
+
privateKey,
|
|
117
|
+
encoding: keyring_api_1.PrivateKeyEncoding.Hexadecimal,
|
|
118
|
+
};
|
|
119
|
+
return exported;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.SimpleKeyringV2 = SimpleKeyringV2;
|
|
123
|
+
_SimpleKeyringV2_instances = new WeakSet(), _SimpleKeyringV2_createKeyringAccount = function _SimpleKeyringV2_createKeyringAccount(address) {
|
|
124
|
+
const id = this.registry.register(address);
|
|
125
|
+
const account = {
|
|
126
|
+
id,
|
|
127
|
+
type: keyring_api_1.EthAccountType.Eoa,
|
|
128
|
+
address,
|
|
129
|
+
scopes: [...this.capabilities.scopes],
|
|
130
|
+
methods: [...SIMPLE_KEYRING_METHODS],
|
|
131
|
+
options: {
|
|
132
|
+
entropy: {
|
|
133
|
+
type: keyring_api_1.KeyringAccountEntropyTypeOption.PrivateKey,
|
|
134
|
+
},
|
|
135
|
+
exportable: true,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
// Add the account to the registry
|
|
139
|
+
this.registry.set(account);
|
|
140
|
+
return account;
|
|
141
|
+
}, _SimpleKeyringV2_getPrivateKeys =
|
|
142
|
+
/**
|
|
143
|
+
* Get all private keys from the inner SimpleKeyring.
|
|
144
|
+
*
|
|
145
|
+
* @returns An array of private keys in hexadecimal format.
|
|
146
|
+
*/
|
|
147
|
+
async function _SimpleKeyringV2_getPrivateKeys() {
|
|
148
|
+
return await this.inner.serialize();
|
|
149
|
+
}, _SimpleKeyringV2_setPrivateKeys =
|
|
150
|
+
/**
|
|
151
|
+
* Set private keys in the inner SimpleKeyring.
|
|
152
|
+
*
|
|
153
|
+
* @param privateKeys - An array of private keys in hexadecimal format.
|
|
154
|
+
*/
|
|
155
|
+
async function _SimpleKeyringV2_setPrivateKeys(privateKeys) {
|
|
156
|
+
await this.inner.deserialize(privateKeys);
|
|
157
|
+
}, _SimpleKeyringV2_withRollback =
|
|
158
|
+
/**
|
|
159
|
+
* Executes a transactional update on the inner keyring state.
|
|
160
|
+
* If the callback throws, the state is automatically rolled back.
|
|
161
|
+
*
|
|
162
|
+
* @param callback - A function that receives the current private keys and performs the update.
|
|
163
|
+
* Should return the result on success, or throw to trigger rollback.
|
|
164
|
+
* @returns The result of the callback.
|
|
165
|
+
* @throws Error if the callback throws (after rollback).
|
|
166
|
+
*/
|
|
167
|
+
async function _SimpleKeyringV2_withRollback(callback) {
|
|
168
|
+
const originalPrivateKeys = await __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_getPrivateKeys).call(this);
|
|
169
|
+
try {
|
|
170
|
+
return await callback(originalPrivateKeys);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
// Rollback on error
|
|
174
|
+
await __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_setPrivateKeys).call(this, originalPrivateKeys);
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}, _SimpleKeyringV2_importPrivateKeyOrRollback =
|
|
178
|
+
/**
|
|
179
|
+
* Import a private key and return the new address.
|
|
180
|
+
* If the import fails (no new address added), rolls back to the original state.
|
|
181
|
+
*
|
|
182
|
+
* @param privateKey - The private key to import in hexadecimal format.
|
|
183
|
+
* @returns The address of the newly imported account.
|
|
184
|
+
* @throws Error if the import fails or no new address is added.
|
|
185
|
+
*/
|
|
186
|
+
async function _SimpleKeyringV2_importPrivateKeyOrRollback(privateKey) {
|
|
187
|
+
return __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_withRollback).call(this, async (currentPrivateKeys) => {
|
|
188
|
+
// Get current addresses before import
|
|
189
|
+
const addressesBefore = new Set(await this.inner.getAccounts());
|
|
190
|
+
// Import the new private key
|
|
191
|
+
await __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_setPrivateKeys).call(this, [...currentPrivateKeys, privateKey]);
|
|
192
|
+
// Get addresses after import and find the newly added one
|
|
193
|
+
const addressesAfter = await this.inner.getAccounts();
|
|
194
|
+
// Find the new address by diffing the two sets
|
|
195
|
+
const newAddresses = addressesAfter.filter((addr) => !addressesBefore.has(addr));
|
|
196
|
+
if (newAddresses.length !== 1 || !newAddresses[0]) {
|
|
197
|
+
throw new Error('Failed to import private key');
|
|
198
|
+
}
|
|
199
|
+
return newAddresses[0];
|
|
200
|
+
});
|
|
201
|
+
};
|
|
202
|
+
//# sourceMappingURL=simple-keyring-v2.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-keyring-v2.cjs","sourceRoot":"","sources":["../src/simple-keyring-v2.ts"],"names":[],"mappings":"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","sourcesContent":["import {\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} 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\n// eslint-disable-next-line @typescript-eslint/naming-convention\nimport type SimpleKeyring from './simple-keyring';\n\n/**\n * Methods supported by SimpleKeyring EOA accounts.\n * SimpleKeyring supports all standard signing methods plus encryption and app keys.\n */\nconst SIMPLE_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 simpleKeyringV2Capabilities: KeyringCapabilities = {\n scopes: [EthScope.Eoa],\n privateKey: {\n importFormats: [\n { encoding: PrivateKeyEncoding.Hexadecimal, type: EthAccountType.Eoa },\n ],\n exportFormats: [{ encoding: PrivateKeyEncoding.Hexadecimal }],\n },\n};\n\n/**\n * Concrete {@link KeyringV2} adapter for {@link SimpleKeyring}.\n *\n * This wrapper exposes the accounts and signing capabilities of the legacy\n * SimpleKeyring via the unified V2 interface.\n */\nexport type SimpleKeyringV2Options = {\n legacyKeyring: SimpleKeyring;\n};\n\nexport class SimpleKeyringV2\n extends EthKeyringWrapper<SimpleKeyring>\n implements KeyringV2\n{\n constructor(options: SimpleKeyringV2Options) {\n super({\n type: KeyringType.PrivateKey,\n inner: options.legacyKeyring,\n capabilities: simpleKeyringV2Capabilities,\n });\n }\n\n /**\n * Creates a KeyringAccount object for the given address and index.\n *\n * @param address - The account address.\n * @returns The created KeyringAccount.\n */\n #createKeyringAccount(address: Hex): KeyringAccount {\n const id = this.registry.register(address);\n\n const account: KeyringAccount = {\n id,\n type: EthAccountType.Eoa,\n address,\n scopes: [...this.capabilities.scopes],\n methods: [...SIMPLE_KEYRING_METHODS],\n options: {\n entropy: {\n type: KeyringAccountEntropyTypeOption.PrivateKey,\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 /**\n * Get all private keys from the inner SimpleKeyring.\n *\n * @returns An array of private keys in hexadecimal format.\n */\n async #getPrivateKeys(): Promise<string[]> {\n return await this.inner.serialize();\n }\n\n /**\n * Set private keys in the inner SimpleKeyring.\n *\n * @param privateKeys - An array of private keys in hexadecimal format.\n */\n async #setPrivateKeys(privateKeys: string[]): Promise<void> {\n await this.inner.deserialize(privateKeys);\n }\n\n /**\n * Executes a transactional update on the inner keyring state.\n * If the callback throws, the state is automatically rolled back.\n *\n * @param callback - A function that receives the current private keys and performs the update.\n * Should return the result on success, or throw to trigger rollback.\n * @returns The result of the callback.\n * @throws Error if the callback throws (after rollback).\n */\n async #withRollback<Result>(\n callback: (currentPrivateKeys: string[]) => Promise<Result>,\n ): Promise<Result> {\n const originalPrivateKeys = await this.#getPrivateKeys();\n\n try {\n return await callback(originalPrivateKeys);\n } catch (error) {\n // Rollback on error\n await this.#setPrivateKeys(originalPrivateKeys);\n throw error;\n }\n }\n\n /**\n * Import a private key and return the new address.\n * If the import fails (no new address added), rolls back to the original state.\n *\n * @param privateKey - The private key to import in hexadecimal format.\n * @returns The address of the newly imported account.\n * @throws Error if the import fails or no new address is added.\n */\n async #importPrivateKeyOrRollback(privateKey: string): Promise<Hex> {\n return this.#withRollback(async (currentPrivateKeys) => {\n // Get current addresses before import\n const addressesBefore = new Set(await this.inner.getAccounts());\n\n // Import the new private key\n await this.#setPrivateKeys([...currentPrivateKeys, privateKey]);\n\n // Get addresses after import and find the newly added one\n const addressesAfter = await this.inner.getAccounts();\n\n // Find the new address by diffing the two sets\n const newAddresses = addressesAfter.filter(\n (addr) => !addressesBefore.has(addr),\n );\n\n if (newAddresses.length !== 1 || !newAddresses[0]) {\n throw new Error('Failed to import private key');\n }\n\n return newAddresses[0];\n });\n }\n\n async getAccounts(): Promise<KeyringAccount[]> {\n const addresses = await this.inner.getAccounts();\n\n return addresses.map((address) => {\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);\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<KeyringAccount[]> {\n return this.withLock(async () => {\n // For SimpleKeyring, we only support private key import\n if (options.type !== 'private-key:import') {\n throw new Error(\n `Unsupported account creation type for SimpleKeyring: ${options.type}`,\n );\n }\n\n // Validate account type\n if (options.accountType !== EthAccountType.Eoa) {\n throw new Error(\n `Unsupported account type for SimpleKeyring: ${options.accountType}. Only '${EthAccountType.Eoa}' is supported.`,\n );\n }\n\n const { encoding, privateKey } = options;\n\n // Validate encoding\n if (encoding !== PrivateKeyEncoding.Hexadecimal) {\n throw new Error(\n `Unsupported encoding for SimpleKeyring: ${encoding}. Only '${PrivateKeyEncoding.Hexadecimal}' is supported.`,\n );\n }\n\n // Import the private key (with automatic rollback on failure)\n const newAddress = await this.#importPrivateKeyOrRollback(privateKey);\n\n // Create and return the new KeyringAccount\n const newAccount = this.#createKeyringAccount(newAddress);\n return [newAccount];\n });\n }\n\n /**\n * Delete an account from the keyring.\n *\n * @param accountId - The account ID to delete.\n */\n async deleteAccount(accountId: AccountId): Promise<void> {\n await this.withLock(async () => {\n const account = await this.getAccount(accountId);\n\n // Remove from the legacy keyring\n this.inner.removeAccount(account.address);\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 const requestedEncoding =\n options?.encoding ?? PrivateKeyEncoding.Hexadecimal;\n\n if (requestedEncoding !== PrivateKeyEncoding.Hexadecimal) {\n throw new Error(\n `Unsupported encoding for SimpleKeyring: ${requestedEncoding}. Only '${PrivateKeyEncoding.Hexadecimal}' is supported.`,\n );\n }\n\n const privateKeyHex = await this.inner.exportAccount(\n this.toHexAddress(account.address),\n );\n // Sanitize private key format\n const privateKey = add0x(privateKeyHex);\n\n const exported: ExportedAccount = {\n type: 'private-key',\n privateKey,\n encoding: PrivateKeyEncoding.Hexadecimal,\n };\n\n return exported;\n }\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type CreateAccountOptions, type ExportAccountOptions, type ExportedAccount, type KeyringAccount, type KeyringV2 } from "@metamask/keyring-api";
|
|
2
|
+
import { EthKeyringWrapper } from "@metamask/keyring-sdk";
|
|
3
|
+
import type { AccountId } from "@metamask/keyring-utils";
|
|
4
|
+
import type SimpleKeyring from "./simple-keyring.cjs";
|
|
5
|
+
/**
|
|
6
|
+
* Concrete {@link KeyringV2} adapter for {@link SimpleKeyring}.
|
|
7
|
+
*
|
|
8
|
+
* This wrapper exposes the accounts and signing capabilities of the legacy
|
|
9
|
+
* SimpleKeyring via the unified V2 interface.
|
|
10
|
+
*/
|
|
11
|
+
export type SimpleKeyringV2Options = {
|
|
12
|
+
legacyKeyring: SimpleKeyring;
|
|
13
|
+
};
|
|
14
|
+
export declare class SimpleKeyringV2 extends EthKeyringWrapper<SimpleKeyring> implements KeyringV2 {
|
|
15
|
+
#private;
|
|
16
|
+
constructor(options: SimpleKeyringV2Options);
|
|
17
|
+
getAccounts(): Promise<KeyringAccount[]>;
|
|
18
|
+
createAccounts(options: CreateAccountOptions): Promise<KeyringAccount[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Delete an account from the keyring.
|
|
21
|
+
*
|
|
22
|
+
* @param accountId - The account ID to delete.
|
|
23
|
+
*/
|
|
24
|
+
deleteAccount(accountId: AccountId): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Export the private key for an account in hexadecimal format.
|
|
27
|
+
*
|
|
28
|
+
* @param accountId - The ID of the account to export.
|
|
29
|
+
* @param options - Export options (only hexadecimal encoding is supported).
|
|
30
|
+
* @returns The exported account with private key.
|
|
31
|
+
*/
|
|
32
|
+
exportAccount(accountId: AccountId, options?: ExportAccountOptions): Promise<ExportedAccount>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=simple-keyring-v2.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-keyring-v2.d.cts","sourceRoot":"","sources":["../src/simple-keyring-v2.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,oBAAoB,EAIzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,cAAc,EAGnB,KAAK,SAAS,EAGf,8BAA8B;AAC/B,OAAO,EAAoB,iBAAiB,EAAE,8BAA8B;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,gCAAgC;AAIzD,OAAO,KAAK,aAAa,6BAAyB;AA6BlD;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,EAAE,aAAa,CAAC;CAC9B,CAAC;AAEF,qBAAa,eACX,SAAQ,iBAAiB,CAAC,aAAa,CACvC,YAAW,SAAS;;gBAER,OAAO,EAAE,sBAAsB;IA8GrC,WAAW,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAkBxC,cAAc,CAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,cAAc,EAAE,CAAC;IAkC5B;;;;OAIG;IACG,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxD;;;;;;OAMG;IACG,aAAa,CACjB,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,eAAe,CAAC;CA0B5B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type CreateAccountOptions, type ExportAccountOptions, type ExportedAccount, type KeyringAccount, type KeyringV2 } from "@metamask/keyring-api";
|
|
2
|
+
import { EthKeyringWrapper } from "@metamask/keyring-sdk";
|
|
3
|
+
import type { AccountId } from "@metamask/keyring-utils";
|
|
4
|
+
import type SimpleKeyring from "./simple-keyring.mjs";
|
|
5
|
+
/**
|
|
6
|
+
* Concrete {@link KeyringV2} adapter for {@link SimpleKeyring}.
|
|
7
|
+
*
|
|
8
|
+
* This wrapper exposes the accounts and signing capabilities of the legacy
|
|
9
|
+
* SimpleKeyring via the unified V2 interface.
|
|
10
|
+
*/
|
|
11
|
+
export type SimpleKeyringV2Options = {
|
|
12
|
+
legacyKeyring: SimpleKeyring;
|
|
13
|
+
};
|
|
14
|
+
export declare class SimpleKeyringV2 extends EthKeyringWrapper<SimpleKeyring> implements KeyringV2 {
|
|
15
|
+
#private;
|
|
16
|
+
constructor(options: SimpleKeyringV2Options);
|
|
17
|
+
getAccounts(): Promise<KeyringAccount[]>;
|
|
18
|
+
createAccounts(options: CreateAccountOptions): Promise<KeyringAccount[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Delete an account from the keyring.
|
|
21
|
+
*
|
|
22
|
+
* @param accountId - The account ID to delete.
|
|
23
|
+
*/
|
|
24
|
+
deleteAccount(accountId: AccountId): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Export the private key for an account in hexadecimal format.
|
|
27
|
+
*
|
|
28
|
+
* @param accountId - The ID of the account to export.
|
|
29
|
+
* @param options - Export options (only hexadecimal encoding is supported).
|
|
30
|
+
* @returns The exported account with private key.
|
|
31
|
+
*/
|
|
32
|
+
exportAccount(accountId: AccountId, options?: ExportAccountOptions): Promise<ExportedAccount>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=simple-keyring-v2.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-keyring-v2.d.mts","sourceRoot":"","sources":["../src/simple-keyring-v2.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,oBAAoB,EAIzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,cAAc,EAGnB,KAAK,SAAS,EAGf,8BAA8B;AAC/B,OAAO,EAAoB,iBAAiB,EAAE,8BAA8B;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,gCAAgC;AAIzD,OAAO,KAAK,aAAa,6BAAyB;AA6BlD;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,EAAE,aAAa,CAAC;CAC9B,CAAC;AAEF,qBAAa,eACX,SAAQ,iBAAiB,CAAC,aAAa,CACvC,YAAW,SAAS;;gBAER,OAAO,EAAE,sBAAsB;IA8GrC,WAAW,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAkBxC,cAAc,CAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,cAAc,EAAE,CAAC;IAkC5B;;;;OAIG;IACG,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxD;;;;;;OAMG;IACG,aAAa,CACjB,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,eAAe,CAAC;CA0B5B"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
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
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var _SimpleKeyringV2_instances, _SimpleKeyringV2_createKeyringAccount, _SimpleKeyringV2_getPrivateKeys, _SimpleKeyringV2_setPrivateKeys, _SimpleKeyringV2_withRollback, _SimpleKeyringV2_importPrivateKeyOrRollback;
|
|
7
|
+
import { EthAccountType, EthMethod, EthScope, KeyringAccountEntropyTypeOption, KeyringType, PrivateKeyEncoding } from "@metamask/keyring-api";
|
|
8
|
+
import { EthKeyringMethod, EthKeyringWrapper } from "@metamask/keyring-sdk";
|
|
9
|
+
import { add0x } from "@metamask/utils";
|
|
10
|
+
/**
|
|
11
|
+
* Methods supported by SimpleKeyring EOA accounts.
|
|
12
|
+
* SimpleKeyring supports all standard signing methods plus encryption and app keys.
|
|
13
|
+
*/
|
|
14
|
+
const SIMPLE_KEYRING_METHODS = [
|
|
15
|
+
EthMethod.SignTransaction,
|
|
16
|
+
EthMethod.Sign,
|
|
17
|
+
EthMethod.PersonalSign,
|
|
18
|
+
EthMethod.SignTypedDataV1,
|
|
19
|
+
EthMethod.SignTypedDataV3,
|
|
20
|
+
EthMethod.SignTypedDataV4,
|
|
21
|
+
EthKeyringMethod.Decrypt,
|
|
22
|
+
EthKeyringMethod.GetEncryptionPublicKey,
|
|
23
|
+
EthKeyringMethod.GetAppKeyAddress,
|
|
24
|
+
EthKeyringMethod.SignEip7702Authorization,
|
|
25
|
+
];
|
|
26
|
+
const simpleKeyringV2Capabilities = {
|
|
27
|
+
scopes: [EthScope.Eoa],
|
|
28
|
+
privateKey: {
|
|
29
|
+
importFormats: [
|
|
30
|
+
{ encoding: PrivateKeyEncoding.Hexadecimal, type: EthAccountType.Eoa },
|
|
31
|
+
],
|
|
32
|
+
exportFormats: [{ encoding: PrivateKeyEncoding.Hexadecimal }],
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
export class SimpleKeyringV2 extends EthKeyringWrapper {
|
|
36
|
+
constructor(options) {
|
|
37
|
+
super({
|
|
38
|
+
type: KeyringType.PrivateKey,
|
|
39
|
+
inner: options.legacyKeyring,
|
|
40
|
+
capabilities: simpleKeyringV2Capabilities,
|
|
41
|
+
});
|
|
42
|
+
_SimpleKeyringV2_instances.add(this);
|
|
43
|
+
}
|
|
44
|
+
async getAccounts() {
|
|
45
|
+
const addresses = await this.inner.getAccounts();
|
|
46
|
+
return addresses.map((address) => {
|
|
47
|
+
// Check if we already have this account in the registry
|
|
48
|
+
const existingId = this.registry.getAccountId(address);
|
|
49
|
+
if (existingId) {
|
|
50
|
+
const cached = this.registry.get(existingId);
|
|
51
|
+
if (cached) {
|
|
52
|
+
return cached;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Create and register the account if not already cached
|
|
56
|
+
return __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_createKeyringAccount).call(this, address);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async createAccounts(options) {
|
|
60
|
+
return this.withLock(async () => {
|
|
61
|
+
// For SimpleKeyring, we only support private key import
|
|
62
|
+
if (options.type !== 'private-key:import') {
|
|
63
|
+
throw new Error(`Unsupported account creation type for SimpleKeyring: ${options.type}`);
|
|
64
|
+
}
|
|
65
|
+
// Validate account type
|
|
66
|
+
if (options.accountType !== EthAccountType.Eoa) {
|
|
67
|
+
throw new Error(`Unsupported account type for SimpleKeyring: ${options.accountType}. Only '${EthAccountType.Eoa}' is supported.`);
|
|
68
|
+
}
|
|
69
|
+
const { encoding, privateKey } = options;
|
|
70
|
+
// Validate encoding
|
|
71
|
+
if (encoding !== PrivateKeyEncoding.Hexadecimal) {
|
|
72
|
+
throw new Error(`Unsupported encoding for SimpleKeyring: ${encoding}. Only '${PrivateKeyEncoding.Hexadecimal}' is supported.`);
|
|
73
|
+
}
|
|
74
|
+
// Import the private key (with automatic rollback on failure)
|
|
75
|
+
const newAddress = await __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_importPrivateKeyOrRollback).call(this, privateKey);
|
|
76
|
+
// Create and return the new KeyringAccount
|
|
77
|
+
const newAccount = __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_createKeyringAccount).call(this, newAddress);
|
|
78
|
+
return [newAccount];
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Delete an account from the keyring.
|
|
83
|
+
*
|
|
84
|
+
* @param accountId - The account ID to delete.
|
|
85
|
+
*/
|
|
86
|
+
async deleteAccount(accountId) {
|
|
87
|
+
await this.withLock(async () => {
|
|
88
|
+
const account = await this.getAccount(accountId);
|
|
89
|
+
// Remove from the legacy keyring
|
|
90
|
+
this.inner.removeAccount(account.address);
|
|
91
|
+
// Remove from the registry
|
|
92
|
+
this.registry.delete(accountId);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Export the private key for an account in hexadecimal format.
|
|
97
|
+
*
|
|
98
|
+
* @param accountId - The ID of the account to export.
|
|
99
|
+
* @param options - Export options (only hexadecimal encoding is supported).
|
|
100
|
+
* @returns The exported account with private key.
|
|
101
|
+
*/
|
|
102
|
+
async exportAccount(accountId, options) {
|
|
103
|
+
const account = await this.getAccount(accountId);
|
|
104
|
+
const requestedEncoding = options?.encoding ?? PrivateKeyEncoding.Hexadecimal;
|
|
105
|
+
if (requestedEncoding !== PrivateKeyEncoding.Hexadecimal) {
|
|
106
|
+
throw new Error(`Unsupported encoding for SimpleKeyring: ${requestedEncoding}. Only '${PrivateKeyEncoding.Hexadecimal}' is supported.`);
|
|
107
|
+
}
|
|
108
|
+
const privateKeyHex = await this.inner.exportAccount(this.toHexAddress(account.address));
|
|
109
|
+
// Sanitize private key format
|
|
110
|
+
const privateKey = add0x(privateKeyHex);
|
|
111
|
+
const exported = {
|
|
112
|
+
type: 'private-key',
|
|
113
|
+
privateKey,
|
|
114
|
+
encoding: PrivateKeyEncoding.Hexadecimal,
|
|
115
|
+
};
|
|
116
|
+
return exported;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
_SimpleKeyringV2_instances = new WeakSet(), _SimpleKeyringV2_createKeyringAccount = function _SimpleKeyringV2_createKeyringAccount(address) {
|
|
120
|
+
const id = this.registry.register(address);
|
|
121
|
+
const account = {
|
|
122
|
+
id,
|
|
123
|
+
type: EthAccountType.Eoa,
|
|
124
|
+
address,
|
|
125
|
+
scopes: [...this.capabilities.scopes],
|
|
126
|
+
methods: [...SIMPLE_KEYRING_METHODS],
|
|
127
|
+
options: {
|
|
128
|
+
entropy: {
|
|
129
|
+
type: KeyringAccountEntropyTypeOption.PrivateKey,
|
|
130
|
+
},
|
|
131
|
+
exportable: true,
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
// Add the account to the registry
|
|
135
|
+
this.registry.set(account);
|
|
136
|
+
return account;
|
|
137
|
+
}, _SimpleKeyringV2_getPrivateKeys =
|
|
138
|
+
/**
|
|
139
|
+
* Get all private keys from the inner SimpleKeyring.
|
|
140
|
+
*
|
|
141
|
+
* @returns An array of private keys in hexadecimal format.
|
|
142
|
+
*/
|
|
143
|
+
async function _SimpleKeyringV2_getPrivateKeys() {
|
|
144
|
+
return await this.inner.serialize();
|
|
145
|
+
}, _SimpleKeyringV2_setPrivateKeys =
|
|
146
|
+
/**
|
|
147
|
+
* Set private keys in the inner SimpleKeyring.
|
|
148
|
+
*
|
|
149
|
+
* @param privateKeys - An array of private keys in hexadecimal format.
|
|
150
|
+
*/
|
|
151
|
+
async function _SimpleKeyringV2_setPrivateKeys(privateKeys) {
|
|
152
|
+
await this.inner.deserialize(privateKeys);
|
|
153
|
+
}, _SimpleKeyringV2_withRollback =
|
|
154
|
+
/**
|
|
155
|
+
* Executes a transactional update on the inner keyring state.
|
|
156
|
+
* If the callback throws, the state is automatically rolled back.
|
|
157
|
+
*
|
|
158
|
+
* @param callback - A function that receives the current private keys and performs the update.
|
|
159
|
+
* Should return the result on success, or throw to trigger rollback.
|
|
160
|
+
* @returns The result of the callback.
|
|
161
|
+
* @throws Error if the callback throws (after rollback).
|
|
162
|
+
*/
|
|
163
|
+
async function _SimpleKeyringV2_withRollback(callback) {
|
|
164
|
+
const originalPrivateKeys = await __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_getPrivateKeys).call(this);
|
|
165
|
+
try {
|
|
166
|
+
return await callback(originalPrivateKeys);
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
// Rollback on error
|
|
170
|
+
await __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_setPrivateKeys).call(this, originalPrivateKeys);
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}, _SimpleKeyringV2_importPrivateKeyOrRollback =
|
|
174
|
+
/**
|
|
175
|
+
* Import a private key and return the new address.
|
|
176
|
+
* If the import fails (no new address added), rolls back to the original state.
|
|
177
|
+
*
|
|
178
|
+
* @param privateKey - The private key to import in hexadecimal format.
|
|
179
|
+
* @returns The address of the newly imported account.
|
|
180
|
+
* @throws Error if the import fails or no new address is added.
|
|
181
|
+
*/
|
|
182
|
+
async function _SimpleKeyringV2_importPrivateKeyOrRollback(privateKey) {
|
|
183
|
+
return __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_withRollback).call(this, async (currentPrivateKeys) => {
|
|
184
|
+
// Get current addresses before import
|
|
185
|
+
const addressesBefore = new Set(await this.inner.getAccounts());
|
|
186
|
+
// Import the new private key
|
|
187
|
+
await __classPrivateFieldGet(this, _SimpleKeyringV2_instances, "m", _SimpleKeyringV2_setPrivateKeys).call(this, [...currentPrivateKeys, privateKey]);
|
|
188
|
+
// Get addresses after import and find the newly added one
|
|
189
|
+
const addressesAfter = await this.inner.getAccounts();
|
|
190
|
+
// Find the new address by diffing the two sets
|
|
191
|
+
const newAddresses = addressesAfter.filter((addr) => !addressesBefore.has(addr));
|
|
192
|
+
if (newAddresses.length !== 1 || !newAddresses[0]) {
|
|
193
|
+
throw new Error('Failed to import private key');
|
|
194
|
+
}
|
|
195
|
+
return newAddresses[0];
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
//# sourceMappingURL=simple-keyring-v2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-keyring-v2.mjs","sourceRoot":"","sources":["../src/simple-keyring-v2.ts"],"names":[],"mappings":"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","sourcesContent":["import {\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} 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\n// eslint-disable-next-line @typescript-eslint/naming-convention\nimport type SimpleKeyring from './simple-keyring';\n\n/**\n * Methods supported by SimpleKeyring EOA accounts.\n * SimpleKeyring supports all standard signing methods plus encryption and app keys.\n */\nconst SIMPLE_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 simpleKeyringV2Capabilities: KeyringCapabilities = {\n scopes: [EthScope.Eoa],\n privateKey: {\n importFormats: [\n { encoding: PrivateKeyEncoding.Hexadecimal, type: EthAccountType.Eoa },\n ],\n exportFormats: [{ encoding: PrivateKeyEncoding.Hexadecimal }],\n },\n};\n\n/**\n * Concrete {@link KeyringV2} adapter for {@link SimpleKeyring}.\n *\n * This wrapper exposes the accounts and signing capabilities of the legacy\n * SimpleKeyring via the unified V2 interface.\n */\nexport type SimpleKeyringV2Options = {\n legacyKeyring: SimpleKeyring;\n};\n\nexport class SimpleKeyringV2\n extends EthKeyringWrapper<SimpleKeyring>\n implements KeyringV2\n{\n constructor(options: SimpleKeyringV2Options) {\n super({\n type: KeyringType.PrivateKey,\n inner: options.legacyKeyring,\n capabilities: simpleKeyringV2Capabilities,\n });\n }\n\n /**\n * Creates a KeyringAccount object for the given address and index.\n *\n * @param address - The account address.\n * @returns The created KeyringAccount.\n */\n #createKeyringAccount(address: Hex): KeyringAccount {\n const id = this.registry.register(address);\n\n const account: KeyringAccount = {\n id,\n type: EthAccountType.Eoa,\n address,\n scopes: [...this.capabilities.scopes],\n methods: [...SIMPLE_KEYRING_METHODS],\n options: {\n entropy: {\n type: KeyringAccountEntropyTypeOption.PrivateKey,\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 /**\n * Get all private keys from the inner SimpleKeyring.\n *\n * @returns An array of private keys in hexadecimal format.\n */\n async #getPrivateKeys(): Promise<string[]> {\n return await this.inner.serialize();\n }\n\n /**\n * Set private keys in the inner SimpleKeyring.\n *\n * @param privateKeys - An array of private keys in hexadecimal format.\n */\n async #setPrivateKeys(privateKeys: string[]): Promise<void> {\n await this.inner.deserialize(privateKeys);\n }\n\n /**\n * Executes a transactional update on the inner keyring state.\n * If the callback throws, the state is automatically rolled back.\n *\n * @param callback - A function that receives the current private keys and performs the update.\n * Should return the result on success, or throw to trigger rollback.\n * @returns The result of the callback.\n * @throws Error if the callback throws (after rollback).\n */\n async #withRollback<Result>(\n callback: (currentPrivateKeys: string[]) => Promise<Result>,\n ): Promise<Result> {\n const originalPrivateKeys = await this.#getPrivateKeys();\n\n try {\n return await callback(originalPrivateKeys);\n } catch (error) {\n // Rollback on error\n await this.#setPrivateKeys(originalPrivateKeys);\n throw error;\n }\n }\n\n /**\n * Import a private key and return the new address.\n * If the import fails (no new address added), rolls back to the original state.\n *\n * @param privateKey - The private key to import in hexadecimal format.\n * @returns The address of the newly imported account.\n * @throws Error if the import fails or no new address is added.\n */\n async #importPrivateKeyOrRollback(privateKey: string): Promise<Hex> {\n return this.#withRollback(async (currentPrivateKeys) => {\n // Get current addresses before import\n const addressesBefore = new Set(await this.inner.getAccounts());\n\n // Import the new private key\n await this.#setPrivateKeys([...currentPrivateKeys, privateKey]);\n\n // Get addresses after import and find the newly added one\n const addressesAfter = await this.inner.getAccounts();\n\n // Find the new address by diffing the two sets\n const newAddresses = addressesAfter.filter(\n (addr) => !addressesBefore.has(addr),\n );\n\n if (newAddresses.length !== 1 || !newAddresses[0]) {\n throw new Error('Failed to import private key');\n }\n\n return newAddresses[0];\n });\n }\n\n async getAccounts(): Promise<KeyringAccount[]> {\n const addresses = await this.inner.getAccounts();\n\n return addresses.map((address) => {\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);\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<KeyringAccount[]> {\n return this.withLock(async () => {\n // For SimpleKeyring, we only support private key import\n if (options.type !== 'private-key:import') {\n throw new Error(\n `Unsupported account creation type for SimpleKeyring: ${options.type}`,\n );\n }\n\n // Validate account type\n if (options.accountType !== EthAccountType.Eoa) {\n throw new Error(\n `Unsupported account type for SimpleKeyring: ${options.accountType}. Only '${EthAccountType.Eoa}' is supported.`,\n );\n }\n\n const { encoding, privateKey } = options;\n\n // Validate encoding\n if (encoding !== PrivateKeyEncoding.Hexadecimal) {\n throw new Error(\n `Unsupported encoding for SimpleKeyring: ${encoding}. Only '${PrivateKeyEncoding.Hexadecimal}' is supported.`,\n );\n }\n\n // Import the private key (with automatic rollback on failure)\n const newAddress = await this.#importPrivateKeyOrRollback(privateKey);\n\n // Create and return the new KeyringAccount\n const newAccount = this.#createKeyringAccount(newAddress);\n return [newAccount];\n });\n }\n\n /**\n * Delete an account from the keyring.\n *\n * @param accountId - The account ID to delete.\n */\n async deleteAccount(accountId: AccountId): Promise<void> {\n await this.withLock(async () => {\n const account = await this.getAccount(accountId);\n\n // Remove from the legacy keyring\n this.inner.removeAccount(account.address);\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 const requestedEncoding =\n options?.encoding ?? PrivateKeyEncoding.Hexadecimal;\n\n if (requestedEncoding !== PrivateKeyEncoding.Hexadecimal) {\n throw new Error(\n `Unsupported encoding for SimpleKeyring: ${requestedEncoding}. Only '${PrivateKeyEncoding.Hexadecimal}' is supported.`,\n );\n }\n\n const privateKeyHex = await this.inner.exportAccount(\n this.toHexAddress(account.address),\n );\n // Sanitize private key format\n const privateKey = add0x(privateKeyHex);\n\n const exported: ExportedAccount = {\n type: 'private-key',\n privateKey,\n encoding: PrivateKeyEncoding.Hexadecimal,\n };\n\n return exported;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask/eth-simple-keyring",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.1.1",
|
|
4
4
|
"description": "A simple standard interface for a series of Ethereum private keys.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ethereum",
|
|
@@ -46,7 +46,9 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@ethereumjs/util": "^9.1.0",
|
|
48
48
|
"@metamask/eth-sig-util": "^8.2.0",
|
|
49
|
-
"@metamask/
|
|
49
|
+
"@metamask/keyring-api": "^22.0.0",
|
|
50
|
+
"@metamask/keyring-sdk": "^1.1.0",
|
|
51
|
+
"@metamask/utils": "^11.10.0",
|
|
50
52
|
"ethereum-cryptography": "^2.1.2",
|
|
51
53
|
"randombytes": "^2.1.0"
|
|
52
54
|
},
|
|
@@ -55,7 +57,7 @@
|
|
|
55
57
|
"@lavamoat/allow-scripts": "^3.2.1",
|
|
56
58
|
"@lavamoat/preinstall-always-fail": "^2.1.0",
|
|
57
59
|
"@metamask/auto-changelog": "^3.4.4",
|
|
58
|
-
"@metamask/keyring-utils": "^3.
|
|
60
|
+
"@metamask/keyring-utils": "^3.2.0",
|
|
59
61
|
"@ts-bridge/cli": "^0.6.3",
|
|
60
62
|
"@types/ethereumjs-tx": "^1.0.1",
|
|
61
63
|
"@types/jest": "^29.5.12",
|