Skip to content

Commit

Permalink
handle blockscout 404 error (#1325)
Browse files Browse the repository at this point in the history
Co-authored-by: Zach Couchman <[email protected]>
  • Loading branch information
ZacharyCouchman and ZacharyCouchman authored Jan 10, 2024
1 parent 86f2ca9 commit ad70ba7
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 76 deletions.
2 changes: 1 addition & 1 deletion packages/checkout/sdk/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const config: Config = {
'^.+\\.(t|j)sx?$': '@swc/jest',
},
transformIgnorePatterns: [],
setupFiles: ['./test/__mocks__/window.ts'],
setupFiles: [],
};

export default config;
16 changes: 2 additions & 14 deletions packages/checkout/sdk/src/api/blockscout/blockscout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,7 @@ export class Blockscout {
const cached = this.getCache(url);
if (cached) return Promise.resolve(cached);

const response = await this.httpClient.get(url);
if (response.status >= 400) {
return Promise.reject({
code: response.status,
message: response.statusText,
});
}
const response = await this.httpClient.get(url); // success if 2XX response otherwise throw error

// To get around an issue with native tokens being an ERC-20, there is the need
// to remove IMX from `resp` and add it back in using getNativeTokenByWalletAddress.
Expand Down Expand Up @@ -151,13 +145,7 @@ export class Blockscout {
const cached = this.getCache(url);
if (cached) return Promise.resolve(cached);

const response = await this.httpClient.get(url);
if (response.status >= 400) {
return Promise.reject({
code: response.status,
message: response.statusText,
});
}
const response = await this.httpClient.get(url); // success if 2XX response otherwise throw error

const data = {
token: this.nativeToken,
Expand Down
35 changes: 19 additions & 16 deletions packages/checkout/sdk/src/api/http/httpClient.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Environment } from '@imtbl/config';
import axios, { AxiosResponse } from 'axios';
import axios, { AxiosError } from 'axios';
import { HttpClient } from './httpClient';
import { CheckoutModuleConfiguration } from '../../types';
import { CheckoutError, CheckoutErrorType } from '../../errors';

jest.mock('axios', () => ({
create: jest.fn(),
Expand Down Expand Up @@ -93,17 +92,22 @@ describe('HttpClient', () => {

['get', 'post', 'put'].forEach((method) => {
describe(method, () => {
it(`[${method}] should throw error when non-200 status`, async () => {
const mockResponse = {
it(`[${method}] should throw error when non-2XX status`, async () => {
const mockError = {
isAxiosError: true,
status: 500,
statusText: 'error 500 message',
} as AxiosResponse;
mockedAxiosInstance.request.mockResolvedValueOnce(mockResponse);
message: 'Internal Server Error',
} as AxiosError;
mockedAxiosInstance.request.mockRejectedValue(mockError);

const httpClient = new HttpClient(testCheckoutConfig);
await expect((httpClient as any)[method]('/'))
.rejects
.toThrowError(new Error('Error: 500 error 500 message'));
try {
await (httpClient as any)[method]('/');
} catch (err: any) {
expect(err.isAxiosError).toBeTruthy();
expect(err.status).toBe(500);
expect(err.message).toBe('Internal Server Error');
}
});

it(`[${method}] should throw error when error fetching`, async () => {
Expand All @@ -112,12 +116,11 @@ describe('HttpClient', () => {
});

const httpClient = new HttpClient(testCheckoutConfig);
await expect(httpClient.get('/')).rejects.toThrow(
new CheckoutError(
'error message',
CheckoutErrorType.API_ERROR,
),
);
try {
await httpClient.get('/');
} catch (error:any) {
expect(error.message).toBe('error message');
}
});
});
});
Expand Down
23 changes: 2 additions & 21 deletions packages/checkout/sdk/src/api/http/httpClient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import { CheckoutModuleConfiguration } from '../../types';
import { CheckoutError, CheckoutErrorType } from '../../errors';

const PUBLISHABLE_KEY_PREFIX = 'pk_imapik-';

Expand Down Expand Up @@ -51,26 +50,8 @@ export class HttpClient {
);
}

// eslint-disable-next-line class-methods-use-this
private processResponse(response: AxiosResponse) {
if (response && response?.status !== 200) {
throw new CheckoutError(
`Error: ${response.status} ${response.statusText}`,
CheckoutErrorType.API_ERROR,
);
}
}

public async request(config: AxiosRequestConfig) {
let response;
try {
response = await this.axiosInstance.request(config);
} catch (error: any) {
throw new CheckoutError(error.message, CheckoutErrorType.API_ERROR);
}

this.processResponse(response);
return response;
return await this.axiosInstance.request(config);
}

public async get(url: string, config?: AxiosRequestConfig) {
Expand Down
28 changes: 22 additions & 6 deletions packages/checkout/sdk/src/config/remoteConfigFetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,17 @@ export class RemoteConfigFetcher {
private async loadConfig(): Promise<RemoteConfiguration | undefined> {
if (this.configCache) return this.configCache;

const response = await this.httpClient.get(
`${this.getEndpoint()}/${this.version}/config`,
);
let response: AxiosResponse;
try {
response = await this.httpClient.get(
`${this.getEndpoint()}/${this.version}/config`,
);
} catch (err: any) {
throw new CheckoutError(
`Error: ${err.message}`,
CheckoutErrorType.API_ERROR,
);
}

// Ensure that the configuration is valid
this.configCache = this.parseResponse<RemoteConfiguration>(response);
Expand All @@ -70,9 +78,17 @@ export class RemoteConfigFetcher {
private async loadConfigTokens(): Promise<ChainsTokensConfig | undefined> {
if (this.tokensCache) return this.tokensCache;

const response = await this.httpClient.get(
`${this.getEndpoint()}/${this.version}/config/tokens`,
);
let response: AxiosResponse;
try {
response = await this.httpClient.get(
`${this.getEndpoint()}/${this.version}/config/tokens`,
);
} catch (err: any) {
throw new CheckoutError(
`Error: ${err.message}`,
CheckoutErrorType.API_ERROR,
);
}

// Ensure that the configuration is valid
this.tokensCache = this.parseResponse<ChainsTokensConfig>(response);
Expand Down
1 change: 1 addition & 0 deletions packages/checkout/sdk/src/widgets/load.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** @jest-environment jsdom */
import { SDK_VERSION_MARKER } from '../env';
import { loadUnresolved } from './load';

Expand Down
10 changes: 0 additions & 10 deletions packages/checkout/sdk/test/__mocks__/window.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -198,21 +198,21 @@ export function WalletWidget(props: WalletWidgetInputs) {
<CryptoFiatProvider environment={environment}>
<WalletContext.Provider value={walletReducerValues}>
{viewState.view.type === SharedViews.LOADING_VIEW && (
<LoadingView loadingText={loadingText} />
<LoadingView loadingText={loadingText} />
)}
{viewState.view.type === WalletWidgetViews.WALLET_BALANCES && (
<WalletBalances balancesLoading={balancesLoading} setBalancesLoading={setBalancesLoading} />
<WalletBalances balancesLoading={balancesLoading} setBalancesLoading={setBalancesLoading} />
)}
{viewState.view.type === WalletWidgetViews.SETTINGS && <Settings />}
{viewState.view.type === WalletWidgetViews.COIN_INFO && (
<CoinInfo />
<CoinInfo />
)}
{viewState.view.type === SharedViews.ERROR_VIEW && (
<ErrorView
actionText={errorActionText}
onActionClick={errorAction}
onCloseClick={() => sendWalletWidgetCloseEvent(eventTarget)}
/>
<ErrorView
actionText={errorActionText}
onActionClick={errorAction}
onCloseClick={() => sendWalletWidgetCloseEvent(eventTarget)}
/>
)}
{viewState.view.type === SharedViews.TOP_UP_VIEW && (
<TopUpView
Expand Down

0 comments on commit ad70ba7

Please sign in to comment.