From 66ba735c80fcc09dd68682c1ba5e486340c0948e Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Thu, 2 Apr 2026 10:45:37 +0200 Subject: [PATCH 1/5] chore(deps): Remove axios dependency, use SDK FetchUtils Replace all axios.get/post calls with fetchWithTimeout/postWithTimeout from @across-protocol/sdk utils. This removes a direct dependency and standardizes HTTP requests on the native fetch-based SDK utilities. Co-Authored-By: Claude Opus 4.6 (1M context) --- package.json | 3 +-- scripts/fetchInventoryConfig.ts | 22 +++++++------------ scripts/simulateFill.ts | 35 ++++++++---------------------- src/clients/AcrossAPIClient.ts | 10 ++++----- src/clients/AcrossApiBaseClient.ts | 23 ++++++++++---------- src/finalizer/utils/helios.ts | 14 ++++++------ src/finalizer/utils/scroll.ts | 14 +++++------- src/refiller/Refiller.ts | 22 +++++++------------ src/utils/BridgeUtils.ts | 16 ++++++-------- src/utils/CCTPUtils.ts | 11 +++------- src/utils/OFTUtils.ts | 7 +++--- src/utils/SDKUtils.ts | 5 +++++ yarn.lock | 28 +++++------------------- 13 files changed, 79 insertions(+), 131 deletions(-) diff --git a/package.json b/package.json index 3347741cfa..a6ea91e8b3 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "dependencies": { "@across-protocol/constants": "^3.1.102", "@across-protocol/contracts": "5.0.4", - "@across-protocol/sdk": "4.3.136", + "@across-protocol/sdk": "4.3.138", "@arbitrum/sdk": "^4.0.2", "@consensys/linea-sdk": "^0.3.0", "@coral-xyz/anchor": "^0.31.1", @@ -33,7 +33,6 @@ "@solana-program/compute-budget": "^0.8.0", "@solana/kit": "^5.4.0", "google-auth-library": "^8.5.1", - "axios": "^1.7.4", "binance-api-node": "0.12.7", "dotenv": "^16.3.1", "ethers": "^5.7.2", diff --git a/scripts/fetchInventoryConfig.ts b/scripts/fetchInventoryConfig.ts index f99cd65b96..63affcc143 100644 --- a/scripts/fetchInventoryConfig.ts +++ b/scripts/fetchInventoryConfig.ts @@ -1,8 +1,7 @@ import { writeFile } from "node:fs/promises"; import { config } from "dotenv"; -import axios from "axios"; import { GoogleAuth } from "google-auth-library"; -import { Logger, waitForLogger, delay } from "../src/utils"; +import { Logger, waitForLogger, delay, fetchWithTimeout } from "../src/utils"; const DEFAULT_ENVIRONMENT = "prod"; const AUTH_TIMEOUT_MS = 30000; @@ -18,7 +17,7 @@ function withTimeout(promise: Promise, timeoutMs: number, operationName: s ]); } -async function fetchWithRetry( +async function fetchConfigWithRetry( url: string, headers: Record, retries = 3, @@ -26,14 +25,13 @@ async function fetchWithRetry( ): Promise { for (let i = 0; i < retries; i++) { try { - const response = await axios.get(url, { headers, responseType: "text", timeout: 30000 }); - return response.data as string; + return await fetchWithTimeout(url, {}, headers, 30000, "text"); } catch (error) { if (i === retries - 1) { throw error; } logger.warn({ - at: "fetchInventoryConfig#fetchWithRetry", + at: "fetchInventoryConfig#fetchConfigWithRetry", message: "Request failed, retrying", attempt: `${i + 1}/${retries}`, delayMs, @@ -130,7 +128,7 @@ async function run(): Promise { label: spec.label, configuramaFilePath, }); - const fileContent = await fetchWithRetry(url, headers); + const fileContent = await fetchConfigWithRetry(url, headers); const jsonData = JSON.parse(fileContent); await writeFile(localFilename, JSON.stringify(jsonData, null, 2)); logger.debug({ @@ -162,16 +160,12 @@ async function run(): Promise { } function getErrorMessage(error: unknown): string { - if (axios.isAxiosError(error)) { - if (error.response?.status === 404) { + if (error instanceof Error) { + if (error.message.includes("HTTP 404")) { return "File not found in Configurama"; - } else if (error.response?.status === 401 || error.response?.status === 403) { + } else if (error.message.includes("HTTP 401") || error.message.includes("HTTP 403")) { return "Authentication failed. Ensure ADC is configured to call the Configurama API."; - } else { - return `Configurama API error: ${error.response?.status} - ${error.message}`; } - } - if (error instanceof Error) { return error.message; } return String(error); diff --git a/scripts/simulateFill.ts b/scripts/simulateFill.ts index df36852748..b0faf96d8b 100644 --- a/scripts/simulateFill.ts +++ b/scripts/simulateFill.ts @@ -1,4 +1,3 @@ -import axios from "axios"; import minimist from "minimist"; import { config } from "dotenv"; import { LogDescription } from "@ethersproject/abi"; @@ -11,6 +10,7 @@ import { getProvider, isDefined, populateV3Relay, + postWithTimeout, toAddressType, chainIsEvm, getBlockForTimestamp, @@ -170,15 +170,14 @@ async function createTenderlySimulation( public: true, // Make simulation publicly accessible }; + const headers = { + "X-Access-Key": tenderlyAccessKey, + }; + try { - const response = await axios.post(tenderlyUrl, simulationPayload, { - headers: { - "X-Access-Key": tenderlyAccessKey, - "Content-Type": "application/json", - }, - }); + const response = await postWithTimeout<{ simulation: { id: string } }>(tenderlyUrl, simulationPayload, {}, headers); - const simulationId = response.data.simulation.id; + const simulationId = response.simulation.id; console.log(`\nDebug: Simulation created with ID: ${simulationId}`); @@ -186,16 +185,7 @@ async function createTenderlySimulation( const shareUrl = `https://api.tenderly.co/api/v1/account/${tenderlyUser}/project/${tenderlyProject}/simulations/${simulationId}/share`; try { - await axios.post( - shareUrl, - {}, // Empty body - { - headers: { - "X-Access-Key": tenderlyAccessKey, - "Content-Type": "application/json", - }, - } - ); + await postWithTimeout(shareUrl, {}, {}, headers); console.log("Debug: Share enabled for simulation"); @@ -207,19 +197,12 @@ async function createTenderlySimulation( } catch (shareError) { // If share endpoint fails, fall back to the regular dashboard URL console.warn("Could not enable sharing, using dashboard URL instead"); - if (axios.isAxiosError(shareError)) { - console.warn("Share endpoint error:", shareError.response?.status, shareError.response?.data); - } + console.warn("Share endpoint error:", (shareError as Error).message); } // Fallback to dashboard URL return `https://dashboard.tenderly.co/${tenderlyUser}/${tenderlyProject}/simulator/${simulationId}`; } catch (error) { - if (axios.isAxiosError(error)) { - throw new Error( - `Tenderly simulation failed: ${error.response?.status} - ${JSON.stringify(error.response?.data)}` - ); - } throw error instanceof Error ? error : new Error(String(error)); } } diff --git a/src/clients/AcrossAPIClient.ts b/src/clients/AcrossAPIClient.ts index b68d1ac8a1..3c63665e0b 100644 --- a/src/clients/AcrossAPIClient.ts +++ b/src/clients/AcrossAPIClient.ts @@ -1,5 +1,5 @@ import _ from "lodash"; -import axios, { AxiosError } from "axios"; +import { fetchWithTimeout } from "../utils"; import { bnZero, winston, @@ -135,8 +135,8 @@ export class AcrossApiClient { const params = { l1Tokens: l1Tokens.join(",") }; let liquidReserves: BigNumber[] = []; try { - const result = await axios(url, { timeout, params }); - if (!result?.data) { + const result = await fetchWithTimeout>(url, params, {}, timeout); + if (!result) { this.logger.error({ at: "AcrossAPIClient", message: `Invalid response from /${path}, expected maxDeposit field.`, @@ -145,9 +145,9 @@ export class AcrossApiClient { result, }); } - liquidReserves = l1Tokens.map((l1Token) => BigNumber.from(result.data[l1Token.toEvmAddress()] ?? bnZero)); + liquidReserves = l1Tokens.map((l1Token) => BigNumber.from(result[l1Token.toEvmAddress()] ?? bnZero)); } catch (err) { - const msg = _.get(err, "response.data", _.get(err, "response.statusText", (err as AxiosError).message)); + const msg = (err as Error).message; this.logger.warn({ at: "AcrossAPIClient", message: `Failed to get ${path},`, url, params, msg }); return l1Tokens.map(() => bnZero); } diff --git a/src/clients/AcrossApiBaseClient.ts b/src/clients/AcrossApiBaseClient.ts index 50d607b824..72c01e77fb 100644 --- a/src/clients/AcrossApiBaseClient.ts +++ b/src/clients/AcrossApiBaseClient.ts @@ -1,4 +1,4 @@ -import axios, { AxiosError } from "axios"; +import { fetchWithTimeout } from "../utils"; import winston from "winston"; /** @@ -34,18 +34,19 @@ export abstract class BaseAcrossApiClient { protected async _get(endpoint: string, params: Record): Promise { try { - const config: { timeout: number; params: Record; headers?: Record } = { - timeout: this.apiResponseTimeout, - params, - }; - + const headers: Record = {}; if (this.apiKey) { - config.headers = { Authorization: `Bearer ${this.apiKey}` }; + headers.Authorization = `Bearer ${this.apiKey}`; } - const response = await axios.get(`${this.urlBase}/${endpoint}`, config); + const result = await fetchWithTimeout( + `${this.urlBase}/${endpoint}`, + params, + headers, + this.apiResponseTimeout + ); - if (!response?.data) { + if (!result) { this.logger.warn({ at: this.logContext, message: `Invalid response from ${this.urlBase}`, @@ -54,14 +55,14 @@ export abstract class BaseAcrossApiClient { }); return; } - return response.data; + return result; } catch (err) { this.logger.warn({ at: this.logContext, message: `Failed to get from ${this.urlBase}`, endpoint, params, - error: (err as AxiosError).message, + error: (err as Error).message, }); return; } diff --git a/src/finalizer/utils/helios.ts b/src/finalizer/utils/helios.ts index 1e2f1ca451..a0a1a3d3b4 100644 --- a/src/finalizer/utils/helios.ts +++ b/src/finalizer/utils/helios.ts @@ -11,10 +11,11 @@ import { isEVMSpokePoolClient, assert, CHAIN_IDs, + fetchWithTimeout, + postWithTimeout, } from "../../utils"; import { spreadEventWithBlockNumber } from "../../utils/EventUtils"; import { FinalizerPromise, CrossChainMessage } from "../types"; -import axios from "axios"; import UNIVERSAL_SPOKE_ABI from "../../common/abi/Universal_SpokePool.json"; import { RelayedCallDataEvent, StoredCallDataEvent } from "../../interfaces/Universal"; import { ApiProofRequest, ProofOutputs, ProofStateResponse, SP1HeliosProofData } from "../../interfaces/ZkApi"; @@ -348,21 +349,20 @@ async function enrichHeliosActions( // eslint-disable-next-line @typescript-eslint/no-explicit-any let getError: any = null; try { - const response = await axios.get(getProofUrl); - proofState = response.data; + proofState = await fetchWithTimeout(getProofUrl); logger.debug({ ...logContext, message: "Proof state received", proofId, status: proofState.status }); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { getError = error; } - // Axios error. Handle based on whether was a NOTFOUND or another error + // Handle fetch error based on whether it was a NOTFOUND or another error if (getError) { - const isNotFoundError = axios.isAxiosError(getError) && getError.response?.status === 404; + const isNotFoundError = getError instanceof Error && getError.message.includes("HTTP 404"); if (isNotFoundError) { // NOTFOUND error -> Request proof logger.debug({ ...logContext, message: "Proof not found (404), requesting...", proofId }); - await axios.post(`${apiBaseUrl}/v1/api/proofs`, apiRequest); + await postWithTimeout(`${apiBaseUrl}/v1/api/proofs`, apiRequest); logger.debug({ ...logContext, message: "Proof requested successfully.", proofId }); continue; } else { @@ -391,7 +391,7 @@ async function enrichHeliosActions( errorMessage: proofState.error_message, }); - await axios.post(`${apiBaseUrl}/v1/api/proofs`, apiRequest); + await postWithTimeout(`${apiBaseUrl}/v1/api/proofs`, apiRequest); logger.debug({ ...logContext, message: "Errored proof requested again successfully.", proofId }); break; } diff --git a/src/finalizer/utils/scroll.ts b/src/finalizer/utils/scroll.ts index 316d2f9e43..6f264ec27d 100644 --- a/src/finalizer/utils/scroll.ts +++ b/src/finalizer/utils/scroll.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { utils as sdkUtils } from "@across-protocol/sdk"; -import axios from "axios"; import { HubPoolClient, SpokePoolClient } from "../../clients"; import { CONTRACT_ADDRESSES } from "../../common"; import { @@ -9,6 +8,7 @@ import { Multicall2Call, winston, convertFromWei, + fetchWithTimeout, getTokenInfo, assert, isEVMSpokePoolClient, @@ -97,7 +97,7 @@ async function findOutstandingClaims(targetAddress: string): Promise(apiUrl, { - params: { - address: targetAddress, - page_size: MAX_PAGE_SIZE, - page: currentPage, - }, + address: targetAddress, + page_size: MAX_PAGE_SIZE, + page: currentPage, }) - ).data.data?.results ?? []; + ).data?.results ?? []; claimList.push( ...requestResponse .filter(({ claim_info }) => claim_info?.claimable) diff --git a/src/refiller/Refiller.ts b/src/refiller/Refiller.ts index dcc9d5d18b..c409f3b23a 100644 --- a/src/refiller/Refiller.ts +++ b/src/refiller/Refiller.ts @@ -1,5 +1,4 @@ import winston from "winston"; -import axios from "axios"; import { RefillerConfig, RefillBalanceData } from "./RefillerConfig"; import { Address, @@ -12,6 +11,7 @@ import { delay, ERC20, EvmAddress, + fetchWithTimeout, formatUnits, getNativeTokenAddressForChain, getNativeTokenSymbol, @@ -22,6 +22,7 @@ import { getTokenInfo, mapAsync, parseUnits, + postWithTimeout, submitTransaction, Signer, toAddressType, @@ -450,7 +451,7 @@ export class Refiller { if (isDefined(addressIdCache)) { addressId = addressIdCache; } else { - const { data: registeredAddresses } = await axios.get(`${nativeMarketsApiUrl}/addresses`, { headers }); + const registeredAddresses = await fetchWithTimeout<{ items: { chain: string; token: string; address_hex: string; id: string }[] }>(`${nativeMarketsApiUrl}/addresses`, {}, headers); addressId = registeredAddresses.items.find( ({ chain, token, address_hex }) => chain === "hyper_evm" && token === "usdh" && address_hex === this.baseSignerAddress.toNative() @@ -469,16 +470,16 @@ export class Refiller { message: `Address ${this.baseSignerAddress.toNative()} is not registered in the native markets API. Creating new address ID.`, address: this.baseSignerAddress, }); - const { data: _addressId } = await axios.post(`${nativeMarketsApiUrl}/addresses`, newAddressIdData, { - headers, - }); + const _addressId = await postWithTimeout<{ id: string }>(`${nativeMarketsApiUrl}/addresses`, newAddressIdData, {}, headers); addressId = _addressId.id; } await this.redisCache.set(addressIdCacheKey, addressId, 7 * day); } // Next, get the transfer route deposit address on Arbitrum. - const { data: transferRoutes } = await axios.get(`${nativeMarketsApiUrl}/transfer_routes`, { headers }); + interface TransferRouteAddress { chain: string; token: string; address_hex: string } + interface TransferRoute { source_address?: TransferRouteAddress; destination_address: TransferRouteAddress } + const transferRoutes = await fetchWithTimeout<{ items: TransferRoute[] }>(`${nativeMarketsApiUrl}/transfer_routes`, {}, headers); let availableTransferRoute = transferRoutes.items .filter((route) => isDefined(route.source_address)) .find( @@ -502,14 +503,7 @@ export class Refiller { address: this.baseSignerAddress, addressId, }); - const { data: _availableTransferRoute } = await axios.post( - `${nativeMarketsApiUrl}/transfer_routes`, - newTransferRouteData, - { - headers, - } - ); - availableTransferRoute = _availableTransferRoute; + availableTransferRoute = await postWithTimeout(`${nativeMarketsApiUrl}/transfer_routes`, newTransferRouteData, {}, headers); } // Create the transfer transaction. diff --git a/src/utils/BridgeUtils.ts b/src/utils/BridgeUtils.ts index 1dde72c9a4..0cf5376d35 100644 --- a/src/utils/BridgeUtils.ts +++ b/src/utils/BridgeUtils.ts @@ -1,5 +1,5 @@ -import { CHAIN_IDs, Address, delay, TOKEN_SYMBOLS_MAP, toBN, winston, BigNumber } from "./"; -import axios, { RawAxiosRequestHeaders } from "axios"; +import { CHAIN_IDs, Address, delay, TOKEN_SYMBOLS_MAP, toBN, winston, BigNumber, fetchWithTimeout, postWithTimeout } from "./"; +import type { FetchHeaders } from "./"; // We need to instruct this bridge what tokens we expect to receive on L2, since the bridge // API supports multiple destination tokens for a single L1 token. @@ -113,17 +113,16 @@ export class BridgeApiClient { return transferRequestData.source_deposit_instructions.to_address; } - defaultHeaders(): RawAxiosRequestHeaders { + defaultHeaders(): FetchHeaders { return { "Api-Key": `${this.bridgeApiKey}`, "Content-Type": "application/json", }; } - async getWithRetry(endpoint: string, headers: RawAxiosRequestHeaders, nRetries = this.nRetries) { + async getWithRetry(endpoint: string, headers: FetchHeaders, nRetries = this.nRetries) { try { - const response = await axios.get(`${this.bridgeApiBase}/${endpoint}`, { headers }); - return response.data; + return await fetchWithTimeout(`${this.bridgeApiBase}/${endpoint}`, {}, headers); } catch (e) { this.logger.debug({ at: "BridgeApi#_get", @@ -142,12 +141,11 @@ export class BridgeApiClient { async postWithRetry( endpoint: string, data: Record, - headers: RawAxiosRequestHeaders, + headers: FetchHeaders, nRetries = this.nRetries ) { try { - const response = await axios.post(`${this.bridgeApiBase}/${endpoint}`, data, { headers }); - return response.data; + return await postWithTimeout(`${this.bridgeApiBase}/${endpoint}`, data, {}, headers); } catch (e) { this.logger.debug({ at: "BridgeApi#_post", diff --git a/src/utils/CCTPUtils.ts b/src/utils/CCTPUtils.ts index ce61682053..391b358e9b 100644 --- a/src/utils/CCTPUtils.ts +++ b/src/utils/CCTPUtils.ts @@ -1,7 +1,6 @@ import { arch, utils } from "@across-protocol/sdk"; import { TokenMessengerMinterIdl } from "@across-protocol/contracts"; import { CHAIN_IDs, TOKEN_SYMBOLS_MAP } from "@across-protocol/constants"; -import axios from "axios"; import { Contract, ethers } from "ethers"; import { CONTRACT_ADDRESSES, CCTP_MAX_SEND_AMOUNT } from "../common"; import { BigNumber } from "./BNUtils"; @@ -26,7 +25,7 @@ import { isDefined } from "./TypeGuards"; import { getCachedProvider, getProvider, getSvmProvider } from "./ProviderUtils"; import { EventSearchConfig, paginatedEventQuery, spreadEvent } from "./EventUtils"; import { Log } from "../interfaces"; -import { assert, getRedisCache, Provider, Signer, ERC20, winston } from "."; +import { assert, fetchWithTimeout, getRedisCache, Provider, Signer, ERC20, winston } from "."; import { KeyPairSigner } from "@solana/kit"; import { TransactionRequest } from "@ethersproject/abstract-provider"; import { @@ -915,19 +914,15 @@ async function _fetchCctpV1Attestation( messageHash: string, isMainnet: boolean ): Promise { - const httpResponse = await axios.get( + return fetchWithTimeout( `https://iris-api${isMainnet ? "" : "-sandbox"}.circle.com/attestations/${messageHash}` ); - const attestationResponse = httpResponse.data; - return attestationResponse; } async function _fetchCCTPSvmAttestationProof(transactionHash: string): Promise { - const httpResponse = await axios.get( + return fetchWithTimeout( `https://iris-api.circle.com/messages/${getCctpDomainForChainId(CHAIN_IDs.SOLANA)}/${transactionHash}` ); - const attestationResponse = httpResponse.data; - return attestationResponse; } /** diff --git a/src/utils/OFTUtils.ts b/src/utils/OFTUtils.ts index 39fcc0b0c0..e852de6e48 100644 --- a/src/utils/OFTUtils.ts +++ b/src/utils/OFTUtils.ts @@ -12,9 +12,9 @@ import { paginatedEventQuery, spreadEventWithBlockNumber, getSrcOftPeriphery, + fetchWithTimeout, } from "."; import { BytesLike } from "ethers"; -import axios from "axios"; import { EVM_OFT_MESSENGERS } from "../common"; import { SortableEvent } from "../interfaces"; @@ -143,11 +143,10 @@ export function buildSimpleSendParamEvm(to: EvmAddress, dstEid: number, roundedA * @returns Array of message data objects as outlined in these docs: https://docs.layerzero.network/v2/concepts/troubleshooting/debugging-messages#response-shape. */ export async function getLzTransactionDetails(txHash: string): Promise { - const httpResponse = await axios.get<{ data: LzTransactionDetails[] }>( + const httpResponse = await fetchWithTimeout<{ data: LzTransactionDetails[] }>( `https://scan.layerzero-api.com/v1/messages/tx/${txHash}` ); - const txDetails = httpResponse.data.data; - return txDetails; + return httpResponse.data; } /** diff --git a/src/utils/SDKUtils.ts b/src/utils/SDKUtils.ts index 08a0b75573..aa7cd1c0ef 100644 --- a/src/utils/SDKUtils.ts +++ b/src/utils/SDKUtils.ts @@ -115,8 +115,13 @@ export const { unpackDepositEvent, unpackFillEvent, chainHasNativeToken, + fetchWithTimeout, + postWithTimeout, } = sdk.utils; +export type FetchHeaders = sdk.utils.FetchHeaders; +export type FetchQueryParams = sdk.utils.FetchQueryParams; + export const { getRefundsFromBundle, isChainDisabledAtBlock, diff --git a/yarn.lock b/yarn.lock index 15eeff3c5d..0e0f522fbe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -40,10 +40,10 @@ yargs "^17.7.2" zksync-web3 "^0.14.3" -"@across-protocol/sdk@4.3.136": - version "4.3.136" - resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-4.3.136.tgz#d85b681a088c31eab261dc66c15c4fa087c517cb" - integrity sha512-uo9Ran/+z/Vive+TJezzfc6j3Kvh59aoJJQ+udgpaR1Qix0lFZTB+VJJi/1097rk31ovHUTSoZfDlWJmsmt/FQ== +"@across-protocol/sdk@4.3.138": + version "4.3.138" + resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-4.3.138.tgz#6a352bc491d98046c8283c38fdc9ea3aa6e58a4d" + integrity sha512-rfLfuJGokEOXheoPwLb9/Rfov6Xj5zV5J8MVs0tWXiivOwWfZY4WEjTXbFvHTlf5xlMw3JE3M62nBW+tSEsoKQ== dependencies: "@across-protocol/constants" "^3.1.100" "@across-protocol/contracts" "5.0.4" @@ -61,7 +61,6 @@ "@uma/contracts-node" "^0.4.0" arweave "^1.14.4" async "^3.2.5" - axios "^0.27.2" bs58 "^6.0.0" decimal.js "^10.3.1" ethers "^5.7.2" @@ -3799,14 +3798,6 @@ axios@^0.21.1, axios@^0.21.2: dependencies: follow-redirects "^1.14.0" -axios@^0.27.2: - version "0.27.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" - integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== - dependencies: - follow-redirects "^1.14.9" - form-data "^4.0.0" - axios@^1.12.2: version "1.12.2" resolved "https://registry.yarnpkg.com/axios/-/axios-1.12.2.tgz#6c307390136cf7a2278d09cec63b136dfc6e6da7" @@ -3816,15 +3807,6 @@ axios@^1.12.2: form-data "^4.0.4" proxy-from-env "^1.1.0" -axios@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2" - integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw== - dependencies: - follow-redirects "^1.15.6" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -5929,7 +5911,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.14.9, follow-redirects@^1.15.6: +follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== From 659f5a3a1a5dac77342dfc02dbb728b7cf2ebdf8 Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Thu, 2 Apr 2026 10:54:19 +0200 Subject: [PATCH 2/5] lint --- src/clients/AcrossApiBaseClient.ts | 7 +----- src/refiller/Refiller.ts | 35 +++++++++++++++++++++++++----- src/utils/BridgeUtils.ts | 14 ++++++++++-- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/clients/AcrossApiBaseClient.ts b/src/clients/AcrossApiBaseClient.ts index 72c01e77fb..56e55d14e2 100644 --- a/src/clients/AcrossApiBaseClient.ts +++ b/src/clients/AcrossApiBaseClient.ts @@ -39,12 +39,7 @@ export abstract class BaseAcrossApiClient { headers.Authorization = `Bearer ${this.apiKey}`; } - const result = await fetchWithTimeout( - `${this.urlBase}/${endpoint}`, - params, - headers, - this.apiResponseTimeout - ); + const result = await fetchWithTimeout(`${this.urlBase}/${endpoint}`, params, headers, this.apiResponseTimeout); if (!result) { this.logger.warn({ diff --git a/src/refiller/Refiller.ts b/src/refiller/Refiller.ts index c409f3b23a..146ff923b1 100644 --- a/src/refiller/Refiller.ts +++ b/src/refiller/Refiller.ts @@ -451,7 +451,9 @@ export class Refiller { if (isDefined(addressIdCache)) { addressId = addressIdCache; } else { - const registeredAddresses = await fetchWithTimeout<{ items: { chain: string; token: string; address_hex: string; id: string }[] }>(`${nativeMarketsApiUrl}/addresses`, {}, headers); + const registeredAddresses = await fetchWithTimeout<{ + items: { chain: string; token: string; address_hex: string; id: string }[]; + }>(`${nativeMarketsApiUrl}/addresses`, {}, headers); addressId = registeredAddresses.items.find( ({ chain, token, address_hex }) => chain === "hyper_evm" && token === "usdh" && address_hex === this.baseSignerAddress.toNative() @@ -470,16 +472,32 @@ export class Refiller { message: `Address ${this.baseSignerAddress.toNative()} is not registered in the native markets API. Creating new address ID.`, address: this.baseSignerAddress, }); - const _addressId = await postWithTimeout<{ id: string }>(`${nativeMarketsApiUrl}/addresses`, newAddressIdData, {}, headers); + const _addressId = await postWithTimeout<{ id: string }>( + `${nativeMarketsApiUrl}/addresses`, + newAddressIdData, + {}, + headers + ); addressId = _addressId.id; } await this.redisCache.set(addressIdCacheKey, addressId, 7 * day); } // Next, get the transfer route deposit address on Arbitrum. - interface TransferRouteAddress { chain: string; token: string; address_hex: string } - interface TransferRoute { source_address?: TransferRouteAddress; destination_address: TransferRouteAddress } - const transferRoutes = await fetchWithTimeout<{ items: TransferRoute[] }>(`${nativeMarketsApiUrl}/transfer_routes`, {}, headers); + interface TransferRouteAddress { + chain: string; + token: string; + address_hex: string; + } + interface TransferRoute { + source_address?: TransferRouteAddress; + destination_address: TransferRouteAddress; + } + const transferRoutes = await fetchWithTimeout<{ items: TransferRoute[] }>( + `${nativeMarketsApiUrl}/transfer_routes`, + {}, + headers + ); let availableTransferRoute = transferRoutes.items .filter((route) => isDefined(route.source_address)) .find( @@ -503,7 +521,12 @@ export class Refiller { address: this.baseSignerAddress, addressId, }); - availableTransferRoute = await postWithTimeout(`${nativeMarketsApiUrl}/transfer_routes`, newTransferRouteData, {}, headers); + availableTransferRoute = await postWithTimeout( + `${nativeMarketsApiUrl}/transfer_routes`, + newTransferRouteData, + {}, + headers + ); } // Create the transfer transaction. diff --git a/src/utils/BridgeUtils.ts b/src/utils/BridgeUtils.ts index 0cf5376d35..2dbb24eab2 100644 --- a/src/utils/BridgeUtils.ts +++ b/src/utils/BridgeUtils.ts @@ -1,5 +1,15 @@ -import { CHAIN_IDs, Address, delay, TOKEN_SYMBOLS_MAP, toBN, winston, BigNumber, fetchWithTimeout, postWithTimeout } from "./"; -import type { FetchHeaders } from "./"; +import { + CHAIN_IDs, + Address, + delay, + TOKEN_SYMBOLS_MAP, + toBN, + winston, + BigNumber, + fetchWithTimeout, + postWithTimeout, + FetchHeaders, +} from "./"; // We need to instruct this bridge what tokens we expect to receive on L2, since the bridge // API supports multiple destination tokens for a single L1 token. From c1980945cc60919516c6f3feba67b8fdd46426b0 Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Thu, 2 Apr 2026 11:08:10 +0200 Subject: [PATCH 3/5] fix: Merge duplicate ../utils imports in AcrossAPIClient Co-Authored-By: Claude Opus 4.6 (1M context) --- src/clients/AcrossAPIClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clients/AcrossAPIClient.ts b/src/clients/AcrossAPIClient.ts index 3c63665e0b..cbcc34ef06 100644 --- a/src/clients/AcrossAPIClient.ts +++ b/src/clients/AcrossAPIClient.ts @@ -1,10 +1,10 @@ import _ from "lodash"; -import { fetchWithTimeout } from "../utils"; import { bnZero, winston, BigNumber, dedupArray, + fetchWithTimeout, getCurrentTime, TOKEN_SYMBOLS_MAP, CHAIN_IDs, From dbbe9abd05917a9fb27f2001f613e5ad6545100a Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Thu, 2 Apr 2026 16:11:05 +0200 Subject: [PATCH 4/5] fix: Import fetchWithTimeout from leaf module to avoid circular dependency Import from ../utils/SDKUtils instead of the ../utils barrel in AcrossApiBaseClient to prevent a circular dependency chain through the clients index. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/clients/AcrossApiBaseClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clients/AcrossApiBaseClient.ts b/src/clients/AcrossApiBaseClient.ts index 56e55d14e2..9935f85715 100644 --- a/src/clients/AcrossApiBaseClient.ts +++ b/src/clients/AcrossApiBaseClient.ts @@ -1,4 +1,4 @@ -import { fetchWithTimeout } from "../utils"; +import { fetchWithTimeout } from "../utils/SDKUtils"; import winston from "winston"; /** From 108dffbe181b1bf9785b1b9578c27abe296f4bf0 Mon Sep 17 00:00:00 2001 From: nicholaspai <9457025+nicholaspai@users.noreply.github.com> Date: Fri, 3 Apr 2026 04:32:37 -0400 Subject: [PATCH 5/5] Update helios.ts --- src/finalizer/utils/helios.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/finalizer/utils/helios.ts b/src/finalizer/utils/helios.ts index 02a8117d88..9b6f6d4a7e 100644 --- a/src/finalizer/utils/helios.ts +++ b/src/finalizer/utils/helios.ts @@ -10,7 +10,6 @@ import { groupObjectCountsByProp, isEVMSpokePoolClient, assert, - CHAIN_IDs, fetchWithTimeout, postWithTimeout, } from "../../utils";