Action Templating
Argus allows you to customize the content of your notifications using templating. This enables dynamic messages that include details from the matched blockchain events.
How Templating Works
When a monitor's filter_script
matches an event, the relevant data (e.g., transaction details, log data) is passed to the configured actions. actions that support templating can then use this data to render a custom message.
Templates are typically defined within your actions.yaml
file as part of the action's message
configuration. The exact syntax and available variables will depend on the specific action type and the templating engine it uses (e.g., Handlebars-like syntax for basic fields, or more advanced templating for body
fields).
Available Data for Templating
All notification templates have access to the following top-level fields from the MonitorMatch
object:
monitor_id
: The unique ID of the monitor that triggered the match (integer).monitor_name
: The human-readable name of the monitor (string).action_name
: The name of the action handling this match (string).block_number
: The block number where the match occurred (integer).transaction_hash
: The hash of the transaction associated with the match (string).
Additionally, the following structured objects are always available:
-
tx
: An object containing details about the transaction. This will benull
if the match is log-based.tx.from
: The sender address of the transaction (string).tx.to
: The recipient address of the transaction (string, can be null for contract creations).tx.hash
: The transaction hash (string).tx.value
: The value transferred in the transaction (string, as a large number).tx.gas_limit
: The gas limit for the transaction (integer).tx.nonce
: The transaction nonce (integer).tx.input
: The transaction input data (string).tx.block_number
: The block number where the transaction was included (integer).tx.transaction_index
: The index of the transaction within its block (integer).tx.gas_price
: (Legacy transactions) The gas price (string, as a large number).tx.max_fee_per_gas
: (EIP-1559 transactions) The maximum fee per gas (string, as a large number).tx.max_priority_fee_per_gas
: (EIP-1559 transactions) The maximum priority fee per gas (string, as a large number).tx.gas_used
: (From receipt) The gas used by the transaction (string, as a large number).tx.status
: (From receipt) The transaction status (integer, 1 for success, 0 for failure).tx.effective_gas_price
: (From receipt) The effective gas price (string, as a large number).
-
log
: An object containing details about the log/event. This will benull
if the match is transaction-based.log.address
: The address of the contract that emitted the log (string).log.log_index
: The index of the log within its block (integer).log.name
: The name of the decoded event (string, e.g., "Transfer").log.params
: A map of the event's decoded parameters (e.g.,log.params.from
,log.params.to
,log.params.value
).
Data Types, Conversions, and Custom Filters in Templates
When displaying blockchain data in Jinja2 templates, especially large numerical values, it's essential to use the provided custom filters for proper formatting and mathematical operations.
Handling Large Numbers (BigInts)
Similar to Rhai scripts, large numerical values from the EVM (e.g., tx.value
, log.params.value
) are passed to templates as BigInt
strings. While these raw string values will be displayed if no conversion is applied, it is highly recommended to use conversion filters for a more user-friendly and accurate representation, especially when performing calculations.
Conversion and Utility Filters
Argus provides several custom Jinja2 filters to help you work with blockchain data:
-
ether
: Converts aBigInt
string (representing Wei) into its equivalent decimal value in Ether (18 decimal places).{{ tx.value | ether }} ETH
Example: If
tx.value
is"1500000000000000000"
, the expression{{ tx.value | ether }}
renders1.5
, and the full template would output1.5 ETH
. -
gwei
: Converts aBigInt
string (representing Wei) into its equivalent decimal value in Gwei (9 decimal places).{{ tx.gas_price | gwei }} Gwei
Example: If
tx.gas_price
is"20000000000"
,{{ tx.gas_price | gwei }}
renders20.0
, and the full template would output20.0 Gwei
. -
usdc
: Converts aBigInt
string into its equivalent decimal value for USDC (6 decimal places).{{ log.params.value | usdc }} USDC
Example: If
log.params.value
is"50000000"
,{{ log.params.value | usdc }}
renders50.0
, and the full template would output50.0 USDC
. -
wbtc
: Converts aBigInt
string into its equivalent decimal value for WBTC (8 decimal places).{{ log.params.value | wbtc }} WBTC
Example: If
log.params.value
is"100000000"
,{{ log.params.value | wbtc }}
renders1.0
, and the full template would output1.0 WBTC
. -
decimals(num_decimals)
: A generic filter to convert aBigInt
string into a decimal value with a specified number of decimal places.{{ log.params.tokenAmount | decimals(18) }}
Example: If
log.params.tokenAmount
is"123450000000000000000"
,{{ log.params.tokenAmount | decimals(18) }}
renders123.45
. -
map(attribute)
: Extracts a specificattribute
from each item in an array. This is particularly useful with aggregation policies to get a list of values forsum
oravg
.{{ matches | map(attribute='log.params.value') }}
-
sum
: Calculates the sum of a list of numerical values. Often used in conjunction withmap
and a conversion filter.{{ matches | map(attribute='log.params.value') | sum | wbtc }} WBTC
-
avg
: Calculates the average of a list of numerical values. Often used in conjunction withmap
and a conversion filter.{{ matches | map(attribute='log.params.value') | avg | wbtc }} WBTC
Important: Always apply the appropriate conversion filter (e.g., ether
, usdc
, wbtc
, decimals
) to BigInt
strings before performing mathematical operations like sum
or avg
to ensure accurate results. For example, {{ matches | map(attribute='log.params.value') | sum | wbtc }}
correctly sums the values and then formats them as WBTC.
Example: Generic Webhook Action
actions:
- name: "my-generic-webhook"
webhook:
url: "https://my-service.com/webhook-endpoint"
method: "POST"
message:
title: "New Transaction Alert: {{ monitor_name }}"
body: |
A new match was detected for monitor {{ monitor_name }}.
- **Block Number**: {{ block_number }}
- **Transaction Hash**: {{ transaction_hash }}
- **Contract Address**: {{ log.address }}
- **Log Index**: {{ log.log_index }}
- **Log Name**: {{ log.name }}
- **Log Params**: {{ log.params }}
In this example, {{ monitor_name }}
, {{ block_number }}
, {{ transaction_hash }}
, {{ log.address }}
, {{ log.log_index }}
, {{ log.name }}
, and {{ log.params }}
are placeholders that will be replaced with the actual data at the time of notification.
Example: Slack Notification with Aggregation Policy
When using an aggregation
policy, the template has access to a matches
array, which contains all the MonitorMatch
objects collected during the aggregation window.
actions:
- name: "slack-with-aggregation"
slack:
slack_url: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
message:
title: "Aggregated Event Summary"
body: "This is a summary of events."
policy:
aggregation:
window_secs: 300 # 5 minutes
template:
title: "Event Summary for {{ monitor_name }}"
body: |
In the last 5 minutes there have been {{ matches | length }} new events
{% for match in matches %}
- Tx: {{ match.transaction_hash }} (Block: {{ match.block_number }})
{% endfor %}
Here, {{ matches | length }}
is used to get the count of aggregated matches, and a {% for match in matches %}
loop iterates through each individual match to display its transaction hash and block number.
Refer to the documentation for specific action types to understand their full templating capabilities and the exact syntax to use.
For more practical examples of action templating, including aggregation policies, refer to the Example Gallery.