Files
wowcheckout/ui/lib/use-xmr-usd-rate.ts
T
jwinterm f8f9b4424c Fork xmrcheckout for Wownero (WOW)
Minimal changes from upstream xmrcheckout to support Wownero:
- Rate provider: Nonlogs WOW-BTC via Kraken BTC/USD
- Subaddress derivation: Wownero network byte overrides (53/63/54)
- Payment URI scheme: wownero:
- Dockerfile: Wownero binaries from Codeberg
- Display text: Monero→Wownero, XMR→WOW throughout UI
- Default daemon: 192.168.88.235:34568
- Added wownero-logo.svg

File and folder structure kept identical to upstream for easy sync.
2026-03-09 11:08:55 -04:00

71 lines
1.6 KiB
TypeScript

import { useEffect, useState } from "react";
const RATE_TTL_MS = 5 * 60 * 1000;
const RATE_URL =
"https://api.coingecko.com/api/v3/simple/price?ids=wownero&vs_currencies=usd";
let cachedRate: number | null = null;
let cachedAt: number | null = null;
let inflight: Promise<number | null> | null = null;
const fetchRate = async (): Promise<number | null> => {
try {
const response = await fetch(RATE_URL, { cache: "no-store" });
if (!response.ok) {
return null;
}
const data = (await response.json()) as {
wownero?: { usd?: number };
};
const rate = data?.wownero?.usd;
if (typeof rate !== "number" || !Number.isFinite(rate)) {
return null;
}
cachedRate = rate;
cachedAt = Date.now();
return rate;
} catch {
return null;
}
};
export const useXmrUsdRate = () => {
const [rate, setRate] = useState<number | null>(cachedRate);
const [updatedAt, setUpdatedAt] = useState<number | null>(cachedAt);
useEffect(() => {
let active = true;
const now = Date.now();
const hasFreshRate =
cachedRate !== null && cachedAt !== null && now - cachedAt < RATE_TTL_MS;
if (hasFreshRate) {
setRate(cachedRate);
setUpdatedAt(cachedAt);
return;
}
const request =
inflight ??
(inflight = fetchRate().finally(() => {
inflight = null;
}));
request.then((nextRate) => {
if (!active) {
return;
}
if (nextRate !== null) {
setRate(nextRate);
setUpdatedAt(cachedAt);
}
});
return () => {
active = false;
};
}, []);
return { rate, updatedAt, source: "coingecko" as const };
};