binbot-charts 0.0.4 → 0.0.5

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.
@@ -5,45 +5,49 @@ require("core-js/modules/web.dom-collections.iterator.js");
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.TVChartContainer = void 0;
8
+ exports.default = void 0;
9
9
 
10
- var React = _interopRequireWildcard(require("react"));
10
+ var _react = _interopRequireWildcard(require("react"));
11
11
 
12
12
  var _charting_library = require("../charting_library");
13
13
 
14
+ var _datafeed = _interopRequireDefault(require("./datafeed"));
15
+
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+
14
18
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
19
 
16
20
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
21
 
18
22
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
19
23
 
20
- class TVChartContainer extends React.PureComponent {
24
+ class TVChartContainer extends _react.Component {
21
25
  constructor(props) {
22
26
  super(props);
23
27
 
24
28
  _defineProperty(this, "tvWidget", null);
25
29
 
26
- this.ref = /*#__PURE__*/React.createRef();
30
+ this.ref = /*#__PURE__*/_react.default.createRef();
27
31
  }
28
32
 
29
33
  componentDidMount() {
30
34
  const widgetOptions = {
31
35
  symbol: "AAPL",
32
36
  // BEWARE: no trailing slash is expected in feed URL
33
- datafeed: new window.Datafeeds.UDFCompatibleDatafeed(this.props.datafeedUrl),
34
- interval: this.props.interval,
37
+ datafeed: _datafeed.default,
38
+ // interval: this.props.interval,
35
39
  container: this.ref.current,
36
40
  library_path: this.props.libraryPath,
37
41
  locale: "en",
38
- disabled_features: ["use_localstorage_for_settings"],
39
- enabled_features: ["study_templates"],
40
- charts_storage_url: this.props.chartsStorageUrl,
41
- charts_storage_api_version: this.props.chartsStorageApiVersion,
42
- client_id: this.props.clientId,
43
- user_id: this.props.userId,
44
- fullscreen: this.props.fullscreen,
45
- autosize: this.props.autosize,
46
- studies_overrides: this.props.studiesOverrides
42
+ // disabled_features: ["use_localstorage_for_settings"],
43
+ // enabled_features: ["study_templates"],
44
+ // charts_storage_url: this.props.chartsStorageUrl,
45
+ // charts_storage_api_version: this.props.chartsStorageApiVersion,
46
+ // client_id: this.props.clientId,
47
+ // user_id: this.props.userId,
48
+ fullscreen: false,
49
+ autosize: false,
50
+ studies_overrides: {}
47
51
  };
48
52
  const tvWidget = new _charting_library.widget(widgetOptions);
49
53
  this.tvWidget = tvWidget;
@@ -61,7 +65,7 @@ class TVChartContainer extends React.PureComponent {
61
65
  }
62
66
 
63
67
  render() {
64
- return /*#__PURE__*/React.createElement("div", {
68
+ return /*#__PURE__*/_react.default.createElement("div", {
65
69
  ref: this.ref,
66
70
  style: {
67
71
  height: "calc(100vh - 80px)"
@@ -71,15 +75,4 @@ class TVChartContainer extends React.PureComponent {
71
75
 
72
76
  }
73
77
 
74
- exports.TVChartContainer = TVChartContainer;
75
-
76
- _defineProperty(TVChartContainer, "defaultProps", {
77
- symbol: "AAPL",
78
- interval: "D",
79
- datafeedUrl: "https://demo_feed.tradingview.com",
80
- libraryPath: "/charting_library/",
81
- chartsStorageApiVersion: "1.1",
82
- fullscreen: false,
83
- autosize: true,
84
- studiesOverrides: {}
85
- });
78
+ exports.default = TVChartContainer;
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ require("core-js/modules/web.dom-collections.iterator.js");
9
+
10
+ require("core-js/modules/es.promise.js");
11
+
12
+ require("core-js/modules/es.symbol.description.js");
13
+
14
+ var _helpers = require("./helpers.js");
15
+
16
+ var _streaming = require("./streaming.js");
17
+
18
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
19
+
20
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
21
+
22
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
23
+
24
+ const lastBarsCache = new Map();
25
+ const exchange = "Binance";
26
+ const configurationData = {
27
+ supported_resolutions: ["1D", "1W", "1M"],
28
+ exchanges: [{
29
+ value: "Binance",
30
+ name: "Binance",
31
+ desc: "Binance"
32
+ }],
33
+ symbols_types: [{
34
+ name: "crypto",
35
+ // `symbolType` argument for the `searchSymbols` method, if a user selects this symbol type
36
+ value: "crypto"
37
+ } // ...
38
+ ]
39
+ };
40
+
41
+ async function getAllSymbols() {
42
+ const data = await (0, _helpers.makeApiRequest)("data/v3/all/exchanges");
43
+ let allSymbols = [];
44
+ const pairs = data.Data[exchange].pairs;
45
+
46
+ for (const leftPairPart of Object.keys(pairs)) {
47
+ const symbols = pairs[leftPairPart].map(rightPairPart => {
48
+ const symbol = (0, _helpers.generateSymbol)(exchange, leftPairPart, rightPairPart);
49
+ return {
50
+ symbol: symbol.short,
51
+ full_name: symbol.full,
52
+ description: symbol.short,
53
+ exchange: exchange,
54
+ type: "crypto"
55
+ };
56
+ });
57
+ allSymbols = [...allSymbols, ...symbols];
58
+ }
59
+
60
+ return allSymbols;
61
+ }
62
+
63
+ class Datafeed {}
64
+
65
+ exports.default = Datafeed;
66
+
67
+ _defineProperty(Datafeed, "onReady", callback => {
68
+ console.log("[onReady]: Method call");
69
+ setTimeout(() => callback(configurationData));
70
+ });
71
+
72
+ _defineProperty(Datafeed, "searchSymbols", async (userInput, exchange, symbolType, onResultReadyCallback) => {
73
+ console.log("[searchSymbols]: Method call");
74
+ const symbols = await getAllSymbols();
75
+ const newSymbols = symbols.filter(symbol => {
76
+ const isExchangeValid = exchange === "" || symbol.exchange === exchange;
77
+ const isFullSymbolContainsInput = symbol.full_name.toLowerCase().indexOf(userInput.toLowerCase()) !== -1;
78
+ return isExchangeValid && isFullSymbolContainsInput;
79
+ });
80
+ onResultReadyCallback(newSymbols);
81
+ });
82
+
83
+ _defineProperty(Datafeed, "resolveSymbol", async (symbolName, onSymbolResolvedCallback, onResolveErrorCallback) => {
84
+ console.log("[resolveSymbol]: Method call", symbolName);
85
+ const symbols = await getAllSymbols();
86
+ const symbolItem = symbols.find(_ref => {
87
+ let {
88
+ full_name
89
+ } = _ref;
90
+ return full_name === symbolName;
91
+ });
92
+
93
+ if (!symbolItem) {
94
+ console.log("[resolveSymbol]: Cannot resolve symbol", symbolName);
95
+ onResolveErrorCallback("cannot resolve symbol");
96
+ return;
97
+ }
98
+
99
+ const symbolInfo = {
100
+ ticker: symbolItem.full_name,
101
+ name: symbolItem.symbol,
102
+ description: symbolItem.description,
103
+ type: symbolItem.type,
104
+ session: "24x7",
105
+ timezone: "Etc/UTC",
106
+ exchange: symbolItem.exchange,
107
+ minmov: 1,
108
+ pricescale: 100,
109
+ has_intraday: false,
110
+ has_no_volume: true,
111
+ has_weekly_and_monthly: false,
112
+ supported_resolutions: ["1D", "1W", "1M"],
113
+ volume_precision: 2,
114
+ data_status: "streaming"
115
+ };
116
+ console.log("[resolveSymbol]: Symbol resolved", symbolName);
117
+ onSymbolResolvedCallback(symbolInfo);
118
+ });
119
+
120
+ _defineProperty(Datafeed, "getBars", async (symbolInfo, resolution, periodParams, onHistoryCallback, onErrorCallback) => {
121
+ const {
122
+ from,
123
+ to,
124
+ firstDataRequest
125
+ } = periodParams;
126
+ console.log("[getBars]: Method call", symbolInfo, resolution, from, to);
127
+ const parsedSymbol = (0, _helpers.parseFullSymbol)(symbolInfo.full_name);
128
+ const urlParameters = {
129
+ e: parsedSymbol.exchange,
130
+ fsym: parsedSymbol.fromSymbol,
131
+ tsym: parsedSymbol.toSymbol,
132
+ toTs: to,
133
+ limit: 2000
134
+ };
135
+ const query = Object.keys(urlParameters).map(name => "".concat(name, "=").concat(encodeURIComponent(urlParameters[name]))).join("&");
136
+
137
+ try {
138
+ const data = await (0, _helpers.makeApiRequest)("data/histoday?".concat(query));
139
+
140
+ if (data.Response && data.Response === "Error" || data.Data.length === 0) {
141
+ // "noData" should be set if there is no data in the requested period.
142
+ onHistoryCallback([], {
143
+ noData: true
144
+ });
145
+ return;
146
+ }
147
+
148
+ let bars = [];
149
+ data.Data.forEach(bar => {
150
+ if (bar.time >= from && bar.time < to) {
151
+ bars = [...bars, {
152
+ time: bar.time * 1000,
153
+ low: bar.low,
154
+ high: bar.high,
155
+ open: bar.open,
156
+ close: bar.close
157
+ }];
158
+ }
159
+ });
160
+
161
+ if (firstDataRequest) {
162
+ lastBarsCache.set(symbolInfo.full_name, _objectSpread({}, bars[bars.length - 1]));
163
+ }
164
+
165
+ console.log("[getBars]: returned ".concat(bars.length, " bar(s)"));
166
+ onHistoryCallback(bars, {
167
+ noData: false
168
+ });
169
+ } catch (error) {
170
+ console.log("[getBars]: Get error", error);
171
+ onErrorCallback(error);
172
+ }
173
+ });
174
+
175
+ _defineProperty(Datafeed, "subscribeBars", (symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback) => {
176
+ console.log("[subscribeBars]: Method call with subscribeUID:", subscribeUID);
177
+ (0, _streaming.subscribeOnStream)(symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback, lastBarsCache.get(symbolInfo.full_name));
178
+ });
179
+
180
+ _defineProperty(Datafeed, "unsubscribeBars", subscriberUID => {
181
+ console.log("[unsubscribeBars]: Method call with subscriberUID:", subscriberUID);
182
+ (0, _streaming.unsubscribeFromStream)(subscriberUID);
183
+ });
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.generateSymbol = generateSymbol;
7
+ exports.makeApiRequest = makeApiRequest;
8
+ exports.parseFullSymbol = parseFullSymbol;
9
+
10
+ require("core-js/modules/es.promise.js");
11
+
12
+ require("core-js/modules/es.regexp.exec.js");
13
+
14
+ require("core-js/modules/es.string.match.js");
15
+
16
+ // Make requests to CryptoCompare API
17
+ async function makeApiRequest(path) {
18
+ try {
19
+ const response = await fetch("https://min-api.cryptocompare.com/".concat(path));
20
+ return response.json();
21
+ } catch (error) {
22
+ throw new Error("CryptoCompare request error: ".concat(error.status));
23
+ }
24
+ } // Generate a symbol ID from a pair of the coins
25
+
26
+
27
+ function generateSymbol(exchange, fromSymbol, toSymbol) {
28
+ const short = "".concat(fromSymbol, "/").concat(toSymbol);
29
+ return {
30
+ short,
31
+ full: "".concat(exchange, ":").concat(short)
32
+ };
33
+ }
34
+
35
+ function parseFullSymbol(fullSymbol) {
36
+ const match = fullSymbol.match(/^(\w+):(\w+)\/(\w+)$/);
37
+
38
+ if (!match) {
39
+ return null;
40
+ }
41
+
42
+ return {
43
+ exchange: match[1],
44
+ fromSymbol: match[2],
45
+ toSymbol: match[3]
46
+ };
47
+ }
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.subscribeOnStream = subscribeOnStream;
7
+ exports.unsubscribeFromStream = unsubscribeFromStream;
8
+
9
+ require("core-js/modules/web.dom-collections.iterator.js");
10
+
11
+ require("core-js/modules/es.regexp.exec.js");
12
+
13
+ require("core-js/modules/es.string.split.js");
14
+
15
+ require("core-js/modules/es.parse-int.js");
16
+
17
+ require("core-js/modules/es.parse-float.js");
18
+
19
+ var _helpers = require("./helpers.js");
20
+
21
+ var _socket = _interopRequireDefault(require("socket.io-client"));
22
+
23
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
+
25
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
26
+
27
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
28
+
29
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
30
+
31
+ const socket = (0, _socket.default)("wss://streamer.cryptocompare.com");
32
+ const channelToSubscription = new Map();
33
+ socket.on("connect", () => {
34
+ console.log("[socket] Connected");
35
+ });
36
+ socket.on("disconnect", reason => {
37
+ console.log("[socket] Disconnected:", reason);
38
+ });
39
+ socket.on("error", error => {
40
+ console.log("[socket] Error:", error);
41
+ });
42
+ socket.on("m", data => {
43
+ console.log("[socket] Message:", data);
44
+ const [eventTypeStr, exchange, fromSymbol, toSymbol,,, tradeTimeStr,, tradePriceStr] = data.split("~");
45
+
46
+ if (parseInt(eventTypeStr) !== 0) {
47
+ // skip all non-TRADE events
48
+ return;
49
+ }
50
+
51
+ const tradePrice = parseFloat(tradePriceStr);
52
+ const tradeTime = parseInt(tradeTimeStr);
53
+ const channelString = "0~".concat(exchange, "~").concat(fromSymbol, "~").concat(toSymbol);
54
+ const subscriptionItem = channelToSubscription.get(channelString);
55
+
56
+ if (subscriptionItem === undefined) {
57
+ return;
58
+ }
59
+
60
+ const lastDailyBar = subscriptionItem.lastDailyBar;
61
+ const nextDailyBarTime = getNextDailyBarTime(lastDailyBar.time);
62
+ let bar;
63
+
64
+ if (tradeTime >= nextDailyBarTime) {
65
+ bar = {
66
+ time: nextDailyBarTime,
67
+ open: tradePrice,
68
+ high: tradePrice,
69
+ low: tradePrice,
70
+ close: tradePrice
71
+ };
72
+ console.log("[socket] Generate new bar", bar);
73
+ } else {
74
+ bar = _objectSpread(_objectSpread({}, lastDailyBar), {}, {
75
+ high: Math.max(lastDailyBar.high, tradePrice),
76
+ low: Math.min(lastDailyBar.low, tradePrice),
77
+ close: tradePrice
78
+ });
79
+ console.log("[socket] Update the latest bar by price", tradePrice);
80
+ }
81
+
82
+ subscriptionItem.lastDailyBar = bar; // send data to every subscriber of that symbol
83
+
84
+ subscriptionItem.handlers.forEach(handler => handler.callback(bar));
85
+ });
86
+
87
+ function getNextDailyBarTime(barTime) {
88
+ const date = new Date(barTime * 1000);
89
+ date.setDate(date.getDate() + 1);
90
+ return date.getTime() / 1000;
91
+ }
92
+
93
+ function subscribeOnStream(symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback, lastDailyBar) {
94
+ const parsedSymbol = (0, _helpers.parseFullSymbol)(symbolInfo.full_name);
95
+ const channelString = "0~".concat(parsedSymbol.exchange, "~").concat(parsedSymbol.fromSymbol, "~").concat(parsedSymbol.toSymbol);
96
+ const handler = {
97
+ id: subscribeUID,
98
+ callback: onRealtimeCallback
99
+ };
100
+ let subscriptionItem = channelToSubscription.get(channelString);
101
+
102
+ if (subscriptionItem) {
103
+ // already subscribed to the channel, use the existing subscription
104
+ subscriptionItem.handlers.push(handler);
105
+ return;
106
+ }
107
+
108
+ subscriptionItem = {
109
+ subscribeUID,
110
+ resolution,
111
+ lastDailyBar,
112
+ handlers: [handler]
113
+ };
114
+ channelToSubscription.set(channelString, subscriptionItem);
115
+ console.log("[subscribeBars]: Subscribe to streaming. Channel:", channelString);
116
+ socket.emit("SubAdd", {
117
+ subs: [channelString]
118
+ });
119
+ }
120
+
121
+ function unsubscribeFromStream(subscriberUID) {
122
+ // find a subscription with id === subscriberUID
123
+ for (const channelString of channelToSubscription.keys()) {
124
+ const subscriptionItem = channelToSubscription.get(channelString);
125
+ const handlerIndex = subscriptionItem.handlers.findIndex(handler => handler.id === subscriberUID);
126
+
127
+ if (handlerIndex !== -1) {
128
+ // remove from handlers
129
+ subscriptionItem.handlers.splice(handlerIndex, 1);
130
+
131
+ if (subscriptionItem.handlers.length === 0) {
132
+ // unsubscribe from the channel, if it was the last handler
133
+ console.log("[unsubscribeBars]: Unsubscribe from streaming. Channel:", channelString);
134
+ socket.emit("SubRemove", {
135
+ subs: [channelString]
136
+ });
137
+ channelToSubscription.delete(channelString);
138
+ break;
139
+ }
140
+ }
141
+ }
142
+ }
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.4",
2
+ "version": "0.0.5",
3
3
  "name": "binbot-charts",
4
4
  "dependencies": {
5
5
  "@babel/cli": "^7.18.10",
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "scripts": {
14
14
  "start": "react-scripts start",
15
- "build": "rm -rf dist && NODE_ENV=production babel src/components src/charting_library --out-dir dist --copy-files",
15
+ "build": "rm -rf dist && cp src/charting_library dist/charting_library NODE_ENV=production babel src/components --out-dir dist --copy-files",
16
16
  "publish": "yarn build && npm publish"
17
17
  },
18
18
  "description": "Binbot charts is the default candlestick bars chart used in terminal.binbot.com to render bots graphically.",