-
-
Notifications
You must be signed in to change notification settings - Fork 188
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
Make findNetworkClientIdByChainId
prefer the current client if multiple match
#3927
Conversation
findNetworkClientIdByChainId
prefer the current clientfindNetworkClientIdByChainId
prefer the current client if multiple match
cc @jiexi an edge case of our use of |
@@ -1374,6 +1374,10 @@ export class NetworkController extends BaseController< | |||
* @returns networkClientId of the network configuration with the given chainId | |||
*/ | |||
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:stateChange
for the providerConfig changeNetworkController:networkWillChange
NetworkController:stateChange
for the selectedNetworkClientId change and default networksMetadataNetworkController:networkDidChange
NetworkController:stateChange
for 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:networkWillChange
NetworkController:stateChange
for the providerConfig, selectedNetworkClientId, and default networksMetadataNetworkController:networkDidChange
NetworkController:stateChange
for 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
findNetworkClientIdByChainId
to 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-controller
findNetworkClientIdByChainId
will prefer the currently selected network client if multiple exist with the given chain id.Checklist