npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ethereum-events

v0.1.3

Published

Efficient and reliable event listener for Ethereum.

Downloads

218

Readme

Ethereum Events

CircleCI NPM Version Coverage Status License

Efficient and reliable event listener for Ethereum.

Receive real-time events from your contracts with minimal effort.

Motivation

Ethereum, and blockchains in general, can be quite challenging for new developers to approach. Most of the difficulty resides in understanding the many dynamics that can occur (e.g. finality, reorgs) and how to deal with them to provide quality UX.

A lot of Ethereum based dApps heavily depend on events fired by their smart contracts. This package is meant to simplify the process of listening for these real-time events in a reliable yet efficient way, keeping away blockchain complexity as much as possible.

How it works

EthereumEvents continuously polls the Ethereum blockchain for new blocks. As soon as a new block is detected, the events contained inside it are immediately delivered for processing.

Since, in the blockchain environment, finality is probabilistic and increases with the number of subsequent blocks mined, blocks are delivered using two different channels: confirmed and unconfirmed.

Unconfirmed blocks are newer blocks that can be subject to reorgs, so the events contained inside them may still change.

Confirmed blocks, on the other hand, are older blocks that have reached a certain number of confirmations. It is relatively safe to assume that the events contained inside them are final and will not change.

For the vast majority of use cases, the default value of 12 confirmations is considered safe but it can be adjusted to fit every need.

Requirements

  • Web3 (1.2.0 or higher)

Installation

npm install ethereum-events

Usage

Setup and instantiate

const Web3 = require('web3');
const EthereumEvents = require('ethereum-events');

const ERC20_ABI = /* ABI for ERC20 token contract */;
const WEB3_PROVIDER = /* Your web3 provider (e.g. geth, Infura) */;

const contracts = [
  {
    name: 'Token',
    address: '0xefE1e4e13F9ED8399eE8e258b3a1717b7D15f054',
    abi: ERC20_ABI,
    events: ['Transfer'] // optional event filter (default: all events)
  } 
];

const options = {
  pollInterval: 13000, // period between polls in milliseconds (default: 13000)
  confirmations: 12,   // n° of confirmation blocks (default: 12)
  chunkSize: 10000,    // n° of blocks to fetch at a time (default: 10000)
  concurrency: 10,     // maximum n° of concurrent web3 requests (default: 10)
  backoff: 1000        // retry backoff in milliseconds (default: 1000)
};

const web3 = new Web3(WEB3_PROVIDER);

const ethereumEvents = new EthereumEvents(web3, contracts, options);

Register listeners

ethereumEvents.on('block.confirmed', (blockNumber, events, done) => {

  // Events contained in 'confirmed' blocks are considered final,
  // hence the callback is fired only once for each blockNumber.
  // Blocks are delivered in sequential order and one at a time so that none is skipped
  // and you know for sure that every block up to the latest one received was processed.
  
  // Call 'done()' after processing the events in order to receive the next block. 
  // If an error occurs, calling 'done(err)' will retry to deliver the same block
  // without skipping it.

});

ethereumEvents.on('block.unconfirmed', (blockNumber, events, done) => {
  
  // Events contained in 'unconfirmed' blocks are NOT considered final
  // and may be subject to change, hence the callback may be fired multiple times
  // for the same blockNumber if the events contained inside that block change.
  // Blocks are received one at a time but, due to reorgs, the order is not guaranteed.
  
  // Call 'done()' after processing the events in order to receive the next block. 
  // If an error occurs, calling 'done(err)' will retry to deliver the same block
  // without skipping it.
  
});

ethereumEvents.on('error', err => {

  // An error occured while fetching new blocks/events.
  // A retry will be attempted after backoff interval.

});

Start listening

const startBlock = 6596988;

ethereumEvents.start(startBlock); // startBlock defaults to 'latest' when omitted

ethereumEvents.isRunning() // true

// Stop listening for events
ethereumEvents.stop();

Event Format

{
  "name": "Transfer",
  "contract": "Token",
  "timestamp": 1591110290,
  "blockHash": "0xde42b82c4e28122218d79f8491b05587608a8c9bb87c0d0df9be9fb9ae6f7e13",
  "blockNumber": 6596988,
  "transactionHash": "0x686943cee4035375b25209a2972535c93eefb688fad42d72e518c452387c69c9",
  "transactionIndex": 10,
  "from": "0x5B848132d3a0111d4daB7060b6051961013C71c7",  // sender of the transaction
  "to": "0xefE1e4e13F9ED8399eE8e258b3a1717b7D15f054",    // receiver of the transaction
  "logIndex": 11,
  "values": {
    "from": "0x343c6A169D973bBF33A8F1535754A4745a3BD9C1",
    "to": "0x78a3339aD6A565B4136077C8878970D7f1B66021",
    "value": "100000000000000000000"
  }
}

Notes

The chunkSize option lets you customize how many blocks to query for events at a time. This is useful when the start block is far behind the current latest block and many blocks have to be fetched to get up to date.
Having a higher chunkSize is more performant but it may cause a failure in the calls to your provider if too many events are retrieved in the same request so the optimal value heavily depends on how many events your contracts emit.

The concurrency option lets you customize how many concurrent requests can be made to your web3 provider so that you can avoid being rate limited.