@@ -4,14 +4,17 @@ const sigUtil = require('eth-sig-util');
44const normalizeAddress = sigUtil . normalize ;
55const sinon = require ( 'sinon' ) ;
66const Wallet = require ( 'ethereumjs-wallet' ) . default ;
7-
7+ const HdKeyring = require ( '@metamask/eth-hd-keyring' ) ;
88const KeyringController = require ( '..' ) ;
99const mockEncryptor = require ( './lib/mock-encryptor' ) ;
1010
1111const password = 'password123' ;
1212const walletOneSeedWords =
1313 'puzzle seed penalty soldier say clay field arctic metal hen cage runway' ;
1414const walletOneAddresses = [ '0xef35ca8ebb9669a35c31b5f6f249a9941a812ac1' ] ;
15+ const walletOnePrivateAddress = [
16+ 'ace918800411c0b96b915f76efbbd4d50e6c997180fee58e01f60d3a412d2f7e' ,
17+ ] ;
1518
1619const walletTwoSeedWords =
1720 'urge letter protect palace city barely security section midnight wealth south deer' ;
@@ -107,6 +110,16 @@ describe('KeyringController', function () {
107110 expect ( actualPassword ) . toBe ( password ) ;
108111 } ) ;
109112 } ) ;
113+
114+ it ( 'should throw error if accounts are not generated correctly' , async ( ) => {
115+ jest
116+ . spyOn ( HdKeyring . prototype , 'getAccounts' )
117+ . mockImplementation ( ( ) => Promise . resolve ( [ ] ) ) ;
118+
119+ await expect ( ( ) =>
120+ keyringController . createNewVaultAndKeychain ( password ) ,
121+ ) . rejects . toThrow ( 'KeyringController - No account found on keychain.' ) ;
122+ } ) ;
110123 } ) ;
111124
112125 describe ( 'createNewVaultAndRestore' , function ( ) {
@@ -159,6 +172,19 @@ describe('KeyringController', function () {
159172 expect ( allAccountsAfter ) . toHaveLength ( 1 ) ;
160173 expect ( allAccountsAfter [ 0 ] ) . toBe ( walletTwoAddresses [ 0 ] ) ;
161174 } ) ;
175+
176+ it ( 'throws error if accounts are not created properly' , async ( ) => {
177+ jest
178+ . spyOn ( HdKeyring . prototype , 'getAccounts' )
179+ . mockImplementation ( ( ) => Promise . resolve ( [ ] ) ) ;
180+
181+ await expect ( ( ) =>
182+ keyringController . createNewVaultAndRestore (
183+ password ,
184+ walletTwoSeedWords ,
185+ ) ,
186+ ) . rejects . toThrow ( 'KeyringController - First Account not found.' ) ;
187+ } ) ;
162188 } ) ;
163189
164190 describe ( 'addNewKeyring' , function ( ) {
@@ -267,10 +293,12 @@ describe('KeyringController', function () {
267293 await keyringController . addNewKeyring ( 'Simple Key Pair' , [
268294 account . privateKey ,
269295 ] ) ;
296+ expect ( keyringController . keyrings ) . toHaveLength ( 2 ) ;
270297
271298 // remove that account that we just added
272299 await keyringController . removeAccount ( account . publicKey ) ;
273300
301+ expect ( keyringController . keyrings ) . toHaveLength ( 1 ) ;
274302 // fetch accounts after removal
275303 const result = await keyringController . getAccounts ( ) ;
276304 expect ( result ) . toStrictEqual ( accountsBeforeAdding ) ;
@@ -298,6 +326,24 @@ describe('KeyringController', function () {
298326 // was also removed after removing the account
299327 expect ( keyringController . keyrings ) . toHaveLength ( 1 ) ;
300328 } ) ;
329+
330+ it ( 'does not remove the keyring if there are accounts remaining after removing one from the keyring' , async function ( ) {
331+ // Add a new keyring with one account
332+ await keyringController . addNewKeyring ( 'HD Key Tree' , {
333+ mnemonic : walletTwoSeedWords ,
334+ numberOfAccounts : 2 ,
335+ } ) ;
336+
337+ // We should have 2 keyrings
338+ expect ( keyringController . keyrings ) . toHaveLength ( 2 ) ;
339+
340+ // remove one account from the keyring we just added
341+ await keyringController . removeAccount ( walletTwoAddresses [ 0 ] ) ;
342+
343+ // Check that the previous keyring with only one account
344+ // was also removed after removing the account
345+ expect ( keyringController . keyrings ) . toHaveLength ( 2 ) ;
346+ } ) ;
301347 } ) ;
302348
303349 describe ( 'unlockKeyrings' , function ( ) {
@@ -312,14 +358,26 @@ describe('KeyringController', function () {
312358 } ) ;
313359
314360 describe ( 'verifyPassword' , function ( ) {
315- it ( 'throws an error if no encrypted vault is in controller state' , async function ( ) {
361+ beforeEach ( ( ) => {
316362 keyringController = new KeyringController ( {
317363 encryptor : mockEncryptor ,
318364 } ) ;
365+ } ) ;
366+ it ( 'throws an error if no encrypted vault is in controller state' , async function ( ) {
319367 await expect ( ( ) =>
320368 keyringController . verifyPassword ( 'test' ) ,
321369 ) . rejects . toThrow ( 'Cannot unlock without a previous vault.' ) ;
322370 } ) ;
371+
372+ it ( 'does not throw if a vault exists in state' , async ( ) => {
373+ await keyringController . createNewVaultAndRestore (
374+ password ,
375+ walletOneSeedWords ,
376+ ) ;
377+ await expect ( ( ) =>
378+ keyringController . verifyPassword ( password ) ,
379+ ) . not . toThrow ( ) ;
380+ } ) ;
323381 } ) ;
324382
325383 describe ( 'addNewAccount' , function ( ) {
@@ -451,4 +509,80 @@ describe('KeyringController', function () {
451509 ) ;
452510 } ) ;
453511 } ) ;
512+
513+ describe ( 'exportAccount' , function ( ) {
514+ it ( 'returns the private key for the public key it is passed' , async ( ) => {
515+ await keyringController . createNewVaultAndRestore (
516+ password ,
517+ walletOneSeedWords ,
518+ ) ;
519+ const privateKey = await keyringController . exportAccount (
520+ walletOneAddresses [ 0 ] ,
521+ ) ;
522+ expect ( privateKey ) . toStrictEqual ( walletOnePrivateAddress [ 0 ] ) ;
523+ } ) ;
524+ } ) ;
525+
526+ describe ( 'signing methods' , function ( ) {
527+ beforeEach ( async ( ) => {
528+ await keyringController . createNewVaultAndRestore (
529+ password ,
530+ walletOneSeedWords ,
531+ ) ;
532+ } ) ;
533+
534+ it ( 'signMessage' , async ( ) => {
535+ const inputParams = {
536+ from : walletOneAddresses [ 0 ] ,
537+ data : '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0' ,
538+ origin : 'https://metamask.github.io' ,
539+ } ;
540+ const result = await keyringController . signMessage ( inputParams ) ;
541+ expect ( result ) . toBe (
542+ '0x93e0035090e8144debae03f45c5339a78d24c41e38e810a82dd3387e48353db645bd77716f3b7c4fb1f07f3b97bdbd33b0d7c55f7e7eedf3a678a2081948b67f1c' ,
543+ ) ;
544+ } ) ;
545+
546+ it ( 'signPersonalMessage' , async ( ) => {
547+ const inputParams = {
548+ from : walletOneAddresses [ 0 ] ,
549+ data : '0x4578616d706c652060706572736f6e616c5f7369676e60206d657373616765' ,
550+ origin : 'https://metamask.github.io' ,
551+ } ;
552+ const result = await keyringController . signPersonalMessage ( inputParams ) ;
553+ expect ( result ) . toBe (
554+ '0xfa2e5989b483e1f40a41b306f275b0009bcc07bfe5322c87682145e7d4889a3247182b4bd8138a965a7e37dea9d9b492b6f9f6d01185412f2d80466237b2805e1b' ,
555+ ) ;
556+ } ) ;
557+
558+ it ( 'getEncryptionPublicKey' , async ( ) => {
559+ const result = await keyringController . getEncryptionPublicKey (
560+ walletOneAddresses [ 0 ] ,
561+ ) ;
562+ expect ( result ) . toBe ( 'SR6bQ1m3OTHvI1FLwcGzm+Uk6hffoFPxsQ0DTOeKMEc=' ) ;
563+ } ) ;
564+
565+ it ( 'signTypedMessage' , async ( ) => {
566+ const inputParams = {
567+ from : walletOneAddresses [ 0 ] ,
568+ data : [
569+ {
570+ type : 'string' ,
571+ name : 'Message' ,
572+ value : 'Hi, Alice!' ,
573+ } ,
574+ {
575+ type : 'uint32' ,
576+ name : 'A number' ,
577+ value : '1337' ,
578+ } ,
579+ ] ,
580+ origin : 'https://metamask.github.io' ,
581+ } ;
582+ const result = await keyringController . signTypedMessage ( inputParams ) ;
583+ expect ( result ) . toBe (
584+ '0x089bb031f5bf2b2cbdf49eb2bb37d6071ab71f950b9dc49e398ca2ba984aca3c189b3b8de6c14c56461460dd9f59443340f1b144aeeff73275ace41ac184e54f1c' ,
585+ ) ;
586+ } ) ;
587+ } ) ;
454588} ) ;
0 commit comments