diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 7bb393db474..12eaf6f79ed 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -7,9 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add dynamic fetching of supported networks from `/v2/supportedNetworks` API endpoint with fallback to hardcoded list ([#7716](https://github.com/MetaMask/core/pull/7716)) + - Add `fetchSupportedNetworks()`, `getSupportedNetworks()`, and `resetSupportedNetworksCache()` exports from token-prices-service + - Add `setNativeAssetIdentifiers()` method to `CodefiTokenPricesServiceV2` for CAIP-19 native token lookups + - Add `updateSupportedNetworks()` method to `CodefiTokenPricesServiceV2` + - Add `NativeAssetIdentifiersMap` type export from token-prices-service +- Integrate `TokenRatesController` with `NetworkEnablementController` to use native asset identifiers for token price lookups ([#7716](https://github.com/MetaMask/core/pull/7716)) + ### Changed - Bump `@metamask/keyring-controller` from `^25.0.0` to `^25.1.0` ([#7713](https://github.com/MetaMask/core/pull/7713)) +- Add `@metamask/network-enablement-controller` as a dependency ([#7716](https://github.com/MetaMask/core/pull/7716)) ## [96.0.0] diff --git a/packages/assets-controllers/package.json b/packages/assets-controllers/package.json index 2957a493e2c..2f9bd216051 100644 --- a/packages/assets-controllers/package.json +++ b/packages/assets-controllers/package.json @@ -69,6 +69,7 @@ "@metamask/metamask-eth-abis": "^3.1.1", "@metamask/multichain-account-service": "^5.1.0", "@metamask/network-controller": "^29.0.0", + "@metamask/network-enablement-controller": "^4.1.0", "@metamask/permission-controller": "^12.2.0", "@metamask/phishing-controller": "^16.1.0", "@metamask/polling-controller": "^16.0.2", diff --git a/packages/assets-controllers/src/TokenRatesController.test.ts b/packages/assets-controllers/src/TokenRatesController.test.ts index 2ab2ae504f9..761657d12dd 100644 --- a/packages/assets-controllers/src/TokenRatesController.test.ts +++ b/packages/assets-controllers/src/TokenRatesController.test.ts @@ -68,7 +68,11 @@ function buildTokenRatesControllerMessenger( }); messenger.delegate({ messenger: tokenRatesControllerMessenger, - actions: ['TokensController:getState', 'NetworkController:getState'], + actions: [ + 'TokensController:getState', + 'NetworkController:getState', + 'NetworkEnablementController:getState', + ], events: ['TokensController:stateChange', 'NetworkController:stateChange'], }); return tokenRatesControllerMessenger; @@ -83,6 +87,48 @@ describe('TokenRatesController', () => { }); }); }); + + it('should call setNativeAssetIdentifiers on tokenPricesService if available', async () => { + const setNativeAssetIdentifiers = jest.fn(); + const tokenPricesService = buildMockTokenPricesService({ + setNativeAssetIdentifiers, + }); + + await withController( + { + options: { + tokenPricesService, + }, + }, + async () => { + expect(setNativeAssetIdentifiers).toHaveBeenCalledWith({ + 'eip155:1': 'eip155:1/slip44:60', + 'eip155:137': 'eip155:137/slip44:966', + }); + }, + ); + }); + + it('should not fail if tokenPricesService does not have setNativeAssetIdentifiers', async () => { + const tokenPricesService = buildMockTokenPricesService(); + // Explicitly remove setNativeAssetIdentifiers to simulate an old service + delete (tokenPricesService as Partial) + .setNativeAssetIdentifiers; + + await withController( + { + options: { + tokenPricesService, + }, + }, + async ({ controller }) => { + // Should not throw and controller should be created + expect(controller.state).toStrictEqual({ + marketData: {}, + }); + }, + ); + }); }); describe('updateExchangeRates', () => { @@ -1213,6 +1259,18 @@ async function withController( }), ); + // Register NetworkEnablementController:getState handler + messenger.registerActionHandler( + 'NetworkEnablementController:getState', + jest.fn().mockReturnValue({ + enabledNetworkMap: {}, + nativeAssetIdentifiers: { + 'eip155:1': 'eip155:1/slip44:60', + 'eip155:137': 'eip155:137/slip44:966', + }, + }), + ); + const controller = new TokenRatesController({ tokenPricesService: buildMockTokenPricesService(), messenger: buildTokenRatesControllerMessenger(messenger), @@ -1259,6 +1317,7 @@ function buildMockTokenPricesService( validateCurrencySupported(_currency: unknown): _currency is string { return true; }, + setNativeAssetIdentifiers: jest.fn(), ...overrides, }; } diff --git a/packages/assets-controllers/src/TokenRatesController.ts b/packages/assets-controllers/src/TokenRatesController.ts index d4f7d002d4d..6b8df1e3f1c 100644 --- a/packages/assets-controllers/src/TokenRatesController.ts +++ b/packages/assets-controllers/src/TokenRatesController.ts @@ -9,6 +9,7 @@ import type { NetworkControllerGetStateAction, NetworkControllerStateChangeEvent, } from '@metamask/network-controller'; +import type { NetworkEnablementControllerGetStateAction } from '@metamask/network-enablement-controller'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import type { Hex } from '@metamask/utils'; import { isEqual } from 'lodash'; @@ -93,7 +94,8 @@ type ChainIdAndNativeCurrency = { */ export type AllowedActions = | TokensControllerGetStateAction - | NetworkControllerGetStateAction; + | NetworkControllerGetStateAction + | NetworkEnablementControllerGetStateAction; /** * The external events available to the {@link TokenRatesController}. @@ -234,6 +236,9 @@ export class TokenRatesController extends StaticIntervalPollingController; + /** * Represents an exchange rate. */ @@ -103,4 +108,14 @@ export type AbstractTokenPricesService< * @returns True if the API supports the currency, false otherwise. */ validateCurrencySupported(currency: unknown): currency is Currency; + + /** + * Sets the native asset identifiers map for resolving native token CAIP-19 IDs. + * This should be called with data from NetworkEnablementController.state.nativeAssetIdentifiers. + * + * @param nativeAssetIdentifiers - Map of CAIP-2 chain IDs to native asset identifiers. + */ + setNativeAssetIdentifiers?( + nativeAssetIdentifiers: NativeAssetIdentifiersMap, + ): void; }; diff --git a/packages/assets-controllers/src/token-prices-service/codefi-v2.test.ts b/packages/assets-controllers/src/token-prices-service/codefi-v2.test.ts index bdb2c516e90..f00735fccd9 100644 --- a/packages/assets-controllers/src/token-prices-service/codefi-v2.test.ts +++ b/packages/assets-controllers/src/token-prices-service/codefi-v2.test.ts @@ -13,6 +13,9 @@ import { fetchSupportedCurrencies, getSupportedCurrencies, resetSupportedCurrenciesCache, + fetchSupportedNetworks, + getSupportedNetworks, + resetSupportedNetworksCache, } from './codefi-v2'; // We're not customizing the default max delay @@ -1920,6 +1923,237 @@ describe('CodefiTokenPricesServiceV2', () => { expect(result).toStrictEqual([...SUPPORTED_CURRENCIES_FALLBACK]); }); }); + + describe('fetchSupportedNetworks', () => { + afterEach(() => { + resetSupportedNetworksCache(); + }); + + it('fetches supported networks from the API and returns them', async () => { + const mockResponse = { + fullSupport: ['eip155:1', 'eip155:137'], + partialSupport: { + spotPricesV2: ['eip155:1', 'eip155:137', 'eip155:56'], + spotPricesV3: ['eip155:1', 'eip155:137', 'eip155:42161'], + }, + }; + nock('https://price.api.cx.metamask.io') + .get('/v2/supportedNetworks') + .reply(200, mockResponse); + + const result = await fetchSupportedNetworks(); + + expect(result).toStrictEqual(mockResponse); + }); + + it('returns the fallback list when the API returns an invalid response', async () => { + nock('https://price.api.cx.metamask.io') + .get('/v2/supportedNetworks') + .reply(200, { invalid: 'response' }); + + const result = await fetchSupportedNetworks(); + + expect(result.fullSupport).toBeDefined(); + expect(result.partialSupport).toBeDefined(); + expect(result.partialSupport.spotPricesV3).toBeDefined(); + }); + + it('returns the fallback list when the API request fails', async () => { + nock('https://price.api.cx.metamask.io') + .get('/v2/supportedNetworks') + .replyWithError('Network error'); + + const result = await fetchSupportedNetworks(); + + expect(result.fullSupport).toBeDefined(); + expect(result.partialSupport).toBeDefined(); + expect(result.partialSupport.spotPricesV3).toBeDefined(); + }); + + it('updates getSupportedNetworks after a successful fetch', async () => { + const mockResponse = { + fullSupport: ['eip155:1'], + partialSupport: { + spotPricesV2: ['eip155:1', 'eip155:56'], + spotPricesV3: ['eip155:1', 'eip155:42161'], + }, + }; + nock('https://price.api.cx.metamask.io') + .get('/v2/supportedNetworks') + .reply(200, mockResponse); + + await fetchSupportedNetworks(); + const result = getSupportedNetworks(); + + expect(result).toStrictEqual(mockResponse); + }); + }); + + describe('getSupportedNetworks', () => { + beforeEach(() => { + resetSupportedNetworksCache(); + }); + + it('returns the fallback list when no networks have been fetched', () => { + const result = getSupportedNetworks(); + + expect(result.fullSupport).toBeDefined(); + expect(result.partialSupport).toBeDefined(); + expect(result.partialSupport.spotPricesV3).toBeDefined(); + expect(Array.isArray(result.fullSupport)).toBe(true); + expect(Array.isArray(result.partialSupport.spotPricesV3)).toBe(true); + }); + }); + + describe('updateSupportedNetworks', () => { + afterEach(() => { + resetSupportedNetworksCache(); + }); + + it('fetches and returns supported networks via the service method', async () => { + const mockResponse = { + fullSupport: ['eip155:1', 'eip155:10'], + partialSupport: { + spotPricesV2: ['eip155:1'], + spotPricesV3: ['eip155:1', 'eip155:10'], + }, + }; + nock('https://price.api.cx.metamask.io') + .get('/v2/supportedNetworks') + .reply(200, mockResponse); + + const service = new CodefiTokenPricesServiceV2(); + const result = await service.updateSupportedNetworks(); + + expect(result).toStrictEqual(mockResponse); + }); + + it('returns the fallback list when the API fails', async () => { + nock('https://price.api.cx.metamask.io') + .get('/v2/supportedNetworks') + .replyWithError('Network error'); + + const service = new CodefiTokenPricesServiceV2(); + const result = await service.updateSupportedNetworks(); + + expect(result.fullSupport).toBeDefined(); + expect(result.partialSupport).toBeDefined(); + }); + }); + + describe('setNativeAssetIdentifiers', () => { + afterEach(() => { + resetSupportedNetworksCache(); + }); + + it('sets native asset identifiers and uses them in fetchTokenPrices', async () => { + // Mock supportedNetworks to include our test chain + const mockNetworksResponse = { + fullSupport: ['eip155:1'], + partialSupport: { + spotPricesV2: [], + spotPricesV3: ['eip155:1'], + }, + }; + nock('https://price.api.cx.metamask.io') + .get('/v2/supportedNetworks') + .reply(200, mockNetworksResponse) + .persist(); + + // Pre-populate the cache + await fetchSupportedNetworks(); + + const customNativeAssetId = 'eip155:1/slip44:60'; + const nativeAssetIdentifiers = { + 'eip155:1': customNativeAssetId, + }; + + // Mock the spot-prices response + nock('https://price.api.cx.metamask.io') + .get('/v3/spot-prices') + .query(true) + .reply(200, { + [customNativeAssetId]: { + price: 2000, + currency: 'USD', + pricePercentChange1d: 1, + priceChange1d: 1, + marketCap: 1000000, + allTimeHigh: 5000, + allTimeLow: 100, + totalVolume: 50000, + high1d: 2100, + low1d: 1900, + circulatingSupply: 1000000, + dilutedMarketCap: 2000000, + marketCapPercentChange1d: 0.5, + pricePercentChange1h: 0.1, + pricePercentChange7d: 5, + pricePercentChange14d: 10, + pricePercentChange30d: 15, + pricePercentChange200d: 50, + pricePercentChange1y: 100, + }, + }); + + const service = new CodefiTokenPricesServiceV2(); + service.setNativeAssetIdentifiers( + nativeAssetIdentifiers as Record< + `${string}:${string}`, + `${string}:${string}/${string}:${string}` + >, + ); + + const result = await service.fetchTokenPrices({ + assets: [{ chainId: '0x1', tokenAddress: ZERO_ADDRESS }], + currency: 'USD', + }); + + expect(result).toHaveLength(1); + expect(result[0].price).toBe(2000); + }); + }); + + describe('validateChainIdSupported with dynamic networks', () => { + afterEach(() => { + resetSupportedNetworksCache(); + }); + + it('returns true for chains in the dynamic supported networks list', async () => { + const mockResponse = { + fullSupport: ['eip155:999999'], + partialSupport: { + spotPricesV2: [], + spotPricesV3: ['eip155:999999'], + }, + }; + nock('https://price.api.cx.metamask.io') + .get('/v2/supportedNetworks') + .reply(200, mockResponse); + + await fetchSupportedNetworks(); + + const service = new CodefiTokenPricesServiceV2(); + // 0xf423f = 999999 in hex + expect(service.validateChainIdSupported('0xf423f')).toBe(true); + }); + + it('returns true for chains in the hardcoded fallback list', () => { + resetSupportedNetworksCache(); + + const service = new CodefiTokenPricesServiceV2(); + // 0x1 (Ethereum mainnet) should always be in the hardcoded list + expect(service.validateChainIdSupported('0x1')).toBe(true); + }); + + it('returns false for unsupported chains', () => { + resetSupportedNetworksCache(); + + const service = new CodefiTokenPricesServiceV2(); + // Some random chain ID that's not supported + expect(service.validateChainIdSupported('0xdeadbeef')).toBe(false); + }); + }); }); /** diff --git a/packages/assets-controllers/src/token-prices-service/codefi-v2.ts b/packages/assets-controllers/src/token-prices-service/codefi-v2.ts index 4a5092d0865..0d026278b25 100644 --- a/packages/assets-controllers/src/token-prices-service/codefi-v2.ts +++ b/packages/assets-controllers/src/token-prices-service/codefi-v2.ts @@ -11,6 +11,7 @@ import type { CaipAssetType, Hex } from '@metamask/utils'; import { hexToNumber, KnownCaipNamespace, + numberToHex, toCaipChainId, } from '@metamask/utils'; @@ -20,6 +21,7 @@ import type { EvmAssetWithId, EvmAssetWithMarketData, ExchangeRatesByCurrency, + NativeAssetIdentifiersMap, } from './abstract-token-prices-service'; import type { MarketDataDetails } from '../TokenRatesController'; @@ -343,20 +345,132 @@ export const SUPPORTED_CHAIN_IDS = Object.keys( */ type SupportedChainId = (typeof SUPPORTED_CHAIN_IDS)[number]; +const BASE_URL_V1 = 'https://price.api.cx.metamask.io/v1'; + +const BASE_URL_V2 = 'https://price.api.cx.metamask.io/v2'; + +const BASE_URL_V3 = 'https://price.api.cx.metamask.io/v3'; + /** - * The list of chain IDs that are supported by V3 of the Codefi Price API. - * Only includes chain IDs from SPOT_PRICES_SUPPORT_INFO that have a non-null CAIP-19 value. + * Response type for the /v2/supportedNetworks endpoint. */ -const SUPPORTED_CHAIN_IDS_V3 = Object.keys(SPOT_PRICES_SUPPORT_INFO).filter( - (chainId) => - SPOT_PRICES_SUPPORT_INFO[ - chainId as keyof typeof SPOT_PRICES_SUPPORT_INFO - ] !== null, -); +type SupportedNetworksResponse = { + fullSupport: string[]; + partialSupport: { + spotPricesV2: string[]; + spotPricesV3: string[]; + }; +}; -const BASE_URL_V1 = 'https://price.api.cx.metamask.io/v1'; +/** + * In-memory store for the last successfully fetched supported networks. + */ +let lastFetchedSupportedNetworks: SupportedNetworksResponse | null = null; -const BASE_URL_V3 = 'https://price.api.cx.metamask.io/v3'; +/** + * Converts a CAIP-2 chain ID (e.g., 'eip155:1') to a hex chain ID (e.g., '0x1'). + * + * @param caipChainId - The CAIP-2 chain ID string. + * @returns The hex chain ID or null if not an EIP-155 chain. + */ +function caipChainIdToHex(caipChainId: string): Hex | null { + const match = caipChainId.match(/^eip155:(\d+)$/u); + if (!match) { + return null; + } + return numberToHex(parseInt(match[1], 10)); +} + +/** + * Fetches the list of supported networks from the API. + * Falls back to the hardcoded list if the fetch fails. + * + * @returns The supported networks response. + */ +export async function fetchSupportedNetworks(): Promise { + try { + const url = `${BASE_URL_V2}/supportedNetworks`; + const response = await handleFetch(url, { + headers: { 'Cache-Control': 'no-cache' }, + }); + + if ( + response && + typeof response === 'object' && + 'fullSupport' in response && + 'partialSupport' in response + ) { + lastFetchedSupportedNetworks = response as SupportedNetworksResponse; + return lastFetchedSupportedNetworks; + } + + // Invalid response format, fall back to hardcoded list + return getSupportedNetworksFallback(); + } catch { + // On any error, fall back to the hardcoded list + return getSupportedNetworksFallback(); + } +} + +/** + * Synchronously gets the list of supported networks. + * Returns the last fetched value if available, otherwise returns the fallback list. + * + * @returns The supported networks response. + */ +export function getSupportedNetworks(): SupportedNetworksResponse { + if (lastFetchedSupportedNetworks !== null) { + return lastFetchedSupportedNetworks; + } + return getSupportedNetworksFallback(); +} + +/** + * Generates a fallback supported networks response from the hardcoded SPOT_PRICES_SUPPORT_INFO. + * + * @returns A SupportedNetworksResponse derived from hardcoded data. + */ +function getSupportedNetworksFallback(): SupportedNetworksResponse { + const caipChainIds = Object.keys(SPOT_PRICES_SUPPORT_INFO).map((hexChainId) => + toCaipChainId( + KnownCaipNamespace.Eip155, + hexToNumber(hexChainId as Hex).toString(), + ), + ); + + return { + fullSupport: caipChainIds.slice(0, 11), // First 11 chains as "full support" + partialSupport: { + spotPricesV2: caipChainIds, + spotPricesV3: caipChainIds, + }, + }; +} + +/** + * Resets the supported networks cache. + * This is primarily intended for testing purposes. + */ +export function resetSupportedNetworksCache(): void { + lastFetchedSupportedNetworks = null; +} + +/** + * Gets the list of supported chain IDs for spot prices v3 as hex values. + * + * @returns Array of hex chain IDs supported by spot prices v3. + */ +function getSupportedChainIdsV3AsHex(): Hex[] { + const supportedNetworks = getSupportedNetworks(); + const allV3Chains = [ + ...supportedNetworks.fullSupport, + ...supportedNetworks.partialSupport.spotPricesV3, + ]; + + return allV3Chains + .map(caipChainIdToHex) + .filter((hexChainId): hexChainId is Hex => hexChainId !== null); +} /** * In-memory store for the last successfully fetched supported currencies. @@ -422,6 +536,12 @@ export class CodefiTokenPricesServiceV2 { readonly #policy: ServicePolicy; + /** + * Map of CAIP-2 chain IDs to their native asset identifiers. + * Updated via setNativeAssetIdentifiers(). + */ + #nativeAssetIdentifiers: NativeAssetIdentifiersMap = {}; + /** * Construct a Codefi Token Price Service. * @@ -526,6 +646,28 @@ export class CodefiTokenPricesServiceV2 return this.#policy.onDegraded(...args); } + /** + * Sets the native asset identifiers map for resolving native token CAIP-19 IDs. + * This should be called with data from NetworkEnablementController.state.nativeAssetIdentifiers. + * + * @param nativeAssetIdentifiers - Map of CAIP-2 chain IDs to native asset identifiers. + */ + setNativeAssetIdentifiers( + nativeAssetIdentifiers: NativeAssetIdentifiersMap, + ): void { + this.#nativeAssetIdentifiers = nativeAssetIdentifiers; + } + + /** + * Updates the supported networks cache by fetching from the API. + * This should be called periodically to keep the supported networks list fresh. + * + * @returns The updated supported networks response. + */ + async updateSupportedNetworks(): Promise { + return fetchSupportedNetworks(); + } + /** * Retrieves prices in the given currency for the tokens identified by the * given addresses which are expected to live on the given chain. @@ -542,9 +684,18 @@ export class CodefiTokenPricesServiceV2 assets: EvmAssetAddressWithChain[]; currency: SupportedCurrency; }): Promise[]> { + // Refresh supported networks in background (non-blocking) + // This ensures the list stays fresh during normal polling + // Note: fetchSupportedNetworks handles errors internally and always resolves + // eslint-disable-next-line @typescript-eslint/no-floating-promises + fetchSupportedNetworks(); + + // Get dynamically fetched supported chain IDs for V3 + const supportedChainIdsV3 = getSupportedChainIdsV3AsHex(); + const assetsWithIds: EvmAssetWithId[] = assets // Filter out assets that are not supported by V3 of the Price API. - .filter((asset) => SUPPORTED_CHAIN_IDS_V3.includes(asset.chainId)) + .filter((asset) => supportedChainIdsV3.includes(asset.chainId)) .map((asset) => { const caipChainId = toCaipChainId( KnownCaipNamespace.Eip155, @@ -552,16 +703,34 @@ export class CodefiTokenPricesServiceV2 ); const nativeAddress = getNativeTokenAddress(asset.chainId); + const isNativeToken = + nativeAddress.toLowerCase() === asset.tokenAddress.toLowerCase(); + + let assetId: string | undefined; + if (isNativeToken) { + // For native tokens, use nativeAssetIdentifiers from NetworkEnablementController, + // falling back to hardcoded SPOT_PRICES_SUPPORT_INFO + assetId = + this.#nativeAssetIdentifiers[caipChainId] ?? + SPOT_PRICES_SUPPORT_INFO[asset.chainId]; + } else { + // For ERC20 tokens, construct the CAIP-19 ID dynamically + assetId = `${caipChainId}/erc20:${asset.tokenAddress.toLowerCase()}`; + } + + if (!assetId) { + return undefined; + } return { ...asset, - assetId: (nativeAddress.toLowerCase() === - asset.tokenAddress.toLowerCase() - ? SPOT_PRICES_SUPPORT_INFO[asset.chainId] - : `${caipChainId}/erc20:${asset.tokenAddress.toLowerCase()}`) as CaipAssetType, + assetId: assetId as CaipAssetType, }; }) - .filter((asset) => asset.assetId); + .filter( + (asset): asset is EvmAssetWithId => + asset !== undefined, + ); if (assetsWithIds.length === 0) { return []; @@ -717,8 +886,15 @@ export class CodefiTokenPricesServiceV2 * @returns True if the API supports the chain ID, false otherwise. */ validateChainIdSupported(chainId: unknown): chainId is SupportedChainId { - const supportedChainIds: readonly string[] = SUPPORTED_CHAIN_IDS; - return typeof chainId === 'string' && supportedChainIds.includes(chainId); + // Use dynamically fetched supported networks + const supportedChainIds = getSupportedChainIdsV3AsHex(); + // Also include the hardcoded fallback list for backwards compatibility + const allSupportedChainIds: readonly string[] = [ + ...new Set([...supportedChainIds, ...SUPPORTED_CHAIN_IDS]), + ]; + return ( + typeof chainId === 'string' && allSupportedChainIds.includes(chainId) + ); } /** diff --git a/packages/assets-controllers/src/token-prices-service/index.test.ts b/packages/assets-controllers/src/token-prices-service/index.test.ts index a59be2ba4de..13ffb135df6 100644 --- a/packages/assets-controllers/src/token-prices-service/index.test.ts +++ b/packages/assets-controllers/src/token-prices-service/index.test.ts @@ -7,6 +7,9 @@ describe('token-prices-service', () => { "CodefiTokenPricesServiceV2", "SUPPORTED_CHAIN_IDS", "getNativeTokenAddress", + "fetchSupportedNetworks", + "getSupportedNetworks", + "resetSupportedNetworksCache", ] `); }); diff --git a/packages/assets-controllers/src/token-prices-service/index.ts b/packages/assets-controllers/src/token-prices-service/index.ts index 509fc680055..cb788010df2 100644 --- a/packages/assets-controllers/src/token-prices-service/index.ts +++ b/packages/assets-controllers/src/token-prices-service/index.ts @@ -1,6 +1,12 @@ -export type { AbstractTokenPricesService } from './abstract-token-prices-service'; +export type { + AbstractTokenPricesService, + NativeAssetIdentifiersMap, +} from './abstract-token-prices-service'; export { CodefiTokenPricesServiceV2, SUPPORTED_CHAIN_IDS, getNativeTokenAddress, + fetchSupportedNetworks, + getSupportedNetworks, + resetSupportedNetworksCache, } from './codefi-v2'; diff --git a/packages/assets-controllers/tsconfig.build.json b/packages/assets-controllers/tsconfig.build.json index 5ef0e52c3b8..cd6fefbce28 100644 --- a/packages/assets-controllers/tsconfig.build.json +++ b/packages/assets-controllers/tsconfig.build.json @@ -14,6 +14,7 @@ { "path": "../controller-utils/tsconfig.build.json" }, { "path": "../keyring-controller/tsconfig.build.json" }, { "path": "../network-controller/tsconfig.build.json" }, + { "path": "../network-enablement-controller/tsconfig.build.json" }, { "path": "../messenger/tsconfig.build.json" }, { "path": "../preferences-controller/tsconfig.build.json" }, { "path": "../polling-controller/tsconfig.build.json" }, diff --git a/packages/assets-controllers/tsconfig.json b/packages/assets-controllers/tsconfig.json index a537b98ca39..88b08f3986a 100644 --- a/packages/assets-controllers/tsconfig.json +++ b/packages/assets-controllers/tsconfig.json @@ -13,6 +13,7 @@ { "path": "../controller-utils" }, { "path": "../keyring-controller" }, { "path": "../network-controller" }, + { "path": "../network-enablement-controller" }, { "path": "../messenger" }, { "path": "../preferences-controller" }, { "path": "../phishing-controller" }, diff --git a/yarn.lock b/yarn.lock index d05973886ae..3a8cba0ba74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2704,6 +2704,7 @@ __metadata: "@metamask/metamask-eth-abis": "npm:^3.1.1" "@metamask/multichain-account-service": "npm:^5.1.0" "@metamask/network-controller": "npm:^29.0.0" + "@metamask/network-enablement-controller": "npm:^4.1.0" "@metamask/permission-controller": "npm:^12.2.0" "@metamask/phishing-controller": "npm:^16.1.0" "@metamask/polling-controller": "npm:^16.0.2"