Skip to content

Commit

Permalink
Retry etherscan calls (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
krzkaczor authored Oct 29, 2023
1 parent 6d3378e commit 974c05d
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/ethereum-viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"fast-json-stable-stringify": "^2.1.0",
"fetch-retry": "^5.0.6",
"match-sorter": "^6.3.1",
"p-finally": "^2.0.1",
"path-browserify": "^1.0.1",
Expand Down
14 changes: 13 additions & 1 deletion packages/ethereum-viewer/src/explorer/fetchFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ import { join } from "path";
import { assert, StrictOmit } from "ts-essentials";

import { fetch as _fetch } from "../util/fetch";
import { makeSolidFetch } from "../util/solidFetch";
import { prettyStringify } from "../util/stringify";
import * as types from "./api-types";
import { apiUrlToWebsite } from "./apiUrlToWebsite";
import { fileExtension } from "./fileExtension";
import { ApiName, explorerApiKeys, explorerApiUrls } from "./networks";

const fetchEtherscanResponse = makeSolidFetch({
async verifyResponse(response: unknown): Promise<boolean> {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
return (response as any)?.message === "OK" || false;
},
});

interface FetchFilesOptions {
/**
* For unit testing.
Expand All @@ -27,7 +35,11 @@ interface FetchFilesOptions {
export async function fetchFiles(
apiName: ApiName,
contractAddress: string,
{ fetch = _fetch, proxyDepth = 3, skipPrefix = false }: FetchFilesOptions = {}
{
fetch = fetchEtherscanResponse,
proxyDepth = 3,
skipPrefix = false,
}: FetchFilesOptions = {}
): Promise<FetchFilesResult> {
const apiUrl = explorerApiUrls[apiName];
const url =
Expand Down
3 changes: 2 additions & 1 deletion packages/ethereum-viewer/src/openContractSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ async function saveSingleContractFilesToFs(
return {
entries,
mainFile: withPrefix(mainFile),
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
contractName: result.info.ContractName ?? "contract",
};
}
Expand All @@ -133,7 +134,7 @@ function getMainContractFile(

if (!fileToShow) {
const regexp = new RegExp(`contract\\s+${name}`);
fileToShow = files.find(([path, source]) => regexp.test(source));
fileToShow = files.find(([_path, source]) => regexp.test(source));
}

if (!fileToShow) fileToShow = files.sort(byPathLength)[0];
Expand Down
45 changes: 45 additions & 0 deletions packages/ethereum-viewer/src/util/solidFetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import fetchRetry from "fetch-retry";

interface MakeSolidFetchOptions {
/**
* return false if the response should be retried
*/
verifyResponse: (response: unknown) => Promise<boolean>;
}

// @note: returns already parsed response
type SolidFetch = (input: string, init?: RequestInit) => Promise<unknown>;

export function makeSolidFetch(opts: MakeSolidFetchOptions): SolidFetch {
const solidFetch = fetchRetry(self.fetch, {
retries: 3,
async retryOn(_attempt, error, response) {
const retry = error !== null || !response?.ok;
if (retry) {
// eslint-disable-next-line no-console
console.log("Retrying failed fetch", {
error,
status: response?.status,
});
}
// if we have a response, we verify it and decide if we should retry
if (!retry) {
const responseJson = await response.clone().json();
const verified = await opts.verifyResponse(responseJson);
if (!verified) {
console.log("Response verification failed, retrying...");
}

return !verified;
}

return true;
},
retryDelay: function (attempt) {
return Math.pow(2, attempt) * 1000;
},
});

return (input: string, init?: RequestInit) =>
solidFetch(input, init).then((response) => response.json());
}
7 changes: 7 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 974c05d

Please sign in to comment.