Skip to content
This repository was archived by the owner on Mar 20, 2026. It is now read-only.
/ swaps-controller Public archive

Commit eb253bd

Browse files
feat: allow using a chainId or networkClientId to fetch top assets (#403)
## Explanation <!-- Thanks for your contribution! Take a moment to answer these questions so that reviewers have the information they need to properly understand your changes: * What is the current state of things and why does it need to change? * What is the solution your changes offer and how does it work? * Are there any changes whose purpose might not obvious to those unfamiliar with the domain? * If your primary goal was to update one package but you found you had to update another one along the way, why did you do so? * If you had to upgrade a dependency, why did you do so? --> This PR allows passing in either a `chainId` or a `networkClientId` to `fetchTopAssets`. Previously only `networkClientId` was allowed. This is to support the case of Bridge where a user could select a destination chain that they have not added to MM yet, there by not having a `networkClientId` to provide. The user will have a destination `chainId` that we want to look up top assets on. ## References <!-- Are there any issues that this pull request is tied to? Are there other links that reviewers should consult to understand these changes better? Are there client or consumer pull requests to adopt any breaking changes? For example: * Fixes #12345 * Related to #67890 --> Related to MetaMask/metamask-mobile#14258 ## Changelog <!-- If you're making any consumer-facing changes, list those changes here as if you were updating a changelog, using the template below as a guide. (CATEGORY is one of BREAKING, ADDED, CHANGED, DEPRECATED, REMOVED, or FIXED. For security-related issues, follow the Security Advisory process.) Please take care to name the exact pieces of the API you've added or changed (e.g. types, interfaces, functions, or methods). If there are any breaking changes, make sure to offer a solution for consumers to follow once they upgrade to the changes. Finally, if you're only making changes to development scripts or tests, you may replace the template below with "None". --> ### `@metamask/swaps-controller` - CHANGED: Allow passing in either a `chainId` or a `networkClientId` to `fetchTopAssets`. Previously only `networkClientId` was allowed. ## Checklist - [x] I've updated the test suite for new or updated code as appropriate - [x] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [x] I've highlighted breaking changes using the "BREAKING" category above as appropriate - [x] I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes
1 parent 41df7ae commit eb253bd

File tree

2 files changed

+80
-8
lines changed

2 files changed

+80
-8
lines changed

src/SwapsController.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2520,6 +2520,67 @@ describe('SwapsController', () => {
25202520
expect(swapsUtilFetchTopAssets).not.toHaveBeenCalled();
25212521
});
25222522
});
2523+
2524+
describe('when the chain ID is provided', () => {
2525+
it('persists fetched top assets to the chain cache and the main part of state', async () => {
2526+
const clientId = 'client-id';
2527+
const chainId = POLYGON_CHAIN_ID;
2528+
const fetchedTokens = [
2529+
{
2530+
address: '0x1111111',
2531+
symbol: 'TOKEN1',
2532+
decimals: 1,
2533+
},
2534+
{
2535+
address: '0x2222222',
2536+
symbol: 'TOKEN2',
2537+
decimals: 2,
2538+
},
2539+
];
2540+
const controller = getSwapsController({
2541+
options: {
2542+
clientId,
2543+
},
2544+
});
2545+
swapsUtilFetchTopAssets.mockImplementation(
2546+
async (givenChainId, givenClientId) => {
2547+
if (givenChainId === chainId && givenClientId === clientId) {
2548+
return fetchedTokens;
2549+
}
2550+
throw new Error(
2551+
`Unknown chain ID '${givenChainId}' and/or client ID '${givenClientId}'`,
2552+
);
2553+
},
2554+
);
2555+
2556+
await controller.fetchTopAssetsWithCache({ chainId });
2557+
2558+
expect(controller.state.topAssets).toStrictEqual(fetchedTokens);
2559+
expect(controller.state.chainCache).toStrictEqual({
2560+
'0x1': {
2561+
aggregatorMetadata: null,
2562+
tokens: null,
2563+
topAssets: null,
2564+
aggregatorMetadataLastFetched: 0,
2565+
topAssetsLastFetched: 0,
2566+
tokensLastFetched: 0,
2567+
},
2568+
[chainId]: {
2569+
topAssets: fetchedTokens,
2570+
topAssetsLastFetched: Date.now(),
2571+
},
2572+
});
2573+
});
2574+
});
2575+
2576+
describe('when the chain ID is not provided and the network client ID is not provided', () => {
2577+
it('throws an error', async () => {
2578+
const controller = getSwapsController();
2579+
await expect(controller.fetchTopAssetsWithCache({})).rejects.toThrow(
2580+
'One of networkClientId or chainId is required',
2581+
);
2582+
});
2583+
});
25232584
});
25242585

