> ## 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.

# Transfers

> Cross-chain bridge transfers, with the sending and arriving sides matched.

One row per cross-chain transfer, with the sending and arriving legs matched onto the same row. `transfer_amount_usd` holds the transfer valued once in USD, taken from whichever leg the row is anchored on.

## Columns

<table>
  <thead>
    <tr>
      <th width="280">Column</th>
      <th width="130">Type</th>
      <th>Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>`block_timestamp`</td>
      <td>`TIMESTAMP`</td>
      <td>Time of the block the row is anchored on: the sending leg's block, or the arriving leg's on a row anchored there. Partition column.</td>
    </tr>

    <tr>
      <td>`project_id`</td>
      <td>`STRING`</td>
      <td>Project operating the bridge.</td>
    </tr>

    <tr>
      <td>`product_id`</td>
      <td>`STRING`</td>
      <td>Version of the bridge within that project.</td>
    </tr>

    <tr>
      <td>`app_id`</td>
      <td>`STRING`</td>
      <td>Bridge app the transfer went through: `chainlink-ccip`, `circle-cctp-v1`, `circle-cctp-v2`, `layerzero-v1` or `layerzero-v2`.</td>
    </tr>

    <tr>
      <td>`match_key`</td>
      <td>`STRING`</td>
      <td>Identifier the two legs are paired on, published by the bridge itself, such as LayerZero's GUID or CCIP's message id.</td>
    </tr>

    <tr>
      <td>`match_method`</td>
      <td>`STRING`</td>
      <td>How the two legs were paired. Reads `exact` on a row with both legs.</td>
    </tr>

    <tr>
      <td>`latency_seconds`</td>
      <td>`INT64`</td>
      <td>Seconds the transfer took: the arriving block's time minus the sending block's. Populated on a row with both legs.</td>
    </tr>

    <tr>
      <td>`unmatched_reason`</td>
      <td>`STRING`</td>
      <td>Why a row has a single leg. On a row anchored on its sending leg it reads `source_key_missing`, `destination_chain_not_indexed`, `destination_leg_not_decoded` or `destination_pending_or_failed`; on one anchored on its arriving leg, `destination_key_missing`, `source_chain_not_indexed`, `source_leg_not_decoded` or `source_leg_missing`.</td>
    </tr>

    <tr>
      <td>`intermediary_address`</td>
      <td>`STRING`</td>
      <td>Address of the relayer that relayed the message, on bridges that name one.</td>
    </tr>

    <tr>
      <td>`source_chain_id`</td>
      <td>`STRING`</td>
      <td>Chain the transfer left. Clustering column.</td>
    </tr>

    <tr>
      <td>`source_transaction_hash`</td>
      <td>`STRING`</td>
      <td>Hash of the transaction the sending leg was in.</td>
    </tr>

    <tr>
      <td>`source_log_index`</td>
      <td>`INT64`</td>
      <td>Position of the sending event within its block.</td>
    </tr>

    <tr>
      <td>`source_sub_log_index`</td>
      <td>`INT64`</td>
      <td>Which token inside a sending event that moved more than one, counting up from zero. CCIP sending legs are the ones that move more than one.</td>
    </tr>

    <tr>
      <td>`source_block_timestamp`</td>
      <td>`TIMESTAMP`</td>
      <td>Time of the block the transfer left in.</td>
    </tr>

    <tr>
      <td>`source_block_number`</td>
      <td>`INT64`</td>
      <td>Number of that block.</td>
    </tr>

    <tr>
      <td>`source_sender_address`</td>
      <td>`STRING`</td>
      <td>Address that sent the transfer.</td>
    </tr>

    <tr>
      <td>`source_recipient_address`</td>
      <td>`STRING`</td>
      <td>Address the sending leg names as the recipient.</td>
    </tr>

    <tr>
      <td>`source_token_address`</td>
      <td>`STRING`</td>
      <td>Token contract on the chain the transfer left.</td>
    </tr>

    <tr>
      <td>`source_token_id`</td>
      <td>`STRING`</td>
      <td>That token's key in [`dimensions.tokens`](https://tokenterminal.com/docs/catalog/tokens/registry).</td>
    </tr>

    <tr>
      <td>`source_bridge_contract_address`</td>
      <td>`STRING`</td>
      <td>Bridge contract the sending event came from.</td>
    </tr>

    <tr>
      <td>`source_amount_raw`</td>
      <td>`BIGNUMERIC`</td>
      <td>Amount leaving, in the token's smallest units, before decimals are applied.</td>
    </tr>

    <tr>
      <td>`destination_chain_id`</td>
      <td>`STRING`</td>
      <td>Chain the transfer arrived on. Clustering column.</td>
    </tr>

    <tr>
      <td>`destination_transaction_hash`</td>
      <td>`STRING`</td>
      <td>Hash of the transaction the arriving leg was in.</td>
    </tr>

    <tr>
      <td>`destination_log_index`</td>
      <td>`INT64`</td>
      <td>Position of the arriving event within its block.</td>
    </tr>

    <tr>
      <td>`destination_block_timestamp`</td>
      <td>`TIMESTAMP`</td>
      <td>Time of the block the transfer arrived in.</td>
    </tr>

    <tr>
      <td>`destination_block_number`</td>
      <td>`INT64`</td>
      <td>Number of that block.</td>
    </tr>

    <tr>
      <td>`destination_sender_address`</td>
      <td>`STRING`</td>
      <td>Sender named on the arriving leg.</td>
    </tr>

    <tr>
      <td>`destination_recipient_address`</td>
      <td>`STRING`</td>
      <td>Address that received the transfer.</td>
    </tr>

    <tr>
      <td>`destination_token_address`</td>
      <td>`STRING`</td>
      <td>Token contract on the chain the transfer arrived on.</td>
    </tr>

    <tr>
      <td>`destination_token_id`</td>
      <td>`STRING`</td>
      <td>That token's key in [`dimensions.tokens`](https://tokenterminal.com/docs/catalog/tokens/registry).</td>
    </tr>

    <tr>
      <td>`destination_bridge_contract_address`</td>
      <td>`STRING`</td>
      <td>Bridge contract the arriving event came from.</td>
    </tr>

    <tr>
      <td>`destination_amount_raw`</td>
      <td>`BIGNUMERIC`</td>
      <td>Amount arriving, in the token's smallest units, before decimals are applied.</td>
    </tr>

    <tr>
      <td>`source_transfer_amount`</td>
      <td>`FLOAT64`</td>
      <td>Amount leaving, in whole token units.</td>
    </tr>

    <tr>
      <td>`source_transfer_amount_usd`</td>
      <td>`FLOAT64`</td>
      <td>Amount leaving, in USD, measured on the sending leg.</td>
    </tr>

    <tr>
      <td>`destination_transfer_amount`</td>
      <td>`FLOAT64`</td>
      <td>Amount arriving, in whole token units. On bridges whose arrival event omits the amount, such as CCIP, this takes the sending leg's amount.</td>
    </tr>

    <tr>
      <td>`destination_transfer_amount_usd`</td>
      <td>`FLOAT64`</td>
      <td>Amount arriving, in USD, measured on the arriving leg, with the same fallback.</td>
    </tr>

    <tr>
      <td>`transfer_amount`</td>
      <td>`FLOAT64`</td>
      <td>The transfer counted once, in whole token units: the sending leg's amount, or the arriving leg's on a row anchored there.</td>
    </tr>

    <tr>
      <td>`transfer_amount_usd`</td>
      <td>`FLOAT64`</td>
      <td>The transfer counted once, in USD. Sum this column for total volume; the two directional columns describe the same value from opposite ends.</td>
    </tr>
  </tbody>
