# Trace giao dịch: debug_traceTransaction và các endpoint trace của Data API

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

## Hai cách tái dựng cây lời gọi

Trace giao dịch là cây lời gọi được tái dựng từ một lần thực thi: hợp đồng nào được gọi, đầu vào là gì, tiêu thụ bao nhiêu gas và thực hiện những lời gọi con nào. BlockVectra cung cấp qua hai giao diện:

* **Phương thức JSON-RPC `debug_trace`** (như `debug_traceTransaction`) — chạy trên node của chuỗi qua endpoint JSON-RPC, nên có thể trace trạng thái gần đây node vẫn còn lưu.
* **Trace của Data API** — `GET /{chain}/transactions/{hash}/trace` và `GET /{chain}/blocks/{number}/traces` trả cây lời gọi đã lưu và lập chỉ mục qua REST.

Cả hai dùng cùng API key và được đo bằng CU theo trọng số phương thức (xem trọng số bên dưới). Lựa chọn phù hợp phụ thuộc vào việc bạn cần một giao dịch hay toàn bộ khối, thời điểm của mục tiêu và có muốn duyệt toàn bộ khối mà không phân trang hay không.

## Giới hạn áp dụng cho phương thức debug\_trace

Yêu cầu `debug_trace` chỉ được chấp nhận cho phương thức và tracer mà chính sách phương thức của chuỗi cho phép:

