Overview
Users currently see escrow amounts only in XLM with no reference to their fiat value. Adding a live XLM/USD price oracle bridges this gap: the backend caches price data with staleness guards, exposes a REST endpoint, and the frontend renders a live rate ticker alongside all XLM amounts in the UI.
What to build
Backend:
GET /api/v1/market/xlm-usd — returns { price_usd: number, source: string, timestamp: ISO8601, stale: bool }
- Price source priority: 1) Stellar Anchor's SEP-38 quote server (if configured), 2) Coingecko free API (
/simple/price?ids=stellar&vs_currencies=usd), 3) Binance REST API (/api/v3/ticker/price?symbol=XLMUSDT)
- Redis cache: key
market:xlm_usd, TTL 60s; if fetch fails and cache is older than 5 min, return cached data with stale: true; if cache is absent and all sources fail, return 503
- Background job (every 60s): proactively refreshes cache so the REST endpoint never waits on an external call; logs source and latency
- Source failover: if source 1 fails, try source 2; if source 2 fails, try source 3; record which source succeeded in the response
Frontend:
useLiveXlmRate() hook: polls GET /api/v1/market/xlm-usd every 60s; returns { rate_usd, stale, loading }
XlmAmount component: displays {xlm_amount} XLM with a ≈ $USD sub-label; USD computed client-side from the live rate; grayed-out if stale=true
RateTicker widget (header bar): shows 1 XLM = $0.XXX USD with a green/red delta arrow vs the previous rate; clicking links to Stellar Expert market data
- Replace all bare XLM amount displays across the app with the
XlmAmount component
- Stale rate indicator: if
stale=true, show a small ⚠ Rate may be outdated tooltip on the USD sub-label
Acceptance Criteria
Technical notes
- Coingecko free API has a 10–50 req/min rate limit; the 60s background job stays well within this
- USD conversion:
usd_value = xlm_amount * rate_usd; displayed with toLocaleString('en-US', { style: 'currency', currency: 'USD' })
Overview
Users currently see escrow amounts only in XLM with no reference to their fiat value. Adding a live XLM/USD price oracle bridges this gap: the backend caches price data with staleness guards, exposes a REST endpoint, and the frontend renders a live rate ticker alongside all XLM amounts in the UI.
What to build
Backend:
GET /api/v1/market/xlm-usd— returns{ price_usd: number, source: string, timestamp: ISO8601, stale: bool }/simple/price?ids=stellar&vs_currencies=usd), 3) Binance REST API (/api/v3/ticker/price?symbol=XLMUSDT)market:xlm_usd, TTL 60s; if fetch fails and cache is older than 5 min, return cached data withstale: true; if cache is absent and all sources fail, return 503Frontend:
useLiveXlmRate()hook: pollsGET /api/v1/market/xlm-usdevery 60s; returns{ rate_usd, stale, loading }XlmAmountcomponent: displays{xlm_amount} XLMwith a≈ $USDsub-label; USD computed client-side from the live rate; grayed-out ifstale=trueRateTickerwidget (header bar): shows1 XLM = $0.XXX USDwith a green/red delta arrow vs the previous rate; clicking links to Stellar Expert market dataXlmAmountcomponentstale=true, show a small⚠ Rate may be outdatedtooltip on the USD sub-labelAcceptance Criteria
setIntervalwith cleanup on unmount; no polling when tab is hiddenXlmAmountwithamount=0displays0 XLMand≈ $0.00 USD(not NaN or blank)RateTickerdelta arrow: green up-arrow if rate increased since last poll, red down-arrow if decreased, no arrow if unchangedXlmAmountcomponent (grep for raw{amount} XLMpatterns)XlmAmountUSD calculation,RateTickerdeltaTechnical notes
usd_value = xlm_amount * rate_usd; displayed withtoLocaleString('en-US', { style: 'currency', currency: 'USD' })