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
1 change: 1 addition & 0 deletions packages/assets-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 3 additions & 2 deletions packages/assets-controller/src/utils/native-assets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
buildNativeAssetsFromConstant,
buildNativeAssetsFromApi,
} from './native-assets';
import { normalizeAssetId } from './normalizeAssetId';

jest.mock('@metamask/controller-utils', () => ({
...jest.requireActual('@metamask/controller-utils'),
Expand All @@ -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));
}
});
});
Expand Down
3 changes: 2 additions & 1 deletion packages/assets-controller/src/utils/native-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -23,7 +24,7 @@ export function buildNativeAssetsFromConstant(): Record<
const nativeAssetsMap: Record<ChainId, Caip19AssetId> = {};
for (const nativeAssetId of Object.values(SPOT_PRICES_SUPPORT_INFO)) {
const { chainId } = parseCaipAssetType(nativeAssetId);
nativeAssetsMap[chainId] = nativeAssetId;
nativeAssetsMap[chainId] = normalizeAssetId(nativeAssetId);
}
return nativeAssetsMap;
}
Expand Down
Loading