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: market data for native tokens with non zero addresses #28584

Merged
merged 8 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,39 +1,3 @@
diff --git a/dist/TokenDetectionController.cjs b/dist/TokenDetectionController.cjs
index 8fd5efde7a3c24080f8a43f79d10300e8c271245..66f656d9a55f1154024a8c18a9fe27b4ed39a21d 100644
--- a/dist/TokenDetectionController.cjs
+++ b/dist/TokenDetectionController.cjs
@@ -250,17 +250,20 @@ _TokenDetectionController_intervalId = new WeakMap(), _TokenDetectionController_
}
});
this.messagingSystem.subscribe('AccountsController:selectedEvmAccountChange',
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
- async (selectedAccount) => {
- const isSelectedAccountIdChanged = __classPrivateFieldGet(this, _TokenDetectionController_selectedAccountId, "f") !== selectedAccount.id;
- if (isSelectedAccountIdChanged) {
- __classPrivateFieldSet(this, _TokenDetectionController_selectedAccountId, selectedAccount.id, "f");
- await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_restartTokenDetection).call(this, {
- selectedAddress: selectedAccount.address,
- });
- }
- });
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
+ async (selectedAccount) => {
+ const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
+ const chainIds = Object.keys(networkConfigurationsByChainId);
+ const isSelectedAccountIdChanged = __classPrivateFieldGet(this, _TokenDetectionController_selectedAccountId, "f") !== selectedAccount.id;
+ if (isSelectedAccountIdChanged) {
+ __classPrivateFieldSet(this, _TokenDetectionController_selectedAccountId, selectedAccount.id, "f");
+ await __classPrivateFieldGet(this, _TokenDetectionController_instances, "m", _TokenDetectionController_restartTokenDetection).call(this, {
+ selectedAddress: selectedAccount.address,
+ chainIds,
+ });
+ }
+ });
}, _TokenDetectionController_stopPolling = function _TokenDetectionController_stopPolling() {
if (__classPrivateFieldGet(this, _TokenDetectionController_intervalId, "f")) {
clearInterval(__classPrivateFieldGet(this, _TokenDetectionController_intervalId, "f"));
diff --git a/dist/assetsUtil.cjs b/dist/assetsUtil.cjs
index 48571b8c1b78e94d88e1837e986b5f8735ac651b..61246f51500c8cab48f18296a73629fb73454caa 100644
--- a/dist/assetsUtil.cjs
Expand All @@ -56,7 +20,7 @@ index 48571b8c1b78e94d88e1837e986b5f8735ac651b..61246f51500c8cab48f18296a73629fb
// because most cid v0s appear to be incompatible with IPFS subdomains
return {
diff --git a/dist/token-prices-service/codefi-v2.mjs b/dist/token-prices-service/codefi-v2.mjs
index e7eaad2cfa8b233c4fd42a51f745233a1cc5c387..bf8ec7819f678c2f185d6a85d7e3ea81f055a309 100644
index a13403446a2376d4d905a9ef733941798da89c88..3c8229f9ea40f4c1ee760a22884e1066dac82ec7 100644
--- a/dist/token-prices-service/codefi-v2.mjs
+++ b/dist/token-prices-service/codefi-v2.mjs
@@ -12,8 +12,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
Expand All @@ -65,7 +29,7 @@ index e7eaad2cfa8b233c4fd42a51f745233a1cc5c387..bf8ec7819f678c2f185d6a85d7e3ea81
import { hexToNumber } from "@metamask/utils";
-import $cockatiel from "cockatiel";
-const { circuitBreaker, ConsecutiveBreaker, ExponentialBackoff, handleAll, retry, wrap, CircuitState } = $cockatiel;
+import { circuitBreaker, ConsecutiveBreaker, ExponentialBackoff, handleAll, retry, wrap, CircuitState } from "cockatiel"
+import { circuitBreaker, ConsecutiveBreaker, ExponentialBackoff, handleAll, retry, wrap, CircuitState } from "cockatiel";
/**
* The list of currencies that can be supplied as the `vsCurrency` parameter to
* the `/spot-prices` endpoint, in lowercase form.

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@
"@metamask/address-book-controller": "^6.0.0",
"@metamask/announcement-controller": "^7.0.0",
"@metamask/approval-controller": "^7.0.0",
"@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A45.0.0#~/.yarn/patches/@metamask-assets-controllers-npm-45.0.0-31810ece32.patch",
"@metamask/assets-controllers": "patch:@metamask/assets-controllers@npm%3A45.1.0#~/.yarn/patches/@metamask-assets-controllers-npm-45.1.0-d914c453f0.patch",
"@metamask/base-controller": "^7.0.0",
"@metamask/bitcoin-wallet-snap": "^0.8.2",
"@metamask/browser-passworder": "^4.3.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { useMemo } from 'react';
import { useSelector } from 'react-redux';

import { zeroAddress, toChecksumAddress } from 'ethereumjs-util';
import { toChecksumAddress } from 'ethereumjs-util';
import { getNativeTokenAddress } from '@metamask/assets-controllers';
import { Hex } from '@metamask/utils';
import {
getCurrentCurrency,
getSelectedAccount,
Expand Down Expand Up @@ -89,8 +91,9 @@ export const AggregatedPercentageOverviewCrossChains = () => {
item.tokensWithBalances,
);
const nativePricePercentChange1d =
crossChainMarketData?.[item.chainId]?.[zeroAddress()]
?.pricePercentChange1d;
crossChainMarketData?.[item.chainId]?.[
getNativeTokenAddress(item.chainId as Hex)
]?.pricePercentChange1d;

const nativeFiat1dAgo = getCalculatedTokenAmount1dAgo(
item.nativeFiatValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
getShouldHideZeroBalanceTokens,
getTokensMarketData,
getPreferences,
getCurrentChainId,
} from '../../../selectors';
import { useAccountTotalFiatBalance } from '../../../hooks/useAccountTotalFiatBalance';
import { AggregatedPercentageOverview } from './aggregated-percentage-overview';
Expand All @@ -26,20 +27,22 @@ jest.mock('../../../selectors', () => ({
getPreferences: jest.fn(),
getShouldHideZeroBalanceTokens: jest.fn(),
getTokensMarketData: jest.fn(),
getCurrentChainId: jest.fn(),
}));

jest.mock('../../../hooks/useAccountTotalFiatBalance', () => ({
useAccountTotalFiatBalance: jest.fn(),
}));

const mockGetIntlLocale = getIntlLocale as unknown as jest.Mock;
const mockGetCurrentCurrency = getCurrentCurrency as jest.Mock;
const mockGetPreferences = getPreferences as jest.Mock;
const mockGetSelectedAccount = getSelectedAccount as unknown as jest.Mock;
const mockGetShouldHideZeroBalanceTokens =
getShouldHideZeroBalanceTokens as jest.Mock;

const mockGetIntlLocale = jest.mocked(getIntlLocale);
const mockGetCurrentCurrency = jest.mocked(getCurrentCurrency);
const mockGetPreferences = jest.mocked(getPreferences);
const mockGetSelectedAccount = jest.mocked(getSelectedAccount);
const mockGetShouldHideZeroBalanceTokens = jest.mocked(
getShouldHideZeroBalanceTokens,
);
Comment on lines +37 to +43
Copy link
Contributor

Choose a reason for hiding this comment

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

TIL jest.mocked way better than casting to jest.Mock like I'm used to 👍

const mockGetTokensMarketData = getTokensMarketData as jest.Mock;
const mockGetCurrentChainId = jest.mocked(getCurrentChainId);

const selectedAccountMock = {
id: 'd51c0116-de36-4e77-b35b-408d4ea82d01',
Expand Down Expand Up @@ -166,7 +169,7 @@ describe('AggregatedPercentageOverview', () => {
mockGetSelectedAccount.mockReturnValue(selectedAccountMock);
mockGetShouldHideZeroBalanceTokens.mockReturnValue(false);
mockGetTokensMarketData.mockReturnValue(marketDataMock);

mockGetCurrentChainId.mockReturnValue('0x1');
jest.clearAllMocks();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React, { useMemo } from 'react';
import { useSelector } from 'react-redux';

import { zeroAddress, toChecksumAddress } from 'ethereumjs-util';
import { toChecksumAddress } from 'ethereumjs-util';
import { getNativeTokenAddress } from '@metamask/assets-controllers';
import {
getCurrentCurrency,
getSelectedAccount,
getShouldHideZeroBalanceTokens,
getTokensMarketData,
getPreferences,
getCurrentChainId,
} from '../../../selectors';

import { useAccountTotalFiatBalance } from '../../../hooks/useAccountTotalFiatBalance';
Expand Down Expand Up @@ -37,6 +39,7 @@ export const AggregatedPercentageOverview = () => {
const fiatCurrency = useSelector(getCurrentCurrency);
const { privacyMode } = useSelector(getPreferences);
const selectedAccount = useSelector(getSelectedAccount);
const currentChainId = useSelector(getCurrentChainId);
const shouldHideZeroBalanceTokens = useSelector(
getShouldHideZeroBalanceTokens,
);
Expand All @@ -63,7 +66,8 @@ export const AggregatedPercentageOverview = () => {
}
// native token
const nativePricePercentChange1d =
tokensMarketData?.[zeroAddress()]?.pricePercentChange1d;
tokensMarketData?.[getNativeTokenAddress(currentChainId)]
?.pricePercentChange1d;
const nativeFiat1dAgo = getCalculatedTokenAmount1dAgo(
item.fiatBalance,
nativePricePercentChange1d,
Expand Down
7 changes: 5 additions & 2 deletions ui/components/app/wallet-overview/coin-overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import React, {
} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import classnames from 'classnames';
import { zeroAddress } from 'ethereumjs-util';
import { CaipChainId } from '@metamask/utils';
import type { Hex } from '@metamask/utils';

import { InternalAccount } from '@metamask/keyring-api';
import { getNativeTokenAddress } from '@metamask/assets-controllers';
import {
Box,
ButtonIcon,
Expand Down Expand Up @@ -231,7 +231,10 @@ export const CoinOverview = ({
return (
<Box className="wallet-overview__currency-wrapper">
<PercentageAndAmountChange
value={tokensMarketData?.[zeroAddress()]?.pricePercentChange1d}
value={
tokensMarketData?.[getNativeTokenAddress(chainId as Hex)]
?.pricePercentChange1d
}
/>
{
///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { zeroAddress } from 'ethereumjs-util';
import { MarketDataDetails } from '@metamask/assets-controllers';
import { getIntlLocale } from '../../../../../ducks/locale/locale';
import {
getCurrentCurrency,
getSelectedAccountCachedBalance,
getTokensMarketData,
getCurrentChainId,
} from '../../../../../selectors';
import {
getConversionRate,
Expand All @@ -26,20 +28,23 @@ jest.mock('../../../../../selectors', () => ({
getCurrentCurrency: jest.fn(),
getSelectedAccountCachedBalance: jest.fn(),
getTokensMarketData: jest.fn(),
getCurrentChainId: jest.fn(),
}));

jest.mock('../../../../../ducks/metamask/metamask', () => ({
getConversionRate: jest.fn(),
getNativeCurrency: jest.fn(),
}));

const mockGetIntlLocale = getIntlLocale as unknown as jest.Mock;
const mockGetCurrentCurrency = getCurrentCurrency as jest.Mock;
const mockGetSelectedAccountCachedBalance =
getSelectedAccountCachedBalance as jest.Mock;
const mockGetConversionRate = getConversionRate as jest.Mock;
const mockGetNativeCurrency = getNativeCurrency as jest.Mock;
const mockGetTokensMarketData = getTokensMarketData as jest.Mock;
const mockGetIntlLocale = jest.mocked(getIntlLocale);
const mockGetCurrentCurrency = jest.mocked(getCurrentCurrency);
const mockGetSelectedAccountCachedBalance = jest.mocked(
getSelectedAccountCachedBalance,
);
const mockGetConversionRate = jest.mocked(getConversionRate);
const mockGetNativeCurrency = jest.mocked(getNativeCurrency);
const mockGetTokensMarketData = jest.mocked(getTokensMarketData);
const mockGetCurrentChainId = jest.mocked(getCurrentChainId);

describe('PercentageChange Component', () => {
beforeEach(() => {
Expand All @@ -51,9 +56,9 @@ describe('PercentageChange Component', () => {
mockGetTokensMarketData.mockReturnValue({
[zeroAddress()]: {
pricePercentChange1d: 2,
},
} as MarketDataDetails,
});

mockGetCurrentChainId.mockReturnValue('0x1');
jest.clearAllMocks();
});

Expand Down Expand Up @@ -108,4 +113,19 @@ describe('PercentageChange Component', () => {
expect(percentageElement).toBeInTheDocument();
expect(numberElement).toBeInTheDocument();
});

it('should display percentage for non-zero native tokens (MATIC)', () => {
mockGetTokensMarketData.mockReturnValue({
'0x0000000000000000000000000000000000001010': {
pricePercentChange1d: 2,
} as MarketDataDetails,
});
mockGetCurrentCurrency.mockReturnValue('POL');
mockGetCurrentChainId.mockReturnValue('0x89');
render(<PercentageAndAmountChange value={1} />);
const percentageElement = screen.getByText('(+1.00%)');
const numberElement = screen.getByText('+POL 12.21');
expect(percentageElement).toBeInTheDocument();
expect(numberElement).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import React, { useMemo } from 'react';
import { useSelector } from 'react-redux';
import { BigNumber } from 'bignumber.js';
import { isHexString, zeroAddress } from 'ethereumjs-util';
import { isHexString } from 'ethereumjs-util';
import { getNativeTokenAddress } from '@metamask/assets-controllers';
import { Text, Box } from '../../../../component-library';
import {
Display,
TextColor,
TextVariant,
} from '../../../../../helpers/constants/design-system';
import {
getCurrentChainId,
getCurrentCurrency,
getSelectedAccountCachedBalance,
getTokensMarketData,
Expand Down Expand Up @@ -66,10 +68,12 @@ export const PercentageAndAmountChange = ({
const conversionRate = useSelector(getConversionRate);
const nativeCurrency = useSelector(getNativeCurrency);
const marketData = useSelector(getTokensMarketData);
const currentChainId = useSelector(getCurrentChainId);

const balanceChange = useMemo(() => {
// Extracts the 1-day percentage change in price from marketData using the zero address as a key.
const percentage1d = marketData?.[zeroAddress()]?.pricePercentChange1d;
const percentage1d =
marketData?.[getNativeTokenAddress(currentChainId)]?.pricePercentChange1d;

// Checks if the balanceValue is in hex format. This is important for cryptocurrency balances which are often represented in hex.
if (isHexString(balanceValue)) {
Expand Down
10 changes: 6 additions & 4 deletions ui/components/multichain/token-list-item/token-list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React, { useContext, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import classnames from 'classnames';
import { zeroAddress } from 'ethereumjs-util';
import { getNativeTokenAddress } from '@metamask/assets-controllers';
import { Hex } from '@metamask/utils';
import {
AlignItems,
BackgroundColor,
Expand Down Expand Up @@ -336,13 +337,14 @@ export const TokenListItem = ({
<PercentageChange
value={
isNativeCurrency
? multiChainMarketData?.[chainId]?.[zeroAddress()]
?.pricePercentChange1d
? multiChainMarketData?.[chainId]?.[
getNativeTokenAddress(chainId as Hex)
]?.pricePercentChange1d
: tokenPercentageChange
}
address={
isNativeCurrency
? (zeroAddress() as `0x${string}`)
? getNativeTokenAddress(chainId as Hex)
: (address as `0x${string}`)
}
/>
Expand Down
Loading
Loading