From 940ebc16d5300d530e312742a2bde4c3714ae109 Mon Sep 17 00:00:00 2001
From: Ogunmodede Joel Taiwo
Date: Mon, 10 Aug 2026 02:36:41 +0100
Subject: [PATCH 1/9] fix(backend): round owed amounts via half-even policy in
loanController.ts roundToCents (#1372)
---
backend/src/__tests__/loanConfig.test.ts | 1 +
backend/src/__tests__/roundToCents.test.ts | 23 +++++++++++++++++++++
backend/src/controllers/loanController.ts | 3 ++-
backend/src/money/__tests__/decimal.test.ts | 15 ++++++++++++++
backend/src/money/decimal.ts | 11 ++++++++++
5 files changed, 52 insertions(+), 1 deletion(-)
create mode 100644 backend/src/__tests__/roundToCents.test.ts
diff --git a/backend/src/__tests__/loanConfig.test.ts b/backend/src/__tests__/loanConfig.test.ts
index b32c78ce..58b307bc 100644
--- a/backend/src/__tests__/loanConfig.test.ts
+++ b/backend/src/__tests__/loanConfig.test.ts
@@ -1,3 +1,4 @@
+import { jest } from '@jest/globals';
import { validateLoanConfig, validateLoanConfigOnStartup } from '../config/loanConfig.js';
describe('Loan config startup validation', () => {
diff --git a/backend/src/__tests__/roundToCents.test.ts b/backend/src/__tests__/roundToCents.test.ts
new file mode 100644
index 00000000..1b085c1c
--- /dev/null
+++ b/backend/src/__tests__/roundToCents.test.ts
@@ -0,0 +1,23 @@
+import { roundToCents } from '../controllers/loanController.js';
+
+describe('roundToCents half-even rounding', () => {
+ it('applies banker rounding (half-even) for .5 cent cases', () => {
+ expect(roundToCents(0.125)).toBe(0.12);
+ expect(roundToCents(0.135)).toBe(0.14);
+ expect(roundToCents(10.005)).toBe(10.0);
+ expect(roundToCents(10.015)).toBe(10.02);
+ });
+
+ it('handles negative half-even rounding symmetrically', () => {
+ expect(roundToCents(-0.125)).toBe(-0.12);
+ expect(roundToCents(-0.135)).toBe(-0.14);
+ });
+
+ it('rounds non-tie values to nearest cent', () => {
+ expect(roundToCents(10.004)).toBe(10.0);
+ expect(roundToCents(10.006)).toBe(10.01);
+ expect(roundToCents(12.3456)).toBe(12.35);
+ expect(roundToCents(12.3412)).toBe(12.34);
+ expect(roundToCents(0.0049)).toBe(0);
+ });
+});
diff --git a/backend/src/controllers/loanController.ts b/backend/src/controllers/loanController.ts
index b79ba540..a11b2a8d 100644
--- a/backend/src/controllers/loanController.ts
+++ b/backend/src/controllers/loanController.ts
@@ -12,6 +12,7 @@ import logger from '../utils/logger.js';
import { cacheService } from '../services/cacheService.js';
import { notificationService } from '../services/notificationService.js';
import { invalidateOnRepay, invalidateOnLoanRequest } from '../utils/cacheKeys.js';
+import { roundToCents } from '../money/decimal.js';
// ─── Test/Dev Only ────────────────────────────────────────────────────────────
@@ -225,7 +226,7 @@ const getLatestLedger = async (): Promise => {
return result.rows[0]?.last_indexed_ledger ?? 0;
};
-const roundToCents = (value: number): number => Math.floor((value + Number.EPSILON) * 100) / 100;
+export { roundToCents };
const addDays = (date: Date, days: number): Date => {
const result = new Date(date);
diff --git a/backend/src/money/__tests__/decimal.test.ts b/backend/src/money/__tests__/decimal.test.ts
index 99448a00..7583255f 100644
--- a/backend/src/money/__tests__/decimal.test.ts
+++ b/backend/src/money/__tests__/decimal.test.ts
@@ -3,6 +3,7 @@ import {
toStroops,
fromStroops,
splitProRata,
+ roundToCents,
RoundingMode,
MoneyError,
STROOP_SCALE,
@@ -168,3 +169,17 @@ describe('splitProRata', () => {
expect(() => splitProRata(1n, [-1n])).toThrow(MoneyError);
});
});
+
+describe('roundToCents', () => {
+ it('rounds via half-even rounding mode (bankers rounding)', () => {
+ expect(roundToCents(0.125)).toBe(0.12);
+ expect(roundToCents(0.135)).toBe(0.14);
+ expect(roundToCents(10.005)).toBe(10.0);
+ expect(roundToCents(10.015)).toBe(10.02);
+ });
+
+ it('handles negative numbers symmetrically', () => {
+ expect(roundToCents(-0.125)).toBe(-0.12);
+ expect(roundToCents(-0.135)).toBe(-0.14);
+ });
+});
diff --git a/backend/src/money/decimal.ts b/backend/src/money/decimal.ts
index 1ee9f5d8..6e45098e 100644
--- a/backend/src/money/decimal.ts
+++ b/backend/src/money/decimal.ts
@@ -154,6 +154,17 @@ export function fromStroops(value: bigint): string {
return `${negative ? '-' : ''}${whole.toString()}.${fraction}`;
}
+/**
+ * Round a numeric amount to 2 decimal places (cents) using the policy's
+ * default half-even rounding mode.
+ */
+export function roundToCents(value: number, mode: RoundingMode = DEFAULT_MODE): number {
+ if (!Number.isFinite(value)) return value;
+ const stroops = toStroops(value.toFixed(7), mode);
+ const cents = roundDiv(stroops, 100_000n, mode);
+ return Number(cents) / 100;
+}
+
/**
* Split `total` stroops across `weights` proportionally using the
* largest-remainder method, guaranteeing the returned parts sum *exactly*
From 2852369de5c8f5994af492033bd1954f6627e595 Mon Sep 17 00:00:00 2001
From: Ogunmodede Joel Taiwo
Date: Mon, 10 Aug 2026 02:41:28 +0100
Subject: [PATCH 2/9] style(frontend): fix Prettier formatting issues
---
frontend/lib/money/format.ts | 2 +-
frontend/src/app/[locale]/activity/page.tsx | 33 ++++++-----
.../src/app/[locale]/lend/LendPageClient.tsx | 24 ++++----
.../app/[locale]/loans/LoansPageClient.tsx | 4 +-
.../loans/[loanId]/LoanDetailsPageClient.tsx | 32 +++++------
frontend/src/app/[locale]/page.tsx | 4 +-
frontend/src/app/[locale]/settings/page.tsx | 4 +-
frontend/src/app/[locale]/wallet/page.tsx | 8 +--
.../borrower/ActiveLoansTracker.tsx | 4 +-
.../src/app/components/borrower/LoanCard.tsx | 56 ++++++++++---------
.../FinancialPerformanceDashboard.tsx | 18 ++++--
.../src/app/components/global_ui/Header.tsx | 8 +--
.../loan-wizard/StepAmountAsset.tsx | 4 +-
.../components/loan-wizard/WizardStepper.tsx | 4 +-
.../src/app/components/loan/LoanHealth.tsx | 8 +--
.../components/providers/WalletProvider.tsx | 6 +-
frontend/src/app/components/ui.tsx | 2 +-
.../app/components/ui/OperationProgress.tsx | 5 +-
frontend/src/app/components/ui/Toaster.tsx | 4 +-
frontend/src/app/hooks/useApi.ts | 8 +--
.../src/app/utils/transactionFormatter.ts | 5 +-
21 files changed, 132 insertions(+), 111 deletions(-)
diff --git a/frontend/lib/money/format.ts b/frontend/lib/money/format.ts
index 24a6594a..c1c57f34 100644
--- a/frontend/lib/money/format.ts
+++ b/frontend/lib/money/format.ts
@@ -150,7 +150,7 @@ export function formatStroops(value: bigint, opts: FormatStroopsOptions = {}): s
const fraction = scaledMagnitude % scale;
const wholeStr =
- (opts.grouped ?? false) ? whole.toLocaleString(opts.locale ?? "en-US") : whole.toString();
+ opts.grouped ?? false ? whole.toLocaleString(opts.locale ?? "en-US") : whole.toString();
const sign = negative && scaledMagnitude !== ZERO ? "-" : "";
diff --git a/frontend/src/app/[locale]/activity/page.tsx b/frontend/src/app/[locale]/activity/page.tsx
index 626f16e9..07507ada 100644
--- a/frontend/src/app/[locale]/activity/page.tsx
+++ b/frontend/src/app/[locale]/activity/page.tsx
@@ -64,16 +64,16 @@ export default function ActivityPage() {
(loan as { latestEventType?: string }).latestEventType === "LoanExtended"
? "Loan Extended"
: (loan as { latestEventType?: string }).latestEventType === "LoanRefinanced"
- ? "Loan Refinanced"
- : loan.status === "repaid"
- ? "Loan Repaid"
- : loan.status === "liquidated"
- ? "Loan Liquidated"
- : loan.status === "defaulted"
- ? "Loan Defaulted"
- : loan.status === "active"
- ? "Loan Active"
- : "Loan Request",
+ ? "Loan Refinanced"
+ : loan.status === "repaid"
+ ? "Loan Repaid"
+ : loan.status === "liquidated"
+ ? "Loan Liquidated"
+ : loan.status === "defaulted"
+ ? "Loan Defaulted"
+ : loan.status === "active"
+ ? "Loan Active"
+ : "Loan Request",
description: `Loan #${loan.id} — ${loan.currency}`,
amount: `${loan.status === "repaid" ? "+" : "-"}${formatCurrency(loan.amount)}`,
timestamp: new Date(loan.createdAt).toISOString(),
@@ -84,7 +84,10 @@ export default function ActivityPage() {
const remittanceEvents: ActivityItem[] = remittances.map((remittance) => ({
id: `remittance-${remittance.id}`,
type: "Remittance",
- description: `To ${remittance.recipientAddress.slice(0, 6)}...${remittance.recipientAddress.slice(-4)}`,
+ description: `To ${remittance.recipientAddress.slice(
+ 0,
+ 6,
+ )}...${remittance.recipientAddress.slice(-4)}`,
amount: `-${formatCurrency(remittance.amount)}`,
timestamp: new Date(remittance.createdAt).toISOString(),
status: remittance.status,
@@ -226,10 +229,10 @@ export default function ActivityPage() {
item.status === "completed" || item.status === "repaid"
? "bg-green-50 dark:bg-green-500/10"
: item.status === "failed" ||
- item.status === "defaulted" ||
- item.status === "liquidated"
- ? "bg-red-50 dark:bg-red-500/10"
- : "bg-indigo-50 dark:bg-indigo-500/10"
+ item.status === "defaulted" ||
+ item.status === "liquidated"
+ ? "bg-red-50 dark:bg-red-500/10"
+ : "bg-indigo-50 dark:bg-indigo-500/10"
}`}
aria-hidden="true"
>
diff --git a/frontend/src/app/[locale]/lend/LendPageClient.tsx b/frontend/src/app/[locale]/lend/LendPageClient.tsx
index 455492d5..825b05dd 100644
--- a/frontend/src/app/[locale]/lend/LendPageClient.tsx
+++ b/frontend/src/app/[locale]/lend/LendPageClient.tsx
@@ -195,19 +195,19 @@ export function LendPageClient() {
sseStatus === "connected"
? "bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-400"
: sseStatus === "connecting"
- ? "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"
- : sseStatus === "polling"
- ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
- : "bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400"
+ ? "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"
+ : sseStatus === "polling"
+ ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
+ : "bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400"
}`}
title={
sseStatus === "connected"
? "Live pool updates connected"
: sseStatus === "connecting"
- ? "Connecting to live updates…"
- : sseStatus === "polling"
- ? "Live updates dropped — polling while reconnecting"
- : "Live updates disconnected — retrying"
+ ? "Connecting to live updates…"
+ : sseStatus === "polling"
+ ? "Live updates dropped — polling while reconnecting"
+ : "Live updates disconnected — retrying"
}
>
{sseStatus === "connected" ? (
@@ -218,10 +218,10 @@ export function LendPageClient() {
{sseStatus === "connected"
? "Live"
: sseStatus === "connecting"
- ? "Connecting…"
- : sseStatus === "polling"
- ? "Reconnecting…"
- : "Offline"}
+ ? "Connecting…"
+ : sseStatus === "polling"
+ ? "Reconnecting…"
+ : "Offline"}
)}
diff --git a/frontend/src/app/[locale]/loans/LoansPageClient.tsx b/frontend/src/app/[locale]/loans/LoansPageClient.tsx
index 4d18346c..bd902f40 100644
--- a/frontend/src/app/[locale]/loans/LoansPageClient.tsx
+++ b/frontend/src/app/[locale]/loans/LoansPageClient.tsx
@@ -71,8 +71,8 @@ export function LoansPageClient() {
overdueCount === 0
? t("health.strong")
: overdueCount <= 2
- ? t("health.watch")
- : t("health.atRisk");
+ ? t("health.watch")
+ : t("health.atRisk");
if (isLoading) {
return ;
diff --git a/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx b/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
index ee8cf095..57b43e9e 100644
--- a/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
+++ b/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
@@ -142,10 +142,10 @@ export function LoanDetailsPageClient() {
realtimeStatus === "connected"
? "bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-400"
: realtimeStatus === "polling"
- ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
- : realtimeStatus === "disconnected"
- ? "bg-red-50 text-red-700 dark:bg-red-500/10 dark:text-red-300"
- : "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300"
+ ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
+ : realtimeStatus === "disconnected"
+ ? "bg-red-50 text-red-700 dark:bg-red-500/10 dark:text-red-300"
+ : "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300"
}`}
>
{realtimeStatus === "connected" ? (
@@ -156,10 +156,10 @@ export function LoanDetailsPageClient() {
{realtimeStatus === "connected"
? "Live loan updates"
: realtimeStatus === "polling"
- ? "Polling while reconnecting"
- : realtimeStatus === "disconnected"
- ? "Realtime temporarily unavailable"
- : "Connecting to live updates"}
+ ? "Polling while reconnecting"
+ : realtimeStatus === "disconnected"
+ ? "Realtime temporarily unavailable"
+ : "Connecting to live updates"}
{daysRemaining <= 0
? "Overdue"
: daysRemaining === 1
- ? "Due tomorrow"
- : `${daysRemaining} days`}
+ ? "Due tomorrow"
+ : `${daysRemaining} days`}
{nextDeadline && (
@@ -398,10 +398,10 @@ export function LoanDetailsPageClient() {
{loan.status === "liquidated"
? "Collateral was liquidated after the position fell below the collateral threshold."
: loan.status === "defaulted"
- ? "Collateral has been seized."
- : loan.status === "repaid"
- ? "Collateral released — loan fully repaid."
- : "Collateral is held in escrow for the duration of this loan."}
+ ? "Collateral has been seized."
+ : loan.status === "repaid"
+ ? "Collateral released — loan fully repaid."
+ : "Collateral is held in escrow for the duration of this loan."}
diff --git a/frontend/src/app/[locale]/page.tsx b/frontend/src/app/[locale]/page.tsx
index d408dd40..d748dc1d 100644
--- a/frontend/src/app/[locale]/page.tsx
+++ b/frontend/src/app/[locale]/page.tsx
@@ -217,8 +217,8 @@ export default function Home() {
l.status === "active"
? "Loan Active"
: l.status === "repaid"
- ? "Loan Repaid"
- : "Loan Request",
+ ? "Loan Repaid"
+ : "Loan Request",
desc: `Loan #${l.id} — ${formatCurrency(l.amount)}`,
amount: l.status === "repaid" ? `+${formatCurrency(l.amount)}` : formatCurrency(l.amount),
time: new Date(l.createdAt).toLocaleDateString(),
diff --git a/frontend/src/app/[locale]/settings/page.tsx b/frontend/src/app/[locale]/settings/page.tsx
index 57d6c47b..da27f195 100644
--- a/frontend/src/app/[locale]/settings/page.tsx
+++ b/frontend/src/app/[locale]/settings/page.tsx
@@ -469,8 +469,8 @@ function NotificationsSection() {
{updateNotificationPreferences.isPending
? "Saving..."
: saved
- ? "Saved!"
- : "Save Preferences"}
+ ? "Saved!"
+ : "Save Preferences"}
diff --git a/frontend/src/app/[locale]/wallet/page.tsx b/frontend/src/app/[locale]/wallet/page.tsx
index f6386772..12176a4e 100644
--- a/frontend/src/app/[locale]/wallet/page.tsx
+++ b/frontend/src/app/[locale]/wallet/page.tsx
@@ -123,7 +123,7 @@ function useHorizonPayments(address: string, horizonUrl: string, cursor: string
return {
records,
nextCursor:
- records.length === TRANSACTIONS_PER_PAGE ? (lastRecord?.paging_token ?? null) : null,
+ records.length === TRANSACTIONS_PER_PAGE ? lastRecord?.paging_token ?? null : null,
};
},
staleTime: 30_000,
@@ -190,7 +190,7 @@ function BalancesCard({ address, horizonUrl }: { address: string; horizonUrl: st
} = useHorizonBalances(address, horizonUrl);
function assetLabel(b: HorizonBalance): string {
- return b.asset_type === "native" ? "XLM" : (b.asset_code ?? "Unknown");
+ return b.asset_type === "native" ? "XLM" : b.asset_code ?? "Unknown";
}
function formatBalance(b: HorizonBalance): string {
@@ -314,14 +314,14 @@ function TransactionHistoryCard({
function paymentAmount(p: HorizonPayment): string {
if (!p.amount) return "—";
- const asset = p.asset_type === "native" ? "XLM" : (p.asset_code ?? "");
+ const asset = p.asset_type === "native" ? "XLM" : p.asset_code ?? "";
return `${parseFloat(p.amount).toLocaleString("en-US", { maximumFractionDigits: 7 })} ${asset}`;
}
function exportCsv() {
const today = new Date().toISOString().split("T")[0];
const rows = payments.map((p) => {
- const asset = p.asset_type === "native" ? "XLM" : (p.asset_code ?? "");
+ const asset = p.asset_type === "native" ? "XLM" : p.asset_code ?? "";
return {
date: p.created_at,
type: paymentLabel(p),
diff --git a/frontend/src/app/components/borrower/ActiveLoansTracker.tsx b/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
index f9c96dd3..70a99910 100644
--- a/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
+++ b/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
@@ -38,8 +38,8 @@ export function ActiveLoansTracker({ borrowerAddress }: { borrowerAddress: strin
filter === "overdue"
? loans.filter((l) => l.status === "active" && new Date(l.nextPaymentDeadline) < now)
: filter === "active"
- ? loans.filter((l) => l.status === "active")
- : loans;
+ ? loans.filter((l) => l.status === "active")
+ : loans;
const tabCounts: Record = {
active: loans.filter((l) => l.status === "active").length,
diff --git a/frontend/src/app/components/borrower/LoanCard.tsx b/frontend/src/app/components/borrower/LoanCard.tsx
index f92ec65d..d991470e 100644
--- a/frontend/src/app/components/borrower/LoanCard.tsx
+++ b/frontend/src/app/components/borrower/LoanCard.tsx
@@ -34,19 +34,19 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
label: isLiquidated
? "Liquidated"
: isDefaulted
- ? "Defaulted"
- : isOverdue
- ? "Overdue"
- : isUrgent
- ? "Due Soon"
- : "On Track",
+ ? "Defaulted"
+ : isOverdue
+ ? "Overdue"
+ : isUrgent
+ ? "Due Soon"
+ : "On Track",
className: isTerminalDistressed
? "bg-red-900 text-white"
: isOverdue
- ? "bg-red-100 text-red-800"
- : isUrgent
- ? "bg-yellow-100 text-yellow-800"
- : "bg-green-100 text-green-800",
+ ? "bg-red-100 text-red-800"
+ : isUrgent
+ ? "bg-yellow-100 text-yellow-800"
+ : "bg-green-100 text-green-800",
}
: null;
@@ -54,31 +54,31 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
const deadlineBg = isTerminalDistressed
? "bg-red-900/20"
: isOverdue
- ? "bg-red-50"
- : isUrgent
- ? "bg-yellow-50"
- : "bg-gray-50";
+ ? "bg-red-50"
+ : isUrgent
+ ? "bg-yellow-50"
+ : "bg-gray-50";
const deadlineTextColor = isTerminalDistressed
? "text-red-900"
: isOverdue
- ? "text-red-600"
- : isUrgent
- ? "text-yellow-600"
- : "text-gray-900";
+ ? "text-red-600"
+ : isUrgent
+ ? "text-yellow-600"
+ : "text-gray-900";
const deadlineSubColor = isTerminalDistressed
? "text-red-700"
: isOverdue
- ? "text-red-600"
- : isUrgent
- ? "text-yellow-600"
- : "text-gray-600";
+ ? "text-red-600"
+ : isUrgent
+ ? "text-yellow-600"
+ : "text-gray-600";
const deadlineLabel = isLiquidated
? "Collateral was liquidated"
: isDefaulted
- ? "Contact support to recover"
- : isOverdue
- ? `${Math.abs(daysUntil)} days overdue`
- : `${daysUntil} days remaining`;
+ ? "Contact support to recover"
+ : isOverdue
+ ? `${Math.abs(daysUntil)} days overdue`
+ : `${daysUntil} days remaining`;
// ── Progress (detailed only) ───────────────────────────────────────────────
const totalForProgress = loan.principal + loan.accruedInterest;
@@ -150,7 +150,9 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
Next Payment
{formatDate(loan.nextPaymentDeadline)}
diff --git a/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx b/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
index c6862d79..aa074e43 100644
--- a/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
+++ b/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
@@ -215,8 +215,8 @@ export function FinancialPerformanceDashboard({
// ── Derived display data ──
const displayCreditScoreData = useMockData
? generateMockCreditScoreData()
- : (creditScoreData ?? []);
- const displayYieldData = useMockData ? generateMockYieldData() : (yieldData ?? []);
+ : creditScoreData ?? [];
+ const displayYieldData = useMockData ? generateMockYieldData() : yieldData ?? [];
const displayLoanStats = useMemo(() => {
if (useMockData) return generateMockLoanStats();
@@ -302,8 +302,8 @@ export function FinancialPerformanceDashboard({
{userType === "both"
? "credit score and yield"
: userType === "borrower"
- ? "credit score"
- : "yield"}{" "}
+ ? "credit score"
+ : "yield"}{" "}
performance over time
@@ -354,7 +354,9 @@ export function FinancialPerformanceDashboard({
@@ -417,7 +419,11 @@ export function FinancialPerformanceDashboard({
value={fmt(displayDepositorStats.currentValue)}
sub={
displayDepositorStats.depositAmount > 0
- ? `+${(((displayDepositorStats.currentValue - displayDepositorStats.depositAmount) / displayDepositorStats.depositAmount) * 100).toFixed(2)}% growth`
+ ? `+${(
+ ((displayDepositorStats.currentValue - displayDepositorStats.depositAmount) /
+ displayDepositorStats.depositAmount) *
+ 100
+ ).toFixed(2)}% growth`
: undefined
}
colorClass="bg-blue-50 text-blue-900 dark:bg-blue-950/30 dark:text-blue-200"
diff --git a/frontend/src/app/components/global_ui/Header.tsx b/frontend/src/app/components/global_ui/Header.tsx
index 3b8fa256..7ebb5343 100644
--- a/frontend/src/app/components/global_ui/Header.tsx
+++ b/frontend/src/app/components/global_ui/Header.tsx
@@ -239,10 +239,10 @@ export function Header({ onMenuClick, className }: HeaderProps) {
const profileLabel = user?.email
? user.email
: user?.walletAddress
- ? truncateWalletAddress(user.walletAddress)
- : walletAddress
- ? truncateWalletAddress(walletAddress)
- : "Connect Wallet";
+ ? truncateWalletAddress(user.walletAddress)
+ : walletAddress
+ ? truncateWalletAddress(walletAddress)
+ : "Connect Wallet";
return (
diff --git a/frontend/src/app/components/loan-wizard/WizardStepper.tsx b/frontend/src/app/components/loan-wizard/WizardStepper.tsx
index f92c3ff3..85b9d311 100644
--- a/frontend/src/app/components/loan-wizard/WizardStepper.tsx
+++ b/frontend/src/app/components/loan-wizard/WizardStepper.tsx
@@ -98,8 +98,8 @@ export function WizardStepper({ steps, currentStep, onStepSelect }: WizardSteppe
isCurrent
? "text-indigo-600 dark:text-indigo-400"
: isCompleted
- ? "text-zinc-700 dark:text-zinc-300"
- : "text-zinc-400 dark:text-zinc-500",
+ ? "text-zinc-700 dark:text-zinc-300"
+ : "text-zinc-400 dark:text-zinc-500",
)}
>
{step.label}
diff --git a/frontend/src/app/components/loan/LoanHealth.tsx b/frontend/src/app/components/loan/LoanHealth.tsx
index 3fd1c821..430c1f61 100644
--- a/frontend/src/app/components/loan/LoanHealth.tsx
+++ b/frontend/src/app/components/loan/LoanHealth.tsx
@@ -99,16 +99,16 @@ export function LoanHealth({ loan, isLoading, isError, topUpHref, labels }: Loan
state === "atRisk"
? "border-red-200 bg-red-50 text-red-700 dark:border-red-900/60 dark:bg-red-950/30 dark:text-red-200"
: state === "watch"
- ? "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-200"
- : "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/60 dark:bg-emerald-950/30 dark:text-emerald-200";
+ ? "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-200"
+ : "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/60 dark:bg-emerald-950/30 dark:text-emerald-200";
const barTone =
state === "atRisk" ? "bg-red-500" : state === "watch" ? "bg-amber-500" : "bg-emerald-500";
const source =
loan?.healthSource === "contract"
? labels.sourceContract
: loan?.healthSource === "backend" || backendRatio || backendHealthFactor
- ? labels.sourceBackend
- : labels.sourceDerived;
+ ? labels.sourceBackend
+ : labels.sourceDerived;
const barWidth = `${Math.min(100, Math.max(6, (ratio / (threshold + 0.5)) * 100))}%`;
return (
diff --git a/frontend/src/app/components/providers/WalletProvider.tsx b/frontend/src/app/components/providers/WalletProvider.tsx
index 9eeb192b..1a4536bd 100644
--- a/frontend/src/app/components/providers/WalletProvider.tsx
+++ b/frontend/src/app/components/providers/WalletProvider.tsx
@@ -98,7 +98,7 @@ function getFallbackHorizonUrl(networkName: string | undefined): string {
function mapBalances(balances: HorizonBalance[] | undefined): TokenBalance[] {
return (balances ?? []).map((balance) => ({
- symbol: balance.asset_type === "native" ? "XLM" : (balance.asset_code ?? "ASSET"),
+ symbol: balance.asset_type === "native" ? "XLM" : balance.asset_code ?? "ASSET",
amount: balance.balance,
usdValue: null,
}));
@@ -181,8 +181,8 @@ export function WalletProvider({ children }: WalletProviderProps) {
const networkResult: FreighterNetworkResult = api.getNetworkDetails
? await api.getNetworkDetails()
: api.getNetwork
- ? await api.getNetwork()
- : { error: "Network info not available." };
+ ? await api.getNetwork()
+ : { error: "Network info not available." };
if (networkResult.error) {
throw new Error(normalizeWalletError(networkResult.error));
diff --git a/frontend/src/app/components/ui.tsx b/frontend/src/app/components/ui.tsx
index 489fdddd..540c805b 100644
--- a/frontend/src/app/components/ui.tsx
+++ b/frontend/src/app/components/ui.tsx
@@ -1 +1 @@
-export { COPY_FEEDBACK_RESET_MS } from './ui/CopyButton';
+export { COPY_FEEDBACK_RESET_MS } from "./ui/CopyButton";
diff --git a/frontend/src/app/components/ui/OperationProgress.tsx b/frontend/src/app/components/ui/OperationProgress.tsx
index 2df7d230..09eb4dca 100644
--- a/frontend/src/app/components/ui/OperationProgress.tsx
+++ b/frontend/src/app/components/ui/OperationProgress.tsx
@@ -88,7 +88,10 @@ export function OperationProgress({ transaction, type = "generic" }: OperationPr
href={`https://stellar.expert/explorer/testnet/tx/${txHash}`}
target="_blank"
rel="noopener noreferrer"
- aria-label={`View transaction ${txHash.slice(0, 8)}… on Stellar Explorer (opens in new tab)`}
+ aria-label={`View transaction ${txHash.slice(
+ 0,
+ 8,
+ )}… on Stellar Explorer (opens in new tab)`}
className="text-xs text-blue-600 hover:text-blue-700 dark:text-blue-400 hover:underline flex items-center gap-1"
>
diff --git a/frontend/src/app/components/ui/Toaster.tsx b/frontend/src/app/components/ui/Toaster.tsx
index adeab47d..52e9f45b 100644
--- a/frontend/src/app/components/ui/Toaster.tsx
+++ b/frontend/src/app/components/ui/Toaster.tsx
@@ -57,7 +57,9 @@ function ToastCard({ toast }: { toast: ToastItem }) {
animate={{ opacity: 1, x: 0, scale: 1 }}
exit={{ opacity: 0, x: 20, scale: 0.96 }}
transition={{ duration: 0.2, ease: "easeOut" }}
- className={`w-full rounded-xl border p-4 shadow-lg shadow-zinc-900/5 ${getToastStyles(toast.type)}`}
+ className={`w-full rounded-xl border p-4 shadow-lg shadow-zinc-900/5 ${getToastStyles(
+ toast.type,
+ )}`}
role="alert"
>
diff --git a/frontend/src/app/hooks/useApi.ts b/frontend/src/app/hooks/useApi.ts
index 5f7509f0..87ca8038 100644
--- a/frontend/src/app/hooks/useApi.ts
+++ b/frontend/src/app/hooks/useApi.ts
@@ -797,8 +797,8 @@ export function useLiquidatableLoans(
const loans = Array.isArray(response)
? response
: "loans" in response
- ? response.loans
- : response.data;
+ ? response.loans
+ : response.data;
const fallbackSource = Array.isArray(response) ? undefined : response.source;
return loans.map((loan) =>
@@ -1493,8 +1493,8 @@ export function useAdminDisputes(
const disputes = Array.isArray(response)
? response
: "disputes" in response
- ? response.disputes
- : response.data;
+ ? response.disputes
+ : response.data;
return disputes.map(normalizeDispute);
},
diff --git a/frontend/src/app/utils/transactionFormatter.ts b/frontend/src/app/utils/transactionFormatter.ts
index 84a9898d..9aa8fe34 100644
--- a/frontend/src/app/utils/transactionFormatter.ts
+++ b/frontend/src/app/utils/transactionFormatter.ts
@@ -186,7 +186,10 @@ export function formatRemittanceSend(params: {
const operations: TransactionOperation[] = [
{
type: "Send Remittance",
- description: `You are sending ${params.amount} ${params.token} to ${params.recipient.slice(0, 8)}...${params.recipient.slice(-6)}`,
+ description: `You are sending ${params.amount} ${params.token} to ${params.recipient.slice(
+ 0,
+ 8,
+ )}...${params.recipient.slice(-6)}`,
amount: params.amount.toString(),
token: params.token,
details: {
From 336bad4c0f99b560328796dd7856b7d477233fe4 Mon Sep 17 00:00:00 2001
From: Ogunmodede Joel Taiwo
Date: Mon, 10 Aug 2026 02:45:34 +0100
Subject: [PATCH 3/9] style(frontend): enforce LF endOfLine in
frontend/.prettierrc
---
frontend/.prettierrc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frontend/.prettierrc b/frontend/.prettierrc
index f47f903b..39a725eb 100644
--- a/frontend/.prettierrc
+++ b/frontend/.prettierrc
@@ -4,5 +4,5 @@
"trailingComma": "all",
"tabWidth": 2,
"printWidth": 100,
- "endOfLine": "auto"
+ "endOfLine": "lf"
}
From 98c4fb05501efd8dbbdfe206165c44a82d7ad5b0 Mon Sep 17 00:00:00 2001
From: Ogunmodede Joel Taiwo
Date: Mon, 10 Aug 2026 02:48:29 +0100
Subject: [PATCH 4/9] build: add .gitattributes to enforce LF line endings
across environments
---
.gitattributes | 8 ++++++++
1 file changed, 8 insertions(+)
create mode 100644 .gitattributes
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..fa27750c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,8 @@
+* text=auto eol=lf
+*.ts text eol=lf
+*.tsx text eol=lf
+*.js text eol=lf
+*.jsx text eol=lf
+*.json text eol=lf
+*.md text eol=lf
+*.css text eol=lf
From d96ef59fc5d133bf11038820bbd362771717778d Mon Sep 17 00:00:00 2001
From: Ogunmodede Joel Taiwo
Date: Mon, 10 Aug 2026 03:05:06 +0100
Subject: [PATCH 5/9] revert(frontend): restore frontend files to original main
state
---
frontend/.prettierrc | 2 +-
frontend/lib/money/format.ts | 2 +-
frontend/src/app/[locale]/activity/page.tsx | 33 +++++------
.../src/app/[locale]/lend/LendPageClient.tsx | 24 ++++----
.../app/[locale]/loans/LoansPageClient.tsx | 4 +-
.../loans/[loanId]/LoanDetailsPageClient.tsx | 32 +++++------
frontend/src/app/[locale]/page.tsx | 4 +-
frontend/src/app/[locale]/settings/page.tsx | 4 +-
frontend/src/app/[locale]/wallet/page.tsx | 8 +--
.../borrower/ActiveLoansTracker.tsx | 4 +-
.../src/app/components/borrower/LoanCard.tsx | 56 +++++++++----------
.../FinancialPerformanceDashboard.tsx | 18 ++----
.../src/app/components/global_ui/Header.tsx | 8 +--
.../loan-wizard/StepAmountAsset.tsx | 4 +-
.../components/loan-wizard/WizardStepper.tsx | 4 +-
.../src/app/components/loan/LoanHealth.tsx | 8 +--
.../components/providers/WalletProvider.tsx | 6 +-
frontend/src/app/components/ui.tsx | 2 +-
.../app/components/ui/OperationProgress.tsx | 5 +-
frontend/src/app/components/ui/Toaster.tsx | 4 +-
frontend/src/app/hooks/useApi.ts | 8 +--
.../src/app/utils/transactionFormatter.ts | 5 +-
22 files changed, 112 insertions(+), 133 deletions(-)
diff --git a/frontend/.prettierrc b/frontend/.prettierrc
index 39a725eb..f47f903b 100644
--- a/frontend/.prettierrc
+++ b/frontend/.prettierrc
@@ -4,5 +4,5 @@
"trailingComma": "all",
"tabWidth": 2,
"printWidth": 100,
- "endOfLine": "lf"
+ "endOfLine": "auto"
}
diff --git a/frontend/lib/money/format.ts b/frontend/lib/money/format.ts
index c1c57f34..24a6594a 100644
--- a/frontend/lib/money/format.ts
+++ b/frontend/lib/money/format.ts
@@ -150,7 +150,7 @@ export function formatStroops(value: bigint, opts: FormatStroopsOptions = {}): s
const fraction = scaledMagnitude % scale;
const wholeStr =
- opts.grouped ?? false ? whole.toLocaleString(opts.locale ?? "en-US") : whole.toString();
+ (opts.grouped ?? false) ? whole.toLocaleString(opts.locale ?? "en-US") : whole.toString();
const sign = negative && scaledMagnitude !== ZERO ? "-" : "";
diff --git a/frontend/src/app/[locale]/activity/page.tsx b/frontend/src/app/[locale]/activity/page.tsx
index 07507ada..626f16e9 100644
--- a/frontend/src/app/[locale]/activity/page.tsx
+++ b/frontend/src/app/[locale]/activity/page.tsx
@@ -64,16 +64,16 @@ export default function ActivityPage() {
(loan as { latestEventType?: string }).latestEventType === "LoanExtended"
? "Loan Extended"
: (loan as { latestEventType?: string }).latestEventType === "LoanRefinanced"
- ? "Loan Refinanced"
- : loan.status === "repaid"
- ? "Loan Repaid"
- : loan.status === "liquidated"
- ? "Loan Liquidated"
- : loan.status === "defaulted"
- ? "Loan Defaulted"
- : loan.status === "active"
- ? "Loan Active"
- : "Loan Request",
+ ? "Loan Refinanced"
+ : loan.status === "repaid"
+ ? "Loan Repaid"
+ : loan.status === "liquidated"
+ ? "Loan Liquidated"
+ : loan.status === "defaulted"
+ ? "Loan Defaulted"
+ : loan.status === "active"
+ ? "Loan Active"
+ : "Loan Request",
description: `Loan #${loan.id} — ${loan.currency}`,
amount: `${loan.status === "repaid" ? "+" : "-"}${formatCurrency(loan.amount)}`,
timestamp: new Date(loan.createdAt).toISOString(),
@@ -84,10 +84,7 @@ export default function ActivityPage() {
const remittanceEvents: ActivityItem[] = remittances.map((remittance) => ({
id: `remittance-${remittance.id}`,
type: "Remittance",
- description: `To ${remittance.recipientAddress.slice(
- 0,
- 6,
- )}...${remittance.recipientAddress.slice(-4)}`,
+ description: `To ${remittance.recipientAddress.slice(0, 6)}...${remittance.recipientAddress.slice(-4)}`,
amount: `-${formatCurrency(remittance.amount)}`,
timestamp: new Date(remittance.createdAt).toISOString(),
status: remittance.status,
@@ -229,10 +226,10 @@ export default function ActivityPage() {
item.status === "completed" || item.status === "repaid"
? "bg-green-50 dark:bg-green-500/10"
: item.status === "failed" ||
- item.status === "defaulted" ||
- item.status === "liquidated"
- ? "bg-red-50 dark:bg-red-500/10"
- : "bg-indigo-50 dark:bg-indigo-500/10"
+ item.status === "defaulted" ||
+ item.status === "liquidated"
+ ? "bg-red-50 dark:bg-red-500/10"
+ : "bg-indigo-50 dark:bg-indigo-500/10"
}`}
aria-hidden="true"
>
diff --git a/frontend/src/app/[locale]/lend/LendPageClient.tsx b/frontend/src/app/[locale]/lend/LendPageClient.tsx
index 825b05dd..455492d5 100644
--- a/frontend/src/app/[locale]/lend/LendPageClient.tsx
+++ b/frontend/src/app/[locale]/lend/LendPageClient.tsx
@@ -195,19 +195,19 @@ export function LendPageClient() {
sseStatus === "connected"
? "bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-400"
: sseStatus === "connecting"
- ? "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"
- : sseStatus === "polling"
- ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
- : "bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400"
+ ? "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"
+ : sseStatus === "polling"
+ ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
+ : "bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400"
}`}
title={
sseStatus === "connected"
? "Live pool updates connected"
: sseStatus === "connecting"
- ? "Connecting to live updates…"
- : sseStatus === "polling"
- ? "Live updates dropped — polling while reconnecting"
- : "Live updates disconnected — retrying"
+ ? "Connecting to live updates…"
+ : sseStatus === "polling"
+ ? "Live updates dropped — polling while reconnecting"
+ : "Live updates disconnected — retrying"
}
>
{sseStatus === "connected" ? (
@@ -218,10 +218,10 @@ export function LendPageClient() {
{sseStatus === "connected"
? "Live"
: sseStatus === "connecting"
- ? "Connecting…"
- : sseStatus === "polling"
- ? "Reconnecting…"
- : "Offline"}
+ ? "Connecting…"
+ : sseStatus === "polling"
+ ? "Reconnecting…"
+ : "Offline"}
)}
diff --git a/frontend/src/app/[locale]/loans/LoansPageClient.tsx b/frontend/src/app/[locale]/loans/LoansPageClient.tsx
index bd902f40..4d18346c 100644
--- a/frontend/src/app/[locale]/loans/LoansPageClient.tsx
+++ b/frontend/src/app/[locale]/loans/LoansPageClient.tsx
@@ -71,8 +71,8 @@ export function LoansPageClient() {
overdueCount === 0
? t("health.strong")
: overdueCount <= 2
- ? t("health.watch")
- : t("health.atRisk");
+ ? t("health.watch")
+ : t("health.atRisk");
if (isLoading) {
return ;
diff --git a/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx b/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
index 57b43e9e..ee8cf095 100644
--- a/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
+++ b/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
@@ -142,10 +142,10 @@ export function LoanDetailsPageClient() {
realtimeStatus === "connected"
? "bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-400"
: realtimeStatus === "polling"
- ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
- : realtimeStatus === "disconnected"
- ? "bg-red-50 text-red-700 dark:bg-red-500/10 dark:text-red-300"
- : "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300"
+ ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
+ : realtimeStatus === "disconnected"
+ ? "bg-red-50 text-red-700 dark:bg-red-500/10 dark:text-red-300"
+ : "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300"
}`}
>
{realtimeStatus === "connected" ? (
@@ -156,10 +156,10 @@ export function LoanDetailsPageClient() {
{realtimeStatus === "connected"
? "Live loan updates"
: realtimeStatus === "polling"
- ? "Polling while reconnecting"
- : realtimeStatus === "disconnected"
- ? "Realtime temporarily unavailable"
- : "Connecting to live updates"}
+ ? "Polling while reconnecting"
+ : realtimeStatus === "disconnected"
+ ? "Realtime temporarily unavailable"
+ : "Connecting to live updates"}
{daysRemaining <= 0
? "Overdue"
: daysRemaining === 1
- ? "Due tomorrow"
- : `${daysRemaining} days`}
+ ? "Due tomorrow"
+ : `${daysRemaining} days`}
{nextDeadline && (
@@ -398,10 +398,10 @@ export function LoanDetailsPageClient() {
{loan.status === "liquidated"
? "Collateral was liquidated after the position fell below the collateral threshold."
: loan.status === "defaulted"
- ? "Collateral has been seized."
- : loan.status === "repaid"
- ? "Collateral released — loan fully repaid."
- : "Collateral is held in escrow for the duration of this loan."}
+ ? "Collateral has been seized."
+ : loan.status === "repaid"
+ ? "Collateral released — loan fully repaid."
+ : "Collateral is held in escrow for the duration of this loan."}
diff --git a/frontend/src/app/[locale]/page.tsx b/frontend/src/app/[locale]/page.tsx
index d748dc1d..d408dd40 100644
--- a/frontend/src/app/[locale]/page.tsx
+++ b/frontend/src/app/[locale]/page.tsx
@@ -217,8 +217,8 @@ export default function Home() {
l.status === "active"
? "Loan Active"
: l.status === "repaid"
- ? "Loan Repaid"
- : "Loan Request",
+ ? "Loan Repaid"
+ : "Loan Request",
desc: `Loan #${l.id} — ${formatCurrency(l.amount)}`,
amount: l.status === "repaid" ? `+${formatCurrency(l.amount)}` : formatCurrency(l.amount),
time: new Date(l.createdAt).toLocaleDateString(),
diff --git a/frontend/src/app/[locale]/settings/page.tsx b/frontend/src/app/[locale]/settings/page.tsx
index da27f195..57d6c47b 100644
--- a/frontend/src/app/[locale]/settings/page.tsx
+++ b/frontend/src/app/[locale]/settings/page.tsx
@@ -469,8 +469,8 @@ function NotificationsSection() {
{updateNotificationPreferences.isPending
? "Saving..."
: saved
- ? "Saved!"
- : "Save Preferences"}
+ ? "Saved!"
+ : "Save Preferences"}
diff --git a/frontend/src/app/[locale]/wallet/page.tsx b/frontend/src/app/[locale]/wallet/page.tsx
index 12176a4e..f6386772 100644
--- a/frontend/src/app/[locale]/wallet/page.tsx
+++ b/frontend/src/app/[locale]/wallet/page.tsx
@@ -123,7 +123,7 @@ function useHorizonPayments(address: string, horizonUrl: string, cursor: string
return {
records,
nextCursor:
- records.length === TRANSACTIONS_PER_PAGE ? lastRecord?.paging_token ?? null : null,
+ records.length === TRANSACTIONS_PER_PAGE ? (lastRecord?.paging_token ?? null) : null,
};
},
staleTime: 30_000,
@@ -190,7 +190,7 @@ function BalancesCard({ address, horizonUrl }: { address: string; horizonUrl: st
} = useHorizonBalances(address, horizonUrl);
function assetLabel(b: HorizonBalance): string {
- return b.asset_type === "native" ? "XLM" : b.asset_code ?? "Unknown";
+ return b.asset_type === "native" ? "XLM" : (b.asset_code ?? "Unknown");
}
function formatBalance(b: HorizonBalance): string {
@@ -314,14 +314,14 @@ function TransactionHistoryCard({
function paymentAmount(p: HorizonPayment): string {
if (!p.amount) return "—";
- const asset = p.asset_type === "native" ? "XLM" : p.asset_code ?? "";
+ const asset = p.asset_type === "native" ? "XLM" : (p.asset_code ?? "");
return `${parseFloat(p.amount).toLocaleString("en-US", { maximumFractionDigits: 7 })} ${asset}`;
}
function exportCsv() {
const today = new Date().toISOString().split("T")[0];
const rows = payments.map((p) => {
- const asset = p.asset_type === "native" ? "XLM" : p.asset_code ?? "";
+ const asset = p.asset_type === "native" ? "XLM" : (p.asset_code ?? "");
return {
date: p.created_at,
type: paymentLabel(p),
diff --git a/frontend/src/app/components/borrower/ActiveLoansTracker.tsx b/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
index 70a99910..f9c96dd3 100644
--- a/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
+++ b/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
@@ -38,8 +38,8 @@ export function ActiveLoansTracker({ borrowerAddress }: { borrowerAddress: strin
filter === "overdue"
? loans.filter((l) => l.status === "active" && new Date(l.nextPaymentDeadline) < now)
: filter === "active"
- ? loans.filter((l) => l.status === "active")
- : loans;
+ ? loans.filter((l) => l.status === "active")
+ : loans;
const tabCounts: Record = {
active: loans.filter((l) => l.status === "active").length,
diff --git a/frontend/src/app/components/borrower/LoanCard.tsx b/frontend/src/app/components/borrower/LoanCard.tsx
index d991470e..f92ec65d 100644
--- a/frontend/src/app/components/borrower/LoanCard.tsx
+++ b/frontend/src/app/components/borrower/LoanCard.tsx
@@ -34,19 +34,19 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
label: isLiquidated
? "Liquidated"
: isDefaulted
- ? "Defaulted"
- : isOverdue
- ? "Overdue"
- : isUrgent
- ? "Due Soon"
- : "On Track",
+ ? "Defaulted"
+ : isOverdue
+ ? "Overdue"
+ : isUrgent
+ ? "Due Soon"
+ : "On Track",
className: isTerminalDistressed
? "bg-red-900 text-white"
: isOverdue
- ? "bg-red-100 text-red-800"
- : isUrgent
- ? "bg-yellow-100 text-yellow-800"
- : "bg-green-100 text-green-800",
+ ? "bg-red-100 text-red-800"
+ : isUrgent
+ ? "bg-yellow-100 text-yellow-800"
+ : "bg-green-100 text-green-800",
}
: null;
@@ -54,31 +54,31 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
const deadlineBg = isTerminalDistressed
? "bg-red-900/20"
: isOverdue
- ? "bg-red-50"
- : isUrgent
- ? "bg-yellow-50"
- : "bg-gray-50";
+ ? "bg-red-50"
+ : isUrgent
+ ? "bg-yellow-50"
+ : "bg-gray-50";
const deadlineTextColor = isTerminalDistressed
? "text-red-900"
: isOverdue
- ? "text-red-600"
- : isUrgent
- ? "text-yellow-600"
- : "text-gray-900";
+ ? "text-red-600"
+ : isUrgent
+ ? "text-yellow-600"
+ : "text-gray-900";
const deadlineSubColor = isTerminalDistressed
? "text-red-700"
: isOverdue
- ? "text-red-600"
- : isUrgent
- ? "text-yellow-600"
- : "text-gray-600";
+ ? "text-red-600"
+ : isUrgent
+ ? "text-yellow-600"
+ : "text-gray-600";
const deadlineLabel = isLiquidated
? "Collateral was liquidated"
: isDefaulted
- ? "Contact support to recover"
- : isOverdue
- ? `${Math.abs(daysUntil)} days overdue`
- : `${daysUntil} days remaining`;
+ ? "Contact support to recover"
+ : isOverdue
+ ? `${Math.abs(daysUntil)} days overdue`
+ : `${daysUntil} days remaining`;
// ── Progress (detailed only) ───────────────────────────────────────────────
const totalForProgress = loan.principal + loan.accruedInterest;
@@ -150,9 +150,7 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
Next Payment
{formatDate(loan.nextPaymentDeadline)}
diff --git a/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx b/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
index aa074e43..c6862d79 100644
--- a/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
+++ b/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
@@ -215,8 +215,8 @@ export function FinancialPerformanceDashboard({
// ── Derived display data ──
const displayCreditScoreData = useMockData
? generateMockCreditScoreData()
- : creditScoreData ?? [];
- const displayYieldData = useMockData ? generateMockYieldData() : yieldData ?? [];
+ : (creditScoreData ?? []);
+ const displayYieldData = useMockData ? generateMockYieldData() : (yieldData ?? []);
const displayLoanStats = useMemo(() => {
if (useMockData) return generateMockLoanStats();
@@ -302,8 +302,8 @@ export function FinancialPerformanceDashboard({
{userType === "both"
? "credit score and yield"
: userType === "borrower"
- ? "credit score"
- : "yield"}{" "}
+ ? "credit score"
+ : "yield"}{" "}
performance over time
@@ -354,9 +354,7 @@ export function FinancialPerformanceDashboard({
@@ -419,11 +417,7 @@ export function FinancialPerformanceDashboard({
value={fmt(displayDepositorStats.currentValue)}
sub={
displayDepositorStats.depositAmount > 0
- ? `+${(
- ((displayDepositorStats.currentValue - displayDepositorStats.depositAmount) /
- displayDepositorStats.depositAmount) *
- 100
- ).toFixed(2)}% growth`
+ ? `+${(((displayDepositorStats.currentValue - displayDepositorStats.depositAmount) / displayDepositorStats.depositAmount) * 100).toFixed(2)}% growth`
: undefined
}
colorClass="bg-blue-50 text-blue-900 dark:bg-blue-950/30 dark:text-blue-200"
diff --git a/frontend/src/app/components/global_ui/Header.tsx b/frontend/src/app/components/global_ui/Header.tsx
index 7ebb5343..3b8fa256 100644
--- a/frontend/src/app/components/global_ui/Header.tsx
+++ b/frontend/src/app/components/global_ui/Header.tsx
@@ -239,10 +239,10 @@ export function Header({ onMenuClick, className }: HeaderProps) {
const profileLabel = user?.email
? user.email
: user?.walletAddress
- ? truncateWalletAddress(user.walletAddress)
- : walletAddress
- ? truncateWalletAddress(walletAddress)
- : "Connect Wallet";
+ ? truncateWalletAddress(user.walletAddress)
+ : walletAddress
+ ? truncateWalletAddress(walletAddress)
+ : "Connect Wallet";
return (
diff --git a/frontend/src/app/components/loan-wizard/WizardStepper.tsx b/frontend/src/app/components/loan-wizard/WizardStepper.tsx
index 85b9d311..f92c3ff3 100644
--- a/frontend/src/app/components/loan-wizard/WizardStepper.tsx
+++ b/frontend/src/app/components/loan-wizard/WizardStepper.tsx
@@ -98,8 +98,8 @@ export function WizardStepper({ steps, currentStep, onStepSelect }: WizardSteppe
isCurrent
? "text-indigo-600 dark:text-indigo-400"
: isCompleted
- ? "text-zinc-700 dark:text-zinc-300"
- : "text-zinc-400 dark:text-zinc-500",
+ ? "text-zinc-700 dark:text-zinc-300"
+ : "text-zinc-400 dark:text-zinc-500",
)}
>
{step.label}
diff --git a/frontend/src/app/components/loan/LoanHealth.tsx b/frontend/src/app/components/loan/LoanHealth.tsx
index 430c1f61..3fd1c821 100644
--- a/frontend/src/app/components/loan/LoanHealth.tsx
+++ b/frontend/src/app/components/loan/LoanHealth.tsx
@@ -99,16 +99,16 @@ export function LoanHealth({ loan, isLoading, isError, topUpHref, labels }: Loan
state === "atRisk"
? "border-red-200 bg-red-50 text-red-700 dark:border-red-900/60 dark:bg-red-950/30 dark:text-red-200"
: state === "watch"
- ? "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-200"
- : "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/60 dark:bg-emerald-950/30 dark:text-emerald-200";
+ ? "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-200"
+ : "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/60 dark:bg-emerald-950/30 dark:text-emerald-200";
const barTone =
state === "atRisk" ? "bg-red-500" : state === "watch" ? "bg-amber-500" : "bg-emerald-500";
const source =
loan?.healthSource === "contract"
? labels.sourceContract
: loan?.healthSource === "backend" || backendRatio || backendHealthFactor
- ? labels.sourceBackend
- : labels.sourceDerived;
+ ? labels.sourceBackend
+ : labels.sourceDerived;
const barWidth = `${Math.min(100, Math.max(6, (ratio / (threshold + 0.5)) * 100))}%`;
return (
diff --git a/frontend/src/app/components/providers/WalletProvider.tsx b/frontend/src/app/components/providers/WalletProvider.tsx
index 1a4536bd..9eeb192b 100644
--- a/frontend/src/app/components/providers/WalletProvider.tsx
+++ b/frontend/src/app/components/providers/WalletProvider.tsx
@@ -98,7 +98,7 @@ function getFallbackHorizonUrl(networkName: string | undefined): string {
function mapBalances(balances: HorizonBalance[] | undefined): TokenBalance[] {
return (balances ?? []).map((balance) => ({
- symbol: balance.asset_type === "native" ? "XLM" : balance.asset_code ?? "ASSET",
+ symbol: balance.asset_type === "native" ? "XLM" : (balance.asset_code ?? "ASSET"),
amount: balance.balance,
usdValue: null,
}));
@@ -181,8 +181,8 @@ export function WalletProvider({ children }: WalletProviderProps) {
const networkResult: FreighterNetworkResult = api.getNetworkDetails
? await api.getNetworkDetails()
: api.getNetwork
- ? await api.getNetwork()
- : { error: "Network info not available." };
+ ? await api.getNetwork()
+ : { error: "Network info not available." };
if (networkResult.error) {
throw new Error(normalizeWalletError(networkResult.error));
diff --git a/frontend/src/app/components/ui.tsx b/frontend/src/app/components/ui.tsx
index 540c805b..489fdddd 100644
--- a/frontend/src/app/components/ui.tsx
+++ b/frontend/src/app/components/ui.tsx
@@ -1 +1 @@
-export { COPY_FEEDBACK_RESET_MS } from "./ui/CopyButton";
+export { COPY_FEEDBACK_RESET_MS } from './ui/CopyButton';
diff --git a/frontend/src/app/components/ui/OperationProgress.tsx b/frontend/src/app/components/ui/OperationProgress.tsx
index 09eb4dca..2df7d230 100644
--- a/frontend/src/app/components/ui/OperationProgress.tsx
+++ b/frontend/src/app/components/ui/OperationProgress.tsx
@@ -88,10 +88,7 @@ export function OperationProgress({ transaction, type = "generic" }: OperationPr
href={`https://stellar.expert/explorer/testnet/tx/${txHash}`}
target="_blank"
rel="noopener noreferrer"
- aria-label={`View transaction ${txHash.slice(
- 0,
- 8,
- )}… on Stellar Explorer (opens in new tab)`}
+ aria-label={`View transaction ${txHash.slice(0, 8)}… on Stellar Explorer (opens in new tab)`}
className="text-xs text-blue-600 hover:text-blue-700 dark:text-blue-400 hover:underline flex items-center gap-1"
>
diff --git a/frontend/src/app/components/ui/Toaster.tsx b/frontend/src/app/components/ui/Toaster.tsx
index 52e9f45b..adeab47d 100644
--- a/frontend/src/app/components/ui/Toaster.tsx
+++ b/frontend/src/app/components/ui/Toaster.tsx
@@ -57,9 +57,7 @@ function ToastCard({ toast }: { toast: ToastItem }) {
animate={{ opacity: 1, x: 0, scale: 1 }}
exit={{ opacity: 0, x: 20, scale: 0.96 }}
transition={{ duration: 0.2, ease: "easeOut" }}
- className={`w-full rounded-xl border p-4 shadow-lg shadow-zinc-900/5 ${getToastStyles(
- toast.type,
- )}`}
+ className={`w-full rounded-xl border p-4 shadow-lg shadow-zinc-900/5 ${getToastStyles(toast.type)}`}
role="alert"
>
diff --git a/frontend/src/app/hooks/useApi.ts b/frontend/src/app/hooks/useApi.ts
index 87ca8038..5f7509f0 100644
--- a/frontend/src/app/hooks/useApi.ts
+++ b/frontend/src/app/hooks/useApi.ts
@@ -797,8 +797,8 @@ export function useLiquidatableLoans(
const loans = Array.isArray(response)
? response
: "loans" in response
- ? response.loans
- : response.data;
+ ? response.loans
+ : response.data;
const fallbackSource = Array.isArray(response) ? undefined : response.source;
return loans.map((loan) =>
@@ -1493,8 +1493,8 @@ export function useAdminDisputes(
const disputes = Array.isArray(response)
? response
: "disputes" in response
- ? response.disputes
- : response.data;
+ ? response.disputes
+ : response.data;
return disputes.map(normalizeDispute);
},
diff --git a/frontend/src/app/utils/transactionFormatter.ts b/frontend/src/app/utils/transactionFormatter.ts
index 9aa8fe34..84a9898d 100644
--- a/frontend/src/app/utils/transactionFormatter.ts
+++ b/frontend/src/app/utils/transactionFormatter.ts
@@ -186,10 +186,7 @@ export function formatRemittanceSend(params: {
const operations: TransactionOperation[] = [
{
type: "Send Remittance",
- description: `You are sending ${params.amount} ${params.token} to ${params.recipient.slice(
- 0,
- 8,
- )}...${params.recipient.slice(-6)}`,
+ description: `You are sending ${params.amount} ${params.token} to ${params.recipient.slice(0, 8)}...${params.recipient.slice(-6)}`,
amount: params.amount.toString(),
token: params.token,
details: {
From 33387bb5a13729e6cacb8d26e38a9a3cbb9bfff2 Mon Sep 17 00:00:00 2001
From: Ogunmodede Joel Taiwo
Date: Mon, 10 Aug 2026 03:11:50 +0100
Subject: [PATCH 6/9] style(frontend): format all frontend files with Prettier
LF line endings
---
frontend/lib/money/format.ts | 2 +-
frontend/src/app/[locale]/activity/page.tsx | 33 ++++++-----
.../src/app/[locale]/lend/LendPageClient.tsx | 24 ++++----
.../app/[locale]/loans/LoansPageClient.tsx | 4 +-
.../loans/[loanId]/LoanDetailsPageClient.tsx | 32 +++++------
frontend/src/app/[locale]/page.tsx | 4 +-
frontend/src/app/[locale]/settings/page.tsx | 4 +-
frontend/src/app/[locale]/wallet/page.tsx | 8 +--
.../borrower/ActiveLoansTracker.tsx | 4 +-
.../src/app/components/borrower/LoanCard.tsx | 56 ++++++++++---------
.../FinancialPerformanceDashboard.tsx | 18 ++++--
.../src/app/components/global_ui/Header.tsx | 8 +--
.../loan-wizard/StepAmountAsset.tsx | 4 +-
.../components/loan-wizard/WizardStepper.tsx | 4 +-
.../src/app/components/loan/LoanHealth.tsx | 8 +--
.../components/providers/WalletProvider.tsx | 6 +-
frontend/src/app/components/ui.tsx | 2 +-
.../app/components/ui/OperationProgress.tsx | 5 +-
frontend/src/app/components/ui/Toaster.tsx | 4 +-
frontend/src/app/hooks/useApi.ts | 8 +--
.../src/app/utils/transactionFormatter.ts | 5 +-
21 files changed, 132 insertions(+), 111 deletions(-)
diff --git a/frontend/lib/money/format.ts b/frontend/lib/money/format.ts
index 24a6594a..c1c57f34 100644
--- a/frontend/lib/money/format.ts
+++ b/frontend/lib/money/format.ts
@@ -150,7 +150,7 @@ export function formatStroops(value: bigint, opts: FormatStroopsOptions = {}): s
const fraction = scaledMagnitude % scale;
const wholeStr =
- (opts.grouped ?? false) ? whole.toLocaleString(opts.locale ?? "en-US") : whole.toString();
+ opts.grouped ?? false ? whole.toLocaleString(opts.locale ?? "en-US") : whole.toString();
const sign = negative && scaledMagnitude !== ZERO ? "-" : "";
diff --git a/frontend/src/app/[locale]/activity/page.tsx b/frontend/src/app/[locale]/activity/page.tsx
index 626f16e9..07507ada 100644
--- a/frontend/src/app/[locale]/activity/page.tsx
+++ b/frontend/src/app/[locale]/activity/page.tsx
@@ -64,16 +64,16 @@ export default function ActivityPage() {
(loan as { latestEventType?: string }).latestEventType === "LoanExtended"
? "Loan Extended"
: (loan as { latestEventType?: string }).latestEventType === "LoanRefinanced"
- ? "Loan Refinanced"
- : loan.status === "repaid"
- ? "Loan Repaid"
- : loan.status === "liquidated"
- ? "Loan Liquidated"
- : loan.status === "defaulted"
- ? "Loan Defaulted"
- : loan.status === "active"
- ? "Loan Active"
- : "Loan Request",
+ ? "Loan Refinanced"
+ : loan.status === "repaid"
+ ? "Loan Repaid"
+ : loan.status === "liquidated"
+ ? "Loan Liquidated"
+ : loan.status === "defaulted"
+ ? "Loan Defaulted"
+ : loan.status === "active"
+ ? "Loan Active"
+ : "Loan Request",
description: `Loan #${loan.id} — ${loan.currency}`,
amount: `${loan.status === "repaid" ? "+" : "-"}${formatCurrency(loan.amount)}`,
timestamp: new Date(loan.createdAt).toISOString(),
@@ -84,7 +84,10 @@ export default function ActivityPage() {
const remittanceEvents: ActivityItem[] = remittances.map((remittance) => ({
id: `remittance-${remittance.id}`,
type: "Remittance",
- description: `To ${remittance.recipientAddress.slice(0, 6)}...${remittance.recipientAddress.slice(-4)}`,
+ description: `To ${remittance.recipientAddress.slice(
+ 0,
+ 6,
+ )}...${remittance.recipientAddress.slice(-4)}`,
amount: `-${formatCurrency(remittance.amount)}`,
timestamp: new Date(remittance.createdAt).toISOString(),
status: remittance.status,
@@ -226,10 +229,10 @@ export default function ActivityPage() {
item.status === "completed" || item.status === "repaid"
? "bg-green-50 dark:bg-green-500/10"
: item.status === "failed" ||
- item.status === "defaulted" ||
- item.status === "liquidated"
- ? "bg-red-50 dark:bg-red-500/10"
- : "bg-indigo-50 dark:bg-indigo-500/10"
+ item.status === "defaulted" ||
+ item.status === "liquidated"
+ ? "bg-red-50 dark:bg-red-500/10"
+ : "bg-indigo-50 dark:bg-indigo-500/10"
}`}
aria-hidden="true"
>
diff --git a/frontend/src/app/[locale]/lend/LendPageClient.tsx b/frontend/src/app/[locale]/lend/LendPageClient.tsx
index 455492d5..825b05dd 100644
--- a/frontend/src/app/[locale]/lend/LendPageClient.tsx
+++ b/frontend/src/app/[locale]/lend/LendPageClient.tsx
@@ -195,19 +195,19 @@ export function LendPageClient() {
sseStatus === "connected"
? "bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-400"
: sseStatus === "connecting"
- ? "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"
- : sseStatus === "polling"
- ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
- : "bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400"
+ ? "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"
+ : sseStatus === "polling"
+ ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
+ : "bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400"
}`}
title={
sseStatus === "connected"
? "Live pool updates connected"
: sseStatus === "connecting"
- ? "Connecting to live updates…"
- : sseStatus === "polling"
- ? "Live updates dropped — polling while reconnecting"
- : "Live updates disconnected — retrying"
+ ? "Connecting to live updates…"
+ : sseStatus === "polling"
+ ? "Live updates dropped — polling while reconnecting"
+ : "Live updates disconnected — retrying"
}
>
{sseStatus === "connected" ? (
@@ -218,10 +218,10 @@ export function LendPageClient() {
{sseStatus === "connected"
? "Live"
: sseStatus === "connecting"
- ? "Connecting…"
- : sseStatus === "polling"
- ? "Reconnecting…"
- : "Offline"}
+ ? "Connecting…"
+ : sseStatus === "polling"
+ ? "Reconnecting…"
+ : "Offline"}
)}
diff --git a/frontend/src/app/[locale]/loans/LoansPageClient.tsx b/frontend/src/app/[locale]/loans/LoansPageClient.tsx
index 4d18346c..bd902f40 100644
--- a/frontend/src/app/[locale]/loans/LoansPageClient.tsx
+++ b/frontend/src/app/[locale]/loans/LoansPageClient.tsx
@@ -71,8 +71,8 @@ export function LoansPageClient() {
overdueCount === 0
? t("health.strong")
: overdueCount <= 2
- ? t("health.watch")
- : t("health.atRisk");
+ ? t("health.watch")
+ : t("health.atRisk");
if (isLoading) {
return ;
diff --git a/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx b/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
index ee8cf095..57b43e9e 100644
--- a/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
+++ b/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
@@ -142,10 +142,10 @@ export function LoanDetailsPageClient() {
realtimeStatus === "connected"
? "bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-400"
: realtimeStatus === "polling"
- ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
- : realtimeStatus === "disconnected"
- ? "bg-red-50 text-red-700 dark:bg-red-500/10 dark:text-red-300"
- : "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300"
+ ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
+ : realtimeStatus === "disconnected"
+ ? "bg-red-50 text-red-700 dark:bg-red-500/10 dark:text-red-300"
+ : "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300"
}`}
>
{realtimeStatus === "connected" ? (
@@ -156,10 +156,10 @@ export function LoanDetailsPageClient() {
{realtimeStatus === "connected"
? "Live loan updates"
: realtimeStatus === "polling"
- ? "Polling while reconnecting"
- : realtimeStatus === "disconnected"
- ? "Realtime temporarily unavailable"
- : "Connecting to live updates"}
+ ? "Polling while reconnecting"
+ : realtimeStatus === "disconnected"
+ ? "Realtime temporarily unavailable"
+ : "Connecting to live updates"}
{daysRemaining <= 0
? "Overdue"
: daysRemaining === 1
- ? "Due tomorrow"
- : `${daysRemaining} days`}
+ ? "Due tomorrow"
+ : `${daysRemaining} days`}
{nextDeadline && (
@@ -398,10 +398,10 @@ export function LoanDetailsPageClient() {
{loan.status === "liquidated"
? "Collateral was liquidated after the position fell below the collateral threshold."
: loan.status === "defaulted"
- ? "Collateral has been seized."
- : loan.status === "repaid"
- ? "Collateral released — loan fully repaid."
- : "Collateral is held in escrow for the duration of this loan."}
+ ? "Collateral has been seized."
+ : loan.status === "repaid"
+ ? "Collateral released — loan fully repaid."
+ : "Collateral is held in escrow for the duration of this loan."}
diff --git a/frontend/src/app/[locale]/page.tsx b/frontend/src/app/[locale]/page.tsx
index d408dd40..d748dc1d 100644
--- a/frontend/src/app/[locale]/page.tsx
+++ b/frontend/src/app/[locale]/page.tsx
@@ -217,8 +217,8 @@ export default function Home() {
l.status === "active"
? "Loan Active"
: l.status === "repaid"
- ? "Loan Repaid"
- : "Loan Request",
+ ? "Loan Repaid"
+ : "Loan Request",
desc: `Loan #${l.id} — ${formatCurrency(l.amount)}`,
amount: l.status === "repaid" ? `+${formatCurrency(l.amount)}` : formatCurrency(l.amount),
time: new Date(l.createdAt).toLocaleDateString(),
diff --git a/frontend/src/app/[locale]/settings/page.tsx b/frontend/src/app/[locale]/settings/page.tsx
index 57d6c47b..da27f195 100644
--- a/frontend/src/app/[locale]/settings/page.tsx
+++ b/frontend/src/app/[locale]/settings/page.tsx
@@ -469,8 +469,8 @@ function NotificationsSection() {
{updateNotificationPreferences.isPending
? "Saving..."
: saved
- ? "Saved!"
- : "Save Preferences"}
+ ? "Saved!"
+ : "Save Preferences"}
diff --git a/frontend/src/app/[locale]/wallet/page.tsx b/frontend/src/app/[locale]/wallet/page.tsx
index f6386772..12176a4e 100644
--- a/frontend/src/app/[locale]/wallet/page.tsx
+++ b/frontend/src/app/[locale]/wallet/page.tsx
@@ -123,7 +123,7 @@ function useHorizonPayments(address: string, horizonUrl: string, cursor: string
return {
records,
nextCursor:
- records.length === TRANSACTIONS_PER_PAGE ? (lastRecord?.paging_token ?? null) : null,
+ records.length === TRANSACTIONS_PER_PAGE ? lastRecord?.paging_token ?? null : null,
};
},
staleTime: 30_000,
@@ -190,7 +190,7 @@ function BalancesCard({ address, horizonUrl }: { address: string; horizonUrl: st
} = useHorizonBalances(address, horizonUrl);
function assetLabel(b: HorizonBalance): string {
- return b.asset_type === "native" ? "XLM" : (b.asset_code ?? "Unknown");
+ return b.asset_type === "native" ? "XLM" : b.asset_code ?? "Unknown";
}
function formatBalance(b: HorizonBalance): string {
@@ -314,14 +314,14 @@ function TransactionHistoryCard({
function paymentAmount(p: HorizonPayment): string {
if (!p.amount) return "—";
- const asset = p.asset_type === "native" ? "XLM" : (p.asset_code ?? "");
+ const asset = p.asset_type === "native" ? "XLM" : p.asset_code ?? "";
return `${parseFloat(p.amount).toLocaleString("en-US", { maximumFractionDigits: 7 })} ${asset}`;
}
function exportCsv() {
const today = new Date().toISOString().split("T")[0];
const rows = payments.map((p) => {
- const asset = p.asset_type === "native" ? "XLM" : (p.asset_code ?? "");
+ const asset = p.asset_type === "native" ? "XLM" : p.asset_code ?? "";
return {
date: p.created_at,
type: paymentLabel(p),
diff --git a/frontend/src/app/components/borrower/ActiveLoansTracker.tsx b/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
index f9c96dd3..70a99910 100644
--- a/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
+++ b/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
@@ -38,8 +38,8 @@ export function ActiveLoansTracker({ borrowerAddress }: { borrowerAddress: strin
filter === "overdue"
? loans.filter((l) => l.status === "active" && new Date(l.nextPaymentDeadline) < now)
: filter === "active"
- ? loans.filter((l) => l.status === "active")
- : loans;
+ ? loans.filter((l) => l.status === "active")
+ : loans;
const tabCounts: Record = {
active: loans.filter((l) => l.status === "active").length,
diff --git a/frontend/src/app/components/borrower/LoanCard.tsx b/frontend/src/app/components/borrower/LoanCard.tsx
index f92ec65d..d991470e 100644
--- a/frontend/src/app/components/borrower/LoanCard.tsx
+++ b/frontend/src/app/components/borrower/LoanCard.tsx
@@ -34,19 +34,19 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
label: isLiquidated
? "Liquidated"
: isDefaulted
- ? "Defaulted"
- : isOverdue
- ? "Overdue"
- : isUrgent
- ? "Due Soon"
- : "On Track",
+ ? "Defaulted"
+ : isOverdue
+ ? "Overdue"
+ : isUrgent
+ ? "Due Soon"
+ : "On Track",
className: isTerminalDistressed
? "bg-red-900 text-white"
: isOverdue
- ? "bg-red-100 text-red-800"
- : isUrgent
- ? "bg-yellow-100 text-yellow-800"
- : "bg-green-100 text-green-800",
+ ? "bg-red-100 text-red-800"
+ : isUrgent
+ ? "bg-yellow-100 text-yellow-800"
+ : "bg-green-100 text-green-800",
}
: null;
@@ -54,31 +54,31 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
const deadlineBg = isTerminalDistressed
? "bg-red-900/20"
: isOverdue
- ? "bg-red-50"
- : isUrgent
- ? "bg-yellow-50"
- : "bg-gray-50";
+ ? "bg-red-50"
+ : isUrgent
+ ? "bg-yellow-50"
+ : "bg-gray-50";
const deadlineTextColor = isTerminalDistressed
? "text-red-900"
: isOverdue
- ? "text-red-600"
- : isUrgent
- ? "text-yellow-600"
- : "text-gray-900";
+ ? "text-red-600"
+ : isUrgent
+ ? "text-yellow-600"
+ : "text-gray-900";
const deadlineSubColor = isTerminalDistressed
? "text-red-700"
: isOverdue
- ? "text-red-600"
- : isUrgent
- ? "text-yellow-600"
- : "text-gray-600";
+ ? "text-red-600"
+ : isUrgent
+ ? "text-yellow-600"
+ : "text-gray-600";
const deadlineLabel = isLiquidated
? "Collateral was liquidated"
: isDefaulted
- ? "Contact support to recover"
- : isOverdue
- ? `${Math.abs(daysUntil)} days overdue`
- : `${daysUntil} days remaining`;
+ ? "Contact support to recover"
+ : isOverdue
+ ? `${Math.abs(daysUntil)} days overdue`
+ : `${daysUntil} days remaining`;
// ── Progress (detailed only) ───────────────────────────────────────────────
const totalForProgress = loan.principal + loan.accruedInterest;
@@ -150,7 +150,9 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
Next Payment
{formatDate(loan.nextPaymentDeadline)}
diff --git a/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx b/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
index c6862d79..aa074e43 100644
--- a/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
+++ b/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
@@ -215,8 +215,8 @@ export function FinancialPerformanceDashboard({
// ── Derived display data ──
const displayCreditScoreData = useMockData
? generateMockCreditScoreData()
- : (creditScoreData ?? []);
- const displayYieldData = useMockData ? generateMockYieldData() : (yieldData ?? []);
+ : creditScoreData ?? [];
+ const displayYieldData = useMockData ? generateMockYieldData() : yieldData ?? [];
const displayLoanStats = useMemo(() => {
if (useMockData) return generateMockLoanStats();
@@ -302,8 +302,8 @@ export function FinancialPerformanceDashboard({
{userType === "both"
? "credit score and yield"
: userType === "borrower"
- ? "credit score"
- : "yield"}{" "}
+ ? "credit score"
+ : "yield"}{" "}
performance over time
@@ -354,7 +354,9 @@ export function FinancialPerformanceDashboard({
@@ -417,7 +419,11 @@ export function FinancialPerformanceDashboard({
value={fmt(displayDepositorStats.currentValue)}
sub={
displayDepositorStats.depositAmount > 0
- ? `+${(((displayDepositorStats.currentValue - displayDepositorStats.depositAmount) / displayDepositorStats.depositAmount) * 100).toFixed(2)}% growth`
+ ? `+${(
+ ((displayDepositorStats.currentValue - displayDepositorStats.depositAmount) /
+ displayDepositorStats.depositAmount) *
+ 100
+ ).toFixed(2)}% growth`
: undefined
}
colorClass="bg-blue-50 text-blue-900 dark:bg-blue-950/30 dark:text-blue-200"
diff --git a/frontend/src/app/components/global_ui/Header.tsx b/frontend/src/app/components/global_ui/Header.tsx
index 3b8fa256..7ebb5343 100644
--- a/frontend/src/app/components/global_ui/Header.tsx
+++ b/frontend/src/app/components/global_ui/Header.tsx
@@ -239,10 +239,10 @@ export function Header({ onMenuClick, className }: HeaderProps) {
const profileLabel = user?.email
? user.email
: user?.walletAddress
- ? truncateWalletAddress(user.walletAddress)
- : walletAddress
- ? truncateWalletAddress(walletAddress)
- : "Connect Wallet";
+ ? truncateWalletAddress(user.walletAddress)
+ : walletAddress
+ ? truncateWalletAddress(walletAddress)
+ : "Connect Wallet";
return (
diff --git a/frontend/src/app/components/loan-wizard/WizardStepper.tsx b/frontend/src/app/components/loan-wizard/WizardStepper.tsx
index f92c3ff3..85b9d311 100644
--- a/frontend/src/app/components/loan-wizard/WizardStepper.tsx
+++ b/frontend/src/app/components/loan-wizard/WizardStepper.tsx
@@ -98,8 +98,8 @@ export function WizardStepper({ steps, currentStep, onStepSelect }: WizardSteppe
isCurrent
? "text-indigo-600 dark:text-indigo-400"
: isCompleted
- ? "text-zinc-700 dark:text-zinc-300"
- : "text-zinc-400 dark:text-zinc-500",
+ ? "text-zinc-700 dark:text-zinc-300"
+ : "text-zinc-400 dark:text-zinc-500",
)}
>
{step.label}
diff --git a/frontend/src/app/components/loan/LoanHealth.tsx b/frontend/src/app/components/loan/LoanHealth.tsx
index 3fd1c821..430c1f61 100644
--- a/frontend/src/app/components/loan/LoanHealth.tsx
+++ b/frontend/src/app/components/loan/LoanHealth.tsx
@@ -99,16 +99,16 @@ export function LoanHealth({ loan, isLoading, isError, topUpHref, labels }: Loan
state === "atRisk"
? "border-red-200 bg-red-50 text-red-700 dark:border-red-900/60 dark:bg-red-950/30 dark:text-red-200"
: state === "watch"
- ? "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-200"
- : "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/60 dark:bg-emerald-950/30 dark:text-emerald-200";
+ ? "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-200"
+ : "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/60 dark:bg-emerald-950/30 dark:text-emerald-200";
const barTone =
state === "atRisk" ? "bg-red-500" : state === "watch" ? "bg-amber-500" : "bg-emerald-500";
const source =
loan?.healthSource === "contract"
? labels.sourceContract
: loan?.healthSource === "backend" || backendRatio || backendHealthFactor
- ? labels.sourceBackend
- : labels.sourceDerived;
+ ? labels.sourceBackend
+ : labels.sourceDerived;
const barWidth = `${Math.min(100, Math.max(6, (ratio / (threshold + 0.5)) * 100))}%`;
return (
diff --git a/frontend/src/app/components/providers/WalletProvider.tsx b/frontend/src/app/components/providers/WalletProvider.tsx
index 9eeb192b..1a4536bd 100644
--- a/frontend/src/app/components/providers/WalletProvider.tsx
+++ b/frontend/src/app/components/providers/WalletProvider.tsx
@@ -98,7 +98,7 @@ function getFallbackHorizonUrl(networkName: string | undefined): string {
function mapBalances(balances: HorizonBalance[] | undefined): TokenBalance[] {
return (balances ?? []).map((balance) => ({
- symbol: balance.asset_type === "native" ? "XLM" : (balance.asset_code ?? "ASSET"),
+ symbol: balance.asset_type === "native" ? "XLM" : balance.asset_code ?? "ASSET",
amount: balance.balance,
usdValue: null,
}));
@@ -181,8 +181,8 @@ export function WalletProvider({ children }: WalletProviderProps) {
const networkResult: FreighterNetworkResult = api.getNetworkDetails
? await api.getNetworkDetails()
: api.getNetwork
- ? await api.getNetwork()
- : { error: "Network info not available." };
+ ? await api.getNetwork()
+ : { error: "Network info not available." };
if (networkResult.error) {
throw new Error(normalizeWalletError(networkResult.error));
diff --git a/frontend/src/app/components/ui.tsx b/frontend/src/app/components/ui.tsx
index 489fdddd..540c805b 100644
--- a/frontend/src/app/components/ui.tsx
+++ b/frontend/src/app/components/ui.tsx
@@ -1 +1 @@
-export { COPY_FEEDBACK_RESET_MS } from './ui/CopyButton';
+export { COPY_FEEDBACK_RESET_MS } from "./ui/CopyButton";
diff --git a/frontend/src/app/components/ui/OperationProgress.tsx b/frontend/src/app/components/ui/OperationProgress.tsx
index 2df7d230..09eb4dca 100644
--- a/frontend/src/app/components/ui/OperationProgress.tsx
+++ b/frontend/src/app/components/ui/OperationProgress.tsx
@@ -88,7 +88,10 @@ export function OperationProgress({ transaction, type = "generic" }: OperationPr
href={`https://stellar.expert/explorer/testnet/tx/${txHash}`}
target="_blank"
rel="noopener noreferrer"
- aria-label={`View transaction ${txHash.slice(0, 8)}… on Stellar Explorer (opens in new tab)`}
+ aria-label={`View transaction ${txHash.slice(
+ 0,
+ 8,
+ )}… on Stellar Explorer (opens in new tab)`}
className="text-xs text-blue-600 hover:text-blue-700 dark:text-blue-400 hover:underline flex items-center gap-1"
>
diff --git a/frontend/src/app/components/ui/Toaster.tsx b/frontend/src/app/components/ui/Toaster.tsx
index adeab47d..52e9f45b 100644
--- a/frontend/src/app/components/ui/Toaster.tsx
+++ b/frontend/src/app/components/ui/Toaster.tsx
@@ -57,7 +57,9 @@ function ToastCard({ toast }: { toast: ToastItem }) {
animate={{ opacity: 1, x: 0, scale: 1 }}
exit={{ opacity: 0, x: 20, scale: 0.96 }}
transition={{ duration: 0.2, ease: "easeOut" }}
- className={`w-full rounded-xl border p-4 shadow-lg shadow-zinc-900/5 ${getToastStyles(toast.type)}`}
+ className={`w-full rounded-xl border p-4 shadow-lg shadow-zinc-900/5 ${getToastStyles(
+ toast.type,
+ )}`}
role="alert"
>
diff --git a/frontend/src/app/hooks/useApi.ts b/frontend/src/app/hooks/useApi.ts
index 5f7509f0..87ca8038 100644
--- a/frontend/src/app/hooks/useApi.ts
+++ b/frontend/src/app/hooks/useApi.ts
@@ -797,8 +797,8 @@ export function useLiquidatableLoans(
const loans = Array.isArray(response)
? response
: "loans" in response
- ? response.loans
- : response.data;
+ ? response.loans
+ : response.data;
const fallbackSource = Array.isArray(response) ? undefined : response.source;
return loans.map((loan) =>
@@ -1493,8 +1493,8 @@ export function useAdminDisputes(
const disputes = Array.isArray(response)
? response
: "disputes" in response
- ? response.disputes
- : response.data;
+ ? response.disputes
+ : response.data;
return disputes.map(normalizeDispute);
},
diff --git a/frontend/src/app/utils/transactionFormatter.ts b/frontend/src/app/utils/transactionFormatter.ts
index 84a9898d..9aa8fe34 100644
--- a/frontend/src/app/utils/transactionFormatter.ts
+++ b/frontend/src/app/utils/transactionFormatter.ts
@@ -186,7 +186,10 @@ export function formatRemittanceSend(params: {
const operations: TransactionOperation[] = [
{
type: "Send Remittance",
- description: `You are sending ${params.amount} ${params.token} to ${params.recipient.slice(0, 8)}...${params.recipient.slice(-6)}`,
+ description: `You are sending ${params.amount} ${params.token} to ${params.recipient.slice(
+ 0,
+ 8,
+ )}...${params.recipient.slice(-6)}`,
amount: params.amount.toString(),
token: params.token,
details: {
From 4896283f3476d888c9ab5632dcbb8380efb7b694 Mon Sep 17 00:00:00 2001
From: Ogunmodede Joel Taiwo
Date: Mon, 10 Aug 2026 03:34:55 +0100
Subject: [PATCH 7/9] build(frontend): update frontend package-lock.json
---
frontend/package-lock.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index f12306c6..26e69e1c 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -11965,7 +11965,6 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
From 2f42e9651a9a287006927da66316ab6d6b2f1f60 Mon Sep 17 00:00:00 2001
From: Ogunmodede Joel Taiwo
Date: Mon, 10 Aug 2026 03:35:43 +0100
Subject: [PATCH 8/9] style(frontend): format 16 frontend files with local
Prettier 3
---
frontend/lib/money/format.ts | 2 +-
frontend/src/app/[locale]/activity/page.tsx | 28 +++++-----
.../src/app/[locale]/lend/LendPageClient.tsx | 24 ++++-----
.../app/[locale]/loans/LoansPageClient.tsx | 4 +-
.../loans/[loanId]/LoanDetailsPageClient.tsx | 32 ++++++------
frontend/src/app/[locale]/page.tsx | 4 +-
frontend/src/app/[locale]/settings/page.tsx | 4 +-
frontend/src/app/[locale]/wallet/page.tsx | 8 +--
.../borrower/ActiveLoansTracker.tsx | 4 +-
.../src/app/components/borrower/LoanCard.tsx | 52 +++++++++----------
.../FinancialPerformanceDashboard.tsx | 8 +--
.../src/app/components/global_ui/Header.tsx | 8 +--
.../components/loan-wizard/WizardStepper.tsx | 4 +-
.../src/app/components/loan/LoanHealth.tsx | 8 +--
.../components/providers/WalletProvider.tsx | 6 +--
frontend/src/app/hooks/useApi.ts | 8 +--
16 files changed, 102 insertions(+), 102 deletions(-)
diff --git a/frontend/lib/money/format.ts b/frontend/lib/money/format.ts
index c1c57f34..24a6594a 100644
--- a/frontend/lib/money/format.ts
+++ b/frontend/lib/money/format.ts
@@ -150,7 +150,7 @@ export function formatStroops(value: bigint, opts: FormatStroopsOptions = {}): s
const fraction = scaledMagnitude % scale;
const wholeStr =
- opts.grouped ?? false ? whole.toLocaleString(opts.locale ?? "en-US") : whole.toString();
+ (opts.grouped ?? false) ? whole.toLocaleString(opts.locale ?? "en-US") : whole.toString();
const sign = negative && scaledMagnitude !== ZERO ? "-" : "";
diff --git a/frontend/src/app/[locale]/activity/page.tsx b/frontend/src/app/[locale]/activity/page.tsx
index 07507ada..cbf2deaf 100644
--- a/frontend/src/app/[locale]/activity/page.tsx
+++ b/frontend/src/app/[locale]/activity/page.tsx
@@ -64,16 +64,16 @@ export default function ActivityPage() {
(loan as { latestEventType?: string }).latestEventType === "LoanExtended"
? "Loan Extended"
: (loan as { latestEventType?: string }).latestEventType === "LoanRefinanced"
- ? "Loan Refinanced"
- : loan.status === "repaid"
- ? "Loan Repaid"
- : loan.status === "liquidated"
- ? "Loan Liquidated"
- : loan.status === "defaulted"
- ? "Loan Defaulted"
- : loan.status === "active"
- ? "Loan Active"
- : "Loan Request",
+ ? "Loan Refinanced"
+ : loan.status === "repaid"
+ ? "Loan Repaid"
+ : loan.status === "liquidated"
+ ? "Loan Liquidated"
+ : loan.status === "defaulted"
+ ? "Loan Defaulted"
+ : loan.status === "active"
+ ? "Loan Active"
+ : "Loan Request",
description: `Loan #${loan.id} — ${loan.currency}`,
amount: `${loan.status === "repaid" ? "+" : "-"}${formatCurrency(loan.amount)}`,
timestamp: new Date(loan.createdAt).toISOString(),
@@ -229,10 +229,10 @@ export default function ActivityPage() {
item.status === "completed" || item.status === "repaid"
? "bg-green-50 dark:bg-green-500/10"
: item.status === "failed" ||
- item.status === "defaulted" ||
- item.status === "liquidated"
- ? "bg-red-50 dark:bg-red-500/10"
- : "bg-indigo-50 dark:bg-indigo-500/10"
+ item.status === "defaulted" ||
+ item.status === "liquidated"
+ ? "bg-red-50 dark:bg-red-500/10"
+ : "bg-indigo-50 dark:bg-indigo-500/10"
}`}
aria-hidden="true"
>
diff --git a/frontend/src/app/[locale]/lend/LendPageClient.tsx b/frontend/src/app/[locale]/lend/LendPageClient.tsx
index 825b05dd..455492d5 100644
--- a/frontend/src/app/[locale]/lend/LendPageClient.tsx
+++ b/frontend/src/app/[locale]/lend/LendPageClient.tsx
@@ -195,19 +195,19 @@ export function LendPageClient() {
sseStatus === "connected"
? "bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-400"
: sseStatus === "connecting"
- ? "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"
- : sseStatus === "polling"
- ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
- : "bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400"
+ ? "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"
+ : sseStatus === "polling"
+ ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
+ : "bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400"
}`}
title={
sseStatus === "connected"
? "Live pool updates connected"
: sseStatus === "connecting"
- ? "Connecting to live updates…"
- : sseStatus === "polling"
- ? "Live updates dropped — polling while reconnecting"
- : "Live updates disconnected — retrying"
+ ? "Connecting to live updates…"
+ : sseStatus === "polling"
+ ? "Live updates dropped — polling while reconnecting"
+ : "Live updates disconnected — retrying"
}
>
{sseStatus === "connected" ? (
@@ -218,10 +218,10 @@ export function LendPageClient() {
{sseStatus === "connected"
? "Live"
: sseStatus === "connecting"
- ? "Connecting…"
- : sseStatus === "polling"
- ? "Reconnecting…"
- : "Offline"}
+ ? "Connecting…"
+ : sseStatus === "polling"
+ ? "Reconnecting…"
+ : "Offline"}
)}
diff --git a/frontend/src/app/[locale]/loans/LoansPageClient.tsx b/frontend/src/app/[locale]/loans/LoansPageClient.tsx
index bd902f40..4d18346c 100644
--- a/frontend/src/app/[locale]/loans/LoansPageClient.tsx
+++ b/frontend/src/app/[locale]/loans/LoansPageClient.tsx
@@ -71,8 +71,8 @@ export function LoansPageClient() {
overdueCount === 0
? t("health.strong")
: overdueCount <= 2
- ? t("health.watch")
- : t("health.atRisk");
+ ? t("health.watch")
+ : t("health.atRisk");
if (isLoading) {
return ;
diff --git a/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx b/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
index 57b43e9e..ee8cf095 100644
--- a/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
+++ b/frontend/src/app/[locale]/loans/[loanId]/LoanDetailsPageClient.tsx
@@ -142,10 +142,10 @@ export function LoanDetailsPageClient() {
realtimeStatus === "connected"
? "bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-400"
: realtimeStatus === "polling"
- ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
- : realtimeStatus === "disconnected"
- ? "bg-red-50 text-red-700 dark:bg-red-500/10 dark:text-red-300"
- : "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300"
+ ? "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-300"
+ : realtimeStatus === "disconnected"
+ ? "bg-red-50 text-red-700 dark:bg-red-500/10 dark:text-red-300"
+ : "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300"
}`}
>
{realtimeStatus === "connected" ? (
@@ -156,10 +156,10 @@ export function LoanDetailsPageClient() {
{realtimeStatus === "connected"
? "Live loan updates"
: realtimeStatus === "polling"
- ? "Polling while reconnecting"
- : realtimeStatus === "disconnected"
- ? "Realtime temporarily unavailable"
- : "Connecting to live updates"}
+ ? "Polling while reconnecting"
+ : realtimeStatus === "disconnected"
+ ? "Realtime temporarily unavailable"
+ : "Connecting to live updates"}
{daysRemaining <= 0
? "Overdue"
: daysRemaining === 1
- ? "Due tomorrow"
- : `${daysRemaining} days`}
+ ? "Due tomorrow"
+ : `${daysRemaining} days`}
{nextDeadline && (
@@ -398,10 +398,10 @@ export function LoanDetailsPageClient() {
{loan.status === "liquidated"
? "Collateral was liquidated after the position fell below the collateral threshold."
: loan.status === "defaulted"
- ? "Collateral has been seized."
- : loan.status === "repaid"
- ? "Collateral released — loan fully repaid."
- : "Collateral is held in escrow for the duration of this loan."}
+ ? "Collateral has been seized."
+ : loan.status === "repaid"
+ ? "Collateral released — loan fully repaid."
+ : "Collateral is held in escrow for the duration of this loan."}
diff --git a/frontend/src/app/[locale]/page.tsx b/frontend/src/app/[locale]/page.tsx
index d748dc1d..d408dd40 100644
--- a/frontend/src/app/[locale]/page.tsx
+++ b/frontend/src/app/[locale]/page.tsx
@@ -217,8 +217,8 @@ export default function Home() {
l.status === "active"
? "Loan Active"
: l.status === "repaid"
- ? "Loan Repaid"
- : "Loan Request",
+ ? "Loan Repaid"
+ : "Loan Request",
desc: `Loan #${l.id} — ${formatCurrency(l.amount)}`,
amount: l.status === "repaid" ? `+${formatCurrency(l.amount)}` : formatCurrency(l.amount),
time: new Date(l.createdAt).toLocaleDateString(),
diff --git a/frontend/src/app/[locale]/settings/page.tsx b/frontend/src/app/[locale]/settings/page.tsx
index da27f195..57d6c47b 100644
--- a/frontend/src/app/[locale]/settings/page.tsx
+++ b/frontend/src/app/[locale]/settings/page.tsx
@@ -469,8 +469,8 @@ function NotificationsSection() {
{updateNotificationPreferences.isPending
? "Saving..."
: saved
- ? "Saved!"
- : "Save Preferences"}
+ ? "Saved!"
+ : "Save Preferences"}
diff --git a/frontend/src/app/[locale]/wallet/page.tsx b/frontend/src/app/[locale]/wallet/page.tsx
index 12176a4e..f6386772 100644
--- a/frontend/src/app/[locale]/wallet/page.tsx
+++ b/frontend/src/app/[locale]/wallet/page.tsx
@@ -123,7 +123,7 @@ function useHorizonPayments(address: string, horizonUrl: string, cursor: string
return {
records,
nextCursor:
- records.length === TRANSACTIONS_PER_PAGE ? lastRecord?.paging_token ?? null : null,
+ records.length === TRANSACTIONS_PER_PAGE ? (lastRecord?.paging_token ?? null) : null,
};
},
staleTime: 30_000,
@@ -190,7 +190,7 @@ function BalancesCard({ address, horizonUrl }: { address: string; horizonUrl: st
} = useHorizonBalances(address, horizonUrl);
function assetLabel(b: HorizonBalance): string {
- return b.asset_type === "native" ? "XLM" : b.asset_code ?? "Unknown";
+ return b.asset_type === "native" ? "XLM" : (b.asset_code ?? "Unknown");
}
function formatBalance(b: HorizonBalance): string {
@@ -314,14 +314,14 @@ function TransactionHistoryCard({
function paymentAmount(p: HorizonPayment): string {
if (!p.amount) return "—";
- const asset = p.asset_type === "native" ? "XLM" : p.asset_code ?? "";
+ const asset = p.asset_type === "native" ? "XLM" : (p.asset_code ?? "");
return `${parseFloat(p.amount).toLocaleString("en-US", { maximumFractionDigits: 7 })} ${asset}`;
}
function exportCsv() {
const today = new Date().toISOString().split("T")[0];
const rows = payments.map((p) => {
- const asset = p.asset_type === "native" ? "XLM" : p.asset_code ?? "";
+ const asset = p.asset_type === "native" ? "XLM" : (p.asset_code ?? "");
return {
date: p.created_at,
type: paymentLabel(p),
diff --git a/frontend/src/app/components/borrower/ActiveLoansTracker.tsx b/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
index 70a99910..f9c96dd3 100644
--- a/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
+++ b/frontend/src/app/components/borrower/ActiveLoansTracker.tsx
@@ -38,8 +38,8 @@ export function ActiveLoansTracker({ borrowerAddress }: { borrowerAddress: strin
filter === "overdue"
? loans.filter((l) => l.status === "active" && new Date(l.nextPaymentDeadline) < now)
: filter === "active"
- ? loans.filter((l) => l.status === "active")
- : loans;
+ ? loans.filter((l) => l.status === "active")
+ : loans;
const tabCounts: Record = {
active: loans.filter((l) => l.status === "active").length,
diff --git a/frontend/src/app/components/borrower/LoanCard.tsx b/frontend/src/app/components/borrower/LoanCard.tsx
index d991470e..4e172b46 100644
--- a/frontend/src/app/components/borrower/LoanCard.tsx
+++ b/frontend/src/app/components/borrower/LoanCard.tsx
@@ -34,19 +34,19 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
label: isLiquidated
? "Liquidated"
: isDefaulted
- ? "Defaulted"
- : isOverdue
- ? "Overdue"
- : isUrgent
- ? "Due Soon"
- : "On Track",
+ ? "Defaulted"
+ : isOverdue
+ ? "Overdue"
+ : isUrgent
+ ? "Due Soon"
+ : "On Track",
className: isTerminalDistressed
? "bg-red-900 text-white"
: isOverdue
- ? "bg-red-100 text-red-800"
- : isUrgent
- ? "bg-yellow-100 text-yellow-800"
- : "bg-green-100 text-green-800",
+ ? "bg-red-100 text-red-800"
+ : isUrgent
+ ? "bg-yellow-100 text-yellow-800"
+ : "bg-green-100 text-green-800",
}
: null;
@@ -54,31 +54,31 @@ export function LoanCard({ loan, variant = "compact" }: LoanCardProps) {
const deadlineBg = isTerminalDistressed
? "bg-red-900/20"
: isOverdue
- ? "bg-red-50"
- : isUrgent
- ? "bg-yellow-50"
- : "bg-gray-50";
+ ? "bg-red-50"
+ : isUrgent
+ ? "bg-yellow-50"
+ : "bg-gray-50";
const deadlineTextColor = isTerminalDistressed
? "text-red-900"
: isOverdue
- ? "text-red-600"
- : isUrgent
- ? "text-yellow-600"
- : "text-gray-900";
+ ? "text-red-600"
+ : isUrgent
+ ? "text-yellow-600"
+ : "text-gray-900";
const deadlineSubColor = isTerminalDistressed
? "text-red-700"
: isOverdue
- ? "text-red-600"
- : isUrgent
- ? "text-yellow-600"
- : "text-gray-600";
+ ? "text-red-600"
+ : isUrgent
+ ? "text-yellow-600"
+ : "text-gray-600";
const deadlineLabel = isLiquidated
? "Collateral was liquidated"
: isDefaulted
- ? "Contact support to recover"
- : isOverdue
- ? `${Math.abs(daysUntil)} days overdue`
- : `${daysUntil} days remaining`;
+ ? "Contact support to recover"
+ : isOverdue
+ ? `${Math.abs(daysUntil)} days overdue`
+ : `${daysUntil} days remaining`;
// ── Progress (detailed only) ───────────────────────────────────────────────
const totalForProgress = loan.principal + loan.accruedInterest;
diff --git a/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx b/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
index aa074e43..c25a1368 100644
--- a/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
+++ b/frontend/src/app/components/dashboards/FinancialPerformanceDashboard.tsx
@@ -215,8 +215,8 @@ export function FinancialPerformanceDashboard({
// ── Derived display data ──
const displayCreditScoreData = useMockData
? generateMockCreditScoreData()
- : creditScoreData ?? [];
- const displayYieldData = useMockData ? generateMockYieldData() : yieldData ?? [];
+ : (creditScoreData ?? []);
+ const displayYieldData = useMockData ? generateMockYieldData() : (yieldData ?? []);
const displayLoanStats = useMemo(() => {
if (useMockData) return generateMockLoanStats();
@@ -302,8 +302,8 @@ export function FinancialPerformanceDashboard({
{userType === "both"
? "credit score and yield"
: userType === "borrower"
- ? "credit score"
- : "yield"}{" "}
+ ? "credit score"
+ : "yield"}{" "}
performance over time
diff --git a/frontend/src/app/components/global_ui/Header.tsx b/frontend/src/app/components/global_ui/Header.tsx
index 7ebb5343..3b8fa256 100644
--- a/frontend/src/app/components/global_ui/Header.tsx
+++ b/frontend/src/app/components/global_ui/Header.tsx
@@ -239,10 +239,10 @@ export function Header({ onMenuClick, className }: HeaderProps) {
const profileLabel = user?.email
? user.email
: user?.walletAddress
- ? truncateWalletAddress(user.walletAddress)
- : walletAddress
- ? truncateWalletAddress(walletAddress)
- : "Connect Wallet";
+ ? truncateWalletAddress(user.walletAddress)
+ : walletAddress
+ ? truncateWalletAddress(walletAddress)
+ : "Connect Wallet";
return (
{step.label}
diff --git a/frontend/src/app/components/loan/LoanHealth.tsx b/frontend/src/app/components/loan/LoanHealth.tsx
index 430c1f61..3fd1c821 100644
--- a/frontend/src/app/components/loan/LoanHealth.tsx
+++ b/frontend/src/app/components/loan/LoanHealth.tsx
@@ -99,16 +99,16 @@ export function LoanHealth({ loan, isLoading, isError, topUpHref, labels }: Loan
state === "atRisk"
? "border-red-200 bg-red-50 text-red-700 dark:border-red-900/60 dark:bg-red-950/30 dark:text-red-200"
: state === "watch"
- ? "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-200"
- : "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/60 dark:bg-emerald-950/30 dark:text-emerald-200";
+ ? "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-200"
+ : "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/60 dark:bg-emerald-950/30 dark:text-emerald-200";
const barTone =
state === "atRisk" ? "bg-red-500" : state === "watch" ? "bg-amber-500" : "bg-emerald-500";
const source =
loan?.healthSource === "contract"
? labels.sourceContract
: loan?.healthSource === "backend" || backendRatio || backendHealthFactor
- ? labels.sourceBackend
- : labels.sourceDerived;
+ ? labels.sourceBackend
+ : labels.sourceDerived;
const barWidth = `${Math.min(100, Math.max(6, (ratio / (threshold + 0.5)) * 100))}%`;
return (
diff --git a/frontend/src/app/components/providers/WalletProvider.tsx b/frontend/src/app/components/providers/WalletProvider.tsx
index 1a4536bd..9eeb192b 100644
--- a/frontend/src/app/components/providers/WalletProvider.tsx
+++ b/frontend/src/app/components/providers/WalletProvider.tsx
@@ -98,7 +98,7 @@ function getFallbackHorizonUrl(networkName: string | undefined): string {
function mapBalances(balances: HorizonBalance[] | undefined): TokenBalance[] {
return (balances ?? []).map((balance) => ({
- symbol: balance.asset_type === "native" ? "XLM" : balance.asset_code ?? "ASSET",
+ symbol: balance.asset_type === "native" ? "XLM" : (balance.asset_code ?? "ASSET"),
amount: balance.balance,
usdValue: null,
}));
@@ -181,8 +181,8 @@ export function WalletProvider({ children }: WalletProviderProps) {
const networkResult: FreighterNetworkResult = api.getNetworkDetails
? await api.getNetworkDetails()
: api.getNetwork
- ? await api.getNetwork()
- : { error: "Network info not available." };
+ ? await api.getNetwork()
+ : { error: "Network info not available." };
if (networkResult.error) {
throw new Error(normalizeWalletError(networkResult.error));
diff --git a/frontend/src/app/hooks/useApi.ts b/frontend/src/app/hooks/useApi.ts
index 87ca8038..5f7509f0 100644
--- a/frontend/src/app/hooks/useApi.ts
+++ b/frontend/src/app/hooks/useApi.ts
@@ -797,8 +797,8 @@ export function useLiquidatableLoans(
const loans = Array.isArray(response)
? response
: "loans" in response
- ? response.loans
- : response.data;
+ ? response.loans
+ : response.data;
const fallbackSource = Array.isArray(response) ? undefined : response.source;
return loans.map((loan) =>
@@ -1493,8 +1493,8 @@ export function useAdminDisputes(
const disputes = Array.isArray(response)
? response
: "disputes" in response
- ? response.disputes
- : response.data;
+ ? response.disputes
+ : response.data;
return disputes.map(normalizeDispute);
},
From f0fb129acbb1caa5b147faa9e1f38a380159bf51 Mon Sep 17 00:00:00 2001
From: Ogunmodede Joel Taiwo
Date: Mon, 10 Aug 2026 03:39:53 +0100
Subject: [PATCH 9/9] fix(frontend): resolve promise initialization in
useReveal.test.tsx
---
frontend/src/app/hooks/useReveal.test.tsx | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/frontend/src/app/hooks/useReveal.test.tsx b/frontend/src/app/hooks/useReveal.test.tsx
index 3feac3ab..454acc39 100644
--- a/frontend/src/app/hooks/useReveal.test.tsx
+++ b/frontend/src/app/hooks/useReveal.test.tsx
@@ -125,12 +125,10 @@ describe("useReveal", () => {
it("does not expose the value before the request resolves", async () => {
let resolveFetch!: (val: unknown) => void;
- global.fetch = jest.fn(
- () =>
- new Promise((resolve) => {
- resolveFetch = resolve;
- }),
- ) as unknown as typeof fetch;
+ const fetchPromise = new Promise((resolve) => {
+ resolveFetch = resolve;
+ });
+ global.fetch = jest.fn(() => fetchPromise) as unknown as typeof fetch;
const { result } = renderHook(() => useReveal(), { wrapper: createWrapper() });