diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 3267782a7a1..d36f8b79fc3 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -366,7 +366,7 @@ }, "packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts": { "@typescript-eslint/explicit-function-return-type": { - "count": 3 + "count": 2 } }, "packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts": { @@ -374,7 +374,7 @@ "count": 1 }, "no-negated-condition": { - "count": 2 + "count": 1 } }, "packages/assets-controllers/src/TokensController.test.ts": { diff --git a/packages/assets-controllers/CHANGELOG.md b/packages/assets-controllers/CHANGELOG.md index 096465d9b9c..997c4968ed1 100644 --- a/packages/assets-controllers/CHANGELOG.md +++ b/packages/assets-controllers/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Removed + +- **BREAKING:** Remove swaps token fetching functionality from TokenSearchDiscoveryDataController ([#7712](https://github.com/MetaMask/core/pull/7712)) + - Remove `swapsTokenAddressesByChainId` from controller state + - Remove `swapsSupportedChainIds`, `fetchTokens`, and `fetchSwapsTokensThresholdMs` constructor parameters + - Remove `fetchSwapsTokens` method + ## [96.0.0] ### Added diff --git a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts index f72c8be26a4..7c7e8fdf570 100644 --- a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts +++ b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.test.ts @@ -8,7 +8,6 @@ import type { } from '@metamask/messenger'; import type { Hex } from '@metamask/utils'; import assert from 'assert'; -import { useFakeTimers } from 'sinon'; import { getDefaultTokenSearchDiscoveryDataControllerState, @@ -21,7 +20,6 @@ import type { TokenSearchDiscoveryDataControllerState, } from './TokenSearchDiscoveryDataController'; import type { NotFoundTokenDisplayData, FoundTokenDisplayData } from './types'; -import { advanceTime } from '../../../../tests/helpers'; import type { AbstractTokenPricesService, EvmAssetWithMarketData, @@ -164,27 +162,12 @@ function buildMockTokenPricesService( }; } -/** - * Builds a mock fetchTokens function. - * - * @param tokenAddresses - The token addresses to return. - * @returns A function that returns the token addresses. - */ -function buildMockFetchTokens(tokenAddresses: string[] = []) { - return async (_chainId: Hex) => { - return tokenAddresses.map((address) => ({ address })); - }; -} - type WithControllerOptions = { options?: Partial< ConstructorParameters[0] >; mockCurrencyRateState?: { currentCurrency: string }; mockTokenPricesService?: Partial; - mockFetchTokens?: (chainId: Hex) => Promise<{ address: string }[]>; - mockSwapsSupportedChainIds?: Hex[]; - mockFetchSwapsTokensThresholdMs?: number; }; type WithControllerCallback = ({ @@ -244,19 +227,10 @@ async function withController( messenger: controllerMessenger, state: { tokenDisplayData: [], - swapsTokenAddressesByChainId: {}, }, tokenPricesService: buildMockTokenPricesService( options.mockTokenPricesService, ), - swapsSupportedChainIds: options.mockSwapsSupportedChainIds ?? [ - ChainId.mainnet, - ], - fetchTokens: - options.mockFetchTokens ?? - buildMockFetchTokens(['0x6B175474E89094C44Da98b954EedeAC495271d0F']), - fetchSwapsTokensThresholdMs: - options.mockFetchSwapsTokensThresholdMs ?? 86400000, ...options.options, }); @@ -285,7 +259,6 @@ describe('TokenSearchDiscoveryDataController', () => { await withController(async ({ controller }) => { expect(controller.state).toStrictEqual({ tokenDisplayData: [], - swapsTokenAddressesByChainId: {}, }); }); }); @@ -305,178 +278,9 @@ describe('TokenSearchDiscoveryDataController', () => { expect(controller.state.tokenDisplayData).toStrictEqual( initialState.tokenDisplayData, ); - expect(controller.state.swapsTokenAddressesByChainId).toStrictEqual( - {}, - ); - }, - ); - }); - }); - - describe('fetchSwapsTokens', () => { - let clock: sinon.SinonFakeTimers; - - beforeEach(() => { - clock = useFakeTimers({ now: Date.now() }); - }); - - afterEach(() => { - clock.restore(); - }); - - it('should not fetch tokens for unsupported chain IDs', async () => { - const mockFetchTokens = jest.fn().mockResolvedValue([]); - const unsupportedChainId = '0x5' as Hex; - - await withController( - { - mockFetchTokens, - mockSwapsSupportedChainIds: [ChainId.mainnet], - }, - async ({ controller }) => { - await controller.fetchSwapsTokens(unsupportedChainId); - - expect(mockFetchTokens).not.toHaveBeenCalled(); - expect( - controller.state.swapsTokenAddressesByChainId[unsupportedChainId], - ).toBeUndefined(); - }, - ); - }); - - it('should fetch tokens for supported chain IDs', async () => { - const mockTokens = [{ address: '0xToken1' }, { address: '0xToken2' }]; - const mockFetchTokens = jest.fn().mockResolvedValue(mockTokens); - - await withController( - { - mockFetchTokens, - mockSwapsSupportedChainIds: [ChainId.mainnet], - }, - async ({ controller }) => { - await controller.fetchSwapsTokens(ChainId.mainnet); - - expect(mockFetchTokens).toHaveBeenCalledWith(ChainId.mainnet); - expect( - controller.state.swapsTokenAddressesByChainId[ChainId.mainnet], - ).toBeDefined(); - expect( - controller.state.swapsTokenAddressesByChainId[ChainId.mainnet] - .addresses, - ).toStrictEqual(['0xToken1', '0xToken2']); - expect( - controller.state.swapsTokenAddressesByChainId[ChainId.mainnet] - .isFetching, - ).toBe(false); - }, - ); - }); - - it('should not fetch tokens again if threshold has not passed', async () => { - const mockTokens = [{ address: '0xToken1' }]; - const mockFetchTokens = jest.fn().mockResolvedValue(mockTokens); - const fetchThreshold = 10000; - - await withController( - { - mockFetchTokens, - mockSwapsSupportedChainIds: [ChainId.mainnet], - mockFetchSwapsTokensThresholdMs: fetchThreshold, - }, - async ({ controller }) => { - await controller.fetchSwapsTokens(ChainId.mainnet); - expect(mockFetchTokens).toHaveBeenCalledTimes(1); - - mockFetchTokens.mockClear(); - - await controller.fetchSwapsTokens(ChainId.mainnet); - expect(mockFetchTokens).not.toHaveBeenCalled(); - - await advanceTime({ clock, duration: fetchThreshold + 1000 }); - - await controller.fetchSwapsTokens(ChainId.mainnet); - expect(mockFetchTokens).toHaveBeenCalledTimes(1); - }, - ); - }); - - it('should set isFetching flag while fetching', async () => { - let resolveTokens: (tokens: { address: string }[]) => void; - const fetchTokensPromise = new Promise<{ address: string }[]>( - (resolve) => { - resolveTokens = resolve; - }, - ); - const mockFetchTokens = jest.fn().mockReturnValue(fetchTokensPromise); - - await withController( - { - mockFetchTokens, - mockSwapsSupportedChainIds: [ChainId.mainnet], - }, - async ({ controller }) => { - const fetchPromise = controller.fetchSwapsTokens(ChainId.mainnet); - - expect( - controller.state.swapsTokenAddressesByChainId[ChainId.mainnet] - .isFetching, - ).toBe(true); - - resolveTokens([{ address: '0xToken1' }]); - - await fetchPromise; - - expect( - controller.state.swapsTokenAddressesByChainId[ChainId.mainnet] - .isFetching, - ).toBe(false); }, ); }); - - it('should refresh tokens after threshold time has elapsed', async () => { - const chainId = ChainId.mainnet; - const initialAddresses = ['0x123', '0x456']; - const newAddresses = ['0x123', '0x456', '0x789']; - const fetchTokensMock = jest - .fn() - .mockResolvedValueOnce(initialAddresses.map((address) => ({ address }))) - .mockResolvedValueOnce(newAddresses.map((address) => ({ address }))); - - const testClock = useFakeTimers(); - const initialTime = Date.now(); - - try { - testClock.setSystemTime(initialTime); - - await withController( - { - mockFetchTokens: fetchTokensMock, - mockFetchSwapsTokensThresholdMs: 1000, - }, - async ({ controller }) => { - await controller.fetchSwapsTokens(chainId); - expect( - controller.state.swapsTokenAddressesByChainId[chainId].addresses, - ).toStrictEqual(initialAddresses); - - await controller.fetchSwapsTokens(chainId); - expect(fetchTokensMock).toHaveBeenCalledTimes(1); - - const fetchThreshold = 86400000; - testClock.tick(fetchThreshold + 1000); - - await controller.fetchSwapsTokens(chainId); - expect(fetchTokensMock).toHaveBeenCalledTimes(2); - expect( - controller.state.swapsTokenAddressesByChainId[chainId].addresses, - ).toStrictEqual(newAddresses); - }, - ); - } finally { - testClock.restore(); - } - }); }); describe('fetchTokenDisplayData', () => { @@ -611,19 +415,6 @@ describe('TokenSearchDiscoveryDataController', () => { ); }); - it('should call fetchSwapsTokens before fetching token display data', async () => { - const tokenAddress = '0x0000000000000000000000000000000000000010'; - const tokenChainId = ChainId.mainnet; - - await withController(async ({ controller }) => { - const fetchSwapsTokensSpy = jest.spyOn(controller, 'fetchSwapsTokens'); - - await controller.fetchTokenDisplayData(tokenChainId, tokenAddress); - - expect(fetchSwapsTokensSpy).toHaveBeenCalledWith(tokenChainId); - }); - }); - it('should handle currency changes correctly', async () => { const tokenAddress = '0x0000000000000000000000000000000000000010'; const tokenChainId = ChainId.mainnet; @@ -907,7 +698,6 @@ describe('TokenSearchDiscoveryDataController', () => { expect(defaultState).toStrictEqual({ tokenDisplayData: [], - swapsTokenAddressesByChainId: {}, }); }); }); @@ -947,7 +737,6 @@ describe('TokenSearchDiscoveryDataController', () => { ), ).toMatchInlineSnapshot(` Object { - "swapsTokenAddressesByChainId": Object {}, "tokenDisplayData": Array [], } `); @@ -964,7 +753,6 @@ describe('TokenSearchDiscoveryDataController', () => { ), ).toMatchInlineSnapshot(` Object { - "swapsTokenAddressesByChainId": Object {}, "tokenDisplayData": Array [], } `); diff --git a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts index b62ac16f47a..3398e2248bc 100644 --- a/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts +++ b/packages/assets-controllers/src/TokenSearchDiscoveryDataController/TokenSearchDiscoveryDataController.ts @@ -27,10 +27,6 @@ export const MAX_TOKEN_DISPLAY_DATA_LENGTH = 10; export type TokenSearchDiscoveryDataControllerState = { tokenDisplayData: TokenDisplayData[]; - swapsTokenAddressesByChainId: Record< - Hex, - { lastFetched: number; addresses: string[]; isFetching: boolean } - >; }; const tokenSearchDiscoveryDataControllerMetadata: StateMetadata = @@ -41,12 +37,6 @@ const tokenSearchDiscoveryDataControllerMetadata: StateMetadata Promise<{ address: string }[]>; - - readonly #fetchSwapsTokensThresholdMs: number; - constructor({ state = {}, messenger, tokenPricesService, - swapsSupportedChainIds, - fetchTokens, - fetchSwapsTokensThresholdMs, }: { state?: Partial; messenger: TokenSearchDiscoveryDataControllerMessenger; tokenPricesService: AbstractTokenPricesService; - swapsSupportedChainIds: Hex[]; - fetchTokens: (chainId: Hex) => Promise<{ address: string }[]>; - fetchSwapsTokensThresholdMs: number; }) { super({ name: controllerName, @@ -166,9 +143,6 @@ export class TokenSearchDiscoveryDataController extends BaseController< this.#abortController = new AbortController(); this.#tokenPricesService = tokenPricesService; - this.#swapsSupportedChainIds = swapsSupportedChainIds; - this.#fetchTokens = fetchTokens; - this.#fetchSwapsTokensThresholdMs = fetchSwapsTokensThresholdMs; } async #fetchPriceData(chainId: Hex, address: string) { @@ -189,47 +163,7 @@ export class TokenSearchDiscoveryDataController extends BaseController< } } - async fetchSwapsTokens(chainId: Hex): Promise { - if (!this.#swapsSupportedChainIds.includes(chainId)) { - return; - } - - const swapsTokens = this.state.swapsTokenAddressesByChainId[chainId]; - if ( - (!swapsTokens || - swapsTokens.lastFetched < - Date.now() - this.#fetchSwapsTokensThresholdMs) && - !swapsTokens?.isFetching - ) { - try { - this.update((state) => { - if (!state.swapsTokenAddressesByChainId[chainId]) { - state.swapsTokenAddressesByChainId[chainId] = { - lastFetched: Date.now(), - addresses: [], - isFetching: true, - }; - } else { - state.swapsTokenAddressesByChainId[chainId].isFetching = true; - } - }); - const tokens = await this.#fetchTokens(chainId); - this.update((state) => { - state.swapsTokenAddressesByChainId[chainId] = { - lastFetched: Date.now(), - addresses: tokens.map((token) => token.address), - isFetching: false, - }; - }); - } catch (error) { - console.error(error); - } - } - } - async fetchTokenDisplayData(chainId: Hex, address: string): Promise { - await this.fetchSwapsTokens(chainId); - let tokenMetadata: TokenListToken | undefined; try { tokenMetadata = await fetchTokenMetadata(