Hi @Moderator_2 ,
Code is ok and tokens are also valid but still getting same response Please check server side, it is major bug
Hi @Moderator_2 ,
Code is ok and tokens are also valid but still getting same response Please check server side, it is major bug
Also code in websocket2 needs some modifications :
In fetchdata function
subscribeData.push(json_req);
const { correlationID, action, params} = json_req;
const {mode , tokenList } = params
Check my code
Feedtype is not correct in your read me for websocket2 in node repo
Change it with feedtype :feed token (generated in login response )
Use feed token in feed type it worked for me
replace code of node_modules\smartapi-javascript\lib\websocket2.0.js with this code
let WebSocket = require('ws');
const Parser = require('binary-parser').Parser;
let { CONSTANTS, ACTION, MODE, EXCHANGES } = require('../config/constant');
let triggers = {
connect: [],
tick: [],
};
let WebSocketV2 = function (params) {
try {
let { clientcode, jwttoken, apikey, feedtype } = params;
let self = this;
let ws = null;
let headers = {
'x-client-code': clientcode,
Authorization: jwttoken,
'x-api-key': apikey,
'x-feed-token': feedtype,
};
const url = CONSTANTS?.websocketURL;
let ping_Interval = CONSTANTS?.Interval;
let timeStamp;
let stopInterval;
let subscribeData = [];
let reset;
let open = 1;
let customErrorHandler = false;
let reconnectionTime;
let reconnectionType = null;
let expMultiplier;
let isReconnect = false;
this.connect = function () {
try {
return new Promise((resolve, reject) => {
if (
headers?.['x-client-code'] === null ||
headers?.['x-feed-token'] === null ||
headers?.['x-api-key'] === null ||
headers?.Authorization === null
) {
return 'client_code or jwt_token or api_key or feed_token is missing';
}
ws = new WebSocket(url, { headers });
ws.onopen = function onOpen(evt) {
if (subscribeData.length > 0) {
let reSubscribe = subscribeData;
subscribeData = [];
reSubscribe.map((data) => {
self.fetchData(data);
});
}
reset = setInterval(function () {
ws.send('ping');
}, ping_Interval);
resolve();
};
ws.onmessage = function (evt) {
let result = evt.data;
timeStamp = Math.floor(Date.now() / 1000);
const buf = Buffer.from(result);
const receivedData = setResponse(buf, result);
trigger('tick', [receivedData]);
resolve(result);
};
stopInterval = setInterval(function () {
let currentTimeStamp = Math.floor(Date.now() / 1000);
let lastMessageTimeStamp = currentTimeStamp - timeStamp;
if (lastMessageTimeStamp > 20) {
if (ws?._readyState === open) {
ws.close();
}
clearInterval(reset);
clearInterval(stopInterval);
self.connect();
}
}, 5000);
ws.onerror = function (evt) {
if (customErrorHandler) {
reject(evt);
}
else {
if (evt?.message?.match(/\d{3}/)?.[0] == 401) {
throw new Error(evt.message);
}
try {
if (ws?._readyState === open) {
ws.close();
}
clearInterval(reset);
} catch (error) {
throw new Error(error);
}
}
};
ws.onclose = function (evt) {
if (isReconnect) {
if (reconnectionType === "simple") {
setTimeout(function () {
clearInterval(reset);
clearInterval(stopInterval);
self.connect();
}, reconnectionTime);
} else if (reconnectionType === "exponential") {
setTimeout(function () {
clearInterval(reset);
clearInterval(stopInterval);
self.connect();
reconnectionTime *= expMultiplier;
}, reconnectionTime);
}
}
};
});
} catch (error) {
throw new Error(error);
}
};
this.fetchData = function (json_req) {
subscribeData.push(json_req);
const { correlationID, action, params} = json_req;
const {mode , tokenList } = params
if (action !== ACTION.Subscribe && action !== ACTION.Unsubscribe) {
throw new Error('Invalid Action value passed');
}
if (
mode !== MODE.LTP &&
mode !== MODE.Quote &&
mode !== MODE.SnapQuote &&
mode !== MODE.Depth
) {
throw new Error("Invalid Mode value passed");
}
if (tokenList.length > 0 &&
tokenList[0].exchangeType !== EXCHANGES.bse_cm &&
tokenList[0].exchangeType !== EXCHANGES.bse_fo &&
tokenList[0].exchangeType !== EXCHANGES.cde_fo &&
tokenList[0].exchangeType !== EXCHANGES.mcx_fo &&
tokenList[0].exchangeType !== EXCHANGES.ncx_fo &&
tokenList[0].exchangeType !== EXCHANGES.nse_cm &&
tokenList[0].exchangeType !== EXCHANGES.nse_fo
) {
throw new Error('Invalid Exchange type passed');
}
if (mode === MODE.Depth) {
if (tokens.length > 50) {
throw new Error(
"Quota exceeded: You can subscribe to a maximum of 50 tokens"
);
}
if (mode === MODE.Depth && exchangeType !== EXCHANGES.nse_cm) {
throw new Error(
"Invalid exchange type: Please check the exchange type and try again"
);
}
}
let reqBody = {
action,
params: {
mode,
tokenList: tokenList,
},
};
if (correlationID) {
reqBody.correlationID = correlationID;
}
console.log(ws._readyState)
if (ws?._readyState === open) {
ws.send(JSON.stringify(reqBody));
}
};
this.on = function (e, callback) {
if (triggers.hasOwnProperty(e)) {
triggers[e].push(callback);
}
};
this.close = function () {
isReconnect = false;
clearInterval(stopInterval);
ws.close();
};
this.customError = function () {
customErrorHandler = true;
};
this.reconnection = function (type, delTime, multiplier) {
isReconnect = true;
reconnectionType = type
if (reconnectionType === 'simple') {
reconnectionTime = delTime
}
if (reconnectionType === 'exponential') {
reconnectionTime = delTime * multiplier;
expMultiplier = multiplier
}
}
} catch (error) {
throw new Error(error);
}
};
function trigger(e, args) {
if (!triggers[e]) return;
for (var n = 0; n < triggers[e].length; n++) {
triggers[e][n].apply(triggers[e][n], args ? args : []);
}
}
function _atos(array) {
var newarray = [];
try {
for (var i = 0; i < array.length; i++) {
newarray.push(String.fromCharCode(array[i]));
}
} catch (e) {
throw new Error(e);
}
let token = JSON.stringify(newarray.join(''));
return token.replaceAll('\\u0000', '');
}
function LTP(buf) {
const ltp = new Parser()
.endianness('little')
.int8('subscription_mode', { formatter: toNumber })
.int8('exchange_type', { formatter: toNumber })
.array('token', {
type: 'uint8',
length: 25,
formatter: _atos,
})
.int64('sequence_number', { formatter: toNumber })
.int64('exchange_timestamp', { formatter: toNumber })
.int32('last_traded_price', { formatter: toNumber });
return ltp.parse(buf);
}
function QUOTE(buf) {
const quote = new Parser()
.endianness('little')
.uint8('subscription_mode', { formatter: toNumber, length: 1 })
.uint8('exchange_type', { formatter: toNumber, length: 1 })
.array('token', { type: 'int8', length: 25, formatter: _atos })
.uint64('sequence_number', { formatter: toNumber, length: 8 })
.uint64('exchange_timestamp', { formatter: toNumber, length: 8 })
.uint64('last_traded_price', { formatter: toNumber, length: 8 })
.int64('last_traded_quantity', { formatter: toNumber, length: 8 })
.int64('avg_traded_price', { formatter: toNumber, length: 8 })
.int64('vol_traded', { formatter: toNumber, length: 8 })
.doublele('total_buy_quantity', { formatter: toNumber, length: 8 })
.doublele('total_sell_quantity', { formatter: toNumber, length: 8 })
.int64('open_price_day', { formatter: toNumber, length: 8 })
.int64('high_price_day', { formatter: toNumber, length: 8 })
.int64('low_price_day', { formatter: toNumber, length: 8 })
.int64('close_price', {
formatter: toNumber,
length: 8,
});
return quote.parse(buf);
}
function SNAP_QUOTE(buf) {
const bestFiveData = new Parser()
.endianness('little')
.int16('flag', { formatter: toNumber, length: 2 })
.int64('quantity', { formatter: toNumber, length: 8 })
.int64('price', { formatter: toNumber, length: 8 })
.int16('no_of_orders', { formatter: toNumber, length: 2 });
const snapQuote = new Parser()
.endianness('little')
.uint8('subscription_mode', { formatter: toNumber, length: 1 })
.uint8('exchange_type', { formatter: toNumber, length: 1 })
.array('token', { type: 'int8', length: 25, formatter: _atos })
.uint64('sequence_number', { formatter: toNumber, length: 8 })
.uint64('exchange_timestamp', { formatter: toNumber, length: 8 })
.uint64('last_traded_price', { formatter: toNumber, length: 8 })
.int64('last_traded_quantity', { formatter: toNumber, length: 8 })
.int64('avg_traded_price', { formatter: toNumber, length: 8 })
.int64('vol_traded', { formatter: toNumber, length: 8 })
.doublele('total_buy_quantity', { formatter: toNumber, length: 8 })
.doublele('total_sell_quantity', { formatter: toNumber, length: 8 })
.int64('open_price_day', { formatter: toNumber, length: 8 })
.int64('high_price_day', { formatter: toNumber, length: 8 })
.int64('low_price_day', { formatter: toNumber, length: 8 })
.int64('close_price', {
formatter: toNumber,
length: 8,
})
.int64('last_traded_timestamp', { formatter: toNumber, length: 8 })
.int64('open_interest', { formatter: toNumber, length: 8 })
.doublele('open_interest_change', {
formatter: toNumber,
length: 8,
})
.array('best_5_buy_data', { type: bestFiveData, lengthInBytes: 100 })
.array('best_5_sell_data', { type: bestFiveData, lengthInBytes: 100 })
.int64('upper_circuit', { formatter: toNumber, length: 8 })
.int64('lower_circuit', { formatter: toNumber, length: 8 })
.int64('fiftytwo_week_high', {
formatter: toNumber,
length: 8,
})
.int64('fiftytwo_week_low', { formatter: toNumber, length: 8 });
// let response = snapQuote.parse(buf);
return snapQuote.parse(buf);
}
function DEPTH(buf) {
const depthTwenty = new Parser()
.endianness("little")
.int32("quantity", { formatter: toNumber, length: 4 })
.int32("price", { formatter: toNumber, length: 4 })
.int16("no_of_orders", { formatter: toNumber, length: 2 });
const depth = new Parser()
.endianness("little")
.uint8("subscription_mode", { formatter: toNumber, length: 1 })
.uint8("exchange_type", { formatter: toNumber, length: 1 })
.array("token", { type: "int8", length: 25, formatter: _atos })
.uint64("exchange_timestamp", { formatter: toNumber, length: 8 })
.int64("packet_received_time", { formatter: toNumber, length: 8 })
.array("depth_twenty_buy_data", { type: depthTwenty, lengthInBytes: 200 })
.array("depth_twenty_sell_data", {
type: depthTwenty,
lengthInBytes: 200,
});
return depth.parse(buf);
}
function toNumber(number) {
return number.toString();
}
function setResponse(buf, result) {
const subscription_mode = new Parser().uint8('subscription_mode');
switch (subscription_mode.parse(buf)?.subscription_mode) {
case MODE.LTP:
return LTP(buf);
case MODE.Quote:
return QUOTE(buf);
case MODE.SnapQuote:
return SNAP_QUOTE(buf);
case MODE.Depth:
return DEPTH(buf);
default:
return result;
}
}
module.exports = WebSocketV2;
Hi @Moderator_2 ,
Code is ok and tokens are also valid but still getting same response Please check server side, it is major bug
Due to lake of support i dropped my idea to use this api in one of the popular tech (Next.Js).
Hi @anand__lunawat ,,,,,, not yet resolved
@admin
I am trying to implement websocket 2.0 in node SDK,
but it shows "Error while processing message"
can you please help me, what i am doing wrong in my code
const feed = {
"correlationID": "abcde12345",
"action": 1,
"params": {
"mode": 1,
"tokenList": [
{
"exchangeType": 2,
"tokens": [
"55429"
]
}
]
}
} new WebSocketClient({
clientcode: process.env.CLIENT_CODE,
jwttoken: session.get("access_token"),
apikey: process.env.API_KEY,
feedtype: JSON.stringify(feed)
});
ws2.connect()
.then(() => {
ws2.fetchData("subscribe",JSON.stringify(feed)); // ACTION_TYPE: subscribe | unsubscribe FEED_TYPE: order_feed
setTimeout(function () {
ws2.close()
}, 60000)
})
ws2.on('tick', receiveTick);
function receiveTick(data) {
console.log("receiveTick:::::", data);
}
When i tried to import smart api package it shows "Module not found: Can't resolve 'fs'"
in Next js can any one suggest possible solution.