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

# leafage-py

> 查询区块、账户状态和合约返回值的 Leafage Python 接口参考。

Leafage 按指定链和区块读取链上状态。以下示例在 Chaintable Notebook 中运行；Function 中的使用方式见[数据访问](/zh/guides/functions/data-access)。[源码](https://github.com/Chaintable/leafage-py)提供完整实现。

## 创建区块上下文

```python theme={null}
from leafage import ChainState

block = ChainState.get_block_by_height('eth', 25939934)
chain = ChainState('eth', block['id'])
```

### `ChainState(chain_id, block_id)`

| 参数         | 类型    | 说明                  |
| ---------- | ----- | ------------------- |
| `chain_id` | `str` | 链 ID，例如以太坊主网为 `eth` |
| `block_id` | `str` | 要读取状态的区块 ID         |

返回 `ChainState` 对象。需要一致的多次读取时，先确定区块 ID，再复用同一个对象。

## 区块查询

以下接口是类方法，直接通过 `ChainState` 调用。

| 接口                                            | 参数         | 返回值           |
| --------------------------------------------- | ---------- | ------------- |
| `get_latest_block(chain_id)`                  | 链 ID       | 最新区块字典        |
| `get_block_by_height(chain_id, block_height)` | 链 ID、整数高度  | 对应区块字典        |
| `get_block_by_id(chain_id, block_id)`         | 链 ID、区块 ID | 对应区块字典        |
| `check_block_is_valid(chain_id, block_id)`    | 链 ID、区块 ID | 区块是否有效，`bool` |

区块字典包含 `id`、`height`、`timestamp` 等字段；`timestamp` 为 Unix 秒数。不同链可能包含不同的附加字段。

## 账户状态

```python theme={null}
wallet = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'
balance_wei = chain.get_address_balance(wallet)
print(balance_wei)
```

| 接口                                             | 参数                | 返回值                              |
| ---------------------------------------------- | ----------------- | -------------------------------- |
| `chain.get_address_balance(addr)`              | 地址字符串             | 原生代币最小单位的 Python `int`；ETH 为 wei |
| `chain.get_address_code(addr)`                 | 合约地址              | `0x` 开头的字节码字符串                   |
| `chain.get_storage_at(addr, slot)`             | 地址、存储槽，例如 `'0x0'` | `0x` 开头的存储值字符串                   |
| `ChainState.get_address_nonce(chain_id, addr)` | 链 ID、地址           | 最新状态下的 nonce，Python `int`        |

`get_address_nonce()` 使用最新区块，不能据此取得上面 `chain` 对象指定的历史 nonce。其他三个实例方法使用对象的区块上下文。

## 单次合约调用

### `chain.call(contract, method, payload, from_addr=None)`

| 参数          | 说明                                          |
| ----------- | ------------------------------------------- |
| `contract`  | 合约地址                                        |
| `method`    | 含输入和输出类型的签名，如 `balanceOf(address)(uint256)` |
| `payload`   | 位置参数列表；无参数时传 `[]`                           |
| `from_addr` | 可选的调用者地址，用于模拟调用上下文                          |

返回解码后的值。多个输出值返回可解包的结果；整数为 Python `int`。

```python theme={null}
pool = '0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc'
reserve_usdc, reserve_weth, timestamp = chain.call(
    pool, 'getReserves()(uint112,uint112,uint32)', []
)
```

这是读取或模拟合约调用，不会向链上发送交易。

## 批量合约调用

```python theme={null}
usdc = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
values = (
    chain.contract(usdc)
    .method('symbol()(string)', 'decimals()(uint8)')
    .payload([], [])
    .values()
)
print(values)
```

输出为 `['USDC', 6]`。

| 构建步骤                            | 参数及结果                      |
| ------------------------------- | -------------------------- |
| `contract(*contracts)`          | 一个或多个合约地址                  |
| `method(*methods)`              | 一个或多个方法签名；合约和方法不能同时为多项     |
| `payload(*payloads)`            | 每次调用的位置参数列表；纯无参数调用可省略空列表   |
| `from_addr(addr)`               | 设置调用者地址                    |
| `options(raise_on_error=False)` | 容许失败项返回 `None`；默认遇到调用错误抛异常 |
| `values()`                      | 返回结果列表                     |
| `zip(*keys)`                    | 返回键与结果的配对迭代器               |
| `dict(*keys)`                   | 返回调用者指定键对应的结果字典            |

例如，将末尾 `.values()` 改为 `.dict('symbol', 'decimals')`，得到 `{'symbol': 'USDC', 'decimals': 6}`。

## 状态覆盖

`set_block_overrides(value)` 和 `set_state_overrides(value)` 设置模拟调用的区块和账户状态覆盖；对应的 `get_*_overrides()` 返回当前设置。覆盖只影响模拟读取，不修改链上状态。字段规范与完整示例见 [Leafage 源码](https://github.com/Chaintable/leafage-py)。
