growwapi
Version:
NodeJS SDK for Groww trading APIs
73 lines (72 loc) • 3.08 kB
JavaScript
import { createUser } from 'ts-nkeys';
import { Auth } from '../../resources/auth';
import { connect } from 'nats.ws';
import { jwtAuthenticator } from 'nats';
import { LIVE_FEED_MAX_RETRY_COUNT, LIVE_FEED_MAX_RETRY_DURATION, SOCKET_URL } from '../../config';
import { Instructions } from '../../resources/instructions';
import { FNOOrderUpdatesDecoder, MarketDepthDecoder, EquityOrderUpdatesDecoder, PositionOrderUpdatesDecoder, PriceDecoder } from './Decoders';
import { liveIndexParser, liveMarketParser, liveUpdatesParser } from './Parser';
import { InstrumentType, LiveFeedSubscriptionType } from '../../types';
const keyPair = createUser();
const publicKey = keyPair.getPublicKey();
export async function connectToLiveFeed() {
const credentials = await Auth.socketAccessToken(publicKey.toString('utf-8'));
const stream = connect({
servers: SOCKET_URL,
authenticator: jwtAuthenticator(credentials.token, keyPair.getSeed()),
});
return { stream: await stream, credentials };
}
export function liveFeedDecoder(type, data) {
switch (type) {
case LiveFeedSubscriptionType.Price:
return PriceDecoder(data);
case LiveFeedSubscriptionType.Index:
return PriceDecoder(data);
case LiveFeedSubscriptionType.MarketDepth:
return MarketDepthDecoder(data);
case LiveFeedSubscriptionType.FnoOrderUpdates:
return FNOOrderUpdatesDecoder(data);
case LiveFeedSubscriptionType.FnoPositionUpdates:
return PositionOrderUpdatesDecoder(data);
case LiveFeedSubscriptionType.EquityOrderUpdates:
return EquityOrderUpdatesDecoder(data);
default:
throw new Error(`Unknown subscription type: ${type}`);
}
}
export async function generateSubscriptionTopic(type, subscriptionId, exchangeToken) {
const instruction = exchangeToken ? (await (new Instructions).getFilteredInstructions({
exchangeToken: exchangeToken,
}))[0] : null;
return buildSubscriptionTopic(type, subscriptionId, instruction);
}
function buildSubscriptionTopic(type, subscriptionId, instruction) {
if (!instruction)
return liveUpdatesParser(type, subscriptionId);
if (instruction.instrumentType == InstrumentType.IDX)
return liveIndexParser(type, instruction);
return liveMarketParser(type, instruction);
}
export async function retryStrategy(connection, retryCount, disconnect, reconnect, action) {
if (!connection) {
console.error('Connection is not established. Please connect first.');
return;
}
try {
await action();
}
catch {
try {
await disconnect();
}
catch { /* ignore */ }
const delay = Math.min(1000 * Math.pow(2, retryCount), LIVE_FEED_MAX_RETRY_DURATION);
setTimeout(async () => {
retryCount++;
if (retryCount < LIVE_FEED_MAX_RETRY_COUNT) {
await retryStrategy(connection, retryCount, disconnect, reconnect, reconnect);
}
}, delay);
}
}