Scanning blockchain events
Test predicates by scanning historical blockchain data before deploying them in production.
This guide shows you how to use Chainhook's scanning mode to test predicates against historical blockchain data. Scanning helps validate your predicate logic and understand what events will be captured before going live.
Basic scanning
Test your predicate against historical data by scanning the blockchain:
$chainhook predicates scan my-predicate.json --mainnet
The scan command downloads blockchain data from Hiro Archive (cached after first run) and evaluates your predicate against each block in the specified range.
Scan with specific networks
$chainhook predicates scan predicate.json --mainnet$chainhook predicates scan predicate.json --testnet$chainhook predicates scan predicate.json --devnet
Block range scanning
Limit scanning to specific blocks for faster testing and targeted analysis:
$chainhook predicates scan my-predicate.json \--start-block 150000 \--end-block 150100 \--mainnet
Configure ranges in predicates
{"chain": "stacks","networks": {"mainnet": {"start_block": 150000,"end_block": 151000,"if_this": {"scope": "contract_call","contract_identifier": "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-dao"}}}}
This predicate scans only blocks 150,000 to 151,000, significantly reducing scan time.
Output configuration
Control where scan results are written using the then_that
section.
File output
{"then_that": {"file_append": {"path": "./scan-results.json"}}}
Console output
{"then_that": {"file_append": {"path": "-" // Writes to stdout}}}
Performance optimization
Speed up your scans by being specific about what you're looking for.
Use specific scopes
{"if_this": {"scope": "contract_call","contract_identifier": "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-dao","method": "collateralize-and-mint"}}
Targeting specific contracts and methods scans much faster than broad scopes.
Limit occurrences
{"networks": {"mainnet": {"expire_after_occurrence": 100,"if_this": {"scope": "nft_event","actions": ["mint"]}}}}
Stop scanning after finding 100 matching events.
Common scanning patterns
Learn from these practical examples of scanning for specific blockchain events.
Find first contract deployment
{"chain": "stacks","networks": {"mainnet": {"expire_after_occurrence": 1,"if_this": {"scope": "contract_deployment","deployer": "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR"}}}}
$chainhook predicates scan find-deployment.json --mainnet
Collect NFT activity
{"if_this": {"scope": "nft_event","asset_identifier": "SP32AEEF6WW5Y0NMJ1S8SBSZDAY8R5J32NBZFPKKZ.free-punks-v0::free-punks","actions": ["mint", "transfer", "burn"]},"then_that": {"file_append": {"path": "./nft-activity.json"}}}
Monitor address transactions
{"if_this": {"scope": "stx_event","actions": ["transfer"],"predicate": {"or": [{"equals": {"sender": "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR"}},{"equals": {"recipient": "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR"}}]}}}
Track all STX transfers involving a specific address as sender or recipient.
Debug scanning
Enable verbose output to understand why events match or don't match:
$chainhook predicates scan my-predicate.json --mainnet --verbose