> ## Documentation Index
> Fetch the complete documentation index at: https://tokenterminal.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> To query the Token Terminal data catalog, read https://tokenterminal.com/docs/catalog/agents-manual.md first. It is the whole catalog as one page: table naming grammar, key columns, partition and cluster rules, units, additivity, and the tables that are documented but not served yet.
> Never query a catalog table on a time bound alone. Also filter its cluster key, which you read from INFORMATION_SCHEMA.COLUMNS; an empty result means the object is a view, whose pruning contract is on its page. Compute is billed to the caller's own Google Cloud project.

# Token transfers

> Every fungible token transfer, joined to the entity that issued it.

One row per fungible token movement in `facts_tokens.transfers`: a transfer, a mint or a burn, on every chain we decode. `amount_raw` is the amount in the token's smallest unit, so divide by `10^decimals` from [`dimensions.tokens`](https://tokenterminal.com/docs/catalog/tokens/registry) to read whole tokens.

## Coverage

Every chain we cover token transfers on.

`acala`
`alephzeroevm`
`algorand`
`aptos`
`arbitrum`
`astar`
`avalanche`
`base`
`berachain`
`blast`
`bob`
`bobanetwork`
`bsc`
`cardano`
`celestia`
`celo`
`centrifuge`
`chainflip`
`cosmoshub`
`dydx`
`ethereum`
`fantom`
`flow`
`flowevm`
`fraxtal`
`gnosis`
`gravityalpha`
`hedera`
`hydradx`
`hydradxevm`
`hyperevm`
`immutablezkevm`
`injective`
`injectiveevm`
`ink`
`interlay`
`iotex`
`katananetwork`
`linea`
`manta`
`mantaatlantic`
`mantra`
`mantrachain`
`mantraevm`
`megaeth`
`monad`
`moonbeam`
`movement`
`near`
`neuroweb`
`noble`
`opbnb`
`optimism`
`osmosis`
`peaq`
`phala`
`plasma`
`polimec`
`polkadex`
`polkadotassethub`
`polygon`
`ripple`
`robinhoodchain`
`ronin`
`rootstock`
`scroll`
`sei`
`seievm`
`solana`
`sonic`
`stacks`
`starknet`
`stellar`
`sui`
`tempo`
`ton`
`tron`
`unichain`
`viction`
`worldchain`
`xai`
`xdc`
`xlayer`
`zksyncera`

## Columns

