@metamask/eth-hd-keyring 5.0.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,11 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- ## [5.0.1]
9
+ ## [6.0.0]
10
+ ### Changed
11
+ - Revert mnemonic serialization format from `Record<number, number>` (i.e. a stringified `Uint8Array`) which was introduced in v5.0.0 back to an untyped array of utf8 encoded bytes, which was the format prior to v5.0.0 ([#81](https://github.com/MetaMask/eth-hd-keyring/pull/81))
12
+
13
+ ## [5.0.1] [DEPRECATED]
10
14
  ### Removed
11
15
  - Remove prepack script and references in order to fix publish release flow ([#77](https://github.com/MetaMask/eth-hd-keyring/pull/77))
12
16
 
13
- ## [5.0.0]
17
+ ## [5.0.0] [DEPRECATED]
14
18
  ### Changed
15
19
  - **BREAKING**: Update minimum Node.js version from v12 to v14 ([#67](https://github.com/MetaMask/eth-hd-keyring/pull/67))
16
20
  - **BREAKING:** Makes version-specific `signTypedData` methods private ([#71](https://github.com/MetaMask/eth-hd-keyring/pull/71))
@@ -54,7 +58,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
54
58
  - 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`.
55
59
  - Package name changed from `eth-hd-keyring` to `@metamask/eth-hd-keyring`.
56
60
 
57
- [Unreleased]: https://github.com/MetaMask/eth-hd-keyring/compare/v5.0.1...HEAD
61
+ [Unreleased]: https://github.com/MetaMask/eth-hd-keyring/compare/v6.0.0...HEAD
62
+ [6.0.0]: https://github.com/MetaMask/eth-hd-keyring/compare/v5.0.1...v6.0.0
58
63
  [5.0.1]: https://github.com/MetaMask/eth-hd-keyring/compare/v5.0.0...v5.0.1
59
64
  [5.0.0]: https://github.com/MetaMask/eth-hd-keyring/compare/v4.0.2...v5.0.0
60
65
  [4.0.2]: https://github.com/MetaMask/eth-hd-keyring/compare/v4.0.1...v4.0.2
package/index.js CHANGED
@@ -80,8 +80,13 @@ class HdKeyring {
80
80
  }
81
81
 
82
82
  serialize() {
83
+ const mnemonicAsString = this._uint8ArrayToString(this.mnemonic);
84
+ const uint8ArrayMnemonic = new TextEncoder('utf-8').encode(
85
+ mnemonicAsString,
86
+ );
87
+
83
88
  return Promise.resolve({
84
- mnemonic: this._mnemonicToUint8Array(this.mnemonic),
89
+ mnemonic: Array.from(uint8ArrayMnemonic),
85
90
  numberOfAccounts: this._wallets.length,
86
91
  hdPath: this.hdPath,
87
92
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/eth-hd-keyring",
3
- "version": "5.0.1",
3
+ "version": "6.0.0",
4
4
  "description": "A simple standard interface for a seed phrase generated set of Ethereum accounts.",
5
5
  "keywords": [
6
6
  "ethereum",
package/test/index.js CHANGED
@@ -37,11 +37,6 @@ const secondAcct = '0x1b00aed43a693f3a957f9feb5cc08afa031e37a0';
37
37
  const notKeyringAddress = '0xbD20F6F5F1616947a39E11926E78ec94817B3931';
38
38
 
39
39
  describe('hd-keyring', () => {
40
- let keyring;
41
- beforeEach(() => {
42
- keyring = new HdKeyring();
43
- });
44
-
45
40
  describe('compare old bip39 implementation with new', () => {
46
41
  it('should derive the same accounts from the same mnemonics', async () => {
47
42
  const mnemonics = [];
@@ -70,7 +65,7 @@ describe('hd-keyring', () => {
70
65
 
71
66
  describe('constructor', () => {
72
67
  it('constructs with a typeof string mnemonic', async () => {
73
- keyring = new HdKeyring({
68
+ const keyring = new HdKeyring({
74
69
  mnemonic: sampleMnemonic,
75
70
  numberOfAccounts: 2,
76
71
  });
@@ -81,7 +76,7 @@ describe('hd-keyring', () => {
81
76
  });
82
77
 
83
78
  it('constructs with a typeof buffer mnemonic', async () => {
84
- keyring = new HdKeyring({
79
+ const keyring = new HdKeyring({
85
80
  mnemonic: Buffer.from(sampleMnemonic, 'utf8'),
86
81
  numberOfAccounts: 2,
87
82
  });
@@ -98,7 +93,7 @@ describe('hd-keyring', () => {
98
93
  const uInt8ArrayOfMnemonic = new Uint8Array(
99
94
  new Uint16Array(indices).buffer,
100
95
  );
101
- keyring = new HdKeyring({
96
+ const keyring = new HdKeyring({
102
97
  mnemonic: uInt8ArrayOfMnemonic,
103
98
  numberOfAccounts: 2,
104
99
  });
@@ -134,6 +129,7 @@ describe('hd-keyring', () => {
134
129
  const alreadyProvidedError =
135
130
  'Eth-Hd-Keyring: Secret recovery phrase already provided';
136
131
  it('double generateRandomMnemonic', () => {
132
+ const keyring = new HdKeyring();
137
133
  keyring.generateRandomMnemonic();
138
134
  expect(() => {
139
135
  keyring.generateRandomMnemonic();
@@ -141,7 +137,7 @@ describe('hd-keyring', () => {
141
137
  });
142
138
 
143
139
  it('constructor + generateRandomMnemonic', () => {
144
- keyring = new HdKeyring({
140
+ const keyring = new HdKeyring({
145
141
  mnemonic: sampleMnemonic,
146
142
  numberOfAccounts: 2,
147
143
  });
@@ -152,7 +148,7 @@ describe('hd-keyring', () => {
152
148
  });
153
149
 
154
150
  it('constructor + deserialize', () => {
155
- keyring = new HdKeyring({
151
+ const keyring = new HdKeyring({
156
152
  mnemonic: sampleMnemonic,
157
153
  numberOfAccounts: 2,
158
154
  });
@@ -175,6 +171,8 @@ describe('hd-keyring', () => {
175
171
 
176
172
  describe('#type', () => {
177
173
  it('returns the correct value', () => {
174
+ const keyring = new HdKeyring();
175
+
178
176
  const { type } = keyring;
179
177
  const correct = HdKeyring.type;
180
178
  expect(type).toStrictEqual(correct);
@@ -182,39 +180,46 @@ describe('hd-keyring', () => {
182
180
  });
183
181
 
184
182
  describe('#serialize mnemonic.', () => {
185
- it('serializes mnemonic stored as a buffer to a Uint8Array', async () => {
186
- keyring.mnemonic = oldMMForkBIP39.generateMnemonic();
187
- const mnemonicAsUint8Array = keyring._stringToUint8Array(
188
- keyring.mnemonic.toString(),
189
- );
183
+ it('serializes the mnemonic in the same format as previous version (an array of utf8 encoded bytes)', async () => {
184
+ const keyring = new HdKeyring({
185
+ mnemonic: sampleMnemonic,
186
+ });
187
+ // uses previous version of eth-hd-keyring to ensure backwards compatibility
188
+ const oldHDKeyring = new OldHdKeyring({ mnemonic: sampleMnemonic });
189
+ const { mnemonic: oldKeyringSerializedMnemonic } =
190
+ await oldHDKeyring.serialize();
191
+
190
192
  const output = await keyring.serialize();
191
- expect(output.numberOfAccounts).toBe(0);
192
- expect(output.mnemonic).toStrictEqual(mnemonicAsUint8Array);
193
+ expect(output.mnemonic).toStrictEqual(oldKeyringSerializedMnemonic);
193
194
  });
194
195
 
195
- it('serializes keyring data with mnemonic stored as a Uint8Array', async () => {
196
- keyring.generateRandomMnemonic();
197
- const { mnemonic } = keyring;
198
- const hdpath = keyring.hdPath;
199
- keyring.addAccounts(1);
196
+ it('serializes mnemonic passed in as a string to an array of utf8 encoded bytes', async () => {
197
+ const keyring = new HdKeyring({
198
+ mnemonic: sampleMnemonic,
199
+ });
200
200
  const output = await keyring.serialize();
201
- expect(output.numberOfAccounts).toBe(1);
202
- expect(output.hdPath).toStrictEqual(hdpath);
203
- expect(output.mnemonic).toStrictEqual(mnemonic);
201
+ // this Buffer.from(...).toString() is the method of converting from an array of utf8 encoded bytes back to a string
202
+ const mnemonicAsString = Buffer.from(output.mnemonic).toString();
203
+ expect(mnemonicAsString).toStrictEqual(sampleMnemonic);
204
204
  });
205
205
 
206
- it('serializes mnemonic stored as a string', async () => {
207
- keyring.mnemonic = sampleMnemonic;
206
+ it('serializes mnemonic passed in as a an array of utf8 encoded bytes in the same format', async () => {
207
+ const uint8Array = new TextEncoder('utf-8').encode(sampleMnemonic);
208
+ const mnemonicAsArrayOfUtf8EncodedBytes = Array.from(uint8Array);
209
+ const keyring = new HdKeyring({
210
+ mnemonic: mnemonicAsArrayOfUtf8EncodedBytes,
211
+ });
212
+
208
213
  const output = await keyring.serialize();
209
- expect(output.numberOfAccounts).toBe(0);
210
- expect(output.mnemonic).toStrictEqual(
211
- keyring._stringToUint8Array(sampleMnemonic),
212
- );
214
+ // this Buffer.from(...).toString() is the method of converting from an array of utf8 encoded bytes back to a string
215
+ const mnemonicAsString = Buffer.from(output.mnemonic).toString();
216
+ expect(mnemonicAsString).toStrictEqual(sampleMnemonic);
213
217
  });
214
218
  });
215
219
 
216
220
  describe('#deserialize a private key', () => {
217
221
  it('serializes what it deserializes', async () => {
222
+ const keyring = new HdKeyring();
218
223
  await keyring.deserialize({
219
224
  mnemonic: sampleMnemonic,
220
225
  numberOfAccounts: 1,
@@ -228,7 +233,7 @@ describe('hd-keyring', () => {
228
233
  expect(accountsSecondCheck[1]).toStrictEqual(secondAcct);
229
234
  expect(accountsSecondCheck).toHaveLength(2);
230
235
  const serialized = await keyring.serialize();
231
- expect(keyring._uint8ArrayToString(serialized.mnemonic)).toStrictEqual(
236
+ expect(Buffer.from(serialized.mnemonic).toString()).toStrictEqual(
232
237
  sampleMnemonic,
233
238
  );
234
239
  });
@@ -237,6 +242,7 @@ describe('hd-keyring', () => {
237
242
  describe('#addAccounts', () => {
238
243
  describe('with no arguments', () => {
239
244
  it('creates a single wallet', async () => {
245
+ const keyring = new HdKeyring();
240
246
  keyring.generateRandomMnemonic();
241
247
  await keyring.addAccounts();
242
248
  const accounts = await keyring.getAccounts();
@@ -244,6 +250,7 @@ describe('hd-keyring', () => {
244
250
  });
245
251
 
246
252
  it('throws an error when no SRP has been generated yet', async () => {
253
+ const keyring = new HdKeyring();
247
254
  expect(() => keyring.addAccounts()).toThrow(
248
255
  'Eth-Hd-Keyring: No secret recovery phrase provided',
249
256
  );
@@ -252,6 +259,7 @@ describe('hd-keyring', () => {
252
259
 
253
260
  describe('with a numeric argument', () => {
254
261
  it('creates that number of wallets', async () => {
262
+ const keyring = new HdKeyring();
255
263
  keyring.generateRandomMnemonic();
256
264
  await keyring.addAccounts(3);
257
265
  const accounts = await keyring.getAccounts();
@@ -262,6 +270,8 @@ describe('hd-keyring', () => {
262
270
 
263
271
  describe('#signPersonalMessage', () => {
264
272
  it('returns the expected value', async () => {
273
+ const keyring = new HdKeyring();
274
+
265
275
  const address = firstAcct;
266
276
  const message = '0x68656c6c6f20776f726c64';
267
277
 
@@ -283,8 +293,8 @@ describe('hd-keyring', () => {
283
293
 
284
294
  describe('#signTypedData', () => {
285
295
  it('can recover a basic signature', async () => {
296
+ const keyring = new HdKeyring();
286
297
  Buffer.from(privKeyHex, 'hex');
287
-
288
298
  const typedData = [
289
299
  {
290
300
  type: 'string',
@@ -316,6 +326,7 @@ describe('hd-keyring', () => {
316
326
  ];
317
327
 
318
328
  it('signs in a compliant and recoverable way', async () => {
329
+ const keyring = new HdKeyring();
319
330
  keyring.generateRandomMnemonic();
320
331
  await keyring.addAccounts(1);
321
332
  const addresses = await keyring.getAccounts();
@@ -334,6 +345,7 @@ describe('hd-keyring', () => {
334
345
 
335
346
  describe('#signTypedData_v3', () => {
336
347
  it('signs in a compliant and recoverable way', async () => {
348
+ const keyring = new HdKeyring();
337
349
  const typedData = {
338
350
  types: {
339
351
  EIP712Domain: [],
@@ -363,6 +375,7 @@ describe('hd-keyring', () => {
363
375
 
364
376
  describe('#signTypedData_v3 signature verification', () => {
365
377
  it('signs in a recoverable way.', async () => {
378
+ const keyring = new HdKeyring();
366
379
  const typedData = {
367
380
  types: {
368
381
  EIP712Domain: [
@@ -419,6 +432,7 @@ describe('hd-keyring', () => {
419
432
 
420
433
  describe('custom hd paths', () => {
421
434
  it('can deserialize with an hdPath param and generate the same accounts.', async () => {
435
+ const keyring = new HdKeyring();
422
436
  const hdPathString = `m/44'/60'/0'/0`;
423
437
  keyring.deserialize({
424
438
  mnemonic: sampleMnemonic,
@@ -432,8 +446,8 @@ describe('hd-keyring', () => {
432
446
  });
433
447
 
434
448
  it('can deserialize with an hdPath param and generate different accounts.', async () => {
449
+ const keyring = new HdKeyring();
435
450
  const hdPathString = `m/44'/60'/0'/1`;
436
-
437
451
  keyring.deserialize({
438
452
  mnemonic: sampleMnemonic,
439
453
  numberOfAccounts: 1,
@@ -454,14 +468,14 @@ describe('hd-keyring', () => {
454
468
 
455
469
  for (let i = 0; i < 1e3; i++) {
456
470
 
457
- keyring = new HdKeyring({
471
+ const keyring = new HdKeyring({
458
472
  numberOfAccounts: 1,
459
473
  })
460
474
  const originalAccounts = await keyring.getAccounts()
461
475
  const serialized = await keyring.serialize()
462
476
  const mnemonic = serialized.mnemonic
463
477
 
464
- keyring = new HdKeyring({
478
+ const keyring = new HdKeyring({
465
479
  numberOfAccounts: 1,
466
480
  mnemonic,
467
481
  })
@@ -481,6 +495,7 @@ describe('hd-keyring', () => {
481
495
 
482
496
  describe('signing methods withAppKeyOrigin option', () => {
483
497
  it('should signPersonalMessage with the expected key when passed a withAppKeyOrigin', async () => {
498
+ const keyring = new HdKeyring();
484
499
  const address = firstAcct;
485
500
  const message = '0x68656c6c6f20776f726c64';
486
501
 
@@ -502,6 +517,7 @@ describe('hd-keyring', () => {
502
517
  });
503
518
 
504
519
  it('should signTypedData with the expected key when passed a withAppKeyOrigin', async () => {
520
+ const keyring = new HdKeyring();
505
521
  const address = firstAcct;
506
522
  const typedData = {
507
523
  types: {
@@ -546,6 +562,7 @@ describe('hd-keyring', () => {
546
562
  '0xb21867b2221db0172e970b7370825b71c57823ff8714168ce9748f32f450e2c43d0fe396eb5b5f59284b7fd108c8cf61a6180a6756bdd3d4b7b9ccc4ac6d51611b';
547
563
 
548
564
  it('passes the dennis test', async function () {
565
+ const keyring = new HdKeyring();
549
566
  await keyring.deserialize({
550
567
  mnemonic: sampleMnemonic,
551
568
  numberOfAccounts: 1,
@@ -555,6 +572,7 @@ describe('hd-keyring', () => {
555
572
  });
556
573
 
557
574
  it('reliably can decode messages it signs', async function () {
575
+ const keyring = new HdKeyring();
558
576
  await keyring.deserialize({
559
577
  mnemonic: sampleMnemonic,
560
578
  numberOfAccounts: 1,
@@ -583,6 +601,7 @@ describe('hd-keyring', () => {
583
601
  });
584
602
 
585
603
  it('throw error for invalid message', async function () {
604
+ const keyring = new HdKeyring();
586
605
  await keyring.deserialize({
587
606
  mnemonic: sampleMnemonic,
588
607
  numberOfAccounts: 1,
@@ -594,6 +613,7 @@ describe('hd-keyring', () => {
594
613
  });
595
614
 
596
615
  it('throw error if empty address is passed', async function () {
616
+ const keyring = new HdKeyring();
597
617
  await keyring.deserialize({
598
618
  mnemonic: sampleMnemonic,
599
619
  numberOfAccounts: 1,
@@ -605,6 +625,7 @@ describe('hd-keyring', () => {
605
625
  });
606
626
 
607
627
  it('throw error if address not associated with the current keyring is passed', async function () {
628
+ const keyring = new HdKeyring();
608
629
  await keyring.deserialize({
609
630
  mnemonic: sampleMnemonic,
610
631
  numberOfAccounts: 1,
@@ -617,6 +638,7 @@ describe('hd-keyring', () => {
617
638
  });
618
639
 
619
640
  describe('#removeAccount', function () {
641
+ let keyring;
620
642
  beforeEach(() => {
621
643
  keyring = new HdKeyring({
622
644
  mnemonic: sampleMnemonic,
@@ -645,6 +667,7 @@ describe('hd-keyring', () => {
645
667
  });
646
668
 
647
669
  describe('getAppKeyAddress', function () {
670
+ let keyring;
648
671
  beforeEach(() => {
649
672
  keyring = new HdKeyring({
650
673
  mnemonic: sampleMnemonic,
@@ -710,6 +733,7 @@ describe('hd-keyring', () => {
710
733
  });
711
734
 
712
735
  describe('exportAccount', function () {
736
+ let keyring;
713
737
  beforeEach(() => {
714
738
  keyring = new HdKeyring({
715
739
  mnemonic: sampleMnemonic,
@@ -734,6 +758,7 @@ describe('hd-keyring', () => {
734
758
 
735
759
  describe('#encryptionPublicKey', function () {
736
760
  const publicKey = 'LV7lWhd0mUDcvxkMU2o6uKXftu25zq4bMYdmMqppXic=';
761
+ let keyring;
737
762
  beforeEach(() => {
738
763
  keyring = new HdKeyring({
739
764
  mnemonic: sampleMnemonic,
@@ -762,6 +787,7 @@ describe('hd-keyring', () => {
762
787
  });
763
788
 
764
789
  describe('#signTypedData V4 signature verification', function () {
790
+ let keyring;
765
791
  beforeEach(() => {
766
792
  keyring = new HdKeyring({
767
793
  mnemonic: sampleMnemonic,
@@ -842,7 +868,7 @@ describe('hd-keyring', () => {
842
868
 
843
869
  describe('#decryptMessage', function () {
844
870
  const message = 'Hello world!';
845
- let encryptedMessage;
871
+ let encryptedMessage, keyring;
846
872
 
847
873
  beforeEach(async () => {
848
874
  keyring = new HdKeyring({
@@ -882,6 +908,7 @@ describe('hd-keyring', () => {
882
908
  });
883
909
 
884
910
  describe('#signTransaction', function () {
911
+ let keyring;
885
912
  beforeEach(() => {
886
913
  keyring = new HdKeyring({
887
914
  mnemonic: sampleMnemonic,