Smart contract listeners, or event listeners, are essential backend components for any Web3 application that needs to react to on-chain activity. Instead of polling a node for state changes, a listener subscribes to specific events emitted by a contract, receiving immediate notifications when they occur. For protocols like TMS (Transaction Management System), which emits events for actions such as TransactionInitiated, TransactionSettled, or TransactionFailed, a listener enables real-time dashboards, automated notifications, and data indexing. This approach is more efficient and scalable than manual queries.
Launching a Smart Contract Listener for Real-Time TMS Events
Launching a Smart Contract Listener for Real-Time TMS Events
A guide to building a listener that captures and processes on-chain events from the TMS protocol in real-time.
To build a listener, you need three core components: a connection to a blockchain node (like an RPC provider from Infura, Alchemy, or a local node), the target smart contract's Application Binary Interface (ABI), and an event loop to process incoming data. The ABI is critical as it defines the structure of the events you want to listen for. You can obtain it from the contract's verified source code on a block explorer like Etherscan or from the project's official GitHub repository. Using a library such as ethers.js or web3.py simplifies the connection and subscription logic.
A basic implementation in JavaScript using ethers.js involves creating a provider, instantiating a contract object with its address and ABI, and then setting up a listener on a specific event. For example, to listen for a TransactionSettled event, your code would call contract.on("TransactionSettled", (from, to, amount, event) => { ... }). The callback function receives the decoded event arguments and the full event log, allowing your application to process the data—logging it to a database, triggering a notification service, or updating a user interface.
For production systems, you must implement robust error handling and reconnection logic. Node connections can drop, and RPC providers may have rate limits. Consider using a service like The Graph for complex historical queries or if you need to aggregate data across many events. However, for low-latency, real-time reactions to specific contract events, a dedicated listener service is often the most direct and performant solution. This guide will walk through setting up a reliable TMS event listener from scratch.
Prerequisites
Before you can launch a smart contract listener to track real-time TMS events, you need to configure your development environment and gather essential resources.
To build a listener for Themis TMS events, you will need a development environment capable of running Node.js (version 18 or later) or Python 3.9+. You must also have a fundamental understanding of EVM-based blockchains, smart contract events, and Web3 libraries like ethers.js or web3.py. Basic familiarity with command-line tools and package managers (npm, yarn, or pip) is required to install the necessary dependencies.
You will need access to a blockchain RPC endpoint. For development, you can use a public provider like Alchemy, Infura, or QuickNode. For production-grade reliability and higher rate limits, a dedicated node or a premium service is recommended. Ensure you have the TMS contract addresses for the networks you wish to monitor (e.g., Ethereum Mainnet, Arbitrum, Base). These can be found in the official Themis documentation or on-chain explorers.
The core of your listener will be built using a library to subscribe to event logs. In JavaScript/TypeScript, this is typically done with ethers.js v6 using its provider.on() method or a more robust solution like Chainscore's Event Streams API. In Python, web3.py provides similar functionality. You must understand the specific event signatures (like TransferSingle) emitted by the TMS contracts to parse the data correctly.
For persistent and scalable listening, especially across multiple contracts or chains, consider using a dedicated event indexing service. While you can build a listener from scratch, services like The Graph, Goldsky, or Chainscore's managed infrastructure handle connection stability, historical data backfilling, and event deduplication, reducing operational complexity. Your choice depends on your application's requirements for latency, data volume, and maintenance overhead.
Finally, ensure you have a secure place to store your RPC API keys and any sensitive configuration. Use environment variables (e.g., a .env file managed by the dotenv package) and never hardcode credentials. Set up a basic project structure with your chosen framework, initialize it with npm init or pip, and install the core Web3 library for your stack to begin coding.
Launching a Smart Contract Listener for Real-Time TMS Events
This guide explains the core components and workflow for building a system that listens to and processes events from the Token Management System (TMS) smart contract on-chain.
A smart contract listener is a backend service that monitors a blockchain for specific on-chain events emitted by a contract. For the Token Management System (TMS), this involves tracking critical actions like token minting, transfers, and policy updates. The architecture is event-driven, meaning your application logic is triggered by these on-chain occurrences rather than polling the chain continuously. This approach is efficient and provides real-time responsiveness, which is essential for applications like dashboards, notification systems, or automated compliance engines that need immediate awareness of state changes.
The core technical stack typically involves a Node.js or Python service using a Web3 library such as ethers.js or web3.py. This service establishes a persistent connection to a blockchain node RPC provider (e.g., Alchemy, Infura, or a self-hosted node). You then create a contract instance using the TMS's Application Binary Interface (ABI) and deployed address. The ABI is crucial as it defines the structure of the events your listener will decode. The service subscribes to these events using methods like contract.on("EventName", callback), which fires your callback function each time the event is emitted on-chain.
When an event is captured, the raw log data must be parsed. The Web3 library uses the ABI to decode the log topics and data into a human-readable JavaScript object containing the event parameters (e.g., from, to, tokenId, amount). Your application logic then processes this data. Common next steps include: validating the event, transforming the data into a internal model, storing it in a database (like PostgreSQL or MongoDB) for historical querying, and triggering downstream actions such as sending an email alert, updating a cache, or publishing a message to a queue (e.g., Redis or RabbitMQ) for further asynchronous processing.
For production reliability, you must implement robust error handling and connection management. Blockchain RPC connections can drop. Your listener should automatically attempt to reconnect and, upon reconnection, reconcile missed events by querying historical logs for the gap period. Consider using a block confirmation threshold (e.g., waiting for 12 block confirmations) before processing an event to guard against chain reorganizations. This architecture decouples the real-time ingestion layer from your business logic, allowing you to scale processing horizontally by having multiple workers consume from the event queue.
Key Concepts
Understanding the core components and patterns for building a real-time listener to track on-chain events from a Token Management Standard (TMS) contract.
Handling Reorgs & Chain Reorganizations
Blockchains can reorganize, where a previously confirmed block is orphaned. A robust listener must handle this by:
- Tracking block confirmations (e.g., waiting for 12+ confirmations on Ethereum).
- Implementing logic to re-fetch logs from an unstable block.
- Using finalized block tags (e.g.,
"finalized"in JSON-RPC) where supported, which are guaranteed not to change.
Scalability & Data Storage
For production systems, consider:
- Idempotency: Design your event handler to process the same log multiple times without duplicate side-effects.
- Checkpointing: Persist the last processed block number to resume from that point after a restart.
- Queueing: Use a message queue (e.g., RabbitMQ, AWS SQS) to decouple event ingestion from business logic processing, improving reliability and scalability.
Common TMS Event Patterns
Token Management Standards like ERC-20, ERC-721, and ERC-1155 have standardized events. Your listener should be configured for:
- ERC-20:
Transfer(address indexed from, address indexed to, uint256 value) - ERC-721:
Transfer(address indexed from, address indexed to, uint256 indexed tokenId) - ERC-1155:
TransferSingleandTransferBatchfor single and bulk transfers. - Custom Admin Events: Look for events related to minting, pausing, or role changes specific to the contract's implementation.
Step 1: Project Setup and Dependencies
This guide walks through initializing a Node.js project and installing the essential libraries required to build a listener for real-time TMS events.
Before writing any code, you need to set up your development environment. This tutorial uses Node.js (v18 or later) and npm or yarn as the package manager. Start by creating a new project directory and initializing it. Run npm init -y in your terminal to generate a package.json file, which will manage your project's dependencies and scripts. This file is crucial for defining your project's entry point and tracking the libraries you'll install next.
The core dependency for interacting with the blockchain is ethers.js v6, a complete library for Ethereum development. Install it using npm install ethers. For listening to events, you will also need a reliable WebSocket provider. While ethers has built-in support, services like Alchemy or Infura provide robust, production-ready WebSocket endpoints. You'll need an API key from one of these services. Optionally, install dotenv (npm install dotenv) to manage your API keys and other sensitive configuration in a .env file, keeping them out of your source code.
Your package.json should now list ethers as a dependency. Create a .gitignore file to exclude node_modules and your .env file from version control. A basic project structure at this stage includes the package.json, a .env file (for your RPC URL and API keys), and your main application file (e.g., index.js or app.js). With the foundational setup complete, you are ready to configure the provider connection and start listening for contract events in the next step.
Step 2: Connect to the Blockchain
Set up a real-time listener to capture and process TMS events directly from the blockchain.
A smart contract listener is a program that monitors a blockchain for specific on-chain events, such as Transfer or Approval, emitted by a contract. For TMS, you will listen for events from the TMSRegistry contract to track the creation and updates of tokenized media assets. This requires connecting to a blockchain node via WebSocket or HTTP JSON-RPC. Popular providers include Alchemy, Infura, or QuickNode, which offer reliable node access without running your own infrastructure. The listener subscribes to event logs, providing a real-time feed of activity.
The core technical implementation involves using an Ethereum library like ethers.js or web3.js. You will create a provider, define the contract's Application Binary Interface (ABI), and filter for the specific event signatures. For example, to listen for a new TMS mint, you would filter for the TokenMinted event. The listener runs continuously, parsing incoming log data—which includes the tokenId, owner address, and metadataURI—and can trigger downstream logic in your application, such as updating a database or sending a notification.
Here is a basic example using ethers.js v6 to listen for TokenMinted events:
javascriptimport { ethers } from 'ethers'; const provider = new ethers.WebSocketProvider('wss://eth-mainnet.g.alchemy.com/v2/YOUR_KEY'); const contractAddress = '0x...'; // TMSRegistry address const abi = ["event TokenMinted(uint256 indexed tokenId, address owner, string metadataURI)"]; const contract = new ethers.Contract(contractAddress, abi, provider); contract.on('TokenMinted', (tokenId, owner, metadataURI, event) => { console.log(`New TMS Minted: ID ${tokenId}, Owner: ${owner}, URI: ${metadataURI}`); // Your custom processing logic here });
This script establishes a persistent connection and executes a callback function each time the event is emitted.
For production systems, consider implementing error handling and reconnection logic. WebSocket connections can drop; your listener should detect disconnections and attempt to re-subscribe. Additionally, to avoid missing events during downtime, you may need to backfill historical logs by querying past blocks. Services like The Graph or Chainscore's own indexers can simplify this by providing a pre-indexed, queryable layer, reducing the complexity of managing raw event listeners and ensuring data consistency.
The data from your listener forms the real-time backbone of your TMS application. By processing events for TokenMinted, Transfer, and MetadataUpdated, you can maintain an accurate, up-to-date view of the entire TMS ecosystem. This enables features like live galleries, royalty distribution triggers, and provenance tracking. The next step involves deciding how to store, index, and serve this streaming data efficiently to end-users.
Step 3: Subscribe to Smart Contract Events
Learn how to set up a listener to capture real-time transaction monitoring system (TMS) events directly from the blockchain.
Smart contract events are a core feature of the Ethereum Virtual Machine (EVM) that allow contracts to log data on-chain in a gas-efficient manner. When a TMS contract executes a function like flagTransaction or updateRiskScore, it emits an event. These logs are stored in the transaction receipt and are indexed, making them queryable by off-chain applications. Subscribing to these events is the most reliable way for your backend service to react to on-chain state changes in real-time, without the need for constant polling.
To subscribe, you need a connection to an Ethereum node. You can use a node provider like Alchemy, Infura, or a local node. Using the Ethers.js library, you create a Provider and a contract instance with the TMS's Application Binary Interface (ABI). The ABI is crucial as it defines the event signatures. For example, to listen for a TransactionFlagged event, your listener setup would initialize with the contract address and the specific event filter.
Here is a basic implementation using Ethers v6:
javascriptimport { ethers } from 'ethers'; import TMS_ABI from './TMS_ABI.json'; const provider = new ethers.JsonRpcProvider('YOUR_RPC_URL'); const contractAddress = '0x...'; const contract = new ethers.Contract(contractAddress, TMS_ABI, provider); // Subscribe to the TransactionFlagged event contract.on('TransactionFlagged', (from, to, txHash, riskScore, event) => { console.log(`Flagged TX: ${txHash}`); console.log(`Risk Score: ${riskScore}`); // Your custom logic: alert, database write, etc. });
This listener will call your callback function every time the event is emitted on-chain.
For production systems, consider resilience and scalability. Your listener should handle node disconnections and re-subscribe automatically. Log all incoming events with timestamps to a database for auditing and idempotent processing. It's also critical to monitor the chain for reorganizations; a robust service should re-fetch events for orphaned blocks. For high-volume chains, using a specialized service like The Graph for historical indexing may be more efficient than a simple RPC subscription.
The data contained in these events powers the real-time layer of your TMS dashboard or compliance engine. By parsing the event arguments—such as transaction hash, risk score, and involved addresses—you can trigger alerts, update user interfaces, and feed data into analytics pipelines. This direct pipeline from on-chain contract logic to your application is what enables proactive monitoring and response to potentially malicious activity across supported networks.
Step 4: Parse Event Logs and Data
Learn how to decode the raw event logs from your listener into structured, usable data for your application.
Once your listener captures an event, you receive raw log data. This data is ABI-encoded, meaning it's a compact, hexadecimal representation. The core components of a log are the topics array and the data field. The first topic (topics[0]) is always the event signature hash (the keccak256 hash of the event name and its parameter types, e.g., Transfer(address,address,uint256)). Subsequent topics typically contain indexed parameters, while non-indexed parameters are packed into the data field. Your task is to decode this back into readable values like addresses, numbers, and strings.
To parse this data, you need the contract's Application Binary Interface (ABI). The ABI is a JSON file that acts as a blueprint, defining the structure of functions and events, including their names and parameter types. For the TMS contract, you must have the specific ABI for the events you're monitoring. You can obtain this from the contract's source code, a verified block explorer like Etherscan, or the project's official documentation. Without the correct ABI, you cannot accurately decode the log data.
Using a library like ethers.js or web3.js simplifies decoding. These libraries provide methods that use the ABI to automatically parse the log. For example, in ethers.js v6, you can use the interface.parseLog(log) method. Pass the raw log object, and the interface (created from the ABI) will return a structured object with the event name and decoded parameters. This transforms cryptic hex data into clear JavaScript objects like {from: '0x...', to: '0x...', value: 1000000000000000000n}.
Handling different data types is crucial. Events can emit uint256, address, string, bytes, and arrays. The decoding library handles this, but you must ensure your application logic accounts for the data types. For instance, a uint256 value for an ERC-20 transfer will be a BigInt in JavaScript to preserve precision. Addresses are checksummed strings. Always validate decoded data against expected types and ranges before using it in your application's business logic to prevent errors.
A robust listener includes error handling for failed parsing. Logs may be malformed, or you might encounter an unexpected event signature. Wrap your decoding logic in a try-catch block. Log the raw hex data and the error for debugging. It's also a best practice to filter events by signature hash at the provider level (using topics filters) before they reach your parsing logic, which reduces the chance of processing irrelevant logs. This step is where your listener transitions from capturing raw blockchain data to providing actionable information for your application.
Step 5: Call the TMS API
This guide explains how to launch a smart contract listener to monitor the Transaction Monitoring System (TMS) for real-time security events and alerts.
The Transaction Monitoring System (TMS) API provides a programmatic interface to receive real-time security alerts. To consume these events, you must deploy a smart contract listener—a dedicated service that polls the TMS endpoint, processes incoming data, and triggers predefined logic. This is essential for applications requiring automated responses to threats, such as pausing a protocol's mint function or notifying an admin dashboard upon detecting a high-risk transaction.
First, you need to set up your listener's infrastructure. A common approach is to use a Node.js or Python script running on a serverless function (like AWS Lambda) or a long-running process. Your listener will make periodic HTTP GET requests to the TMS event stream endpoint, typically https://api.chainscore.dev/v1/tms/events. You must authenticate using your project's API key in the request headers: Authorization: Bearer YOUR_API_KEY. The API returns a paginated list of event objects in JSON format.
Each event object contains critical fields you must parse: eventId, type (e.g., SUSPICIOUS_TOKEN_TRANSFER, FLASH_LOAN_DETECTED), severity (HIGH, MEDIUM, LOW), chainId, transactionHash, and a details payload with protocol-specific data. Your listener's core logic should filter events by severity and type, then execute corresponding actions. For example, upon receiving a HIGH severity event, your script could call a function on your smart contract's admin module to temporarily disable certain features.
Here is a simplified Node.js code snippet using axios to fetch and process events:
javascriptconst axios = require('axios'); const API_URL = 'https://api.chainscore.dev/v1/tms/events'; const API_KEY = process.env.CHAINSCORE_API_KEY; async function pollTMSEvents() { try { const response = await axios.get(API_URL, { headers: { 'Authorization': `Bearer ${API_KEY}` } }); response.data.events.forEach(event => { if (event.severity === 'HIGH') { console.log(`High-risk event detected: ${event.type}`); // Add logic to interact with your smart contract here } }); } catch (error) { console.error('Failed to fetch TMS events:', error); } } // Poll every 30 seconds setInterval(pollTMSEvents, 30000);
For production reliability, implement error handling, retry logic, and event deduplication using the eventId. Consider storing the last processed eventId in a database to avoid reprocessing the same alerts. Additionally, set up monitoring and alerts for your listener service itself to ensure it remains operational. The TMS API documentation provides details on webhook configurations for a push-based model, which can be more efficient than polling for high-volume applications.
Integrating the TMS listener completes your proactive security stack. By acting on real-time intelligence—such as freezing a compromised pool or logging an attack vector—you significantly reduce the window of exposure. This step transforms the TMS from a monitoring tool into an active defense mechanism within your application's architecture.
Event to TMS Action Mapping
Common smart contract events and their corresponding TMS (Transaction Management System) actions for automated workflows.
| Smart Contract Event | TMS Action | Typical Payload Data | Use Case |
|---|---|---|---|
Transfer(address,address,uint256) | Send Notification | from, to, value | Wallet activity alerts, compliance monitoring |
Approval(address,address,uint256) | Update Database | owner, spender, value | Track allowance changes for dApp dashboards |
Swap(address,uint256,uint256,address,address) | Execute Trade | sender, amountIn, amountOut, to | Trigger limit orders or portfolio rebalancing |
Deposit(address,uint256,uint256) | Mint LP Token | caller, assets, shares | Automatically stake LP tokens after deposit |
Withdraw(address,uint256,uint256) | Burn LP Token | caller, assets, shares | Unstake and claim rewards upon withdrawal |
LoanRepaid(uint256,uint256) | Update Credit Score | loanId, amount | On-chain credit history and risk assessment |
GovernanceProposalCreated(uint256) | Create Task | proposalId | Alert DAO members and initiate voting process |
Frequently Asked Questions
Common questions and solutions for developers building real-time listeners for the Token Messaging Standard (TMS).
A silent listener is often due to configuration or connectivity issues. Follow this checklist:
- RPC Provider: Ensure your WebSocket endpoint (e.g., Alchemy, Infura) is active and supports the correct chain. Free tiers may have connection limits.
- Contract Address: Verify you are listening to the correct TMS contract address (
0x...for mainnet). A single character error will result in no events. - Event Signature: Confirm the event name and parameter types match the contract ABI exactly. Use the official TMS ABI from the repository.
- Starting Block: If you specified a
fromBlockin the past, ensure it hasn't been pruned by your archive node. For a fresh start, use'latest'. - Error Handling: Implement robust
on('error')handlers in your WebSocket client to catch and log connection drops or subscription failures.
Resources and Tools
Tools and reference implementations for launching a real-time smart contract listener that feeds events into a Transaction Monitoring System (TMS). Each resource focuses on reliability, latency, and production-safe event handling.
Conclusion and Next Steps
You have successfully built a system to listen for and process real-time TMS events. This guide covered the core concepts and a practical implementation using Chainscore's WebSocket feed.
Your listener now provides a foundational real-time data pipeline. The key components you implemented include: establishing a secure WebSocket connection to wss://api.chainscore.dev/v1/ws, subscribing to specific event types like tms_transaction or tms_contract, parsing the incoming JSON payloads, and handling connection lifecycle events such as reconnects. This setup allows you to react to on-chain activity—like token transfers or contract interactions—within seconds, enabling use cases like live dashboards, instant notifications, and automated trading signals.
For production deployment, consider these critical next steps. First, implement robust error handling and reconnection logic with exponential backoff to maintain uptime. Second, add data validation and sanitization for incoming messages to prevent malformed data from crashing your service. Third, integrate a message queue (e.g., RabbitMQ, Apache Kafka) between your listener and business logic to decouple consumption from processing, ensuring events are never lost during high load. Finally, set up comprehensive logging and monitoring to track event volume, latency, and system health.
To extend your listener's capabilities, explore Chainscore's broader API. You can fetch historical TMS data via the REST API to backfill your database or perform analysis. Experiment with filtering subscriptions to specific contracts or addresses to reduce noise. For advanced use, you can combine TMS events with other Chainscore data streams, such as MEV bundle tracking or gas price feeds, to build more sophisticated analytics. The official Chainscore API Documentation provides detailed references for all available endpoints and subscription parameters.
The architecture you've built is a template for various blockchain monitoring applications. Developers commonly adapt it for: DeFi portfolio trackers that update balances in real-time, NFT minting bots that detect new collections, compliance monitors that flag suspicious transactions, and data aggregation services for on-chain analytics. By processing events as they occur, you move beyond slow, polling-based methods to a truly reactive system aligned with the pace of the blockchain.