# 交易 trace：debug_traceTransaction 與 Data API trace 端點

> Source: https://docs.blockvectra.com/zh-hant/guides/transaction-traces/

## 重建呼叫樹的兩種方式

交易 trace 是一次執行所重建出的呼叫樹：呼叫了哪個合約、帶入什麼輸入、消耗多少 gas，以及發起了哪些子呼叫。BlockVectra 透過兩個介面提供：

* **JSON-RPC `debug_trace` 方法**（例如 `debug_traceTransaction`）——透過 JSON-RPC 端點在該鏈的節點上執行，因此可追蹤節點仍保留的近期狀態。
* **Data API traces**——`GET /{chain}/transactions/{hash}/trace` 與 `GET /{chain}/blocks/{number}/traces` 透過 REST 回傳已儲存、已索引的呼叫樹。

兩者都使用同一把 API key，並依方法權重以 CU 計量（見下方權重）。該選哪一種，取決於你需要單筆交易還是整個區塊、目標有多新，以及你是否想在不分頁的情況下走訪完整區塊。

## debug\_trace 方法適用的限制

`debug_trace` 請求僅在該鏈的方法策略允許的方法與 tracer 範圍內受理：

* **允許的 tracer**：`tracer` 參數只接受內建原生 tracer——`callTracer`、`flatCallTracer`、`prestateTracer`、`4byteTracer`、`noopTracer`，或省略以使用預設 struct logger。其他任何值都會以 JSON-RPC 錯誤 `-32602 tracer not allowed` 拒絕（不計費）。
* **Trace 逾時**：`timeout` 參數必須是有效的 duration，且最多 30s；否則請求會以 `-32602 trace timeout not allowed` 拒絕（不計費）。
* **節點同步防護**：當鏈的節點尚未同步時，除了 `eth_chainId` 之外的每個方法——包括 `debug_trace` 方法——都會回傳 `-32010`（不計費）。
* **狀態視窗**：`debug_traceCall`、`debug_traceBlockByNumber`、`debug_traceTransaction` 與 `debug_traceBlockByHash` 的目標區塊必須在該鏈的狀態視窗內。目標早於視窗，或使用 `safe`、`finalized`、`earliest` 標籤，會回傳 `-32011`（不計費）。
* **雜湊與區塊查詢**：格式錯誤或未知的雜湊會回傳 `-32000 transaction not found` / `block not found`；暫時性失敗會回傳 `-32603 upstream unavailable`（可重試）。不計費。
* **各鏈方法策略**：某條鏈允許哪些 `debug_trace` 方法，由公開的 `GET /v1/chains` 回應發布。請在執行階段讀取，而不要硬編碼方法清單；鏈列於[支援的鏈](https://docs.blockvectra.com/zh-hant/chains/)，方法參考位於 [JSON-RPC 方法](https://docs.blockvectra.com/zh-hant/api/json-rpc/methods/)頁面。

### 使用 callTracer 請求 debug\_traceTransaction

下列呼叫加入 `tracer` 參數以請求呼叫樹：

**cURL**

```bash
export BLOCKVECTRA_API_KEY=rgw_your_api_key

# 加入 "tracer"，使用其中一個允許的原生 tracer 請求呼叫樹。
curl -s "https://api.blockvectra.com/v1/robinhood_mainnet" \
  -H 'Content-Type: application/json' \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "debug_traceTransaction",
    "params": [
      "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
      { "tracer": "callTracer" }
    ]
  }'
```


  **TypeScript**

```ts
const RPC_ENDPOINT = "https://api.blockvectra.com/v1/robinhood_mainnet";

const res = await fetch(RPC_ENDPOINT, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": process.env.BLOCKVECTRA_API_KEY!,
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "debug_traceTransaction",
    params: [
      "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
      { tracer: "callTracer" },
    ],
  }),
});

const body = (await res.json()) as {
  result?: unknown;
  error?: { code: number; message: string };
};

if (body.error) {
  throw new Error(`debug_traceTransaction error ${body.error.code}: ${body.error.message}`);
}
console.log(body.result);

// npx tsx example.mts
```


  **Python**

```python
import os
import requests

RPC_ENDPOINT = "https://api.blockvectra.com/v1/robinhood_mainnet"

res = requests.post(
    RPC_ENDPOINT,
    headers={
        "Content-Type": "application/json",
        "x-api-key": os.environ["BLOCKVECTRA_API_KEY"],
    },
    json={
        "jsonrpc": "2.0",
        "id": 1,
        "method": "debug_traceTransaction",
        "params": [
            "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
            {"tracer": "callTracer"},
        ],
    },
)
res.raise_for_status()
body = res.json()

if "error" in body:
    err = body["error"]
    raise RuntimeError(f"debug_traceTransaction error {err.get('code')}: {err.get('message')}")
print(body["result"])
```


## Data API trace 端點提供什麼

Data API 為兩種範圍回傳已儲存的呼叫樹。兩者都不分頁：`next_cursor` 絕不會出現。

* `GET /{chain}/transactions/{hash}/trace`——以交易雜湊查詢單筆交易的呼叫框架。
* `GET /{chain}/blocks/{number}/traces`——區塊中每筆交易一棵呼叫樹，依 `tx_index` 排序。沒有交易的區塊會回傳 `data: []`。

回應結構為：

* `TxTraceEnvelope`：`data` 直接是 `CallFrame`，另有 `meta`。
* `BlockTracesEnvelope`：`data` 是 `BlockTraceItem` 陣列，每個項目帶有 `txHash` 與 `result` 的 `CallFrame`，另有 `meta`。

兩個 trace 端點都回傳標準的以太坊 `callTracer` 格式。這是 Data API「金額安全」編碼的一項例外：在其他地方，可能超過 `2^53` 的值會序列化為十進位字串；在這兩個端點上，`value`、`gas` 與 `gasUsed` 是 `0x` 開頭的十六進位數量，而非十進位字串。每個 `CallFrame` 都帶有 `type`、`from`、`gas`、`gasUsed` 與 `input`；`type` 為 `CALL`、`DELEGATECALL`、`STATICCALL`、`CREATE`、`CREATE2` 或 `SELFDESTRUCT` 之一。`CREATE`/`CREATE2` 框架的目標沒有 `to`，`STATICCALL` 框架沒有 `value`。選填成員有 `output`（呼叫未回傳資料時不存在）、`error`（成功時不存在）、`revertReason`（僅在 `Error(string)` 回滾時出現）與 `calls`（依呼叫順序排列的巢狀子呼叫）。框架的其他成員會原樣保留。

為具體呈現其結構，以下是 `CallFrame` 的欄位骨架：

```jsonc
{
  "type": "CALL | DELEGATECALL | STATICCALL | CREATE | CREATE2 | SELFDESTRUCT",
  "from": "0x…",                      // 20 位元組地址
  "to": "0x…",                        // CREATE/CREATE2 目標不存在
  "value": "0x…",                     // 0x 開頭的十六進位數量；STATICCALL 不存在
  "gas": "0x…",                       // 0x 開頭的十六進位數量
  "gasUsed": "0x…",                   // 0x 開頭的十六進位數量
  "input": "0x…",
  "output": "0x…",                    // 呼叫未回傳資料時不存在
  "error": "…",                       // 成功時不存在
  "revertReason": "…",                // 除非呼叫以 Error(string) 回滾，否則不存在
  "calls": []                         // 依呼叫順序排列的巢狀子呼叫；葉節點框架不存在
}
```

### 參數

* `{chain}`（路徑參數，必填）：鏈識別碼，即 `GET /chains` 中某個項目的 `chain` 值。採完全相符且區分大小寫；不接受別名與數字 chain ID。
* `{hash}`（路徑參數，交易 trace 必填）：32 位元組交易雜湊，`0x` 前綴為選填，十六進位字元大小寫皆可。
* `{number}`（路徑參數，區塊 traces 必填）：非負的區塊高度。

### 涵蓋範圍與最終性

* 兩個端點都屬於 `traces` 能力。沒有此能力的鏈會回傳 `422 no_coverage`。提供此資料集的鏈以[支援的鏈](https://docs.blockvectra.com/zh-hant/chains/)頁面與資料集目錄為準。
* Trace 資料的起點可能晚於該鏈其餘已索引歷史。`GET /chains` 以 `coverage.traces_from_block` 回報此界限；早於此界限的請求，或落在無法追蹤的區間內，會回傳 `422 no_coverage`。
* 交易 trace：若找不到雜湊，會回傳 `404 not_found`（對於剛提交或剛出塊的交易，請先等待數秒後重試，再視為永久不存在）；若雜湊解析出的區塊高於 `as_of_block`，則改回傳 `409 not_indexed_yet`。
* 區塊 traces 端點接受區塊編號。`{number}` 高於 `as_of_block` 會回傳 `409 not_indexed_yet` 並帶有 `indexed_through`；`{number}` 等於或低於 `as_of_block` 則立即提供。
* 有交易但尚無 trace 資料的近期區塊會回傳 `503 unavailable`，並附帶 `Retry-After` 標頭。

### 從 Data API 請求 trace

**cURL**

```bash
export BLOCKVECTRA_API_KEY=rgw_your_api_key

# 單筆交易的呼叫框架。
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/transactions/0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd/trace" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"

# 區塊中每筆交易一棵呼叫樹。
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/blocks/79900000/traces" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"
```


  **TypeScript**

```ts
const hash = "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd";

const txRes = await fetch(
  `https://api.blockvectra.com/v1/data/robinhood_mainnet/transactions/${hash}/trace`,
  { headers: { "x-api-key": process.env.BLOCKVECTRA_API_KEY! } },
);
const txBody = await txRes.json();
console.log(txBody.data, txBody.meta);

const blockRes = await fetch("https://api.blockvectra.com/v1/data/robinhood_mainnet/blocks/79900000/traces", {
  headers: { "x-api-key": process.env.BLOCKVECTRA_API_KEY! },
});
const blockBody = await blockRes.json();
console.log(blockBody.data.map((item: { txHash: string }) => item.txHash));

// npx tsx example.mts
```


  **Python**

```python
import os
import requests

hash_ = "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
headers = {"x-api-key": os.environ["BLOCKVECTRA_API_KEY"]}

tx = requests.get(
    f"https://api.blockvectra.com/v1/data/robinhood_mainnet/transactions/{hash_}/trace",
    headers=headers,
)
tx.raise_for_status()
tx_body = tx.json()
print(tx_body["data"], tx_body["meta"])

block = requests.get(
    "https://api.blockvectra.com/v1/data/robinhood_mainnet/blocks/79900000/traces",
    headers=headers,
)
block.raise_for_status()
block_body = block.json()
print([item["txHash"] for item in block_body["data"]])
```


## 該選哪一種

| 典型任務               | 較合適                                      | 原因                                                |
| ------------------ | ---------------------------------------- | ------------------------------------------------- |
| 交易剛上鏈後立即重建單筆交易     | `debug_traceTransaction`                 | 它針對節點的目前狀態執行；可用性依該鏈的方法策略而定。                       |
| 讀取單筆交易已儲存的呼叫樹      | `GET /{chain}/transactions/{hash}/trace` | 透過 REST 直接回傳該交易的 `CallFrame`；提供至 `as_of_block`。   |
| 一次請求讀取一個區塊中的所有呼叫樹  | `GET /{chain}/blocks/{number}/traces`    | 以不分頁方式回傳整個區塊，依 `tx_index` 排序；提供至 `as_of_block`。   |
| 追蹤節點仍保留但資料集尚未儲存的狀態 | `debug_trace` 方法                         | Data API 提供至 `as_of_block` 的已儲存資料；節點則可為尚未寫入的區塊作答。 |

## 每次呼叫的 CU

每個方法都依其 CU 權重計費。下方權重讀自平台方案 API：

**單次呼叫的 CU 權重**

| 方法 | 單次呼叫 CU |
| --- | --- |
| `debug_traceBlockByHash` | 100 |
| `debug_traceBlockByNumber` | 100 |
| `debug_traceCall` | 100 |
| `debug_traceTransaction` | 100 |
| `trace_block` | 100 |
| `trace_call` | 100 |
| `trace_get` | 100 |
| `trace_replayTransaction` | 100 |
| `trace_transaction` | 100 |
| `data.block_traces` | 200 |
| `data.transaction_trace` | 200 |

被拒絕的請求不計費。完整計費規則請參閱[哪些情況不計費：錯誤碼與計費規則](https://docs.blockvectra.com/zh-hant/guides/billing-rules/)。

## 下一步

* [查看免費方案與定價](https://blockvectra.com/zh-hant/pricing/#free)，確認你的帳戶包含哪些內容。
* [登入控制台](https://console.blockvectra.com/login/?next=%2Fkeys%2F)建立 API key。
