Skip to content

Commit d4030cf

Browse files
authored
[Token Detection V2] 1 of 7 - Throw on failure for fetchTokenMetadata in token service (#812)
* Add type to fetchTokenMetadata and throw on failure. * Define fetch token metadata error with const
1 parent 2819895 commit d4030cf

File tree

2 files changed

+57
-39
lines changed

2 files changed

+57
-39
lines changed

src/apis/token-service.test.ts

+51-35
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import nock from 'nock';
22
import { NetworksChainId } from '../network/NetworkController';
3-
import { fetchTokenList, fetchTokenMetadata } from './token-service';
3+
import {
4+
fetchTokenList,
5+
fetchTokenMetadata,
6+
FETCH_TOKEN_METADATA_ERROR,
7+
} from './token-service';
48

59
const TOKEN_END_POINT_API = 'https://token-api.metaswap.codefi.network';
610

@@ -233,7 +237,7 @@ describe('Token service', () => {
233237
expect(token).toStrictEqual(sampleToken);
234238
});
235239

236-
it('should return undefined if the fetch is aborted', async () => {
240+
it('should throw error if the fetch is aborted', async () => {
237241
const abortController = new AbortController();
238242
nock(TOKEN_END_POINT_API)
239243
.get(`/tokens/${NetworksChainId.mainnet}`)
@@ -242,49 +246,49 @@ describe('Token service', () => {
242246
.reply(200, sampleTokenList)
243247
.persist();
244248

245-
const fetchPromise = fetchTokenMetadata(
246-
NetworksChainId.mainnet,
247-
'0x514910771af9ca656af840dff83e8264ecf986ca',
248-
abortController.signal,
249-
);
250-
abortController.abort();
251-
252-
expect(await fetchPromise).toBeUndefined();
249+
await expect(async () => {
250+
await fetchTokenMetadata(
251+
NetworksChainId.mainnet,
252+
'0x514910771af9ca656af840dff83e8264ecf986ca',
253+
abortController.signal,
254+
);
255+
abortController.abort();
256+
}).rejects.toThrow(FETCH_TOKEN_METADATA_ERROR);
253257
});
254258

255-
it('should return undefined if the fetch fails with a network error', async () => {
259+
it('should throw error if the fetch fails with a network error', async () => {
256260
const { signal } = new AbortController();
257261
nock(TOKEN_END_POINT_API)
258262
.get(`/tokens/${NetworksChainId.mainnet}`)
259263
.replyWithError('Example network error')
260264
.persist();
261265

262-
const result = await fetchTokenMetadata(
263-
NetworksChainId.mainnet,
264-
'0x514910771af9ca656af840dff83e8264ecf986ca',
265-
signal,
266-
);
267-
268-
expect(result).toBeUndefined();
266+
await expect(async () => {
267+
await fetchTokenMetadata(
268+
NetworksChainId.mainnet,
269+
'0x514910771af9ca656af840dff83e8264ecf986ca',
270+
signal,
271+
);
272+
}).rejects.toThrow(FETCH_TOKEN_METADATA_ERROR);
269273
});
270274

271-
it('should return undefined if the fetch fails with an unsuccessful status code', async () => {
275+
it('should throw error if the fetch fails with an unsuccessful status code', async () => {
272276
const { signal } = new AbortController();
273277
nock(TOKEN_END_POINT_API)
274278
.get(`/tokens/${NetworksChainId.mainnet}`)
275279
.reply(500)
276280
.persist();
277281

278-
const result = await fetchTokenMetadata(
279-
NetworksChainId.mainnet,
280-
'0x514910771af9ca656af840dff83e8264ecf986ca',
281-
signal,
282-
);
283-
284-
expect(result).toBeUndefined();
282+
await expect(async () => {
283+
await fetchTokenMetadata(
284+
NetworksChainId.mainnet,
285+
'0x514910771af9ca656af840dff83e8264ecf986ca',
286+
signal,
287+
);
288+
}).rejects.toThrow(FETCH_TOKEN_METADATA_ERROR);
285289
});
286290

287-
it('should return undefined if the fetch fails with a timeout', async () => {
291+
it('should throw error if the fetch fails with a timeout', async () => {
288292
const { signal } = new AbortController();
289293
nock(TOKEN_END_POINT_API)
290294
.get(`/tokens/${NetworksChainId.mainnet}`)
@@ -293,14 +297,26 @@ describe('Token service', () => {
293297
.reply(200, sampleTokenList)
294298
.persist();
295299

296-
const result = await fetchTokenMetadata(
297-
NetworksChainId.mainnet,
298-
'0x514910771af9ca656af840dff83e8264ecf986ca',
299-
signal,
300-
{ timeout: ONE_MILLISECOND },
301-
);
302-
303-
expect(result).toBeUndefined();
300+
await expect(async () => {
301+
await fetchTokenMetadata(
302+
NetworksChainId.mainnet,
303+
'0x514910771af9ca656af840dff83e8264ecf986ca',
304+
signal,
305+
{ timeout: ONE_MILLISECOND },
306+
);
307+
}).rejects.toThrow(FETCH_TOKEN_METADATA_ERROR);
304308
});
305309
});
310+
311+
it('should call the tokens api and return undefined', async () => {
312+
const { signal } = new AbortController();
313+
nock(TOKEN_END_POINT_API)
314+
.get(`/tokens/${NetworksChainId.mainnet}`)
315+
.reply(404, undefined)
316+
.persist();
317+
318+
const tokens = await fetchTokenList(NetworksChainId.mainnet, signal);
319+
320+
expect(tokens).toBeUndefined();
321+
});
306322
});

src/apis/token-service.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { timeoutFetch } from '../util';
22

33
const END_POINT = 'https://token-api.metaswap.codefi.network';
4+
export const FETCH_TOKEN_METADATA_ERROR =
5+
'TokenService Error: No response from fetchTokenMetadata';
46

57
/**
68
* Get the tokens URL for a specific network.
@@ -63,18 +65,18 @@ export async function fetchTokenList(
6365
* @param options.timeout - The fetch timeout.
6466
* @returns The token metadata, or `undefined` if the request was cancelled.
6567
*/
66-
export async function fetchTokenMetadata(
68+
export async function fetchTokenMetadata<T>(
6769
chainId: string,
6870
tokenAddress: string,
6971
abortSignal: AbortSignal,
7072
{ timeout = defaultTimeout } = {},
71-
): Promise<unknown> {
73+
): Promise<T> {
7274
const tokenMetadataURL = getTokenMetadataURL(chainId, tokenAddress);
7375
const response = await queryApi(tokenMetadataURL, abortSignal, timeout);
7476
if (response) {
75-
return parseJsonResponse(response);
77+
return parseJsonResponse(response) as Promise<T>;
7678
}
77-
return undefined;
79+
throw new Error(FETCH_TOKEN_METADATA_ERROR);
7880
}
7981

8082
/**

0 commit comments

Comments
 (0)