From 36f0e63ac5e22f161b88f8f6f35ca0d74a449e9d Mon Sep 17 00:00:00 2001 From: Kriys94 Date: Tue, 8 Sep 2026 16:14:48 +0200 Subject: [PATCH] fix(assets-controller): add partialSupport from AccountsAPI --- packages/assets-controller/CHANGELOG.md | 2 + .../AccountsApiDataSource.test.ts | 51 +++++++++++++++++-- .../src/data-sources/AccountsApiDataSource.ts | 46 ++++++++++++++--- packages/core-backend/CHANGELOG.md | 1 + .../src/api/accounts/client.test.ts | 9 +++- .../core-backend/src/api/accounts/client.ts | 1 + .../core-backend/src/api/accounts/types.ts | 8 ++- 7 files changed, 100 insertions(+), 18 deletions(-) diff --git a/packages/assets-controller/CHANGELOG.md b/packages/assets-controller/CHANGELOG.md index ca2c281a44b..3f2eff4d8e9 100644 --- a/packages/assets-controller/CHANGELOG.md +++ b/packages/assets-controller/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bump `@metamask/account-tree-controller` from `^10.0.0` to `^10.0.1` ([#10166](https://github.com/MetaMask/core/pull/10166)) - Bump `@metamask/assets-controllers` from `^112.0.0` to `^112.0.1` ([#10166](https://github.com/MetaMask/core/pull/10166)) - Bump `@metamask/core-backend` from `^10.0.0` to `^10.0.1` ([#10166](https://github.com/MetaMask/core/pull/10166)) +- `AccountsApiDataSource` now treats Accounts API `/v2/supportedNetworks` `partialSupport` as active chains in addition to `fullSupport`, still gated by the Snaps assets migration feature flags ([#10144](https://github.com/MetaMask/core/pull/10144)) +- `AccountsApiDataSource` now reads Accounts API `/v2/supportedNetworks` as CAIP-2 `fullSupport` and `partialSupport` string arrays, matching the current API payload ## [16.0.0] diff --git a/packages/assets-controller/src/data-sources/AccountsApiDataSource.test.ts b/packages/assets-controller/src/data-sources/AccountsApiDataSource.test.ts index 382439a702d..0ade66456c8 100644 --- a/packages/assets-controller/src/data-sources/AccountsApiDataSource.test.ts +++ b/packages/assets-controller/src/data-sources/AccountsApiDataSource.test.ts @@ -63,16 +63,17 @@ function createMockAccount( } function createMockApiClient( - supportedChains: number[] = [1, 137], + supportedChains: (number | string)[] = [1, 137], balances: V5BalanceItem[] = [], unprocessedNetworks: string[] = [], v6Balances: V6BalanceItem[] = [], + partialSupport: (number | string)[] = [], ): MockApiClient { return { accounts: { fetchV2SupportedNetworks: jest.fn().mockResolvedValue({ fullSupport: supportedChains, - partialSupport: [], + partialSupport, }), fetchV5MultiAccountBalances: jest.fn().mockResolvedValue({ balances, @@ -141,7 +142,8 @@ type SetupResult = { async function setupController( options: { - supportedChains?: number[]; + supportedChains?: (number | string)[]; + partialSupport?: (number | string)[]; balances?: V5BalanceItem[]; unprocessedNetworks?: string[]; fetchTimeoutMs?: number; @@ -151,6 +153,7 @@ async function setupController( ): Promise { const { supportedChains = [1, 137], + partialSupport = [], balances = [], unprocessedNetworks = [], fetchTimeoutMs, @@ -196,6 +199,7 @@ async function setupController( balances, unprocessedNetworks, v6Balances, + partialSupport, ); const controller = new AccountsApiDataSource({ @@ -279,7 +283,7 @@ describe('AccountsApiDataSource', () => { activeChainsUpdateHandler.mockClear(); apiClient.accounts.fetchV2SupportedNetworks.mockClear(); apiClient.accounts.fetchV2SupportedNetworks.mockResolvedValue({ - fullSupport: [1, 137], + fullSupport: ['eip155:1', 'eip155:137'], partialSupport: [], }); @@ -478,6 +482,45 @@ describe('AccountsApiDataSource', () => { controller.destroy(); }); + it('treats v2 CAIP-2 fullSupport and partialSupport arrays as active chains', async () => { + const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'; + const SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1'; + const TRON_MAINNET = 'tron:728126428'; + const STELLAR_PUBNET = 'stellar:pubnet'; + const { controller } = await setupController({ + supportedChains: ['eip155:1', 'eip155:137', 'eip155:59144'], + partialSupport: [ + TRON_MAINNET, + SOLANA_MAINNET, + SOLANA_DEVNET, + STELLAR_PUBNET, + ], + remoteFeatureFlags: { + [SNAPS_ASSETS_MIGRATION_FLAG_KEYS.solana]: { + stage: SnapsAssetsMigrationStage.ReadAssetsControllerWithFallback, + }, + [SNAPS_ASSETS_MIGRATION_FLAG_KEYS.tron]: { + stage: SnapsAssetsMigrationStage.ReadAssetsControllerWithFallback, + }, + [SNAPS_ASSETS_MIGRATION_FLAG_KEYS.stellar]: { + stage: SnapsAssetsMigrationStage.ReadAssetsControllerWithFallback, + }, + }, + }); + + expect(await controller.getActiveChains()).toStrictEqual([ + CHAIN_MAINNET, + CHAIN_POLYGON, + 'eip155:59144', + TRON_MAINNET, + SOLANA_MAINNET, + SOLANA_DEVNET, + STELLAR_PUBNET, + ]); + + controller.destroy(); + }); + it.each([ { input: 1, expected: 'eip155:1' }, { input: '137', expected: 'eip155:137' }, diff --git a/packages/assets-controller/src/data-sources/AccountsApiDataSource.ts b/packages/assets-controller/src/data-sources/AccountsApiDataSource.ts index 31e55cdfa72..4779f8928a7 100644 --- a/packages/assets-controller/src/data-sources/AccountsApiDataSource.ts +++ b/packages/assets-controller/src/data-sources/AccountsApiDataSource.ts @@ -124,6 +124,38 @@ function decimalToChainId(decimalChainId: number | string): ChainId { return toCaipChainId(KnownCaipNamespace.Eip155, String(decimalChainId)); } +/** + * Collect chain ids from Accounts API `/v2/supportedNetworks`. + * + * `fullSupport` and `partialSupport` are CAIP-2 arrays. The older + * `{ balances: number[] }` `partialSupport` object is still read so mixed + * deploys keep working until every environment has rolled forward. + * + * @param response - The v2 supported-networks payload. + * @param response.fullSupport - Fully supported chain ids (CAIP-2 or decimals). + * @param response.partialSupport - Partially supported chain ids, as a CAIP-2 + * array or legacy `{ balances }` object. + * @returns Unique normalized chain ids, `fullSupport` first then `partialSupport`. + */ +function collectSupportedNetworkIds(response: { + fullSupport?: (number | string)[]; + partialSupport?: (number | string)[] | { balances?: (number | string)[] }; +}): ChainId[] { + const fullSupport = response.fullSupport ?? []; + const { partialSupport } = response; + const partialIds = Array.isArray(partialSupport) + ? partialSupport + : (partialSupport?.balances ?? []); + + return [ + ...new Set( + [...fullSupport, ...partialIds].map((rawChainId) => + decimalToChainId(rawChainId), + ), + ), + ]; +} + /** * Convert a CAIP-2 chain ID from the API response to our ChainId type. * Handles both formats: "eip155:1" or just "1" (decimal). @@ -367,17 +399,17 @@ export class AccountsApiDataSource extends AbstractDataSource< async #fetchActiveChains(): Promise { const response = await this.#apiClient.accounts.fetchV2SupportedNetworks(); - // Use fullSupport networks as active chains, gated by the Snaps → - // AssetsController migration FF: non-migration namespaces (e.g. `eip155`) - // are always surfaced, while migration networks (Solana, Stellar, Tron) are - // only surfaced once their per-network stage reaches + // Use fullSupport and partialSupport as active chains, gated by the + // Snaps → AssetsController migration FF: non-migration namespaces + // (e.g. `eip155`) are always surfaced, while migration networks (Solana, + // Stellar, Tron) are only surfaced once their per-network stage reaches // ReadAssetsControllerWithFallback. const { remoteFeatureFlags } = this.#messenger.call( 'RemoteFeatureFlagController:getState', ); - return response.fullSupport - .map(decimalToChainId) - .filter((chainId) => shouldSupportChain(chainId, remoteFeatureFlags)); + return collectSupportedNetworkIds(response).filter((chainId) => + shouldSupportChain(chainId, remoteFeatureFlags), + ); } // ============================================================================ diff --git a/packages/core-backend/CHANGELOG.md b/packages/core-backend/CHANGELOG.md index 07f38169eb7..607833768cd 100644 --- a/packages/core-backend/CHANGELOG.md +++ b/packages/core-backend/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **BREAKING:** Accounts API `V2SupportedNetworksResponse` now uses CAIP-2 string arrays for both `fullSupport` and `partialSupport`, replacing decimal `fullSupport` and object-shaped `partialSupport.balances` ([#10144](https://github.com/MetaMask/core/pull/10144)) - Bump `@metamask/profile-sync-controller` from `^32.0.0` to `^32.1.0` ([#10184](https://github.com/MetaMask/core/pull/10184)) ## [10.0.1] diff --git a/packages/core-backend/src/api/accounts/client.test.ts b/packages/core-backend/src/api/accounts/client.test.ts index 3963817a7a4..b9b3e80d9cd 100644 --- a/packages/core-backend/src/api/accounts/client.test.ts +++ b/packages/core-backend/src/api/accounts/client.test.ts @@ -42,8 +42,13 @@ describe('AccountsApiClient', () => { it('fetches v2 supported networks', async () => { const mockResponse: V2SupportedNetworksResponse = { - fullSupport: [1, 137], - partialSupport: { balances: [56] }, + fullSupport: ['eip155:1', 'eip155:137', 'eip155:59144'], + partialSupport: [ + 'tron:728126428', + 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', + 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', + 'stellar:pubnet', + ], }; mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)); diff --git a/packages/core-backend/src/api/accounts/client.ts b/packages/core-backend/src/api/accounts/client.ts index 549e6524583..4b5468abbd1 100644 --- a/packages/core-backend/src/api/accounts/client.ts +++ b/packages/core-backend/src/api/accounts/client.ts @@ -146,6 +146,7 @@ export class AccountsApiClient extends BaseApiClient { /** * Get list of supported networks (v2 endpoint). + * Returns CAIP-2 chain IDs in both `fullSupport` and `partialSupport`. * * @param options - Fetch options including cache settings. * @returns The list of supported networks. diff --git a/packages/core-backend/src/api/accounts/types.ts b/packages/core-backend/src/api/accounts/types.ts index bf789a277d6..e26e343f502 100644 --- a/packages/core-backend/src/api/accounts/types.ts +++ b/packages/core-backend/src/api/accounts/types.ts @@ -171,12 +171,10 @@ export type V1SupportedNetworksResponse = { supportedNetworks: number[]; }; -/** V2 Supported networks response */ +/** V2 Supported networks response (CAIP-2 chain IDs). */ export type V2SupportedNetworksResponse = { - fullSupport: number[]; - partialSupport: { - balances: number[]; - }; + fullSupport: string[]; + partialSupport: string[]; }; /** Active networks response */