Skip to main content
Glama
connect.js40.4 kB
'use strict'; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.KiteConnect = void 0; const axios_1 = __importDefault(require("axios")); const papaparse_1 = __importDefault(require("papaparse")); const sha256_1 = __importDefault(require("crypto-js/sha256")); const qs_1 = __importDefault(require("qs")); const utils_1 = __importDefault(require("./utils")); const interfaces_1 = require("../interfaces"); const constants_1 = require("../constants"); /** * @classdesc API client class. In production, you may initialise a single instance of this class per `api_key`. * This module provides an easy to use abstraction over the HTTP APIs. * The HTTP calls have been converted to methods and their JSON responses. * See the **[Kite Connect API documentation](https://kite.trade/docs/connect/v3/)** * for the complete list of APIs, supported parameters and values, and response formats. * * Getting started with API * ------------------------ * ~~~~ * * import { KiteConnect } from 'kiteconnect'; * * const apiKey = 'your_api_key' * const apiSecret = 'your_api_secret' * const requestToken = 'your_request_token' * * const kc = new KiteConnect({ api_key: apiKey }) * * async function init() { * try { * await generateSession() * await getProfile() * } catch (err) { * console.error(err) * } * } * * async function generateSession() { * try { * const response = await kc.generateSession(requestToken, apiSecret) * kc.setAccessToken(response.access_token) * console.log('Session generated:', response) * } catch (err) { * console.error('Error generating session:', err) * } * } * * async function getProfile() { * try { * const profile = await kc.getProfile() * console.log('Profile:', profile) * } catch (err) { * console.error('Error getting profile:', err) * } * } * // Initialize the API calls * init(); * ~~~~ * * API promises * ------------- * All API calls return a promise which you can `await` to handle asynchronously. * * ~~~~ * try { * const result = await kiteConnectApiCall; * // On success * } catch (error) { * // On rejection * } * ~~~~ * * @constructor * @name KiteConnect * * @param {Object} params Init params. * @param {string} params.api_key API key issued to you. * @param {string} [params.access_token=null] Token obtained after the login flow in * exchange for the `request_token`. Pre-login, this will default to null, * but once you have obtained it, you should persist it in a database or session to pass * to the Kite Connect class initialisation for subsequent requests. * @param {string} [params.root='https://api.kite.trade'] API end point root. Unless you explicitly * want to send API requests to a non-default endpoint, this can be ignored. * @param {string} [params.login_uri='https://kite.zerodha.com/connect/login'] Kite connect login url * @param {bool} [params.debug=false] If set to true, will console log requests and responses. * @param {number} [params.timeout=7000] Time (milliseconds) for which the API client will wait * for a request to complete before it fails. * * @example <caption>Initialize KiteConnect object</caption> * const kc = new KiteConnect({ api_key: apiKey }) */ class KiteConnect { /** * Creates an instance of KiteConnect. * * @constructor * @param {KiteConnectParams} params - The configuration parameters for initializing the instance. */ constructor(params) { // Constants this.PRODUCT_MIS = 'MIS'; this.PRODUCT_CNC = 'CNC'; this.PRODUCT_NRML = 'NRML'; // Order types this.ORDER_TYPE_MARKET = 'MARKET'; this.ORDER_TYPE_LIMIT = 'LIMIT'; this.ORDER_TYPE_SLM = 'SL-M'; this.ORDER_TYPE_SL = 'SL'; // Varieties this.VARIETY_REGULAR = 'regular'; this.VARIETY_CO = 'co'; this.VARIETY_AMO = 'amo'; this.VARIETY_ICEBERG = 'iceberg'; this.VARIETY_AUCTION = 'auction'; // Transaction types this.TRANSACTION_TYPE_BUY = 'BUY'; this.TRANSACTION_TYPE_SELL = 'SELL'; // Validities this.VALIDITY_DAY = 'DAY'; this.VALIDITY_IOC = 'IOC'; this.VALIDITY_TTL = 'TTL'; // Exchanges this.EXCHANGE_NSE = 'NSE'; this.EXCHANGE_BSE = 'BSE'; this.EXCHANGE_NFO = 'NFO'; this.EXCHANGE_CDS = 'CDS'; this.EXCHANGE_BCD = 'BCD'; this.EXCHANGE_BFO = 'BFO'; this.EXCHANGE_MCX = 'MCX'; // Margins segments this.MARGIN_EQUITY = 'equity'; this.MARGIN_COMMODITY = 'commodity'; // Statuses this.STATUS_CANCELLED = 'CANCELLED'; this.STATUS_REJECTED = 'REJECTED'; this.STATUS_COMPLETE = 'COMPLETE'; // GTT types this.GTT_TYPE_OCO = 'two-leg'; this.GTT_TYPE_SINGLE = 'single'; // GTT statuses this.GTT_STATUS_ACTIVE = 'active'; this.GTT_STATUS_TRIGGERED = 'triggered'; this.GTT_STATUS_DISABLED = 'disabled'; this.GTT_STATUS_EXPIRED = 'expired'; this.GTT_STATUS_CANCELLED = 'cancelled'; this.GTT_STATUS_REJECTED = 'rejected'; this.GTT_STATUS_DELETED = 'deleted'; // Position types this.POSITION_TYPE_DAY = 'day'; this.POSITION_TYPE_OVERNIGHT = 'overnight'; /** * Sets a callback function to be invoked when the session expires. * * @param cb - The callback function to set as the session expiry hook. * @returns void */ this.setSessionExpiryHook = function (cb) { this.session_expiry_hook = cb; }; /** * Invalidates the specified refresh token. * * @param {string} refresh_token - The refresh token to invalidate. * @returns A promise that resolves when the DELETE request is complete. */ this.invalidateRefreshToken = function (refresh_token) { return this._delete('api.token.invalidate', { api_key: this.api_key, refresh_token: refresh_token }); }; this.api_key = params.api_key; this.root = params.root || constants_1.DEFAULTS.root; this.timeout = params.timeout || constants_1.DEFAULTS.timeout; this.debug = params.debug || constants_1.DEFAULTS.debug; this.access_token = params.access_token || null; this.default_login_uri = constants_1.DEFAULTS.login; this.session_expiry_hook = null; this.requestInstance = this.createAxiosInstance(); } /** * Creates a custom Axios instance with the provided configuration. * * @private * @returns {AxiosInstance} Custom Axios instance */ createAxiosInstance() { const kiteVersion = 3; // Kite version to send in header const userAgent = utils_1.default.getUserAgent(); // User agent to be sent with every request const requestInstance = axios_1.default.create({ baseURL: this.root, timeout: this.timeout, headers: { 'X-Kite-Version': kiteVersion, 'User-Agent': userAgent }, paramsSerializer(params) { const searchParams = new URLSearchParams(); for (const key in params) { if (params.hasOwnProperty(key)) { const value = params[key]; if (Array.isArray(value)) { value.forEach(val => searchParams.append(key, val)); } else { searchParams.append(key, value); } } } return searchParams.toString(); } }); // Add a request interceptor requestInstance.interceptors.request.use((request) => { if (this.debug) console.log(request); return request; }); // Add a response interceptor requestInstance.interceptors.response.use((response) => { if (this.debug) console.log(response); const contentType = response.headers['content-type']; if (contentType === 'application/json' && typeof response.data === 'object') { // Throw incase of error if (response.data.error_type) throw response.data; // Return success data return response.data.data; } else if (contentType === 'text/csv') { // Return the response directly return response.data; } else { return { 'error_type': 'DataException', 'message': 'Unknown content type (' + contentType + ') with response: (' + response.data + ')' }; } }, (error) => { let resp = { 'message': 'Unknown error', 'error_type': 'GeneralException', 'data': null }; if (error.response) { // The request was made and the server responded with a status code // that falls out of the range of 2xx if (error.response.data && error.response.data.error_type) { if (error.response.data.error_type === 'TokenException' && this.session_expiry_hook) { this.session_expiry_hook(); } resp = error.response.data; } else { resp.error_type = 'NetworkException'; resp.message = error.response.statusText; } } else if (error.request) { // The request was made but no response was received // `error.request` is an instance of XMLHttpRequest in the browser and an instance of // http.ClientRequest in node.js resp.error_type = 'NetworkException'; resp.message = 'No response from server with error code: ' + error.code; } else if (error.message) { resp = error; } return Promise.reject(resp); }); return requestInstance; } /** * Sets the access token for the API client. * * @param accessToken The access token to set. * @returns {void} */ setAccessToken(accessToken) { this.access_token = accessToken; } /** * Returns the login URL with the embedded API key. * * @remarks * This method constructs and returns the login URL with the embedded API key. * * @returns The login URL with the embedded API key. */ getLoginURL() { return `${this.default_login_uri}?api_key=${this.api_key}&v=3`; } ; /** * Generates a session using the provided request token and API secret. * * @remarks * This method generates a session by sending a request to the API with the provided request token and API secret. * Upon successful completion, the method resolves with the session details, including the access token. If an error occurs, * the method rejects with an error. * * @param {string} request_token - The request token obtained during the login flow. * @param {string} api_secret - The API secret associated with the user's account. * @returns {Promise<any>} A promise that resolves when the session generation is successful and rejects if an error occurs. */ generateSession(request_token, api_secret) { return new Promise((resolve, reject) => { const checksum = (0, sha256_1.default)(this.api_key + request_token + api_secret).toString(); const p = this._post('api.token', { api_key: this.api_key, request_token: request_token, checksum: checksum }, null, formatGenerateSession); p.then((resp) => { // Set access token. if (resp && resp.access_token) { this.setAccessToken(resp.access_token); } return resolve(resp); }).catch(function (err) { return reject(err); }); }); } ; /** * Invalidates the access token. * * @remarks * This method sends a DELETE request to invalidate the specified access token. * If no access token is provided, the method uses the default access token associated with the instance. * * @param {string} [access_token] - The access token to invalidate. If not provided, the default access token is used. * @returns {Promise<boolean>} A promise that resolves when the DELETE request is complete. */ invalidateAccessToken(access_token) { return this._delete('api.token.invalidate', { api_key: this.api_key, access_token: access_token || this.access_token, }); } ; /** * Renews the access token using the provided refresh token and API secret. * * @remarks * This method sends a request to renew the access token using the given refresh token * and API secret. If the renewal is successful, the promise resolves to the renewed * access token. If the renewal fails, the promise is rejected with an error message. * * @param {string} refresh_token - The refresh token used for renewing the access token. * @param {string} api_secret - The API secret required for the renewal process. * @returns {Promise<any>} A promise that resolves to the renewed access token if successful. * If the renewal fails, the promise is rejected with an error message. */ renewAccessToken(refresh_token, api_secret) { return new Promise((resolve, reject) => { const checksum = (0, sha256_1.default)(this.api_key + refresh_token + api_secret).toString(); const p = this._post('api.token.renew', { api_key: this.api_key, refresh_token: refresh_token, checksum: checksum }); p.then((resp) => { if (resp && resp.access_token) { this.setAccessToken(resp.access_token); } return resolve(resp); }).catch(function (err) { return reject(err); }); }); } ; /** * Retrieves the user's profile. * * @returns {Promise<any>} A promise that resolves with the user's profile data. */ getProfile() { return this._get('user.profile'); } ; /** * Retrieves margin details for the specified segment or all segments. * * @remarks * If a segment is specified, margin details for that segment are retrieved. Otherwise, margin details for all segments are retrieved. * * @param {?string} segment - Optional. The segment for which to retrieve margin details. * @returns {Promise<any>} A promise that resolves with the margin details. * If a segment is specified, the promise resolves with margin details for that segment. * If no segment is specified, the promise resolves with margin details for all segments. */ getMargins(segment) { if (segment) { return this._get('user.margins.segment', { 'segment': segment }); } else { return this._get('user.margins'); } } ; /** * Places an order with the specified variety and parameters. * * @param {Varieties} variety - The variety of the order. * @param {PlaceOrderParams} params - The parameters for the order. * @returns {Promise<any>} A promise that resolves with the result of the order placement. */ placeOrder(variety, params) { params.variety = variety; return this._post('order.place', params); } ; /** * @param {Varieties} variety - The variety of the order. * @param {(string | number)} order_id - The ID of the order to modify. * @param {ModifyOrderParams} params - The parameters for modifying the order. * @returns {Promise<any>} A Promise that resolves with the modified order details. */ modifyOrder(variety, order_id, params) { params.variety = variety; params.order_id = order_id; return this._put('order.modify', params); } ; /** * @param {Varieties} variety - The variety of the order. * @param {(string | number)} order_id - The ID of the order to modify. * @param {?CancelOrderParams} [params] - The parameters for cancelling the order. * @returns {Promise<any>} */ cancelOrder(variety, order_id, params) { params = params || {}; params.variety = variety; params.order_id = order_id; return this._delete('order.cancel', params); } ; /** * @param {Varieties} variety - The variety of the order. * @param {string} order_id - The ID of the order to modify. * @param {ExitOrderParams} params - The parameters required for exiting the order. * @returns {Promise<any>} */ exitOrder(variety, order_id, params) { return this.cancelOrder(variety, order_id, params); } ; /** * Retrieves orders. * * @returns {Promise<any>} A Promise that resolves to the retrieved orders. */ getOrders() { return this._get('orders', null, null, this.formatResponse); } ; /** * Retrieves the order history for a given order ID. * * @param {(string | number)} order_id - The ID of the order to retrieve history for. * @returns {Promise<any>} - A Promise that resolves to the order history information. * The resolved value can be of any type. */ getOrderHistory(order_id) { return this._get('order.info', { 'order_id': order_id }, null, this.formatResponse); } ; /** * Retrieves trades data. * * @remarks * This method retrieves trades data from the server. * * @returns {Promise<any>} A Promise that resolves with the trades data. */ getTrades() { return this._get('trades', null, null, this.formatResponse); } ; /** * Retrieves the trades associated with a specific order. * * @param {string | number} order_id - The ID of the order. * @returns {Promise<any>} A Promise resolving to the trades associated with the order. */ getOrderTrades(order_id) { return this._get('order.trades', { 'order_id': order_id }, null, this.formatResponse); } ; /** * Calculates margins for the specified orders. * * @param {MarginOrder[]} orders - The array of orders for which margins are to be calculated. * @param {string} [mode='compact'] - The mode for margin calculation (optional). * @returns {Promise<any>} - A Promise that resolves with the calculated margins. */ orderMargins(orders, mode = 'compact') { return this._post('order.margins', orders, null, undefined, true, { 'mode': mode }); } ; /** * Retrieves the virtual contract note for the specified orders. * * @param {VirtualContractParam[]} orders - The array of orders for which to retrieve the virtual contract note. * @returns {Promise<any>} A Promise that resolves with the virtual contract note. */ getvirtualContractNote(orders) { return this._post('order.contract_note', orders, null, undefined, true, null); } ; /** * Retrieves margin information for a basket of orders. * * @param {Order[]} orders - The array of orders for which to retrieve margin information. * @param {boolean} [consider_positions=true] - Flag indicating whether to consider existing positions. * @param {*} [mode='compact'] - The mode of operation. Default is compact. * @returns {Promise<any>} - A Promise that resolves to margin information for the basket of orders. */ orderBasketMargins(orders, consider_positions = true, mode = 'compact') { return this._post('order.margins.basket', orders, null, undefined, true, { 'consider_positions': consider_positions, 'mode': mode }); } ; /** * Retrieves the holdings from the portfolio. * * @returns {Promise<any>} A Promise that resolves with the holdings data. */ getHoldings() { return this._get('portfolio.holdings'); } ; /** * Retrieves auction instruments. * * @remarks * This method retrieves auction instruments from the portfolio holdings. * * @returns {Promise<any>} A Promise that resolves with the auction instruments. */ getAuctionInstruments() { return this._get('portfolio.holdings.auction'); } ; /** * Retrieves positions from the portfolio. * * @returns {Promise<any>} A promise that resolves with the positions data. */ getPositions() { return this._get('portfolio.positions'); } ; /** * Converts a position based on the provided parameters. * * @param {ConvertPositionParams} params - The parameters for converting the position. * @returns {Promise<any>} A Promise that resolves with the result of the conversion. * */ convertPosition(params) { return this._put('portfolio.positions.convert', params); } ; /** * Retrieves instruments based on the provided exchange. * * @param {Exchanges} exchange - Exchange name * @returns {Promise<any>} - A Promise resolving to the fetched instruments. */ getInstruments(exchange) { if (exchange) { return this._get('market.instruments', { 'exchange': exchange }, null, this.transformInstrumentsResponse); } else { return this._get('market.instruments.all', null, null, this.transformInstrumentsResponse); } } ; /** * Retrieves Quote data for the specified instruments. * * @param {(string | string[])} instruments - An array of exchange:tradingsymbol * @returns {Promise<any>} A promise that resolves with the quote data for the specified instruments. */ getQuote(instruments) { return this._get('market.quote', { "i": instruments }, null, formatQuoteResponse); } ; /** * Retrieves OHLC (Open, High, Low, Close) data for the specified instruments. * * @param {(string | string[])} instruments - An array of exchange:tradingsymbol. * @returns {Promise<any>} A promise that resolves with the OHLC data for the specified instruments. */ getOHLC(instruments) { return this._get('market.quote.ohlc', { "i": instruments }); } ; /** * Retrieves the last traded price (LTP) of the specified instruments. * * @remarks * This method fetches the last traded price (LTP) for the provided instruments. * * @param {(string | string[])} instruments - An array of exchange:tradingsymbol * @returns {Promise<any>} The last traded price (LTP) of the specified instruments as a Promise<any>. */ getLTP(instruments) { return this._get('market.quote.ltp', { "i": instruments }); } ; /** * Retrieve historical data (candles) for an instrument. * For example: * ~~~~ * [{ * date: '2015-02-10T00:00:00+0530', * open: 277.5, * high: 290.8, * low: 275.7, * close: 287.3, * volume: 22589681 * }, ....] * ~~~~ * @param {(number | string)} instrument_token * @param {string} interval * @param {(string | Date)} from_date * @param {(string | Date)} to_date * @param {(number | boolean)} [continuous=false] * @param {(number | boolean)} [oi=false] * @returns {Promise<any>} */ getHistoricalData(instrument_token, interval, from_date, to_date, continuous = false, oi = false) { continuous = continuous ? 1 : 0; oi = oi ? 1 : 0; if (typeof to_date === 'object') to_date = _getDateTimeString(to_date); if (typeof from_date === 'object') from_date = _getDateTimeString(from_date); return this._get('market.historical', { instrument_token: instrument_token, interval: interval, from: from_date, to: to_date, continuous: continuous, oi: oi }, null, this.parseHistorical); } ; /** * @param {?(string | number)} [order_id] * @returns {*} */ getMFOrders(order_id) { if (order_id) { return this._get('mf.order.info', { 'order_id': order_id }, null, this.formatResponse); } else { return this._get('mf.orders', null, null, this.formatResponse); } } ; /** * * * @param {PlaceMFOrderParams} params * @returns {*} */ placeMFOrder(params) { return this._post('mf.order.place', params); } /** * * * @param {(string | number)} order_id * @returns {*} */ cancelMFOrder(order_id) { return this._delete('mf.order.cancel', { 'order_id': order_id }); } /** * * * @param {?(string | number)} [sip_id] * @returns {*} */ getMFSIPS(sip_id) { if (sip_id) { return this._get('mf.sip.info', { 'sip_id': sip_id }, null, this.formatResponse); } else { return this._get('mf.sips', null, null, this.formatResponse); } } /** * * * @param {Order} params * @returns {*} */ placeMFSIP(params) { return this._post('mf.sip.place', params); } /** * * * @param {(string | number)} sip_id * @param {Order} params * @returns {*} */ modifyMFSIP(sip_id, params) { params.sip_id = sip_id; return this._put('mf.sip.modify', params); } /** * * * @param {(string | number)} sip_id * @returns {*} */ cancelMFSIP(sip_id) { return this._delete('mf.sip.cancel', { 'sip_id': sip_id }); } /** * * * @returns {*} */ getMFHoldings() { return this._get('mf.holdings'); } /** * * * @returns {*} */ getMFInstruments() { return this._get('mf.instruments', null, null, transformMFInstrumentsResponse); } /** * Get GTTs list * * @returns {Promise<any>} */ getGTTs() { return this._get('gtt.triggers', null, null, this.formatResponse); } /** * Get specific GTT history * * @param {(string | number)} trigger_id * @returns {Promise<any>} */ getGTT(trigger_id) { return this._get('gtt.trigger_info', { 'trigger_id': trigger_id }, null, this.formatResponse); } ; /** * Get API params from user defined GTT params * * @param {PlaceGTTParams} params * @returns {{ condition: { exchange: Exchanges; tradingsymbol: string; trigger_values: {}; last_price: any; }; orders: {}; }} */ _getGTTPayload(params) { var _a, _b; if (params.trigger_type !== interfaces_1.GTTStatusTypes.GTT_TYPE_OCO && params.trigger_type !== interfaces_1.GTTStatusTypes.GTT_TYPE_SINGLE) { throw new Error('Invalid `params.trigger_type`'); } if (params.trigger_type === interfaces_1.GTTStatusTypes.GTT_TYPE_OCO && ((_a = params.trigger_values) === null || _a === void 0 ? void 0 : _a.length) !== 2) { throw new Error('Invalid `trigger_values` for `OCO` order type'); } if (params.trigger_type === interfaces_1.GTTStatusTypes.GTT_TYPE_SINGLE && ((_b = params.trigger_values) === null || _b === void 0 ? void 0 : _b.length) !== 1) { throw new Error('Invalid `trigger_values` for `single` order type'); } const condition = { exchange: params.exchange, tradingsymbol: params.tradingsymbol, trigger_values: params.trigger_values, last_price: params.last_price }; let orders = []; for (let o of params.orders) { orders.push({ transaction_type: o.transaction_type, order_type: o.order_type, product: o.product, quantity: parseInt(o.quantity), price: parseFloat(o.price), exchange: params.exchange, tradingsymbol: params.tradingsymbol }); } return { condition, orders }; } ; /** * Place GTT. * @param {PlaceGTTParams} params * @returns {Promise<any>} */ placeGTT(params) { const payload = this._getGTTPayload(params); return this._post('gtt.place', { condition: JSON.stringify(payload.condition), orders: JSON.stringify(payload.orders), type: params.trigger_type }); } ; /** * Modify GTT Order * * @param {(string | number)} trigger_id * @param {PlaceGTTParams} params * @returns {Promise<any>} */ modifyGTT(trigger_id, params) { const payload = this._getGTTPayload(params); return this._put('gtt.modify', { trigger_id: trigger_id, type: params.trigger_type, condition: JSON.stringify(payload.condition), orders: JSON.stringify(payload.orders) }); } ; /** * Delete specific GTT order * * @param {(string | number)} trigger_id * @returns {Promise<any>} */ deleteGTT(trigger_id) { return this._delete('gtt.delete', { 'trigger_id': trigger_id }, null, undefined); } ; /** * Validate postback data checksum * * @param {AnyObject} postback_data * @param {string} api_secret * @returns {boolean} */ validatePostback(postback_data, api_secret) { if (!postback_data || !postback_data.checksum || !postback_data.order_id || !postback_data.order_timestamp || !api_secret) { throw new Error('Invalid postback data or api_secret'); } const inputString = postback_data.order_id + postback_data.order_timestamp + api_secret; let checksum; try { checksum = (0, sha256_1.default)(inputString).toString(); } catch (e) { throw (e); } return postback_data.checksum === checksum; } /** * * @private * @param {string} route * @param {?(AnyObject | null)} [params] * @param {?(string | null)} [responseType] * @param {?AxiosTransformer} [responseTransformer] * @param {boolean} [isJSON=false] * @returns {*} */ _get(route, params, responseType, responseTransformer, isJSON = false) { return this.request(route, 'GET', params || {}, responseType, responseTransformer, isJSON); } /** * * * @private * @param {string} route * @param {(AnyObject | null)} params * @param {?(string | null)} [responseType] * @param {?AxiosTransformer} [responseTransformer] * @param {boolean} [isJSON=false] * @param {(AnyObject | null)} [queryParams=null] * @returns {*} */ _post(route, params, responseType, responseTransformer, isJSON = false, queryParams = null) { return this.request(route, 'POST', params || {}, responseType, responseTransformer, isJSON, queryParams); } /** * * * @private * @param {string} route * @param {(AnyObject | null)} params * @param {?(string | null)} [responseType] * @param {?AxiosTransformer} [responseTransformer] * @param {boolean} [isJSON=false] * @param {*} [queryParams=null] * @returns {*} */ _put(route, params, responseType, responseTransformer, isJSON = false, queryParams = null) { return this.request(route, 'PUT', params || {}, responseType, responseTransformer, isJSON, queryParams); } /** * * * @private * @param {string} route * @param {(AnyObject | null)} params * @param {?(string | null)} [responseType] * @param {?AxiosTransformer} [responseTransformer] * @param {boolean} [isJSON=false] * @returns {*} */ _delete(route, params, responseType, responseTransformer, isJSON = false) { return this.request(route, 'DELETE', params || {}, responseType, responseTransformer, isJSON); } /** * * * @private * @param {string} route * @param {Method} method * @param {AnyObject} params * @param {?(string | null)} [responseType] * @param {?AxiosTransformer} [responseTransformer] * @param {?boolean} [isJSON] * @param {?(Record<string, any> | null)} [queryParams] * @returns {*} */ request(route, method, params, responseType, responseTransformer, isJSON, queryParams) { // Check access token if (!responseType) responseType = 'json'; let uri = constants_1.ROUTES[route]; // Replace variables in 'RESTful' URLs with corresponding params if (uri.indexOf('{') !== -1) { let k; for (k in params) { if (params.hasOwnProperty(k)) { uri = uri.replace('{' + k + '}', params[k]); } } } let payload = null; if (method === 'GET' || method === 'DELETE') { queryParams = params; } else { if (isJSON) { // post JSON payload payload = JSON.stringify(params); } else { // post url encoded payload payload = qs_1.default.stringify(params); } } const options = { method, url: uri, params: queryParams, data: payload, // Set auth header headers: {} }; // Send auth token if (this.access_token) { const authHeader = `${this.api_key}:${this.access_token}`; options['headers']['Authorization'] = `token ${authHeader}`; } // Set request header content type if (isJSON) { options['headers']['Content-Type'] = 'application/json'; } else { options['headers']['Content-Type'] = 'application/x-www-form-urlencoded'; } // Set response transformer if (responseTransformer) { options.transformResponse = axios_1.default.defaults.transformResponse.concat(responseTransformer); } return this.requestInstance.request(options); } /** * * * @private * @param {AnyObject} jsonData * @returns {AnyObject} */ parseHistorical(jsonData) { // Return if its an error if (jsonData.error_type) return jsonData; const results = []; for (let i = 0; i < jsonData.data.candles.length; i++) { const d = jsonData.data.candles[i]; const c = { 'date': new Date(d[0]), 'open': d[1], 'high': d[2], 'low': d[3], 'close': d[4], 'volume': d[5] }; // Add OI field if its returned if (d[6]) { c['oi'] = d[6]; } results.push(c); } return { 'data': results }; } /** * * * @private * @param {*} data * @param {AnyObject} headers * @returns {*} */ transformInstrumentsResponse(data, headers) { // Parse CSV responses if (headers['content-type'] === 'text/csv') { const parsedData = papaparse_1.default.parse(data, { 'header': true }).data; for (const item of parsedData) { item['last_price'] = parseFloat(item['last_price']); item['strike'] = parseFloat(item['strike']); item['tick_size'] = parseFloat(item['tick_size']); item['lot_size'] = parseInt(item['lot_size']); if (item['expiry'] && item['expiry'].length === 10) { item['expiry'] = new Date(item['expiry']); } } return parsedData; } return data; } /** * * * @private * @param {AnyObject} data * @returns {AnyObject} */ formatResponse(data) { if (!data.data || typeof data.data !== 'object') return data; let list = []; if (data.data instanceof Array) { list = data.data; } else { list = [data.data]; } const results = []; const fields = ['order_timestamp', 'exchange_timestamp', 'created', 'last_instalment', 'fill_timestamp']; for (const item of list) { for (const field of fields) { if (item[field] && item[field].length === 19) { item[field] = new Date(item[field]); } } results.push(item); } if (data.data instanceof Array) { data.data = results; } else { data.data = results[0]; } return data; } } exports.KiteConnect = KiteConnect; /** * * @param {AnyObject} data * @returns {AnyObject} */ function formatGenerateSession(data) { if (!data.data || typeof data.data !== 'object') return data; if (data.data.login_time) { data.data.login_time = new Date(data.data.login_time); } return data; } /** * * @param {AnyObject} data * @returns {AnyObject} */ function formatQuoteResponse(data) { if (!data.data || typeof data.data !== 'object') return data; for (const k in data.data) { const item = data.data[k]; for (const field of ['timestamp', 'last_trade_time']) { if (item[field] && item[field].length === 19) { item[field] = new Date(item[field]); } } } return data; } // Format response ex. datetime string to date /** * * @param {*} data * @param {AnyObject} headers * @returns {*} */ function transformMFInstrumentsResponse(data, headers) { // Parse CSV responses if (headers['content-type'] === 'text/csv') { const parsedData = papaparse_1.default.parse(data, { 'header': true }).data; for (const item of parsedData) { item['minimum_purchase_amount'] = parseFloat(item['minimum_purchase_amount']); item['purchase_amount_multiplier'] = parseFloat(item['purchase_amount_multiplier']); item['minimum_additional_purchase_amount'] = parseFloat(item['minimum_additional_purchase_amount']); item['redemption_quantity_multiplier'] = parseFloat(item['redemption_quantity_multiplier']); item['minimum_additional_purchase_amount'] = parseFloat(item['minimum_additional_purchase_amount']); item['last_price'] = parseFloat(item['last_price']); item['purchase_allowed'] = Boolean(parseInt(item['purchase_allowed'])); item['redemption_allowed'] = Boolean(parseInt(item['redemption_allowed'])); if (item['last_price_date'] && item['last_price_date'].length === 10) { item['last_price_date'] = new Date(item['last_price_date']); } } return parsedData; } return data; } /** * * @param {Date} date * @returns {*} */ function _getDateTimeString(date) { const isoString = date.toISOString(); return isoString.replace('T', ' ').split('.')[0]; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yogendhra9/ZerodhaMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server