Skip to content

Fix conversion rate issues#11066

Closed
adonesky1 wants to merge 15 commits intoMetaMask:developfrom
adonesky1:fix-conversion-rate-issue
Closed

Fix conversion rate issues#11066
adonesky1 wants to merge 15 commits intoMetaMask:developfrom
adonesky1:fix-conversion-rate-issue

Conversation

@adonesky1
Copy link
Copy Markdown
Contributor

@adonesky1 adonesky1 commented May 12, 2021

Fixes: #9492

Explanation: In cases where a user has not entered a symbol ticker for a custom RPC network (or our conversion rate API doesn't recognize the asset), don't currently update our conversionRate in state and use the conversion rate from the previously used network with a valild conversion rate. Moreover, in useCurrencyDisplay (where we apply the conversion for most UI elements where the value of a secondary currency is required) we haven't had a clear conditional separation of values that require conversion (Secondary currencies / Fiat) and those that do not (Primary Currency / native assets).

This PR, in tandem with this one allows conversionRates to be null when we cannot calculate them. In such cases we do not show a converted secondary currency (even if the user has selected to show conversions in testnets). This prevents us from showing inaccurate conversions. It also adds logic to avoid applying conversion rates to primary currencies which results in some of the more alarming bugs (show in video in linked PR above).

tldr: when reviewing start at useCurrencyDisplay.js

Additional work here:

  • Removes user-preferenced-token-input & user-preferenced-currency-input components because they are just wrapping token-input and currency-input and passing a single additional prop (useNativeCurrencyAsPrimaryCurrency) that can be added by the component's containers. IMO this pattern makes it harder to tell where props are coming from and how to reason about what the components are trying to achieves. Furthermore there is currently no where that the token-input or currency-input is used where it wasn't wrapped by user-preference-token-input /user-preference-currency-input so the pattern isn't creating any meaningful distinction between the wrapped and unwrapped versions.
  • add functionality such that when a user has selected fiat as their primary currency token asset list items also show fiat as primary.

Work to follow:

  • Proposal to replace useCurrencyDisplay with a hook that is more agnostic and versatile to consolidate the many patterns we have for calculating and displaying currentCurrency and nativeCurrency together and clean up the impossible to reason about logic that lives in components like currency-input.component and token-input.component.
  • A PR to change the names of currentCurrency and nativeCurrency to preferredCurrency and networkCurrency respectively per this thread. If you have thoughts on this please include comments here?

Manual testing steps:

  • In advanced settings, turn Show Conversion on Testnets on.
  • Go between mainnet, a custom rpc network where you have added a ticker symbol and a custom rpc network where you haven't added a ticker symbol.
  • Check that conversions are correct for all assets across these different networks (for the network with no ticker symbol there should be no conversions).

@adonesky1 adonesky1 requested a review from a team as a code owner May 12, 2021 20:36
@adonesky1 adonesky1 requested a review from brad-decker May 12, 2021 20:36
@github-actions
Copy link
Copy Markdown
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.

@adonesky1 adonesky1 force-pushed the fix-conversion-rate-issue branch from 39f5b8f to 2d899f2 Compare May 12, 2021 23:23
@brad-decker brad-decker marked this pull request as draft May 14, 2021 20:45
@adonesky1 adonesky1 force-pushed the fix-conversion-rate-issue branch 4 times, most recently from 1e81c7e to 1a842fc Compare May 18, 2021 17:20
@adonesky1 adonesky1 changed the title Fix conversion rate issue / WIP Fix conversion rate issues May 19, 2021
@darkwing darkwing added the DO-NOT-MERGE Pull requests that should not be merged label May 19, 2021
@darkwing
Copy link
Copy Markdown
Contributor

Added DONOTMERGE based on Alex's PR description, which could be lost in the rest of the text

@adonesky1 adonesky1 force-pushed the fix-conversion-rate-issue branch 2 times, most recently from 93813d6 to e7af0ca Compare May 24, 2021 22:56
@Gudahtt Gudahtt mentioned this pull request May 25, 2021
@adonesky1 adonesky1 force-pushed the fix-conversion-rate-issue branch from 3a10ca4 to c4a8d27 Compare May 26, 2021 19:23
@adonesky1 adonesky1 removed the DO-NOT-MERGE Pull requests that should not be merged label May 26, 2021
@adonesky1 adonesky1 marked this pull request as ready for review May 27, 2021 14:35
@adonesky1 adonesky1 force-pushed the fix-conversion-rate-issue branch 2 times, most recently from 92abc5f to 8953502 Compare May 27, 2021 16:01
@adonesky1 adonesky1 requested a review from danjm June 3, 2021 16:44
>
<h2>
<span className="asset-list-item__token-value">{primary}</span>
<span className="asset-list-item__token-symbol">{tokenSymbol}</span>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In some other places, we intentionally put the symbol and the value in separate elements so that we can use CSS to ellipse long values without obscuring the symbol. That seems like it would be useful here too 🤔 But that said I can't see any evidence of such a strategy being used here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added back!

@adonesky1 adonesky1 requested a review from Gudahtt June 4, 2021 15:44
@adonesky1 adonesky1 force-pushed the fix-conversion-rate-issue branch 4 times, most recently from c4ed806 to d56f07a Compare June 4, 2021 17:13
@adonesky1 adonesky1 force-pushed the fix-conversion-rate-issue branch from 05618c8 to 649f696 Compare June 18, 2021 18:32
@adonesky1 adonesky1 force-pushed the fix-conversion-rate-issue branch 5 times, most recently from 94e0f59 to a3c576c Compare June 21, 2021 17:41
@adonesky1 adonesky1 requested a review from brad-decker June 21, 2021 17:42
@adonesky1 adonesky1 force-pushed the fix-conversion-rate-issue branch from a3c576c to e6f5674 Compare June 21, 2021 17:55
Copy link
Copy Markdown
Contributor

@brad-decker brad-decker left a comment

Choose a reason for hiding this comment

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

There's a number of issues with this PR due to conversionRate possibly being undefined where it was never assumed to be undefined before. Might want to hardcode the selector to return undefined to figure out what should be displayed in these cases. I've left a number of feedback items here too. I also started a thread in the design team channel to discuss how we should handle the changes to make assets display fiat as the "primary" display value when the appropriate setting is set.

"@metamask/contract-metadata": "^1.26.0",
"@metamask/controllers": "^9.0.0",
"@metamask/eth-ledger-bridge-keyring": "^0.6.0",
"@metamask/controllers": "^10.0.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

NIT: the positional change here is unnecessary and breaks alphabetical order.

onClick,
tokenAddress,
tokenSymbol,
primarySymbol,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[req]

instead of primary/primarySymbol etc

what if we had:
primaryAsset.amount and primaryAsset.symbol and primaryAsset.isFiat ( also primaryAsset.decimals and primaryAsset.address and primaryAsset.image )?
similarily
secondaryAsset.amount amd secondaryAsset.symbol

I think this could go a long way in reducing confusion in this component and make clearer what primary/secondary means. I still don't like these words as a data descriptor. They are being described as how they usually appear in our UI which leads to the confusion that needs to have flags for reversing their meaning. That's a conversation for another PR I think 😬

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

actually after reviewing this bit:

  const tokenSymbol = useMemo(
    () => (primaryIsFiat ? secondarySymbol : primarySymbol),
    [primaryIsFiat, secondarySymbol, primarySymbol],
  );

I'm more confused.

the asset row exists to display a specific asset, the user's preferences do not change that. primary in this case is meant to describe the larger, more dominant value whereas secondary is the one under it that is smaller and supports the former.

I think we should go with something like this:

asset: PropTypes.shape({
  amount: PropTypes.string.isRequired,
  symbol: PropTypes.string.isRequired,
  decimals: PropTypes.number,
  address: PropTypes.string,
  image: PropTypes.string,
}).isRequired,
conversionAsset: PropTypes.shape({
  amount: PropTypes.string.isRequired,
  symbol: PropTypes.string.isRequired,
}),
conversionIsPrimary: propTypes.bool,

we can then always rely on the distinction that asset is the asset we are rendering. conversion is clearer as well than secondary, especially with the combination of conversionIsPrimary. We also do not extend the problem of treating the "secondary" asset as fiat when it could be other crypto. I probably haven't thought this all the way through, so feel free to mutate it to make sense but I think this is much easier to reason about when trying to support this component moving forward.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also related, when conversionRate is undefined (hardcoded in getConversionRate):

image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re the last comment, the conversionRate should be null when not available? and I'm not seeing that behavior where some tokens are USD and others are with their symbols...?

Regarding the shape you suggest for primary/secondary -> asset/conversionAsset, I agree it is an improvement. I'll move forward with that for now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ah sorry, you have to set "primary" currency as "Fiat" in settings to see this. I did update the getConversionRate selector to return null instead of undefined and same result.

<span className="asset-list-item__secondary-value">
{secondary}
</span>
<span className="asset-list-item__secondary-symbol">
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think your intention may have been to utilize the token-value styles to ellipse long text here. If that's the case you need to add the class to those styles.

const isMainnet = getIsMainnet(state);
const showFiat = isMainnet || Boolean(showFiatInTestnets);
const { conversionRate } = state.metamask;
const showFiat = Boolean((isMainnet || showFiatInTestnets) && conversionRate);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can this use the getShouldShowFiat selector now?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yessir!

const currentCurrency = useSelector(getCurrentCurrency);
const userPrefersShownFiat = useSelector(getShouldShowFiat);
const showFiat = overrides.showFiat ?? userPrefersShownFiat;
const showFiat = overrides?.showFiat ?? userPrefersShownFiat;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This file throws an error when getConversionRate is hardwired to return undefined, because it doesn't check if this is available before trying to compute values.

conversionRate,
numberOfDecimals: 2,
});
const fiatTransactionAmount = conversionRate
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

image
left: this PR, "Fiat" selected for primary, getConversionRate set to return undefined.

My assumption would be that, when the conversionRate is undefined, that the original UI (right) is shown but without the $0.00?

const currentCurrency = useSelector(getCurrentCurrency);
const userPrefersShownFiat = useSelector(getShouldShowFiat);
const showFiat = overrides.showFiat ?? userPrefersShownFiat;
const showFiat = Boolean(overrides.showFiat ?? userPrefersShownFiat);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this boolean needs to be updated to take into account the possibility of conversionRate not being present.

chainId,
nativeCurrencySymbol,
}) {
const showInFiat = Boolean(nativeCurrencySymbol && conversionRate);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Something in the swaps changes has caused the middle row to never fill in fee estimate regardless of conversionRate being defined or not:

image

@brad-decker brad-decker self-assigned this Jun 21, 2021
@adonesky1
Copy link
Copy Markdown
Contributor Author

The core of this PR was extracted and merged. The remaining pieces will be added in subsequent PRs.

@adonesky1 adonesky1 closed this Jun 24, 2021
@github-actions github-actions bot locked and limited conversation to collaborators Jun 24, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom network incorrect account balance when symbol is left blank.

5 participants