@@ -19,9 +19,10 @@ import {
1919} from '@metamask/keyring-api' ;
2020import { KeyringTypes } from '@metamask/keyring-controller' ;
2121import type {
22- KeyringControllerState ,
2322 KeyringControllerGetKeyringsByTypeAction ,
2423 KeyringControllerStateChangeEvent ,
24+ KeyringControllerAccountAddedEvent ,
25+ KeyringControllerAccountRemovedEvent ,
2526 KeyringControllerGetStateAction ,
2627 KeyringObject ,
2728} from '@metamask/keyring-controller' ;
@@ -202,6 +203,8 @@ export type AccountsControllerAccountAssetListUpdatedEvent = {
202203export type AllowedEvents =
203204 | SnapStateChange
204205 | KeyringControllerStateChangeEvent
206+ | KeyringControllerAccountRemovedEvent
207+ | KeyringControllerAccountAddedEvent
205208 | SnapKeyringAccountAssetListUpdatedEvent
206209 | SnapKeyringAccountBalancesUpdatedEvent
207210 | SnapKeyringAccountTransactionsUpdatedEvent
@@ -506,7 +509,10 @@ export class AccountsController extends BaseController<
506509 ) ;
507510 }
508511
509- #assertAccountCanBeRenamed( account : InternalAccount , accountName : string ) {
512+ #assertAccountCanBeRenamed(
513+ account : InternalAccount ,
514+ accountName : string ,
515+ ) : void {
510516 if (
511517 this . listMultichainAccounts ( ) . find (
512518 ( internalAccount ) =>
@@ -748,168 +754,59 @@ export class AccountsController extends BaseController<
748754 this . messenger . publish ( event , ...payload ) ;
749755 }
750756
751- /**
752- * Handles changes in the keyring state, specifically when new accounts are added or removed.
753- *
754- * @param keyringState - The new state of the keyring controller.
755- * @param keyringState.isUnlocked - True if the keyrings are unlocked, false otherwise.
756- * @param keyringState.keyrings - List of all keyrings.
757- */
758- #handleOnKeyringStateChange( {
759- isUnlocked,
760- keyrings,
761- } : KeyringControllerState ) : void {
762- // TODO: Change when accountAdded event is added to the keyring controller.
763-
764- // We check for keyrings length to be greater than 0 because the extension client may try execute
765- // submit password twice and clear the keyring state.
766- // https://github.com/MetaMask/KeyringController/blob/2d73a4deed8d013913f6ef0c9f5c0bb7c614f7d3/src/KeyringController.ts#L910
767- if ( ! isUnlocked || keyrings . length === 0 ) {
768- return ;
769- }
770-
771- // State patches.
772- const generatePatch = ( ) => {
773- return {
774- previous : { } as Record < string , InternalAccount > ,
775- added : [ ] as {
776- address : string ;
777- keyring : KeyringObject ;
778- } [ ] ,
779- updated : [ ] as InternalAccount [ ] ,
780- removed : [ ] as InternalAccount [ ] ,
781- } ;
782- } ;
783- const patches = {
784- snap : generatePatch ( ) ,
785- normal : generatePatch ( ) ,
786- } ;
787-
788- // Gets the patch object based on the keyring type (since Snap accounts and other accounts
789- // are handled differently).
790- const patchOf = ( type : string ) => {
791- if ( isSnapKeyringType ( type ) ) {
792- return patches . snap ;
793- }
794- return patches . normal ;
795- } ;
796-
797- // Create a map (with lower-cased addresses) of all existing accounts.
798- for ( const account of this . listMultichainAccounts ( ) ) {
799- const address = account . address . toLowerCase ( ) ;
800- const patch = patchOf ( account . metadata . keyring . type ) ;
757+ #handleOnKeyringAccountAdded( address : string , keyring : KeyringObject ) {
758+ let account : InternalAccount | undefined ;
801759
802- patch . previous [ address ] = account ;
803- }
760+ this . #update ( ( state ) => {
761+ const { internalAccounts } = state ;
804762
805- // Go over all keyring changes and create patches out of it.
806- const addresses = new Set < string > ( ) ;
807- for ( const keyring of keyrings ) {
808- const patch = patchOf ( keyring . type ) ;
763+ account = this . #getInternalAccountFromAddressAndType( address , keyring ) ;
764+ if ( account ) {
765+ // Re-compute the list of accounts everytime, so we can make sure new names
766+ // are also considered.
767+ const accounts = Object . values (
768+ internalAccounts . accounts ,
769+ ) as InternalAccount [ ] ;
809770
810- for ( const accountAddress of keyring . accounts ) {
811- // Lower-case address to use it in the `previous` map.
812- const address = accountAddress . toLowerCase ( ) ;
813- const account = patch . previous [ address ] ;
771+ // Get next account name available for this given keyring.
772+ const name = this . getNextAvailableAccountName (
773+ account . metadata . keyring . type ,
774+ accounts ,
775+ ) ;
814776
815- if ( account ) {
816- // If the account exists before, this might be an update.
817- patch . updated . push ( account ) ;
818- } else {
819- // Otherwise, that's a new account.
820- patch . added . push ( {
821- address,
822- keyring,
823- } ) ;
824- }
777+ // If it's the first account, we need to select it.
778+ const lastSelected =
779+ accounts . length === 0 ? this . #getLastSelectedIndex( ) : 0 ;
825780
826- // Keep track of those address to check for removed accounts later.
827- addresses . add ( address ) ;
781+ internalAccounts . accounts [ account . id ] = {
782+ ...account ,
783+ metadata : {
784+ ...account . metadata ,
785+ name,
786+ importTime : Date . now ( ) ,
787+ lastSelected,
788+ } ,
789+ } ;
828790 }
829- }
791+ } ) ;
830792
831- // We might have accounts associated with removed keyrings, so we iterate
832- // over all previous known accounts and check against the keyring addresses.
833- for ( const patch of [ patches . snap , patches . normal ] ) {
834- for ( const [ address , account ] of Object . entries ( patch . previous ) ) {
835- // If a previous address is not part of the new addesses, then it got removed.
836- if ( ! addresses . has ( address ) ) {
837- patch . removed . push ( account ) ;
838- }
839- }
793+ if ( account ) {
794+ this . messenger . publish ( 'AccountsController:accountAdded' , account ) ;
840795 }
796+ }
841797
842- // Diff that we will use to publish events afterward.
843- const diff = {
844- removed : [ ] as string [ ] ,
845- added : [ ] as InternalAccount [ ] ,
846- } ;
798+ #handleOnKeyringAccountRemoved( address : string ) {
799+ const account = this . listMultichainAccounts ( ) . find (
800+ ( { address : accountAddress } ) => accountAddress === address ,
801+ ) ;
847802
848- this . #update (
849- ( state ) => {
803+ if ( account ) {
804+ this . #update ( ( state ) => {
850805 const { internalAccounts } = state ;
851806
852- for ( const patch of [ patches . snap , patches . normal ] ) {
853- for ( const account of patch . removed ) {
854- delete internalAccounts . accounts [ account . id ] ;
855-
856- diff . removed . push ( account . id ) ;
857- }
858-
859- for ( const added of patch . added ) {
860- const account = this . #getInternalAccountFromAddressAndType(
861- added . address ,
862- added . keyring ,
863- ) ;
864-
865- if ( account ) {
866- // Re-compute the list of accounts everytime, so we can make sure new names
867- // are also considered.
868- const accounts = Object . values (
869- internalAccounts . accounts ,
870- ) as InternalAccount [ ] ;
871-
872- // Get next account name available for this given keyring.
873- const name = this . getNextAvailableAccountName (
874- account . metadata . keyring . type ,
875- accounts ,
876- ) ;
877-
878- // If it's the first account, we need to select it.
879- const lastSelected =
880- accounts . length === 0 ? this . #getLastSelectedIndex( ) : 0 ;
881-
882- internalAccounts . accounts [ account . id ] = {
883- ...account ,
884- metadata : {
885- ...account . metadata ,
886- name,
887- importTime : Date . now ( ) ,
888- lastSelected,
889- } ,
890- } ;
891-
892- diff . added . push ( internalAccounts . accounts [ account . id ] ) ;
893- }
894- }
895- }
896- } ,
897- // Will get executed after the update, but before re-selecting an account in case
898- // the current one is not valid anymore.
899- ( ) => {
900- // Now publish events
901- for ( const id of diff . removed ) {
902- this . messenger . publish ( 'AccountsController:accountRemoved' , id ) ;
903- }
904-
905- for ( const account of diff . added ) {
906- this . messenger . publish ( 'AccountsController:accountAdded' , account ) ;
907- }
908- } ,
909- ) ;
910-
911- // NOTE: Since we also track "updated" accounts with our patches, we could fire a new event
912- // like `accountUpdated` (we would still need to check if anything really changed on the account).
807+ delete internalAccounts . accounts [ account . id ] ;
808+ } ) ;
809+ }
913810 }
914811
915812 /**
@@ -1215,8 +1112,13 @@ export class AccountsController extends BaseController<
12151112 this . #handleOnSnapStateChange( snapStateState ) ,
12161113 ) ;
12171114
1218- this . messenger . subscribe ( 'KeyringController:stateChange' , ( keyringState ) =>
1219- this . #handleOnKeyringStateChange( keyringState ) ,
1115+ this . messenger . subscribe ( 'KeyringController:accountRemoved' , ( address ) =>
1116+ this . #handleOnKeyringAccountRemoved( address ) ,
1117+ ) ;
1118+
1119+ this . messenger . subscribe (
1120+ 'KeyringController:accountAdded' ,
1121+ ( address , keyring ) => this . #handleOnKeyringAccountAdded( address , keyring ) ,
12201122 ) ;
12211123
12221124 this . messenger . subscribe (
0 commit comments