Viewing File: /home/ubuntu/efiexchange-node-base/src/app.ts
import "reflect-metadata";
import express, { Request, Response, NextFunction } from "express";
import logger from "./utils/logger";
import mainRoutes from "./routes";
import cors from "cors";
import fileUpload from "express-fileupload";
import methodOverride from "method-override";
import path from "path";
import fs from "fs";
import http from "http";
import { fetchExchangeRate, fetchGatewayExchangeRate, fetchSDKExchangeRate } from "./controllers/userApp/exchange.controller";
import { errorHandler } from '@shared/infra/http/middlewares/errorHandler'
import { headerHandler } from '@shared/infra/http/middlewares/headerHandler'
// Sentry Bitcoin
import { sentryConfig } from '@config/sentry'
import * as Sentry from '@sentry/node'
import { fetchOTCExchangeRate } from "./controllers/exchange";
import { loadValidBinanceSymbols } from "./controllers/exchange/functions/providerSymbols";
import { loadValidOKXSymbols } from "./controllers/exchange/providers/okx";
import { stopAllPollingForUser } from "./controllers/exchange/providers/bvnk";
import { unsubscribeAllProviders } from "./controllers/exchange/functions/disconnectProviders";
import { sendUnsubscribe, sendDepthSubscribe, sendDepthUnsubscribe, sendTickerSubscribe, sendTickerUnsubscribe } from "./controllers/exchange/providers/binance"
const SocketIo = require("socket.io");
const port = process.env.NODE_SERVER_PORT || 9001;
const SSL_KEY = process.env.SSL_KEY;
const SSL_CERTIFICATE = process.env.SSL_CERTIFICATE;
const app = express();
sentryConfig(app)
let server;
const corsOpts = {
origin: '*',
methods: ['GET', 'POST'],
};
// Middleware for cross-origin requests
app.use(cors(corsOpts));
// Middleware for parsing requests
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride());
app.use(Sentry.Handlers.errorHandler())
// Create HTTP or HTTPS server based on the presence of SSL certificates
if (SSL_KEY && SSL_CERTIFICATE) {
const https = require('https');
server = https.createServer({
key: fs.readFileSync(SSL_KEY),
cert: fs.readFileSync(SSL_CERTIFICATE),
}, app);
} else {
server = http.createServer(app);
}
// Extend Response interface to include custom methods
declare global {
namespace Express {
interface Response {
sendResponse: (data: any, message: string) => void;
sendError: (ex: any, ex_code?: number) => void;
sendErrorCode: (ex: any, ex_code?: number) => void;
}
}
}
// Middleware for custom response helpers
app.use((req: Request, res: Response, next: NextFunction) => {
// logger.info(" - - - - - - - - - - BODY START - - - - - - - - - - ");
// logger.info(JSON.stringify(req.body));
// logger.info(" - - - - - - - - - - BODY END - - - - - - - - - - ");
logger.info(" - - - - - - - - - - - - - - - - - - - - - - - - - - ");
// Success Response
res.sendResponse = (data: any, message: string) => {
return res.status(200).json({
success: true,
data,
message,
code: 200,
});
};
// Failure Response
res.sendError = (ex: any, ex_code: number = 200) => {
return res.status(ex_code).json({
success: false,
error: ex,
code: 200,
});
};
// Failure with code
res.sendErrorCode = (ex: any, ex_code: number) => {
return res.status(200).json({
success: false,
error: ex,
code: ex_code,
});
};
next();
});
// Default home page route
app.get("/", (req: Request, res: Response) => {
res.send("Welcome to Wallet App");
});
// Enable file uploads with security
app.use(
fileUpload({
createParentPath: true,
limits: { fileSize: 10 * 1024 * 1024 }, // Limit file size to 10 MB
abortOnLimit: true, // Abort request if file exceeds size limit
safeFileNames: true, // Remove potentially harmful characters from filenames
})
);
// Serve static files
app.use(express.static("public"));
app.use("/public", express.static(path.resolve(__dirname, "public")));
// API routes with Error Handlers
app.use(headerHandler)
app.use("/api", mainRoutes);
app.use(errorHandler)
// Catch 404 and forward to error handler
app.use((req: Request, res: Response) => {
res.status(404).json({
success: false,
message: "The requested URL is not found",
code: 404,
});
});
// Centralized error-handling middleware
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
logger.error(err.message);
res.status(500).json({
success: false,
error: err.message,
code: 500,
});
});
// Exchange Rate Socket
const io = SocketIo(server, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
});
interface UserBinanceWS {
ws: WebSocket;
depthSubs: Set<string>;
}
const users: Record<string, UserBinanceWS> = {};
io.on("connection", (socket: any) => {
console.log("New client connected:", socket.id);
let monitoringSessions = {};
socket.on("fetchConversionRate", (data: any) => {
const { pair, type, currency_pair_id, user_configuration } = data;
console.log(`pairs logger--------->`,pair); // USD-TRX,ETH-BNB,TRX-BTC
if(!pair || pair.length === 0 || pair === "undefined" || pair === null) return;
// const [fromCurrency, toCurrency] = pair.split("-");
// console.log(`Fetch Exchange Rate For : ${fromCurrency}-${toCurrency}`);
// Split the comma-separated pairs into an array
const pairs = Array.isArray(pair) ? pair : pair.split(",").map((p: string) => p.trim());
console.log("pair--------------->", pair);// USD-TRX,ETH-BNB,TRX-BTC
// New Currencies with country code
if (isNaN(currency_pair_id)) {
stopAllPollingForUser(socket.id);
unsubscribeAllProviders(socket.id);
}
// Loop through each currency pair
pairs.forEach((p: string) => {
const [fromCurrency, toCurrency] = p.split("-");
console.log(`Exchange Rate For : ${fromCurrency}-${toCurrency}`);
console.log("fetching started");
if (fromCurrency.includes(":") || toCurrency.includes(":")) {
console.log("currency includes :");
let fiatCurrency;
if (fromCurrency.includes(":")) {
console.log("fromCurrency includes :");
fiatCurrency = fromCurrency.split(":")[0];
} else if (toCurrency.includes(":")) {
console.log("toCurrency includes :");
fiatCurrency = toCurrency.split(":")[0];
}
if (["USD", "EUR"].includes(fiatCurrency) && fiatCurrency.includes(":")) {
console.log("fiatCurrency includes :");
let fromCurrencyCode = fromCurrency.split(":")[0];
let toCurrencyCode = toCurrency.split(":")[0];
// Provider subscription
fetchOTCExchangeRate(
fromCurrencyCode,
toCurrencyCode,
socket.id,
socket,
type,
p,
user_configuration
);
} else {
// API calls
fetchExchangeRate(
fromCurrency.replace(":", "-"),
toCurrency.replace(":", "-"),
socket.id,
socket,
type
);
}
} else {
// Provider subscription
fetchOTCExchangeRate(
fromCurrency,
toCurrency,
socket.id,
socket,
type,
p,
user_configuration
);
}
});
});
socket.on("fetchExchangeRate", (data:any) => {
const { pair, type, currency_pair_id, user_configuration } = data;
const [fromCurrency, toCurrency] = pair.split("-");
console.log(`Conversion Rate For : ${fromCurrency}-${toCurrency}`);
// New Currencies with country code
if(isNaN(currency_pair_id)){
stopAllPollingForUser(socket.id);
unsubscribeAllProviders(socket.id);
}
if((fromCurrency.includes(':') || toCurrency.includes(':'))) {
let fiatCurrency;
if(fromCurrency.includes(':')) {
fiatCurrency = fromCurrency.split(':')[0];
} else if(toCurrency.includes(':')) {
fiatCurrency = toCurrency.split(':')[0];
}
if(["USD", "EUR"].includes(fiatCurrency)) {
let fromCurrencyCode = fromCurrency.split(':')[0];
let toCurrencyCode = toCurrency.split(':')[0];
// Provider subscription
fetchOTCExchangeRate(fromCurrencyCode, toCurrencyCode, socket.id, socket, type, currency_pair_id, user_configuration);
} else {
// API calls
fetchExchangeRate(fromCurrency.replace(":", "-"), toCurrency.replace(":", "-"), socket.id, socket, type);
}
} else {
// Provider subscription
fetchOTCExchangeRate(fromCurrency, toCurrency, socket.id, socket, type, currency_pair_id, user_configuration);
}
});
// used binance socket to fetch crypto rates
socket.on("subcribeCryptoRates", (data: any) => {
const {pair, user_id} = data;
if (!pair || !user_id) return;
sendTickerSubscribe(user_id, pair.toLowerCase(), socket);
});
socket.on("unsubscribeCryptoRates", (data: any) => {
const {pair, user_id} = data;
if (!pair || !user_id) return;
sendTickerUnsubscribe(user_id, pair.toLowerCase(), socket);
});
socket.on("fetchSDKExchangeRate", (data: any) => {
const { pair, user_id, type, apiKey, userId } = data;
const [fromCurrency, toCurrency] = pair.split("-");
console.log(`Fetch SDK Exchange Rate For : ${fromCurrency}-${toCurrency}`);
fetchSDKExchangeRate(fromCurrency, toCurrency, user_id, socket, type, apiKey, userId);
});
socket.on("subcribeDepthRate", (data: any) => {
const {pair, user_id} = data;
if (!pair || !user_id) return;
sendDepthSubscribe(user_id, pair.toLowerCase(), socket);
});
socket.on("unsubcribeDepthRate", (data: any) => {
const {pair, user_id} = data;
if (!pair || !user_id) return;
sendDepthUnsubscribe(user_id, pair.toLowerCase(), socket);
});
socket.on("fetchGatewayExchangeRate", (data: any) => {
const { pair, user_id, type, apiKey, userId } = data;
const [fromCurrency, toCurrency] = pair.split("-");
console.log(`Fetch Gateway Exchange Rate For : ${fromCurrency}-${toCurrency}`);
fetchGatewayExchangeRate(fromCurrency, toCurrency, user_id, socket, type, apiKey, userId);
});
socket.on("closeProviders", (data: any) => {
console.log("Closing providers manually")
stopAllPollingForUser(socket.id);
unsubscribeAllProviders(socket.id);
// fetchOTCExchangeRate(fromCurrency, toCurrency, user_id, socket, type, currency_pair_id, user_configuration);
});
socket.on("disconnect", () => {
stopAllPollingForUser(socket.id);
unsubscribeAllProviders(socket.id);
console.log("Client disconnected:", socket.id);
});
});
// Server Initiation
server.listen(port, () => {
try {
(async () => {
await loadValidBinanceSymbols()
await loadValidOKXSymbols()
})();
logger.info(`Server is listening on port ${port}`);
} catch (err) {
process.exit(1);
}
});
Back to Directory
File Manager