@rabby-wallet/eth-simple-keyring 4.2.1 → 5.0.0-alpha
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/index.js +113 -40
- package/package.json +5 -1
- package/CHANGELOG.md +0 -9
package/index.js
CHANGED
|
@@ -1,9 +1,34 @@
|
|
|
1
1
|
const { EventEmitter } = require('events');
|
|
2
|
-
const Wallet = require('ethereumjs-wallet').default;
|
|
3
|
-
const ethUtil = require('ethereumjs
|
|
2
|
+
// const Wallet = require('ethereumjs-wallet').default;
|
|
3
|
+
const ethUtil = require('@ethereumjs/util');
|
|
4
|
+
const sigUtil = require('@metamask/eth-sig-util');
|
|
5
|
+
const { keccak256 } = require('ethereum-cryptography/keccak');
|
|
6
|
+
const { getRandomBytesSync } = require('ethereum-cryptography/random');
|
|
4
7
|
|
|
5
8
|
const type = 'Simple Key Pair';
|
|
6
|
-
|
|
9
|
+
|
|
10
|
+
function generateKey() {
|
|
11
|
+
const privateKey = getRandomBytesSync(32);
|
|
12
|
+
|
|
13
|
+
if (!ethUtil.isValidPrivate(privateKey)) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
'Private key does not satisfy the curve requirements (ie. it is invalid)',
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
return privateKey;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function add0x(hexadecimal) {
|
|
22
|
+
if (hexadecimal.startsWith('0x')) {
|
|
23
|
+
return hexadecimal;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (hexadecimal.startsWith('0X')) {
|
|
27
|
+
return `0x${hexadecimal.substring(2)}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return `0x${hexadecimal}`;
|
|
31
|
+
}
|
|
7
32
|
|
|
8
33
|
class SimpleKeyring extends EventEmitter {
|
|
9
34
|
constructor(opts) {
|
|
@@ -15,18 +40,23 @@ class SimpleKeyring extends EventEmitter {
|
|
|
15
40
|
|
|
16
41
|
serialize() {
|
|
17
42
|
return Promise.resolve(
|
|
18
|
-
this.wallets.map((w) =>
|
|
43
|
+
this.wallets.map((w) =>
|
|
44
|
+
ethUtil.stripHexPrefix(ethUtil.bytesToHex(w.privateKey)),
|
|
45
|
+
),
|
|
19
46
|
);
|
|
20
47
|
}
|
|
21
48
|
|
|
22
49
|
deserialize(privateKeys = []) {
|
|
23
50
|
return new Promise((resolve, reject) => {
|
|
24
51
|
try {
|
|
25
|
-
this.wallets = privateKeys.map((
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
52
|
+
this.wallets = privateKeys.map((hexPrivateKey) => {
|
|
53
|
+
let privk = hexPrivateKey;
|
|
54
|
+
if (!privk.startsWith('0x')) {
|
|
55
|
+
privk = ethUtil.addHexPrefix(privk);
|
|
56
|
+
}
|
|
57
|
+
const privateKey = ethUtil.hexToBytes(privk);
|
|
58
|
+
const publicKey = ethUtil.privateToPublic(privateKey);
|
|
59
|
+
return { privateKey, publicKey };
|
|
30
60
|
});
|
|
31
61
|
} catch (e) {
|
|
32
62
|
reject(e);
|
|
@@ -38,25 +68,31 @@ class SimpleKeyring extends EventEmitter {
|
|
|
38
68
|
addAccounts(n = 1) {
|
|
39
69
|
const newWallets = [];
|
|
40
70
|
for (let i = 0; i < n; i++) {
|
|
41
|
-
|
|
71
|
+
const privateKey = generateKey();
|
|
72
|
+
newWallets.push({
|
|
73
|
+
privateKey,
|
|
74
|
+
publicKey: ethUtil.privateToPublic(privateKey),
|
|
75
|
+
});
|
|
42
76
|
}
|
|
43
77
|
this.wallets = this.wallets.concat(newWallets);
|
|
44
|
-
const hexWallets = newWallets.map((
|
|
45
|
-
ethUtil.
|
|
78
|
+
const hexWallets = newWallets.map(({ publicKey }) =>
|
|
79
|
+
add0x(ethUtil.bytesToHex(ethUtil.publicToAddress(publicKey))),
|
|
46
80
|
);
|
|
47
81
|
return Promise.resolve(hexWallets);
|
|
48
82
|
}
|
|
49
83
|
|
|
50
84
|
getAccounts() {
|
|
51
85
|
return Promise.resolve(
|
|
52
|
-
this.wallets.map((
|
|
86
|
+
this.wallets.map(({ publicKey }) => {
|
|
87
|
+
return add0x(ethUtil.bytesToHex(ethUtil.publicToAddress(publicKey)));
|
|
88
|
+
}),
|
|
53
89
|
);
|
|
54
90
|
}
|
|
55
91
|
|
|
56
92
|
// tx is an instance of the ethereumjs-transaction class.
|
|
57
93
|
signTransaction(address, tx, opts = {}) {
|
|
58
|
-
const privKey = this.getPrivateKeyFor(address, opts);
|
|
59
|
-
const signedTx = tx.sign(privKey);
|
|
94
|
+
const privKey = ethUtil.addHexPrefix(this.getPrivateKeyFor(address, opts));
|
|
95
|
+
const signedTx = tx.sign(Buffer.from(privKey, 'hex'));
|
|
60
96
|
// Newer versions of Ethereumjs-tx are immutable and return a new tx object
|
|
61
97
|
return Promise.resolve(signedTx === undefined ? tx : signedTx);
|
|
62
98
|
}
|
|
@@ -82,17 +118,26 @@ class SimpleKeyring extends EventEmitter {
|
|
|
82
118
|
|
|
83
119
|
// For personal_sign, we need to prefix the message:
|
|
84
120
|
signPersonalMessage(address, msgHex, opts = {}) {
|
|
85
|
-
const privKey =
|
|
86
|
-
|
|
87
|
-
|
|
121
|
+
const privKey = ethUtil.stripHexPrefix(
|
|
122
|
+
ethUtil.bytesToHex(this.getPrivateKeyFor(address, opts)),
|
|
123
|
+
);
|
|
124
|
+
const sig = sigUtil.personalSign({
|
|
125
|
+
privateKey: privKey,
|
|
126
|
+
data: msgHex,
|
|
127
|
+
});
|
|
88
128
|
return Promise.resolve(sig);
|
|
89
129
|
}
|
|
90
130
|
|
|
91
131
|
// For eth_decryptMessage:
|
|
92
132
|
decryptMessage(withAccount, encryptedData) {
|
|
93
133
|
const wallet = this._getWalletForAccount(withAccount);
|
|
94
|
-
const privKey = ethUtil.stripHexPrefix(
|
|
95
|
-
|
|
134
|
+
const privKey = ethUtil.stripHexPrefix(
|
|
135
|
+
ethUtil.bytesToHex(wallet.privateKey),
|
|
136
|
+
);
|
|
137
|
+
const sig = sigUtil.decrypt({
|
|
138
|
+
encryptedData,
|
|
139
|
+
privateKey: privKey,
|
|
140
|
+
});
|
|
96
141
|
return Promise.resolve(sig);
|
|
97
142
|
}
|
|
98
143
|
|
|
@@ -112,28 +157,48 @@ class SimpleKeyring extends EventEmitter {
|
|
|
112
157
|
|
|
113
158
|
// personal_signTypedData, signs data along with the schema
|
|
114
159
|
signTypedData_v1(withAccount, typedData, opts = {}) {
|
|
115
|
-
const privKey =
|
|
116
|
-
|
|
160
|
+
const privKey = ethUtil.stripHexPrefix(
|
|
161
|
+
ethUtil.bytesToHex(this.getPrivateKeyFor(withAccount, opts)),
|
|
162
|
+
);
|
|
163
|
+
const sig = sigUtil.signTypedData({
|
|
164
|
+
privateKey: Buffer.from(privKey, 'hex'),
|
|
165
|
+
data: typedData,
|
|
166
|
+
version: sigUtil.SignTypedDataVersion.V1,
|
|
167
|
+
});
|
|
117
168
|
return Promise.resolve(sig);
|
|
118
169
|
}
|
|
119
170
|
|
|
120
171
|
// personal_signTypedData, signs data along with the schema
|
|
121
172
|
signTypedData_v3(withAccount, typedData, opts = {}) {
|
|
122
|
-
const privKey =
|
|
123
|
-
|
|
173
|
+
const privKey = ethUtil.stripHexPrefix(
|
|
174
|
+
ethUtil.bytesToHex(this.getPrivateKeyFor(withAccount, opts)),
|
|
175
|
+
);
|
|
176
|
+
const sig = sigUtil.signTypedData({
|
|
177
|
+
privateKey: Buffer.from(privKey, 'hex'),
|
|
178
|
+
data: typedData,
|
|
179
|
+
version: sigUtil.SignTypedDataVersion.V3,
|
|
180
|
+
});
|
|
124
181
|
return Promise.resolve(sig);
|
|
125
182
|
}
|
|
126
183
|
|
|
127
184
|
// personal_signTypedData, signs data along with the schema
|
|
128
185
|
signTypedData_v4(withAccount, typedData, opts = {}) {
|
|
129
|
-
const privKey =
|
|
130
|
-
|
|
186
|
+
const privKey = ethUtil.stripHexPrefix(
|
|
187
|
+
ethUtil.bytesToHex(this.getPrivateKeyFor(withAccount, opts)),
|
|
188
|
+
);
|
|
189
|
+
const sig = sigUtil.signTypedData({
|
|
190
|
+
privateKey: Buffer.from(privKey, 'hex'),
|
|
191
|
+
data: typedData,
|
|
192
|
+
version: sigUtil.SignTypedDataVersion.V4,
|
|
193
|
+
});
|
|
131
194
|
return Promise.resolve(sig);
|
|
132
195
|
}
|
|
133
196
|
|
|
134
197
|
// get public key for nacl
|
|
135
198
|
getEncryptionPublicKey(withAccount, opts = {}) {
|
|
136
|
-
const privKey =
|
|
199
|
+
const privKey = ethUtil.stripHexPrefix(
|
|
200
|
+
ethUtil.bytesToHex(this.getPrivateKeyFor(withAccount, opts)),
|
|
201
|
+
);
|
|
137
202
|
const publicKey = sigUtil.getEncryptionPublicKey(privKey);
|
|
138
203
|
return Promise.resolve(publicKey);
|
|
139
204
|
}
|
|
@@ -143,8 +208,7 @@ class SimpleKeyring extends EventEmitter {
|
|
|
143
208
|
throw new Error('Must specify address.');
|
|
144
209
|
}
|
|
145
210
|
const wallet = this._getWalletForAccount(address, opts);
|
|
146
|
-
|
|
147
|
-
return privKey;
|
|
211
|
+
return wallet.privateKey;
|
|
148
212
|
}
|
|
149
213
|
|
|
150
214
|
// returns an address specific to an app
|
|
@@ -158,7 +222,7 @@ class SimpleKeyring extends EventEmitter {
|
|
|
158
222
|
withAppKeyOrigin: origin,
|
|
159
223
|
});
|
|
160
224
|
const appKeyAddress = sigUtil.normalize(
|
|
161
|
-
|
|
225
|
+
ethUtil.bytesToHex(ethUtil.publicToAddress(wallet.publicKey)),
|
|
162
226
|
);
|
|
163
227
|
return resolve(appKeyAddress);
|
|
164
228
|
} catch (e) {
|
|
@@ -170,22 +234,27 @@ class SimpleKeyring extends EventEmitter {
|
|
|
170
234
|
// exportAccount should return a hex-encoded private key:
|
|
171
235
|
exportAccount(address, opts = {}) {
|
|
172
236
|
const wallet = this._getWalletForAccount(address, opts);
|
|
173
|
-
return Promise.resolve(
|
|
237
|
+
return Promise.resolve(ethUtil.bytesToHex(wallet.privateKey));
|
|
174
238
|
}
|
|
175
239
|
|
|
176
240
|
removeAccount(address) {
|
|
177
241
|
if (
|
|
178
242
|
!this.wallets
|
|
179
|
-
.map((
|
|
243
|
+
.map(({ publicKey }) =>
|
|
244
|
+
add0x(
|
|
245
|
+
ethUtil.bytesToHex(ethUtil.publicToAddress(publicKey)),
|
|
246
|
+
).toLowerCase(),
|
|
247
|
+
)
|
|
180
248
|
.includes(address.toLowerCase())
|
|
181
249
|
) {
|
|
182
250
|
throw new Error(`Address ${address} not found in this keyring`);
|
|
183
251
|
}
|
|
184
252
|
|
|
185
253
|
this.wallets = this.wallets.filter(
|
|
186
|
-
(
|
|
187
|
-
|
|
188
|
-
|
|
254
|
+
({ publicKey }) =>
|
|
255
|
+
add0x(
|
|
256
|
+
ethUtil.bytesToHex(ethUtil.publicToAddress(publicKey)),
|
|
257
|
+
).toLowerCase() !== address.toLowerCase(),
|
|
189
258
|
);
|
|
190
259
|
}
|
|
191
260
|
|
|
@@ -195,18 +264,22 @@ class SimpleKeyring extends EventEmitter {
|
|
|
195
264
|
_getWalletForAccount(account, opts = {}) {
|
|
196
265
|
const address = sigUtil.normalize(account);
|
|
197
266
|
let wallet = this.wallets.find(
|
|
198
|
-
(
|
|
267
|
+
({ publicKey }) =>
|
|
268
|
+
add0x(
|
|
269
|
+
ethUtil.bytesToHex(ethUtil.publicToAddress(publicKey)),
|
|
270
|
+
).toLowerCase() === address.toLowerCase(),
|
|
199
271
|
);
|
|
200
272
|
if (!wallet) {
|
|
201
273
|
throw new Error('Simple Keyring - Unable to find matching address.');
|
|
202
274
|
}
|
|
203
275
|
|
|
204
276
|
if (opts.withAppKeyOrigin) {
|
|
205
|
-
const
|
|
277
|
+
const { privateKey } = wallet;
|
|
206
278
|
const appKeyOriginBuffer = Buffer.from(opts.withAppKeyOrigin, 'utf8');
|
|
207
|
-
const appKeyBuffer = Buffer.concat([
|
|
208
|
-
const
|
|
209
|
-
|
|
279
|
+
const appKeyBuffer = Buffer.concat([privateKey, appKeyOriginBuffer]);
|
|
280
|
+
const appKeyPrivateKey = keccak256(appKeyBuffer);
|
|
281
|
+
const appKeyPublicKey = ethUtil.privateToPublic(appKeyPrivateKey);
|
|
282
|
+
wallet = { privateKey: appKeyPrivateKey, publicKey: appKeyPublicKey };
|
|
210
283
|
}
|
|
211
284
|
|
|
212
285
|
return wallet;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rabby-wallet/eth-simple-keyring",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0-alpha",
|
|
4
4
|
"description": "A simple standard interface for a series of Ethereum private keys.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ethereum",
|
|
@@ -30,8 +30,12 @@
|
|
|
30
30
|
"lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
+
"@ethereumjs/util": "^9.0.0",
|
|
34
|
+
"@metamask/eth-sig-util": "^7.0.0",
|
|
35
|
+
"@metamask/utils": "^8.1.0",
|
|
33
36
|
"chai": "^4.3.4",
|
|
34
37
|
"eth-sig-util": "^3.0.1",
|
|
38
|
+
"ethereum-cryptography": "^2.1.2",
|
|
35
39
|
"ethereumjs-tx": "^2.1.2",
|
|
36
40
|
"ethereumjs-util": "^7.0.9",
|
|
37
41
|
"ethereumjs-wallet": "^1.0.2",
|
package/CHANGELOG.md
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
All notable changes to this project will be documented in this file.
|
|
3
|
-
|
|
4
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
-
|
|
7
|
-
## [Unreleased]
|
|
8
|
-
|
|
9
|
-
[Unreleased]: https://github.com/MetaMask/eth-simple-keyring/
|