Triggers
A trigger prompts a WAVS service to run. Operators listen for the trigger event specified by the service and execute the corresponding component off-chain. Triggers can be any onchain event emitted from any contract.
Trigger lifecycle
-
A service is deployed with a service.json manifest which contains information on the service and workflow logic (components, triggers, submission logic).
-
Operators maintain lookup maps to track and verify triggers. For EVM and Cosmos events, they map chain names, contract addresses, and event identifiers to trigger IDs. Block interval triggers are tracked by chain name with countdown timers, while cron triggers are managed in a priority queue ordered by execution time.
-
When a trigger is detected, operators verify it against their lookup maps according to trigger type. If a match is found, a TriggerAction is created with the trigger configuration and event data.
-
TriggerAction
has 2 fields:TriggerConfig
which contains the service, workflow, and trigger configuration, andTriggerData
contains the trigger data based on the trigger type.
pub struct TriggerAction {pub config: TriggerConfig, // Contains service_id, workflow_id, and trigger typepub data: TriggerData, // Contains the actual trigger data}pub struct TriggerConfig {pub service_id: ServiceID,pub workflow_id: WorkflowID,pub trigger: Trigger,}pub enum TriggerData {CosmosContractEvent { //For Cosmos event triggerscontract_address: layer_climb_address::Address, /// The address of the contract that emitted the eventchain_name: ChainName, /// The name of the chain where the event was emittedevent: cosmwasm_std::Event, /// The data that was emitted by the contractblock_height: u64, /// The block height where the event was emitted},EvmContractEvent { //For EVM event triggerscontract_address: alloy_primitives::Address, /// The address of the contract that emitted the eventchain_name: ChainName, /// The name of the chain where the event was emittedlog: LogData, /// The raw event logblock_height: u64, /// The block height where the event was emitted},BlockInterval { //For block interval triggerschain_name: ChainName, /// The name of the chain where the blocks are checkedblock_height: u64, /// The block height where the event was emitted},Cron { //For cron triggerstrigger_time: Timestamp, /// The trigger time}}
- The TriggerAction is converted to a WASI-compatible format and passed to the component where it is decoded and processed. The component decodes the incoming event trigger data using the
decode_event_log_data!
macro from thewavs-wasi-utils
crate. Visit the components page for more information on decoding and processing trigger data in your component.
Trigger configuration
Triggers define when and how the component should be executed. Each workflow needs a trigger to be set. They are set in the trigger
field of the service.json
file.
EVM event trigger
This trigger listens for specific events emitted by contracts on EVM-compatible chains, executing the component when a matching event is detected. Event triggers pass raw log data to the component.
"trigger": {"evm_contract_event": {"address": "0x00000000219ab540356cbb839cbe05303d7705fa", // Contract address to monitor"chain_name": "ethereum", // Chain to monitor"event_hash": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" // Event hash (32 bytes)}}
Your evm chain information must be set in wavs.toml
under the [default.chains.evm.<chain_name>]
section:
# Mainnet[default.chains.evm.ethereum]chain_id = "1"ws_endpoint = "wss://eth.drpc.org"http_endpoint = "https://eth.drpc.org"
You'll need to set your EVM chain credential in your .env
file to establish a connection for monitoring the EVM chain:
WAVS_CLI_EVM_CREDENTIAL="0x5ze146f435835b1762ed602088740d201b68fd94bf808f97fd04588f1a63c9ab"
Cosmos event trigger
This trigger monitors events emitted by Cosmos smart contracts, executing your component when a matching event type is detected from the specified contract address. Cosmos event triggers pass the contract data that was emitted by the contract to the component.
"trigger": {"cosmos_contract_event": {"address": {"Cosmos": {"bech32_addr": "neutron1qlaq54uh9f52d3p66q77s6kh9k9ee3vasy8gkdkk3yvgezcs6zts0mkcv4", // Contract address to monitor"prefix_len": 7 // Length of the Bech32 prefix (7 for Neutron)}},"chain_name": "neutron", // Chain to monitor"event_type": "send_nft" // Event type to watch}},
Your chain information must be set in wavs.toml
under the [default.chains.cosmos.<chain_name>]
section:
# == Cosmos chains ==[default.chains.cosmos.neutron]chain_id = "pion-1"bech32_prefix = "neutron"rpc_endpoint = "https://rpc-falcron.pion-1.ntrn.tech"grpc_endpoint = "http://grpc-falcron.pion-1.ntrn.tech:80"gas_price = 0.0053gas_denom = "untrn"
Your Cosmos mnemonic must be set in your .env
file to establish a connection for monitoring the Cosmos chain:
WAVS_CLI_COSMOS_MNEMONIC="large slab plate twenty laundry illegal vacuum phone drum example topic reason"
Cron trigger
Executes your component on a schedule defined by a cron expression, with optional start and end times to control the execution window. If no start or end time is provided, the component will start immediately and run indefinitely. Cron triggers pass the trigger timestamp to the component.
"trigger": {"cron": {"schedule": "0 */5 * * * *", // Every 5 minutes (at 0 seconds)"start_time": 1704067200000000000, // Optional start time in nanoseconds since Unix epoch (2024-01-01T00:00:00Z) (default: null)"end_time": 1735689599000000000 // Optional end time in nanoseconds since Unix epoch (default: null)}}// Cron Expression Format:// * * * * * *// │ │ │ │ │ │// │ │ │ │ │ └── Day of week (0-6, where 0 is Sunday)// │ │ │ │ └──── Month (1-12)// │ │ │ └────── Day of month (1-31)// │ │ └──────── Hour (0-23)// │ └────────── Minute (0-59)// └──────────── Second (0-59)//// Each field can be:// - A number: `5` (exact time)// - A range: `1-5` (1 through 5)// - A list: `1,3,5` (1, 3, and 5)// - A step: `*/5` (every 5 units)// - An asterisk: `*` (every unit)//// Common examples:// - `0 */5 * * * *` - Every 5 minutes (at 0 seconds)// - `0 0 */6 * * *` - Every 6 hours (at 0 minutes and 0 seconds)// - `0 0 0 * * *` - Every day at midnight (00:00:00)// - `0 0 12 * * *` - Every day at noon (12:00:00)// - `0 0 12 1 * *` - Noon on the first day of every month// - `0 0 12 * * 1` - Noon every Monday
Crontab.guru is a helpful tool for making cron expressions.
There may be slight variations in Cron trigger execution time between operators due to network latency and clock drift. Cron triggers are best suited for tasks that don't require precise synchronization between operators:
- Triggering components that don't need exact synchronization.
- Collecting data from external services with monotonic pagination.
- Background tasks where eventual consistency is acceptable.
If you need precise timing synchronization between operators, consider using block-based triggers instead.
Block trigger
Executes your component at regular block intervals on a specified EVM or Cosmos chain, useful for chain-specific operations that need to run periodically. Block interval triggers pass the block height and chain name to the component.
"trigger": {"block_interval": {"chain_name": "ethereum-mainnet","n_blocks": 10,"start_block": null, // Optional blockheight to start"end_block": null // Optional blockheight to end}}