UNPKG

growwapi

Version:
73 lines (72 loc) 3.08 kB
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); } }