Documentation Index
Fetch the complete documentation index at: https://docs.moralis.com/llms.txt
Use this file to discover all available pages before exploring further.
Question it answers
“Give me the ERC-20 metadata —The recipe lands one observation per TOKEN-type deployed contract and projects it into a one-row-per-token metadata surface. Token metadata is fixed at deploy time, so there is normally exactly one row pername/symbol/decimals/total_supply— for token 0x….” Mirrors MoralisGET /erc20/metadata.
(chain_id, token_address) — the latest deploy by (block_number, transaction_index) is canonical (defensive against a CREATE2 re-deploy at a reused address).
What you get
One row per token contract, keyed bytoken_address:
| Column | Description |
|---|---|
token_address | The deployed token contract address |
name | ERC-20 token name (raw string; may contain quotes/odd characters) |
symbol | ERC-20 token symbol |
decimals | ERC-20 decimals — apply at read time to scale total_supply and any raw amounts |
total_supply | Raw uint256 supply, no decimals applied — divide by 10^decimals for the human-readable value |
deployer_address | Address that deployed the contract |
block_number, transaction_index | Deploy position (the recency tiebreaker for re-deploys) |
block_timestamp / event_ts | Deploy block time |
symbol is non-empty and ≤ 100 chars, decimals ≤ 50, and deployer_address is non-empty.
Source
The transform reads the per-blockdeployedContracts array, filtered to entries whose type contains TOKEN (the token-contract slice of the block EVM data). Each surviving entry becomes one row. deployedContracts carries no log index, so transaction_index is the intra-block tiebreaker — one deploy per (tx, contract).
Destination
| Destination | Table | Read pattern |
|---|---|---|
| ClickHouse (first-class) | fact_token_metadata | Prefix scan on (chain_id, token_address); read with FINAL, take latest deploy via argMax(…, (block_number, transaction_index)) |
| Postgres | token_metadata (materialized view over token_metadata_observations) | Unique index on (token_address) |
| MySQL | token_metadata (latest-wins trigger state table over observations) | Primary key on (token_address) |
DISTINCT ON (token_address) materialized view; MySQL maintains it incrementally via an AFTER INSERT latest-wins trigger.
Full schema
The complete read table this recipe produces. Keep the columns you need and drop the rest (see Schema & flexibility).total_supply is the raw uint256 stored as text / wide integer (it exceeds standard numeric precision); apply decimals at read time for the human-readable value.
ClickHouse — fact_token_metadata
ClickHouse — fact_token_metadata
sign column drives reorg collapsing — read with FINAL or a sign-aware aggregate, and take the latest deploy with argMax(…, (block_number, transaction_index)). A single-node setup can use CollapsingMergeTree(sign) without the replication path. Because metadata is fixed at deploy, there is normally one row per token; the latest-deploy logic only matters for a CREATE2 re-deploy at a reused address.Postgres — token_metadata
Postgres — token_metadata
REFRESH MATERIALIZED VIEW CONCURRENTLY token_metadata;. total_supply is NUMERIC(76, 0) — the explicit precision keeps large raw supplies from overflowing. MySQL is the same shape with DECIMAL(65,0) for total_supply and VARCHAR(255) for name / symbol, maintaining token_metadata incrementally via an AFTER INSERT latest-wins trigger. position is the block-level cursor used during backfill.Example reads
Metadata for one token, latest deploy wins (ClickHouse):Modes
Shipped defaults: ClickHousehybrid (backfill → realtime), Postgres / MySQL historical (one-shot backfill). For live/reorg-safe ingestion, use ClickHouse — see the overview.
The Postgres / MySQL realtime reorg path needs a single-column
UNIQUE on the position column, but position is block-level (one block can deploy several token contracts), so array-expanded rows can only carry a composite unique. Run realtime/hybrid on ClickHouse, where the collapsing log table corrects reorgs per-block. The Postgres / MySQL configs are intended for historical backfill — a once-off metadata census is the dominant use of this recipe anyway.Multichain
The recipe is chain-parametrized via thechain setting — point it at any supported EVM chain. The vendor_event_id already includes chain_id, tx_hash, transaction_index, and token_address, so rows stay unique without the Solana log-index widening other recipes need. Note that SPL token metadata does not flow through deployedContracts the way EVM contract deploys do — this recipe is EVM-shaped.
Fidelity gaps
The core on-chain fields —token_address, name, symbol, decimals, total_supply, plus block_number and deployer_address — are fully sourced. A few enrichment fields GET /erc20/metadata returns are not sourced here, as they come from off-chain or separate pipelines:
logo/thumbnail/logo_hash— off-chain logo CDN assets.validated/possible_spam/verified_contract— Moralis spam & verification heuristics.categories— editorial token categorisation.created_at(wall-clock) — this recipe carries on-chainblock_number/block_timestampinstead.
total_supply is the raw uint256 with no decimals applied — divide by 10^decimals for the human-readable supply.
Related
Token Holders
All non-zero holders of a token — pair with metadata for decimals and symbol.
Token Analytics
The use case this metadata census powers — the decimals lookup behind every scaled amount.

