# Трейсы транзакций: debug_traceTransaction и эндпоинты трейсов Data API

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

## Два способа восстановления дерева вызовов

Трейс транзакции представляет собой восстановленное дерево вызовов исполнения: какой контракт был вызван, с какими входными данными, сколько газа он израсходовал и какие подвызовы совершил. BlockVectra предоставляет доступ к нему через два интерфейса:

* **Методы JSON-RPC `debug_trace`** (такие как `debug_traceTransaction`) — выполняются на узле сети через JSON-RPC эндпоинт, поэтому могут трассировать недавнее состояние, которое узел все еще хранит.
* **Трейсы Data API** — `GET /{chain}/transactions/{hash}/trace` и `GET /{chain}/blocks/{number}/traces` возвращают сохраненные индексированные деревья вызовов через REST.

Оба интерфейса используют один и тот же API key и тарифицируются в CU по весу метода (см. веса ниже). Выбор подходящего зависит от того, нужна ли вам одна транзакция или весь блок целиком, насколько свежей является цель и хотите ли вы пройти весь блок без пагинации.

## Ограничения, действующие для методов debug\_trace

Запросы `debug_trace` принимаются только для методов и трассировщиков (tracers), разрешенных политикой методов конкретной сети:

* **Разрешенные трассировщики**: параметр `tracer` принимает только встроенные нативные трассировщики — `callTracer`, `flatCallTracer`, `prestateTracer`, `4byteTracer`, `noopTracer`, либо может быть опущен для использования стандартного struct logger. Любое другое значение отклоняется с ошибкой JSON-RPC `-32602 tracer not allowed` (не тарифицируется).
* **Таймаут трассировки**: параметр `timeout` должен быть допустимой длительностью и не превышать 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/ru/chains/), а справочник методов доступен на странице [Методы JSON-RPC](https://docs.blockvectra.com/ru/api/json-rpc/methods/).

### Запрос debug\_traceTransaction с callTracer

Приведенный ниже вызов добавляет параметр `tracer` для запроса дерева вызовов:

**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"])
```


## Что предоставляют эндпоинты трейсов Data API

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` и результирующий `CallFrame`, плюс `meta`.

Оба эндпоинта трейсов возвращают стандартный формат `callTracer` Ethereum. Это исключение из правил кодирования Data API для безопасности финансовых вычислений (money-safety): в остальных случаях любое значение, способное превысить `2^53`, сериализуется как десятичная строка; на этих двух эндпоинтах `value`, `gas` и `gasUsed` представляют собой шестнадцатеричные величины с префиксом `0x`, а не десятичные строки. Каждый `CallFrame` содержит `type`, `from`, `gas`, `gasUsed` и `input`; `type` принимает одно из значений: `CALL`, `DELEGATECALL`, `STATICCALL`, `CREATE`, `CREATE2` или `SELFDESTRUCT`. Поле `to` отсутствует для целевого адреса фреймов `CREATE`/`CREATE2`, а `value` отсутствует для фрейма `STATICCALL`. Необязательные поля: `output` (отсутствует, если вызов не вернул данных), `error` (отсутствует при успешном выполнении), `revertReason` (присутствует только при откате с `Error(string)`) и `calls` (вложенные подвызовы в порядке вызова). Дополнительные поля фрейма сохраняются.

Чтобы наглядно представить структуру, ниже приведен скелет полей `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
}
```

### Параметры

* `{chain}` (параметр пути, обязательный): идентификатор сети, значение поля `chain` записи из `GET /chains`. Сопоставление строгое и чувствительное к регистру; псевдонимы и числовые chain ID не принимаются.
* `{hash}` (параметр пути, обязательный для трейса транзакции): 32-байтовый хеш транзакции, префикс `0x` необязателен, допускается любой регистр.
* `{number}` (параметр пути, обязательный для трейсов блока): неотрицательная высота блока.

### Покрытие и финальность

* Оба эндпоинта относятся к возможности `traces`. Сеть без нее возвращает `422 no_coverage`. Список сетей, предоставляющих этот набор данных, регулируется страницей [Поддерживаемые сети](https://docs.blockvectra.com/ru/chains/) и каталогом наборов данных.
* Данные трейсов могут начинаться позже остальной индексированной истории сети. `GET /chains` сообщает границу в поле `coverage.traces_from_block`; запрос до нее или внутри диапазона, который не удалось трассировать, возвращает `422 no_coverage`.
* Для трейсов транзакций: если хеш не найден, возвращается `404 not_found` (для только что отправленной или добытой транзакции повторите попытку через несколько секунд, прежде чем считать ошибку постоянной); если хеш относится к блоку выше `as_of_block`, вместо этого возвращается `409 not_indexed_yet`.
* Эндпоинт трейсов блока принимает номер блока. Значение `{number}` выше `as_of_block` возвращает `409 not_indexed_yet` с указанием `indexed_through`; значение `{number}` на уровне или ниже `as_of_block` отдается немедленно.
* Недавний блок с транзакциями, для которого данные трейсов еще не сформированы, возвращает `503 unavailable` с заголовком `Retry-After`.

### Запрос трейса через 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"]])
```


## Что выбрать

| Типовая задача                                                                           | Что лучше подходит                       | Почему                                                                                                               |
| ---------------------------------------------------------------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Восстановление одной транзакции сразу после ее включения в блок                          | `debug_traceTransaction`                 | Выполняется на текущем состоянии узла; доступность определяется политикой методов сети.                              |
| Чтение сохраненного дерева вызовов одной транзакции                                      | `GET /{chain}/transactions/{hash}/trace` | Возвращает `CallFrame` транзакции напрямую через REST; обслуживается вплоть до `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/ru/guides/billing-rules/).

## Следующие шаги

* [Ознакомьтесь с бесплатным тарифом и ценами](https://blockvectra.com/ru/pricing/#free), чтобы узнать, что включено в ваш аккаунт.
* [Войдите в консоль](https://console.blockvectra.com/login/?next=%2Fkeys%2F), чтобы создать API key.
