Перейти к основному содержанию
Draft-ссылка открывает Tenderly Simulator с предзаполненной формой. Ничего не запускается, пока получатель не нажмёт Simulate, поэтому ссылкой безопасно делиться в тест-отчётах, pull request’ах или оповещениях. Draft предзаполняет одиночную симуляцию, а не бандл. Он заполняет одну форму транзакции (один row); он не восстанавливает многошаговый бандл.

Формат URL

Ссылка — это маршрут новой симуляции Simulator с query-параметром draft: https://dashboard.tenderly.co/<org>/<project>/simulator/new?draft=<value> <value> — это JSON-полезная нагрузка draft’а, закодированная в UTF-8, а затем в base64url: стандартный base64 с +, заменённым на -, /, заменённым на _, и удалёнными символами заполнения =.
Для разового обмена вам не нужен скрипт. Заполните форму в Simulator и нажмите Copy draft link в заголовке страницы (отображается, когда в бандле одна симуляция). Остальная часть этой страницы предназначена для программной генерации ссылок из CI, тест-отчётов или других инструментов.

Быстрый старт

Минимального draft’а с сырым calldata достаточно для большинства CI-скриптов. Адрес to идёт в contractAddress, а calldata — в rawFunctionInput:
{
  "v": 1,
  "network": { "id": "1" },
  "row": {
    "contractAddress": "0xdac17f958d2ee523a2206206994597c13d831ec7",
    "from": "0xab5801a7d398351b8be11c439e05c5b3259aec9b",
    "inputDataType": "raw",
    "rawFunctionInput": "0xa9059cbb…"
  }
}
Закодируйте эту полезную нагрузку и добавьте её к URL:
import base64, json

payload = {
    "v": 1,
    "network": {"id": "1"},
    "row": {
        "contractAddress": "0xdac17f958d2ee523a2206206994597c13d831ec7",
        "from": "0xab5801a7d398351b8be11c439e05c5b3259aec9b",
        "inputDataType": "raw",
        "rawFunctionInput": "0xa9059cbb…",
    },
}

draft = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=")
url = f"https://dashboard.tenderly.co/<org>/<project>/simulator/new?draft={draft}"
// Node.js
const payload = {
  v: 1,
  network: { id: "1" },
  row: {
    contractAddress: "0xdac17f958d2ee523a2206206994597c13d831ec7",
    from: "0xab5801a7d398351b8be11c439e05c5b3259aec9b",
    inputDataType: "raw",
    rawFunctionInput: "0xa9059cbb…",
  },
};

const draft = Buffer.from(JSON.stringify(payload)).toString("base64url");
const url = `https://dashboard.tenderly.co/<org>/<project>/simulator/new?draft=${draft}`;
# Shell, читая полезную нагрузку из payload.json (GNU coreutils)
DRAFT=$(jq -c . payload.json | basenc --base64url -w0 | tr -d '=')
# Резервный вариант для macOS:
DRAFT=$(jq -c . payload.json | base64 | tr '+/' '-_' | tr -d '=\n')

Полезная нагрузка верхнего уровня

ПолеТипОбязательноОписание
vnumberдаВерсия схемы. Должна быть 1.
network{ "id": string } или nullдаChain id как строка ("1" — Mainnet, "56" — BNB Chain и так далее). Должна быть сетью, включённой в проекте получателя, иначе он получит ошибку «network not available» и пустую форму. Всегда указывайте её. null принимается, но пропускает поиск контракта и оставляет форму в основном непригодной для использования. Chain id см. в Supported Networks.
rowobjectдаПоля формы. См. row fields ниже.

Поля row

Только contractAddress обязательно. Опускайте всё, что вам не нужно. Опущенные поля сохраняют значения по умолчанию формы, а неизвестные дополнительные поля игнорируются.

Контракт и функция

