Alerting API reference
Introduction
Tenderly’s Alert API allows you to create simple and complex Alerts. A simple alert consists of one rule, for examplemethod_call will get triggered when a transaction invokes your public or external method. A complex alert can have several conditions, and will get triggered when all of them are met. For example, an alert with method_call and state_change will trigger when a transaction calls the given method and updates the specified storage slot.
When defining an Alert using the API, you need to specify the following:
- delivery channels that get notified when alerting rule is triggered. See more about Delivery Channels.
- expressions array that will trigger the alert when all conditions represented by individual expressions are met.
Email, Discord, and Sentry delivery channels can be created via the API (
POST /api/v1/account/{accountId}/delivery-channel). Slack, Telegram, and PagerDuty channels require the OAuth/bot connection flow and can be created only via the Dashboard. All channels can be fetched using the API.Authentication
Before creating alerts, you’ll need to set up authentication and identify your project:- 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'
}
Expression Types
You can use different expression types for specifying Alerts’ trigger rules.| Expression Type | Monitoring | Main Use Case | Required Arguments | Optional Arguments |
|---|---|---|---|---|
method_call | Specific function calls in contracts (direct or internal transactions apply) | Track when important functions are called | - address: Contract address; signature: Object with function_name and input_types (ordered ABI input types, e.g. ["address", "uint256"]) | - transaction_type: “any” (default), “direct”, “source”, or “internal”; parameter_conditions: Array of conditions; not: boolean |
whitelisted_caller_addresses | For calls from specific addresses | Allow-list based access control | - addresses: Array of Ethereum addresses | None |
blacklisted_caller_addresses | For calls from blocked addresses | Block-list based access control | - addresses: Array of Ethereum addresses | None |
contract_address | Specific contract interactions | Track all interactions with a contract | - address: Contract address | - transaction_type: “direct”, “source”, or “internal”; when omitted, both direct and internal calls match |
network | Events on specific networks | Multi-chain monitoring | - network_id: Network/chain ID | None |
tag | Contracts with specific tags | Group-based monitoring | - tag: Tag string | - transaction_type: “direct”, “source”, or “internal”; when omitted, behaves like “internal” |
tx_status | Transaction success/failure | Track failed transactions | None | - transaction_success: boolean |
tx_value | Transaction value | Track large transfers | - transaction_value: Amount in wei; operator: Comparison operator | None |
emitted_log | Contract events | Track specific events | - address: Contract address; event_name: Event name; event_id: Event signature | - match_any: boolean (match logs from any contract); match_non_project_contracts: boolean; decode_events: boolean; parameter_conditions: Array of conditions; not: boolean |
state_change | Contract state changes | Track storage changes | - address: Contract address; parameter_conditions: Array of conditions | - match_any: boolean (match state changes on any contract); match_non_project_contracts: boolean; not: boolean; comparison options (threshold, percentage) |
view_function | Read-only function results | Track computed values | - address: Contract address; input: ABI encoded function data; network_id: Network ID | - parameter_condition: Value comparison; not: boolean |
eth_balance | ETH balance changes | Track balance thresholds | - address: Contract address; threshold: Balance in wei | - operator: Comparison operator (default <=); not: boolean |
erc20_transfer_matcher | ERC20 transfer consistency | Validate transfer mechanics | - address: Token address; log_name: Event name; balances: State variable name | None |
Notes
- These are all the expression types the API accepts. A payload with any other
typevalue is rejected with a400(“Expressions are not in the right format”). - All expressions within an alert are AND-ed: the alert fires only when every expression matches the same transaction. To monitor independent conditions, create a separate alert for each.
- For comparison operators (
operator), valid values are:>,>=,<,<=,==,!=,contains,notContains - Parameter types (
parameter_type) include:uint,int,bool,address,string,slice,array,tuple,fixed_bytes,bytes,hash,function - The expression types
emitted_log,erc20_transfer_matcher,eth_balance,tx_value,method_call,state_change,tx_status, andview_functionsupport an optionalnot: truefield that negates the match eth_balancefires only when a transaction moves the balance across the threshold (from non-matching to matching), not on every transaction while the condition holds- All addresses must be valid Ethereum addresses (
0xprefixed, 40 hex chars) - Wei values should be passed as strings to handle large numbers
- Network IDs should match the target blockchain (e.g., “1” for Ethereum mainnet)
Simple expressions examples
Explore examples of setting up simple expression rules.1. Method Call Monitoring
Use Case: Monitor specific function calls in your smart contract.- JavaScript
- Shell
- Python
const methodCallAlert = {
name: "Critical Function Call Alert",
description: "Monitors calls to critical functions",
enabled: true,
expressions: [{
type: "method_call",
expression: {
address: "0xe592427a0aece92de3edee1f18e0157c05861564",
signature: {
function_name: "unwrapWETH9", // name of the function to match
input_types: ["uint256", "address"] // ordered ABI input types
}
}
},
{
"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": {
"address": "0xe592427a0aece92de3edee1f18e0157c05861564",
"signature": {
"function_name": "unwrapWETH9",
"input_types": ["uint256", "address"]
}
}
},
{
"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": {
"address": "0xe592427a0aece92de3edee1f18e0157c05861564",
"signature": {
"function_name": "unwrapWETH9",
"input_types": ["uint256", "address"]
}
}
},
{
"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. State Change Monitoring
Use Case: Monitor changes in contract state variables, especially useful for tracking critical parameters like paused state or balance thresholds.- 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. Event Monitoring
Use Case: Monitor specific events emitted by your contracts, with parameter filtering.- 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. Native ETH Balance Monitoring
Use Case: Alert when an address’s native ETH balance falls below a threshold, for example a relayer or operations wallet that must stay funded. Scope the alert to a network and an address, then compare the native balance against the threshold (in 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
)
Complex Alert Examples
Explore examples of showing complex expression rules. The alert will get triggered when every expression in theexpressions array is satisfied.
1. Security Monitoring System
Use Case: Comprehensive security monitoring combining multiple conditions:- Monitor admin function calls
- Track large value transfers
- Watch for blacklisted addresses
- Alert on state changes to critical parameters
- 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: {
address: "0xe592427a0aece92de3edee1f18e0157c05861564",
signature: {
function_name: "transferOwnership",
input_types: ["address"]
}
}
},
// 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": {
"address": "0xe592427a0aece92de3edee1f18e0157c05861564",
"signature": {
"function_name": "transferOwnership",
"input_types": ["address"]
}
}
},
{
"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": {
"address": "0xe592427a0aece92de3edee1f18e0157c05861564",
"signature": {
"function_name": "transferOwnership",
"input_types": ["address"]
}
}
},
{
"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 Protocol Monitor
Use Case: Monitor a DeFi pool for:- Large trades/swaps
- Liquidity changes
- Failed transactions
- JavaScript
- Shell
- Python
const defiAlerts = [
// Alert 1: large swaps via events
{
name: "Large Swaps",
description: "Swap events moving 1000+ tokens out of the pool",
enabled: true,
expressions: [{
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
}
}],
delivery_channels: [{ id: "your_channel_id", enabled: true }]
},
// Alert 2: liquidity changes
{
name: "Liquidity Shift",
description: "Pool reserves moved by 10% or more",
enabled: true,
expressions: [{
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: ">="
}
]
}
}],
delivery_channels: [{ id: "your_channel_id", enabled: true }]
},
// Alert 3: failed transactions on the pool
{
name: "Failed Transactions",
description: "Failed transactions involving the pool",
enabled: true,
expressions: [
{
type: "contract_address",
expression: { address: "0xpool_address" }
},
{
type: "tx_status",
expression: { transaction_success: false }
}
],
delivery_channels: [{ id: "your_channel_id", enabled: true }]
}
];
for (const alert of defiAlerts) {
await axios.post(
`/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
alert,
baseConfig
);
}
# Alert 1: large swaps via events
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 Swaps",
"description": "Swap events moving 1000+ tokens out of the pool",
"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
}
}],
"delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
}'
# Alert 2: liquidity changes
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": "Liquidity Shift",
"description": "Pool reserves moved by 10% or more",
"enabled": true,
"expressions": [{
"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": ">="
}
]
}
}],
"delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
}'
# Alert 3: failed transactions on the pool
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": "Failed Transactions",
"description": "Failed transactions involving the pool",
"enabled": true,
"expressions": [
{
"type": "contract_address",
"expression": { "address": "0xpool_address" }
},
{
"type": "tx_status",
"expression": { "transaction_success": false }
}
],
"delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
}'
defi_alerts = [
# Alert 1: large swaps via events
{
"name": "Large Swaps",
"description": "Swap events moving 1000+ tokens out of the pool",
"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
}
}],
"delivery_channels": [{"id": "your_channel_id", "enabled": True}]
},
# Alert 2: liquidity changes
{
"name": "Liquidity Shift",
"description": "Pool reserves moved by 10% or more",
"enabled": True,
"expressions": [{
"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": ">="
}
]
}
}],
"delivery_channels": [{"id": "your_channel_id", "enabled": True}]
},
# Alert 3: failed transactions on the pool
{
"name": "Failed Transactions",
"description": "Failed transactions involving the pool",
"enabled": True,
"expressions": [
{
"type": "contract_address",
"expression": {"address": "0xpool_address"}
},
{
"type": "tx_status",
"expression": {"transaction_success": False}
}
],
"delivery_channels": [{"id": "your_channel_id", "enabled": True}]
}
]
for alert in defi_alerts:
response = requests.post(
f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
headers=headers,
json=alert
)
3. ERC20 Token Monitor
Use Case: Token monitoring including:- Transfer consistency checks
- Large transfer monitoring
- Total supply changes
- JavaScript
- Shell
- Python
const tokenAlerts = [
// Alert 1: Transfer event consistency
{
name: "Transfer Consistency",
description: "Transfer events inconsistent with balance changes",
enabled: true,
expressions: [{
type: "erc20_transfer_matcher",
expression: {
address: "0xtoken_address",
log_name: "Transfer",
balances: "balances"
}
}],
delivery_channels: [{ id: "your_channel_id", enabled: true }]
},
// Alert 2: large transfers
{
name: "Large Transfers",
description: "Transfers of 1000+ tokens",
enabled: true,
expressions: [{
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
}
]
}
}],
delivery_channels: [{ id: "your_channel_id", enabled: true }]
},
// Alert 3: total supply changes
{
name: "Supply Change",
description: "totalSupply moved by 1% or more",
enabled: true,
expressions: [{
type: "state_change",
expression: {
address: "0xtoken_address",
parameter_conditions: [
{
parameter_name: "totalSupply",
parameter_type: "uint",
compare_percentage: true,
comparison_value: "1",
operator: ">="
}
]
}
}],
delivery_channels: [{ id: "your_channel_id", enabled: true }]
}
];
for (const alert of tokenAlerts) {
await axios.post(
`/account/${ACCOUNT_ID}/project/${PROJECT_SLUG}/alert`,
alert,
baseConfig
);
}
# Alert 1: Transfer event consistency
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": "Transfer Consistency",
"description": "Transfer events inconsistent with balance changes",
"enabled": true,
"expressions": [{
"type": "erc20_transfer_matcher",
"expression": {
"address": "0xtoken_address",
"log_name": "Transfer",
"balances": "balances"
}
}],
"delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
}'
# Alert 2: large transfers
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 Transfers",
"description": "Transfers of 1000+ tokens",
"enabled": true,
"expressions": [{
"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"
}
]
}
}],
"delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
}'
# Alert 3: total supply changes
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": "Supply Change",
"description": "totalSupply moved by 1% or more",
"enabled": true,
"expressions": [{
"type": "state_change",
"expression": {
"address": "0xtoken_address",
"parameter_conditions": [
{
"parameter_name": "totalSupply",
"parameter_type": "uint",
"compare_percentage": true,
"comparison_value": "1",
"operator": ">="
}
]
}
}],
"delivery_channels": [{ "id": "your_channel_id", "enabled": true }]
}'
token_alerts = [
# Alert 1: Transfer event consistency
{
"name": "Transfer Consistency",
"description": "Transfer events inconsistent with balance changes",
"enabled": True,
"expressions": [{
"type": "erc20_transfer_matcher",
"expression": {
"address": "0xtoken_address",
"log_name": "Transfer",
"balances": "balances"
}
}],
"delivery_channels": [{"id": "your_channel_id", "enabled": True}]
},
# Alert 2: large transfers
{
"name": "Large Transfers",
"description": "Transfers of 1000+ tokens",
"enabled": True,
"expressions": [{
"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"
}
]
}
}],
"delivery_channels": [{"id": "your_channel_id", "enabled": True}]
},
# Alert 3: total supply changes
{
"name": "Supply Change",
"description": "totalSupply moved by 1% or more",
"enabled": True,
"expressions": [{
"type": "state_change",
"expression": {
"address": "0xtoken_address",
"parameter_conditions": [
{
"parameter_name": "totalSupply",
"parameter_type": "uint",
"compare_percentage": True,
"comparison_value": "1",
"operator": ">="
}
]
}
}],
"delivery_channels": [{"id": "your_channel_id", "enabled": True}]
}
]
for alert in token_alerts:
response = requests.post(
f"{base_url}/account/{ACCOUNT_ID}/project/{PROJECT_SLUG}/alert",
headers=headers,
json=alert
)