Wildcard Off-Chain Reactivity Tutorial
Example of how to subscribe to all events and fetch state on Somnia using WebSockets off-chain
This tutorial shows how to set up an off-chain subscription in TypeScript to listen for all events emitted on the Somnia blockchain (wildcard mode). Notifications will push event data plus results from Solidity view calls (e.g., querying contract state like balances) in a single atomic payload. This reduces RPC roundtrips compared to traditional event listening + separate state fetches.
We'll use the Reactivity SDK for WebSocket subscriptions and viem for chain setup, ABI handling, and decoding. For familiarity, we'll subscribe to all events but decode a common one (ERC20 Transfer) in the callback.
Whilst most developers are unlikely to use reactivity in this way in production, there are scenarios where this will be useful:
Testing reactivity before applying more filters (see our other tutorials)
Building an indexer which scrapes required information from the chain into a secondary database that would serve other applications that want large volumes of historical chain data
Overview
Off-chain reactivity uses WebSockets to push notifications to your TypeScript app. Key features:
Wildcard Listening: Catch every event without filters.
Bundled State: Include ETH view calls executed at the event's block height.
Real-Time: Low-latency updates for UIs, backends, or scripts.
No Gas Costs: Off-chain, so free per notification (after setup).
This enables reactive apps like live dashboards or automated alerts.
Prerequisites:
Node.js 20+
Somnia testnet access (RPC: https://dream-rpc.somnia.network)
Install dependencies:
npm i @somnia-chain/reactivity viem
Key Objectives
Set Up the Chain and SDK: Configure viem for Somnia Testnet and initialize the SDK.
Define ETH Calls: Specify view functions to run on events (e.g., balanceOf).
Create the Subscription: Start a wildcard WebSocket sub with a data callback.
Decode Notifications: Use viem to parse event logs and function results.
Run and Test: Handle incoming data in real-time.
Step 1: Install Dependencies
Step 2: Define the Somnia Chain
Use viem's defineChain to configure the testnet.
Step 3: Initialize the SDK
Create a public client with WebSocket transport and pass it to the SDK.
Step 4: Define ETH Calls
Specify view calls to execute when events emit. Here, we query an ERC721 balanceOf (adjust addresses as needed).
Step 5: Create the Wildcard Subscription
Subscribe with ethCalls and an onData callback. Omit filters for wildcard (all events).
Unsubscribe Later:
subscription.unsubscribe();
Step 6: Decode Data in the Callback
Use viem to decode the event log and function results. For example, assuming an ERC20 Transfer event (use erc20Abi from viem).
Notes:
data.resultcontainstopics,data(event payload), andsimulationResults(view call outputs). Handle errors if decoding fails (e.g., non-matching ABI).
Step 7: Put It All Together and Run
Full script (main.ts):
Run: ts-node main.ts (install ts-node if needed).
Testing
Run the script.
Trigger events on Somnia Testnet (e.g., transfer ERC20 tokens via a wallet).
Watch console for decoded notifications.
If no events: Deploy a test contract and emit manually.
Troubleshooting
No Data? Ensure WebSocket RPC is connected; check filters (none for wildcard).
Decoding Errors? Verify ABI matches the event/contract.
Connection Issues? Use HTTP fallback if WS fails, but prefer WS for reactivity.
Next Steps
Add filters (e.g.,
eventTopics: ['0xddf...']for Transfer keccak).Integrate with React (future hooks).
Handle multiple ethCalls/decodes.
Explore on-chain version: On-Chain Tutorial.
Last updated