⚠️ Alpha · testnets only. ChainRender is in active alpha and deployed on testnets only — Ethereum Sepolia, the Robinhood Chain Testnet, and the Circle Arc Testnet — not on any mainnet. Contracts, addresses, and APIs may change. Do not use with real funds or production assets.
Concepts

Resolvers & Data Binding

A resolver is an on-chain contract that supplies live data to your UI at render time. It's how a ChainRender app shows real, current chain state — a price, a balance, an ENS profile, a chart series — while staying fully on-chain and grade-A.

The idea

Your composition has data slots. Each slot names a resolver and a "kind" of data. When the app renders, the interpreter calls resolver.resolve(kind, args) — a view call — and inlines the (escaped) result. The data is never baked into the app's bytes; it's read live, so the same app always shows current state.

// a slot bound to a live oracle price
compose.slot("feed", { resolver: "0x…", arg: encodedArgs  }) // slot(bind, { resolver, arg })

Why resolvers instead of baking data in

If data were baked into the app's bytes, the app would show stale data forever (and every update would be a new hash). By reading through a resolver at render time, the app stays immutable and current — the bytes say "show the price from this feed," and the price itself is always fresh. This is the separation of structure (immutable, in the hash) from state (live, from resolvers).

The resolver interface

Every resolver implements a tiny interface: supportsKind(kind) (a capability check) and resolve(kind, args) (the read). This uniformity is what lets the interpreter treat all data sources identically, and lets you swap one resolver for another without changing your UI. Some resolvers also implement richer interfaces (IChartData, ITableSource, IRouteSource) for structured data.

Fail-closed, always

A resolver that reverts, runs out of gas, or returns garbage never breaks the render — the slot falls back to an honest "unavailable." A resolver can never inject markup (its output is escaped) and never move value (reads are view). Binding live data adds a READ_CHAIN capability and nothing more.

The built resolver catalog

ChainRender ships a large library of ready resolvers — oracles (Chainlink, Uniswap V3), DeFi (Aave, protocol stats), identity (ENS profile, attested credentials), media (NFT images, generative art, SDF scenes, geo maps), and structured data (charts, tables). See the Resolver Catalog.

Related