Skip to content

Latest commit

Β 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🚨 RasadX

Cryptocurrency Listing Monitoring & Alert System

Node.js JavaScript Tests License

RasadX is a modular Node.js monitoring and notification system that detects newly listed trading pairs across cryptocurrency exchanges and sends real-time alerts through Telegram and Email.

The project is built with a focus on clean architecture, separation of concerns, dependency injection, testability, and extensibility.


πŸ”— Quick Links


✨ Features

  • πŸ”Ž Monitor cryptocurrency listings
  • 🏦 Binance integration
  • 🏦 Bybit integration
  • πŸ“± Telegram notifications
  • πŸ“§ Email notifications
  • πŸ’Ύ JSON-based persistent state
  • πŸ”„ Automatic retry for temporary API failures
  • πŸ§ͺ Unit testing with Vitest
  • 🧩 Modular and extensible architecture
  • πŸ“ Structured logging
  • ⏱️ Periodic monitoring
  • πŸ›‘οΈ Duplicate listing prevention
  • πŸ” Environment-based configuration

πŸ—οΈ Architecture

rasadX follows a modular architecture based on separation of responsibilities.

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚     index.js     β”‚
                    β”‚   Application    β”‚
                    β”‚      Entry       β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚                         β”‚
                β–Ό                         β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚    Binance    β”‚         β”‚     Bybit     β”‚
        β”‚    Adapter    β”‚         β”‚    Adapter    β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                β”‚                         β”‚
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚ ListingMonitor  β”‚
                    β”‚  Core Business  β”‚
                    β”‚      Logic      β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚                 β”‚
                    β–Ό                 β–Ό
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚ JsonRepository β”‚ β”‚ Notifications  β”‚
           β”‚   Persistence  β”‚ β”‚    Layer       β”‚
           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                      β”‚
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”
                              β–Ό               β–Ό
                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                         β”‚Telegram β”‚     β”‚  Email  β”‚
                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”„ How It Works

1. Fetch exchange data

Exchange adapters retrieve the latest market information.

Binance API
     ↓
Binance Adapter
Bybit API
     ↓
Bybit Adapter

2. Normalize exchange data

Different exchanges return different response formats.

Each adapter converts exchange-specific responses into a common internal structure:

{
  symbol: "BTCUSDT",
  status: "TRADING",
  baseAsset: "BTC",
  quoteAsset: "USDT"
}

This keeps the monitoring layer independent from exchange-specific API formats.

3. Compare current state with previous state

Previously detected symbols are stored in:

data/symbols.json

Example:

{
  "Binance": [
    "BTCUSDT",
    "ETHUSDT"
  ],
  "Bybit": [
    "BTCUSDT",
    "SOLUSDT"
  ]
}

If the exchange returns:

Previous:
BTCUSDT
ETHUSDT

Current:
BTCUSDT
ETHUSDT
ABCUSDT

rasadX detects:

🚨 ABCUSDT

as a new listing.

4. Send notifications

Every newly detected listing is passed to the configured notification services.

New Listing
     β”‚
     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Ί Telegram
     β”‚
     └──────────► Email

Example:

🚨 NEW LISTING

Exchange: Binance
Symbol: ABCUSDT
Time: 2026-08-12T12:00:00.000Z

🧩 Project Structure

rasadX/
β”‚
β”œβ”€β”€ src/
β”‚   β”‚
β”‚   β”œβ”€β”€ exchanges/
β”‚   β”‚   β”œβ”€β”€ Binance.js
β”‚   β”‚   └── Bybit.js
β”‚   β”‚
β”‚   β”œβ”€β”€ repositories/
β”‚   β”‚   └── JsonRepository.js
β”‚   β”‚
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”œβ”€β”€ ListingMonitor.js
β”‚   β”‚   β”œβ”€β”€ NotificationService.js
β”‚   β”‚   └── EmailNotificationService.js
β”‚   β”‚
β”‚   β”œβ”€β”€ utils/
β”‚   β”‚   β”œβ”€β”€ logger.js
β”‚   β”‚   └── retry.js
β”‚   β”‚
β”‚   └── index.js
β”‚
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ Binance.test.js
β”‚   β”œβ”€β”€ Bybit.test.js
β”‚   β”œβ”€β”€ EmailNotificationService.test.js
β”‚   β”œβ”€β”€ JsonRepository.test.js
β”‚   β”œβ”€β”€ ListingMonitor.test.js
β”‚   β”œβ”€β”€ NotificationService.test.js
β”‚   └── retry.test.js
β”‚
β”œβ”€β”€ data/
β”‚   └── symbols.json
β”‚
β”œβ”€β”€ .env.example
β”œβ”€β”€ .gitignore
β”œβ”€β”€ package.json
└── README.md

πŸ› οΈ Tech Stack

Runtime

  • Node.js
  • JavaScript
  • ES Modules

HTTP / APIs

  • Axios
  • Binance REST API
  • Bybit REST API

