2

I would like to create a sever that continuously watch the events of multiple smart contract at once. Sending me an alert via email when an event is detected.

I understand that there is a web3.js function that watch contracts. But how do I make it run perpetually on my server to do the task?

Furthermore, when there is an additional contract i would like to watch, is it possible to dynamically watch the new contract.

Thanks!

3 Answers 3

0

You can use WebSocket protocol to connect to Ethereum node and subscribe for the contract events. WebSocket pushes events to your server as fast as they arrive to the node over Ethereum network gossip.

You can find more details in this blog post https://hanezu.github.io/posts/Enable-WebSocket-support-of-Ganache-CLI-and-Subscribe-to-Events.html

You can subscribe to multiple contracts (addresses).

0

The most simple way to interact with Contracts and listen to the events is by using 0xweb

You can install multiple contracts (generate strongly typed classes for the contracts):

$ npm i 0xweb -g
$ 0xweb init
$ 0xweb install 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 --name USDC --chain eth
$ 0xweb config -e
# open the config file and edit your `WebSocket` server URL for ETH chain.

Here we have auto-generated classes for USDC contract, now to listen to Transfer events.

import { USDC } from '@0xweb/eth/USDC/USDC';
import { Config } from '@dequanto/Config';

async function example () {

    await Config.fetch();

    console.log('START listening');
    let usdc = new USDC();
    usdc.onTransfer((event, from, to, value) => {
        console.log('Event', event)
        sendEmail(`${value} USDC transferred ${from} → ${to}`);
    });
    // ... add additional contracts or listeners
}

example();

To execute the script run

npx atma run ./example.ts

To implement the sendEmail method - use NodeMailer

And to start the script on the server use PM2. This will ensure the script is restarted on crashes, system restarts, etc.

0

dev advocate at Chainstack here.

To create a server that continuously watches the events of multiple smart contracts and sends email alerts upon event detection, you can use Node.js with the web3.js library. Here's a high-level approach to achieve this:

  1. Setup Node.js and web3.js: Begin by setting up a Node.js environment and installing web3.js, a popular library for interacting with Ethereum smart contracts.

  2. Create WebSocket Connection: Web3.js allows you to create a WebSocket connection to an Ethereum node. This is crucial for real-time event listening.

  3. Subscribe to Contract Events: Use web3.eth.subscribe('logs', options, callback) to listen to events from smart contracts. You can specify the contract addresses and event signatures in the options parameter.

  4. Running the Server Continuously: You can make a simple server using Express.js.

  5. Sending Email Alerts: Integrate an email service like Nodemailer with your Node.js application. Configure it to send emails within the callback of the event listener, which triggers when an event log is received.

  6. Dynamically Adding New Contracts: To watch new contracts dynamically, you can create an API endpoint in your server application that accepts new contract details. You can set up a new subscription for its events when a new contract is added. Or you could pick the list of contracts from an environment variable.

  7. Security and Reliability: Handle errors and network disconnections gracefully. Reconnection logic in WebSocket and proper error handling in both the event subscription and email sending are important for reliability.

Here's a simplified example demonstrating the key parts of such an application:

Install the packages

npm install express [email protected] nodemailer
const express = require('express');
const Web3 = require('web3');
const nodemailer = require('nodemailer');

const app = express();
const port = 3000;

// Web3 and WebSocket configuration
const NODE_URL = "YOUR_CHAINSTACK_WSS_ENDPOINT";
const websocketOptions = {
    clientConfig: {
        reconnect: {
            auto: true,
            delay: 5000,
            maxRetries: 10,
        },
    },
};

const web3 = new Web3(new Web3.providers.WebsocketProvider(NODE_URL, websocketOptions));

// Email configuration (customize with your SMTP settings)
const transporter = nodemailer.createTransport({
    service: 'gmail', // For example, using Gmail
    auth: {
        user: '[email protected]',
        pass: 'yourpassword' // Use environment variables or a secure method to store credentials
    }
});

// Function to send email
function sendEmail(logData) {
    const mailOptions = {
        from: '[email protected]',
        to: '[email protected]',
        subject: 'Smart Contract Event Detected',
        text: `New log data: ${JSON.stringify(logData)}`
    };

    transporter.sendMail(mailOptions, function(error, info){
        if (error) {
            console.log(`Error sending email: ${error}`);
        } else {
            console.log(`Email sent: ${info.response}`);
        }
    });
}

// Subscribe to contract logs
async function subscribeToContractLogs() {
    try {
        const logsFilter = {
            address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
            topics: ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
        };

        const subscription = await web3.eth.subscribe("logs", logsFilter);

        subscription.on("connected", (subscriptionId) => {
            console.log(`New subscription: ${subscriptionId}`);
        });

        subscription.on("data", (logData) => {
            console.log(logData);
            sendEmail(logData); // Send email on receiving log data
        });

        subscription.on("error", (error) => {
            console.error(`Error receiving logs: ${error}`);
        });

    } catch (error) {
        console.error(`Error subscribing to contract logs: ${error}`);
    }
}

subscribeToContractLogs();

// Basic Express route
app.get('/', (req, res) => {
    res.send('Ethereum log subscription server is running.');
});

app.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}`);
});

In this example, you could pass the list of contracts from an env variable and update it when adding more contracts.

Keep in mind you need a WebSocket endpoint to get real-time events.

You can learn more about fetching real-time data here:

This approach should provide a good starting point for your server application that watches multiple smart contracts and sends email alerts. Remember to test thoroughly and consider security implications.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.