Last active
May 16, 2024 13:57
-
-
Save WilfredAlmeida/9adea27abb5958178c4370c5656e89b7 to your computer and use it in GitHub Desktop.
Using Axios for JSON RPC calls instead of fetch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a custom fetch function that uses axios to make requests and retries on errors or 502 status codes | |
// Run this file by executing `npx tsx axiosFetchWithRetries.ts` | |
import { Connection } from "@solana/web3.js"; | |
import axios from "axios"; | |
const RETRY_ATTEMPTS = 3; | |
const agent = new https.Agent({ | |
maxSockets: 100, | |
}); | |
const axiosObject = axios.create({ | |
httpsAgent: agent, | |
}); | |
export async function axiosFetchWithRetries( | |
input: string | URL | globalThis.Request, | |
init?: RequestInit, | |
retryAttempts = 0 | |
): Promise<Response> { | |
let attempt = 0; | |
// Adding default headers | |
if (!init || !init.headers) { | |
init = { | |
headers: { | |
"Content-Type": "application/json", | |
}, | |
...init, | |
}; | |
} | |
while (attempt < retryAttempts) { | |
try { | |
let axiosHeaders = {}; | |
axiosHeaders = Array.from(new Headers(init.headers).entries()).reduce( | |
(acc, [key, value]) => { | |
acc[key] = value; | |
return acc; | |
}, | |
{} | |
); | |
const axiosConfig = { | |
data: init.body, | |
headers: axiosHeaders, | |
method: init.method, | |
baseURL: input.toString(), | |
validateStatus: (status) => true, | |
}; | |
const axiosResponse = await axiosObject.request(axiosConfig); | |
const { data, status, statusText, headers } = axiosResponse; | |
// Mapping headers from axios to fetch format | |
const headersArray: [string, string][] = Object.entries(headers).map( | |
([key, value]) => [key, value] | |
); | |
const fetchHeaders = new Headers(headersArray); | |
const response = new Response(JSON.stringify(data), { | |
status, | |
statusText, | |
headers: fetchHeaders, | |
}); | |
// Comment the above lines and uncomment the following one to switch from axios to fetch | |
// const response = await fetch(input, init); | |
// Traffic might get routed to backups or node restarts or if anything throws a 502, retry | |
if (response.status === 502) { | |
console.log("Retrying due to 502"); | |
attempt++; | |
// Backoff to avoid hammering the server | |
await new Promise<void>((resolve) => | |
setTimeout(resolve, 100 * attempt) | |
); | |
continue; | |
} | |
return Promise.resolve(response); | |
} catch (e) { | |
console.log(`Retrying due to error ${e}`, e); | |
attempt++; | |
continue; | |
} | |
} | |
return Promise.reject("Max retries reached"); | |
} | |
async function main() { | |
const connection = new Connection("https://api.devnet.solana.com", { | |
async fetch(input, init?) { | |
console.log( | |
"Custom fetch function", | |
input, | |
init.method, | |
init.body, | |
init.headers | |
); | |
return await axiosFetchWithRetries(input, init, RETRY_ATTEMPTS); | |
}, | |
}); | |
const blockhash = await connection.getLatestBlockhash(); | |
console.log("LATEST BLOCKHASH"); | |
console.log(blockhash); | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment