Off-Chain Reactivity: Filtered Subscriptions tutorial

This tutorial builds on basic off-chain reactivity by adding filters to your WebSocket subscriptions. While wildcard (all events) is great for quick testing and seeing reactivity in action, it's often too verbose for production—flooding logs with irrelevant data. Instead, use filters to target specific emitters or events, making your app more efficient and focused.

We'll subscribe to Transfer events from a specific ERC20 contract, include a view call (e.g., balanceOf), and enable onlyPushChanges to notify only on state changes. This is ideal for real-time UIs or monitoring without noise.

Overview

Off-chain subscriptions push filtered events + state via WebSockets to TypeScript apps. Filters reduce volume:

  • eventContractSources: Limit to specific emitter addresses.

  • topicOverrides: Filter by event topics (e.g., keccak256 signatures like Transfer's 0xddf...).

  • onlyPushChanges: Skip notifications if ethCalls results match the previous one.

  • ethCalls: Optional view calls for bundled state.

  • onError: Handle failures gracefully.

No gas costs; runs off-chain.

Prerequisites:

  • Same as wildcard tutorial: Node.js, npm i @somnia-chain/reactivity viem.

  • Know your target contract/event (e.g., ERC20 Transfer).

Key Objectives

  1. Set Up Chain and SDK: Configure viem and initialize SDK.

  2. Define Filters and ETH Calls: Specify emitters, topics, and views.

  3. Create Filtered Subscription: Use params for targeted listening.

  4. Decode and Handle Data: Parse with viem; add error handling.

  5. Run and Optimize: Test with onlyPushChanges.

Step 1: Install Dependencies

Step 2: Define the Somnia Chain

(Reuse from wildcard tutorial.)

Step 3: Initialize the SDK

Step 4: Define ETH Calls and Filters

  • ethCalls: Query balanceOf on an ERC20.

  • eventContractSources: Array of emitter addresses (e.g., one ERC20 contract).

  • topicOverrides: Hex for event signatures (e.g., Transfer: 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef).

Step 5: Create the Filtered Subscription

Include onlyPushChanges: true to notify only on balance changes. Add onError for robustness.

Step 6: Decode Data in the Callback

Parse the event (Transfer) and view result (balanceOf).

Step 7: Put It All Together and Run

Full script (main.ts):

Run: ts-node main.ts.

Testing

  1. Run the script.

  2. Trigger a Transfer on the filtered contract (e.g., send tokens).

  3. See notifications only on relevant events/changes.

  • If too quiet: Remove onlyPushChanges or broaden filters.

  • Prod Tip: Start with wildcard for debugging, then add filters.

Troubleshooting

  • No Notifications? Verify topics/address (use explorers for keccak). Check WS connection.

  • Errors? Handle in onError; common: Invalid filters or RPC issues.

  • Too Many? Tighten topicOverrides or eventContractSources.

Next Steps

  • Multi-emitters: Add more to eventContractSources.

  • Custom Events: Compute topics for your ABI.

  • Advanced: Combine with React for live UIs.

  • Compare to On-Chain: On-Chain Tutorial.

Last updated