-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
144 lines (126 loc) · 4.78 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
const express = require("express");
const puppeteer = require("puppeteer");
const path = require("path");
const { getBinancePositions, closeBinancePosition } = require("./positions");
const { UMFutures } = require("@binance/futures-connector");
const app = express();
const PORT = 3000;
const apiKey = process.env.BINANCE_API_KEY;
const apiSecret = process.env.BINANCE_API_SECRET;
const umFuturesClient = new UMFutures(apiKey, apiSecret, { baseURL: "https://fapi.binance.com" });
let cachedNews = [];
// Fetch latest news using Puppeteer
async function fetchLatestNews() {
try {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://news.treeofalpha.com", { waitUntil: "networkidle2" });
const news = await page.evaluate(() => {
return Array.from(document.querySelectorAll(".box.padding-smallest.rowToColumn")).map(element => {
const titleElement = element.querySelector(".contentTitle a");
const dateElement = element.querySelector(".originTime");
if (titleElement && dateElement) {
return {
title: titleElement.innerText.trim(),
date: dateElement.innerText.trim(),
link: titleElement.href,
};
}
return null;
}).filter(item => item !== null);
});
await browser.close();
cachedNews = news;
console.log("Updated cached news: ", cachedNews);
} catch (error) {
console.error("Error during scraping: ", error);
}
}
// Initial news fetch and periodic update
fetchLatestNews();
setInterval(fetchLatestNews, 300000); // 5 minutes
// Middleware
app.use(express.static(path.join(__dirname, "public")));
app.use(express.json()); // Built-in middleware to parse JSON bodies
// API Endpoints
app.get("/api/news", (req, res) => {
console.log("Serving cached news");
res.json(cachedNews);
});
app.get("/api/positions", async (req, res) => {
try {
const positions = await getBinancePositions();
res.json(positions);
} catch (error) {
console.error("Error fetching positions:", error);
res.status(500).json({ error: error.message });
}
});
app.post("/api/close-position", async (req, res) => {
const { symbol, side, quantity } = req.body;
if (!symbol || !side || !quantity) {
return res.status(400).json({ error: "Missing 'symbol', 'side' or 'quantity' parameter" });
}
try {
const response = await closeBinancePosition(symbol, side, quantity);
res.json(response);
} catch (error) {
console.error(`Error closing position for ${symbol}:`, error.response ? error.response.data : error.message);
res.status(500).json({ error: error.message });
}
});
app.post("/api/buy", async (req, res) => {
const { symbol, quantity } = req.body;
try {
const response = await umFuturesClient.newOrder(symbol, "BUY", "MARKET", { quantity });
if (response.status === 200) {
res.json({ success: true, message: `Successfully bought ${quantity} of ${symbol.toUpperCase()}` });
} else {
res.json({ success: false, message: response.data.msg });
}
} catch (error) {
console.error("Error buying coin:", error);
res.status(500).json({ success: false, message: "Internal server error: Positions size might be too big" });
}
});
app.post("/api/sell", async (req, res) => {
const { symbol, quantity } = req.body;
try {
const response = await umFuturesClient.newOrder(symbol, "SELL", "MARKET", { quantity });
if (response.status === 200) {
res.json({ success: true, message: `Successfully sold ${quantity} of ${symbol.toUpperCase()}` });
} else {
res.json({ success: false, message: response.data.msg });
}
} catch (error) {
console.error("Error selling coin:", error);
res.status(500).json({ success: false, message: "Internal server error: Positions size might be too big" });
}
});
app.post("/api/close-position", async (req, res) => {
const { symbol } = req.query;
try {
const positions = await umFuturesClient.getPositionRisk();
const position = positions.find(pos => pos.symbol === symbol && pos.positionAmt !== 0);
if (!position) {
return res.status(400).json({ message: "Position not found" });
}
const side = position.positionAmt > 0 ? "SELL" : "BUY";
const quantity = Math.abs(position.positionAmt);
const response = await umFuturesClient.newOrder(symbol, side, "MARKET", { quantity });
res.json(response);
} catch (error) {
res.status(error.response ? error.response.status : 500).json({
message: error.message,
data: error.response ? error.response.data : null,
});
}
});
// Serve main HTML file
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "public", "index.html"));
});
// Start server
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});