Skip to content

Node.js app for monitoring transactions that interact with CHZ smart contract

Notifications You must be signed in to change notification settings

gabuladze/chz-transaction-monitor

Repository files navigation

Table of Contents



Problem Statement

Write a NodeJs program that could index the Ethereum blockchain in real-time. Watch and store any new transactions interacting with the CHZ token smart contract (0x3506424f91fd33084466f402d5d97f05f8e3b4af). Provide two private API endpoints (no need for authentication)

  • One that would allow a user to retrieve the total amount of CHZ transferred (since the start of the program)
  • One that would return whether a transaction is interacting with the CHZ token smart contract or not given its transaction hash (transaction older than the program is possible)

Solution Overview

The app uses:

  • web3.js for interacting with eth node.
  • Decimal.js for avoiding arithmetic precision errors
  • Express.js for http server
  • Eslint with standard preset for linting
  • Mocha, chai, chai-http for tests
  • Docker, docker-compose
  • MongoDB for storing transactions & app state
  • swagger-ui-express for providing swagger ui of the OpenAPI definition of the API

The app looks at every transaction in each block and picks out transactions that interact with contract specified in config.js (CHZ by default).
The script that processes blocks supports small chain reorganizations, bigger reorgs can be supported by keeping track of more blocks in db.
The code in services/TransactionsService.js can identify [account]->[CHZ contract] transactions as well as transactions with internal contract transfers (account->[Some smart contract]->[CHZ smart contract]).

Since this is just a test task, I don't see a point in going super in-depth and spending a lot of time polishing the app. But there are a few points that have to be made. The next steps I would take for optimizing the app would be:

  • Add multi-document transactions for consecutive db insert operations.
    • With current implementation, db insert operations in the processBlock script are not atomic. If the script fails somewhere in the middle, same transactions can be inserted more than once, resulting in incorrect results in getTotalTokensTransferedSinceStart function's aggregation pipeline.
  • Split the app into two services: one with processBlock script and the other with HTTP server for API endpoints
    • Reason for this is that in some cases processBlock could block current thread and make the request to API endoints timeout.

Setup

1. Create .env file

You can use the .env.example provided in the repo. Run:

cp .env.example .env

After this make sure to populate the WS_HOST and WS_PORT or only INFURA_URL env variables with correct values. The rest of the values provided in .env.example will work.

Parameter Description Default Value
NODE_ENV App Environment Dev
WS_HOST Geth WS server host
WS_PORT Geth WS server port
INFURA_URL Infura url
MONGODB_USERNAME MongoDB Username
MONGODB_PASSWORD MongoDB Password
MONGODB_HOST MongoDB Host
MONGODB_PORT MongoDB Port
MONGODB_DBNAME MongoDB Db name

When connecting to Geth, the app will look for WS_HOST & WS_PORT variables first, if they are not specified the app will fall back to INFURA_URL

1.1 Extra configuration parameters

In config.js you can set TOKEN.SYMBOL & TOKEN.CONTRACT_ADDRESS to monitor any ERC20 token transactions. Default value is CHZ.

2. Start the app

Next step would be to run the app.
Once started, the the app will start looking at every block and saving transaction receipts for transactions that interract with CHZ smart contract.

Start with docker-compose

Run:

docker-compose up

This will build the docker image, install dependencies & start the chz-transaction-monitor-1 & chz-transaction-monitor-mongodb-1 containers.
You will be presented the stdout of the containers.
The http server in the container will be bound to host port 3003.
To stop, press Ctrl+C.

Start without docker-compose

The app was tested on Node.js 16.13 LTS, therefore I would suggest to use this version to avoid any bugs/anomalies.
To run the app:

  1. Start a MongoDB server
  2. Run npm i to install all the dependencies
  3. Run npm start

API Reference

You can visit the swagger ui at http://localhost:3003/api-reference. Or see the details below:

Retrieve the total amount of CHZ transferred (since the start of the program)

  • Request Path: /api/transactions/totals
  • Request Method: GET Response:
{
    "totalTokensTransfered": 0,
    "totalTokensTransferedNative": 0
}

totalTokensTransfered will be the amount in CHZ
totalTokensTransferedNative will be the native amount aka totalTokensTransfered * Math.pow(10, chzTokenDecimals)

Check whether a transaction is interacting with the CHZ token smart contract or not given its transaction hash (transaction older than the program is possible)

  • Request Path: /api/transactions/check/:transactionHash
  • Request Method: GET Response:
{
    "isTokenTransaction": true
}

Tests

I've included few simple tests in the test folder. The tests follow the Arrange-Act-Assert pattern and use mocha, chai & chai-http. To run them run:

npm test

or if you used docker-compose:

docker exec -it chz-transaction-monitor-1 npm test

About

Node.js app for monitoring transactions that interact with CHZ smart contract

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages