From 7013489702e5235eba968e1cf00983183ee10bc0 Mon Sep 17 00:00:00 2001 From: tokenjunkielabs Date: Sun, 20 Sep 2026 20:03:21 -0400 Subject: [PATCH 1/5] fix(frontend): centralize API client configuration --- frontend/src/services/transactionHistory.ts | 49 +++++++-------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/frontend/src/services/transactionHistory.ts b/frontend/src/services/transactionHistory.ts index 64a3a44f..c81c2aaa 100644 --- a/frontend/src/services/transactionHistory.ts +++ b/frontend/src/services/transactionHistory.ts @@ -1,7 +1,6 @@ +import api from '../utils/api'; import { contractService } from './contracts'; -const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000'; - export interface HistoryFilters { search: string; status: string; @@ -36,15 +35,6 @@ function asString(value: unknown, fallback = ''): string { return fallback; } -function toQuery(params: Record): string { - const query = new URLSearchParams(); - Object.entries(params).forEach(([key, value]) => { - if (value === undefined || value === '') return; - query.set(key, String(value)); - }); - return query.toString(); -} - function normalizeClassicItem(row: Record): TimelineItem { const txHash = asString(row.tx_hash, '') || null; return { @@ -82,23 +72,18 @@ export async function fetchHistoryPage(options: { filters: HistoryFilters; }): Promise<{ items: TimelineItem[]; hasMore: boolean }> { const { page, limit, filters } = options; - const query = toQuery({ - page, - limit, - status: filters.status || undefined, - employee: filters.employee || undefined, - asset: filters.asset || undefined, - startDate: filters.startDate || undefined, - endDate: filters.endDate || undefined, - search: filters.search || undefined, + const { data: auditPayload } = await api.get('/v1/audit', { + params: { + page, + limit, + status: filters.status || undefined, + employee: filters.employee || undefined, + asset: filters.asset || undefined, + startDate: filters.startDate || undefined, + endDate: filters.endDate || undefined, + search: filters.search || undefined, + }, }); - - const auditResponse = await fetch(`${API_BASE_URL}/api/v1/audit?${query}`); - if (!auditResponse.ok) { - throw new Error(`Failed to fetch audit records (${auditResponse.status})`); - } - - const auditPayload = (await auditResponse.json()) as AuditResponse; const classicItems = (auditPayload.data || []).map(normalizeClassicItem); await contractService.initialize(); @@ -112,13 +97,11 @@ export async function fetchHistoryPage(options: { await Promise.all( contractIds.map(async (contractId) => { try { - const eventResponse = await fetch( - `${API_BASE_URL}/api/events/${contractId}?page=1&limit=10` - ); - if (!eventResponse.ok) return; - const payload = (await eventResponse.json()) as { + const { data: payload } = await api.get<{ data?: Array>; - }; + }>(`/events/${contractId}`, { + params: { page: 1, limit: 10 }, + }); (payload.data || []).forEach((row) => { contractItems.push(normalizeContractItem(contractId, row)); }); From 1a5d1a293b0b32dd65b9ee874b32b2616e1a5be2 Mon Sep 17 00:00:00 2001 From: tokenjunkielabs Date: Sun, 20 Sep 2026 20:03:23 -0400 Subject: [PATCH 2/5] fix(frontend): centralize API client configuration --- frontend/src/services/forecastApi.ts | 33 ++++++++-------------------- 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/frontend/src/services/forecastApi.ts b/frontend/src/services/forecastApi.ts index 9b281168..924f1c21 100644 --- a/frontend/src/services/forecastApi.ts +++ b/frontend/src/services/forecastApi.ts @@ -1,6 +1,4 @@ -import axios from 'axios'; - -const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3001/api/v1'; +import api from '../utils/api'; export interface ForecastLiquidity { status: 'green' | 'yellow' | 'red'; @@ -52,28 +50,16 @@ export interface LiquiditySettings { alertEmails?: string[]; } -function authHeaders() { - const token = localStorage.getItem('payd_auth_token'); - return token ? { Authorization: `Bearer ${token}` } : undefined; -} - export const getForecast = async (monthsForward: number = 6): Promise => { - const { data } = await axios.get<{ success: boolean; data: ForecastResponse }>( - `${API_BASE_URL}/forecast`, - { - params: { monthsForward }, - headers: authHeaders(), - } - ); + const { data } = await api.get<{ success: boolean; data: ForecastResponse }>('/v1/forecast', { + params: { monthsForward }, + }); return data.data; }; export const getLiquiditySettings = async (): Promise => { - const { data } = await axios.get<{ success: boolean; data: LiquiditySettings | null }>( - `${API_BASE_URL}/forecast/settings`, - { - headers: authHeaders(), - } + const { data } = await api.get<{ success: boolean; data: LiquiditySettings | null }>( + '/v1/forecast/settings' ); return data.data; }; @@ -81,10 +67,9 @@ export const getLiquiditySettings = async (): Promise export const updateLiquiditySettings = async ( input: LiquiditySettings ): Promise => { - const { data } = await axios.put<{ success: boolean; data: LiquiditySettings }>( - `${API_BASE_URL}/forecast/settings`, - input, - { headers: authHeaders() } + const { data } = await api.put<{ success: boolean; data: LiquiditySettings }>( + '/v1/forecast/settings', + input ); return data.data; }; From 69f853e2a15858f9f5b1cbddd2129752fef578f3 Mon Sep 17 00:00:00 2001 From: tokenjunkielabs Date: Sun, 20 Sep 2026 20:03:25 -0400 Subject: [PATCH 3/5] fix(frontend): centralize API client configuration --- frontend/src/services/cashFlowForecastApi.ts | 56 +++++++------------- 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/frontend/src/services/cashFlowForecastApi.ts b/frontend/src/services/cashFlowForecastApi.ts index 9ccef1e1..8b65a1de 100644 --- a/frontend/src/services/cashFlowForecastApi.ts +++ b/frontend/src/services/cashFlowForecastApi.ts @@ -1,7 +1,5 @@ -import axios, { type AxiosError } from 'axios'; - -const API_BASE_URL = - (import.meta.env.VITE_API_BASE_URL as string | undefined) || 'http://localhost:3001'; +import { isAxiosError, type AxiosError } from 'axios'; +import api from '../utils/api'; export interface HistoricalPayrollData { period: string; @@ -98,15 +96,12 @@ export interface AlertsResponse { */ export const getForecast = async (params: ForecastParams): Promise => { try { - const response = await axios.get(`${API_BASE_URL}/api/cash-flow/forecast`, { + const response = await api.get('/cash-flow/forecast', { params: { forecastDays: params.forecastDays || 90, distributionAccount: params.distributionAccount, assetIssuer: params.assetIssuer, }, - headers: { - Authorization: `Bearer ${localStorage.getItem('accessToken') || ''}`, - }, }); if (!response.data.success) { @@ -115,7 +110,7 @@ export const getForecast = async (params: ForecastParams): Promise; const errorMessage = (axiosError.response?.data as { message?: string } | undefined)?.message || @@ -139,17 +134,11 @@ export const getHistoricalData = async ( averages: { weekly: number; biweekly: number; monthly: number }; }> => { try { - const response = await axios.get( - `${API_BASE_URL}/api/cash-flow/historical`, - { - params: { - monthsBack: monthsBack || 6, - }, - headers: { - Authorization: `Bearer ${localStorage.getItem('accessToken') || ''}`, - }, - } - ); + const response = await api.get('/cash-flow/historical', { + params: { + monthsBack: monthsBack || 6, + }, + }); if (!response.data.success) { throw new Error('Failed to fetch historical data'); @@ -157,7 +146,7 @@ export const getHistoricalData = async ( return response.data.data; } catch (error) { - if (axios.isAxiosError(error)) { + if (isAxiosError(error)) { const axiosError = error as AxiosError<{ message?: string }>; const errorMessage = (axiosError.response?.data as { message?: string } | undefined)?.message || @@ -178,17 +167,11 @@ export const getProjections = async ( forecastDays?: number ): Promise => { try { - const response = await axios.get( - `${API_BASE_URL}/api/cash-flow/projections`, - { - params: { - forecastDays: forecastDays || 90, - }, - headers: { - Authorization: `Bearer ${localStorage.getItem('accessToken') || ''}`, - }, - } - ); + const response = await api.get('/cash-flow/projections', { + params: { + forecastDays: forecastDays || 90, + }, + }); if (!response.data.success) { throw new Error('Failed to fetch projections'); @@ -196,7 +179,7 @@ export const getProjections = async ( return response.data.data; } catch (error) { - if (axios.isAxiosError(error)) { + if (isAxiosError(error)) { const axiosError = error as AxiosError<{ message?: string }>; const errorMessage = (axiosError.response?.data as { message?: string } | undefined)?.message || @@ -220,15 +203,12 @@ export const getAlerts = async ( summary: { totalAlerts: number; criticalAlerts: number; warningAlerts: number }; }> => { try { - const response = await axios.get(`${API_BASE_URL}/api/cash-flow/alerts`, { + const response = await api.get('/cash-flow/alerts', { params: { forecastDays: params.forecastDays || 90, distributionAccount: params.distributionAccount, assetIssuer: params.assetIssuer, }, - headers: { - Authorization: `Bearer ${localStorage.getItem('accessToken') || ''}`, - }, }); if (!response.data.success) { @@ -237,7 +217,7 @@ export const getAlerts = async ( return response.data.data; } catch (error) { - if (axios.isAxiosError(error)) { + if (isAxiosError(error)) { const axiosError = error as AxiosError<{ message?: string }>; const errorMessage = (axiosError.response?.data as { message?: string } | undefined)?.message || From 90b441f447476cb138718c992c89fe56278123a8 Mon Sep 17 00:00:00 2001 From: tokenjunkielabs Date: Sun, 20 Sep 2026 20:03:26 -0400 Subject: [PATCH 4/5] fix(frontend): centralize API client configuration --- frontend/src/services/withdrawal.ts | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/frontend/src/services/withdrawal.ts b/frontend/src/services/withdrawal.ts index 633d2dcf..8ae07795 100644 --- a/frontend/src/services/withdrawal.ts +++ b/frontend/src/services/withdrawal.ts @@ -3,9 +3,7 @@ * Handles anchor discovery, withdrawal initiation, and transaction polling. */ -import axios from 'axios'; - -const API_BASE_URL = (import.meta.env.VITE_API_URL as string) || 'http://localhost:3000/api'; +import api from '../utils/api'; export interface AnchorInfo { domain: string; @@ -60,10 +58,9 @@ const withdrawalService = { */ getAvailableAnchors: async (assetCode: string = 'ORGUSD'): Promise => { try { - const response = await axios.get<{ anchors: AnchorInfo[] }>( - `${API_BASE_URL}/withdrawal/anchors`, - { params: { assetCode } } - ); + const response = await api.get<{ anchors: AnchorInfo[] }>('/withdrawal/anchors', { + params: { assetCode }, + }); return response.data.anchors; } catch { // Mock data for development until backend is ready @@ -101,10 +98,7 @@ const withdrawalService = { */ initiateWithdrawal: async (request: WithdrawalRequest): Promise => { try { - const response = await axios.post( - `${API_BASE_URL}/withdrawal/initiate`, - request - ); + const response = await api.post('/withdrawal/initiate', request); return response.data; } catch { // Mock response for development @@ -125,8 +119,8 @@ const withdrawalService = { anchorDomain: string ): Promise => { try { - const response = await axios.get( - `${API_BASE_URL}/withdrawal/status/${transactionId}`, + const response = await api.get( + `/withdrawal/status/${transactionId}`, { params: { anchorDomain } } ); return response.data; @@ -149,7 +143,7 @@ const withdrawalService = { */ cancelWithdrawal: async (transactionId: string): Promise => { try { - await axios.post(`${API_BASE_URL}/withdrawal/cancel`, { transactionId }); + await api.post('/withdrawal/cancel', { transactionId }); } catch { // Mock success for development console.log('Mock: Withdrawal cancelled', transactionId); From ceaffbbe70e028e5e24cae9abe5431870c3a964b Mon Sep 17 00:00:00 2001 From: tokenjunkielabs Date: Sun, 20 Sep 2026 20:03:28 -0400 Subject: [PATCH 5/5] fix(frontend): centralize API client configuration --- frontend/src/services/benefitsApi.ts | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/frontend/src/services/benefitsApi.ts b/frontend/src/services/benefitsApi.ts index e8e043b3..c5cc5c13 100644 --- a/frontend/src/services/benefitsApi.ts +++ b/frontend/src/services/benefitsApi.ts @@ -1,11 +1,4 @@ -import axios from 'axios'; - -const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3001/api/v1'; - -function authHeaders() { - const token = localStorage.getItem('payd_auth_token'); - return token ? { Authorization: `Bearer ${token}` } : undefined; -} +import api from '../utils/api'; export interface DraftPayslipLine { source: 'deduction_rule' | 'tax_rule'; @@ -29,11 +22,8 @@ export interface DraftPayslip { } export const getMyDeductionsDraftPayslip = async (): Promise => { - const { data } = await axios.get<{ success: boolean; data: DraftPayslip }>( - `${API_BASE_URL}/benefits/me/deductions`, - { - headers: authHeaders(), - } + const { data } = await api.get<{ success: boolean; data: DraftPayslip }>( + '/v1/benefits/me/deductions' ); return data.data;