/** @format */ import express from "express"; import cors from "cors"; import admin from "firebase-admin"; import fetch from "node-fetch"; import fs from "fs"; import { format } from "date-fns"; const serviceAccount = JSON.parse( fs.readFileSync("./serviceAccountKey.json", "utf-8") ); const app = express(); app.use(cors()); // Initialize Firebase Admin SDK admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "https://cryptocoinex-fa700-default-rtdb.europe-west1.firebasedatabase.app", }); const db = admin.database(); app.get("/api/price", async (req, res) => { const { symbol } = req.query; try { // Fetch price data from CoinCap API const response = await fetch(`https://api.coincap.io/v2/assets/${symbol}`); const data = await response.json(); if (data && data.data) { res.json({ price: data.data.priceUsd, symbol: data.data.symbol, name: data.data.name, }); } else { res.status(404).json({ error: "Asset not found" }); } } catch (error) { console.error("Error fetching price:", error); res.status(500).json({ error: "Error fetching price" }); } }); // Fetch market prices from an external API async function fetchMarketPrices() { const response = await fetch("https://api.coincap.io/v2/assets"); if (!response.ok) { throw new Error(`Failed to fetch market prices: ${response.statusText}`); } const data = await response.json(); return data.data; // Array of market data } // Update database based on market changes async function processMarketData() { console.log( `[${format(new Date(), "dd/MM/yyyy, HH:mm:ss")}] Fetching market data...` ); try { const marketData = await fetchMarketPrices(); console.log("Market data fetched successfully."); const updates = {}; for (const token of marketData) { if (token.symbol === "USDT") continue; const tokenRef = db.ref(`OrderBook/${token.symbol}`); const snapshot = await tokenRef.once("value"); const orders = snapshot.val(); if (orders) { Object.entries(orders).forEach(([orderId, order]) => { let orderPrice = parseFloat(order.price); let tokenPrice = parseFloat(token.priceUsd); const user = order.user; if ( order.status === "open" && (tokenPrice >= orderPrice || tokenPrice <= orderPrice) ) { updates[`OrderBook/${token.symbol}/${orderId}/status`] = "filled"; updates[`OrderBook/${token.symbol}/${orderId}/updatedAt`] = format( new Date(), "dd/MM/yyyy, HH:mm:ss" ); // const userWalletsRef = db.ref(`UserAccounts/${user}/Wallet`); // userWalletsRef.once("value", (walletSnapshot) => { // const userWallets = walletSnapshot.val(); // if (userWallets) { // let walletKey = null; // Object.entries(userWallets).forEach(([walletId, wallet]) => { // if (wallet.Token === order.currencySymbol) { // walletKey = walletId; // } // }); // if (walletKey) { // // const tokenWallet = userWallets[walletKey]; // // if (order.type === "buy") { // // updates[`UserAccounts/${user}/Wallet/${walletKey}/Amount`] = // // parseFloat(tokenWallet.Amount) + parseFloat(order.paid); // // } else if (order.type === "sell") { // // updates[`UserAccounts/${user}/Wallet/${walletKey}/Amount`] = // // parseFloat(tokenWallet.Amount) - parseFloat(order.paid); // // } // } else { // // Create a new wallet if none exists // const newWalletRef = userWalletsRef.push(); // updates[`UserAccounts/${user}/Wallet/${newWalletRef.key}`] = { // Amount: parseFloat(order.mySize), // Token: order.currencySymbol, // walletAddress: generateWalletAddress(), // }; // } // } // }); } }); } } if (Object.keys(updates).length > 0) { await db.ref().update(updates); console.log("Database updated successfully:", updates); } else { console.log("No updates required."); } } catch (error) { console.error( `[${format( new Date(), "dd/MM/yyyy, HH:mm:ss" )}] Error processing market data:`, error.message ); } } console.log(process.memoryUsage()); function determineMarketTrend(currentPrice, entryPrice) { return currentPrice > entryPrice ? "bullish" : "bearish"; } const calculateProfit = ({ entryPrice, closingPrice, leverage, tokens }) => { const priceDifference = closingPrice - entryPrice; const profit = priceDifference * leverage * tokens; return profit; }; async function monitorAndManageTrades() { console.log( `[${format( new Date(), "dd/MM/yyyy, HH:mm:ss" )}] Monitoring filled trades...` ); try { const marketData = await fetchMarketPrices(); const updates = {}; for (const token of marketData) { const tokenRef = db.ref(`OrderBook/${token.symbol}`); const snapshot = await tokenRef.once("value"); const orders = snapshot.val(); if (orders) { Object.entries(orders).forEach(([orderId, order]) => { if (order.status === "filled") { let entryPrice = parseFloat(order.price); let currentPrice = parseFloat(token.priceUsd); let leverage = parseFloat(order.leverage); const trend = determineMarketTrend(currentPrice, entryPrice); const user = order.user; let tokensOwned = (parseFloat(order.paid).toFixed(2) * leverage) / entryPrice; let profitOrLoss = calculateProfit({ entryPrice: order.type === "buy" ? entryPrice : currentPrice, closingPrice: order.type === "buy" ? currentPrice : entryPrice, leverage, tokens: tokensOwned, }); updates[`OrderBook/${token.symbol}/${orderId}/currentPrice`] = currentPrice; updates[`OrderBook/${token.symbol}/${orderId}/trend`] = trend; updates[`OrderBook/${token.symbol}/${orderId}/profitOrLoss`] = profitOrLoss.toFixed(2); const userWalletsRef = db.ref(`UserAccounts/${user}/FundingWallet`); userWalletsRef.once("value", (walletSnapshot) => { const userWallets = walletSnapshot.val(); if (userWallets) { let walletKey = null; Object.entries(userWallets).forEach(([walletId, wallet]) => { if (wallet.Token === "USDT") { walletKey = walletId; } }); if (walletKey) { const usdtWallet = userWallets[walletKey]; let updatedWalletAmount = parseFloat(usdtWallet.Amount) + parseFloat(profitOrLoss); let stopLoss = parseFloat(order.stopLoss); let takeProfit = parseFloat(order.takeProfit); if (stopLoss && currentPrice <= stopLoss) { updates[`OrderBook/${token.symbol}/${orderId}/status`] = "closed"; updates[`OrderBook/${token.symbol}/${orderId}/reason`] = "Stop loss hit"; console.log(`Order ${orderId} closed: Stop loss hit.`); // Deduct from wallet if (profitOrLoss < 0) { updatedWalletAmount += profitOrLoss; if (updatedWalletAmount < 0) updatedWalletAmount = 0; updates[ `UserAccounts/${user}/FundingWallet/${walletKey}/Amount` ] = updatedWalletAmount; } } else if (takeProfit && currentPrice >= takeProfit) { updates[`OrderBook/${token.symbol}/${orderId}/status`] = "closed"; updates[`OrderBook/${token.symbol}/${orderId}/reason`] = "Take profit hit"; console.log(`Order ${orderId} closed: Take profit hit.`); // Add profit to wallet updates[ `UserAccounts/${user}/FundingWallet/${walletKey}/Amount` ] = updatedWalletAmount + profitOrLoss; } else if (profitOrLoss < 0) { updatedWalletAmount += profitOrLoss; if (updatedWalletAmount < 0) updatedWalletAmount = 0; updates[ `UserAccounts/${user}/FundingWallet/${walletKey}/Amount` ] = updatedWalletAmount; updates[`OrderBook/${token.symbol}/${orderId}/status`] = "closed"; updates[`OrderBook/${token.symbol}/${orderId}/reason`] = "Low Balance"; console.log(`Order ${orderId} closed: Low Balance.`); } } } }); } }); } } if (Object.keys(updates).length > 0) { await db.ref().update(updates); console.log( "Trade monitoring and updates applied successfully:", updates ); } else { console.log("No updates required for trades."); } } catch (error) { console.error( `[${format( new Date(), "dd/MM/yyyy, HH:mm:ss" )}] Error monitoring trades:`, error.message ); } } // Combine market data processing and trade monitoring (async function monitorTradesAndPrices() { await processMarketData(); await monitorAndManageTrades(); setInterval(async () => { await processMarketData(); await monitorAndManageTrades(); }, 5000); })(); const PORT = 5000; app.listen(PORT, '0.0.0.0', () => { console.log(`Server is running on port ${PORT}`); });