brighter-trading/static/communication.js

211 lines
7.7 KiB
JavaScript

class Comms {
constructor() {
// Callback collections that will receive various updates.
this.candleUpdateCallbacks = [];
this.candleCloseCallbacks = [];
this.indicatorUpdateCallbacks = [];
// Flags
this.connectionOpen = false;
}
/**
* Register a callback function to receive updates for a specific target.
* @param {string} target - The target for the callback ('candle_update', 'candle_close', or 'indicator_update').
* @param {function} callbackFunc - The callback function to register.
*/
registerCallback(target, callbackFunc) {
const callbackMap = {
'candle_update': this.candleUpdateCallbacks,
'candle_close': this.candleCloseCallbacks,
'indicator_update': this.indicatorUpdateCallbacks
};
const callbackList = callbackMap[target];
if (callbackList) {
callbackList.push(callbackFunc);
} else {
console.log('Comms: Invalid target for callback');
}
}
/* Callback declarations */
candleUpdate(newCandle) {
for (const callback of this.candleUpdateCallbacks) {
callback(newCandle);
}
}
candleClose(newCandle) {
this.sendToApp('candle_data', newCandle);
for (const callback of this.candleCloseCallbacks) {
callback(newCandle);
}
}
indicatorUpdate(data) {
for (const callback of this.indicatorUpdateCallbacks) {
callback(data);
}
}
/**
* Fetches the price history data for a user.
* @param {string} userName - The name of the user.
* @returns {Promise<Object|null>} - A promise that resolves
* to the fetched price history data, or null if an error occurs.
*/
async getPriceHistory(userName) {
try {
const response = await fetch('http://localhost:5000/api/history', {
credentials: 'include',
mode: 'cors',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ "user_name": userName })
});
const data = await response.json();
console.log('Communication[56]: Received candles from the server:');
console.log(data);
return data;
} catch (error) {
console.error('Error fetching price history:', error);
return null;
}
}
/**
* Fetches the Indicator data for a specific user.
* @param {string} userName - The name of the user.
* @returns {Promise<Object|null>} - A promise that resolves
* to the fetched Indicator data, or null if an error occurs.
*/
async getIndicatorData(userName) {
try {
const response = await fetch('http://localhost:5000/api/indicator_init', {
credentials: 'same-origin',
mode: 'cors',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ "user_name": userName })
});
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching indicator data:', error);
return null;
}
}
/**
* Sends a message to the application server.
* @param {string} messageType - The type of the message.
* @param {Object} data - The data to be sent with the message.
*/
sendToApp(messageType, data) {
console.log('window.UI.data.comms.sendToApp(): Sending->');
console.log(JSON.stringify({ message_type: messageType, data: data }));
if (this.connectionOpen) {
this.appCon.send(JSON.stringify({ message_type: messageType, data: data }));
} else {
setTimeout(() => {
window.UI.data.comms.appCon.send(JSON.stringify({ message_type: messageType, data: data }));
}, 1000);
}
}
/**
* Sets up the WebSocket connection to the application server.
*/
setAppCon() {
this.appCon = new WebSocket('ws://localhost:5000/ws');
this.appCon.onopen = () => {
this.appCon.send("Connection OK");
this.connectionOpen = true;
};
this.appCon.addEventListener('message', (event) => {
if (event.data) {
const message = JSON.parse(event.data);
if (message && message.request !== undefined) {
console.log('Received a request from the server');
console.log(message.request);
}
if (message && message.reply !== undefined) {
if (message.reply === 'updates') {
const { i_updates, s_updates, stg_updts, trade_updts } = message.data;
if (i_updates) {
this.indicatorUpdate(i_updates);
window.UI.signals.i_update(i_updates);
}
if (s_updates) {
const updates = s_updates;
window.UI.signals.update_signal_states(updates);
window.UI.alerts.publish_alerts('signal_changes', updates);
}
if (stg_updts) {
const stg_updts = stg_updts;
window.UI.strats.update_received(stg_updts);
}
if (trade_updts) {
const trade_updts = trade_updts;
window.UI.trade.update_received(trade_updts);
}
} else if (message.reply === 'signals') {
window.UI.signals.set_data(message.data);
} else if (message.reply === 'strategies') {
window.UI.strats.set_data(message.data);
} else if (message.reply === 'trades') {
window.UI.trade.set_data(message.data);
} else if (message.reply === 'signal_created') {
const list_of_one = [message.data];
window.UI.signals.set_data(list_of_one);
} else if (message.reply === 'trade_created') {
const list_of_one = [message.data];
window.UI.trade.set_data(list_of_one);
} else {
console.log(message.reply);
console.log(message.data);
}
}
}
});
}
/**
* Sets up a WebSocket connection to the exchange for receiving candlestick data.
* @param {string} interval - The interval of the candlestick data.
* @param {string} tradingPair - The trading pair to subscribe to.
*/
setExchangeCon(interval, tradingPair) {
tradingPair = tradingPair.toLowerCase();
const ws = `wss://stream.binance.com:9443/ws/${tradingPair}@kline_${interval}`;
this.exchangeCon = new WebSocket(ws);
this.exchangeCon.onmessage = (event) => {
let message = JSON.parse(event.data);
let candlestick = message.k;
let newCandle = {
time: candlestick.t / 1000,
open: candlestick.o,
high: candlestick.h,
low: candlestick.l,
close: candlestick.c,
vol: candlestick.v
};
this.candleUpdate(newCandle);
if (candlestick.x === true) {
this.candleClose(newCandle);
}
};
}
}