25252586
describe('fetchAggregatorMetadataWithCache', () => {

src/SwapsController.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,31 +1013,42 @@ export default class SwapsController extends BaseController<
10131013
* Fetches the top assets and updates the state with them.
10141014
* @param args - The arguments to this method.
10151015
* @param args.networkClientId - The ID of a network client from
1016-
* NetworkController.
1016+
* NetworkController. This or chainId is required.
1017+
* @param args.chainId - The chain ID to fetch the top assets for. This or
1018+
* networkClientId is required. chainId will be preferred over networkClientId.
10171019
*/
10181020
async fetchTopAssetsWithCache({
10191021
networkClientId,
1022+
chainId,
10201023
}: {
1021-
networkClientId: NetworkClientId;
1024+
networkClientId?: NetworkClientId;
1025+
chainId?: Hex;
10221026
}) {
1023-
const chainId = this.#getChainId(networkClientId);
1027+
let chainIdToUse;
1028+
if (chainId) {
1029+
chainIdToUse = chainId;
1030+
} else if (networkClientId) {
1031+
chainIdToUse = this.#getChainId(networkClientId);
1032+
} else {
1033+
throw new Error('One of networkClientId or chainId is required');
1034+
}
10241035

1025-
if (!this.#supportedChainIds.includes(chainId)) {
1036+
if (!this.#supportedChainIds.includes(chainIdToUse)) {
10261037
return;
10271038
}
10281039

10291040
const { topAssets } = this.state;
10301041

10311042
const topAssetsLastFetchedForChain =
1032-
this.state.chainCache[chainId]?.topAssetsLastFetched ?? 0;
1043+
this.state.chainCache[chainIdToUse]?.topAssetsLastFetched ?? 0;
10331044

10341045
const isPastThresholdForChain =
10351046
this.#fetchTopAssetsThreshold < Date.now() - topAssetsLastFetchedForChain;
10361047

10371048
if (!topAssets || isPastThresholdForChain) {
10381049
const releaseLock = await this.#mutex.acquire();
10391050
try {
1040-
const newTopAssets = await fetchTopAssets(chainId, this.#clientId);
1051+
const newTopAssets = await fetchTopAssets(chainIdToUse, this.#clientId);
10411052
const data = {
10421053
topAssets: newTopAssets,
10431054
topAssetsLastFetched: Date.now(),
@@ -1046,7 +1057,7 @@ export default class SwapsController extends BaseController<
10461057
_state.topAssets = data.topAssets;
10471058
_state.chainCache = getNewChainCache(
10481059
_state.chainCache,
1049-
chainId,
1060+
chainIdToUse,
10501061
data,
10511062
);
10521063
});
@@ -1055,7 +1066,7 @@ export default class SwapsController extends BaseController<
10551066
this.update((_state) => {
10561067
_state.chainCache = getNewChainCache(
10571068
_state.chainCache,
1058-
chainId,
1069+
chainIdToUse,
10591070
data,
10601071
);
10611072
});

0 commit comments

Comments
 (0)