ПолеТипОписание
contractAddressstringОбязательно. Адрес «to». Контракт и его ABI загружаются на стороне получателя при открытии ссылки.
inputDataType"decoded" или "raw"Выбирает режим ввода функции. Используйте "raw" с rawFunctionInput или "decoded" с contractFunction и functionInputs.
rawFunctionInputstringHex calldata (0x…) для raw-режима. ABI не требуется, что делает это самым надёжным вариантом для скриптов.
contractFunctionobject или nullСсылка на функцию в decoded-режиме: { "name": string, "selector"?: string, "signature"?: string }. name обязательно внутри объекта. selector (4-байтовый hex, например "0xa9059cbb") необязателен, но предпочтителен: он сопоставляется первым и точен для перегруженных функций. Без него сопоставление возвращается к name и может выбрать неверную перегрузку. signature служит только для информации.
functionInputsarray или objectЗначения аргументов в decoded-режиме. Предпочтительно: позиционный массив в порядке ABI, например ["0xabc…", "1000000", ["0xa…", "0xb…"]]. Значения — строки, числа или булевы. Аргументы-массивы и кортежи можно передавать нативно как вложенные массивы или объекты без предварительного преобразования в строки. Также принимается ключевая форма { "input_0": … } (это то, что выдаёт кнопка Copy в UI).
contractAbiImportstringПредзаполняет поле «Edit ABI» в приложении. Сопоставление функций при открытии использует только загруженный ABI, поэтому это поле не заставит decoded-режим работать для неверифицированных контрактов. Используйте для них сырое calldata.

Параметры транзакции

ПолеТипОписание
fromstringАдрес отправителя.
gasstring или numberЛимит газа, например "8000000".
gasPricestring или numberЦена газа в wei.
valuestring или numberЗначение нативного токена в wei.

Выбор блока

ПолеТипОписание
blockstring или numberНомер блока для симуляции. Опустите для головы цепочки.
blockIndexstring, number или nullПозиция транзакции внутри блока. null или отсутствие означает начало блока.
endOfBlockbooleantrue запускает симулированную транзакцию после каждой транзакции в блоке (переопределяет blockIndex).
usePendingBlockbooleantrue симулирует на pending-блоке вместо фиксированного номера.
О том, как выбор блока и индекс транзакции работают в UI, см. в Simulation Parameters.

Параметры L2

Эти поля применяются только к сетям OP-stack и Boba.
ПолеТипОписание
depositTxbooleanОтметить как L2 deposit-транзакцию.
systemTxbooleanОтметить как L2 system-транзакцию.
mintstringСумма deposit mint.
l1BlockNumberstringНомер исходного блока L1.
l1TimestampstringМетка времени исходного L1.
l1MessageSenderstringАдрес отправителя сообщения L1.
l1TuringstringДанные Boba Turing.

Переопределения

ПолеТипОписание
blockHeaderOverridesobject{ "number"?: …, "timestamp"?: … }, каждое — строка, число или null. Переопределяет заголовок симулируемого блока.
stateOverridesarrayПереопределения состояния по контрактам: { "id"?: string, "contractAddress": string, "balance": string, "storage"?: [{ "key": string, "value": string }], "code"?: string }. id необязателен и генерируется при отсутствии. balance в wei ("" означает отсутствие переопределения баланса). Ключи и значения storage — 32-байтовый hex.
accessListarrayAccess list EIP-2930: { "address": string, "storageKeys": string[] }.
Два типа переопределений доступны только в UI и не могут быть заданы в draft’е. Настройте их в приложении после открытия ссылки: переопределения ERC-20 fund-address и пользовательские исходники Solidity (функция «Edit source» в приложении).

Валидация

Гидратация draft’а — всё или ничего. Отсутствующее обязательное поле, неверный v или любое поле с неправильным типом отклоняет всю полезную нагрузку: получатель видит «This draft link is invalid or corrupted» и пустую форму. Частичной гидратации нет, так что сломанный скрипт даёт видимый сбой вместо того, чтобы работать наполовину.

Ограничения и советы

  • Держите итоговый URL короче 2000 символов. Приложение отказывается копировать более длинные ссылки, а браузеры и прокси могут их обрезать. Decoded-вызовы с большим количеством входов достигают ~1900.
  • Обнаружение формы полезной нагрузки: заполните форму в UI Simulator, нажмите Copy draft link и декодируйте значение draft из base64url. Результат — заведомо корректная полезная нагрузка для вашего конкретного случая, и это лучший способ правильно получить продвинутые формы (stateOverrides, accessList).
  • ABI контракта загружается при открытии ссылки. Если он не может быть разрешён (неверифицированный контракт), decoded-режим draft’а откроется с заполненным адресом, но без выбранной функции. Raw-режим этому не подвержен.
О полях формы, которые заполняет draft, см. в Simulation Parameters. Чтобы сохранить изменённое состояние как постоянное окружение вместо одноразовой симуляции, используйте Virtual Environments.