Skip to content
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,4 +1,6 @@
import { BigNumber } from 'bignumber.js';
import { CHAIN_IDS } from '@metamask/transaction-controller';
import { Hex } from '@metamask/utils';
import { act } from '@testing-library/react';

import { getMockConfirmStateForTransaction } from '../../../../../../test/data/confirmations/helper';
Expand All @@ -10,18 +12,23 @@ import * as TokenUtils from '../../../utils/token';
import { Confirmation } from '../../../types/confirm';
import { useDappSwapUSDValues } from './useDappSwapUSDValues';

async function runHook() {
async function runHook(
tokenAddresses?: Hex[],
mockConfirmation?: Confirmation,
) {
const response = renderHookWithConfirmContextProvider(
() =>
useDappSwapUSDValues({
tokenAddresses: [
tokenAddresses: tokenAddresses ?? [
'0x0000000000000000000000000000000000000000',
'0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
'0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9',
],
destTokenAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
}),
getMockConfirmStateForTransaction(mockSwapConfirmation as Confirmation),
getMockConfirmStateForTransaction(
mockConfirmation ?? (mockSwapConfirmation as Confirmation),
),
);

await act(async () => {
Expand Down Expand Up @@ -98,4 +105,35 @@ describe('useDappSwapUSDValues', () => {
'0xfdcc3dd6671eab0709a4c0f3f53de9a333d80798': 1,
});
});

it('return correct fiat rates token on Polygon', async () => {
jest.spyOn(Utils, 'fetchTokenExchangeRates').mockResolvedValue({
'0x0000000000000000000000000000000000001010': 4052.27,
'0x833589fcd6edb6e08f4c7c32d4f71b54bda02913': 0.999804,
});
jest.spyOn(TokenUtils, 'fetchAllTokenDetails').mockResolvedValue({
'0x0000000000000000000000000000000000000000': {
symbol: 'POL',
decimals: '18',
} as TokenStandAndDetails,
'0x833589fcd6edb6e08f4c7c32d4f71b54bda02913': {
symbol: 'USDT',
decimals: '6',
} as TokenStandAndDetails,
});

const result = await runHook(
[
'0x0000000000000000000000000000000000000000',
'0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
],
{ ...mockSwapConfirmation, chainId: CHAIN_IDS.POLYGON } as Confirmation,
);

expect(result.fiatRates).toEqual({
'0x0000000000000000000000000000000000000000': 4052.27,
'0x0000000000000000000000000000000000001010': 4052.27,
'0x833589fcd6edb6e08f4c7c32d4f71b54bda02913': 0.999804,
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
getNativeAssetForChainId,
isNativeAddress,
Copy link
Contributor

@gauthierpetetin gauthierpetetin Nov 21, 2025

Choose a reason for hiding this comment

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

Note to facilitate the future stable-sync PR:

In the original PR on main, isNativeAddress is imported from a different location:

import { isNativeAddress } from '../../../../../helpers/utils/token-insights';

This is because the location of isNativeAddress was moved in this PR, which is part of 13.11.0 but is not included in 13.10.1.

} from '@metamask/bridge-controller';
import { TransactionMeta } from '@metamask/transaction-controller';
import { CHAIN_IDS, TransactionMeta } from '@metamask/transaction-controller';
import { useCallback } from 'react';

import { TokenStandAndDetails } from '../../../../../store/actions';
Expand All @@ -15,6 +15,8 @@ import { fetchAllTokenDetails } from '../../../utils/token';
import { getTokenValueFromRecord } from '../../../utils/dapp-swap-comparison-utils';
import { useConfirmContext } from '../../../context/confirm';

const POLYGON_NATIVE_ASSET = '0x0000000000000000000000000000000000001010';

export function useDappSwapUSDValues({
tokenAddresses = [],
destTokenAddress,
Expand All @@ -30,11 +32,22 @@ export function useDappSwapUSDValues({

const { value: fiatRates, pending: fiatRatesPending } = useAsyncResult<
Record<Hex, number | undefined>
>(() => {
>(async () => {
const addresses = tokenAddresses.filter(
(tokenAddress) => !isNativeAddress(tokenAddress),
);
return fetchTokenExchangeRates('usd', addresses as Hex[], chainId);
const exchangeRates = await fetchTokenExchangeRates(
'usd',
addresses as Hex[],
chainId,
);

if (chainId === CHAIN_IDS.POLYGON) {
const nativeAddress = getNativeAssetForChainId(chainId).address;
exchangeRates[nativeAddress] = exchangeRates[POLYGON_NATIVE_ASSET];
}
Copy link

Choose a reason for hiding this comment

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

Bug: Missing zero address mapping for Polygon native token rates

When on Polygon, the code maps the exchange rate from POLYGON_NATIVE_ASSET (0x0000000000000000000000000000000000001010) to the chain's native asset address. However, callers may also reference the universal zero address (0x0000000000000000000000000000000000000000) for the native token. The current implementation only populates the Polygon native asset address, leaving lookups by the zero address without a rate value, causing incorrect USD value calculations.

Fix in Cursor Fix in Web


return exchangeRates;
}, [chainId, tokenAddresses?.length]);

const { value: tokenDetails, pending: tokenDetailsPending } = useAsyncResult<
Expand Down
Loading