Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add MultichainNetworkController to handle both EVM and non-EVM network and account switching #5215

Merged
merged 77 commits into from
Feb 12, 2025

Conversation

Cal-L
Copy link
Contributor

@Cal-L Cal-L commented Jan 30, 2025

Explanation

This PR updates both the MultichainNetworkController and AccountsController to handle network switching as well as account switching. The logic handles the following logic:

  • Switching accounts on AccountsController will notify MultichainNetworkController to update if the account belongs to evm vs non-evm network (MultichainNetworkController subscribes to AccountsController event)
  • Switching between networks on MultichainNetworkController will notify AccountsController to update accounts based on which network the account belongs to (AccountsController subscribes to MultichainNetworkController event)

References

Fixes https://github.com/MetaMask/accounts-planning/issues/804

Changelog

@metamask/accounts-controller

  • BREAKING:
    • Added MultichainNetworkController:networkDidChange to allowed events. This is used to subscribe to the setActiveNetwork event from the MultichainNetworkController and is responsible for updating selected account based on network changes (both EVM and non-EVM).

@metamask/multichain-network-controller

  • ADDED:
    • Allowed actions - NetworkControllerGetStateAction | NetworkControllerSetActiveNetworkAction. The MultichainNetworkController acts as a proxy for the NetworkController and will update it based on EVM network changes.
    • Allowed events - AccountsControllerSelectedAccountChangeEvent to allowed events. This is used to subscribe to the selectedAccountChange event from the AccountsController and is responsible for updating active network based on account changes (both EVM and non-EVM).

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate
  • I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes

@Cal-L Cal-L requested a review from a team as a code owner January 30, 2025 06:01
@tommasini
Copy link
Contributor

This looks amazing! Lets align today with the review made on the PR #5209

@Cal-L Cal-L marked this pull request as draft February 3, 2025 18:29
@Cal-L Cal-L requested a review from a team as a code owner February 12, 2025 03:18
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a lot better now. I had a couple of comments about the use of barrel exports and also a missing dependency in accounts-controller but other than that the rest are minor and can be deferred to a future PR.

tommasini
tommasini previously approved these changes Feb 12, 2025
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, just one more thing.

mcmire
mcmire previously approved these changes Feb 12, 2025
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good!

Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linting errors :(

Copy link
Member

@gantunesr gantunesr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. We'll follow up this PR with the decoupling of the selected network from the network configurations

@Cal-L Cal-L merged commit ce12485 into main Feb 12, 2025
130 checks passed
@Cal-L Cal-L deleted the feat/handle-multichain-network-and-account-switching branch February 12, 2025 19:20
}

// Handle switching to non-EVM network
const nonEvmChainId = getChainIdForNonEvmAddress(accountAddress);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use account.scopes to check which chains are supported by the account.

With the new scopes we don't need this kind of runtime logic anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate on how this logic might look with your suggestion? FYI, one of the reasons that we kept accounts controller and multichain network controller away from each other is prevent circular dependencies.

Comment on lines +61 to +65
// Notify listeners that setActiveNetwork was called
this.messagingSystem.publish(
'MultichainNetworkController:networkDidChange',
id,
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this should have been fired after the actually update the network configuration.

If some logic is checking the actual state from this controller (and its counterpart the NetworkController) and react to this event, the state won't be "consistent", no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

Comment on lines +110 to +114
// Notify listeners that setActiveNetwork was called
this.messagingSystem.publish(
'MultichainNetworkController:networkDidChange',
id,
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we notify twice? We just do it in the if right before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. It was missing a return statement. Ended up simplifying this logic

Comment on lines +1152 to +1157
this.update((currentState) => {
currentState.internalAccounts.accounts[accountId].metadata.lastSelected =
Date.now();
currentState.internalAccounts.selectedAccount = accountId;
});
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we're not calling setSelectedAccount here to avoid triggering the "account change" event?

If yes, we should add a comment to explain this, cause this could easily be refactored and since there's no comment, we could make a mistake here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think that changing the account without publishing this event might have some side effects (like for other controllers that listen to this change event).

I'm not sure how to avoid infinite loop with those inter-dependent events, but that's something we might wanna re-visit at some point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with comment. Yeah it's a tricky problem. We're just being extra careful not to subscribe and publish to the same controller in each handler atm. Regarding side effects, if another controller relies on account changes, it should subscribe to the state change event and manage its own logic

*
* @param id - The EVM client ID or non-EVM chain ID that changed.
*/
readonly #handleMultichainNetworkChange = (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The handler name is not following the same convention as the others, it should be #handleOnMultichainNetworkDidChange

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

Comment on lines +178 to +181
this.update((state) => {
state.selectedMultichainNetworkChainId = nonEvmChainId;
state.isEvmSelected = false;
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, we should add a comment to explain why we are not firing any event in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

@Cal-L Cal-L mentioned this pull request Feb 13, 2025
4 tasks
Gudahtt added a commit that referenced this pull request Feb 17, 2025
## Explanation

CODEOWNER rules have been added for all packages that are currently
missing them:

* `example-controllers`: These are examples maintained by the wallet
framework team.
* `mutlichain-network-controller`: This package has been a collaboration
between many teams, but for now the owners have been set to the same as
the `network-controller` plus the accounts team (who proposed this
controller's creation). We can change this further if appropriate.


## References

The `multichain-network-controller` package was added here:
#5215

## Changelog

N/A

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've highlighted breaking changes using the "BREAKING" category
above as appropriate
- [x] I've prepared draft pull requests for clients and consumer
packages to resolve any breaking changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

5 participants