From d0f6f92430bf091ac6e87cb607ff9f8e5b0fd5ef Mon Sep 17 00:00:00 2001 From: Bernardo Garces Chapero Date: Wed, 13 May 2026 13:07:20 +0100 Subject: [PATCH 1/2] normalize assetIds for native assets --- packages/assets-controller/src/utils/native-assets.test.ts | 5 +++-- packages/assets-controller/src/utils/native-assets.ts | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/assets-controller/src/utils/native-assets.test.ts b/packages/assets-controller/src/utils/native-assets.test.ts index 1712a996be..e63df1bd83 100644 --- a/packages/assets-controller/src/utils/native-assets.test.ts +++ b/packages/assets-controller/src/utils/native-assets.test.ts @@ -5,6 +5,7 @@ import { buildNativeAssetsFromConstant, buildNativeAssetsFromApi, } from './native-assets'; +import { normalizeAssetId } from './normalizeAssetId'; jest.mock('@metamask/controller-utils', () => ({ ...jest.requireActual('@metamask/controller-utils'), @@ -14,12 +15,12 @@ jest.mock('@metamask/controller-utils', () => ({ const fetchWithErrorHandlingMock = jest.mocked(fetchWithErrorHandling); describe('buildNativeAssetsFromConstant', () => { - it('includes an entry for every value in SPOT_PRICES_SUPPORT_INFO', () => { + it('includes a normalized entry for every value in SPOT_PRICES_SUPPORT_INFO', () => { const result = buildNativeAssetsFromConstant(); const supportInfoValues = Object.values(SPOT_PRICES_SUPPORT_INFO); for (const assetId of supportInfoValues) { - expect(Object.values(result)).toContain(assetId); + expect(Object.values(result)).toContain(normalizeAssetId(assetId)); } }); }); diff --git a/packages/assets-controller/src/utils/native-assets.ts b/packages/assets-controller/src/utils/native-assets.ts index 6dc7e8cac5..2693daae52 100644 --- a/packages/assets-controller/src/utils/native-assets.ts +++ b/packages/assets-controller/src/utils/native-assets.ts @@ -3,6 +3,7 @@ import { fetchWithErrorHandling } from '@metamask/controller-utils'; import { parseCaipAssetType } from '@metamask/utils'; import type { Caip19AssetId, ChainId } from '../types'; +import { normalizeAssetId } from './normalizeAssetId'; const CHAINID_NETWORK_URL = 'https://chainid.network/chains.json'; @@ -23,7 +24,7 @@ export function buildNativeAssetsFromConstant(): Record< const nativeAssetsMap: Record = {}; for (const nativeAssetId of Object.values(SPOT_PRICES_SUPPORT_INFO)) { const { chainId } = parseCaipAssetType(nativeAssetId); - nativeAssetsMap[chainId] = nativeAssetId; + nativeAssetsMap[chainId] = normalizeAssetId(nativeAssetId); } return nativeAssetsMap; } From 0f4595f6c9f9865465e007c71357264e13c77ca7 Mon Sep 17 00:00:00 2001 From: Bernardo Garces Chapero Date: Wed, 13 May 2026 13:10:47 +0100 Subject: [PATCH 2/2] changelog --- packages/assets-controller/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/assets-controller/CHANGELOG.md b/packages/assets-controller/CHANGELOG.md index a0eba5b54d..726e2c1db4 100644 --- a/packages/assets-controller/CHANGELOG.md +++ b/packages/assets-controller/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- `buildNativeAssetsFromConstant` now normalizes each native asset ID via `normalizeAssetId`, ensuring ERC20 addresses are EIP-55 checksummed and consistent with IDs written by data sources ([#8789](https://github.com/MetaMask/core/pull/8789)) - `RpcDataSource` no longer writes `{ amount: "NaN" }` entries into `assetsBalance` when state holds malformed native metadata ([#8781](https://github.com/MetaMask/core/pull/8781)) - Existing native metadata in `assetsInfo` is now only reused when its `decimals` field is a finite, non-negative number (via a new `#hasValidDecimals` guard). Stale entries like `{ type: 'native', decimals: null, name: '', symbol: '' }` or `{ decimals: -1, ... }` are replaced with the chain-status stub (`{ type: 'native', symbol/name: chainStatus.nativeCurrency, decimals: 18 }`) so balance conversion has a usable `decimals` and consumers never see a negative `decimals` in `assetsInfo`. - `decimals: 0` is treated as valid; `name` and `symbol` are not required.