Data Aggregation
Emojis.Trade pulls live statistics for every emoji token directly from public indexers. This guide explains where the data comes from, how we query it, and best practices for performance & reliability.
1. Primary Source: UniSat Open API
UniSat is the first widely‑used BRC‑20 + Ordinals indexer. Core endpoint:
GET https://open-api.unisat.io/v1/indexer/brc20/<ticker>/info
Response Fields
ticker
Token identifier (may be emoji‑encoded)
max
Max supply cap
totalMinted
Total minted so far
holdersCount
Unique holder addresses
limit
Max tokens per mint
op
creator
Deploying address
deployTime
ISO timestamp
💡 Some fields (e.g.
volume24h
) are returned only if UniSat has price data.
Auth & Rate Limits
API key required — set header
Authorization: Bearer <KEY>
.Free tier ≈ 30 req/min. Spike beyond that → HTTP 429.
We stagger requests 100–150 ms apart (configurable:
VITE_API_STAGGER_MS
).
2. Code Snippet
// src/lib/unisat.ts
export async function fetchInfo(tickerEncoded: string) {
const url = `https://open-api.unisat.io/v1/indexer/brc20/${tickerEncoded}/info`;
const res = await fetch(url, {
headers: {
Authorization: `Bearer ${import.meta.env.VITE_UNISAT_API_KEY}`,
Accept: 'application/json'
}
});
const json = await res.json();
if (json.code !== 0) throw new Error(json.msg);
return json.data;
}
fetchInfo
is wrapped in SWR/React Query for caching & revalidation.
3. Performance Strategies
Chunked Parallelism
Fetch 10 tokens → Promise.all
→ 100 ms wait → next chunk.
Client Cache
SWR stale‑while‑revalidate keeps data fresh without refetch blinks.
Server Proxy (optional)
GET /api/cache/brc20/<ticker>
hits a Node cache (TTL 60 s) to offload UniSat rate limits.
Conditional Fetch
Skip refetch if totalMinted
hasn’t changed (ETag header planned).
4. Extending Data Sources
24 h Price / Volume
OKLink BRC‑20 Tracker → /brc20/token/<ticker>
Address Portfolio
UniSat /v1/indexer/brc20/{addr}/summary
Marketplace Trades
UniSat /market/brc20/<ticker>/orders
(coming soon)
Category Metadata
Static emoji-category.json
or Unicode DB
Always namespace new fetchers in
src/lib/
and reuse global fetch util.
5. Cross‑Verification
Relying on one indexer can introduce data drift. Options:
Dual fetch: Query a second indexer (e.g. Ordiscan) and compare
totalMinted
.Alarm: If variance > 1 %, flag token row yellow.
Fallback: If UniSat 5xx for >3 s, switch UI to backup indexer.
6. Error Handling Pattern
try {
const info = await fetchInfo(ticker);
setTokenData(info);
} catch (err) {
console.error('API error', err);
setTokenData({ status: 'error' });
}
In the table, error rows show 🚫 “Data NA” but keep layout intact.
7. Security & Privacy
API key is client‑side; use low‑priv key.
No user PII sent — only ticker strings.
For future private endpoints, route through serverless functions (keeps secrets on server).
8. Checklist Before Merging a New Fetcher
That’s the data‑pipeline in a nutshell. If you build a new integration or spot outdated endpoints, open a pull request! 🎉