Notifications

  • Telegram Bot API
  • Nodemailer
  • SMTP

Persistence

  • JSON file storage

Testing

  • Vitest
  • Mocking external dependencies

Utilities

  • dotenv
  • Structured logging
  • Reusable retry mechanism

πŸ”„ Retry Mechanism

External APIs can temporarily fail because of:

  • Network problems
  • Server errors
  • Rate limits
  • Temporary service unavailability

rasadX includes a reusable retry utility.

Example:

await retry(fetchData, {
  retries: 3,
  delay: 2000,
  shouldRetry: (error) => {
    const status = error.response?.status;

    return (
      !status ||
      status === 429 ||
      status >= 500
    );
  }
});

The system retries temporary failures while avoiding unnecessary retries for client-side errors.

Request
   β”‚
   β”œβ”€β”€ ❌ 500
   β”‚
   β”œβ”€β”€ Retry
   β”‚
   β”œβ”€β”€ ❌ 500
   β”‚
   β”œβ”€β”€ Retry
   β”‚
   └── βœ… Success

πŸ§ͺ Testing

rasadX uses Vitest for unit testing.

Tests cover:

  • Listing detection
  • Duplicate listing prevention
  • First-run initialization
  • Exchange state isolation
  • Multiple notification services
  • JSON persistence
  • Binance API adapter
  • Bybit API adapter
  • Telegram notification service
  • Email notification service
  • Retry behavior

External services are mocked during unit tests.

Therefore, the test suite does not require:

  • Real Binance API calls
  • Real Bybit API calls
  • Real Telegram messages
  • A real SMTP server

Run the test suite:

npm test

πŸš€ Getting Started

Prerequisites

Make sure you have:

  • Node.js 20+
  • npm

1. Clone the repository

git clone https://github.com/RadinAnsari/rasadX.git
cd rasadX

2. Install dependencies

npm install

3. Configure environment variables

Create a .env file:

cp .env.example .env

Example:

TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=

SMTP_HOST=
SMTP_PORT=465
SMTP_USER=
SMTP_PASSWORD=

EMAIL_FROM=
EMAIL_TO=

Never commit .env to Git.

4. Initialize JSON storage

Create:

data/symbols.json

with:

{}

The application will populate the exchange state automatically.

5. Start the monitor

npm run app

The application periodically checks the configured exchanges and sends notifications when new listings are detected.


πŸ” Environment Variables

Variable Description
TELEGRAM_BOT_TOKEN Telegram bot token
TELEGRAM_CHAT_ID Telegram destination chat
SMTP_HOST SMTP server hostname
SMTP_PORT SMTP server port
SMTP_USER SMTP username
SMTP_PASSWORD SMTP credential / app password
EMAIL_FROM Sender email
EMAIL_TO Destination email

Sensitive credentials are intentionally stored in environment variables and excluded from version control.


βž• Adding a New Exchange

The exchange layer is designed around a simple adapter concept.

For example:

src/exchanges/OKX.js
export class OKX {
  constructor() {
    this.name = "OKX";
  }

  async getSymbols() {
    // Fetch and normalize OKX symbols
  }
}

The core ListingMonitor does not need to know the details of the OKX API.

This makes the system easy to extend to additional exchanges.


βž• Adding a New Notification Channel

Notification services follow the same conceptual interface.

For example:

src/services/DiscordNotificationService.js
export class DiscordNotificationService {
  async sendNewListing({
    exchange,
    symbol,
  }) {
    // Send Discord notification
  }
}

It can then be added to the notification services array:

const notificationServices = [
  telegramNotification,
  emailNotification,
  discordNotification,
];

The core listing detection logic does not need to change.


🧠 Design Principles

Separation of Concerns

Exchange communication, business logic, persistence, and notifications are separated.

Exchange
   ↓
ListingMonitor
   ↓
Repository / Notifications

Dependency Injection

Core services receive their dependencies instead of creating them internally.

new ListingMonitor(
  exchange,
  repository,
  notificationServices
);

This makes the business logic easier to test and extend.

Adapter Pattern

Each exchange adapter hides exchange-specific API details.

Binance API ──► Binance Adapter ──┐
                                  β”œβ”€β”€β–Ί Common Format
Bybit API ────► Bybit Adapter β”€β”€β”€β”€β”˜

Extensible Notification Layer

Notification providers expose the same conceptual operation:

sendNewListing({
  exchange,
  symbol
});

This allows additional channels to be introduced without changing the core listing detection logic.

Testability

External dependencies are injected and mocked during unit tests.

This allows the core business logic to be tested without network access or real credentials.

⚠️ Disclaimer

This project is an educational and software engineering project.

It monitors publicly available exchange market information and sends notifications.

It does not execute trades or provide financial advice.


πŸ“„ License

This project is licensed under the MIT License.


Built with Node.js and JavaScript.

About

A Node.js monitoring and notification system for detecting newly listed trading pairs across cryptocurrency exchanges.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages