Skip to content

Commit

Permalink
[Token Detection V2] 1 of 7 - Throw on failure for fetchTokenMetadata…
Browse files Browse the repository at this point in the history
… in token service (#812)

* Add type to fetchTokenMetadata and throw on failure.

* Define fetch token metadata error with const
  • Loading branch information
Cal-L authored May 5, 2022
1 parent 2819895 commit d4030cf
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 39 deletions.
86 changes: 51 additions & 35 deletions src/apis/token-service.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import nock from 'nock';
import { NetworksChainId } from '../network/NetworkController';
import { fetchTokenList, fetchTokenMetadata } from './token-service';
import {
fetchTokenList,
fetchTokenMetadata,
FETCH_TOKEN_METADATA_ERROR,
} from './token-service';

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

Expand Down Expand Up @@ -233,7 +237,7 @@ describe('Token service', () => {
expect(token).toStrictEqual(sampleToken);
});

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

const fetchPromise = fetchTokenMetadata(
NetworksChainId.mainnet,
'0x514910771af9ca656af840dff83e8264ecf986ca',
abortController.signal,
);
abortController.abort();

expect(await fetchPromise).toBeUndefined();
await expect(async () => {
await fetchTokenMetadata(
NetworksChainId.mainnet,
'0x514910771af9ca656af840dff83e8264ecf986ca',
abortController.signal,
);
abortController.abort();
}).rejects.toThrow(FETCH_TOKEN_METADATA_ERROR);
});

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

const result = await fetchTokenMetadata(
NetworksChainId.mainnet,
'0x514910771af9ca656af840dff83e8264ecf986ca',
signal,
);

expect(result).toBeUndefined();
await expect(async () => {
await fetchTokenMetadata(
NetworksChainId.mainnet,
'0x514910771af9ca656af840dff83e8264ecf986ca',
signal,
);
}).rejects.toThrow(FETCH_TOKEN_METADATA_ERROR);
});

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

const result = await fetchTokenMetadata(
NetworksChainId.mainnet,
'0x514910771af9ca656af840dff83e8264ecf986ca',
signal,
);

expect(result).toBeUndefined();
await expect(async () => {
await fetchTokenMetadata(
NetworksChainId.mainnet,
'0x514910771af9ca656af840dff83e8264ecf986ca',
signal,
);
}).rejects.toThrow(FETCH_TOKEN_METADATA_ERROR);
});

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

const result = await fetchTokenMetadata(
NetworksChainId.mainnet,
'0x514910771af9ca656af840dff83e8264ecf986ca',
signal,
{ timeout: ONE_MILLISECOND },
);

expect(result).toBeUndefined();
await expect(async () => {
await fetchTokenMetadata(
NetworksChainId.mainnet,
'0x514910771af9ca656af840dff83e8264ecf986ca',
signal,
{ timeout: ONE_MILLISECOND },
);
}).rejects.toThrow(FETCH_TOKEN_METADATA_ERROR);
});
});

it('should call the tokens api and return undefined', async () => {
const { signal } = new AbortController();
nock(TOKEN_END_POINT_API)
.get(`/tokens/${NetworksChainId.mainnet}`)
.reply(404, undefined)
.persist();

const tokens = await fetchTokenList(NetworksChainId.mainnet, signal);

expect(tokens).toBeUndefined();
});
});
10 changes: 6 additions & 4 deletions src/apis/token-service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { timeoutFetch } from '../util';

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

/**
* Get the tokens URL for a specific network.
Expand Down Expand Up @@ -63,18 +65,18 @@ export async function fetchTokenList(
* @param options.timeout - The fetch timeout.
* @returns The token metadata, or `undefined` if the request was cancelled.
*/
export async function fetchTokenMetadata(
export async function fetchTokenMetadata<T>(
chainId: string,
tokenAddress: string,
abortSignal: AbortSignal,
{ timeout = defaultTimeout } = {},
): Promise<unknown> {
): Promise<T> {
const tokenMetadataURL = getTokenMetadataURL(chainId, tokenAddress);
const response = await queryApi(tokenMetadataURL, abortSignal, timeout);
if (response) {
return parseJsonResponse(response);
return parseJsonResponse(response) as Promise<T>;
}
return undefined;
throw new Error(FETCH_TOKEN_METADATA_ERROR);
}

/**
Expand Down

0 comments on commit d4030cf

Please sign in to comment.