@@ -4,7 +4,7 @@ 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, keyringBuilderFactory } = require ( '..' ) ;
99const { KeyringMockWithInit } = require ( './lib/mock-keyring' ) ;
1010const mockEncryptor = require ( './lib/mock-encryptor' ) ;
@@ -19,6 +19,9 @@ const MOCK_ENCRYPTION_DATA = `{"data":"2fOOPRKClNrisB+tmqIcETyZvDuL2iIR1Hr1nO7XZ
1919const walletOneSeedWords =
2020 'puzzle seed penalty soldier say clay field arctic metal hen cage runway' ;
2121const walletOneAddresses = [ '0xef35ca8ebb9669a35c31b5f6f249a9941a812ac1' ] ;
22+ const walletOnePrivateAddress = [
23+ 'ace918800411c0b96b915f76efbbd4d50e6c997180fee58e01f60d3a412d2f7e' ,
24+ ] ;
2225
2326const walletTwoSeedWords =
2427 'urge letter protect palace city barely security section midnight wealth south deer' ;
@@ -143,6 +146,16 @@ describe('KeyringController', function () {
143146 expect ( actualPassword ) . toBe ( password ) ;
144147 } ) ;
145148 } ) ;
149+
150+ it ( 'should throw error if accounts are not generated correctly' , async ( ) => {
151+ jest
152+ . spyOn ( HdKeyring . prototype , 'getAccounts' )
153+ . mockImplementation ( ( ) => Promise . resolve ( [ ] ) ) ;
154+
155+ await expect ( ( ) =>
156+ keyringController . createNewVaultAndKeychain ( password ) ,
157+ ) . rejects . toThrow ( 'KeyringController - No account found on keychain.' ) ;
158+ } ) ;
146159 } ) ;
147160
148161 describe ( 'createNewVaultAndRestore' , function ( ) {
@@ -195,6 +208,19 @@ describe('KeyringController', function () {
195208 expect ( allAccountsAfter ) . toHaveLength ( 1 ) ;
196209 expect ( allAccountsAfter [ 0 ] ) . toBe ( walletTwoAddresses [ 0 ] ) ;
197210 } ) ;
211+
212+ it ( 'throws error if accounts are not created properly' , async ( ) => {
213+ jest
214+ . spyOn ( HdKeyring . prototype , 'getAccounts' )
215+ . mockImplementation ( ( ) => Promise . resolve ( [ ] ) ) ;
216+
217+ await expect ( ( ) =>
218+ keyringController . createNewVaultAndRestore (
219+ password ,
220+ walletTwoSeedWords ,
221+ ) ,
222+ ) . rejects . toThrow ( 'KeyringController - First Account not found.' ) ;
223+ } ) ;
198224 } ) ;
199225
200226 describe ( 'addNewKeyring' , function ( ) {
@@ -322,10 +348,12 @@ describe('KeyringController', function () {
322348 await keyringController . addNewKeyring ( 'Simple Key Pair' , [
323349 account . privateKey ,
324350 ] ) ;
351+ expect ( keyringController . keyrings ) . toHaveLength ( 2 ) ;
325352
326353 // remove that account that we just added
327354 await keyringController . removeAccount ( account . publicKey ) ;
328355
356+ expect ( keyringController . keyrings ) . toHaveLength ( 1 ) ;
329357 // fetch accounts after removal
330358 const result = await keyringController . getAccounts ( ) ;
331359 expect ( result ) . toStrictEqual ( accountsBeforeAdding ) ;
@@ -353,6 +381,24 @@ describe('KeyringController', function () {
353381 // was also removed after removing the account
354382 expect ( keyringController . keyrings ) . toHaveLength ( 1 ) ;
355383 } ) ;
384+
385+ it ( 'does not remove the keyring if there are accounts remaining after removing one from the keyring' , async function ( ) {
386+ // Add a new keyring with one account
387+ await keyringController . addNewKeyring ( 'HD Key Tree' , {
388+ mnemonic : walletTwoSeedWords ,
389+ numberOfAccounts : 2 ,
390+ } ) ;
391+
392+ // We should have 2 keyrings
393+ expect ( keyringController . keyrings ) . toHaveLength ( 2 ) ;
394+
395+ // remove one account from the keyring we just added
396+ await keyringController . removeAccount ( walletTwoAddresses [ 0 ] ) ;
397+
398+ // Check that the newly added keyring was not removed after
399+ // removing the account since it still has an account left
400+ expect ( keyringController . keyrings ) . toHaveLength ( 2 ) ;
401+ } ) ;
356402 } ) ;
357403
358404 describe ( 'unlockKeyrings' , function ( ) {
@@ -377,14 +423,26 @@ describe('KeyringController', function () {
377423 } ) ;
378424
379425 describe ( 'verifyPassword' , function ( ) {
380- it ( 'throws an error if no encrypted vault is in controller state' , async function ( ) {
426+ beforeEach ( ( ) => {
381427 keyringController = new KeyringController ( {
382428 encryptor : mockEncryptor ,
383429 } ) ;
430+ } ) ;
431+ it ( 'throws an error if no encrypted vault is in controller state' , async function ( ) {
384432 await expect ( ( ) =>
385433 keyringController . verifyPassword ( 'test' ) ,
386434 ) . rejects . toThrow ( 'Cannot unlock without a previous vault.' ) ;
387435 } ) ;
436+
437+ it ( 'does not throw if a vault exists in state' , async ( ) => {
438+ await keyringController . createNewVaultAndRestore (
439+ password ,
440+ walletOneSeedWords ,
441+ ) ;
442+ await expect ( ( ) =>
443+ keyringController . verifyPassword ( password ) ,
444+ ) . not . toThrow ( ) ;
445+ } ) ;
388446 } ) ;
389447
390448 describe ( 'addNewAccount' , function ( ) {
@@ -636,4 +694,80 @@ describe('KeyringController', function () {
636694 expect ( keyringController . memStore . getState ( ) . encryptionKey ) . toBeNull ( ) ;
637695 } ) ;
638696 } ) ;
697+
698+ describe ( 'exportAccount' , function ( ) {
699+ it ( 'returns the private key for the public key it is passed' , async ( ) => {
700+ await keyringController . createNewVaultAndRestore (
701+ password ,
702+ walletOneSeedWords ,
703+ ) ;
704+ const privateKey = await keyringController . exportAccount (
705+ walletOneAddresses [ 0 ] ,
706+ ) ;
707+ expect ( privateKey ) . toStrictEqual ( walletOnePrivateAddress [ 0 ] ) ;
708+ } ) ;
709+ } ) ;
710+
711+ describe ( 'signing methods' , function ( ) {
712+ beforeEach ( async ( ) => {
713+ await keyringController . createNewVaultAndRestore (
714+ password ,
715+ walletOneSeedWords ,
716+ ) ;
717+ } ) ;
718+
719+ it ( 'signMessage' , async ( ) => {
720+ const inputParams = {
721+ from : walletOneAddresses [ 0 ] ,
722+ data : '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0' ,
723+ origin : 'https://metamask.github.io' ,
724+ } ;
725+ const result = await keyringController . signMessage ( inputParams ) ;
726+ expect ( result ) . toBe (
727+ '0x93e0035090e8144debae03f45c5339a78d24c41e38e810a82dd3387e48353db645bd77716f3b7c4fb1f07f3b97bdbd33b0d7c55f7e7eedf3a678a2081948b67f1c' ,
728+ ) ;
729+ } ) ;
730+
731+ it ( 'signPersonalMessage' , async ( ) => {
732+ const inputParams = {
733+ from : walletOneAddresses [ 0 ] ,
734+ data : '0x4578616d706c652060706572736f6e616c5f7369676e60206d657373616765' ,
735+ origin : 'https://metamask.github.io' ,
736+ } ;
737+ const result = await keyringController . signPersonalMessage ( inputParams ) ;
738+ expect ( result ) . toBe (
739+ '0xfa2e5989b483e1f40a41b306f275b0009bcc07bfe5322c87682145e7d4889a3247182b4bd8138a965a7e37dea9d9b492b6f9f6d01185412f2d80466237b2805e1b' ,
740+ ) ;
741+ } ) ;
742+
743+ it ( 'getEncryptionPublicKey' , async ( ) => {
744+ const result = await keyringController . getEncryptionPublicKey (
745+ walletOneAddresses [ 0 ] ,
746+ ) ;
747+ expect ( result ) . toBe ( 'SR6bQ1m3OTHvI1FLwcGzm+Uk6hffoFPxsQ0DTOeKMEc=' ) ;
748+ } ) ;
749+
750+ it ( 'signTypedMessage' , async ( ) => {
751+ const inputParams = {
752+ from : walletOneAddresses [ 0 ] ,
753+ data : [
754+ {
755+ type : 'string' ,
756+ name : 'Message' ,
757+ value : 'Hi, Alice!' ,
758+ } ,
759+ {
760+ type : 'uint32' ,
761+ name : 'A number' ,
762+ value : '1337' ,
763+ } ,
764+ ] ,
765+ origin : 'https://metamask.github.io' ,
766+ } ;
767+ const result = await keyringController . signTypedMessage ( inputParams ) ;
768+ expect ( result ) . toBe (
769+ '0x089bb031f5bf2b2cbdf49eb2bb37d6071ab71f950b9dc49e398ca2ba984aca3c189b3b8de6c14c56461460dd9f59443340f1b144aeeff73275ace41ac184e54f1c' ,
770+ ) ;
771+ } ) ;
772+ } ) ;
639773} ) ;
0 commit comments