Skip to content
119 changes: 119 additions & 0 deletions src/pages/quickstart/querying-tempo.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
---
title: Querying Tempo
description: Write correct analytics queries for Tempo. Covers fee units, TIP-20 decimals, Transfer events, fee_payer attribution, system transactions, and supply.
showOutline: 1
---

import { IndexSupplyQuery } from '../../components/IndexSupplyQuery'

# Querying Tempo

Tempo is EVM-compatible, so most query patterns you already know work here. There are a handful of differences that will silently produce wrong numbers if you carry over Ethereum assumptions.

These examples use [Index Supply](https://www.indexsupply.net) as the indexing provider. Each query runs against Tempo mainnet (chain 4217) — click **Run Query** to execute live.

## 1. Fees are in USD, not ETH

On Ethereum, gas price is in wei (10⁻¹⁸ ETH). On Tempo, it's in **attodollars** (10⁻¹⁸ USD). The fee calculation result is USD. There is no native token.

Round to the nearest microdollar (how fees actually settle):

<IndexSupplyQuery
chainId={4217}
title={'Daily USD Fees'}
query={`SELECT
num / 100000 * 100000 AS block_range,
COUNT(*) AS tx_count,
SUM(gas_price * gas / 1e18) AS usd_fees
FROM txs
WHERE chain = 4217
GROUP BY block_range
ORDER BY block_range DESC
LIMIT 10`}
/>

## 2. TIP-20 tokens use 6 decimals, not 18

Divide token amounts by `1e6`. Using `1e18` gives a result 10¹² times too small.

## 3. Use Transfer events for volume, not tx.value

`tx.value` is always zero on Tempo. All token movement is in `Transfer` events.

<IndexSupplyQuery
chainId={4217}
title={'Recent TIP-20 Transfers'}
query={`SELECT
block_num,
"from",
"to",
value / 1e6 AS amount,
address AS token_address,
tx_hash
FROM transfer
WHERE chain = 4217
ORDER BY block_num DESC
LIMIT 10`}
signatures={["Transfer"]}
/>

`TransferWithMemo` (used by MPP) also emits a standard `Transfer`. Query only `Transfer` to avoid double-counting.

## 4. Use COALESCE(fee_payer, from) for attribution

Sponsored transactions populate a separate `fee_payer` field. Grouping by `from` attributes sponsored activity to the wrong address.

```sql
SELECT COALESCE(fee_payer, "from") AS payer,
COUNT(*) AS tx_count
FROM transactions
GROUP BY 1
ORDER BY 2 DESC;
```

> **Note:** The `fee_payer` column is available on platforms like Dune that decode Tempo-specific fields. In Index Supply's base `txs` table, use `"from"` for sender attribution.

## 5. Exclude system transactions from user metrics

`from = 0x0000…0000` is system-level. Include in raw chain metrics, exclude when measuring users.

## 6. Compute supply from Transfer events, not Mint events

Genesis mints may not emit `Mint`. Derive supply from `Transfer`: mints have `from = 0x0…0`, burns have `to = 0x0…0`.

<IndexSupplyQuery
chainId={4217}
title={'Token Supply from Transfers'}
query={`SELECT
address AS token_address,
SUM(CASE WHEN "from" = '0x0000000000000000000000000000000000000000'
THEN value / 1e6 ELSE 0 END) AS total_minted,
SUM(CASE WHEN "to" = '0x0000000000000000000000000000000000000000'
THEN value / 1e6 ELSE 0 END) AS total_burned
FROM transfer
WHERE chain = 4217
AND ("from" = '0x0000000000000000000000000000000000000000'
OR "to" = '0x0000000000000000000000000000000000000000')
GROUP BY token_address
ORDER BY total_minted DESC
LIMIT 10`}
signatures={["Transfer"]}
/>

## Key addresses

| Contract | Address |
| --- | --- |
| FeeManager | `0xfeec000000000000000000000000000000000000` |
| Stablecoin DEX | `0xdec0000000000000000000000000000000000000` |
| TIP-20 Factory | `0x20fc000000000000000000000000000000000000` |
| pathUSD | `0x20c0000000000000000000000000000000000000` |

## Networks

| | Mainnet | Testnet (Moderato) |
| --- | --- | --- |
| Chain ID | `4217` | `42431` |
| RPC | `https://rpc.tempo.xyz` | `https://rpc.moderato.tempo.xyz` |
| Explorer | `https://explore.tempo.xyz` | `https://explore.testnet.tempo.xyz` |
| Tokenlist | `https://tokenlist.tempo.xyz/list/4217` | `https://tokenlist.tempo.xyz/list/42431` |
7 changes: 7 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ function syncTips(): Plugin {
// Escape angle brackets outside of code blocks/inline code so MDX doesn't
// treat them as JSX (e.g. `Mapping<B256, bool>` in prose).
content = escapeAngleBrackets(content)
// Quote frontmatter `authors:` values that start with a YAML reserved
// character (e.g. `@handle`). Upstream TIPs occasionally include GitHub
// handles like `@0xrusowsky`, which break YAML parsing unless quoted.
content = content.replace(
/^(authors:\s*)([@&*!|>%#`].*)$/m,
(_m, prefix, value) => `${prefix}"${value.replace(/"/g, '\\"')}"`,
)
const outputPath = path.join(outputDir, file.name.replace('.md', '.mdx'))
await fs.writeFile(outputPath, content)
}),
Expand Down
4 changes: 4 additions & 0 deletions vocs.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ export default defineConfig({
text: 'Wallet Developers',
link: '/quickstart/wallet-developers',
},
{
text: 'Querying Tempo',
link: '/quickstart/querying-tempo',
},
{
text: 'Contract Verification',
link: '/quickstart/verify-contracts',
Expand Down
Loading