Skip to content

Commit a99dd2a

Browse files
committed
fix(accounts-controller): fire :accountAdded before :selectedAccountChange on KeyringController:stateChange
1 parent 29a7354 commit a99dd2a

File tree

1 file changed

+63
-49
lines changed

1 file changed

+63
-49
lines changed

packages/accounts-controller/src/AccountsController.ts

Lines changed: 63 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -833,63 +833,71 @@ export class AccountsController extends BaseController<
833833
added: [] as InternalAccount[],
834834
};
835835

836-
this.#update((state) => {
837-
const { internalAccounts } = state;
836+
this.#update(
837+
(state) => {
838+
const { internalAccounts } = state;
838839

839-
for (const patch of [patches.snap, patches.normal]) {
840-
for (const account of patch.removed) {
841-
delete internalAccounts.accounts[account.id];
840+
for (const patch of [patches.snap, patches.normal]) {
841+
for (const account of patch.removed) {
842+
delete internalAccounts.accounts[account.id];
842843

843-
diff.removed.push(account.id);
844-
}
845-
846-
for (const added of patch.added) {
847-
const account = this.#getInternalAccountFromAddressAndType(
848-
added.address,
849-
added.keyring,
850-
);
844+
diff.removed.push(account.id);
845+
}
851846

852-
if (account) {
853-
// Re-compute the list of accounts everytime, so we can make sure new names
854-
// are also considered.
855-
const accounts = Object.values(
856-
internalAccounts.accounts,
857-
) as InternalAccount[];
858-
859-
// Get next account name available for this given keyring.
860-
const name = this.getNextAvailableAccountName(
861-
account.metadata.keyring.type,
862-
accounts,
847+
for (const added of patch.added) {
848+
const account = this.#getInternalAccountFromAddressAndType(
849+
added.address,
850+
added.keyring,
863851
);
864852

865-
// If it's the first account, we need to select it.
866-
const lastSelected =
867-
accounts.length === 0 ? this.#getLastSelectedIndex() : 0;
868-
869-
internalAccounts.accounts[account.id] = {
870-
...account,
871-
metadata: {
872-
...account.metadata,
873-
name,
874-
importTime: Date.now(),
875-
lastSelected,
876-
},
877-
};
878-
879-
diff.added.push(internalAccounts.accounts[account.id]);
853+
if (account) {
854+
// Re-compute the list of accounts everytime, so we can make sure new names
855+
// are also considered.
856+
const accounts = Object.values(
857+
internalAccounts.accounts,
858+
) as InternalAccount[];
859+
860+
// Get next account name available for this given keyring.
861+
const name = this.getNextAvailableAccountName(
862+
account.metadata.keyring.type,
863+
accounts,
864+
);
865+
866+
// If it's the first account, we need to select it.
867+
const lastSelected =
868+
accounts.length === 0 ? this.#getLastSelectedIndex() : 0;
869+
870+
internalAccounts.accounts[account.id] = {
871+
...account,
872+
metadata: {
873+
...account.metadata,
874+
name,
875+
importTime: Date.now(),
876+
lastSelected,
877+
},
878+
};
879+
880+
diff.added.push(internalAccounts.accounts[account.id]);
881+
}
880882
}
881883
}
882-
}
883-
});
884-
885-
// Now publish events
886-
for (const id of diff.removed) {
887-
this.messagingSystem.publish('AccountsController:accountRemoved', id);
888-
}
884+
},
885+
// Will get executed after the update, but before re-selecting an account in case
886+
// the current one is not valid anymore.
887+
() => {
888+
// Now publish events
889+
for (const id of diff.removed) {
890+
this.messagingSystem.publish('AccountsController:accountRemoved', id);
891+
}
889892

890-
for (const account of diff.added) {
891-
this.messagingSystem.publish('AccountsController:accountAdded', account);
892-
}
893+
for (const account of diff.added) {
894+
this.messagingSystem.publish(
895+
'AccountsController:accountAdded',
896+
account,
897+
);
898+
}
899+
},
900+
);
893901

894902
// NOTE: Since we also track "updated" accounts with our patches, we could fire a new event
895903
// like `accountUpdated` (we would still need to check if anything really changed on the account).
@@ -899,9 +907,12 @@ export class AccountsController extends BaseController<
899907
* Update the state and fixup the currently selected account.
900908
*
901909
* @param callback - Callback for updating state, passed a draft state object.
910+
* @param beforeAutoSelectAccount - Callback to be executed before auto-selecting an account
911+
* if the current one is no longer available.
902912
*/
903913
#update(
904914
callback: (state: WritableDraft<AccountsControllerStrictState>) => void,
915+
beforeAutoSelectAccount?: () => void,
905916
) {
906917
// The currently selected account might get deleted during the update, so keep track
907918
// of it before doing any change.
@@ -932,6 +943,9 @@ export class AccountsController extends BaseController<
932943
}
933944
});
934945

946+
// We might want to do some pre-work before selecting a new account.
947+
beforeAutoSelectAccount?.();
948+
935949
// Now, we compare the newly selected account, and we send event if different.
936950
const { selectedAccount } = this.state.internalAccounts;
937951
if (selectedAccount && selectedAccount !== previouslySelectedAccount) {

0 commit comments

Comments
 (0)