diff --git a/app/api/rates/route.ts b/app/api/rates/route.ts
index 6f9e1cc..8bebc27 100644
--- a/app/api/rates/route.ts
+++ b/app/api/rates/route.ts
@@ -5,7 +5,7 @@ import {
RATES_CACHE_CONTROL_VALUE,
} from "@/lib/server/rates-cache";
-export const revalidate = 300;
+export const revalidate = 60;
export async function GET() {
try {
@@ -19,13 +19,18 @@ export async function GET() {
});
} catch (error) {
const cachedRates = getLastCachedRates();
+ const fallbackErrorMessage =
+ error instanceof Error
+ ? error.message.replace(/[\r\n]+/g, " ")
+ : "Upstream provider error";
if (cachedRates) {
return NextResponse.json(cachedRates, {
status: 200,
headers: {
"Cache-Control": RATES_CACHE_CONTROL_VALUE,
- "X-Cache-Fallback": "stale-on-error"
+ "X-Cache-Fallback": "stale-on-error",
+ "X-Cache-Fallback-Error": fallbackErrorMessage
}
});
}
diff --git a/components/converter/converter-card.tsx b/components/converter/converter-card.tsx
index dcb2b16..cdcb338 100644
--- a/components/converter/converter-card.tsx
+++ b/components/converter/converter-card.tsx
@@ -243,6 +243,24 @@ export function ConverterCard({
}
};
+ const displayUpdatedAt = useMemo(() => {
+ if (!data) {
+ return null;
+ }
+
+ const timestamps = [new Date(data.updatedAt).getTime()];
+
+ if (marketData?.updatedAt) {
+ timestamps.push(new Date(marketData.updatedAt).getTime());
+ }
+
+ const latest = Math.max(
+ ...timestamps.filter((timestamp) => Number.isFinite(timestamp)),
+ );
+
+ return Number.isFinite(latest) ? new Date(latest).toISOString() : data.updatedAt;
+ }, [data, marketData?.updatedAt]);
+
if (isLoading && !data) {
return
Last updated
- {formatTimestamp(data.updatedAt)} + {formatTimestamp(displayUpdatedAt ?? data.updatedAt)}