Blockchain data is vast and complex, making it difficult to track specific events in real-time. Traditional methods require developers to write custom scripts that poll for specific contract events or state changes, a process that is time-consuming and requires constant infrastructure maintenance. Natural language alerts bridge this gap by allowing you to describe what you want to monitor in plain English, which is then automatically converted into executable on-chain logic. This tutorial will guide you through setting up a system that watches for smart contract events—like a large token transfer, a governance proposal submission, or a specific function call—and sends you an immediate notification.
Setting Up Natural Language Alerts for Smart Contract Events
Introduction: From Natural Language to On-Chain Actions
Learn how to translate human-readable queries into automated blockchain monitoring and notifications.
At its core, this process involves three key components: an event listener, a trigger condition, and a notification channel. The event listener, often a service like Chainscore's Alerts API, subscribes to on-chain data streams. The trigger condition is defined using a natural language prompt, such as "alert me when the balance of vault X falls below 100 ETH." This prompt is parsed and translated into a precise query against the blockchain's data. Finally, the notification channel—which could be email, Discord, Telegram, or a webhook—delivers the alert when the condition is met.
Let's consider a practical example for a DeFi user. You want to know if a liquidity pool you're providing to on Uniswap V3 experiences significant impermanent loss. Instead of manually checking the pool's composition daily, you could set an alert with the prompt: "Notify me when the price of ETH/USDC in the 0x... pool deviates by more than 5% from my entry price." The system would monitor the pool's Swap events and the resulting sqrtPriceX96 value, calculate the deviation, and ping you only when your threshold is crossed. This turns a complex manual tracking task into a hands-free, automated safeguard.
For developers, this capability is integrated directly into workflows. You can use the Chainscore SDK to programmatically create alerts as part of your application's deployment script. For instance, after deploying a new staking contract, you might immediately set up an alert to monitor for failed withdrawals or unusually high gas fees on the unstake function. This proactive monitoring helps with debugging, security, and user support by providing instant visibility into contract interactions without needing to build and host a dedicated indexer.
Setting up your first alert is straightforward. You'll need an API key from a provider like Chainscore and a basic understanding of the event or state you wish to track. The typical workflow is: 1) Formulate your natural language query, 2) Use the provider's dashboard or API to create the alert, specifying the target chain, contract address, and notification method, and 3) Test the alert with a simulated transaction. This guide will walk you through each step with concrete code examples for both using a web interface and the JavaScript SDK.
Prerequisites and Tech Stack
Before building natural language alerts for smart contract events, you need a foundational setup. This section outlines the essential tools, accounts, and knowledge required to follow this guide.
To implement this system, you will need a working knowledge of JavaScript/TypeScript and a basic understanding of smart contracts and Ethereum events. Familiarity with Node.js and npm is assumed for running the backend service. The core technical stack involves an EVM-compatible node provider (like Alchemy, Infura, or a local node), the Chainscore API for event monitoring, and a Large Language Model (LLM) API such as OpenAI's GPT-4 or Anthropic's Claude for generating summaries.
You must create accounts and obtain API keys for the required services. First, sign up for a Chainscore account at chainscore.dev to access their event streaming API. Next, secure an API key from an LLM provider; for OpenAI, you can get one from their platform. Finally, you will need access to an RPC endpoint. For development, you can use a free tier from a service like Alchemy or run a local Hardhat node.
The project structure will be a Node.js application. Initialize a new project with npm init -y and install the necessary dependencies. You will need the Chainscore SDK (@chainscore/sdk), an Ethers.js v6 library for blockchain interactions, the official SDK for your chosen LLM, and a framework like Express.js if you plan to build a webhook server. A basic package.json might include: "dependencies": { "@chainscore/sdk": "^1.0.0", "ethers": "^6.0.0", "openai": "^4.0.0", "express": "^4.18.0" }.
Ensure your development environment is configured correctly. You should have Node.js v18+ installed. It is also helpful to use a code editor like VS Code and a tool like ngrok or localhost.run to expose your local webhook server to the internet for testing. Having a wallet (e.g., MetaMask) with testnet ETH will allow you to interact with example contracts and trigger events during development.
Conceptually, you should understand the publish-subscribe pattern. Chainscore will publish event data to a webhook URL your server provides. Your application subscribes to specific smart contract events, receives the raw blockchain data, processes it, and uses the LLM to generate a human-readable alert. The final step is delivering that alert via a channel like Discord, Telegram, or email using their respective APIs.
With these prerequisites in place—developer accounts, API keys, a Node.js project, and a conceptual model—you are ready to proceed with building the alert system. The following sections will guide you through writing the code to connect these components, from setting up the event listener to formatting and sending the final natural language notification.
Setting Up Natural Language Alerts for Smart Contract Events
This guide details the architectural components and workflow for creating a system that translates on-chain events into human-readable notifications.
A natural language alert system for smart contracts requires a multi-layered architecture. The core components are an event listener (like an indexer or RPC node), a data processing layer that decodes and enriches event data, and a notification service that formats and dispatches messages. This architecture moves from raw blockchain data to actionable insights. For example, monitoring a Uniswap V3 pool for large swaps involves listening for the Swap event, calculating USD value using an oracle, and sending a Telegram alert if the amount exceeds a threshold.
The event listener is the system's foundation. You can use services like The Graph for historical indexing, Alchemy's Enhanced APIs for real-time logs, or run your own node with WebSocket subscriptions. The key is reliable, low-latency access to event logs. For processing, you need the contract's ABI to decode the log data into readable parameters. This step often involves fetching additional context, such as converting token amounts to fiat values using Chainlink Price Feeds or calculating percentages of a pool's liquidity.
The notification logic defines the business rules. This is where you implement filters (e.g., "only for transactions > $10k") and craft the human-readable message. A robust system templates these messages, inserting variables like ${tokenSymbol}, ${amountUSD}, and ${txHash}. Finally, the dispatcher integrates with communication platforms. Common choices include Discord webhooks, Telegram Bot API, Slack apps, and transactional email services like SendGrid or Resend for critical alerts.
Here is a simplified code snippet illustrating the core flow using ethers.js and a hypothetical Discord webhook:
javascriptconst ethers = require('ethers'); const axios = require('axios'); const provider = new ethers.WebSocketProvider(WS_URL); const contract = new ethers.Contract(POOL_ADDRESS, UNISWAP_V3_ABI, provider); const DISCORD_WEBHOOK = 'your_webhook_url'; contract.on('Swap', async (sender, amount0, amount1, sqrtPriceX96, liquidity, tick) => { // 1. Decode & Calculate const usdValue = await calculateUSDValue(amount0, token0Address); // 2. Apply Alert Logic if (usdValue > 10000) { // 3. Format Message const message = `Large Swap Alert! $${usdValue.toFixed(2)} swap on Uniswap V3.`; // 4. Dispatch Notification await axios.post(DISCORD_WEBHOOK, { content: message }); } });
For production systems, consider scalability and reliability. A single script listening to a WebSocket can fail. A more resilient design uses a message queue (like RabbitMQ or AWS SQS) to decouple the event listener from processors. This allows for load balancing and retry logic for failed notifications. Furthermore, storing alert history in a database (PostgreSQL or TimescaleDB) enables analytics and user preference management, allowing users to customize thresholds or mute certain alert types.
Security is paramount. Never hardcode private keys or sensitive API tokens. Use environment variables or a secrets manager. Validate all incoming data to prevent injection attacks in notification messages. When calculating values, be aware of oracle manipulation risks and consider using time-weighted average prices (TWAPs) for high-value alerts. By architecting with these principles—modularity, resilience, and security—you can build a robust alerting system that provides real-time, intelligible insights into on-chain activity.
LLM Prompt Strategies for Intent Parsing
Evaluating prompt engineering approaches for extracting structured alert parameters from natural language.
| Strategy | Zero-Shot Prompting | Few-Shot Prompting | Chain-of-Thought Prompting |
|---|---|---|---|
Accuracy on Unseen Queries | 65-75% | 85-92% | 88-95% |
Context Window Usage | Low (< 200 tokens) | Medium (200-500 tokens) | High (500-1000+ tokens) |
Handles Complex Logic | |||
Requires Example Dataset | |||
Latency (GPT-4) | < 2 sec | 2-4 sec | 3-6 sec |
Best For | Simple, common queries | Domain-specific patterns | Multi-step reasoning tasks |
Extracts Nested Parameters | |||
Cost per 1k Queries (est.) | $0.03-0.06 | $0.08-0.15 | $0.12-0.25 |
Step 1: Parsing User Intent with an LLM
This guide explains how to use a Large Language Model (LLM) to interpret user requests and translate them into actionable queries for monitoring smart contract events.
The first step in building a natural language alert system is intent parsing. Users will ask questions like "Alert me when the price of ETH on Uniswap V3 drops below $3000" or "Notify me if a specific wallet receives more than 10,000 USDC." An LLM's role is to extract the structured parameters from this unstructured text. This involves identifying key entities: the contract address, the event name (e.g., Swap, Transfer), the blockchain network, and any conditions (price thresholds, amount filters).
You can implement this using the OpenAI API or open-source models like Llama 3 or Mistral. The process involves creating a system prompt that defines the LLM's role and a user prompt containing the natural language query. The LLM should return a structured JSON object. For example, the query about an ETH price drop should output a target contract (the WETH/USDC pool), the Swap event, the chain (Ethereum Mainnet), and a condition to check if amount0 or amount1 indicates ETH is below $3000.
Here is a basic implementation using the OpenAI Python SDK. The system prompt instructs the model to act as a parser for blockchain events, and we use function calling or structured outputs to guarantee a valid JSON response. The event_abi field is crucial, as it allows our system to later decode the raw blockchain log data.
pythonimport openai system_prompt = """You are a parser that converts natural language requests for blockchain event alerts into structured data. Extract the contract address, event name, blockchain network, and any conditions. Return valid JSON.""" user_query = "Alert me when the DAI balance of vault.eth drops below 5000 tokens on Ethereum." response = openai.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_query} ], response_format={ "type": "json_object" } ) parsed_intent = json.loads(response.choices[0].message.content) # Output might be: {"contract": "0x...", "event": "Transfer", "network": "ethereum", "condition": "to=='vault.eth' and value < 5000e18"}
Handling ambiguity is critical. The LLM might need to resolve token symbols to contract addresses using an on-chain or off-chain registry. For the example "ETH price on Uniswap V3," the model should know to use the canonical WETH/USDC 0.05% fee tier pool address. You can provide context in the system prompt with a short list of common token pairs and their mainnet addresses. For production systems, this parsing layer often integrates with a token API like the CoinGecko or Moralis Unified API to resolve symbols in real-time.
The output of this step is a normalized, machine-readable intent object. This object becomes the input for the next stage: configuring the event listener. It tells our system exactly what on-chain data to subscribe to and what logic to apply when an event occurs. By decoupling the natural language interface from the blockchain client logic, we create a flexible system that can easily support new types of queries or conditions by simply updating the LLM's prompting instructions.
Step 2: Creating and Storing the Event Subscription
This step involves programmatically defining the specific on-chain events you want to monitor and securely storing that subscription configuration for the Chainscore backend to process.
With your Chainscore API key and project ID ready, you can now define your event subscription. This is done by making a POST request to the Chainscore API endpoint /api/v1/subscriptions. The core of this request is the subscription object, a JSON payload that specifies the blockchain, the smart contract, and the exact events to track. For a natural language alert, you must also include the nlDescription field, which is the plain English question or statement that will trigger the alert, such as "Notify me when the ETH price drops below $3,000."
A critical component of the subscription is the webhook URL. This is a publicly accessible endpoint on your server that Chainscore will call with a payload whenever your defined conditions are met. The payload includes the decoded event data and your custom nlDescription. Your server must be configured to listen for these POST requests. For local development, you can use a service like ngrok to create a secure tunnel and generate a public URL for your local server.
Here is a concrete example of a subscription payload for monitoring large USDC transfers on Ethereum. Notice the filters array, which allows you to specify event signatures and parameter conditions, and the required webhook and nlDescription fields:
json{ "projectId": "your_project_id_here", "name": "Large USDC Transfer Alert", "chainId": 1, "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "abi": ["event Transfer(address indexed from, address indexed to, uint256 value)"], "filters": [{"event": "Transfer", "filters": {"value": {"gt": "1000000000"}}}], "webhook": "https://your-server.com/chainscore-webhook", "nlDescription": "Alert me when a USDC transfer exceeds 1,000 USDC." }
After sending the POST request, the Chainscore API will validate your subscription, compile the necessary indexing logic, and return a subscription ID in the response. You must store this ID securely in your application's database. This ID is essential for all future interactions with this specific subscription, including retrieving its status, updating its parameters, or deleting it. The backend system will immediately begin scanning historical blocks and monitoring new blocks for events matching your criteria.
It's important to design your nlDescription for clarity and specificity. Vague descriptions may lead to false positives or missed alerts. Combine specific on-chain data (like value > 1000000) with clear intent ("large transfer") in your natural language query. For complex logic, you can use multiple conditions within the filters array. Once active, the subscription runs autonomously until you pause or delete it, providing a persistent, serverless monitor for your specified on-chain activity.
Step 3: Building the Blockchain Event Listener
This guide details how to build a production-ready listener that captures on-chain events and triggers natural language alerts, moving from raw logs to actionable insights.
The core of your alerting system is the event listener, a service that continuously monitors the blockchain for specific smart contract events. You'll need to connect to an RPC provider like Alchemy, Infura, or a public node. Using a library such as ethers.js or viem, you can create a provider instance and subscribe to logs using a filter. This filter is defined by the contract address and the event signature, a unique identifier derived from the event name and parameter types (e.g., Transfer(address,address,uint256)). The listener runs in a loop or uses WebSocket subscriptions for real-time updates, capturing raw log data each time the event is emitted.
Once you capture a raw event log, you must decode it to extract human-readable parameters. The log contains topics (an array of indexed parameters) and data (a bytes string for non-indexed parameters). Using your contract's Application Binary Interface (ABI), you can decode this data. For example, a decoded Transfer event from an ERC-20 contract yields the from address, to address, and value. This structured data is the foundation for your alert. It's crucial to handle reorgs by confirming a certain number of block confirmations (e.g., 12 for Ethereum mainnet) before processing the log to ensure finality.
With the decoded event data, you can construct a natural language alert. This involves templating and contextual enrichment. A basic template might be: "Transfer of {value} {tokenSymbol} from {from} to {to}". For more useful alerts, enrich this data by fetching the current USD value of the token from an oracle like Chainlink or a DEX API, converting the raw value (in wei) to a readable number using the token's decimals, and using an ENS lookup or address label service to make from and to more identifiable. This transforms 0xabc... into "vitalik.eth" or "Binance 14".
The final step is delivery. Your listener should pass the fully constructed alert message to a notification service. This could be a simple function call to send an email via SendGrid, a message to a Discord channel using a webhook, a push notification via Push Protocol or WalletConnect Notify, or an SMS. Implement robust error handling and retry logic here, as delivery services can fail. For production, consider queuing alerts (e.g., with Redis or RabbitMQ) to decouple the listening process from the delivery process, ensuring you don't miss events during notification outages.
To see this in practice, here's a simplified ethers.js snippet for listening to USDC transfers:
javascriptconst { ethers } = require('ethers'); const provider = new ethers.JsonRpcProvider(RPC_URL); const usdcAddress = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'; const usdcAbi = ['event Transfer(address indexed from, address indexed to, uint256 value)']; const contract = new ethers.Contract(usdcAddress, usdcAbi, provider); contract.on('Transfer', async (from, to, value, event) => { // Wait for confirmations const receipt = await event.getTransactionReceipt(); if (receipt.confirmations < 12) return; // Decode & Enrich const formattedValue = ethers.formatUnits(value, 6); // USDC has 6 decimals const alertMsg = `Transfer of ${formattedValue} USDC from ${from} to ${to}`; // Send to notification service await sendToDiscord(alertMsg); });
This provides a functional blueprint you can expand with enrichment and queuing.
For advanced implementations, consider monitoring multiple contracts across different chains using a multi-RPC provider setup. Tools like Chainstack or Blockdaemon offer unified APIs. Always implement logging and monitoring for your listener service itself using tools like Prometheus and Grafana to track uptime, event volume, and error rates. The key to a reliable listener is idempotency—ensuring the same event is not processed multiple times—and the ability to recover from downtime by replaying past blocks, which can be managed by persisting the last processed block number to a database.
Step 4: Generating and Sending the Alert Message
This final step transforms your detected on-chain events into actionable notifications delivered to your preferred communication channels.
With your event listener configured and the logic to parse event data in place, you now need to construct a human-readable message. This involves formatting the raw blockchain data—like transaction hashes, wallet addresses, token amounts, and event-specific parameters—into a clear narrative. For example, a large token transfer detection might generate: "Alert: 10,000 USDC transferred from 0xABC... to 0xDEF... in tx 0x123... on Ethereum mainnet." Use string interpolation in your handler function to inject the dynamic values captured from the event log.
The message string must then be routed to your chosen notification service. For a Discord webhook, you would send a POST request with a JSON payload containing your message, often within an embeds array for rich formatting. For Telegram, you might use the sendMessage method of the Bot API. For email, you would use an SMTP library like Nodemailer. Each service has specific API requirements; the core task is to reliably call their endpoint from within your event handler's execution path, ensuring the alert fires synchronously with the blockchain event.
Implement robust error handling around the message-sending API call. Network issues or rate limits could cause failures. Wrap the request in a try-catch block, log errors, and consider implementing a retry logic with exponential backoff for production reliability. For critical alerts, you may want to fail loudly by sending a secondary alert to an admin channel if the primary notification fails. This ensures your monitoring system itself is monitored.
Finally, consider message templating for scalability. Instead of hardcoding message formats, store templates (e.g., as environment variables or in a config file) that can be reused across different alert types. A template might look like: "{protocol} Alert: {eventName} triggered by {fromAddress}. Details: {args}". This approach makes it easier to manage and update alert copy without modifying your core application logic.
Essential Tools and Resources
These tools and frameworks let developers create natural language alerts for onchain activity such as smart contract events, state changes, and security incidents. Each resource focuses on translating low-level blockchain data into actionable notifications delivered via Slack, email, Telegram, or webhooks.
Common Alert Types and Their Implementation
Comparison of key characteristics for different categories of smart contract event alerts.
| Alert Type | Implementation Complexity | Typical Latency | Primary Use Case | Example Trigger |
|---|---|---|---|---|
Function Call Alert | Low | < 5 seconds | Specific contract interactions | transfer() function called on USDC contract |
Event Emission Alert | Low | < 3 seconds | Log-based state changes | Transfer(address,address,uint256) event emitted |
State Variable Change | Medium | < 10 seconds | Monitoring governance or configuration | Owner address variable updated |
Gas Price Threshold | Low | < 2 seconds | Cost monitoring and anomaly detection | Transaction gas price > 150 gwei |
Large Transfer Alert | Medium | < 5 seconds | Whale tracking and security | Single transfer > $1M USD value |
Contract Creation Alert | Low | < 15 seconds | New deployment monitoring | New contract created by factory address |
Failed Transaction Alert | Medium | < 8 seconds | Security and bug detection | Transaction reverted with specific error |
Frequency/Speed Alert | High | < 1 second | Detecting flash loan attacks or spam |
|
Frequently Asked Questions
Common questions and troubleshooting for developers setting up on-chain event monitoring with natural language.
Natural language alerts translate on-chain events into human-readable notifications using large language models (LLMs). Instead of writing complex queries for raw log data, you describe the event you want to monitor in plain English.
How it works:
- You submit a prompt like "Alert me when a whale deposits more than 1000 ETH into the Lido staking contract."
- An LLM interprets the intent and generates the corresponding blockchain query logic (e.g., filters for the
StETHcontract'sSubmittedevent wheresenderis a top holder andamount> 1000 ETH). - This query is deployed as a listener on a node or indexer.
- When the conditions are met, you receive a notification via your chosen channel (Discord, Telegram, email).
This abstracts away the need to know specific contract ABIs, event signatures, or complex filtering logic.
Conclusion and Next Steps
You have successfully configured a system to monitor smart contract events using natural language queries. This guide covered the essential steps from setting up an indexer to creating and managing alerts.
The core workflow you've implemented involves using a specialized indexer like Chainscore or The Graph to ingest and structure on-chain data. By writing a subgraph schema and mapping logic, you defined which contract events to track and how to store them in a queryable format. The final step was integrating a natural language interface, such as an AI-powered query layer, to translate plain English requests into precise GraphQL queries against your indexed data. This setup moves beyond simple block explorers, enabling proactive monitoring.
For production deployment, consider these next steps to enhance reliability and scalability. First, implement rate limiting and query cost analysis to manage API usage, especially if using a hosted service. Second, set up a dedicated alerting channel—like a Discord webhook, Telegram bot, or email pipeline—to receive notifications. Third, backtest your alert logic against historical data to fine-tune triggers and reduce false positives. Finally, document your subgraph schema and alert rules for team collaboration and future maintenance.
To expand this system's capabilities, explore integrating multiple data sources. You could combine your event alerts with off-chain data from oracles like Chainlink for richer context, or layer in analytics from platforms like Dune Analytics for comparative insights. For advanced use cases, consider setting up a dashboard using a framework like Streamlit or Grafana to visualize alert trends and contract activity in real-time. The foundational indexing layer you've built is the critical first step toward sophisticated, automated on-chain monitoring and analysis.