Market Data
Market-Data Enrichment
Dexscreener is Seshat's primary market feed, but a single source can be thin or wrong for new tokens. CoinGecko and DeFiLlama add cross-source context — categories, all-time-high data, an independent price with a confidence score, and protocol TVL — so the picture isn't built on one provider alone.
Design principles
Cross-source, not authoritative
These feeds add context on top of Dexscreener. They are enrichment — most clanker/meme tokens won't be listed on CoinGecko or map to a DeFiLlama protocol, and that's expected.
Fail-soft everywhere
404 (not listed), 429 (rate limited), or any network error → null. A missing feed never breaks enrichment.
Hard-cached in KV
Every response is cached in the CACHE KV namespace (default ~1h TTL) to respect free-tier rate limits — CoinGecko's keyless tier is ~30 req/min.
CoinGecko
Looked up by on-chain contract address on the base asset platform. When COINGECKO_API_KEY is set, the demo header x-cg-demo-api-key is sent; otherwise the keyless free tier is used. It returns category tags, market cap, total volume, all-time-high data, 24h change, and links (Twitter handle, homepage, description).
// providers/coingecko.ts — getByContract(address, platform = 'base')
// GET /coins/{platform}/contract/{address} (cache key: cg:contract:{addr})
interface CoinGeckoData {
coingecko_id: string | null;
categories: string[]; // e.g. ["AI", "Base Ecosystem"]
market_cap_usd: number | null;
total_volume_usd: number | null;
ath_usd: number | null;
ath_change_pct: number | null;
price_change_24h_pct: number | null;
twitter: string | null; // handle without @
homepage: string | null;
description: string | null;
}
// !res.ok (404/429/etc.) → null. Cached on success.DeFiLlama
No API key required. Two endpoints: an independent spot price with a confidence value (how much Llama trusts that price — a useful cross-check against Dexscreener), and protocol TVL by slug.
// providers/defillama.ts
// 1. getCurrentPrice(address, chain = 'base')
// GET coins.llama.fi/prices/current/{chain}:{address}
interface LlamaPrice {
price_usd: number | null;
confidence: number | null; // 0-1 — how trustworthy Llama considers the price
symbol: string | null;
}
// 2. getProtocolTvl(slug)
// GET api.llama.fi/tvl/{slug} → bare JSON number (USD)
// Most meme/clanker tokens don't map to a protocol → null (expected).Why the confidence field matters
A low DeFiLlama price confidence on a token that Dexscreener reports as liquid is a quiet warning — the two sources disagree on how real the price is. It's exactly the kind of cross-source context a single feed can't give you.
How it runs
The external enrich step runs on the 2-hour cron as qualitative context and can be triggered manually via POST /api/admin/enrich-external. Like the other context layers, this data informs the picture (categories feed narrative and research context; cross-source prices sanity-check the market read) but is not itself a weighted dimension in the composite score.
Lineage
Both providers are native re-implementations of the most useful data sources from web3-research-mcp — an MCP stdio server that can't run inside a Worker — rebuilt to match Seshat's provider idioms (KV cache, fail-soft return shapes) so they run edge-native with no external process.