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

fix: undefined market data selector #26264

Merged
merged 3 commits into from
Aug 2, 2024
Merged

Conversation

bergeron
Copy link
Contributor

@bergeron bergeron commented Jul 31, 2024

Description

Fixes an issue when Show balance and token price checker is turned off in settings, certain actions like sending, importing, or swapping a token crash metamask.

Open in GitHub Codespaces

Related issues

Fixes: #26243

Manual testing steps

  1. Go into settings > security and privacy
  2. Turn off Show balance and token price checker
  3. Switch chains
  4. Click import tokens on the tokens tab. Modal should popup without error
  5. Click swap and enter tokens + amount. Swap rate should fetch successfully.

Screenshots/Recordings

Before

After

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

Comment on lines -156 to -167
const contractExchangeRatesSelector = (state) => {
const chainId = getCurrentChainId(state);
const contractMarketData = state.metamask.marketData?.[chainId];

return Object.entries(contractMarketData).reduce(
(acc, [address, marketData]) => {
acc[address] = marketData?.price ?? null;
return acc;
},
{},
);
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This chunk was identical to the getTokenExchangeRates selector, except it did not include a ?? {} to handle the undefined case. So I just made it re-use that selector instead.

@@ -218,7 +206,7 @@ export const sendTokenTokenAmountAndToAddressSelector = createSelector(
);

export const contractExchangeRateSelector = createSelector(
contractExchangeRatesSelector,
(state) => getTokenExchangeRates(state),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

You'd think getTokenExchangeRates would work here instead of a lambda, but the tests don't like it. I suspect that's why the original code duplicated the selector.

 FAIL  app/scripts/metamask-controller.actions.test.js
  ● Test suite failed to run

    Selector creators expect all input-selectors to be functions, instead received the following types: [undefined, function]

      206 | );
      207 |
    > 208 | export const contractExchangeRateSelector = createSelector(
          |                                                           ^
      209 |   getTokenExchangeRates,

I've encountered this situation a few times, and never discovered why it happens. I think you can also fix it by stubbing the selector in the tests. But the lambda seems to work too.

Copy link
Member

Choose a reason for hiding this comment

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

This error is caused by the function being undefined at the point in time this is executed. This could happen because the function is defined later in the module (as a variable, so not hoisted to the top like function declarations are), but more often I've seen this happen due to a circular dependency between the current file and the file we're importing the selector from.

One of the tech debt tasks in-progress now is an effort to remove all circular dependencies in our codebase and implement a lint rule preventing their re-introduction, so hopefully we can resolve this soon. But in the meantime this solution works.

@bergeron bergeron marked this pull request as ready for review July 31, 2024 19:18
@bergeron bergeron requested a review from a team as a code owner July 31, 2024 19:18
gambinish
gambinish previously approved these changes Jul 31, 2024
@@ -218,7 +206,7 @@ export const sendTokenTokenAmountAndToAddressSelector = createSelector(
);

export const contractExchangeRateSelector = createSelector(
contractExchangeRatesSelector,
(state) => getTokenExchangeRates(state),
tokenAddressSelector,
(contractExchangeRates, tokenAddress) => {
return contractExchangeRates[
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Code below could probably look up via the checksummed address instead of the O(n) case insensitive search

@metamaskbot
Copy link
Collaborator

Builds ready [c4ea0a6]
Page Load Metrics (215 ± 225 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint573101116531
domContentLoaded95922147
load391626215468225
domInteractive95822147
Bundle size diffs [🚀 Bundle size reduced!]
  • background: 0 Bytes (0.00%)
  • ui: 0 Bytes (0.00%)
  • common: -160 Bytes (-0.00%)

Copy link

codecov bot commented Jul 31, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 69.94%. Comparing base (2beba47) to head (e5c9a75).
Report is 4 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #26264      +/-   ##
===========================================
- Coverage    69.95%   69.94%   -0.01%     
===========================================
  Files         1411     1411              
  Lines        49963    49966       +3     
  Branches     13800    13801       +1     
===========================================
- Hits         34948    34947       -1     
- Misses       15015    15019       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@bergeron
Copy link
Contributor Author

Something fishier may be going on. This selector should run when there's a pending transaction, not when importing a token.

salimtb
salimtb previously approved these changes Jul 31, 2024
@bergeron bergeron dismissed stale reviews from salimtb and gambinish via 241c39d July 31, 2024 20:33
@sleepytanya
Copy link
Contributor

@bergeron I still the 'Cannot convert undefined or null to object' error

@@ -137,7 +137,7 @@ export const ImportTokensModal = ({ onClose }) => {
const accounts = useSelector(getInternalAccounts);
const tokens = useSelector((state) => state.metamask.tokens);
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider);
const contractExchangeRates = useSelector(contractExchangeRateSelector);
const contractExchangeRates = useSelector(getTokenExchangeRates);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think the previous selector made sense. It only returned the exchange rate of the current token being transacted. Whereas the variable is accessed like an object containing rates for multiple tokens.

@bergeron
Copy link
Contributor Author

@bergeron I still the 'Cannot convert undefined or null to object' error

With what repro steps

@sleepytanya
Copy link
Contributor

@bergeron
Go into settings > security and privacy
Turn off Show balance and token price checker
Switch chains
Click import tokens on the tokens tab
Swap - error fetching quotes / Cannot convert undefined or null to object

I'm using this build #26264 (comment)

@bergeron
Copy link
Contributor Author

I can't reproduce with those steps on that build

@metamaskbot
Copy link
Collaborator

Builds ready [241c39d]
Page Load Metrics (352 ± 305 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint673131306732
domContentLoaded10173313718
load412158352635305
domInteractive10173313718
Bundle size diffs [🚀 Bundle size reduced!]
  • background: 0 Bytes (0.00%)
  • ui: -7 Bytes (-0.00%)
  • common: -160 Bytes (-0.00%)

@bergeron bergeron requested a review from a team as a code owner July 31, 2024 21:16
Copy link

@sleepytanya
Copy link
Contributor

@bergeron Fixed!
build commit e5c9a75

fixed.mov

@metamaskbot
Copy link
Collaborator

Builds ready [e5c9a75]
Page Load Metrics (133 ± 147 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint62247973919
domContentLoaded9176253517
load381457133306147
domInteractive9176253517
Bundle size diffs [🚀 Bundle size reduced!]
  • background: 21 Bytes (0.00%)
  • ui: -7 Bytes (-0.00%)
  • common: -160 Bytes (-0.00%)

@gambinish gambinish self-requested a review August 1, 2024 14:58
Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

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

LGTM!

Copy link
Contributor

@klejeune klejeune left a comment

Choose a reason for hiding this comment

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

Approved on behalf of @martahj

@bergeron bergeron merged commit c670085 into develop Aug 2, 2024
84 checks passed
@bergeron bergeron deleted the brian/fix-undefined-market-data branch August 2, 2024 16:37
@github-actions github-actions bot locked and limited conversation to collaborators Aug 2, 2024
@metamaskbot metamaskbot added the release-12.4.0 Issue or pull request that will be included in release 12.4.0 label Aug 2, 2024
@gauthierpetetin gauthierpetetin added release-12.3.0 Issue or pull request that will be included in release 12.3.0 and removed release-12.4.0 Issue or pull request that will be included in release 12.4.0 labels Sep 11, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
release-12.3.0 Issue or pull request that will be included in release 12.3.0 team-assets
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

[Bug]: Cannot convert undefined or null to object