Справочник Alerting API
Введение
Tenderly Alert API позволяет создавать как простые, так и сложные оповещения (Alerts). Простое оповещение состоит из одного правила, например,method_call будет срабатывать, когда транзакция вызывает ваш публичный или внешний метод. Сложное оповещение может содержать несколько условий и сработает только когда все они выполняются. Например, оповещение с method_call и state_change сработает, когда транзакция вызовет указанный метод и изменит указанный слот хранилища.
При определении оповещения через API вам необходимо указать следующее:
- каналы доставки (delivery channels), которые получат уведомление при срабатывании правила. Подробнее о каналах доставки (Delivery Channels).
- массив выражений (expressions), которые вызовут срабатывание оповещения, если все условия, представленные отдельными выражениями, будут выполнены.
Каналы доставки можно создавать только через Dashboard, но получить их можно через API.
Аутентификация
Прежде чем создавать оповещения, вам нужно настроить аутентификацию и идентифицировать ваш проект:- JavaScript
- Shell
- Python
const TENDERLY_API_KEY = 'your_api_key';
const PROJECT_SLUG = 'your_project_slug';
const ACCOUNT_ID = 'me'; // Use 'me' or your specific account ID
// Base configuration for axios
const baseConfig = {
baseURL: 'https://api.tenderly.co/api/v1',
headers: {
'X-Access-Key': TENDERLY_API_KEY,
'Content-Type': 'application/json'
}
};
export TENDERLY_API_KEY="your_api_key"
export PROJECT_SLUG="your_project_slug"
export ACCOUNT_ID="me" # Use 'me' or your specific account ID
import requests
TENDERLY_API_KEY = 'your_api_key'
PROJECT_SLUG = 'your_project_slug'
ACCOUNT_ID = 'me' # Use 'me' or your specific account ID
# Base configuration for requests
base_url = 'https://api.tenderly.co/api/v1'
headers = {
'X-Access-Key': TENDERLY_API_KEY,
'Content-Type': 'application/json'
}
Типы выражений
Для задания правил срабатывания оповещений можно использовать различные типы выражений.| Тип выражения | Мониторинг | Основной сценарий использования | Обязательные аргументы | Необязательные аргументы |
|---|---|---|---|---|
method_call | Определённые вызовы функций в контрактах (прямые или внутренние транзакции) | Отслеживание вызовов важных функций | - line_number: строка, в которой определена функция; call_position: позиция вызова (“first”, “last”, “any”) | Нет |
whitelisted_caller_addresses | Вызовы от определённых адресов | Контроль доступа по allow-list | - addresses: массив Ethereum-адресов | Нет |
blacklisted_caller_addresses | Вызовы от заблокированных адресов | Контроль доступа по block-list | - addresses: массив Ethereum-адресов | Нет |
contract_address | Взаимодействия с конкретным контрактом | Отслеживание всех взаимодействий с контрактом | - address: адрес контракта | - transaction_type: “direct”, “source” или “internal” |
network | События в определённых сетях | Мультичейн-мониторинг | - network_id: ID сети/цепочки | Нет |
tag | Контракты с определёнными тегами | Мониторинг по группам | - tag: строка тега | - transaction_type: “direct”, “source” или “internal” |
tx_status | Успех/неуспех транзакции | Отслеживание неудачных транзакций | Нет | - transaction_success: boolean |
function_params | Значения параметров функций | Отслеживание конкретных входных параметров функций | - address: адрес контракта; function_line_number: строка определения функции; parameter_conditions: массив условий | - Специфичные для параметра опции |
tx_value | Значение транзакции | Отслеживание крупных переводов | - transaction_value: сумма в wei; operator: оператор сравнения | Нет |
emitted_log | События контракта | Отслеживание конкретных событий | - address: адрес контракта; event_name: имя события; event_id: сигнатура события | - match_any: boolean; decode_events: boolean; parameter_conditions: массив условий |
state_change | Изменения состояния контракта | Отслеживание изменений в хранилище | - address: адрес контракта; parameter_conditions: массив условий | - Параметры сравнения (пороговое значение, процент) |
view_function | Результаты read-only функций | Отслеживание вычисляемых значений | - address: адрес контракта; input: ABI-закодированные данные функции; network_id: ID сети | - parameter_condition: сравнение значений |
eth_balance | Изменения баланса ETH | Отслеживание пороговых значений баланса | - address: адрес контракта; threshold: баланс в wei; operator: оператор сравнения | Нет |
erc20_transfer_matcher | Согласованность ERC20-переводов | Проверка корректности переводов | - address: адрес токена; log_name: имя события; balances: имя переменной состояния | Нет |
tx_error | Ошибки транзакции | Отслеживание непредвиденных сбоев | Нет | - addresses_to_ignore: массив адресов |
tx_internal_error | Внутренние ошибки транзакции | Отслеживание сбоев внутренних вызовов | Нет | - addresses_to_match: массив адресов |
no_action | Отсутствие активности | Отслеживание бездействия контракта | - check_after_seconds: пороговое время | - no_log: условия по событиям; no_transaction: условия по транзакциям |
sandwich_transaction | Сэндвич-атаки | Отслеживание MEV-активности | - address: адрес контракта | - transaction_type: “direct”, “source” или “internal” |
Примечания
- Для операторов сравнения (
operator) допустимые значения:>,>=,<,<=,==,!=,contains,notContains - Типы параметров (
parameter_type) включают:uint,int,bool,address,string,byte - Все адреса должны быть валидными Ethereum-адресами (с префиксом
0x, 40 hex-символов) - Значения в wei следует передавать в виде строк для работы с большими числами
- ID сети должны соответствовать целевому блокчейну (например, “1” для Ethereum mainnet)
Примеры простых выражений
Рассмотрим примеры настройки простых правил-выражений.1. Мониторинг вызовов методов
Сценарий: отслеживание вызовов определённых функций в вашем смарт-контракте.- JavaScript
- Shell
- Python
const methodCallAlert = {
name: "Critical Function Call Alert",
description: "Monitors calls to critical functions",
enabled: true,
expressions: [{
type: "method_call",
expression: {
line_number: 123, // Line where function is defined
call_position: "any" // "first", "last", or "any"
}
},
{
"type": "contract_address",
"expression": {
"address": "0xe592427a0aece92de3edee1f18e0157c05861564"
}
}
],
delivery_channels: [{
id: "your_channel_id",
enabled: true
}]
};
await axios.post(
`/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
methodCallAlert,
baseConfig
);
curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
--header "Content-Type: application/json" \
--header "X-Access-Key: ${TENDERLY_API_KEY}" \
--data-raw '{
"name": "Critical Function Call Alert",
"description": "Monitors calls to critical functions",
"enabled": true,
"expressions": [
{
"type": "method_call",
"expression": {
"line_number": 123,
"call_position": "any"
}
},
{
"type": "contract_address",
"expression": {
"address": "0xe592427a0aece92de3edee1f18e0157c05861564"
}
}
],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": true
}]
}'
method_call_alert = {
"name": "Critical Function Call Alert",
"description": "Monitors calls to critical functions",
"enabled": True,
"expressions": [{
"type": "method_call",
"expression": {
"line_number": 123,
"call_position": "any"
}
},
{
"type": "contract_address",
"expression": {
"address": "0xe592427a0aece92de3edee1f18e0157c05861564"
}
}],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": True
}]
}
response = requests.post(
f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
headers=headers,
json=method_call_alert
)
2. Мониторинг изменений состояния
Сценарий: мониторинг изменений переменных состояния контракта, особенно полезен для отслеживания критичных параметров, таких как состояние паузы или пороговые значения баланса.- JavaScript
- Shell
- Python
const stateChangeAlert = {
name: "Critical State Change Alert",
description: "Monitors important state changes",
enabled: true,
expressions: [{
type: "state_change",
expression: {
address: "0x1234....",
parameter_conditions: [
{
parameter_name: "pause",
parameter_type: "bool",
compare_change: true
},
{
parameter_name: "totalSupply",
parameter_type: "uint",
compare_percentage: true,
comparison_value: "5",
operator: ">="
}
]
}
}],
delivery_channels: [{
id: "your_channel_id",
enabled: true
}]
};
await axios.post(
`/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
stateChangeAlert,
baseConfig
);
curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
--header "Content-Type: application/json" \
--header "X-Access-Key: ${TENDERLY_API_KEY}" \
--data-raw '{
"name": "Critical State Change Alert",
"description": "Monitors important state changes",
"enabled": true,
"expressions": [{
"type": "state_change",
"expression": {
"address": "0x1234....",
"parameter_conditions": [
{
"parameter_name": "pause",
"parameter_type": "bool",
"compare_change": true
},
{
"parameter_name": "totalSupply",
"parameter_type": "uint",
"compare_percentage": true,
"comparison_value": "5",
"operator": ">="
}
]
}
}],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": true
}]
}'
state_change_alert = {
"name": "Critical State Change Alert",
"description": "Monitors important state changes",
"enabled": True,
"expressions": [{
"type": "state_change",
"expression": {
"address": "0x1234....",
"parameter_conditions": [
{
"parameter_name": "pause",
"parameter_type": "bool",
"compare_change": True
},
{
"parameter_name": "totalSupply",
"parameter_type": "uint",
"compare_percentage": True,
"comparison_value": "5",
"operator": ">="
}
]
}
}],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": True
}]
}
response = requests.post(
f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
headers=headers,
json=state_change_alert
)
3. Мониторинг событий
Сценарий: мониторинг определённых событий, генерируемых вашими контрактами, с фильтрацией по параметрам.- JavaScript
- Shell
- Python
const eventAlert = {
name: "Large Transfer Event Alert",
description: "Monitors large transfer events",
enabled: true,
expressions: [{
type: "emitted_log",
expression: {
address: "0x1234....",
event_name: "Transfer",
event_id: "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80",
parameter_conditions: [
{
parameter_name: "amount",
parameter_type: "uint",
operator: ">=",
comparison_value: "1000000000000000000" // 1 ETH
}
],
decode_events: true
}
}],
delivery_channels: [{
id: "your_channel_id",
enabled: true
}]
};
await axios.post(
`/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
eventAlert,
baseConfig
);
curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
--header "Content-Type: application/json" \
--header "X-Access-Key: ${TENDERLY_API_KEY}" \
--data-raw '{
"name": "Large Transfer Event Alert",
"description": "Monitors large transfer events",
"enabled": true,
"expressions": [{
"type": "emitted_log",
"expression": {
"address": "0x1234....",
"event_name": "Transfer",
"event_id": "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80",
"parameter_conditions": [
{
"parameter_name": "amount",
"parameter_type": "uint",
"operator": ">=",
"comparison_value": "1000000000000000000"
}
],
"decode_events": true
}
}],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": true
}]
}'
event_alert = {
"name": "Large Transfer Event Alert",
"description": "Monitors large transfer events",
"enabled": True,
"expressions": [{
"type": "emitted_log",
"expression": {
"address": "0x1234....",
"event_name": "Transfer",
"event_id": "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80",
"parameter_conditions": [
{
"parameter_name": "amount",
"parameter_type": "uint",
"operator": ">=",
"comparison_value": "1000000000000000000"
}
],
"decode_events": True
}
}],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": True
}]
}
response = requests.post(
f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
headers=headers,
json=event_alert
)
4. Мониторинг баланса нативного ETH
Сценарий: оповещение о снижении баланса нативного ETH некоторого адреса ниже порогового значения, например, для релеера или операционного кошелька, который должен оставаться пополненным. Ограничьте оповещение сетью и адресом, затем сравните нативный баланс с пороговым значением (в wei).- JavaScript
- Shell
- Python
const balanceAlert = {
name: "Low ETH balance alert",
description: "Alerts when the native ETH balance falls below 0.1 ETH",
enabled: true,
expressions: [
// Scope to a specific network
{
type: "network",
expression: {
network_id: "1" // Ethereum mainnet
}
},
// Scope to the watched address
{
type: "contract_address",
expression: {
address: "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b"
}
},
// Trigger when the native balance drops below the threshold
{
type: "eth_balance",
expression: {
address: "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b",
threshold: "100000000000000000", // 0.1 ETH in wei
operator: "<"
}
}
],
delivery_channels: [{
id: "your_channel_id",
enabled: true
}]
};
await axios.post(
`/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
balanceAlert,
baseConfig
);
curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
--header "Content-Type: application/json" \
--header "X-Access-Key: ${TENDERLY_API_KEY}" \
--data-raw '{
"name": "Low ETH balance alert",
"description": "Alerts when the native ETH balance falls below 0.1 ETH",
"enabled": true,
"expressions": [
{
"type": "network",
"expression": {
"network_id": "1"
}
},
{
"type": "contract_address",
"expression": {
"address": "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b"
}
},
{
"type": "eth_balance",
"expression": {
"address": "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b",
"threshold": "100000000000000000",
"operator": "<"
}
}
],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": true
}]
}'
balance_alert = {
"name": "Low ETH balance alert",
"description": "Alerts when the native ETH balance falls below 0.1 ETH",
"enabled": True,
"expressions": [
{
"type": "network",
"expression": {
"network_id": "1"
}
},
{
"type": "contract_address",
"expression": {
"address": "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b"
}
},
{
"type": "eth_balance",
"expression": {
"address": "0x3b8c2f1a9d7e4605c8a1b2d3e4f5061728394a5b",
"threshold": "100000000000000000",
"operator": "<"
}
}
],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": True
}]
}
response = requests.post(
f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
headers=headers,
json=balance_alert
)
Примеры сложных оповещений
Далее приведены примеры сложных правил-выражений. Оповещение сработает, когда каждое выражение в массивеexpressions выполнено.
1. Система мониторинга безопасности
Сценарий: комплексный мониторинг безопасности, объединяющий несколько условий:- Мониторинг вызовов административных функций
- Отслеживание крупных переводов
- Отслеживание адресов из чёрного списка
- Оповещения об изменениях критичных параметров состояния
- JavaScript
- Shell
- Python
const securityAlert = {
name: "Security Monitoring System",
description: "Comprehensive security monitoring for contract",
enabled: true,
expressions: [
{
"type": "contract_address",
"expression": {
"address": "0xe592427a0aece92de3edee1f18e0157c05861564"
}
},
// Admin function monitoring
{
type: "method_call",
expression: {
line_number: 123,
call_position: "any"
}
},
// Blacklist checking
{
type: "blacklisted_caller_addresses",
expression: {
addresses: [
"0xblacklisted1...",
"0xblacklisted2..."
]
}
},
// Large value transfers
{
type: "tx_value",
expression: {
transaction_value: "100000000000000000000", // 100 ETH
operator: ">"
}
},
// Critical state changes
{
type: "state_change",
expression: {
address: "0x1234....",
parameter_conditions: [
{
parameter_name: "pause",
parameter_type: "bool",
compare_change: true
},
{
parameter_name: "owner",
parameter_type: "address",
compare_change: true
}
]
}
}
],
delivery_channels: [{
id: "your_channel_id",
enabled: true
}]
};
await axios.post(
`/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
securityAlert,
baseConfig
);
curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
--header "Content-Type: application/json" \
--header "X-Access-Key: ${TENDERLY_API_KEY}" \
--data-raw '{
"name": "Security Monitoring System",
"description": "Comprehensive security monitoring for contract",
"enabled": true,
"expressions": [
{
"type": "contract_address",
"expression": {
"address": "0xe592427a0aece92de3edee1f18e0157c05861564"
}
},
{
"type": "method_call",
"expression": {
"line_number": 123,
"call_position": "any"
}
},
{
"type": "blacklisted_caller_addresses",
"expression": {
"addresses": [
"0xblacklisted1...",
"0xblacklisted2..."
]
}
},
{
"type": "tx_value",
"expression": {
"transaction_value": "100000000000000000000",
"operator": ">"
}
},
{
"type": "state_change",
"expression": {
"address": "0x1234....",
"parameter_conditions": [
{
"parameter_name": "pause",
"parameter_type": "bool",
"compare_change": true
},
{
"parameter_name": "owner",
"parameter_type": "address",
"compare_change": true
}
]
}
}
],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": true
}]
}'
security_alert = {
"name": "Security Monitoring System",
"description": "Comprehensive security monitoring for contract",
"enabled": True,
"expressions": [
{
"type": "contract_address",
"expression": {
"address": "0xe592427a0aece92de3edee1f18e0157c05861564"
}
},
{
"type": "method_call",
"expression": {
"line_number": 123,
"call_position": "any"
}
},
{
"type": "blacklisted_caller_addresses",
"expression": {
"addresses": [
"0xblacklisted1...",
"0xblacklisted2..."
]
}
},
{
"type": "tx_value",
"expression": {
"transaction_value": "100000000000000000000",
"operator": ">"
}
},
{
"type": "state_change",
"expression": {
"address": "0x1234....",
"parameter_conditions": [
{
"parameter_name": "pause",
"parameter_type": "bool",
"compare_change": True
},
{
"parameter_name": "owner",
"parameter_type": "address",
"compare_change": True
}
]
}
}
],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": True
}]
}
response = requests.post(
f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
headers=headers,
json=security_alert
)
2. Мониторинг DeFi-протокола
Сценарий: мониторинг DeFi-протокола для:- Крупных сделок/свопов
- Значительного влияния на цену
- Изменений ликвидности
- Неудачных транзакций
- Сэндвич-атак
- JavaScript
- Shell
- Python
const defiMonitor = {
name: "DeFi Protocol Monitor",
description: "Comprehensive DeFi protocol monitoring system",
enabled: true,
expressions: [
// Monitor large swaps via events
{
type: "emitted_log",
expression: {
address: "0xpool_address",
event_name: "Swap",
event_id: "0x...", // Swap event signature
parameter_conditions: [
{
parameter_name: "amountOut",
parameter_type: "uint",
operator: ">=",
comparison_value: "1000000000000000000000" // 1000 tokens
}
],
decode_events: true
}
},
// Monitor liquidity changes
{
type: "state_change",
expression: {
address: "0xpool_address",
parameter_conditions: [
{
parameter_name: "reserve0",
parameter_type: "uint",
compare_percentage: true,
comparison_value: "10",
operator: ">="
},
{
parameter_name: "reserve1",
parameter_type: "uint",
compare_percentage: true,
comparison_value: "10",
operator: ">="
}
]
}
},
// Monitor for sandwich attacks
{
type: "sandwich_transaction",
expression: {
address: "0xpool_address",
transaction_type: "direct"
}
},
// Monitor failed transactions
{
type: "tx_error",
expression: {
addresses_to_ignore: [] // Monitor all addresses
}
}
],
delivery_channels: [{
id: "your_channel_id",
enabled: true
}]
};
await axios.post(
`/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
defiMonitor,
baseConfig
);
curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
--header "Content-Type: application/json" \
--header "X-Access-Key: ${TENDERLY_API_KEY}" \
--data-raw '{
"name": "DeFi Protocol Monitor",
"description": "Comprehensive DeFi protocol monitoring system",
"enabled": true,
"expressions": [
{
"type": "emitted_log",
"expression": {
"address": "0xpool_address",
"event_name": "Swap",
"event_id": "0x...",
"parameter_conditions": [
{
"parameter_name": "amountOut",
"parameter_type": "uint",
"operator": ">=",
"comparison_value": "1000000000000000000000"
}
],
"decode_events": true
}
},
{
"type": "state_change",
"expression": {
"address": "0xpool_address",
"parameter_conditions": [
{
"parameter_name": "reserve0",
"parameter_type": "uint",
"compare_percentage": true,
"comparison_value": "10",
"operator": ">="
},
{
"parameter_name": "reserve1",
"parameter_type": "uint",
"compare_percentage": true,
"comparison_value": "10",
"operator": ">="
}
]
}
},
{
"type": "sandwich_transaction",
"expression": {
"address": "0xpool_address",
"transaction_type": "direct"
}
},
{
"type": "tx_error",
"expression": {
"addresses_to_ignore": []
}
}
],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": true
}]
}'
defi_monitor = {
"name": "DeFi Protocol Monitor",
"description": "Comprehensive DeFi protocol monitoring system",
"enabled": True,
"expressions": [
{
"type": "emitted_log",
"expression": {
"address": "0xpool_address",
"event_name": "Swap",
"event_id": "0x...",
"parameter_conditions": [
{
"parameter_name": "amountOut",
"parameter_type": "uint",
"operator": ">=",
"comparison_value": "1000000000000000000000"
}
],
"decode_events": True
}
},
{
"type": "state_change",
"expression": {
"address": "0xpool_address",
"parameter_conditions": [
{
"parameter_name": "reserve0",
"parameter_type": "uint",
"compare_percentage": True,
"comparison_value": "10",
"operator": ">="
},
{
"parameter_name": "reserve1",
"parameter_type": "uint",
"compare_percentage": True,
"comparison_value": "10",
"operator": ">="
}
]
}
},
{
"type": "sandwich_transaction",
"expression": {
"address": "0xpool_address",
"transaction_type": "direct"
}
},
{
"type": "tx_error",
"expression": {
"addresses_to_ignore": []
}
}
],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": True
}]
}
response = requests.post(
f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
headers=headers,
json=defi_monitor
)
3. Мониторинг ERC20-токена с оповещениями о бездействии
Сценарий: комплексный мониторинг токена, включающий:- Мониторинг переводов
- Проверки баланса
- Проверки согласованности состояния
- Мониторинг бездействия
- JavaScript
- Shell
- Python
const tokenMonitor = {
name: "ERC20 Token Monitor",
description: "Comprehensive ERC20 token monitoring with inactivity alerts",
enabled: true,
expressions: [
// Monitor Transfer event consistency
{
type: "erc20_transfer_matcher",
expression: {
address: "0xtoken_address",
log_name: "Transfer",
balances: "balances"
}
},
// Monitor large transfers
{
type: "emitted_log",
expression: {
address: "0xtoken_address",
event_name: "Transfer",
event_id: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
parameter_conditions: [
{
parameter_name: "value",
parameter_type: "uint",
operator: ">=",
comparison_value: "1000000000000000000000" // 1000 tokens
}
]
}
},
// Monitor total supply changes
{
type: "state_change",
expression: {
address: "0xtoken_address",
parameter_conditions: [
{
parameter_name: "totalSupply",
parameter_type: "uint",
compare_percentage: true,
comparison_value: "1",
operator: ">="
}
]
}
},
// Monitor for inactivity
{
type: "no_action",
expression: {
no_log: {
address: "0xtoken_address",
event_name: "Transfer",
event_id: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
},
check_after_seconds: 86400 // 24 hours
}
}
],
delivery_channels: [{
id: "your_channel_id",
enabled: true
}]
};
await axios.post(
`/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
tokenMonitor,
baseConfig
);
curl -X POST "https://api.tenderly.co/api/v1/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert" \
--header "Content-Type: application/json" \
--header "X-Access-Key: ${TENDERLY_API_KEY}" \
--data-raw '{
"name": "ERC20 Token Monitor",
"description": "Comprehensive ERC20 token monitoring with inactivity alerts",
"enabled": true,
"expressions": [
{
"type": "erc20_transfer_matcher",
"expression": {
"address": "0xtoken_address",
"log_name": "Transfer",
"balances": "balances"
}
},
{
"type": "emitted_log",
"expression": {
"address": "0xtoken_address",
"event_name": "Transfer",
"event_id": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"parameter_conditions": [
{
"parameter_name": "value",
"parameter_type": "uint",
"operator": ">=",
"comparison_value": "1000000000000000000000"
}
]
}
},
{
"type": "state_change",
"expression": {
"address": "0xtoken_address",
"parameter_conditions": [
{
"parameter_name": "totalSupply",
"parameter_type": "uint",
"compare_percentage": true,
"comparison_value": "1",
"operator": ">="
}
]
}
},
{
"type": "no_action",
"expression": {
"no_log": {
"address": "0xtoken_address",
"event_name": "Transfer",
"event_id": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
},
"check_after_seconds": 86400
}
}
],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": true
}]
}'
token_monitor = {
"name": "ERC20 Token Monitor",
"description": "Comprehensive ERC20 token monitoring with inactivity alerts",
"enabled": True,
"expressions": [
{
"type": "erc20_transfer_matcher",
"expression": {
"address": "0xtoken_address",
"log_name": "Transfer",
"balances": "balances"
}
},
{
"type": "emitted_log",
"expression": {
"address": "0xtoken_address",
"event_name": "Transfer",
"event_id": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"parameter_conditions": [
{
"parameter_name": "value",
"parameter_type": "uint",
"operator": ">=",
"comparison_value": "1000000000000000000000"
}
]
}
},
{
"type": "state_change",
"expression": {
"address": "0xtoken_address",
"parameter_conditions": [
{
"parameter_name": "totalSupply",
"parameter_type": "uint",
"compare_percentage": True,
"comparison_value": "1",
"operator": ">="
}
]
}
},
{
"type": "no_action",
"expression": {
"no_log": {
"address": "0xtoken_address",
"event_name": "Transfer",
"event_id": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
},
"check_after_seconds": 86400
}
}
],
"delivery_channels": [{
"id": "your_channel_id",
"enabled": True
}]
}
response = requests.post(
f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
headers=headers,
json=token_monitor
)