From 598e8a83a5c31fb2b3c05ed410ffbb3ee1b78c2d Mon Sep 17 00:00:00 2001 From: IF <139582705+infiniteflower@users.noreply.github.com> Date: Mon, 31 Mar 2025 23:35:24 -0400 Subject: [PATCH 1/3] feat: allow using a chainId or networkClientId to fetch top assets --- src/SwapsController.test.ts | 61 +++++++++++++++++++++++++++++++++++++ src/SwapsController.ts | 24 ++++++++++----- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/SwapsController.test.ts b/src/SwapsController.test.ts index f6fd05f2..7fa6b916 100644 --- a/src/SwapsController.test.ts +++ b/src/SwapsController.test.ts @@ -2520,6 +2520,67 @@ describe('SwapsController', () => { expect(swapsUtilFetchTopAssets).not.toHaveBeenCalled(); }); }); + + describe('when the chain ID is provided', () => { + it('persists fetched top assets to the chain cache and the main part of state', async () => { + const clientId = 'client-id'; + const chainId = POLYGON_CHAIN_ID; + const fetchedTokens = [ + { + address: '0x1111111', + symbol: 'TOKEN1', + decimals: 1, + }, + { + address: '0x2222222', + symbol: 'TOKEN2', + decimals: 2, + }, + ]; + const controller = getSwapsController({ + options: { + clientId, + }, + }); + swapsUtilFetchTopAssets.mockImplementation( + async (givenChainId, givenClientId) => { + if (givenChainId === chainId && givenClientId === clientId) { + return fetchedTokens; + } + throw new Error( + `Unknown chain ID '${givenChainId}' and/or client ID '${givenClientId}'`, + ); + }, + ); + + await controller.fetchTopAssetsWithCache({ chainId }); + + expect(controller.state.topAssets).toStrictEqual(fetchedTokens); + expect(controller.state.chainCache).toStrictEqual({ + '0x1': { + aggregatorMetadata: null, + tokens: null, + topAssets: null, + aggregatorMetadataLastFetched: 0, + topAssetsLastFetched: 0, + tokensLastFetched: 0, + }, + [chainId]: { + topAssets: fetchedTokens, + topAssetsLastFetched: Date.now(), + }, + }); + }); + }); + + describe('when the chain ID is not provided and the network client ID is not provided', () => { + it('throws an error', async () => { + const controller = getSwapsController(); + await expect(controller.fetchTopAssetsWithCache({})).rejects.toThrow( + 'One of networkClientId or chainId is required', + ); + }); + }); }); describe('fetchAggregatorMetadataWithCache', () => { diff --git a/src/SwapsController.ts b/src/SwapsController.ts index d6782dad..805aab1c 100644 --- a/src/SwapsController.ts +++ b/src/SwapsController.ts @@ -1014,22 +1014,32 @@ export default class SwapsController extends BaseController< * @param args - The arguments to this method. * @param args.networkClientId - The ID of a network client from * NetworkController. + * @param args.chainId - The chain ID to fetch the top assets for. */ async fetchTopAssetsWithCache({ networkClientId, + chainId, }: { - networkClientId: NetworkClientId; + networkClientId?: NetworkClientId; + chainId?: Hex; }) { - const chainId = this.#getChainId(networkClientId); + let chainIdToUse; + if (chainId) { + chainIdToUse = chainId; + } else if (networkClientId) { + chainIdToUse = this.#getChainId(networkClientId); + } else { + throw new Error('One of networkClientId or chainId is required'); + } - if (!this.#supportedChainIds.includes(chainId)) { + if (!this.#supportedChainIds.includes(chainIdToUse)) { return; } const { topAssets } = this.state; const topAssetsLastFetchedForChain = - this.state.chainCache[chainId]?.topAssetsLastFetched ?? 0; + this.state.chainCache[chainIdToUse]?.topAssetsLastFetched ?? 0; const isPastThresholdForChain = this.#fetchTopAssetsThreshold < Date.now() - topAssetsLastFetchedForChain; @@ -1037,7 +1047,7 @@ export default class SwapsController extends BaseController< if (!topAssets || isPastThresholdForChain) { const releaseLock = await this.#mutex.acquire(); try { - const newTopAssets = await fetchTopAssets(chainId, this.#clientId); + const newTopAssets = await fetchTopAssets(chainIdToUse, this.#clientId); const data = { topAssets: newTopAssets, topAssetsLastFetched: Date.now(), @@ -1046,7 +1056,7 @@ export default class SwapsController extends BaseController< _state.topAssets = data.topAssets; _state.chainCache = getNewChainCache( _state.chainCache, - chainId, + chainIdToUse, data, ); }); @@ -1055,7 +1065,7 @@ export default class SwapsController extends BaseController< this.update((_state) => { _state.chainCache = getNewChainCache( _state.chainCache, - chainId, + chainIdToUse, data, ); }); From 1ec0fdca4a81cf7e2019bec6c77669fe2e5c2398 Mon Sep 17 00:00:00 2001 From: IF <139582705+infiniteflower@users.noreply.github.com> Date: Mon, 31 Mar 2025 23:41:17 -0400 Subject: [PATCH 2/3] chore: add comment --- src/SwapsController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SwapsController.ts b/src/SwapsController.ts index 805aab1c..e4b2a394 100644 --- a/src/SwapsController.ts +++ b/src/SwapsController.ts @@ -1014,7 +1014,7 @@ export default class SwapsController extends BaseController< * @param args - The arguments to this method. * @param args.networkClientId - The ID of a network client from * NetworkController. - * @param args.chainId - The chain ID to fetch the top assets for. + * @param args.chainId - The chain ID to fetch the top assets for. chainId will be preferred over networkClientId. */ async fetchTopAssetsWithCache({ networkClientId, From 4b74911b75ad0947bbe60776453b388413f6de59 Mon Sep 17 00:00:00 2001 From: IF <139582705+infiniteflower@users.noreply.github.com> Date: Mon, 31 Mar 2025 23:42:16 -0400 Subject: [PATCH 3/3] chore: add comment --- src/SwapsController.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SwapsController.ts b/src/SwapsController.ts index e4b2a394..366d5977 100644 --- a/src/SwapsController.ts +++ b/src/SwapsController.ts @@ -1013,8 +1013,9 @@ export default class SwapsController extends BaseController< * Fetches the top assets and updates the state with them. * @param args - The arguments to this method. * @param args.networkClientId - The ID of a network client from - * NetworkController. - * @param args.chainId - The chain ID to fetch the top assets for. chainId will be preferred over networkClientId. + * NetworkController. This or chainId is required. + * @param args.chainId - The chain ID to fetch the top assets for. This or + * networkClientId is required. chainId will be preferred over networkClientId. */ async fetchTopAssetsWithCache({ networkClientId,