</table>

## Sample queries

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

**One day, one chain**

`source_chain_id` is a clustering column alongside the partition, so a single chain over one day reads a fraction of that day. Amounts here are the sending leg's own, in the token's units and in USD.

```sql theme={null}
select
    transfers.block_timestamp,
    transfers.app_id,
    transfers.source_transaction_hash,
    transfers.destination_chain_id,
    transfers.source_token_id,
    transfers.source_transfer_amount,
    transfers.source_transfer_amount_usd
from `facts_bridge_tokens.transfers` as transfers
where transfers.source_chain_id = 'ethereum'
  and transfers.block_timestamp >= timestamp('2026-08-20')
  and transfers.block_timestamp < timestamp('2026-08-21')
order by transfers.source_transfer_amount_usd desc
limit 100
```

**Daily volume by app**

`transfer_amount_usd` takes the sending leg's value, or the arriving leg's on a row anchored there, so each transfer contributes once to the total. Both bounds on `block_timestamp` are what hold the scan to the window.

```sql theme={null}
select
    timestamp_trunc(transfers.block_timestamp, day) as day,
    transfers.app_id,
    sum(transfers.transfer_amount_usd) as volume_usd
from `facts_bridge_tokens.transfers` as transfers
where transfers.block_timestamp >= timestamp('2026-08-01')
  and transfers.block_timestamp < timestamp('2026-08-08')
group by day, transfers.app_id
order by day, volume_usd desc
```

**Routes by volume**

A route is the pair `source_chain_id` and `destination_chain_id`, both filled in on a row with two legs, and both are clustering columns. Ranking on `transfer_amount_usd` keeps each transfer to one route.

```sql theme={null}
select
    transfers.source_chain_id,
    transfers.destination_chain_id,
    sum(transfers.transfer_amount_usd) as volume_usd
from `facts_bridge_tokens.transfers` as transfers
where transfers.block_timestamp >= timestamp('2026-08-01')
  and transfers.block_timestamp < timestamp('2026-08-08')
  and transfers.destination_chain_id is not null
group by transfers.source_chain_id, transfers.destination_chain_id
order by volume_usd desc
limit 25
```

**Latency by app**

`latency_seconds` is filled in on a row with both legs, so the average runs over the transfers whose arrival was found. The median is the more useful figure here: a long tail of slow arrivals pulls the mean up.

```sql theme={null}
select
    transfers.app_id,
    round(avg(transfers.latency_seconds)) as mean_seconds,
    approx_quantiles(transfers.latency_seconds, 100)[offset(50)] as median_seconds
from `facts_bridge_tokens.transfers` as transfers
where transfers.block_timestamp >= timestamp('2026-08-01')
  and transfers.block_timestamp < timestamp('2026-08-02')
  and transfers.latency_seconds is not null
group by transfers.app_id
order by median_seconds
```


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