binbot-charts 0.5.6 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/dist/components/datafeed.js +0 -153
- package/dist/components/helpers.js +0 -45
- package/dist/components/streaming.js +0 -106
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.5.
|
|
2
|
+
"version": "0.5.7",
|
|
3
3
|
"name": "binbot-charts",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"react": "^18.3.1",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"start": "react-scripts start",
|
|
23
|
-
"build": "rm -rf dist && NODE_ENV=production
|
|
23
|
+
"build": "rm -rf dist && NODE_ENV=production tsc && cp -r src/charting_library dist/charting_library && tsc",
|
|
24
24
|
"release": "yarn build && yarn publish"
|
|
25
25
|
},
|
|
26
26
|
"description": "Binbot charts is the default candlestick bars chart used in terminal.binbot.in to render bots graphically.",
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
var _helpers = require("./helpers.js");
|
|
8
|
-
var _streaming = require("./streaming.js");
|
|
9
|
-
const binanceResolutions = ["1s", "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M"];
|
|
10
|
-
const getConfigurationData = async () => {
|
|
11
|
-
return {
|
|
12
|
-
supports_marks: true,
|
|
13
|
-
supports_time: true,
|
|
14
|
-
supports_timescale_marks: true,
|
|
15
|
-
supports_time: true,
|
|
16
|
-
supported_resolutions: ["1S", "1", "3", "5", "15", "30", "60", "120", "240", "360", "480", "720", "1D", "3D", "1W", "12M"],
|
|
17
|
-
exchanges: [{
|
|
18
|
-
value: "Binance",
|
|
19
|
-
name: "Binance",
|
|
20
|
-
desc: "Binance"
|
|
21
|
-
}],
|
|
22
|
-
symbols_types: [{
|
|
23
|
-
name: "crypto",
|
|
24
|
-
value: "crypto"
|
|
25
|
-
}]
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param timescale { Array }. timescaleMark objects
|
|
31
|
-
* @param interval { string }. Klines timescale from the list of Binance Enums
|
|
32
|
-
*/
|
|
33
|
-
class Datafeed {
|
|
34
|
-
constructor() {
|
|
35
|
-
let timescaleMarks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
36
|
-
let interval = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "1h";
|
|
37
|
-
this.streaming = null;
|
|
38
|
-
this.timescaleMarks = timescaleMarks;
|
|
39
|
-
this.interval = interval;
|
|
40
|
-
}
|
|
41
|
-
onReady = async callback => {
|
|
42
|
-
this.configurationData = await getConfigurationData();
|
|
43
|
-
callback(this.configurationData);
|
|
44
|
-
};
|
|
45
|
-
searchSymbols = async (userInput, exchange, symbolType, onResultReadyCallback) => {
|
|
46
|
-
const symbols = await (0, _helpers.getAllSymbols)(userInput);
|
|
47
|
-
onResultReadyCallback(symbols);
|
|
48
|
-
};
|
|
49
|
-
resolveSymbol = async (symbolName, onSymbolResolvedCallback, onResolveErrorCallback) => {
|
|
50
|
-
if (!symbolName) {
|
|
51
|
-
await onResolveErrorCallback("cannot resolve symbol");
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
const symbolInfo = () => {
|
|
55
|
-
return {
|
|
56
|
-
ticker: symbolName,
|
|
57
|
-
name: symbolName,
|
|
58
|
-
ticker: symbolName,
|
|
59
|
-
description: symbolName,
|
|
60
|
-
type: "crypto",
|
|
61
|
-
session: "24x7",
|
|
62
|
-
timezone: "Etc/UTC",
|
|
63
|
-
exchange: "Binance",
|
|
64
|
-
minmov: 100,
|
|
65
|
-
pricescale: 100000,
|
|
66
|
-
has_daily: true,
|
|
67
|
-
has_intraday: true,
|
|
68
|
-
has_no_volume: false,
|
|
69
|
-
has_seconds: true,
|
|
70
|
-
seconds_multipliers: [1],
|
|
71
|
-
volume: "hundreds",
|
|
72
|
-
volume_precision: 9,
|
|
73
|
-
data_status: "streaming",
|
|
74
|
-
resolution: "1h"
|
|
75
|
-
};
|
|
76
|
-
};
|
|
77
|
-
const symbol = await symbolInfo();
|
|
78
|
-
onSymbolResolvedCallback(symbol);
|
|
79
|
-
};
|
|
80
|
-
getBars = async (symbolInfo, resolution, periodParams, onHistoryCallback, onErrorCallback) => {
|
|
81
|
-
const {
|
|
82
|
-
from,
|
|
83
|
-
to,
|
|
84
|
-
firstDataRequest
|
|
85
|
-
} = periodParams;
|
|
86
|
-
let interval = "60"; // 1 hour
|
|
87
|
-
// Calculate interval using resolution data
|
|
88
|
-
if (!/[a-zA-Z]$/.test(resolution)) {
|
|
89
|
-
if (parseInt(resolution) >= 60) {
|
|
90
|
-
interval = parseInt(resolution) / 60 + "h";
|
|
91
|
-
} else {
|
|
92
|
-
interval = resolution + "m";
|
|
93
|
-
}
|
|
94
|
-
} else {
|
|
95
|
-
interval = resolution.toLowerCase().replace(/[a-z]\b/g, c => c.toLowerCase());
|
|
96
|
-
}
|
|
97
|
-
let urlParameters = {
|
|
98
|
-
symbol: symbolInfo.name,
|
|
99
|
-
interval: interval,
|
|
100
|
-
startTime: Math.abs(from * 1000),
|
|
101
|
-
endTime: Math.abs(to * 1000),
|
|
102
|
-
limit: 600
|
|
103
|
-
};
|
|
104
|
-
const query = Object.keys(urlParameters).map(name => `${name}=${encodeURIComponent(urlParameters[name])}`).join("&");
|
|
105
|
-
try {
|
|
106
|
-
const data = await (0, _helpers.makeApiRequest)(`api/v3/uiKlines?${query}`);
|
|
107
|
-
if (data.Response && data.Response === "Error" || data.length === 0) {
|
|
108
|
-
// "noData" should be set if there is no data in the requested period.
|
|
109
|
-
onHistoryCallback([], {
|
|
110
|
-
noData: true
|
|
111
|
-
});
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
let bars = [];
|
|
115
|
-
data.forEach(bar => {
|
|
116
|
-
if (bar[0] >= from * 1000 && bar[0] < to * 1000) {
|
|
117
|
-
bars = [...bars, {
|
|
118
|
-
time: bar[0],
|
|
119
|
-
low: bar[3],
|
|
120
|
-
high: bar[2],
|
|
121
|
-
open: bar[1],
|
|
122
|
-
close: bar[4],
|
|
123
|
-
volume: bar[5]
|
|
124
|
-
}];
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
onHistoryCallback(bars, {
|
|
128
|
-
noData: false
|
|
129
|
-
});
|
|
130
|
-
} catch (error) {
|
|
131
|
-
console.log("[getBars]: Get error", error);
|
|
132
|
-
onErrorCallback(error);
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
getTimescaleMarks(symbolInfo, from, to, onDataCallback, resolution) {
|
|
136
|
-
if (this.timescaleMarks.length > 0) {
|
|
137
|
-
let timescaleMarks = Object.assign([], this.timescaleMarks);
|
|
138
|
-
onDataCallback(timescaleMarks);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
async getServerTime(onServertimeCallback) {
|
|
142
|
-
const data = await (0, _helpers.makeApiRequest)(`api/v3/time`);
|
|
143
|
-
const serverTime = data.serverTime / 1000;
|
|
144
|
-
onServertimeCallback(serverTime);
|
|
145
|
-
}
|
|
146
|
-
subscribeBars = (symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback) => {
|
|
147
|
-
(0, _streaming.subscribeOnStream)(symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback, this.interval);
|
|
148
|
-
};
|
|
149
|
-
unsubscribeBars = subscriberUID => {
|
|
150
|
-
(0, _streaming.unsubscribeFromStream)(subscriberUID);
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
exports.default = Datafeed;
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.getAllSymbols = getAllSymbols;
|
|
7
|
-
exports.makeApiRequest = makeApiRequest;
|
|
8
|
-
exports.usePrevious = usePrevious;
|
|
9
|
-
var _react = require("react");
|
|
10
|
-
async function makeApiRequest(path) {
|
|
11
|
-
try {
|
|
12
|
-
const response = await fetch(`https://api.binance.com/${path}`);
|
|
13
|
-
return response.json();
|
|
14
|
-
} catch (error) {
|
|
15
|
-
throw new Error(`Binance request error: ${error.status}`);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
async function getAllSymbols(symbol) {
|
|
19
|
-
let newSymbols = [];
|
|
20
|
-
try {
|
|
21
|
-
const data = await makeApiRequest(`api/v3/exchangeInfo?symbol=${symbol.toUpperCase()}`);
|
|
22
|
-
data.symbols.forEach(item => {
|
|
23
|
-
if (item.status === "TRADING") {
|
|
24
|
-
newSymbols.push({
|
|
25
|
-
symbol: item.symbol,
|
|
26
|
-
full_name: `${item.baseAsset}/${item.quoteAsset}`,
|
|
27
|
-
description: `Precision: ${item.quoteAssetPrecision}`,
|
|
28
|
-
exchange: "Binance",
|
|
29
|
-
ticker: item.symbol,
|
|
30
|
-
type: "crypto"
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
} catch (e) {
|
|
35
|
-
return newSymbols;
|
|
36
|
-
}
|
|
37
|
-
return newSymbols;
|
|
38
|
-
}
|
|
39
|
-
function usePrevious(value) {
|
|
40
|
-
const ref = (0, _react.useRef)();
|
|
41
|
-
(0, _react.useEffect)(() => {
|
|
42
|
-
ref.current = value;
|
|
43
|
-
});
|
|
44
|
-
return ref.current;
|
|
45
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.subscribeOnStream = subscribeOnStream;
|
|
7
|
-
exports.unsubscribeFromStream = unsubscribeFromStream;
|
|
8
|
-
const channelToSubscription = new Map();
|
|
9
|
-
function setupSockets(subRequest) {
|
|
10
|
-
const socket = new WebSocket("wss://stream.binance.com:9443/ws");
|
|
11
|
-
window.socket = socket;
|
|
12
|
-
socket.onopen = event => {
|
|
13
|
-
console.log("[socket] Connected");
|
|
14
|
-
socket.send(JSON.stringify(subRequest));
|
|
15
|
-
};
|
|
16
|
-
socket.onclose = reason => {
|
|
17
|
-
console.log("[socket] Disconnected:", reason);
|
|
18
|
-
};
|
|
19
|
-
socket.onerror = error => {
|
|
20
|
-
console.log("[socket] Error:", error);
|
|
21
|
-
};
|
|
22
|
-
socket.onmessage = e => {
|
|
23
|
-
const data = JSON.parse(e.data);
|
|
24
|
-
if (data.e == undefined) {
|
|
25
|
-
// skip all non-TRADE events
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
const {
|
|
29
|
-
s: symbol,
|
|
30
|
-
t: startTime,
|
|
31
|
-
T: closeTime,
|
|
32
|
-
i: interval,
|
|
33
|
-
o: open,
|
|
34
|
-
c: close,
|
|
35
|
-
h: high,
|
|
36
|
-
l: low,
|
|
37
|
-
v: volume,
|
|
38
|
-
n: trades,
|
|
39
|
-
q: quoteVolume
|
|
40
|
-
} = data.k;
|
|
41
|
-
const channelString = `${symbol.toLowerCase()}@kline_${interval}`;
|
|
42
|
-
const subscriptionItem = channelToSubscription.get(channelString);
|
|
43
|
-
if (subscriptionItem === undefined) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const bar = {
|
|
47
|
-
time: startTime,
|
|
48
|
-
open: open,
|
|
49
|
-
high: high,
|
|
50
|
-
low: low,
|
|
51
|
-
close: close,
|
|
52
|
-
volume: volume
|
|
53
|
-
};
|
|
54
|
-
// send data to every subscriber of that symbol
|
|
55
|
-
subscriptionItem.handlers.forEach(handler => handler.callback(bar));
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
function subscribeOnStream(symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback, interval) {
|
|
59
|
-
const channelString = `${symbolInfo.name.toLowerCase()}@kline_${interval}`;
|
|
60
|
-
const handler = {
|
|
61
|
-
id: subscribeUID,
|
|
62
|
-
callback: onRealtimeCallback
|
|
63
|
-
};
|
|
64
|
-
let subscriptionItem = channelToSubscription.get(channelString);
|
|
65
|
-
if (subscriptionItem) {
|
|
66
|
-
// already subscribed to the channel, use the existing subscription
|
|
67
|
-
subscriptionItem.handlers.push(handler);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
subscriptionItem = {
|
|
71
|
-
subscribeUID,
|
|
72
|
-
resolution,
|
|
73
|
-
handlers: [handler]
|
|
74
|
-
};
|
|
75
|
-
const subRequest = {
|
|
76
|
-
method: "SUBSCRIBE",
|
|
77
|
-
params: [channelString],
|
|
78
|
-
id: 1
|
|
79
|
-
};
|
|
80
|
-
channelToSubscription.set(channelString, subscriptionItem);
|
|
81
|
-
setupSockets(subRequest);
|
|
82
|
-
}
|
|
83
|
-
function unsubscribeFromStream(subscriberUID) {
|
|
84
|
-
// find a subscription with id === subscriberUID
|
|
85
|
-
for (const channelString of channelToSubscription.keys()) {
|
|
86
|
-
const subscriptionItem = channelToSubscription.get(channelString);
|
|
87
|
-
const handlerIndex = subscriptionItem.handlers.findIndex(handler => handler.id === subscriberUID);
|
|
88
|
-
if (handlerIndex !== -1) {
|
|
89
|
-
// remove from handlers
|
|
90
|
-
subscriptionItem.handlers.splice(handlerIndex, 1);
|
|
91
|
-
if (subscriptionItem.handlers.length === 0) {
|
|
92
|
-
// unsubscribe from the channel, if it was the last handler
|
|
93
|
-
console.log("[unsubscribeBars]: Unsubscribe from streaming. Channel:", channelString);
|
|
94
|
-
const subRequest = {
|
|
95
|
-
method: "UNSUBSCRIBE",
|
|
96
|
-
params: [channelString],
|
|
97
|
-
id: 1
|
|
98
|
-
};
|
|
99
|
-
window.socket.send(JSON.stringify(subRequest));
|
|
100
|
-
channelToSubscription.delete(channelString);
|
|
101
|
-
window.socket = undefined;
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|