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

# Data access

> Read Chaintable tables in a Function and use Leafage to query balances and contract state.

Functions can read existing data during computation. Use the BlockDB SDK for tables and Leafage for on-chain balances and contract calls. Place imports inside the function body and pass results back with `return`.

## Read a Chaintable table

This function reads the latest native ETH record from the Ethereum price table. Create a Function in your Space, enter the code, and click **Run**. No parameters are needed.

```python theme={null}
def _():
    from blockdb import TimeTable

    return TimeTable('price.price.eth').get(
        '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
    )
```

The record contains `id`, `time_at`, and `value`: the token ID, price timestamp, and price.

Choose the SDK class for the table type:

| Table type        | Read interface                           |
| ----------------- | ---------------------------------------- |
| Normal Table      | `NormalTable(table_id).get(id)`          |
| Block Event Table | `EventTable(table_id, block_id).get(id)` |
| Block State Table | `StateTable(table_id, block_id).get(id)` |
| Time Table        | `TimeTable(table_id, time_at).get(id)`   |

Omitting the block or time parameter reads the latest value and does not fall back to consensus height. For the default read behavior of each table type, see [How tables work](/guides/tables/model#block-data-and-processing-progress).

**In functions that process blocks**, pass the block ID being processed to read data at that block. The server checks that the table's consensus height covers it.

`get()` returns `None` when no record exists. Handle missing records as needed before accessing fields such as `row['value']`.

See [blockdb-py](/reference/sdk/blockdb-py) for full parameters and batch reads.

## Query an on-chain balance

Leafage locates chain state by Chaintable chain ID and block ID. Ethereum's chain ID is `eth`.

```python theme={null}
def _(address):
    from leafage import ChainState

    block = ChainState.get_latest_block('eth')
    chain = ChainState('eth', block['id'])
    return {
        'block': block,
        'balance_wei': str(chain.get_address_balance(address)),
    }
```

Set the `address` parameter type to `ADDRESS` and test with `0xd8da6bf26964af9d7eed9e03e53415d37aa96045`. The balance is in wei; returning a string preserves integer precision.

## Call a contract

This example reads the Uniswap V2 USDC–ETH pool reserves at a fixed historical block:

```python theme={null}
def _():
    from leafage import ChainState

    block = ChainState.get_block_by_height('eth', 25939934)
    chain = ChainState('eth', block['id'])
    usdc, weth, timestamp = chain.call(
        '0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc',
        'getReserves()(uint112,uint112,uint32)',
        [],
    )
    return {
        'reserve_usdc': str(usdc),
        'reserve_weth': str(weth),
        'timestamp': timestamp,
    }
```

The method signature includes both input and output types. `getReserves()` takes no inputs, so pass an empty list. It returns two reserve values and the update timestamp recorded by the contract.
