Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions src/SwapsController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
27 changes: 19 additions & 8 deletions src/SwapsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1013,31 +1013,42 @@ 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.
* 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,
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;

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(),
Expand All @@ -1046,7 +1057,7 @@ export default class SwapsController extends BaseController<
_state.topAssets = data.topAssets;
_state.chainCache = getNewChainCache(
_state.chainCache,
chainId,
chainIdToUse,
data,
);
});
Expand All @@ -1055,7 +1066,7 @@ export default class SwapsController extends BaseController<
this.update((_state) => {
_state.chainCache = getNewChainCache(
_state.chainCache,
chainId,
chainIdToUse,
data,
);
});
Expand Down