From 0fed099a752e36e6c0cfe070f66fdecaa26dc1bb Mon Sep 17 00:00:00 2001 From: Brendan Ryan <1572504+brendanjryan@users.noreply.github.com> Date: Sun, 31 May 2026 09:15:18 -0700 Subject: [PATCH 1/4] docs: add hosted TIDX indexer docs --- src/components/TidxQuery.tsx | 276 +++++++++++++++++++++++ src/pages/developer-tools/indexer.mdx | 138 ++++++++++++ src/pages/quickstart/developer-tools.mdx | 6 + vocs.config.ts | 4 + 4 files changed, 424 insertions(+) create mode 100644 src/components/TidxQuery.tsx create mode 100644 src/pages/developer-tools/indexer.mdx diff --git a/src/components/TidxQuery.tsx b/src/components/TidxQuery.tsx new file mode 100644 index 00000000..c7c57013 --- /dev/null +++ b/src/components/TidxQuery.tsx @@ -0,0 +1,276 @@ +'use client' + +import * as React from 'react' +import { Container } from './Container' +import { SqlEditor } from './SqlEditor' + +type Network = { + name: string + chainId: number + endpoint: string +} + +type Preset = { + name: string + description: string + network: 'mainnet' | 'testnet' + engine: 'postgres' | 'clickhouse' + signature?: string + sql: string +} + +type TidxResponse = { + columns: string[] + rows: Array> + row_count: number + engine: string + query_time_ms?: number + ok: boolean +} + +const NETWORKS = { + mainnet: { + name: 'Mainnet', + chainId: 4217, + endpoint: 'https://indexer.tempo.xyz', + }, + testnet: { + name: 'Testnet', + chainId: 42431, + endpoint: 'https://indexer.testnet.tempo.xyz', + }, +} as const satisfies Record + +const PRESETS: Preset[] = [ + { + name: 'Latest blocks', + description: 'Read the most recent blocks from mainnet.', + network: 'mainnet', + engine: 'clickhouse', + sql: `SELECT num, hash, timestamp +FROM blocks +ORDER BY num DESC +LIMIT 5`, + }, + { + name: 'Block count', + description: 'Run a simple aggregate over the blocks table.', + network: 'mainnet', + engine: 'clickhouse', + sql: `SELECT count() AS block_count +FROM blocks`, + }, + { + name: 'Recent transactions', + description: 'Inspect recent testnet transactions.', + network: 'testnet', + engine: 'clickhouse', + sql: `SELECT block_num, hash, "from", "to" +FROM txs +ORDER BY block_num DESC +LIMIT 5`, + }, + { + name: 'Decode Transfer events', + description: 'Use a signature to query decoded event logs.', + network: 'mainnet', + engine: 'clickhouse', + signature: 'Transfer(address,address,uint256)', + sql: `SELECT "from", "to", value, block_num, tx_hash +FROM Transfer +ORDER BY block_num DESC +LIMIT 5`, + }, +] + +function shorten(value: string) { + if (!value.startsWith('0x') || value.length <= 18) return value + return `${value.slice(0, 8)}...${value.slice(-6)}` +} + +function renderValue(value: string | number | boolean | null) { + if (value === null) return null + if (typeof value === 'boolean') return value ? 'true' : 'false' + if (typeof value === 'string') return shorten(value) + return String(value) +} + +export function TidxQuery() { + const [presetIndex, setPresetIndex] = React.useState(0) + const activePreset = PRESETS[presetIndex] ?? PRESETS[0] + const [networkKey, setNetworkKey] = React.useState<'mainnet' | 'testnet'>(activePreset.network) + const [engine, setEngine] = React.useState<'postgres' | 'clickhouse'>(activePreset.engine) + const [signature, setSignature] = React.useState(activePreset.signature ?? '') + const [sql, setSql] = React.useState(activePreset.sql) + const [result, setResult] = React.useState(null) + const [error, setError] = React.useState(null) + const [isLoading, setIsLoading] = React.useState(false) + + const network = NETWORKS[networkKey] + + const applyPreset = (nextIndex: number) => { + const next = PRESETS[nextIndex] ?? PRESETS[0] + setPresetIndex(nextIndex) + setNetworkKey(next.network) + setEngine(next.engine) + setSignature(next.signature ?? '') + setSql(next.sql) + setResult(null) + setError(null) + } + + const runQuery = async () => { + const query = sql.trim() + if (!query) { + setError('Enter a SQL query.') + return + } + + setIsLoading(true) + setError(null) + setResult(null) + + try { + const url = new URL('/query', network.endpoint) + url.searchParams.set('chainId', String(network.chainId)) + url.searchParams.set('engine', engine) + url.searchParams.set('sql', query) + if (signature.trim()) url.searchParams.set('signature', signature.trim()) + + const response = await fetch(url) + const json = await response.json() + + if (!response.ok || json.ok === false) { + const message = + typeof json === 'object' && json !== null && 'error' in json + ? String((json as { error: unknown }).error) + : response.statusText + throw new Error(message) + } + + setResult(json as TidxResponse) + } catch (err) { + setError(err instanceof Error ? err.message : 'Query failed.') + } finally { + setIsLoading(false) + } + } + + return ( + Hosted TIDX Query + } + headerRight={ + + } + > +
+
+ + + +
+ +

{activePreset.description}

+ + + + + + {error && ( +
+ {error} +
+ )} + + {result && ( +
+
+ Rows: {result.row_count} + Engine: {result.engine} + {result.query_time_ms !== undefined && ( + Query time: {result.query_time_ms.toFixed(1)} ms + )} +
+
+ + + + {result.columns.map((column) => ( + + ))} + + + + {result.rows.map((row) => ( + + {result.columns.map((column, cellIndex) => ( + + ))} + + ))} + +
+ {column} +
+ {renderValue(row[cellIndex] ?? null)} +
+
+
+ )} +
+
+ ) +} diff --git a/src/pages/developer-tools/indexer.mdx b/src/pages/developer-tools/indexer.mdx new file mode 100644 index 00000000..13f30a79 --- /dev/null +++ b/src/pages/developer-tools/indexer.mdx @@ -0,0 +1,138 @@ +--- +title: Indexer (TIDX) +description: Query Tempo blocks, transactions, logs, token balances, and decoded events through Tempo's hosted TIDX indexer. +interactive: true +--- + +import { Card, Cards } from 'vocs' +import { TidxQuery } from '../../components/TidxQuery' + +# Indexer (TIDX) + +Tempo provides a free indexing service built on [TIDX](https://github.com/tempoxyz/tidx). It exposes structured Tempo chain data over SQL, with PostgreSQL for point lookups and ClickHouse for analytics queries. + +Use it when you need block, transaction, log, token, holder, or decoded event data without running your own indexing pipeline. + +## Hosted endpoints + +The public hosted endpoints are unauthenticated, read-only, and CORS-enabled. + +| Network | URL | Chain ID | +| --- | --- | --- | +| Mainnet | `https://indexer.tempo.xyz` | `4217` | +| Testnet | `https://indexer.testnet.tempo.xyz` | `42431` | + +### Rate limits + +The public hosted endpoints are rate-limited. Responses include `X-Ratelimit-Limit`, `X-Ratelimit-Remaining`, and `X-Ratelimit-Reset` headers. + +Clients should keep queries bounded, include explicit `LIMIT` clauses, avoid polling expensive aggregates, and back off when remaining quota is low. + +## Using in production + +The free hosted TIDX endpoints are useful for prototyping, demos, scripts, and low-volume reads. They do not currently come with uptime, latency, support, or data freshness SLAs. + +For production systems that need stronger guarantees, dedicated support, custom schemas, or predictable low-cost indexing at scale, use an indexing partner from the [Data & Analytics partners page](/ecosystem/data-analytics). + +## Query TIDX + +### Latest blocks + +```bash +curl -G "https://indexer.tempo.xyz/query" \ + --data-urlencode "chainId=4217" \ + --data-urlencode "engine=clickhouse" \ + --data-urlencode "sql=SELECT num, hash, timestamp FROM blocks ORDER BY num DESC LIMIT 5" +``` + +### Decoded events + +```bash +curl -G "https://indexer.tempo.xyz/query" \ + --data-urlencode "chainId=4217" \ + --data-urlencode "engine=clickhouse" \ + --data-urlencode "signature=Transfer(address,address,uint256)" \ + --data-urlencode 'sql=SELECT "from", "to", value, block_num, tx_hash FROM Transfer ORDER BY block_num DESC LIMIT 5' +``` + +### Status + +```bash +curl "https://indexer.tempo.xyz/status" +``` + +## Interactive example + +Run live SQL against the hosted indexer. + + + +## API reference + +| Endpoint | Description | +| --- | --- | +| `GET /health` | Health check | +| `GET /status` | Sync status for indexed chains | +| `GET /query` | Execute a read-only SQL query | +| `GET /views?chainId=` | List ClickHouse materialized views | +| `GET /views/{name}?chainId=` | Get materialized view details | + +`/query` accepts these parameters: + +| Parameter | Required | Description | +| --- | --- | --- | +| `chainId` | yes | `4217` for mainnet or `42431` for testnet | +| `sql` | yes | Read-only SQL query | +| `engine` | no | `postgres` or `clickhouse` | +| `signature` | no | Event signature for decoded event tables | +| `live` | no | Enables SSE streaming for PostgreSQL queries | + +:::info +Creating or deleting materialized views is only available from trusted infrastructure. Use the hosted endpoints for read-only queries, or run your own TIDX instance when you need custom view management. +::: + +## Run your own indexer + +The [TIDX repository](https://github.com/tempoxyz/tidx) includes Docker, source build, configuration, CLI, schema, and materialized view docs. + +```bash +git clone https://github.com/tempoxyz/tidx +cd tidx +docker run -v $(pwd)/config.toml:/config.toml ghcr.io/tempoxyz/tidx up +``` + +See the [TIDX README](https://github.com/tempoxyz/tidx) for the full setup guide and CLI reference. + +## How it works + +TIDX writes chain data into two stores: + +- **PostgreSQL** for point lookups such as a single block, transaction, or address range. +- **ClickHouse** for analytical queries such as aggregates, holder lists, and large scans. + +The `/query` endpoint accepts SQL and can expose decoded events on demand through the `signature` query parameter. For example, passing `Transfer(address,address,uint256)` creates a virtual `Transfer` table for that query. + +TIDX also maintains ClickHouse materialized tables for expensive common reads, such as token balances, token holders, supply, approvals, and address activity. + +## Next steps + + + + + + diff --git a/src/pages/quickstart/developer-tools.mdx b/src/pages/quickstart/developer-tools.mdx index cf4ddf71..95cf6a88 100644 --- a/src/pages/quickstart/developer-tools.mdx +++ b/src/pages/quickstart/developer-tools.mdx @@ -93,6 +93,12 @@ Get started with the [Squid docs](https://docs.squidrouter.com/) or try the [bri ## Data & Analytics +### Tempo Indexer (TIDX) + +[TIDX](/developer-tools/indexer) is Tempo's hosted indexer for querying blocks, transactions, logs, token balances, and decoded events through SQL. Use the public mainnet endpoint at `https://indexer.tempo.xyz` or the testnet endpoint at `https://indexer.testnet.tempo.xyz`. + +The hosted indexer powers explorer-style reads and supports ClickHouse-backed analytical queries for expensive reads like holder lists and token activity. Try the [interactive TIDX example](/developer-tools/indexer#interactive-example) or read the [TIDX README](https://github.com/tempoxyz/tidx) to run your own indexer. + ### Allium [Allium](https://www.allium.so) is an enterprise blockchain data platform that delivers real-time, analytics-ready datasets through a unified schema across chains. Developers can fetch wallet, token, and price data in milliseconds without managing infrastructure, decoding raw data, or inferring transactions—making it easy to focus on building Tempo applications. diff --git a/vocs.config.ts b/vocs.config.ts index 5c302675..8153bcd5 100644 --- a/vocs.config.ts +++ b/vocs.config.ts @@ -760,6 +760,10 @@ export default defineConfig({ text: 'Accounts SDK', link: '/accounts', }, + { + text: 'Indexer (TIDX)', + link: '/developer-tools/indexer', + }, { text: 'CLI', collapsed: true, From e0b24b069160c374024293aea403d4ead59348b4 Mon Sep 17 00:00:00 2001 From: Brendan Ryan <1572504+brendanjryan@users.noreply.github.com> Date: Sun, 31 May 2026 09:48:34 -0700 Subject: [PATCH 2/4] Update indexer.mdx --- src/pages/developer-tools/indexer.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/developer-tools/indexer.mdx b/src/pages/developer-tools/indexer.mdx index 13f30a79..43e78786 100644 --- a/src/pages/developer-tools/indexer.mdx +++ b/src/pages/developer-tools/indexer.mdx @@ -9,7 +9,7 @@ import { TidxQuery } from '../../components/TidxQuery' # Indexer (TIDX) -Tempo provides a free indexing service built on [TIDX](https://github.com/tempoxyz/tidx). It exposes structured Tempo chain data over SQL, with PostgreSQL for point lookups and ClickHouse for analytics queries. +For developers building on Tempo, Tempo Labs provides a free indexing service built on [TIDX](https://github.com/tempoxyz/tidx). It exposes structured Tempo chain data over SQL, with PostgreSQL for point lookups and ClickHouse for analytics queries. Use it when you need block, transaction, log, token, holder, or decoded event data without running your own indexing pipeline. From 4c383c8561b1bcbd6f2d6d32dcdaf056aa62ed2d Mon Sep 17 00:00:00 2001 From: Brendan Ryan <1572504+brendanjryan@users.noreply.github.com> Date: Sun, 31 May 2026 09:15:18 -0700 Subject: [PATCH 3/4] docs: add hosted TIDX indexer docs --- src/components/TidxQuery.tsx | 2 +- src/pages/developer-tools/indexer.mdx | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/TidxQuery.tsx b/src/components/TidxQuery.tsx index c7c57013..d4212d57 100644 --- a/src/components/TidxQuery.tsx +++ b/src/components/TidxQuery.tsx @@ -76,7 +76,7 @@ LIMIT 5`, network: 'mainnet', engine: 'clickhouse', signature: 'Transfer(address,address,uint256)', - sql: `SELECT "from", "to", value, block_num, tx_hash + sql: `SELECT arg0 AS from_address, arg1 AS to_address, arg2 AS value, block_num, tx_hash FROM Transfer ORDER BY block_num DESC LIMIT 5`, diff --git a/src/pages/developer-tools/indexer.mdx b/src/pages/developer-tools/indexer.mdx index 43e78786..c4163387 100644 --- a/src/pages/developer-tools/indexer.mdx +++ b/src/pages/developer-tools/indexer.mdx @@ -52,13 +52,13 @@ curl -G "https://indexer.tempo.xyz/query" \ --data-urlencode "chainId=4217" \ --data-urlencode "engine=clickhouse" \ --data-urlencode "signature=Transfer(address,address,uint256)" \ - --data-urlencode 'sql=SELECT "from", "to", value, block_num, tx_hash FROM Transfer ORDER BY block_num DESC LIMIT 5' + --data-urlencode 'sql=SELECT arg0 AS from_address, arg1 AS to_address, arg2 AS value, block_num, tx_hash FROM Transfer ORDER BY block_num DESC LIMIT 5' ``` -### Status +### Health check ```bash -curl "https://indexer.tempo.xyz/status" +curl "https://indexer.tempo.xyz/health" ``` ## Interactive example @@ -72,7 +72,6 @@ Run live SQL against the hosted indexer. | Endpoint | Description | | --- | --- | | `GET /health` | Health check | -| `GET /status` | Sync status for indexed chains | | `GET /query` | Execute a read-only SQL query | | `GET /views?chainId=` | List ClickHouse materialized views | | `GET /views/{name}?chainId=` | Get materialized view details | @@ -110,7 +109,7 @@ TIDX writes chain data into two stores: - **PostgreSQL** for point lookups such as a single block, transaction, or address range. - **ClickHouse** for analytical queries such as aggregates, holder lists, and large scans. -The `/query` endpoint accepts SQL and can expose decoded events on demand through the `signature` query parameter. For example, passing `Transfer(address,address,uint256)` creates a virtual `Transfer` table for that query. +The `/query` endpoint accepts SQL and can expose decoded events on demand through the `signature` query parameter. For example, passing `Transfer(address,address,uint256)` creates a virtual `Transfer` table with decoded arguments such as `arg0`, `arg1`, and `arg2` for that query. TIDX also maintains ClickHouse materialized tables for expensive common reads, such as token balances, token holders, supply, approvals, and address activity. From ccd6d0c9e7c9092c141f13f3e93dc94cbc249517 Mon Sep 17 00:00:00 2001 From: Derek <256792747+decofe@users.noreply.github.com> Date: Sun, 31 May 2026 18:25:45 +0000 Subject: [PATCH 4/4] docs: document TIDX MPP overflow pricing --- src/pages/developer-tools/indexer.mdx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pages/developer-tools/indexer.mdx b/src/pages/developer-tools/indexer.mdx index c4163387..9efe2f26 100644 --- a/src/pages/developer-tools/indexer.mdx +++ b/src/pages/developer-tools/indexer.mdx @@ -28,9 +28,15 @@ The public hosted endpoints are rate-limited. Responses include `X-Ratelimit-Lim Clients should keep queries bounded, include explicit `LIMIT` clauses, avoid polling expensive aggregates, and back off when remaining quota is low. +### Pricing + +Requests within the public rate limit are free. When a client exceeds the free quota, the hosted indexer returns an MPP challenge for paid overflow access at `$0.001` per request. + +Use an MPP-capable client, such as `tempo request`, for paid overflow traffic. Plain `curl` and browser requests can use the free quota, but they will not automatically pay a `402 Payment Required` challenge. + ## Using in production -The free hosted TIDX endpoints are useful for prototyping, demos, scripts, and low-volume reads. They do not currently come with uptime, latency, support, or data freshness SLAs. +The hosted TIDX endpoints are useful for prototyping, demos, scripts, and low-volume reads. Free requests and MPP paid overflow access do not currently come with uptime, latency, support, or data freshness SLAs. For production systems that need stronger guarantees, dedicated support, custom schemas, or predictable low-cost indexing at scale, use an indexing partner from the [Data & Analytics partners page](/ecosystem/data-analytics).