@rabby-wallet/eth-simple-keyring 4.2.1 → 5.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.
Files changed (3) hide show
  1. package/index.js +113 -40
  2. package/package.json +5 -1
  3. 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-util');
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
- const sigUtil = require('eth-sig-util');
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) => w.getPrivateKey().toString('hex')),
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((privateKey) => {
26
- const stripped = ethUtil.stripHexPrefix(privateKey);
27
- const buffer = Buffer.from(stripped, 'hex');
28
- const wallet = Wallet.fromPrivateKey(buffer);
29
- return wallet;
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
- newWallets.push(Wallet.generate());
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((w) =>
45
- ethUtil.bufferToHex(w.getAddress()),
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((w) => ethUtil.bufferToHex(w.getAddress())),
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 = this.getPrivateKeyFor(address, opts);
86
- const privKeyBuffer = Buffer.from(privKey, 'hex');
87
- const sig = sigUtil.personalSign(privKeyBuffer, { data: msgHex });
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(wallet.getPrivateKey());
95
- const sig = sigUtil.decrypt(encryptedData, privKey);
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 = this.getPrivateKeyFor(withAccount, opts);
116
- const sig = sigUtil.signTypedDataLegacy(privKey, { data: typedData });
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 = this.getPrivateKeyFor(withAccount, opts);
123
- const sig = sigUtil.signTypedData(privKey, { data: typedData });
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 = this.getPrivateKeyFor(withAccount, opts);
130
- const sig = sigUtil.signTypedData_v4(privKey, { data: typedData });
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 = this.getPrivateKeyFor(withAccount, opts);
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
- const privKey = ethUtil.toBuffer(wallet.getPrivateKey());
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
- wallet.getAddress().toString('hex'),
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(wallet.getPrivateKey().toString('hex'));
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((w) => ethUtil.bufferToHex(w.getAddress()).toLowerCase())
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
- (w) =>
187
- ethUtil.bufferToHex(w.getAddress()).toLowerCase() !==
188
- address.toLowerCase(),
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
- (w) => ethUtil.bufferToHex(w.getAddress()) === address,
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 privKey = wallet.getPrivateKey();
277
+ const { privateKey } = wallet;
206
278
  const appKeyOriginBuffer = Buffer.from(opts.withAppKeyOrigin, 'utf8');
207
- const appKeyBuffer = Buffer.concat([privKey, appKeyOriginBuffer]);
208
- const appKeyPrivKey = ethUtil.keccak(appKeyBuffer, 256);
209
- wallet = Wallet.fromPrivateKey(appKeyPrivKey);
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": "4.2.1",
3
+ "version": "5.0.0",
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/