* **Tracer được phép**: tham số `tracer` chỉ chấp nhận tracer native tích hợp sẵn — `callTracer`, `flatCallTracer`, `prestateTracer`, `4byteTracer`, `noopTracer`, hoặc bỏ qua để dùng struct logger mặc định. Giá trị khác bị từ chối với lỗi JSON-RPC `-32602 tracer not allowed` (không tính phí).
* **Thời gian chờ trace**: tham số `timeout` phải là khoảng thời gian hợp lệ và tối đa 30s; nếu không, yêu cầu bị từ chối với `-32602 trace timeout not allowed` (không tính phí).
* **Kiểm tra đồng bộ node**: khi node của chuỗi chưa đồng bộ, mọi phương thức trừ `eth_chainId` — gồm cả phương thức `debug_trace` — trả `-32010` (không tính phí).
* **Cửa sổ trạng thái**: `debug_traceCall`, `debug_traceBlockByNumber`, `debug_traceTransaction` và `debug_traceBlockByHash` nhắm tới khối phải nằm trong cửa sổ trạng thái của chuỗi. Mục tiêu trước cửa sổ, hoặc dùng tag `safe`, `finalized` hay `earliest`, trả `-32011` (không tính phí).
* **Tra cứu hash và khối**: hash sai định dạng hoặc không xác định trả `-32000 transaction not found` / `block not found`; lỗi tạm thời trả `-32603 upstream unavailable` (có thể thử lại). Không tính phí.
* **Chính sách phương thức theo chuỗi**: các phương thức `debug_trace` mà chuỗi cho phép được công bố trong phản hồi công khai `GET /v1/chains`. Đọc khi chạy thay vì viết cứng danh sách phương thức; các chuỗi được liệt kê tại [Chuỗi được hỗ trợ](https://docs.blockvectra.com/vi/chains/), và tham chiếu phương thức nằm trong trang [Phương thức JSON-RPC](https://docs.blockvectra.com/vi/api/json-rpc/methods/).

### Yêu cầu debug\_traceTransaction với callTracer

Lệnh gọi dưới đây thêm tham số `tracer` để yêu cầu cây lời gọi:

**cURL**

```bash
export BLOCKVECTRA_API_KEY=rgw_your_api_key

# Add "tracer" to request a call tree with one of the allowed native tracers.
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"])
```


## Các endpoint trace của Data API cung cấp gì

Data API trả cây lời gọi đã lưu cho hai phạm vi. Cả hai đều không phân trang: `next_cursor` không bao giờ xuất hiện.

* `GET /{chain}/transactions/{hash}/trace` — khung lời gọi của một giao dịch, được tra cứu bằng hash giao dịch.
* `GET /{chain}/blocks/{number}/traces` — một cây lời gọi cho mỗi giao dịch trong khối, theo thứ tự `tx_index`. Khối không có giao dịch trả `data: []`.

Cấu trúc phản hồi là:

* `TxTraceEnvelope`: `data` là một `CallFrame` trực tiếp, kèm `meta`.
* `BlockTracesEnvelope`: `data` là mảng `BlockTraceItem`, mỗi phần tử có `txHash` và `CallFrame` trong `result`, kèm `meta`.

Cả hai endpoint trace trả định dạng `callTracer` Ethereum tiêu chuẩn. Đây là ngoại lệ của cách mã hóa số tiền an toàn trong Data API: ở nơi khác, giá trị có thể vượt `2^53` được tuần tự hóa thành chuỗi thập phân; trên hai endpoint này, `value`, `gas` và `gasUsed` là đại lượng thập lục phân có tiền tố `0x`, không phải chuỗi thập phân. Mỗi `CallFrame` có `type`, `from`, `gas`, `gasUsed` và `input`; `type` là một trong `CALL`, `DELEGATECALL`, `STATICCALL`, `CREATE`, `CREATE2` hoặc `SELFDESTRUCT`. `to` không có đối với đích của khung `CREATE`/`CREATE2`, và `value` không có trong khung `STATICCALL`. Các trường tùy chọn là `output` (không có khi lời gọi không trả dữ liệu), `error` (không có khi thành công), `revertReason` (chỉ có khi revert `Error(string)`) và `calls` (lời gọi con lồng nhau theo thứ tự gọi). Các trường bổ sung của khung được giữ nguyên.

Để làm rõ cấu trúc, dưới đây là khung các trường của `CallFrame`:

```jsonc
{
  "type": "CALL | DELEGATECALL | STATICCALL | CREATE | CREATE2 | SELFDESTRUCT",
  "from": "0x…",                      // 20-byte address
  "to": "0x…",                        // absent for a CREATE/CREATE2 target
  "value": "0x…",                     // 0x-prefixed hex quantity; absent for STATICCALL
  "gas": "0x…",                       // 0x-prefixed hex quantity
  "gasUsed": "0x…",                   // 0x-prefixed hex quantity
  "input": "0x…",
  "output": "0x…",                    // absent when the call returned no data
  "error": "…",                       // absent on success
  "revertReason": "…",                // absent unless the call reverted with Error(string)
  "calls": []                         // nested sub-calls in call order; absent for a leaf frame
}
```

### Tham số

* `{chain}` (tham số đường dẫn, bắt buộc): mã định danh chuỗi, là giá trị `chain` của một mục trong `GET /chains`. So khớp chính xác và phân biệt hoa thường; không chấp nhận bí danh hay Chain ID dạng số.
* `{hash}` (tham số đường dẫn, bắt buộc cho trace giao dịch): hash giao dịch 32 byte, tiền tố `0x` tùy chọn, chấp nhận chữ số thập lục phân viết hoa hoặc thường.
* `{number}` (tham số đường dẫn, bắt buộc cho trace khối): độ cao khối không âm.

### Phạm vi bao phủ và tính hoàn tất

* Cả hai endpoint thuộc khả năng `traces`. Chuỗi không có khả năng này trả `422 no_coverage`. Các chuỗi cung cấp bộ dữ liệu này theo trang [Chuỗi được hỗ trợ](https://docs.blockvectra.com/vi/chains/) và danh mục bộ dữ liệu.
* Dữ liệu trace có thể bắt đầu muộn hơn phần lịch sử còn lại đã lập chỉ mục của chuỗi. `GET /chains` báo ranh giới bằng `coverage.traces_from_block`; yêu cầu trước ranh giới, hoặc trong khoảng không thể trace, trả `422 no_coverage`.
* Với trace giao dịch: nếu không tìm thấy hash, trả `404 not_found` (với giao dịch vừa gửi hoặc vừa được đưa vào khối, thử lại sau vài giây trước khi coi lỗi là vĩnh viễn); nếu hash tương ứng với khối cao hơn `as_of_block`, thay vào đó trả `409 not_indexed_yet`.
* Endpoint trace khối nhận số khối. `{number}` cao hơn `as_of_block` trả `409 not_indexed_yet` với `indexed_through`; `{number}` bằng hoặc thấp hơn `as_of_block` được phục vụ ngay.
* Khối gần đây có giao dịch nhưng chưa có dữ liệu trace trả `503 unavailable` với header `Retry-After`.

### Yêu cầu trace từ Data API

**cURL**

```bash
export BLOCKVECTRA_API_KEY=rgw_your_api_key

# One transaction's call frame.
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/transactions/0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd/trace" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"

# One call tree per transaction in a block.
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"]])
```


## Nên dùng cách nào

| Tác vụ điển hình                                            | Lựa chọn phù hợp hơn                     | Lý do                                                                                          |
| ----------------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Tái dựng một giao dịch ngay sau khi được đưa vào khối       | `debug_traceTransaction`                 | Chạy trên trạng thái hiện tại của node; tính khả dụng theo chính sách phương thức của chuỗi.   |
| Đọc cây lời gọi đã lưu của một giao dịch                    | `GET /{chain}/transactions/{hash}/trace` | Trả trực tiếp `CallFrame` của giao dịch qua REST; phục vụ đến `as_of_block`.                   |
| Đọc mọi cây lời gọi trong một khối bằng một yêu cầu         | `GET /{chain}/blocks/{number}/traces`    | Trả toàn bộ khối không phân trang, theo thứ tự `tx_index`; phục vụ đến `as_of_block`.          |
| Trace trạng thái node vẫn còn lưu nhưng bộ dữ liệu chưa lưu | Phương thức `debug_trace`                | Data API phục vụ dữ liệu đã lưu đến `as_of_block`; node có thể trả lời cho khối chưa được ghi. |

## CU mỗi lệnh gọi

Mỗi phương thức được tính phí theo trọng số CU. Trọng số bên dưới được đọc từ API gói dịch vụ của nền tảng:

**Trọng số CU mỗi lệnh gọi**

| Phương thức | CU mỗi lệnh gọi |
| --- | --- |
| `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 |

Yêu cầu bị từ chối không bị tính phí. Xem đầy đủ quy tắc tính phí tại [Những gì không tính phí: mã lỗi và quy tắc tính phí](https://docs.blockvectra.com/en/guides/billing-rules/).

## Các bước tiếp theo

* [Xem gói miễn phí và bảng giá](https://blockvectra.com/vi/pricing/#free) để kiểm tra những gì tài khoản của bạn bao gồm.
* [Đăng nhập bảng điều khiển](https://console.blockvectra.com/login/?next=%2Fkeys%2F) để tạo API key.
