Usage examples
Learn Chainhook's core functionality through practical examples - predicates, event scopes, reorg handling, and operation modes.
Predicates
Predicates are JSON specifications that tell Chainhook what blockchain events to monitor and how to respond. They follow an if-this-then-that pattern.
{"chain": "stacks","uuid": "1","name": "Monitor STX Transfers","version": 1,"networks": {"mainnet": {"if_this": {"scope": "stx_event","actions": ["transfer"]},"then_that": {"http_post": {"url": "https://api.example.com/stx-transfers","authorization_header": "Bearer secret-token"}},"start_block": 100000}}}
This predicate monitors all STX transfer events starting from block 100,000 and sends them to your webhook endpoint.
Predicate components
{"chain": "bitcoin", // Target blockchain: "bitcoin" or "stacks""uuid": "unique-id-123", // Unique identifier for tracking"name": "My Bitcoin Monitor", // Human-readable name"version": 1, // Predicate version"networks": { // Network-specific configurations"mainnet": { ... },"testnet": { ... }}}
Event scopes
Each blockchain supports different event types. Scopes define what specific events your predicate will match.
Stacks events
{"if_this": {"scope": "contract_call","contract_identifier": "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-oracle-v2-3","method": "update-price"}}
Monitor specific contract function calls. Available Stacks scopes:
stx_event
- STX transfers, mints, burnscontract_call
- Smart contract function callscontract_deployment
- New contract deploymentsprint_event
- Contract print statementsft_event
- Fungible token operationsnft_event
- Non-fungible token operations
Bitcoin events
{"if_this": {"scope": "ordinals_protocol","operation": "inscription_feed"}}
Track Bitcoin ordinal inscriptions. Available Bitcoin scopes:
p2pkh
,p2sh
,p2wpkh
,p2tr
- Address typesordinals_protocol
- Ordinal inscriptionsstacks_protocol
- Stacks-specific Bitcoin operations
Action handlers
Define how Chainhook responds when events match your predicate criteria.
Webhook delivery
{"then_that": {"http_post": {"url": "https://api.myapp.com/events","authorization_header": "Bearer ${WEBHOOK_SECRET}"}}}
Chainhook POSTs matching events to your endpoint with the authorization header.
File output
{"then_that": {"file_append": {"path": "/data/blockchain-events.jsonl"}}}
Append events to a local file, one JSON object per line.
Blockchain reorganizations
Chainhook automatically handles blockchain reorganizations (reorgs) by sending both rollback and apply events.
{"apply": [{"block_identifier": {"index": 792101,"hash": "0x123..."},"transactions": [// New canonical chain transactions]}],"rollback": [{"block_identifier": {"index": 792100,"hash": "0x456..."},"transactions": [// Transactions to rollback]}]}
Your application must handle both event types to maintain data consistency during reorgs.
Handling reorg events
app.post('/chainhook-events', (req, res) => {const { apply, rollback } = req.body;// First, rollback orphaned transactionsif (rollback) {for (const block of rollback) {await removeTransactions(block.transactions);}}// Then apply new canonical transactionsif (apply) {for (const block of apply) {await processTransactions(block.transactions);}}res.status(200).send('OK');});
Operation modes
Chainhook operates in two primary modes depending on your use case.
Scanning mode
Analyze historical blockchain data by scanning archived blocks:
$chainhook predicates scan my-predicate.json --mainnet
Use scanning mode for:
- Testing predicates before deployment
- Analyzing past blockchain events
- Backfilling historical data
Service mode
Monitor live blockchain events in real-time:
$chainhook service start --config-path=config.toml
[http_api]http_port = 20456database_uri = "redis://localhost:6379"[network]mode = "mainnet"bitcoind_rpc_url = "http://localhost:8332"stacks_node_rpc_url = "http://localhost:20443"
Service mode maintains persistent connections to blockchain nodes and processes new blocks as they arrive.
Network configuration
Configure predicates differently for each network environment:
{"networks": {"mainnet": {"start_block": 100000,"if_this": {"scope": "stx_event","actions": ["transfer", "mint"]}},"testnet": {"start_block": 1,"decode_clarity_values": true,"include_proof": true,"if_this": {"scope": "print_event"}}}}
Configuration options
{"start_block": 100000, // Begin scanning from this block"end_block": 200000, // Stop at this block (optional)"expire_after_occurrence": 5000, // Stop after N matches"decode_clarity_values": true, // Decode Clarity data types"include_proof": false, // Include merkle proofs"include_contract_abi": true // Include contract interfaces}