Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/services/marketRate/coingeckoFetcher.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axios from "axios";
import { OUTGOING_HTTP_TIMEOUT_MS } from "../../utils/httpTimeout.js";
import { withRetry } from "../../utils/retryUtil.js";

export class CoinGeckoFetcher {
Expand All @@ -11,7 +12,10 @@ export class CoinGeckoFetcher {
*/
static async fetchXlmUsdPrice(): Promise<number> {
const response = await withRetry(
() => axios.get(CoinGeckoFetcher.API_URL),
() =>
axios.get(CoinGeckoFetcher.API_URL, {
timeout: OUTGOING_HTTP_TIMEOUT_MS,
}),
{
maxRetries: 3,
retryDelay: 1000,
Expand Down
9 changes: 5 additions & 4 deletions src/services/marketRate/ghsFetcher.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import axios from 'axios';
import { MarketRateFetcher, MarketRate } from './types';
import { validatePrice } from './validation';
import { OUTGOING_HTTP_TIMEOUT_MS } from '../../utils/httpTimeout.js';

type CoinGeckoPriceResponse = {
stellar?: {
Expand Down Expand Up @@ -42,7 +43,7 @@ export class GHSRateFetcher implements MarketRateFetcher {
() => axios.get<CoinGeckoPriceResponse>(
this.coinGeckoUrl,
{
timeout: 10000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
"User-Agent": "StellarFlow-Oracle/1.0",
},
Expand Down Expand Up @@ -81,7 +82,7 @@ export class GHSRateFetcher implements MarketRateFetcher {
() => axios.get<CoinGeckoPriceResponse>(
this.coinGeckoUrl,
{
timeout: 10000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
"User-Agent": "StellarFlow-Oracle/1.0",
},
Expand All @@ -100,7 +101,7 @@ export class GHSRateFetcher implements MarketRateFetcher {
() => axios.get<ExchangeRateApiResponse>(
this.usdToGhsUrl,
{
timeout: 10000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
"User-Agent": "StellarFlow-Oracle/1.0",
},
Expand All @@ -119,7 +120,7 @@ export class GHSRateFetcher implements MarketRateFetcher {
const usdPrice = validatePrice(stellarPrice.usd);

const exchangeRateResponse = await axios.get<ExchangeRateApiResponse>(this.usdToGhsUrl, {
timeout: 10000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
"User-Agent": "StellarFlow-Oracle/1.0",
},
Expand Down
7 changes: 4 additions & 3 deletions src/services/marketRate/kesFetcher.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import axios from 'axios';
import { MarketRateFetcher, MarketRate, RateSource } from './types';
import { validatePrice } from './validation';
import { OUTGOING_HTTP_TIMEOUT_MS } from '../../utils/httpTimeout.js';

/**
* Binance Ticker Response Interface
Expand Down Expand Up @@ -170,7 +171,7 @@ const BINANCE_P2P_URL =
/**
* Default timeout for API requests (ms)
*/
const DEFAULT_TIMEOUT_MS = 8000;
const DEFAULT_TIMEOUT_MS = OUTGOING_HTTP_TIMEOUT_MS;

/**
* Approximate KES/USD rate for calculation fallback
Expand Down Expand Up @@ -505,7 +506,7 @@ export class KESRateFetcher implements MarketRateFetcher {
try {
const response = await withRetry(
() => axios.get(cbkSource.url, {
timeout: 10000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
"User-Agent": "StellarFlow-Oracle/1.0",
Accept: "application/json",
Expand Down Expand Up @@ -545,7 +546,7 @@ export class KESRateFetcher implements MarketRateFetcher {
try {
const response = await withRetry(
() => axios.get(source.url, {
timeout: 10000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
"User-Agent": "StellarFlow-Oracle/1.0",
Accept: "application/json",
Expand Down
11 changes: 6 additions & 5 deletions src/services/marketRate/ngnFetcher.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axios from "axios";
import { OUTGOING_HTTP_TIMEOUT_MS } from "../../utils/httpTimeout.js";
import {
MarketRateFetcher,
MarketRate,
Expand Down Expand Up @@ -112,7 +113,7 @@ export class NGNRateFetcher implements MarketRateFetcher {
`${this.vtpassBase()}/service-variations`,
{
params: { serviceID: serviceId },
timeout: 15000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
...headers,
"User-Agent": "StellarFlow-Oracle/1.0",
Expand Down Expand Up @@ -147,7 +148,7 @@ export class NGNRateFetcher implements MarketRateFetcher {
const coinGeckoResponse = await withRetry(
() =>
axios.get<CoinGeckoPriceResponse>(this.coinGeckoUrl, {
timeout: 10000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
"User-Agent": "StellarFlow-Oracle/1.0",
},
Expand Down Expand Up @@ -178,7 +179,7 @@ export class NGNRateFetcher implements MarketRateFetcher {
const coinGeckoResponse = await withRetry(
() =>
axios.get<CoinGeckoPriceResponse>(this.coinGeckoUrl, {
timeout: 10000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
"User-Agent": "StellarFlow-Oracle/1.0",
},
Expand Down Expand Up @@ -211,7 +212,7 @@ export class NGNRateFetcher implements MarketRateFetcher {
const coinGeckoResponse = await withRetry(
() =>
axios.get<CoinGeckoPriceResponse>(this.coinGeckoUrl, {
timeout: 10000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
"User-Agent": "StellarFlow-Oracle/1.0",
},
Expand All @@ -228,7 +229,7 @@ export class NGNRateFetcher implements MarketRateFetcher {
const fxResponse = await withRetry(
() =>
axios.get<ExchangeRateApiResponse>(this.usdToNgnUrl, {
timeout: 10000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
headers: {
"User-Agent": "StellarFlow-Oracle/1.0",
},
Expand Down
2 changes: 2 additions & 0 deletions src/services/multiSigService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import prisma from "../lib/prisma";
import { Keypair } from "@stellar/stellar-sdk";
import dotenv from "dotenv";
import { createTimeoutSignal } from "../utils/httpTimeout.js";

dotenv.config();

Expand Down Expand Up @@ -205,6 +206,7 @@ export class MultiSigService {
Authorization: `Bearer ${process.env.MULTI_SIG_AUTH_TOKEN || ""}`,
},
body: JSON.stringify(payload),
signal: createTimeoutSignal(),
});

if (!response.ok) {
Expand Down
3 changes: 2 additions & 1 deletion src/services/webhook.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axios from "axios";
import { OUTGOING_HTTP_TIMEOUT_MS } from "../utils/httpTimeout.js";
import { withRetry } from "../utils/retryUtil.js";

type MarkdownText = {
Expand Down Expand Up @@ -107,7 +108,7 @@ export class WebhookService {
() =>
axios.post(webhookUrl, message, {
headers: { "Content-Type": "application/json" },
timeout: 5000,
timeout: OUTGOING_HTTP_TIMEOUT_MS,
}),
{
maxRetries: 3,
Expand Down
5 changes: 5 additions & 0 deletions src/utils/httpTimeout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const OUTGOING_HTTP_TIMEOUT_MS = 5000;

export function createTimeoutSignal(timeoutMs = OUTGOING_HTTP_TIMEOUT_MS): AbortSignal {
return AbortSignal.timeout(timeoutMs);
}
6 changes: 5 additions & 1 deletion src/utils/retryUtil.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axios, { AxiosError, AxiosRequestConfig } from "axios";
import { OUTGOING_HTTP_TIMEOUT_MS } from "./httpTimeout.js";

/**
* Retry configuration options
Expand Down Expand Up @@ -190,7 +191,10 @@ export function createRetryableAxiosInstance(
axiosConfig: AxiosRequestConfig = {},
retryConfig: RetryConfig = {}
) {
const instance = axios.create(axiosConfig);
const instance = axios.create({
timeout: OUTGOING_HTTP_TIMEOUT_MS,
...axiosConfig,
});

// Add response interceptor for retry logic
instance.interceptors.response.use(
Expand Down
Loading