-
-
Notifications
You must be signed in to change notification settings - Fork 183
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
Fix another TokenRatesController
event ordering bug
#1511
Conversation
When the network switches, the `TokenRatesController` was relying upon the combination of two state updates (from the network controller and the tokens controller), both of which were needed in order to ensure the controller configuration was valid. These events don't arrive at the same time, meaning that the controller was potentially making one invalid call each network switch. Additionally, there is a risk that the second event could result in no update (e.g. because the destination network isn't supported, or because there were no tokens), resulting in the data from the invalid call remaining in state. This has been prevented by updating the controller to use the `allTokens` and `allDetectedTokens` state rather than the `tokens` state. A network switch now triggers a single event, and the controller configuration never enters an invalid state.
0a78d8d
to
1cc946f
Compare
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.
Definitely makes more sense to keep track of tokens by chain ID rather than replace the collection each time the network is changed. Had a question that I'm curious to know the answer to before approving, but should be a quick approval after that.
@@ -203,7 +214,9 @@ export class TokenRatesController extends BaseController< | |||
interval: 3 * 60 * 1000, | |||
nativeCurrency: initialTicker, | |||
chainId: initialChainId, | |||
tokens: [], | |||
selectedAddress: initialSelectedAddress, | |||
allTokens: {}, // TODO: initialize these correctly, maybe as part of BaseControllerV2 migration |
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'm just now noticing that the only thing that TokenRatesController has in state is contractExchangeRates
. Is config
persisted to state and if not, shouldn't it at least be read-only? i.e. should allTokens
and allDetectedTokens
be a part of state too?
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.
Config and state are separate; config is not persisted to-disk.
I'm not sure I follow the question about whether it should be read-only; are you talking about config or state there? What exactly should we consider making read-only and why?
I don't understand why we'd move allTokens
and allDetectedTokens
into state; they're already in the state of the tokens controller. That would cause an overlap.
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.
By read-only, I mean that this property is only used to set the initial private state of the controller and is not changed. It seems that we are changing allTokens
and allDetectedTokens
throughout the lifetime of the controller, however, and that we'd want to instead use the values that come through in config
to set private properties that then get changed.
Perhaps this pattern is not new, though, and config
has been used as form of private state all along. I suppose it's not a big deal — this will go away when the controller is converted to BaseControllerV2 — I just didn't know if it was intentional or not.
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.
Indeed, this is how config has always worked unfortunately. Agreed that it's not good. That will be fixed with the BaseControllerV2 migration
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.
Looks good!
* Fix another `TokenRatesController` event ordering bug When the network switches, the `TokenRatesController` was relying upon the combination of two state updates (from the network controller and the tokens controller), both of which were needed in order to ensure the controller configuration was valid. These events don't arrive at the same time, meaning that the controller was potentially making one invalid call each network switch. Additionally, there is a risk that the second event could result in no update (e.g. because the destination network isn't supported, or because there were no tokens), resulting in the data from the invalid call remaining in state. This has been prevented by updating the controller to use the `allTokens` and `allDetectedTokens` state rather than the `tokens` state. A network switch now triggers a single event, and the controller configuration never enters an invalid state. * Prevent update while polling inactive, and add tests
* Fix another `TokenRatesController` event ordering bug When the network switches, the `TokenRatesController` was relying upon the combination of two state updates (from the network controller and the tokens controller), both of which were needed in order to ensure the controller configuration was valid. These events don't arrive at the same time, meaning that the controller was potentially making one invalid call each network switch. Additionally, there is a risk that the second event could result in no update (e.g. because the destination network isn't supported, or because there were no tokens), resulting in the data from the invalid call remaining in state. This has been prevented by updating the controller to use the `allTokens` and `allDetectedTokens` state rather than the `tokens` state. A network switch now triggers a single event, and the controller configuration never enters an invalid state. * Prevent update while polling inactive, and add tests
Explanation
When the network switches, the
TokenRatesController
was relying upon the combination of two state updates (from the network controller and the tokens controller), both of which were needed in order to ensure the controller configuration was valid. These events don't arrive at the same time, meaning that the controller was potentially making one invalid call each network switch.Additionally, there is a risk that the second event could result in no update (e.g. because the destination network isn't supported, or because there were no tokens), resulting in the data from the invalid call remaining in state.
This has been prevented by updating the controller to use the
allTokens
andallDetectedTokens
state rather than thetokens
state. A network switch now triggers a single event, and the controller configuration never enters an invalid state.References
This tangentially relates to #1466
Changelog
@metamask/assets-controllers
TokenRatesController
now requires two new constructor parameters:selectedAddress
andonPreferencesStateChange
TokenRatesController
configuration/state upon network switchingChecklist