<table>
  <thead>
    <tr>
      <th width="230">Column</th>
      <th width="120">Type</th>
      <th>Description</th>
    </tr>
  </thead>

  <tbody>
    <tr><td>`partition_key`</td><td>TIMESTAMP</td><td>The month the row belongs to. The table is partitioned on it, so a date filter is cheapest when it names this alongside `block_timestamp`.</td></tr>
    <tr><td>`block_timestamp`</td><td>TIMESTAMP</td><td>When the block was produced.</td></tr>
    <tr><td>`block_number`</td><td>INT64</td><td>Block height, or the slot on Solana.</td></tr>
    <tr><td>`transaction_hash`</td><td>STRING</td><td>Transaction the movement belongs to. Null on `hydradx`, where a transfer can be emitted by a block hook instead of by a transaction.</td></tr>
    <tr><td>`transaction_index`</td><td>INT64</td><td>Position of the transaction in its block. Solana only.</td></tr>
    <tr><td>`outer_event_index`</td><td>INT64</td><td>Enclosing instruction position on Solana. Null on the log-shaped chains, which have one nesting level, and null on Solana wherever the instruction is top level and has nothing enclosing it.</td></tr>
    <tr><td>`event_index`</td><td>INT64</td><td>Position within the transaction: the log index, or the instruction index on Solana.</td></tr>
    <tr><td>`chain_id`</td><td>STRING</td><td>Chain the movement happened on.</td></tr>
    <tr><td>`token_type`</td><td>STRING</td><td>Token standard: `erc20`, `spl` or `trc20`.</td></tr>
    <tr><td>`token_id`</td><td>STRING</td><td>Join key to [`dimensions.tokens`](https://tokenterminal.com/docs/catalog/tokens/registry).</td></tr>
    <tr><td>`token_address`</td><td>STRING</td><td>The token. Filter on this. Null on the Solana transfers whose token account the upstream decode could not resolve, which leaves `token_id` null on the same rows.</td></tr>
    <tr><td>`event_type`</td><td>STRING</td><td>`transfer`, `mint` or `burn`.</td></tr>
    <tr><td>`from_address`</td><td>STRING</td><td>Account debited. Null on a mint.</td></tr>
    <tr><td>`to_address`</td><td>STRING</td><td>Account credited. Null on a burn.</td></tr>
    <tr><td>`to_owner`</td><td>STRING</td><td>Holder behind `to_address`. Solana transfers only: null on exactly the rows where `token_address` is, and always null on mints and burns.</td></tr>
    <tr><td>`authority_address`</td><td>STRING</td><td>Account that authorised the instruction. Solana only.</td></tr>
    <tr><td>`transaction_signer`</td><td>STRING</td><td>Signer of the enclosing transaction. Solana only.</td></tr>
    <tr><td>`executing_account`</td><td>STRING</td><td>Program that executed the instruction. Solana only.</td></tr>
    <tr><td>`amount_raw`</td><td>STRING</td><td>Amount in the token's smallest unit, as a decimal string, because a uint256 exceeds every BigQuery numeric type. Divide by `10^decimals`.</td></tr>
    <tr><td>`surrogate_key`</td><td>BYTES</td><td>Row identity, a 128-bit hash of the columns that define the grain. Stable across rebuilds; compare it with `from_hex`.</td></tr>
  </tbody>
</table>

## Sample queries

> [!WARNING]
>
> This table is large and split by month on `partition_key`. Bound `block_timestamp` and filter `chain_id` on every query, or you read the whole table and the whole table is billed to you.

**One asset, every deployment**

`dimensions.asset_tokens` turns one asset into its deployments, and `dimensions.tokens` has the decimals that turn `amount_raw` into whole tokens.

```sql theme={null}
select
    transfers.block_timestamp,
    deployments.chain_id,
    transfers.from_address,
    transfers.to_address,
    cast(transfers.amount_raw as bignumeric) / pow(10, tokens.decimals) as amount
from `facts_tokens.transfers` as transfers
join `dimensions.asset_tokens` as deployments
    using (token_id)
join `dimensions.tokens` as tokens
    on tokens.token_id = transfers.token_id
where deployments.asset_id = 'usdc'
  and transfers.block_timestamp >= timestamp('2026-08-20')
  and transfers.block_timestamp < timestamp('2026-08-21')
limit 100
```

**Daily volume in USD**

The fact has token amounts, so USD comes from a join to `metrics_tokens.price_daily` on `token_id` and the day the transfer falls in.

```sql theme={null}
select
    timestamp_trunc(transfers.block_timestamp, day) as day,
    round(sum(cast(transfers.amount_raw as bignumeric) / pow(10, tokens.decimals) * prices.price)) as volume_usd
from `facts_tokens.transfers` as transfers
join `dimensions.tokens` as tokens
    using (token_id)
join `dimensions.asset_tokens` as deployments
    on deployments.token_id = transfers.token_id
join `metrics_tokens.price_daily` as prices
    on prices.token_id = transfers.token_id
    and prices.timestamp = timestamp_trunc(transfers.block_timestamp, day)
where deployments.asset_id = 'usdc'
  and transfers.block_timestamp >= timestamp('2026-08-01')
  and transfers.block_timestamp < timestamp('2026-08-08')
group by day
order by day
```

**Counterparties of an account**

`from_address` and `chain_id` together identify the sender, because the same address on two chains is two accounts.

```sql theme={null}
select
    transfers.to_address,
    tokens.symbol,
    count(*) as transfer_count
from `facts_tokens.transfers` as transfers
join `dimensions.tokens` as tokens
    using (token_id)
where transfers.from_address = '0x28c6c06298d514db089934071355e5743bf21d60'
  and transfers.chain_id = 'ethereum'
  and transfers.block_timestamp >= timestamp('2026-08-01')
  and transfers.block_timestamp < timestamp('2026-08-08')
group by transfers.to_address, tokens.symbol
order by transfer_count desc
limit 25
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.