UNPKG

upstox-js-sdk

Version:

The official Node Js client for communicating with the Upstox API

151 lines (146 loc) 5.18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MarketDataFeeder = void 0; var _ws = _interopRequireDefault(require("ws")); var _protobufjs = _interopRequireDefault(require("protobufjs")); var _path = _interopRequireDefault(require("path")); var _uuid = _interopRequireDefault(require("uuid4")); var _ApiClient = require("../ApiClient"); var _Feeder = _interopRequireDefault(require("./Feeder")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } class MarketDataFeeder extends _Feeder.default { constructor(instrumentKeys = [], mode = this.Mode.FULL) { super(); //Required enums _defineProperty(this, "Mode", Object.freeze({ LTPC: "ltpc", FULL: "full" })); _defineProperty(this, "Method", Object.freeze({ SUBSCRIBE: "sub", CHANGE_METHOD: "change_mode", UNSUBSCRIBE: "unsub" })); _defineProperty(this, "ws", null); _defineProperty(this, "instrumentKeys", []); _defineProperty(this, "mode", ""); _defineProperty(this, "userClosedWebSocket", false); _defineProperty(this, "closingCode", -1); _defineProperty(this, "protobufRoot", null); this.apiClient = _ApiClient.ApiClient.instance; this.instrumentKeys = instrumentKeys; this.mode = mode; this.initProtobuf(); } async connect() { // Skip if its already connected if (this.ws && (this.ws.readyState == ws.CONNECTING || ws.readyState == ws.OPEN)) return; this.ws = await this.connectWebSocket(`wss://api.upstox.com/v2/feed/market-data-feed`, this.apiClient.authentications["OAUTH2"].accessToken); this.onOpen(); this.onMessage(); this.onClose(); this.onError(); } shouldReconnect() { return this.ws === null || !this.userClosedWebSocket && this.ws.readyState !== _ws.default.OPEN; } onOpen() { this.ws.on("open", () => { this.emit("open"); }); } onMessage() { this.ws.on("message", data => { const decodedData = this.decodeProtobuf(data); this.push(JSON.stringify(decodedData)); }); } onClose() { this.ws.on("close", code => { this.push(null); this.closingCode = code; if (code === 1000) { this.userClosedWebSocket = true; } }); } onError() { this.ws.on("error", e => { this.emit("error", e); }); } disconnect() { this.ws.close(1000); } subscribe(instrumentKeys, mode) { if (this.ws && this.ws.readyState === _ws.default.OPEN) { this.ws.send(this.buildRequest(instrumentKeys, this.Method.SUBSCRIBE, mode)); } else { throw new Error("Failed to subscribe: WebSocket is not open."); } } unsubscribe(instrumentKeys) { if (this.ws && this.ws.readyState === _ws.default.OPEN) { this.ws.send(this.buildRequest(instrumentKeys, this.Method.UNSUBSCRIBE)); } } changeMode(instrumentKeys, newMode) { if (this.ws && this.ws.readyState === _ws.default.OPEN) { this.ws.send(this.buildRequest(instrumentKeys, this.Method.SUBSCRIBE, newMode)); } else { throw new Error("Failed to changeMode: WebSocket is not open."); } } // Function to establish WebSocket connection async connectWebSocket(wsUrl, accessToken) { return new Promise(resolve => { const ws = new _ws.default(wsUrl, { headers: { Authorization: `Bearer ${accessToken}` }, followRedirects: true }); resolve(ws); }); } // Function to initialize the protobuf part async initProtobuf() { const protoPath = _path.default.resolve(__dirname, "./proto/MarketDataFeed.proto"); _protobufjs.default.load(protoPath, (error, root) => { if (error) { console.error("Error loading .proto file", error); return; } this.protobufRoot = root; }); } // Function to decode protobuf message decodeProtobuf(buffer) { if (!this.protobufRoot) { console.warn("Protobuf part not initialized yet!"); return null; } const FeedResponse = this.protobufRoot.lookupType("com.upstox.marketdatafeeder.rpc.proto.FeedResponse"); return FeedResponse.decode(buffer); } buildRequest(instrumentKeys, method, mode) { const requestObj = { guid: (0, _uuid.default)(), method, data: { instrumentKeys } }; // Only add 'mode' to 'data' if it is not undefined if (mode !== undefined) { requestObj.data.mode = mode; } return Buffer.from(JSON.stringify(requestObj)); } } exports.MarketDataFeeder = MarketDataFeeder;