Build your own cryptocurrency price alert service using NodeJS

ExpressJS, BullMQ, Cron jobs, email notifications and more.

Photo by CardMapr on Unsplash

Everyone in this world is busy. We are poor at remembering things (especially me). Being motivated by the above two statements, I ended up building this simple cryptocurrency price alert microservice, which will send an email notification if the price of the specified coin goes above/below the threshold price. We need not stare at the market to check the price all day. All you need to do is just choose the currency and specify the threshold price, that’s it. You’ll get notified via the provided email address.

I have used NodeJS for implementation. You can follow the steps and build the same using other programming languages as well. This tutorial is just for a demonstration, it is not production-ready or stable (as I will use store the alerts in-memory for simplicity). However, I’m sure that you’ll find this demo pretty interesting as we will implement queuing for notifications, send emails, service workers(Cron jobs), and more. You can also improve this by adding more features.

Having said that, let us have a glance at the key features of this project :

  • Set price alerts — For the prices above/below a threshold price.

  • Fetch all the active alerts

  • Automatic expiry of alerts.

  • Email notification.

Before getting started, you’ll need the following :

  • NodeJS : Install the LTS version for your operating system.

  • Postman : A tool to play with the APIs on the fly. In this demo, we will use this software to create and retrieve alerts.

  • Redis server : Install and configure it locally or you can opt for a cloud service provider if you prefer. We need the Redis server to deal with the Bull MQ.

  • SendGrid API key : Use this link to create a new account and get the API key. It is required to send email notifications

Once the environment is set up, we can dive into the implementation part.

Initialize the project :

Follow the below steps to initialize an empty NodeJS project.

  1. Create an empty directory - mkdir price-alert

  2. Navigate to the directory — cd price-alert

  3. Initialize a new project — npm init and answer the questions. Or you can use npm init -y to settle with the default configuration.

Install the dependencies :

We will use the following dependencies in our project.

1.Express: To handle the HTTP requests from the client. Helpful in building APIs

2.Axios: A library that helps us make HTTP requests to external resources.

3.Bull: Robust messaging queue based on Redis

4.Cron: Used for job scheduling.

5.Nodemailer: Used for sending email notifications.

Let us now install all the dependencies using the following command :

npm install express axios bull cron nodemailer --save

Note: You can also install the developer dependencies like nodemailer if you prefer.

Project Directory Structure:

Let’s get started:

In the app.js file let us configure the express server. Add the following contents and save the file.

Fire up the server using the node app command. You’ll see the following output :

> Server started listening!

If you navigate to http://localhost:5000/ .You must see the status as “Up and running”

Cool. Now our application can process the HTTP requests.

Implementing the endpoints :

Let’s now create a router.js file that will contain all the endpoints used in our project.

The controller.js file will contain the logic for each endpoint.

Let us define the logic for the endpoints. First, let’s start with the CurrentPrice endpoint.

You can see that I used the function currentPrice to fetch the current market price.

Let us implement the “currentPrice” function inside the helpers folder. This is the most important function as we will use this function in many places of this application.

> For the sake of simplicity, I implemented only BTC and ETH price alerts in this demo. You can add whatever assets you prefer.

To fetch the current price of ETH and BTC, I am using the nomics api . You can fetch the price from any source.

Also, I have defined an error object in the config.js file which can be sent, in case any unknown errors occur while processing requests.

Import the error object and the current price function in the controller file and save it.

Now let us test our GET /prices endpoint.Fire up the server and navigate to http://localhost:5000/prices. You can see the price object being displayed in the browser or hit the endpoint through the Postman.

Great! We managed to get the current market price of ETH and BTC in USD.

Let us move ahead to implement two more endpoints for creating alerts and retrieving all active alerts. For using the alerts globally in our application, we will create a file alerts.js that exports an empty array.

module.exports = [ ];

Import the file at the top of controller.js file.

var alerts = require(‘./alerts’);

Let’s define the logic to create new alerts.

I’m storing the alerts in-memory to keep this demo simple. The alerts will be lost if we stop the server as they are stored temporarily on the volatile memory. Please use a database if you want to use this in production.

Next, define the logic to retrieve all the active alerts. This endpoint is simple. We need to just return the alerts array.

exports.GetAlerts = async (req, res) => { return res.send( { success: true, alerts: alerts } )};

That’s it. We need to define endpoints to create and retrieve alerts.

router.get(“/alerts”, Controller.GetAlerts); router.post(“/alert”, Controller.CreateAlert);

After defining all three routes, the router.js file will look like this :

We need to import and use this router file in out app.js file.

Now it’s time to have some fun. Let’s open up the Postman and test our endpoints. First we will try creating an alert for BTC with a threshold price below 49000.095 USD

You can see the Alert created message in the response. Similarly you can try creating multiple alerts for the threshold price and you can also specify the email address too for receiving the alerts.

Now we can try fetching all the alerts.

It works! We have implemented all the endpoints required for this project. Now we need to remove the expired alerts. I have set the expiry time for the alerts to 5 minutes. You can modify it based on your requirements.

Implementing the Cron Jobs (Scheduler) :

We need to implement 2 schedulers. One is to remove the expired alerts and the other is to send alerts to email if the price of the specified coin goes above/below the threshold.

First, let us implement the removeExpired service. To keep things simple, the worker will iterate through all the active alerts every 10 seconds and remove the alerts that are created before 5 minutes from now.

Save the file and require it on the controller.js file :

require(./workers/removeExpired.js)

Scheduler starts as soon as we start the application.

Now, start the server and add some alerts. You can see that the alerts are removed in 5 minutes after they are created. You can use the GET /alerts endpoint to confirm that the removeExpired service works as expected.

Before implementing our second scheduler — sendAlert we need to implement the sendEmailNotification helper function to send email notifications.

Open up the helpers/sendEmailNotification.js and add the following :

Save the file. Make sure you add the USERNAME, PASSWORD, EMAIL, and NAME in the config file.

Add the following contents to workers/sendAlert.js :

I’m running the scheduler every 25 seconds. You can change it as per your requirement. Once an alert is pushed to the queue, we will remove it from the alerts array to prevent redundant alerts.

Also, make sure that the redis-server is up and running on port 6379 if you are using localhost and the REDIS_URL must be entered correctly in the config.js file.

I have set the max retry times as 3 and the backoff period as 3 seconds, which means in case that some error occurred while sending the email, the bullmq’s consumer process will try to process the request at a time interval of 3 seconds. If the request fails 3 times, then it will be discarded.

Now save the file and start the server by running the npm run start command.

Open up the postman and add some alerts. You’ll get alerts to the specified email address like this.

If the email didn’t hit the inbox, make sure you check the spam and promotions folder. Also, you need to whitelist the sender in your SendGrid account, so that your emails will hit the inbox.

> You can find the entire source code for this project here on GitHub.

Conclusion:

As I previously mentioned, this application is not suitable for production unless you make some more improvements like saving the alerts to a database, passing the keys as env variables, configuring process managers, and so on.,

Try to take this demo to the next level by adding some more features.

You can try :

  • Adding push notifications or SMS alerts

  • Adding more coins/tokens.

  • Sending an alert to multiple email addresses.

  • Turning this demo into a full-stack application by designing the UI

  • Taking it online by deploying on the cloud server.

That’s all folks. As always, feel free to share your thoughts and suggestions.

Happy coding!