-
-
Notifications
You must be signed in to change notification settings - Fork 266
Make findNetworkClientIdByChainId prefer the current client if multiple match
#3927
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
Conversation
findNetworkClientIdByChainId prefer the current clientfindNetworkClientIdByChainId prefer the current client if multiple match
|
cc @jiexi an edge case of our use of |
| */ | ||
| findNetworkClientIdByChainId(chainId: Hex): NetworkClientId { | ||
| if (this.state.providerConfig.chainId === chainId) { | ||
| return this.state.providerConfig.id ?? this.state.providerConfig.type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. A NetworkController:stateChange event for the providerConfig changing fires before a stateChange event for the selectedNetworkClientId changing.
I feel the order of events we fire is incorrect. Currently when the active network changes events are fired in the following order:
NetworkController:stateChangefor the providerConfig changeNetworkController:networkWillChangeNetworkController:stateChangefor the selectedNetworkClientId change and default networksMetadataNetworkController:networkDidChangeNetworkController:stateChangefor updating networksMetadata with EIP1559 compatibilityNetworkController:infuraIsUnblocked
It seems like steps 1 and 3 should be combined and fired after step 2. So it should look like this:
NetworkController:networkWillChangeNetworkController:stateChangefor the providerConfig, selectedNetworkClientId, and default networksMetadataNetworkController:networkDidChangeNetworkController:stateChangefor updating networksMetadata with EIP1559 compatibilityNetworkController:infuraIsUnblocked
@Gudahtt @mcmire @adonesky1 @shanejonas @BelfordZ thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it matters when the stateChange occurs, because clients shouldn't be using that event to know whether the network changes, they should be using networkDidChange — and that already works today. But grouping like state changes together in the same update does make sense, so that we can guarantee that providerConfig matches selectedNetworkClientId.
Can you help me understand how ensuring the active networkClient is used for detection fixes this bug? I'm not saying we shouldn't address the mismatch but I am a bit confused about how it resolves the issue in this case |
@adonesky1 Does this help?
In the old code, the chosen network client is an arbitrary one that matches the chain id. This may not be the active network if there are multiple with that chain id. Causing the balance check to run on a different RPC than user selected. The new code gives precedence to the active network if multiple match the chain id. In the linked bug, someone is using a tenderly fork which made it more obvious that the wrong RPC was being used. |
| if (this.state.providerConfig.chainId === chainId) { | ||
| return this.state.providerConfig.id ?? this.state.providerConfig.type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... does it make sense to fall back to this.state.providerConfig.type here? Despite the TypeScript types matching, this.state.providerConfig.type is not quite the same thing as the network client ID. To be specific, NetworkType (which is the type property is) includes "rpc", but there is no network client registered under "rpc". So if you tried to feed this into getNetworkClientById there is a small change you might get an error.
What about:
| if (this.state.providerConfig.chainId === chainId) { | |
| return this.state.providerConfig.id ?? this.state.providerConfig.type; | |
| if ( | |
| this.state.providerConfig.chainId === chainId && | |
| ( | |
| this.state.providerConfig.id ?? | |
| this.state.providerConfig.type !== NetworkType.rpc | |
| ) | |
| ) { | |
| return this.state.providerConfig.id ?? this.state.providerConfig.type; | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like a good idea. I'm trying to handle the fact that NetworkClientIds seem to come from different fields in custom vs infura. The suggested guard would prevent a bug in the (theoretical, shouldn't happen?) case of type === NetworkType.rpc but no id
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, practically it shouldn't happen based on the logic we have in setActiveNetwork and is purely theoretical based on the fact that NetworkType is a slightly wider type than NetworkClientId.
|
Reviewing this PR again, I'm curious if this is the right direction to take. As far as I understand — @adonesky1 you can correct me if I'm wrong — I think DetectTokensController is where the bug really lies. There are a few problems I can see with it:
So, if we make these changes in DetectTokensController then we don't have to mess with this method and thus For what it's worth, all of these changes have been made to TokenDetectionController in this repo, and we are very close to switching extension to use the controller instead of DetectTokensController. So, does it make sense to wait until we've done that? |
That all makes sense to me! My remaining concern is #3923 is currently introducing the |

Explanation
Modifies the network controller's
findNetworkClientIdByChainIdto prefer the current network client if multiple exist with the given chain id.This fix was prompted by MetaMask/metamask-extension#22992. The setup is multiple networks/RPCs with the same chain ID
1. When extension triggers a token detection, it was doing so on the built-in mainnet RPC instead of the currently selected RPC.I am not 100% sure about this fix.
References
Bug report: MetaMask/metamask-extension#22992
Changelog
@metamask/network-controllerfindNetworkClientIdByChainIdwill prefer the currently selected network client if multiple exist with the given chain id.Checklist