# Data Sources & Integrations

ChainRender apps show *live* on-chain data through **resolvers** — small `view` contracts that read chain state at
render time. This page covers the built integrations for real protocols. All are fully on-chain and Grade A: a live
read is still an on-chain read.

## Chainlink price feeds

Two built integrations turn Chainlink feeds into live UI:

### Live price value (`ChainlinkFeedResolver`)
Reads a Chainlink `AggregatorV3` feed and renders the current price — **honestly**. A stale feed is never presented
as current: the value is marked/badged when the round is old, and a non-positive or non-contract feed fails closed
to "unavailable" rather than showing a fabricated price.

### Live price-history chart (`ChainlinkChartSource`)
An `IChartData` source that turns a Chainlink feed into a **live, reactive on-chain chart series**. Each render
reads *current* chain state (`latestRoundData()` + recent rounds), so the chart genuinely updates as new rounds are
written on-chain — a Chainlink heartbeat or deviation update moves the chart. Bind it to a chart component:

```ts
// a chart bound to a Chainlink feed's on-chain price history
compose.slot("chart", { resolver: chainlinkChartSource, arg: encodedFeedArg });
```

This is the honest kind of "live chart": no off-chain data provider, no CDN — the series *is* the on-chain feed's
round history, read at render time.

## Uniswap V3 prices (`UniswapV3PriceResolver`)
Reads a Uniswap V3 pool to render a live spot/TWAP-derived price on-chain — an alternative price source to an
oracle feed, straight from the AMM.

## Aave (`AaveReserveResolver`)
Reads an Aave lending-pool reserve to render live DeFi state (rates, reserve data) — protocol state as on-chain UI.

## Token balances & metadata
- **`Erc20BalanceResolver`** — a live ERC-20 balance for an address, formatted with the token's own decimals.
- **`Erc721MetadataResolver`** / **`NftImageResolver`** — on-chain NFT metadata + media (reference-and-resolve).

## ENS
- **`EnsProfileResolver`** — live ENS identity as UI (name, avatar, records), reverse-resolution with
  forward-verification (a reverse name whose forward record points elsewhere is refused — no spoofed identities).
- **`EnsRecordResolver`** / **`EnsV2Resolver`** — ENS text/records and the ENS-v2 (CCIP / offchain-lookup) path.

## Attestations (EAS)
- **`AttestationAdapter`** — reads Ethereum Attestation Service (EAS) attestations, so an app can render "this
  subject holds attestation X from attester Y" — the on-chain trust/identity signal, rendered honestly and
  fail-closed on a missing/invalid attestation.

## Generic reads (build your own)
For anything not covered by a named integration:
- **`CallResolver`** — a single `view` call → a rendered value.
- **`MultiCallResolver`** — several reads combined (join/sum/reduce).
- **`ComputeResolver`** — a derived value from a small on-chain computation.

Or **[write a custom resolver](../guides/writing-a-resolver.md)** — it's a tiny `view` contract.

## The client read path (how reads are fetched)

The resolvers above define *what* is read and *when* (render time). The runtime client hardens *how* those reads
reach an RPC — all transparent, and none of it changes what a resolver returns (the on-chain floor is unchanged):

- **Multicall batching (aggregate3).** Many reads in a render collapse into a single `eth_call` to a chain's
  Multicall3 via `aggregate3`, so a data-heavy app is one round-trip instead of dozens. Per-call failures come back
  individually, so one reverting read still fails closed on its own without sinking the batch.
- **Block-pinning.** A batch is pinned to one block number, so every value in a render is a **consistent snapshot**
  of the same block — no tearing between reads taken microseconds apart.
- **Caching with honest freshness.** Results are cached in-memory with a TTL that is **clamped to the source's
  `maxStaleSeconds`** — a value can never be served staler than the resolver itself would allow. Reads a caller
  marks immutable can opt into a persistent (IndexedDB) cache; everything else stays per-session.
- **RPC failover + bounded retry.** Each request has a timeout and a bounded retry, and the client fails over across
  a chain's configured RPCs, so a single flaky endpoint doesn't blank the UI.

None of this is a trust concession: the grade, the fail-closed behaviour, and the escaping below all still hold —
these mechanisms only make the same on-chain reads faster and more resilient.

## The common guarantee
Every integration is a `view` read → **Grade A** (an on-chain read never lowers the grade), **fail-closed** (a
reverting/stale/missing source shows an honest fallback, never a fabricated value), and **escaped** (a source can
never inject markup). Live data, fully on-chain.

## Related
- **[Resolvers & Data Binding](../concepts/resolvers.md)** · **[Resolver Catalog](./resolvers.md)** ·
  **[Bind Live On-Chain Data](../guides/bind-data.md)**
