-
Notifications
You must be signed in to change notification settings - Fork 0
/
component---src-pages-app-upstox-index-js-46726161d0ee648c4794.js.map
1 lines (1 loc) · 188 KB
/
component---src-pages-app-upstox-index-js-46726161d0ee648c4794.js.map
1
{"version":3,"file":"component---src-pages-app-upstox-index-js-46726161d0ee648c4794.js","mappings":"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","sources":["webpack://kaagzi/./src/app/Upstox/providers/UpstoxUser/index.js","webpack://kaagzi/./src/app/Upstox/providers/UpstoxMasterData/index.js","webpack://kaagzi/./src/app/Upstox/providers/UpstoxWebSocket/index.js","webpack://kaagzi/./src/app/Upstox/components/MarketWatch/SearchResults/searchResults.module.css","webpack://kaagzi/./src/app/Upstox/components/MarketWatch/SearchResults/index.js","webpack://kaagzi/./src/app/Upstox/components/MarketWatch/marketWatch.module.css","webpack://kaagzi/./src/app/Upstox/components/MarketWatch/index.js","webpack://kaagzi/./src/app/Upstox/components/Positions/positions.module.css","webpack://kaagzi/./src/app/Upstox/components/Positions/index.js","webpack://kaagzi/./src/app/Upstox/index.js","webpack://kaagzi/./src/pages/app/upstox/index.js"],"sourcesContent":["/*global process*/\n//https://techblogs.42gears.com/extract-gzip-data-in-javascript/\nimport React, { createContext, useContext, useEffect, useRef, useState } from 'react';\n\n// import { getCookie } from '@utils';\n// import { chromeWebExtension_UUID, firefoxWebExtension_UUID } from '../../../../../../configs/webextension.config.js';\n// import { chromeWebExtension_UUID, firefoxWebExtension_UUID } from '@webextensionConfig';\nimport { ToastNotificationContext } from '@providers/ToastNotification';\nimport { NetworkCheckContext } from '@providers/NetworkAvailabilityCheck';\nimport { LambdaContext } from '@providers/aws/Lambda';\n// import { StockMarketBrokerContext } from '@providers/StockMarketBroker';\n// import BrokerSelector from '@components/BrokerSelector';\n\n// import Button, { LinkButton } from '@ui/Button';\nimport Loading from '@components/ui/Loading';\nimport BrokerLogin from '@appSharedComponents/BrokerLogin';\n// import SidebarBottomSheet from '@commonContainers/SidebarBottomSheet';\n\n//==================+\n//\t\tTYPES\t\t|\n//==================+\n/** Upstox logged in user data stored in localstorage\n * @typedef {import('@types_upstox').UpstoxUserDataStored} UpstoxUserDataStored\n */\n\nexport const UpstoxUserContext = createContext({\n\tid: null,\n\tname: null,\n\temail: null,\n\taccessToken: null,\n\n\t/** Checks if access token is still alive and not expired\n\t * Useful before making API calls to Upstox (including websocket)\n\t * @returns {Boolean} TRUE if still valid, FALSE if expired\n\t */\n\tcheckIfAccessTokenIsAlive: () => {},\n\n\t/**\n\t * Checks if Upstox user is logged-in and updates state\n\t * @returns {Promise<({atk:string,ftk:string,id:string,nm:string,eml:string,t:number}|false)>} Logged-in Upstox user-data or FALSE if no user is logged-in\n\t */\n\tchkIfUpstoxUserIsLoggedIn: () => {},\n\n\t/** Logs user out of Upstox\n\t * @returns {Promise<boolean>} TRUE upon successfully logging out\n\t */\n\tlogOut: () => {},\n});\n\nexport default function UpstoxUser_ContextProvider({ children }) {\n\t// const [authCode, setAuthCode] = useState(null);\n\tconst [isSigningInWip, setIsSigningInWip] = useState(false);\n\tconst [accessToken, setAccessToken] = useState(null);\n\tconst [id, setId] = useState(null);\n\tconst [name, setName] = useState(null);\n\tconst [email, setEmail] = useState(null);\n\n\tconst { notify } = useContext(ToastNotificationContext);\n\tconst isOnline = useContext(NetworkCheckContext);\n\tconst invokeFn = useContext(LambdaContext);\n\t// const { setCurrentBroker } = useContext(StockMarketBrokerContext);\n\n\tconst authWindowRef = useRef(null);\n\n\t/** Resets state */\n\tconst _reset = () => {\n\t\t// setAuthCode(null);\n\t\tsetIsSigningInWip(false);\n\t\tsetAccessToken(null);\n\t\tsetId(null);\n\t\tsetName(null);\n\t\tsetEmail(null);\n\t\tauthWindowRef.current = null;\n\t};\n\n\t/**\n\t * Opens the auth window\n\t * @see https://elvisciotti.medium.com/how-to-create-a-oauth-popup-in-react-7ab102ea48f\n\t */\n\tconst openAuthWindow = () => {\n\t\tif (!isOnline) {\n\t\t\tnotify('Network unavailable', 'err');\n\t\t\treturn null;\n\t\t}\n\t\tif (authWindowRef.current !== null) {\n\t\t\t//here close that previously opened window before opening a new one\n\t\t\t// authWindowRef.current.removeEventListener('beforeunload', readTokenFromAuthWindowRedirectUrl_n_setup);\n\t\t\tauthWindowRef.current.close();\n\t\t\tauthWindowRef.current = null;\n\t\t\t// clearInterval(intervalRef);\n\t\t\t// intervalRef.current = null;\n\t\t}\n\n\t\ttry {\n\t\t\tauthWindowRef.current = window.open(\n\t\t\t\t`https://api.upstox.com/v2/login/authorization/dialog?response_type=code&client_id=${\n\t\t\t\t\tprocess.env.GATSBY_UPSTOX_API_KEY\n\t\t\t\t}&redirect_uri=${encodeURIComponent('https://kaagzi.in/app/upstox/welcome')}`,\n\t\t\t\t'Upstox Login',\n\t\t\t\t'popup=yes,resizable=no,location=no,menubar=no,scrollbars=yes,status=no,titlebar=no,toolbar=no,fullscreen=no,dependent=no,height=640,width=960',\n\t\t\t);\n\n\t\t\t// authWindowRef.current.addEventListener('beforeunload', readTokenFromAuthWindowRedirectUrl_n_setup);\n\t\t\t//here set interval to poll the window and read tokens from window's url\n\t\t\t// intervalRef.current && clearInterval(intervalRef.current);\n\t\t\t// setInterval(readTokenFromAuthWindowRedirectUrl_n_setup, 1000);\n\t\t} catch (err) {\n\t\t\tconsole.log(err);\n\t\t}\n\t};\n\n\t// /**\n\t// * Fetch access token by exchanging the auth code received from oAuth login with broker\n\t// * @param {string} authCode - The auth code received from oAuth login with broker\n\t// * @returns {Promise<?string>} Access token if fetch successful or NULL otherwise\n\t// */\n\t/* const _getAccessTokenUsingAuthCode = async (authCode) => {\n\t\tif (!authCode || typeof authCode !== 'string' || authCode.toString().trim() === '') return null;\n\t\ttry {\n\t\t\t//==================================+\n\t\t\t//\t\tTHIS SHUD BE SERVER SIDE\t|\n\t\t\t//----------------------------------+\n\t\t\t//app secret to be used in the redirect '/app/upstox/welcome' page while testing -- tgb1808jz0 (in production mode, it should be server side)\n\t\t\tconst access_token_resp = await fetch('https://api.upstox.com/v2/login/authorization/token', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t\t\tAccept: 'application/json',\n\t\t\t\t},\n\t\t\t\tbody: `code=${authCode}&client_id=${process.env.GATSBY_UPSTOX_API_KEY}&client_secret=tgb1808jz0&redirect_uri=${encodeURIComponent(\n\t\t\t\t\t'https://kaagzi.in/app/upstox/welcome',\n\t\t\t\t)}&grant_type=authorization_code`,\n\t\t\t}).catch((err) => {\n\t\t\t\tthrow new Error('Error fetching access token');\n\t\t\t});\n\t\t\t// if (!access_token_resp) throw new Error();\n\t\t\tconst access_token_resp_json = await access_token_resp.json();\n\t\t\t// const access_token_resp_json_shape = {\n\t\t\t// \temail: '[email protected]',\n\t\t\t// \texchanges: ['NFO', 'NSE', 'MCX', 'BCD', 'CDS', 'BFO', 'BSE'],\n\t\t\t// \tproducts: ['OCO', 'D', 'CO', 'I'],\n\t\t\t// \tbroker: 'UPSTOX',\n\t\t\t// \tuser_id: '8FA3BA',\n\t\t\t// \tuser_name: 'NIMISH SUDHIR RAJWADE',\n\t\t\t// \torder_types: ['MARKET', 'LIMIT', 'SL', 'SL-M'],\n\t\t\t// \tuser_type: 'individual',\n\t\t\t// \tpoa: false,\n\t\t\t// \tis_active: true,\n\t\t\t// \taccess_token: 'eyJ0eXAiOiJKV1QiLCJrZXlfaWQiOiJza192MS4wIiwiYWxnIjoiSFMyNTYifQ.eyJzdWIiOiI4RkEzQkEiLCJqdGkiOiI2NmJjZDY3YzQ5M2JmODMzNjVmZmIwYzMiLCJpc011bHRpQ2xpZW50IjpmYWxzZSwiaWF0IjoxNzIzNjUxNzA4LCJpc3MiOiJ1ZGFwaS1nYXRld2F5LXNlcnZpY2UiLCJleHAiOjE3MjM2NzI4MDB9.830eafX4W4hkg6--AALKmkxnbQk1c4HrVMmKm-BSrVQ',\n\t\t\t// \textended_token: null,\n\t\t\t// };\n\t\t\tif (!access_token_resp_json) throw new Error();\n\t\t\tif (!Object.prototype.hasOwnProperty.call(access_token_resp_json, 'access_token')) throw new Error();\n\t\t\t// console.log('Access token:', access_token_resp_json.access_token);\n\t\t\t//----------------------------------+\n\t\t\t//\tEND | THIS SHUD BE SERVER SIDE\t|\n\t\t\t//==================================+\n\t\t\treturn access_token_resp_json.access_token;\n\t\t} catch (err) {\n\t\t\treturn null;\n\t\t}\n\t}; */\n\n\t/**\n\t * Fetch access token by exchanging the auth code received from oAuth login with broker\n\t * @param {string} authCode - The auth code received from oAuth login with broker\n\t * @returns {Promise<?string>} Access token if fetch successful or NULL otherwise\n\t */\n\tconst _getAccessTokenUsingAuthCode = async (authCode) => {\n\t\tif (!authCode || typeof authCode !== 'string' || authCode.toString().trim() === '') return null;\n\t\ttry {\n\t\t\t// if (!authCode || typeof authCode !== 'string' || authCode.toString().trim() === '') throw new Error('Auth code not provided');\n\t\t\t/** @type {{s:1,at:'access_token'}|{s:0,m:'error message'}} */\n\t\t\tconst access_token_resp = await invokeFn('kaagzi-lambda-upstox-getAccessToken', {\n\t\t\t\tc: authCode,\n\t\t\t\ts: 'wa', //wa -- WebApp, we -- WebExtension\n\t\t\t});\n\t\t\tif (!access_token_resp) throw new Error();\n\t\t\tif (!Object.prototype.hasOwnProperty.call(access_token_resp, 's')) throw new Error(); //here check response status\n\t\t\tif (access_token_resp.s === 0) throw new Error(access_token_resp.m); //Show error returned by backend\n\t\t\tif (access_token_resp.s !== 1) throw new Error(); //If still the status isn't okay\n\n\t\t\tif (!Object.prototype.hasOwnProperty.call(access_token_resp, 'at')) throw new Error();\n\t\t\t// console.log('Access token:', access_token_resp.at);\n\t\t\treturn access_token_resp.at;\n\t\t} catch (err) {\n\t\t\tconsole.error(err.message || 'Error fetching access token from Upstox');\n\t\t\t// notify(err.message || 'Error fetching access token from Upstox', 'err');\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Given the access-token, fetch user profile from the broker and update storage and state\n\t * @param {string} upstoxAccessToken - The access token received from broker after exchanging authCode\n\t * @returns {Promise<Boolean>} TRUE if profie fetched successfully, FALSE otherwise\n\t */\n\tconst _fetchUserProfileData_n_update_storage_n_state = async (upstoxAccessToken) => {\n\t\ttry {\n\t\t\tconst profileResponse = await fetch('https://api.upstox.com/v2/user/profile', {\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: 'Bearer ' + upstoxAccessToken,\n\t\t\t\t\tAccept: 'application/json',\n\t\t\t\t},\n\t\t\t}).catch((err) => {\n\t\t\t\tthrow new Error('Error fetching profile data');\n\t\t\t});\n\t\t\tconst profileData = await profileResponse.json();\n\t\t\tif (profileData.status !== 'success') throw new Error('Error fetching profile data');\n\t\t\t// console.log('Upstox user profile data:', profileData.data);\n\n\t\t\t//here save it in localstorage\n\t\t\tlocalStorage.setItem(\n\t\t\t\t'upstoxUser',\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tatk: upstoxAccessToken,\n\t\t\t\t\tid: profileData.data.user_id,\n\t\t\t\t\tnm: profileData.data.user_name,\n\t\t\t\t\teml: profileData.data.email,\n\t\t\t\t\tt: Date.now(), //Math.floor(Date.now() / 1000), //login-time\n\t\t\t\t}),\n\t\t\t);\n\t\t\t//here update state\n\t\t\tsetAccessToken(upstoxAccessToken);\n\t\t\tsetId(profileData.data.user_id);\n\t\t\tsetName(profileData.data.user_name);\n\t\t\tsetEmail(profileData.data.email);\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t// /**\n\t// * Launches web auth flow and authenticates user\n\t// * @returns {Promise<?string>} ID-Token or NULL\n\t// */\n\t/* const launchWebAuthFlow_n_getToken = async () => {\n\t\t// console.log('redirect URL:', browser.identity.getRedirectURL());\n\t\t// https://fnfcjndgmmihmmjllhmflcdnnicflijp.chromiumapp.org/\n\t\tif (!isOnline) {\n\t\t\tnotify('Network unavailable', 'err');\n\t\t\treturn null;\n\t\t}\n\t\ttry {\n\t\t\tconst redirectUrl = await browser.identity.launchWebAuthFlow({\n\t\t\t\tinteractive: true,\n\t\t\t\turl: `https://api.upstox.com/v2/login/authorization/dialog?response_type=code&client_id=${\n\t\t\t\t\tprocess.env.Upstox_apiKey\n\t\t\t\t}&redirect_uri=${encodeURIComponent(browser.identity.getRedirectURL())}`,\n\t\t\t});\n\t\t\t// console.log('redirectUrl:', redirectUrl);\n\t\t\tif (!redirectUrl) throw new Error('Error getting redirect URL');\n\t\t\t// return _extractTokens(redirectUrl);\n\n\t\t\tlet m = redirectUrl.match(/[#?](.*)/);\n\t\t\tif (!m || m.length < 1) throw new Error();\n\t\t\tlet params = new URLSearchParams(m[1].split('#')[0]);\n\t\t\tconst auth_code = params.get('code');\n\t\t\tif (!auth_code) throw new Error();\n\t\t\tconsole.log('Auth code:', auth_code);\n\n\t\t\t//==================================+\n\t\t\t//\t\tTHIS SHUD BE SERVER SIDE\t|\n\t\t\t//----------------------------------+\n\t\t\tconst access_token_resp = await fetch('https://api.upstox.com/v2/login/authorization/token', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t\t\tAccept: 'application/json',\n\t\t\t\t},\n\t\t\t\tbody: `code=${auth_code}&client_id=${process.env.Upstox_apiKey}&client_secret=nrr1ml51yx&redirect_uri=${encodeURIComponent(\n\t\t\t\t\tbrowser.identity.getRedirectURL(),\n\t\t\t\t)}&grant_type=authorization_code`,\n\t\t\t}).catch((err) => {\n\t\t\t\tthrow new Error('Error fetching access token');\n\t\t\t});\n\t\t\t// if (!access_token_resp) throw new Error();\n\t\t\tconst access_token_resp_json = await access_token_resp.json();\n\t\t\t// const access_token_resp_json_shape = {\n\t\t\t// \temail: '[email protected]',\n\t\t\t// \texchanges: ['NFO', 'NSE', 'MCX', 'BCD', 'CDS', 'BFO', 'BSE'],\n\t\t\t// \tproducts: ['OCO', 'D', 'CO', 'I'],\n\t\t\t// \tbroker: 'UPSTOX',\n\t\t\t// \tuser_id: '8FA3BA',\n\t\t\t// \tuser_name: 'NIMISH SUDHIR RAJWADE',\n\t\t\t// \torder_types: ['MARKET', 'LIMIT', 'SL', 'SL-M'],\n\t\t\t// \tuser_type: 'individual',\n\t\t\t// \tpoa: false,\n\t\t\t// \tis_active: true,\n\t\t\t// \taccess_token: 'eyJ0eXAiOiJKV1QiLCJrZXlfaWQiOiJza192MS4wIiwiYWxnIjoiSFMyNTYifQ.eyJzdWIiOiI4RkEzQkEiLCJqdGkiOiI2NmJjZDY3YzQ5M2JmODMzNjVmZmIwYzMiLCJpc011bHRpQ2xpZW50IjpmYWxzZSwiaWF0IjoxNzIzNjUxNzA4LCJpc3MiOiJ1ZGFwaS1nYXRld2F5LXNlcnZpY2UiLCJleHAiOjE3MjM2NzI4MDB9.830eafX4W4hkg6--AALKmkxnbQk1c4HrVMmKm-BSrVQ',\n\t\t\t// \textended_token: null,\n\t\t\t// };\n\t\t\tif (!access_token_resp_json) throw new Error();\n\t\t\tif (!Object.prototype.hasOwnProperty.call(access_token_resp_json, 'access_token')) throw new Error();\n\t\t\tconsole.log('Access token:', access_token_resp_json.access_token);\n\t\t\t//----------------------------------+\n\t\t\t//\tEND | THIS SHUD BE SERVER SIDE\t|\n\t\t\t//==================================+\n\n\t\t\t//here fetch user profile\n\t\t\tconst profileResponse = await fetch('https://api.upstox.com/v2/user/profile', {\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: 'Bearer ' + access_token_resp_json.access_token,\n\t\t\t\t\tAccept: 'application/json',\n\t\t\t\t},\n\t\t\t}).catch((err) => {\n\t\t\t\tthrow new Error('Error fetching profile data');\n\t\t\t});\n\t\t\tconst profileData = await profileResponse.json();\n\t\t\tif (profileData.status !== 'success') throw new Error('Error fetching profile data');\n\t\t\tconsole.log('Upstox user profile data:', profileData.data);\n\t\t\tsetAccessToken(access_token_resp_json.access_token);\n\t\t\tsetId(profileData.data.user_id);\n\t\t\tsetName(profileData.data.user_name);\n\t\t\tsetEmail(profileData.data.email);\n\n\t\t\t//here maybe save it in webextension storage\n\t\t\tawait browser.storage.local.set({\n\t\t\t\tupstoxUser: {\n\t\t\t\t\tatk: access_token_resp_json.access_token,\n\t\t\t\t\tid: profileData.data.user_id,\n\t\t\t\t\tnm: profileData.data.user_name,\n\t\t\t\t\teml: profileData.data.email,\n\t\t\t\t\tt: Date.now() / 1000, //login-time\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tconsole.error(err.message || 'Error while authenticating! Kindly re-login');\n\t\t\treturn null;\n\t\t}\n\t}; */\n\n\t/**\n\t * Checks if user is stored in localstorage and updates state\n\t * @returns {Promise<(UpstoxUserDataStored|false)>} Logged-in Upstox user-data or FALSE if no user is logged-in\n\t */\n\tconst chkStoredUpstoxUser_n_updateState = async () => {\n\t\tconst storedUpstoxUserReadResultObj = localStorage.getItem('upstoxUser'); //await browser.storage.local.get('upstoxUser');\n\t\tif (!storedUpstoxUserReadResultObj) {\n\t\t\t// console.log('No logged-in Upstox user');\n\t\t\t_reset();\n\t\t\treturn false;\n\t\t}\n\n\t\t/** @type {UpstoxUserDataStored} */\n\t\tconst upstoxUserData = JSON.parse(storedUpstoxUserReadResultObj);\n\t\t//here check last-login timestamp (ie when the data was stored in storage) and check if it isn't before 3:30 AM (as per Upstox, access tokens are valid until 3:30 AM0)\n\t\tif (!_isAccessTokenStillAlive(upstoxUserData.t)) {\n\t\t\t_reset();\n\t\t\tlocalStorage.removeItem('upstoxUser');\n\t\t\treturn false;\n\t\t}\n\n\t\t//here update state\n\t\tsetAccessToken(upstoxUserData.atk);\n\t\tsetId(upstoxUserData.id);\n\t\tsetName(upstoxUserData.nm);\n\t\t// console.log('upstoxUserData.nm:', upstoxUserData.nm);\n\t\tsetEmail(upstoxUserData.eml);\n\n\t\treturn upstoxUserData;\n\t};\n\n\t/** Checks if access token is valid for today.\n\t * If time right now is past 3:30 AM IST, then we check if last token fetch time is anytime past 3:30 AM\n\t * If time right now is before 3:30 AM, then we check if last token fetch time is anytime past 3:30 AM of yesterday.\n\t * @param {number} [lastTokenFetchTimestampMs] - Epoch in milliseconds. If not specified, fn tries to read from localstorage\n\t * @returns {Boolean} TRUE if token is valid, FALSE otherwise\n\t */\n\tconst _isAccessTokenStillAlive = (lastTokenFetchTimestampMs) => {\n\t\ttry {\n\t\t\t//here if 'lastTokenFetchTimestampMs' is not provided, then try reading it from storage\n\t\t\tif (!lastTokenFetchTimestampMs) {\n\t\t\t\tconst storedUpstoxUserReadResultObj = localStorage.getItem('upstoxUser'); //await browser.storage.local.get('upstoxUser');\n\t\t\t\tif (storedUpstoxUserReadResultObj) {\n\t\t\t\t\t/** @type {UpstoxUserDataStored} */\n\t\t\t\t\tconst upstoxUserData = JSON.parse(storedUpstoxUserReadResultObj);\n\t\t\t\t\tif (Object.prototype.hasOwnProperty.call(upstoxUserData, 't') && !isNaN(upstoxUserData.t)) lastTokenFetchTimestampMs = upstoxUserData.t;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!lastTokenFetchTimestampMs) return false; //if still 'lastTokenFetchTimestampMs' is undefined, return false\n\t\t\t// console.log('token fetch ts:', new Date(lastTokenFetchTimestampMs).toLocaleString());\n\n\t\t\t//here check epoch\n\t\t\t//Chat GPT prompt:\n\t\t\t//write a javascript function that accepts a epoch in ms and returns a boolean given the following condition:\n\t\t\t//If current time is more than 3:30 AM, today, the function checks if the argument epoch is not less than today 3:30 am. If it is less than today 3:30 am, then returns FALSE, else returns TRUE.\n\t\t\t//If the current time is less than 3:30 AM, today, the function checks if the argument epoch is not less than yesterday 3:30 am. If it is less than yesterday 3:30 am, then returns false, else returns true\n\t\t\t// Get the current time\n\t\t\t// const now = new Date();\n\t\t\tconst indiaDateNow = new Date(new Date().toLocaleString('en-US', { timeZone: 'Asia/Kolkata' }));\n\t\t\t// console.log('indiaDateNow:', indiaDateNow.toLocaleString());\n\n\t\t\t// Create a date object for today at 3:30 AM in India\n\t\t\tconst indiaToday330AM = new Date(indiaDateNow);\n\t\t\tindiaToday330AM.setHours(3, 30, 0, 0);\n\t\t\t// console.log('indiaToday3:30AM:', indiaToday330AM.toLocaleString());\n\n\t\t\t// Create a date object for yesterday at 3:30 AM in India\n\t\t\tconst indiaYesterday330AM = new Date(indiaToday330AM);\n\t\t\tindiaYesterday330AM.setDate(indiaYesterday330AM.getDate() - 1);\n\n\t\t\t// Convert the epoch time to a date object\n\t\t\t// const lastTokenFetchDate = new Date(lastTokenFetchTimestampMs);\n\t\t\t//adjust it for india standard time\n\t\t\tconst lastTokenFetchDateAsPerIndia = new Date(new Date(lastTokenFetchTimestampMs).toLocaleString('en-US', { timeZone: 'Asia/Kolkata' }));\n\t\t\t// console.log('token fetch as per India ts:', lastTokenFetchDateAsPerIndia.toLocaleString());\n\n\t\t\t// Check the current time and compare with the epoch time\n\t\t\tif (indiaDateNow >= indiaToday330AM) {\n\t\t\t\t// If current time is past 3:30 AM today\n\t\t\t\treturn lastTokenFetchDateAsPerIndia >= indiaToday330AM;\n\t\t\t\t// return lastTokenFetchDateAsPerIndia >= indiaToday330AM ? Number(lastTokenFetchTimestampMs) : false;\n\t\t\t} else {\n\t\t\t\t// If current time is before 3:30 AM today\n\t\t\t\treturn lastTokenFetchDateAsPerIndia >= indiaYesterday330AM;\n\t\t\t\t// return lastTokenFetchDateAsPerIndia >= indiaYesterday330AM ? Number(lastTokenFetchTimestampMs) : false;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/** Checks if access token is still alive and not expired\n\t * Useful before making API calls to Upstox (including websocket)\n\t * @returns {Boolean} TRUE if still valid, FALSE if expired\n\t */\n\tconst checkIfAccessTokenIsAlive = () => {\n\t\tconst isAlive = _isAccessTokenStillAlive();\n\t\tif (!isAlive) {\n\t\t\t_reset();\n\t\t\tlocalStorage.removeItem('upstoxUser');\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t};\n\n\t// /** Logs user out of Upstox\n\t// * @returns {Promise<boolean>} TRUE upon successfully logging out\n\t// */\n\t/* const logOut = async () => {\n\t\tif (!accessToken) return false;\n\t\ttry {\n\t\t\tconst logoutResponse = await fetch('https://api.upstox.com/v2/logout', {\n\t\t\t\tmethod: 'DELETE',\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: 'Bearer ' + accessToken,\n\t\t\t\t\tAccept: 'application/json',\n\t\t\t\t},\n\t\t\t\t// body: '',\n\t\t\t}).catch((err) => {\n\t\t\t\tthrow new Error();\n\t\t\t});\n\t\t\tconst logoutResponseData = await logoutResponse.json();\n\t\t\tif (logoutResponseData.status !== 'success' || !logoutResponseData.data) throw new Error();\n\t\t\t_reset();\n\t\t\t//here clear localstorage\n\t\t\t// await browser.storage.local.remove('upstoxUser');\n\t\t\tlocalStorage.removeItem('upstoxUser');\n\t\t\tnotify('Successfully logged out of Upstox');\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\t// console.error(err);\n\t\t\tnotify('Error logging out of Upstox', 'err');\n\t\t\treturn false;\n\t\t}\n\t}; */\n\n\t/** Logs user out of Upstox */\n\tconst logOut = () => {\n\t\t//invalidate access token\n\t\tif (accessToken) {\n\t\t\tfetch('https://api.upstox.com/v2/logout', {\n\t\t\t\tmethod: 'DELETE',\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: 'Bearer ' + accessToken,\n\t\t\t\t\tAccept: 'application/json',\n\t\t\t\t},\n\t\t\t\t// body: '',\n\t\t\t})\n\t\t\t\t.then((resp) => resp.json())\n\t\t\t\t.then(({ status }) => {\n\t\t\t\t\tstatus === 'success' && notify('Successfully logged out of Upstox', 'success');\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tnotify('Logged out of Upstox');\n\t\t\t\t});\n\t\t}\n\t\t//logout\n\t\t_reset();\n\t\tlocalStorage.removeItem('upstoxUser');\n\t};\n\n\t/**\n\t * We listen for message containing aauth code from the oAuth popup\n\t * @param {!{origin,data}} event - Storage Event\n\t */\n\tconst _handleMsgFromAuthPopup = (event) => {\n\t\t// if (event.origin !== 'http://localhost:8000') return;\n\t\tif (!event.source.location.href.startsWith('https://kaagzi.in/app/upstox/welcome')) return; //only entertain incoming messages from the popup\n\n\t\t// console.log('msg from popup', event);\n\t\t// console.log('msging window location', event.source.location.href);\n\t\tevent.source.close(); //close the popup window\t//we close() in the popup page too, but still do it here irrespectively\n\t\tauthWindowRef.current = null;\n\t\ttry {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(event.data, 'authCode')) throw new Error();\n\t\t\t//here fetch access token\n\t\t\t(async () => {\n\t\t\t\ttry {\n\t\t\t\t\t//here show WIP loading\n\t\t\t\t\tsetIsSigningInWip(true);\n\t\t\t\t\tconst upstoxAccessToken = await _getAccessTokenUsingAuthCode(event.data.authCode);\n\t\t\t\t\tif (!upstoxAccessToken) throw new Error('Error fetching access token from Upstox');\n\t\t\t\t\tconst fetchProfileAndLogin = await _fetchUserProfileData_n_update_storage_n_state(upstoxAccessToken);\n\t\t\t\t\tif (!fetchProfileAndLogin) throw new Error('Error fetching user profile from Upstox');\n\t\t\t\t\tnotify('Successfully logged into Upstox', 'success');\n\t\t\t\t} catch (err) {\n\t\t\t\t\tnotify(err.message || 'Error while signing into Upstox', 'err');\n\t\t\t\t} finally {\n\t\t\t\t\tsetIsSigningInWip(false);\n\t\t\t\t}\n\t\t\t})();\n\t\t} catch (err) {\n\t\t\tnotify('Error while signing into Upstox', 'err');\n\t\t}\n\t\t// finally {\n\t\t// \t//here maybe clear any popup polling timer\n\t\t// }\n\t};\n\n\t/**\n\t * We listen for any messages from the content-script\n\t * @param {!{origin,data:{action,msgFlowDirection:'contentScript-to-webPage'}}} event - Post message Event\n\t */\n\tconst _handleMsgsFromContentScript = (event) => {\n\t\tif (event.source != window) return; // We only accept messages from ourselves, (ie sent by the same window object the content-script is running in)\n\t\tif (!event.origin.startsWith('http://localhost:') && event.origin !== 'https://kaagzi.in') {\n\t\t\t// console.warn('Does not accept incoming messages from ' + event.origin + ' origin');\n\t\t\treturn;\n\t\t}\n\t\t//here also chk if message is from content-script to webpage and not the other way around\n\t\tif (!Object.prototype.hasOwnProperty.call(event.data, 'msgFlowDirection')) return;\n\t\tif (event.data.msgFlowDirection !== 'contentScript-to-webPage') return;\n\n\t\tif (!Object.prototype.hasOwnProperty.call(event.data, 'action')) return;\n\t\tswitch (event.data.action) {\n\t\t\tcase 'upstoxUserUpdated':\n\t\t\t\t//The content-script would have already written the updated data to the localstorage\n\t\t\t\t(async () => {\n\t\t\t\t\tawait chkStoredUpstoxUser_n_updateState();\n\t\t\t\t})();\n\t\t\t\tbreak;\n\t\t\t// case 'userSignedOut':\n\t\t\t// \tsignOut(true);\n\t\t\t// \tbreak;\n\t\t\t// default:\n\t\t\t// \t//do something default\n\t\t\t// \tconsole.log('User_ContextProvider received message from content-script with foll action: ' + event.data.action);\n\t\t}\n\t};\n\n\tuseEffect(() => {\n\t\twindow.addEventListener('message', _handleMsgFromAuthPopup);\n\t\twindow.addEventListener('message', _handleMsgsFromContentScript);\n\t\treturn () => {\n\t\t\twindow.removeEventListener('message', _handleMsgFromAuthPopup);\n\t\t\twindow.removeEventListener('message', _handleMsgsFromContentScript);\n\t\t};\n\t}, []); //runs only on mount\n\n\tuseEffect(() => {\n\t\t(async () => {\n\t\t\tawait chkStoredUpstoxUser_n_updateState();\n\t\t})();\n\t}, [isOnline]); //runs on mount and then whenever isOnline changes\n\n\treturn (\n\t\t<>\n\t\t\t{id !== null && accessToken !== null ? (\n\t\t\t\t<UpstoxUserContext.Provider\n\t\t\t\t\tvalue={{ id, name, email, accessToken, checkIfAccessTokenIsAlive, chkIfUpstoxUserIsLoggedIn: chkStoredUpstoxUser_n_updateState, logOut }}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</UpstoxUserContext.Provider>\n\t\t\t) : (\n\t\t\t\t// <div id={styles.noUserWrap}>\n\t\t\t\t// \t<Button onClick={launchWebAuthFlow_n_getToken}>Sign into Angel One</Button>\n\t\t\t\t// \t<LinkButton to={browser.runtime.getURL('app/appChooser/index.html')} variant=\"tertiary\">\n\t\t\t\t// \t\tChoose different broker\n\t\t\t\t// \t</LinkButton>\n\t\t\t\t// </div>\n\t\t\t\t<>\n\t\t\t\t\t<BrokerLogin\n\t\t\t\t\t\tbroker=\"Upstox\"\n\t\t\t\t\t\tdoOnLoginClick={openAuthWindow}\n\t\t\t\t\t\t// referralUrlForNewSignupWithBroker=\"https://link.upstox.com/FxPt9MAeYxPsRSnS9\"\n\t\t\t\t\t\treferralUrlForNewSignupWithBroker={process.env.GATSBY_UPSTOX_REFERRAL_LINK}\n\t\t\t\t\t/>\n\t\t\t\t\t{isSigningInWip && <Loading note=\"Signing into Upstox\" />}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","import React, { createContext, useRef, useEffect, useContext, useState } from 'react';\n\nimport Loading from '@components/ui/Loading';\nimport { NetworkCheckContext } from '@providers/NetworkAvailabilityCheck';\nimport { UserContext } from '@providers/User';\nimport { UpstoxUserContext } from '@upstoxProviders/UpstoxUser';\n\n//==================+\n//\t\tTYPES\t\t|\n//==================+\n/** Selective attributes from the Instrument object representing the columns of the master CSV data\n * @typedef {import('@types_upstox').UpstoxInstrument_selective} UpstoxInstrument_selective\n */\n\n//==================+\n//\t\tCONTEXT\t\t|\n//==================+\n\n/** React context for downloaded master data */\nexport const UpstoxMasterDataContext = createContext({\n\t/** @type {Boolean} */\n\tisMasterDataReady: false,\n\n\t/** In child components we can watch for when this changes in order to update it's own state by refetching current data\n\t * @type {?Number}\n\t */\n\tmasterDataEpochTimestamp: null,\n\n\t// getInstrumentTokensForTradingInstruments: () => {},\n\n\t/**\n\t * Read an instrument stored in IndexedDb Upstox Master Data\n\t * @param {Exchange} exchange The exchange the instrument belongs to\n\t * @param {string} tradingsymbol Trading symbol (Primary Key ID used in the table)\n\t * @returns {Promise<?UpstoxInstrument_selective>} Instrument object or NULL\n\t */\n\tgetInstrument: async (exchange, tradingsymbol) => {}, //eslint-disable-line\n\n\t// /**\n\t// * Given an array of Instrument IDs (IndexedDb Key), returns array of instrument objs stored in IndexedDb Upstox Master Data\n\t// * @param {string[]} keysAry Array of primary Key ID in the form 'tradingsymbol:exchange'\n\t// * @returns {Promise<?{instruments:Instrument[],instrumentsNotFound:string[]}>} Object with array of Instrument objects and the keys for which no items were found OR NULL\n\t// */\n\t/**\n\t * Given an array of Instrument IDs (IndexedDb Key), returns array of instrument objs stored in IndexedDb Upstox Master Data\n\t * @param {{'exchange_name':string[]}} exchangeSymbolsObj Object with keys as the exchange name and each key has value as array of 'tradingsymbol' (primary Key ID)\n\t * @returns {Promise<?{'exchange_name':{instrumentsFound:UpstoxInstrument_selective[],instrumentsNotFound:string[]}}>} Object with keys as the exchange name and each key has an object as it's value. Where the object hos two properties 'instrumentsFound' holding array of instruments and 'instrumentsNotFound' holding trading_symbols of instruments not found\n\t */\n\tgetInstruments: async (exchangeSymbolsObj) => {}, //eslint-disable-line\n\n\t/**\n\t * For each exchange, given an array of Instrument tradingsymbol (IndexedDb Key), returns an obj with 'tradingsymbol:exchange' as property and instrument_token as value\n\t * @param {{'exchange_name':string[]}} exchangeSymbolsObj Object with keys as the exchange name and each key has value as array of 'tradingsymbol' (primary Key ID)\n\t * @returns {Promise<?{instrumentsAndTheirToken:{'tradingsymbol1:exchange':'instrument_token','tradingsymbol2:exchange':'instrument_token'},instrumentsNotFound:{symbol:string,exchange:('NSE'|'BSE'|'NFO'|'MCX'|'CDS')}}}>} Instrument tokens for each of the instruments given by tradingsymbol and exchange\n\t */\n\tgetTokenForInstruments: async (exchangeSymbolsObj) => {}, //eslint-disable-line\n\n\t/**\n\t * Query search instruments from master data\n\t * @param {Exchange} exchange The exchange within which to search for the instrument\n\t * @param {string} queryPrefix\n\t * @param {?Number} [limit=20]\n\t * @returns {Promise<?UpstoxInstrument_selective[]>}\n\t */\n\tsearchInstruments: async (exchange, queryPrefix, limit) => {}, //eslint-disable-line\n});\n\n//======================+\n//\t\tCOMPONENT\t\t|\n//======================+\n\n/** Provider component for downloaded master data.\n * We use IndexedDB to store data for offline access.\n * @see {@link https://javascript.info/indexeddb}\n * @see {@link https://web.dev/indexeddb}\n */\nexport default function UpstoxMasterData_ContextProvider({ children }) {\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [isMasterDataReady, setIsMasterDataReady] = useState(false);\n\tconst [masterDataEpochTimestamp, setMasterDataEpochTimestamp] = useState(null); //in child components we can watch for when this changes in order to update it's own state with current data\n\n\t// const dbRef = useRef(null); //we do not store it in a normal 'var' so as for it to persist across re-renders, kindoff like a static value\n\n\tconst isOnline = useContext(NetworkCheckContext);\n\tconst { id: kaagziUserId } = useContext(UserContext);\n\tconst { id: upstoxUserId, accessToken } = useContext(UpstoxUserContext);\n\n\tconst dbRef = useRef(null);\n\n\tconst currentDbStoreVer = 1; //if there are any changes to the DB structure, we can increment this\n\n\t/** @type {['NSE', 'BSE', 'NFO', 'CDS', 'MCX']} Array of exchanges we download master data for */\n\tconst exchangesAry = ['NSE', 'BSE', 'NFO', 'CDS', 'MCX'];\n\n\t/**\n\t * Sets up & initializes IndexedDB client and saves it as static for reuse later\n\t * @returns {Promise<?IDBDatabase>} IndexedDB handle or DOMException error.\n\t */\n\tasync function __setupIfNotAlreadyAndGetDbHandle() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t//check if a DB handle is already stored\n\t\t\tif (dbRef.current?.constructor.name == 'IDBDatabase') {\n\t\t\t\tif (dbRef.current?.name === 'UpstoxMasterData') {\n\t\t\t\t\treturn resolve(dbRef.current); //if the stored DB is the one that we req, then return it\n\t\t\t\t} else {\n\t\t\t\t\t//close any other open DB connections (Mostly this could be of different user logged-in before the current user has just loggen-in)\n\t\t\t\t\tdbRef.current?.close?.(); //since anyhow we shall be only allowing one single user logged-in at any given time, and that user shall have one single DB\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//setup DB if not already\n\t\t\tconst openRequest = indexedDB.open('UpstoxMasterData', currentDbStoreVer); //openRequest.construstor.name == IDBOpenDBRequest\n\n\t\t\t//EVENTS\n\t\t\topenRequest.onupgradeneeded = (event) => {\n\t\t\t\t//only fired when an attempt was made to open a database with a version number higher than its current version, or if no database existed before\n\t\t\t\tdbRef.current = openRequest.result; //same as 'event.target.result'\t//had we not required it below to get 'dbRef.current.objectStoreNames' we need not have required to assign it here since we do it in the 'onsuccess' event\n\n\t\t\t\t// check existing db version\n\t\t\t\tif (event.oldVersion === 0) {\n\t\t\t\t\t// version 0 means that the client had no database\n\t\t\t\t\t// perform initialization\n\n\t\t\t\t\t// if (!dbRef.current.objectStoreNames.contains('NSE')) {\n\t\t\t\t\t// \t//dbRef.current.createObjectStore('instruments', { keyPath: 'id' }); // here we specify the column-name to tell what it should use as primary-key (weve named it as 'id' as short for instrumentId)\n\t\t\t\t\t// \t////so now, when adding or updating items, we need not specify the 'key' explicitely\n\t\t\t\t\t// \tdbRef.current.createObjectStore('instruments');\n\t\t\t\t\t// }\n\t\t\t\t\t// //the 'metaData' table shall be used to store any meta data related to master data, for eg, last data fetch timestamp (since this data needs to be refreshed each trading day)\n\t\t\t\t\t// if (!dbRef.current.objectStoreNames.contains('metaData')) {\n\t\t\t\t\t// \tdbRef.current.createObjectStore('metaData'); // note that in this case, we do not tell it to use inline keys from the data by opting not to specify the keyPath\n\t\t\t\t\t// }\n\t\t\t\t\t[...exchangesAry, 'metaData'].forEach((storeName) => {\n\t\t\t\t\t\tif (!dbRef.current.objectStoreNames.contains(storeName)) dbRef.current.createObjectStore(storeName);\n\t\t\t\t\t});\n\t\t\t\t} else if (event.oldVersion > 0 && event.oldVersion < currentDbStoreVer) {\n\t\t\t\t\t// client had old version\n\t\t\t\t\t// update\n\t\t\t\t\t[...exchangesAry, 'metaData'].forEach((storeName) => {\n\t\t\t\t\t\tdbRef.current.createObjectStore(storeName);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t};\n\n\t\t\topenRequest.onerror = () => {\n\t\t\t\treject(openRequest.error);\n\t\t\t};\n\n\t\t\topenRequest.onsuccess = (event) => {\n\t\t\t\t//fired after 'onupgradeneeded()' and if no errors while opening\n\t\t\t\tdbRef.current = openRequest.result; //event.target.result;\n\t\t\t\tdbRef.current.onversionchange = () => {\n\t\t\t\t\t//installs the onversionchange handler, that triggers if the current database connection becomes outdated (db version is updated elsewhere) and closes the connection\n\t\t\t\t\tdbRef.current.close();\n\t\t\t\t\tdbRef.current = null;\n\t\t\t\t\tconsole.warn('Master database is outdated, please reload the page');\n\t\t\t\t};\n\t\t\t\tdbRef.current.onclose = () => {\n\t\t\t\t\t//fires only if the DB connection is unexpectedly closed\n\t\t\t\t\tdbRef.current = null; // console.log(\"Database connection closed\");\n\t\t\t\t};\n\t\t\t\t// console.log('typeof dbRef.current:', typeof dbRef.current);\t\t\t\t\t//object\n\t\t\t\t// console.log('dbRef.current.constructor.name:', dbRef.current.constructor.name);\t\t//IDBDatabase\n\t\t\t\t// the db is ready, continue working with database using dbRef.current object\n\n\t\t\t\t// resolve(openRequest.result);\n\t\t\t\tresolve(dbRef.current);\n\t\t\t};\n\t\t});\n\t}\n\n\t/**\n\t * Initiates a transaction after getting handle to DB\n\t * @param {(string|string[])} tableOrTablesAry ObjectStore or array of ObjectStores\n\t * @param {IDBTransactionMode} mode Mode of transaction\n\t * @returns {Promise<?IDBTransaction>} IndexedDb Transaction\n\t */\n\tconst _withDbTransaction = async (tableOrTablesAry, mode) => {\n\t\tif (!tableOrTablesAry) return null;\n\t\tif (typeof tableOrTablesAry === 'string' && tableOrTablesAry.trim() === '') return null;\n\t\tif (!['readonly', 'readwrite', 'versionchange'].includes(mode)) return null;\n\t\ttry {\n\t\t\tconst db = await __setupIfNotAlreadyAndGetDbHandle();\n\t\t\tif (!db) return null;\n\n\t\t\t//check if table exists in DB\n\t\t\tconst tables = db.objectStoreNames; //https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/objectStoreNames\n\t\t\tif (tables.length < 1) return null; //since we do not have any tables configured in this DB\n\t\t\tconst tablesAry = Array.from(tables); //since, db.objectStoreNames return DOMStringList and not Array, we convert it to array\n\t\t\tif (Array.isArray(tableOrTablesAry)) {\n\t\t\t\tfor (var i = 0; i < tableOrTablesAry.length; i++) {\n\t\t\t\t\tif (!tablesAry.includes(tableOrTablesAry[i])) throw new Error('The ' + tableOrTablesAry[i] + ' table does not exist in cache database');\n\t\t\t\t}\n\t\t\t} else if (typeof tableOrTablesAry === 'string') {\n\t\t\t\tif (!tablesAry.includes(tableOrTablesAry)) throw new Error('The ' + tableOrTablesAry + ' table does not exist in cache database');\n\t\t\t}\n\t\t\treturn db.transaction(tableOrTablesAry, mode);\n\t\t} catch (err) {\n\t\t\tconsole.error(err.message);\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/** Clears all tables in the 'UpstoxMasterData' IndexedDB database\n\t * @returns {Promise<boolean>} TRUE if clearing successful. FALSE otherwise.\n\t */\n\tconst _clearAllTables = async () => {\n\t\tconst db = await __setupIfNotAlreadyAndGetDbHandle();\n\t\tif (!db) return false;\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tconst tables = db.objectStoreNames; //https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/objectStoreNames\n\t\t\t\tif (tables.length < 1) return resolve(true); //since we do not have any tables to clear\n\n\t\t\t\tconst tablesAry = Array.from(tables); //since, db.objectStoreNames return DOMStringList and not Array, we convert it to array\n\n\t\t\t\tconst transaction = db.transaction(tablesAry, 'readwrite'); //https://developer.chrome.com/blog/defining-scope-In-indexeddb-transactions/\n\n\t\t\t\ttransaction.onabort = () => {\n\t\t\t\t\treject(transaction.error);\n\t\t\t\t};\n\t\t\t\ttransaction.oncomplete = () => {\n\t\t\t\t\tresolve(true);\n\t\t\t\t};\n\n\t\t\t\ttablesAry.forEach((table) => {\n\t\t\t\t\t// let clearRequest = transaction.objectStore(table).clear();\t// clear the storage\n\t\t\t\t\t// clearRequest.onerror = (event) => { reject(`Error clearing '${table}' cache`); };\n\t\t\t\t\t// clearRequest.onsuccess = () => {resolve();};\t//this may prematurely resolve promise before next ir=teration inside loop\n\t\t\t\t\ttransaction.objectStore(table).clear();\n\t\t\t\t\t// console.log(`Cleared ${table} cache`);\n\t\t\t\t});\n\t\t\t\t// resolve(true);\n\t\t\t} catch (err) {\n\t\t\t\treject();\n\t\t\t}\n\t\t});\n\t};\n\n\t/** Checks if master data is valid for today.\n\t * If time right now is past 7:30 AM, then we check if last download time is anytime past 7:30 AM\n\t * If time right now is before 7:30 AM, then we check if last download time is anytime past 7:30 AM of yesterday.\n\t * As per Upstox, their master data refresehes each day around 6 AM.\n\t * @returns {Promise<(number|false)>} If data is valid for the time, epoch timestamp for when the stored data was fetched, FALSE otherwise\n\t * @see {@link https://upstox.com/developer/api-documentation/instruments/}\n\t */\n\tconst _checkIfMasterDataValidForToday = async () => {\n\t\ttry {\n\t\t\t// const db = await __setupIfNotAlreadyAndGetDbHandle();\n\t\t\t// if (!db) return false;\n\n\t\t\t// //check if table exists in DB\n\t\t\t// const tables = db.objectStoreNames; //https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/objectStoreNames\n\t\t\t// if (tables.length < 1) return false; //reject(); //since we do not have any tables configured in this DB\n\t\t\t// const tablesAry = Array.from(tables); //since, db.objectStoreNames return DOMStringList and not Array, we convert it to array\n\t\t\t// if (!tablesAry.includes('metaData')) throw new Error(\"Master data reading failed! The 'metaData' table does not exist in cache database\"); //reject(`Write failed! The 'metaData' table does not exist in database`);\n\n\t\t\t// const transaction = db.transaction('metaData', 'readonly');\n\t\t\tconst transaction = await _withDbTransaction('metaData', 'readonly');\n\n\t\t\tconst request = transaction.objectStore('metaData').get('masterData_dl_timestamp');\n\t\t\tconst lastDlEpoch = await new Promise((resolve, reject) => {\n\t\t\t\trequest.onerror = () => reject(request.error);\n\t\t\t\trequest.onsuccess = () => {\n\t\t\t\t\tif (request.result !== undefined) {\n\t\t\t\t\t\tresolve(request.result);\n\t\t\t\t\t} else reject(false);\n\t\t\t\t};\n\t\t\t});\n\t\t\tif (!lastDlEpoch) return false;\n\n\t\t\t//here check epoch\n\t\t\t//Chat GPT prompt:\n\t\t\t//write a javascript function that accepts a epoch in ms and returns a boolean given the following condition:\n\t\t\t//If current time is more than 7:30 AM, today, the function checks if the argument epoch is not less than today 7:30 am. If it is less than today 7:30 am, then returns FALSE, else returns TRUE.\n\t\t\t//If the current time is less than 7:30 AM, today, the function checks if the argument epoch is not less than yesterday 7:30 am. If it is less than yesterday 7:30 am, then returns false, else returns true\n\t\t\t// Get the current time\n\t\t\tconst now = new Date();\n\n\t\t\t// Create a date object for today at 7:30 AM\n\t\t\tconst today730AM = new Date();\n\t\t\ttoday730AM.setHours(7, 30, 0, 0);\n\n\t\t\t// Create a date object for yesterday at 7:30 AM\n\t\t\tconst yesterday730AM = new Date(today730AM);\n\t\t\tyesterday730AM.setDate(yesterday730AM.getDate() - 1);\n\n\t\t\t// Convert the epoch time to a date object\n\t\t\tconst lastDlEpochDate = new Date(lastDlEpoch);\n\n\t\t\t// Check the current time and compare with the epoch time\n\t\t\tif (now >= today730AM) {\n\t\t\t\t// If current time is more than 7:30 AM today\n\t\t\t\t// return lastDlEpochDate >= today730AM;\n\t\t\t\treturn lastDlEpochDate >= today730AM ? Number(lastDlEpoch) : false;\n\t\t\t} else {\n\t\t\t\t// If current time is less than 7:30 AM today\n\t\t\t\t// return lastDlEpochDate >= yesterday730AM;\n\t\t\t\treturn lastDlEpochDate >= yesterday730AM ? Number(lastDlEpoch) : false;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/** Fetches master data and updates IndexedDB.\n\t * The tradingsymbol is used as the key and the data is stored as CSV row value.\n\t * @returns {Promise<?Date>} Returns date object for when this data is being fetched\n\t */\n\tconst _fetchMasterDataAndUpdateInDb = async () => {\n\t\tif (isLoading) return false;\n\t\ttry {\n\t\t\tsetIsLoading(true);\n\t\t\t// browser.runtime.sendMessage({ action: 'upstoxMasterData_isDownloading' });\n\t\t\t// if (!isOnline) return false;\n\t\t\t//here we can first do some checks for if data already exists\n\n\t\t\t// const response = await fetch('https://margincalculator.angelbroking.com/OpenAPI_File/files/OpenAPIScripMaster.json');\n\t\t\t// const masterDataAry = await response.json();\n\t\t\t// if (!masterDataAry) throw new Error('Error fetching AngelOne master data');\n\n\t\t\t/** @type {{tradingsymbol,segment,csvRowData}[][]} An array of arrays, each containing parsed data*/\n\t\t\tconst fetchRespAry = await Promise.all(\n\t\t\t\t// exchangesAry.map(async (exchange) => {\n\t\t\t\t['NSE', 'BSE', 'MCX'].map(async (exchange) => {\n\t\t\t\t\t//NFO is listed in same data as NSE and maybe CDS is listed in same data as BSE\n\t\t\t\t\tconst response = await fetch(`https://nimworks.github.io/market-data/upstox/${exchange}.csv.gz`, {\n\t\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t// Accept: 'application/gzip',\n\t\t\t\t\t\t\t'Accept-Encoding': 'gzip',\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tconst blobObj = await response.blob();\n\t\t\t\t\t/////\n\t\t\t\t\t//https://stackoverflow.com/questions/36185110/is-there-a-way-to-use-browsers-native-gzip-decompression-using-javascript\n\t\t\t\t\t//https://developer.chrome.com/blog/compression-streams-api\n\t\t\t\t\t//https://developer.mozilla.org/en-US/docs/Web/API/Compression_Streams_API\n\t\t\t\t\tconst ds = new DecompressionStream('gzip');\n\t\t\t\t\tconst decompressedStream = blobObj.stream().pipeThrough(ds);\n\t\t\t\t\tconst csvTxtData = await new Response(decompressedStream).text();\n\t\t\t\t\t// Parse the CSV string\n\t\t\t\t\tconst rows = csvTxtData.trim().split('\\n');\n\t\t\t\t\trows.shift(); //remove the header row\n\t\t\t\t\t//return an array\n\t\t\t\t\treturn rows.map((row) => {\n\t\t\t\t\t\tconst columns = row.split(',');\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttradingsymbol: columns[1], // Assuming 'tradingsymbol' is the 2nd column\n\t\t\t\t\t\t\tsegment: columns[0].split('|')[0], // Infer 'segment' from the instrument_key which shall be of the format 'segment|isin'\n\t\t\t\t\t\t\tcsvRowData: row,\n\t\t\t\t\t\t};\n\t\t\t\t\t});\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (!fetchRespAry) throw new Error('Error fetching Upstox master data');\n\n\t\t\t//here clear all tables\n\t\t\tawait _clearAllTables();\n\t\t\tsetIsMasterDataReady(false);\n\n\t\t\tconst transaction = await _withDbTransaction([...exchangesAry, 'metaData'], 'readwrite');\n\t\t\tconst nseTable = transaction.objectStore('NSE'),\n\t\t\t\tbseTable = transaction.objectStore('BSE'),\n\t\t\t\tnfoTable = transaction.objectStore('NFO'),\n\t\t\t\tcdsTable = transaction.objectStore('CDS'),\n\t\t\t\tmcxTable = transaction.objectStore('MCX');\n\t\t\t// console.log('masterDataAry', masterDataAry.length);\n\n\t\t\tfetchRespAry.forEach((itemsAry, index) => {\n\t\t\t\t// const table = transaction.objectStore(exchangesAry[index]);\n\t\t\t\t// itemsAry.forEach((item) => {\n\t\t\t\t// \ttable.put(item.data, item.tradingsymbol);\n\t\t\t\t// });\n\t\t\t\titemsAry.forEach((item) => {\n\t\t\t\t\tconst { tradingsymbol, segment, csvRowData } = item;\n\t\t\t\t\t//for NSE instruments, only save the 'EQ' ie equity type instruments and ignore other like BL\n\t\t\t\t\tif (segment === 'NSE_EQ') nseTable.put(`${csvRowData},NSE`, tradingsymbol);\n\t\t\t\t\tif (segment === 'BSE_EQ') bseTable.put(`${csvRowData},BSE`, tradingsymbol);\n\t\t\t\t\tif (segment === 'NSE_FO') nfoTable.put(`${csvRowData},NFO`, tradingsymbol);\n\t\t\t\t\t// if (segment === 'BSE_FO') nfoTable.put(`${csvRowData},NFO`, tradingsymbol);\n\t\t\t\t\tif (segment === 'NCD_FO') cdsTable.put(`${csvRowData},CDS`, tradingsymbol);\n\t\t\t\t\t// if (segment === 'BCD_FO') cdsTable.put(`${csvRowData},CDS`, tradingsymbol);\n\t\t\t\t\tif (segment === 'MCX_FO') mcxTable.put(`${csvRowData},MCX`, tradingsymbol);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tconst metaDataTable = transaction.objectStore('metaData');\n\n\t\t\tconst epochTimestamp = Date.now();\n\t\t\tmetaDataTable.put(epochTimestamp, 'masterData_dl_timestamp');\n\n\t\t\tsetIsMasterDataReady(true);\n\t\t\tsetMasterDataEpochTimestamp(epochTimestamp);\n\t\t\tsetIsLoading(false);\n\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\ttransaction.onabort = () => reject(transaction.error);\n\t\t\t\ttransaction.oncomplete = () => resolve(true);\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tconsole.error(err.message);\n\t\t\tsetIsLoading(false);\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/**\n\t * Checks if data exists or is valid for today and refetches if necessary\n\t * @returns {Promise<Boolean>} TRUE if valid and loaded, FALSE in case of any error\n\t */\n\tconst _checkValidityAndReFetchIfNecessary = async () => {\n\t\ttry {\n\t\t\tconst lastDownloadEpoch = await _checkIfMasterDataValidForToday(); //here check IndexedDB 'metaData' table to know when the master data was last downloaded\n\t\t\tif (!lastDownloadEpoch) {\n\t\t\t\t//if data either does not exist or is old\n\t\t\t\tif (isLoading) return false;\n\t\t\t\tconsole.log('Loading Upstox master data');\n\t\t\t\t// setIsLoading(true);\n\t\t\t\t// isDownloading = true;\n\t\t\t\tawait _fetchMasterDataAndUpdateInDb(); //if master data was not downloaded before or is from any day before today, we clear the tables and redownload master data and update meta data\n\t\t\t\t//.finally(() => {\n\t\t\t\t// \t// setIsLoading(false);\n\t\t\t\t// \tisDownloading = false;\n\t\t\t\t// });\n\t\t\t} else {\n\t\t\t\tconsole.log('Upstox master data already loaded and valid');\n\t\t\t\tsetIsMasterDataReady(true);\n\t\t\t}\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/**\n\t * Parses the CSV data stored in IndexedDb into JSON object\n\t * @param {string} csvLine CSV string\n\t * @returns {?UpstoxInstrument_selective}\n\t */\n\tconst _upstoxInstrumentData_csvToObj = (csvLine) => {\n\t\ttry {\n\t\t\tconst data = csvLine.split(',');\n\t\t\tif (data.length !== 7) return null;\n\t\t\treturn {\n\t\t\t\ttoken: data[0],\n\t\t\t\tsymbol: data[1],\n\t\t\t\tname: data[2],\n\t\t\t\texpiry: data[3],\n\t\t\t\tlotsize: data[4],\n\t\t\t\tinstrumenttype: data[5],\n\t\t\t\tsegment: data[6],\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tconsole.error(err.message);\n\t\t}\n\t};\n\n\t//------------------------------+\n\t//\t\tEXPORTED METHODS\t\t|\n\t//------------------------------+\n\n\t/**\n\t * Read an instrument stored in IndexedDb Upstox Master Data\n\t * @param {('NSE'|'BSE'|'NFO'|'CDS'|'MCX')} exchange The exchange the instrument belongs to\n\t * @param {string} tradingsymbol Trading symbol (Primary Key ID used in the table)\n\t * @returns {Promise<?UpstoxInstrument_selective>} Instrument object or NULL\n\t */\n\tconst getInstrument = async (exchange, tradingsymbol) => {\n\t\t// if (!isReady) return null;\n\t\tif (!tradingsymbol || typeof tradingsymbol !== 'string') return null;\n\t\tif (tradingsymbol.trim() === '') return null;\n\t\ttry {\n\t\t\tconst chkValidityAndRefetchIfReqSts = await _checkValidityAndReFetchIfNecessary();\n\t\t\tif (!chkValidityAndRefetchIfReqSts) return null;\n\n\t\t\tconst transaction = await _withDbTransaction(exchange, 'readonly');\n\t\t\tif (!transaction) return null;\n\t\t\tconst request = transaction.objectStore(exchange).get(tradingsymbol);\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\trequest.onerror = () => reject(request.error);\n\t\t\t\trequest.onsuccess = () => {\n\t\t\t\t\tif (request.result !== undefined) {\n\t\t\t\t\t\t//here we parse the CSV into object data\n\t\t\t\t\t\t// resolve(request.result);\n\t\t\t\t\t\tconst instrumentObjFromCsv = _upstoxInstrumentData_csvToObj(request.result);\n\t\t\t\t\t\tif (!instrumentObjFromCsv) reject(null);\n\t\t\t\t\t\tresolve(instrumentObjFromCsv);\n\t\t\t\t\t} else reject(null);\n\t\t\t\t};\n\t\t\t});\n\t\t} catch (err) {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * For each exchange, given an array of Instrument tradingsymbol (IndexedDb Key), returns array of instrument objs stored in IndexedDb Kite Master Data\n\t * @param {{'exchange_name':string[]}} exchangeSymbolsObj Object with keys as the exchange name and each key has value as array of 'tradingsymbol' (primary Key ID)\n\t * @returns {Promise<?{instrumentsFound:UpstoxInstrument_selective[],instrumentsNotFound:{symbol:string,exchange:string}[]}>} Instruments that were found from across all requested exchanges\n\t */\n\tconst getInstruments = async (exchangeSymbolsObj) => {\n\t\t// if (!isReady) return null;\n\t\tif (!exchangeSymbolsObj) return null;\n\t\tif (typeof exchangeSymbolsObj !== 'object') return null;\n\t\tconst reqExchangesAry = Object.keys(exchangeSymbolsObj);\n\t\tif (reqExchangesAry.length < 1) return null;\n\t\ttry {\n\t\t\tconst chkValidityAndRefetchIfReqSts = await _checkValidityAndReFetchIfNecessary();\n\t\t\tif (!chkValidityAndRefetchIfReqSts) return null;\n\n\t\t\tconst transaction = await _withDbTransaction(reqExchangesAry, 'readonly'); //since objectstores are named after the exchanges itself\n\t\t\tif (!transaction) return null;\n\n\t\t\tconst instrumentsFound = []; //instruments found in table\n\t\t\tconst instrumentsNotFound = []; //instruments not found in table\n\n\t\t\t/** @type {true[]} */\n\t\t\tconst allTablesReadRespAry = await Promise.all(\n\t\t\t\t//array of promises for each table (ie exchange)\n\t\t\t\treqExchangesAry.map(async (exchange) => {\n\t\t\t\t\t//the exchange name is the table name in our IndexedDB\n\t\t\t\t\tif (!exchangesAry.includes(exchange)) return false; //read from the exchange tables for eg NSE, BSE, NFO..\n\t\t\t\t\tconst table = transaction.objectStore(exchange);\n\n\t\t\t\t\t//array of promises for the specified 'symbols' to get instrument data for, within the 'exchange'\n\t\t\t\t\tconst allItemsReadAry = await Promise.all(\n\t\t\t\t\t\texchangeSymbolsObj[exchange].map((tradingSymbol_PK) => {\n\t\t\t\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\t\t\t\tconst request = table.get(tradingSymbol_PK);\n\t\t\t\t\t\t\t\trequest.onsuccess = () => {\n\t\t\t\t\t\t\t\t\t// console.log('request.result for ' + tradingSymbol_PK + ' :', request.result);\n\t\t\t\t\t\t\t\t\tif (!request.result) {\n\t\t\t\t\t\t\t\t\t\tinstrumentsNotFound.push({ symbol: tradingSymbol_PK, exchange });\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tconst instrumentObjFromCsv = _upstoxInstrumentData_csvToObj(request.result);\n\t\t\t\t\t\t\t\t\t\t// if (!instrumentObjFromCsv) reject(null);\n\t\t\t\t\t\t\t\t\t\tinstrumentsFound.push(instrumentObjFromCsv);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\trequest.onerror = () => {\n\t\t\t\t\t\t\t\t\tinstrumentsNotFound.push({ symbol: tradingSymbol_PK, exchange });\n\t\t\t\t\t\t\t\t\t// reject('Error retrieving instrument with key: ' + key);\n\t\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\treturn true; // return { instrumentsFound, instrumentsNotFound };\n\t\t\t\t}),\n\t\t\t);\n\t\t\t// console.log({ instrumentsFound, instrumentsNotFound });\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\ttransaction.onabort = () => reject(transaction.error);\n\t\t\t\ttransaction.oncomplete = () => resolve({ instrumentsFound, instrumentsNotFound });\n\t\t\t});\n\t\t} catch (err) {\n\t\t\t// console.error(err);\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * For each exchange, given an array of Instrument tradingsymbol (IndexedDb Key), returns an obj with 'tradingsymbol:exchange' as property and instrument_token as value\n\t * @param {{'exchange_name':string[]}} exchangeSymbolsObj Object with keys as the exchange name and each key has value as array of 'tradingsymbol' (primary Key ID)\n\t * @returns {Promise<?{instrumentsAndTheirToken:{'tradingsymbol1:exchange':'instrument_token','tradingsymbol2:exchange':'instrument_token'},instrumentsNotFound:{symbol:string,exchange:('NSE'|'BSE'|'NFO'|'MCX'|'CDS')}}}>} Instrument tokens for each of the instruments given by tradingsymbol and exchange\n\t */\n\tconst getTokenForInstruments = async (exchangeSymbolsObj) => {\n\t\t// if (!isReady) return null;\n\t\tif (!exchangeSymbolsObj) return null;\n\t\tif (typeof exchangeSymbolsObj !== 'object') return null;\n\t\tconst reqExchangesAry = Object.keys(exchangeSymbolsObj);\n\t\tif (reqExchangesAry.length < 1) return null;\n\t\ttry {\n\t\t\tconst chkValidityAndRefetchIfReqSts = await _checkValidityAndReFetchIfNecessary();\n\t\t\tif (!chkValidityAndRefetchIfReqSts) return null;\n\n\t\t\tconst transaction = await _withDbTransaction(reqExchangesAry, 'readonly'); //since objectstores are named after the exchanges itself\n\t\t\tif (!transaction) return null;\n\n\t\t\tconst instrumentsAndTheirToken = {}; //tokens for each instrument found in that exchange (ie table)\n\t\t\tconst instrumentsNotFound = []; //instruments not found in table\n\n\t\t\t/** @type {true[]} */\n\t\t\tconst allTablesReadRespAry = await Promise.all(\n\t\t\t\t//array of promises for each table (ie exchange)\n\t\t\t\treqExchangesAry.map(async (exchange) => {\n\t\t\t\t\t//the exchange name is the table name in our IndexedDB\n\t\t\t\t\tif (!exchangesAry.includes(exchange)) return false; //read from the exchange tables for eg NSE, BSE, NFO..\n\t\t\t\t\tconst table = transaction.objectStore(exchange);\n\n\t\t\t\t\t//array of promises for the specified 'symbols' to get instrument data for, within the 'exchange'\n\t\t\t\t\tconst allItemsReadAry = await Promise.all(\n\t\t\t\t\t\texchangeSymbolsObj[exchange].map((tradingSymbol_PK) => {\n\t\t\t\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\t\t\t\tconst request = table.get(tradingSymbol_PK);\n\t\t\t\t\t\t\t\trequest.onsuccess = () => {\n\t\t\t\t\t\t\t\t\tif (request.result !== undefined) {\n\t\t\t\t\t\t\t\t\t\tconst { symbol, segment, token } = _upstoxInstrumentData_csvToObj(request.result);\n\t\t\t\t\t\t\t\t\t\t// if (!instrumentObjFromCsv) reject(null);\n\t\t\t\t\t\t\t\t\t\t// instrumentsFound.push(instrumentObjFromCsv);\n\t\t\t\t\t\t\t\t\t\tinstrumentsAndTheirToken[`${symbol}:${segment}`] = token;\n\t\t\t\t\t\t\t\t\t\t// resolve();\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tinstrumentsNotFound.push({ symbol: tradingSymbol_PK, exchange });\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\trequest.onerror = () => {\n\t\t\t\t\t\t\t\t\t// instrumentsNotFound.push(`${tradingSymbol_PK}:${exchange}`);\n\t\t\t\t\t\t\t\t\t// // reject('Error retrieving instrument with key: ' + key);\n\t\t\t\t\t\t\t\t\treject();\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\treturn true; // return { instrumentsFound, instrumentsNotFound };\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\ttransaction.onabort = () => reject(transaction.error);\n\t\t\t\t// transaction.oncomplete = () => resolve(instrumentsAndTheirToken);\n\t\t\t\ttransaction.oncomplete = () => resolve({ instrumentsAndTheirToken, instrumentsNotFound });\n\t\t\t});\n\t\t} catch (err) {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Query search instruments from master data\n\t * @param {Exchanges} exchange The exchange within which to search for the instrument\n\t * @param {string} queryPrefix\n\t * @param {?Number} [limit=20]\n\t * @returns {Promise<?UpstoxInstrument_selective[]>}\n\t */\n\tconst searchInstruments = async (exchange, queryPrefix, limit) => {\n\t\t// if (!isReady) return null; //if data isn't downloaded yet\n\t\tif (queryPrefix.trim() === '') return null;\n\t\tqueryPrefix = queryPrefix.toUpperCase();\n\t\tif (!limit || !Number.isInteger(Number(limit))) limit = 20;\n\t\t// console.log('searchInstruments():', 'Begin search');\n\t\ttry {\n\t\t\tconst chkValidityAndRefetchIfReqSts = await _checkValidityAndReFetchIfNecessary();\n\t\t\tif (!chkValidityAndRefetchIfReqSts) return null;\n\t\t\t// console.log('searchInstruments():', 'abt to open transaction');\n\t\t\t// const db = await __setupIfNotAlreadyAndGetDbHandle();\n\t\t\t// if (!db) return null;\n\n\t\t\t// //check if table exists in DB\n\t\t\t// const tables = db.objectStoreNames; //https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/objectStoreNames\n\t\t\t// if (tables.length < 1) return false; //reject(); //since we do not have any tables configured in this DB\n\t\t\t// const tablesAry = Array.from(tables); //since, db.objectStoreNames return DOMStringList and not Array, we convert it to array\n\t\t\t// if (!tablesAry.includes('instruments')) throw new Error(\"Master data reading failed! The 'instruments' table does not exist in cache database\"); //reject(`Write failed! The 'metaData' table does not exist in database`);\n\n\t\t\t// const transaction = db.transaction('instruments', 'readonly');\n\t\t\tconst transaction = await _withDbTransaction(exchange, 'readonly');\n\n\t\t\treturn await new Promise((resolve, reject) => {\n\t\t\t\ttry {\n\t\t\t\t\t// const store = transaction.objectStore('instruments');\n\t\t\t\t\t// const keyRange = IDBKeyRange.bound(queryPrefix, queryPrefix + '\\uffff');\n\t\t\t\t\t// const cursorRequest = store.openCursor(keyRange);\n\t\t\t\t\tconst cursorRequest = transaction.objectStore(exchange).openCursor(IDBKeyRange.bound(queryPrefix, queryPrefix + '\\uffff'));\n\t\t\t\t\t// const cursorRequest = transaction.objectStore('instruments').openCursor(IDBKeyRange.bound(queryPrefix, queryPrefix + 'z'));\n\t\t\t\t\tconst instruments = [];\n\t\t\t\t\tlet count = 0; // Counter for the number of collected entries\n\n\t\t\t\t\tcursorRequest.onsuccess = (e) => {\n\t\t\t\t\t\t// console.log('cursorRequest.onsuccess = (e):', e);\n\t\t\t\t\t\tconst cursor = e.target.result;\n\t\t\t\t\t\t// console.log('cursor', cursor);\n\t\t\t\t\t\tif (cursor && count < limit) {\n\t\t\t\t\t\t\tif (cursor.key.startsWith(queryPrefix)) {\n\t\t\t\t\t\t\t\t// instruments.push(cursor.value);\n\t\t\t\t\t\t\t\tconst instrumentObjFromCsv = _upstoxInstrumentData_csvToObj(cursor.value);\n\t\t\t\t\t\t\t\tinstrumentObjFromCsv && instruments.push(instrumentObjFromCsv);\n\t\t\t\t\t\t\t\t// console.log('cursor.value:', cursor.value);\n\t\t\t\t\t\t\t\tcount++; // Increment the counter\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcursor.continue(); //continue to next item\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// No more matching records or limit reached\n\t\t\t\t\t\t\tresolve(instruments);\n\t\t\t\t\t\t\t// console.log(instruments);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// transaction.oncomplete = () => {\n\t\t\t\t\t// \tresolve(instruments);\n\t\t\t\t\t// \tconsole.log(instruments);\n\t\t\t\t\t// };\n\n\t\t\t\t\tcursorRequest.onerror = (e) => {\n\t\t\t\t\t\treject(e);\n\t\t\t\t\t};\n\t\t\t\t} catch (err) {\n\t\t\t\t\treject(err.message);\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (err) {\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t//==========================+\n\t//\t\t\t\t\t\t\t|\n\t//\t\tEFFECT-HOOKS\t\t|\n\t//\t\t\t\t\t\t\t|\n\t//==========================+\n\n\tuseEffect(() => {\n\t\tif (!isOnline) return;\n\t\tif (!kaagziUserId && !upstoxUserId) return; //proceed to chk and download master-data only if user is logged into both, Kaagzi and Zerodha Kite\n\t\t(async () => {\n\t\t\tawait _checkValidityAndReFetchIfNecessary();\n\t\t})();\n\t}, [isOnline, kaagziUserId, upstoxUserId]); //runs on first mount and then when either isOnline, kaagziUserId or kiteUserId changes\n\n\treturn (\n\t\t<UpstoxMasterDataContext.Provider\n\t\t\tvalue={{\n\t\t\t\tisMasterDataReady,\n\t\t\t\tmasterDataEpochTimestamp,\n\t\t\t\t// getInstrumentTokensForTradingInstruments,\n\t\t\t\tgetInstrument,\n\t\t\t\tgetInstruments,\n\t\t\t\tgetTokenForInstruments,\n\t\t\t\tsearchInstruments,\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t\t{isLoading && <Loading note=\"Setting Up! May take time\" coverFullPage={true} />}\n\t\t</UpstoxMasterDataContext.Provider>\n\t);\n}\n","/*global process*/\nimport React, { createContext, useContext, useEffect, useRef, useState } from 'react';\n\nimport { NetworkCheckContext } from '@providers/NetworkAvailabilityCheck';\nimport { UpstoxUserContext } from '@upstoxProviders/UpstoxUser';\n\nexport const UpstoxWebSocketContext = createContext({\n\t// isAlive: false, // if we stop receiving heartbeat from server, we set this to false after setTimeout\n\n\t/** @type {boolean} Toggles between FALSE and TRUE upon receiving tick data from WebSocket. Preferred instead of a counter */\n\ttick: false,\n\n\t/**\tQuotes for subscribed instruments updated by WebSocket for NSE exchange\n\t * @type {Object.<string, {ltp:number,cp:number }>}\n\t */\n\tquotes: {},\n\n\t/**\n\t * Subscribes to quotes (if not already)\n\t * @param {string[]} instrumentTokenAry - An array of instrument tokens\n\t * @returns {Promise<boolean>}\n\t */\n\tsubscribeToQuotes: (instrumentTokenAry) => {}, //eslint-disable-line\n\n\t/**\n\t * Unsubscribes the given instruments from websocket quotes\n\t * @param {string[]} instrumentTokenAry - An array of instrument tokens\n\t * @returns {Boolean} TRUE in case request to unsubscribe sent successfully. FALSE otherwise\n\t */\n\tunsubscribeToQuotes: (instrumentTokenAry) => {}, //eslint-disable-line\n});\n\n/** Upstox WebSocket provider component */\nexport default function UpstoxWebSocket_ContextProvider({ children }) {\n\tconst [isAlive, setIsAlive] = useState(false);\n\tconst [tick, setTick] = useState(false); //shall toggle between FALSE and TRUE upon receiving tick data from WebSocket. Preferred instead of a counter\n\t// const [quotes, setQuotes] = useState(/** @type {Object.<number, {ltp:number,cp:number }>}*/ ({}));\n\n\t//we maintain this global var which we can directly manipulate since when adding to the 'quotes' object we might need to make a clone of it\n\t//but since when initiating the state, we set an empty object {}, 'quotes' shall always point to that original empty obj reference in memory\n\t//so we actually cannot use it to clone since it shall always be empty (as was when initiating)\n\t//thus we use below var to first manipulate the object and then set the state\n\t// const quotesBasket = useRef(/** @type {Object.<number, {ltp:number,cp:number }>}*/ ({}));\n\n\tconst quotesBasket = useRef(/** @type {Object.<string, {ltp:number,cp:number }>}*/ ({}));\n\n\tconst isOnline = useContext(NetworkCheckContext);\n\tconst { id: upstoxUserId, accessToken, checkIfAccessTokenIsAlive } = useContext(UpstoxUserContext);\n\n\t/** @type {{current:?WebSocket}} */\n\tconst webSocketRef = useRef(null);\n\t// const heartbeatIntervalRef = useRef(null);\n\n\t// /** Instruments already subscribed to\n\t// * @type {{current:number[]|[]}}\n\t// */\n\t// const subscribedInstruments = useRef([]);\n\n\t// const sendHeartbeat = () => {\n\t// \t//if (webSocketRef.current?.readyState === WebSocket.OPEN) {\n\t// \tif (webSocketRef.current?.readyState === 1) {\n\t// \t\twebSocketRef.current.send('ping');\n\t// \t}\n\t// };\n\t// Function to stop the heartbeat ticker\n\t// function stopHeartbeat() {\n\t// \tclearInterval(heartbeatIntervalRef.current);\n\t// }\n\n\t/**\n\t * Gets handle to the already created WebSocket or creates a new one if it does not alread exist\n\t * @returns {Promise<?WebSocket>}\n\t */\n\tconst _createSocketConnection = async () => {\n\t\tif (!isOnline) return null;\n\t\tif (!accessToken) return null;\n\t\tif (webSocketRef.current?.readyState === 1 && checkIfAccessTokenIsAlive()) return webSocketRef.current; //a previously created WS connection is still alive / open\n\n\t\tconst wsUrlFetchResp_raw = await fetch('https://api.upstox.com/v2/feed/market-data-feed/authorize', {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\tAccept: 'application/json',\n\t\t\t\tAuthorization: 'Bearer ' + accessToken,\n\t\t\t},\n\t\t});\n\t\tconst wsUrlFetchResp = await wsUrlFetchResp_raw.json();\n\n\t\tif (!Object.prototype.hasOwnProperty.call(wsUrlFetchResp, 'status')) return null;\n\t\tif (wsUrlFetchResp.status !== 'success') return null;\n\t\tif (!Object.prototype.hasOwnProperty.call(wsUrlFetchResp, 'data')) return null;\n\t\tif (!Object.prototype.hasOwnProperty.call(wsUrlFetchResp.data, 'authorized_redirect_uri')) return null;\n\t\tconst wsUrl = wsUrlFetchResp.data.authorized_redirect_uri;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tif (!isOnline) return reject(null);\n\t\t\tif (!accessToken) return reject(null);\n\t\t\ttry {\n\t\t\t\t//if (webSocketRef.current?.readyState === 1) resolve(webSocketRef.current); //a previously created WS connection is still alive / open\n\t\t\t\t///// fetch websocket URL\n\n\t\t\t\tconst socket = new WebSocket(wsUrl); //always prefer wss://\n\t\t\t\tsocket.onopen = () => {\n\t\t\t\t\tsetIsAlive(true); //since it has just been opened\n\t\t\t\t\twebSocketRef.current = socket;\n\t\t\t\t\t// console.log('Socket connection established')\n\t\t\t\t\t//_startLifeTimer();\n\n\t\t\t\t\t// //here start heartbeat\n\t\t\t\t\t// webSocketRef.current.send('ping');\n\t\t\t\t\t// heartbeatIntervalRef.current && clearInterval(heartbeatIntervalRef.current);\n\t\t\t\t\t// heartbeatIntervalRef.current = setInterval(() => {\n\t\t\t\t\t// \t//if (webSocketRef.current?.readyState === WebSocket.OPEN) {\n\t\t\t\t\t// \tif (webSocketRef.current?.readyState === 1) {\n\t\t\t\t\t// \t\twebSocketRef.current.send('ping');\n\t\t\t\t\t// \t}\n\t\t\t\t\t// }, 29000); // 29 seconds in milliseconds\n\n\t\t\t\t\t/////\n\t\t\t\t\tresolve(socket);\n\t\t\t\t};\n\t\t\t\tsocket.onclose = (e) => {\n\t\t\t\t\t// eslint-disable-line no-unused-vars -- we haven't used the 'event' obj available to us\n\t\t\t\t\t// if(e.wasClean){\n\t\t\t\t\t// \t//console.log(`[close] Connection closed cleanly, code=${e.code} reason=${e.reason}`);\n\t\t\t\t\t// } else {\n\t\t\t\t\t// \t// e.g. server process killed or network down | event.code is usually 1006 in this case\n\t\t\t\t\t// \t//console.error('[close] Connection died');\n\t\t\t\t\t// \t//here we try reconnecting after setInterval\n\t\t\t\t\t// }\n\t\t\t\t\tsetIsAlive(false);\n\t\t\t\t\t// setTick(0);\n\t\t\t\t\twebSocketRef.current = null;\n\t\t\t\t\t//clearTimeout(wsLifeTimer);\n\t\t\t\t\t// //here stop heartbeat\n\t\t\t\t\t// clearInterval(heartbeatIntervalRef.current);\n\t\t\t\t\treject(null);\n\t\t\t\t};\n\t\t\t\tsocket.onerror = () => {\n\t\t\t\t\tif (socket.readyState !== 1) {\n\t\t\t\t\t\t//meaning socket is not open\t//https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState\n\t\t\t\t\t\tsetIsAlive(false);\n\t\t\t\t\t\t// setTick(0);\n\t\t\t\t\t\twebSocketRef.current = null;\n\t\t\t\t\t\t// clearInterval(heartbeatIntervalRef.current);\n\t\t\t\t\t}\n\t\t\t\t\t// reject();\n\t\t\t\t};\n\t\t\t\tsocket.onmessage = (e) => {\n\t\t\t\t\tsetIsAlive(true);\n\t\t\t\t\t//_extendLifeTimeout();\t// here we clear setTimeout that resets 'isAlive' to false\n\t\t\t\t\t__doOnWebSocketResponse(e.data);\n\t\t\t\t};\n\t\t\t\t//webSocketRef.current = socket;\n\t\t\t} catch (err) {\n\t\t\t\t// console.error(err);\n\t\t\t\tsetIsAlive(false);\n\t\t\t\treject(null);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst closeSocketConnection = () => {\n\t\twebSocketRef.current?.close();\n\t\twebSocketRef.current = null;\n\t\tsetIsAlive(false); //although this is handled in onclose event of websocket, we do it here too\n\t\t// //shut down the heart-beat timer\n\t\t// clearInterval(heartbeatIntervalRef.current);\n\t};\n\n\t// const __doOnWebSocketResponse = (respData) => {\n\t// \t//console.log(`WS resp type: ${respData.constructor.name}`);\n\t// \t//console.log(JSON.parse(respData));\n\t// \tif (respData.constructor.name != 'Blob') return; //few msgs would be in 'String' type which we can parse as JSON\n\t// \t//console.log('Size in bytes:',respData.size);\n\t// \tif (respData.size <= 1) return; //we ignore the 1-byte heartbeat sent by server to keep connection alive\t//or maybe use that to set a flag to tell us that con is alive\n\t// \trespData.arrayBuffer().then((aryBufr) => {\n\t// \t\t// const chunk = new Int32Array(aryBufr);\t//new Int16Array(buffer, byteOffset, length)\n\t// \t\t// console.log('Num packets:',chunk);\n\t// \t\t//console.log('ArrayBuffer size:',aryBufr.byteLength,'bytes');\n\t// \t\tif (aryBufr.byteLength <= 2) return;\n\t// \t\tconst view = new DataView(aryBufr); //ArrayBuffer, byte-offset!, byte-length!\n\n\t// \t\tlet seekOffset = 0;\n\t// \t\tconst numPackets = view.getUint16(seekOffset); //read first 2 bytes\n\t// \t\t// console.log('Number of packets:',numPackets);\n\t// \t\tseekOffset += 2;\n\n\t// \t\t// let newQuotes = {};\n\t// \t\t// let subscribedQuotesAry = [];\n\n\t// \t\tconsole.log('OriObj keys before cloning:', Object.keys(quotes));\n\t// \t\t// let newQuotesObj = quotes;//this actually store the obj as a reference instead of cloning it\n\t// \t\t//https://www.freecodecamp.org/news/clone-an-object-in-javascript/\n\t// \t\t// let newQuotesObj = { ...quotes }; //clones the original object\n\t// \t\t// let newQuotesObj = Object.assign({}, quotes); //same as above, clones properties into new object\n\t// \t\t//above methods would only do shallow copy but since we have sub-objects as values,we need to de deep copy\n\t// \t\tconst newQuotesObj = JSON.parse(JSON.stringify(quotes));\n\n\t// \t\tconsole.log('newQuotesObj keys after cloning:', Object.keys(newQuotesObj));\n\n\t// \t\tfor (var i = 0; i < numPackets; i++) {\n\t// \t\t\t//read each packet\n\t// \t\t\t//const packetLength = view.getUint16(seekOffset);\n\t// \t\t\tseekOffset += 2;\n\t// \t\t\tconst instrumentToken = view.getUint32(seekOffset);\n\t// \t\t\tseekOffset += 4;\n\t// \t\t\tconst ltp = view.getInt32(seekOffset); //although ltp can't b negative, we still do not use unsigned-integer\n\t// \t\t\tseekOffset += 4;\n\t// \t\t\tconst closePrice = view.getInt32(seekOffset); //although close price can't b negative, we still do not use unsigned-integer\n\t// \t\t\tseekOffset += 4; //not needed since we have reached end of reading data\n\n\t// \t\t\t//console.log('Packet length:',packetLength,' | tk:',instrumentToken,' | ltp:',ltp/100,' | close:',closePrice/100);\n\t// \t\t\t//console.table({'Packet size':packetLength,'Instrument token':instrumentToken,'LTP':ltp/100,'Close price':closePrice/100});\n\t// \t\t\tnewQuotesObj[instrumentToken] = { ltp: ltp / 100, cp: closePrice / 100 };\n\t// \t\t}\n\t// \t\t//console.table(newQuotesObj);\n\t// \t\tsetQuotes(newQuotesObj);\n\t// \t\tconsole.log('KiteWebSocket Newly set quotes:', Object.keys(newQuotesObj));\n\t// \t\t//optionally here broadcast via channel to other tabs\n\t// \t});\n\t// };\n\tconst __doOnWebSocketResponse = (respData) => {\n\t\ttry {\n\t\t\t//copy ws response as hex using chrome and paste in -- https://hexed.it/\n\t\t\t//console.log(`WS resp type: ${respData.constructor.name}`);\n\t\t\t//console.log(JSON.parse(respData));\n\t\t\tif (respData.constructor.name != 'Blob') return; //few msgs would be in 'String' type which we can parse as JSON\n\t\t\t//console.log('Size in bytes:',respData.size);\n\t\t\t// const totalBytes = respData.size;\n\t\t\tif (respData.size <= 1) return; //we ignore the 1-byte heartbeat sent by server to keep connection alive\t//or maybe use that to set a flag to tell us that con is alive\n\t\t\trespData.arrayBuffer().then((aryBufr) => {\n\t\t\t\t// const chunk = new Int32Array(aryBufr);\t//new Int16Array(buffer, byteOffset, length)\n\t\t\t\t// console.log('Num packets:',chunk);\n\t\t\t\t//console.log('ArrayBuffer size:',aryBufr.byteLength,'bytes');\n\t\t\t\tconst totalBytes = aryBufr.byteLength;\n\t\t\t\tif (totalBytes <= 2) return; //no need here, since we already check for skipping heartbeat above\n\t\t\t\tconst view = new DataView(aryBufr); //ArrayBuffer, byte-offset!, byte-length!\n\n\t\t\t\t//--------------------------------------+\n\t\t\t\t//\tTRIAL READING OF FIRST INSTRUMENT\t|\n\t\t\t\t//--------------------------------------+\n\t\t\t\t// //const nextBytes = view.getUint8(1);\t//read the 2nd byte (at offset 1)\t//seemingly tells us about how many bytes next constitute the instrument data\n\t\t\t\t// //const strLength = view.getUint8(3);\t//read the 4th byte (at offset 3)\t//seemingly tells about the number of next text bytes\n\t\t\t\t// let textBytes = new Uint8Array(aryBufr, 4, 19); //19 bytes starting from offset 4\n\t\t\t\t// let token = String.fromCharCode.apply(null, textBytes).trim(); //replace(/\\0/g, ''); // Remove null delimiters\n\t\t\t\t// let ltp = Number(view.getFloat64(28, true)); //jump to reading LTP //we convert it to number before performing arithmatic ops using it\n\t\t\t\t// let closePrice = Number(view.getFloat64(46, true)); //jump to reading close-price\n\t\t\t\t// console.log('WS quote token:', token, ' | ltp: ', ltp, ' | cp:', closePrice);\n\t\t\t\t// quotesBasket.current[token] = { ltp: ltp, cp: closePrice };\n\n\t\t\t\t// const numInstruments = Math.floor(totalBytes / 54); //since each instrument occupies 54 bytes\n\t\t\t\t// let seekOffset = 0;\n\t\t\t\t// for (var i = 0; i < numInstruments; i++) {\n\t\t\t\t// \tseekOffset += 4;\n\t\t\t\t// \tlet textBytes = new Uint8Array(aryBufr, seekOffset, 19); //19 bytes starting from seekOffset\n\t\t\t\t// \tlet token = String.fromCharCode.apply(null, textBytes); //.trim(); //replace(/\\0/g, ''); // Remove null delimiters\n\t\t\t\t// \tseekOffset += 24; //19 (from above reading op) + 5\n\t\t\t\t// \tlet ltp = Number(view.getFloat64(seekOffset, true)); //jump to reading LTP //we convert it to number before performing arithmatic ops using it\n\t\t\t\t// \tseekOffset += 18; //8 (from above reading op) + 10\n\t\t\t\t// \tlet closePrice = Number(view.getFloat64(seekOffset, true)); //jump to reading close-price\n\t\t\t\t// \tseekOffset += 8; //8 (from above reading op)\t//in prep for next loop iteration\n\t\t\t\t// \t// console.log('WS quote token:', token, ' | ltp: ', ltp, ' | cp:', closePrice);\n\t\t\t\t// \tquotesBasket.current[token] = { ltp: ltp, cp: closePrice };\n\t\t\t\t// }\n\n\t\t\t\tlet seekOffset = 0;\n\t\t\t\tif (view.getUint8(0) === 8 && view.getUint8(1) === 1) seekOffset = 2;\n\t\t\t\t//the first 2 bytes are not present in the first incoming msg after we send() a msg.\n\t\t\t\t//These are present in the tick updates. We read the bytes and skip to offset accordingly\n\t\t\t\twhile (seekOffset < totalBytes) {\n\t\t\t\t\tseekOffset += 1; //skip first byte\n\t\t\t\t\tconst dataNumBytesNext = view.getUint8(seekOffset); //read the 2nd byte (at offset 1)\t//tells us about how many bytes next constitute the instrument data\n\t\t\t\t\tseekOffset += 1; //advance 1 byte forward\n\t\t\t\t\tconst dataEndsAtByte = seekOffset + dataNumBytesNext;\n\t\t\t\t\tif (dataEndsAtByte > totalBytes) break; //break out of loop if it overflows / goes out of bounds\n\t\t\t\t\tseekOffset += 1; //also skip third byte\n\t\t\t\t\tconst strLength = view.getUint8(seekOffset); //read the 4th byte (at offset 3)\t//tells about the number of next text bytes\n\t\t\t\t\tseekOffset += 1; //advance 1 byte forward\n\t\t\t\t\tlet textBytes = new Uint8Array(aryBufr, seekOffset, strLength); //'strLength' num of bytes starting from seekOffset\n\t\t\t\t\tlet token = String.fromCharCode.apply(null, textBytes);\n\t\t\t\t\tseekOffset += strLength; //advance 'strLength' num of bytes forward\n\t\t\t\t\tseekOffset += 5; //skip next 5 bytes\n\t\t\t\t\tlet ltp = Number(view.getFloat64(seekOffset, true)); //we convert it to number before performing arithmatic ops using it\n\t\t\t\t\t// seekOffset += 8; //advance 8 bytes forward\n\t\t\t\t\tseekOffset = dataEndsAtByte - 8; //jump to reading the last 8 bytes\n\t\t\t\t\tlet closePrice = Number(view.getFloat64(seekOffset, true)); //read close-price\n\t\t\t\t\tseekOffset += 8; //advance 8 bytes forward, in prep for next loop iteration\n\n\t\t\t\t\tif (seekOffset > totalBytes) break; //break out of loop if it overflows / goes out of bounds\n\t\t\t\t\t// console.log('WS quote token:', token, ' | ltp: ', ltp, ' | cp:', closePrice);\n\t\t\t\t\tquotesBasket.current[token] = { ltp: ltp, cp: closePrice };\n\t\t\t\t}\n\n\t\t\t\t// console.log('UpstoxWebSocket with newly appended quotes:', Object.keys(quotesBasket.current));\n\t\t\t\t//optionally here broadcast via channel to other tabs\n\n\t\t\t\t// setTick(tick + 1);\n\t\t\t\t// setTick((tk) => tk + 1); // setTick(tick + 1, () => console.log('tick after setting state :', tick));\n\t\t\t\tsetTick((tk) => !tk); //this is only to trigger state change in child components / consumers\n\t\t\t});\n\t\t} catch (err) {\n\t\t\t// console.error(err);\n\t\t\treturn;\n\t\t}\n\t};\n\n\t/** Generates a random GUID (to be used in JSON data sent via websocket send() method) */\n\tconst generateGUID = () => {\n\t\treturn 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n\t\t\tvar r = (Math.random() * 16) | 0,\n\t\t\t\tv = c === 'x' ? r : (r & 0x3) | 0x8;\n\t\t\treturn v.toString(16);\n\t\t});\n\t};\n\n\t/** Converts string to ArrayBuffer (may be required format by Upstox ws send() fn)\n\t * @see https://developer.chrome.com/blog/how-to-convert-arraybuffer-to-and-from-string\n\t */\n\tconst _str2ab = (str) => {\n\t\t// Foll 2 lines are for NODE-JS using the 'buffer' package/module\n\t\t// const { Buffer } = require('node:buffer');\n\t\t// const buf = Buffer.from('hello world', 'utf8');\n\n\t\t//javascript implementation\n\t\tvar buf = new ArrayBuffer(str.length);\n\t\tvar bufView = new Uint8Array(buf);\n\t\tfor (var i = 0, strLen = str.length; i < strLen; i++) {\n\t\t\tbufView[i] = str.charCodeAt(i);\n\t\t}\n\t\treturn buf;\n\t};\n\n\t/**\n\t * Subscribes to quotes (if not already)\n\t * @param {string[]} instrumentTokenAry - An array of instrument tokens\n\t * @returns {Promise<boolean>}\n\t */\n\tconst subscribeToQuotes = async (instrumentTokenAry) => {\n\t\ttry {\n\t\t\tif (!instrumentTokenAry) return null;\n\t\t\tif (instrumentTokenAry.constructor.name !== 'Array') return null;\n\t\t\tif (instrumentTokenAry.length < 1) return null;\n\n\t\t\tconst subscriptionObj = {\n\t\t\t\tguid: generateGUID(), //'somerandomguid',\n\t\t\t\tmethod: 'sub',\n\t\t\t\tdata: {\n\t\t\t\t\tmode: 'ltpc',\n\t\t\t\t\tinstrumentKeys: instrumentTokenAry,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\t//if there is already a websocket connection and if it is still alive\n\t\t\tif (webSocketRef.current?.readyState == 1 && checkIfAccessTokenIsAlive()) {\n\t\t\t\twebSocketRef.current?.send(_str2ab(JSON.stringify(subscriptionObj)));\n\t\t\t\treturn true;\n\t\t\t} //else\n\t\t\t//create a new connection & re-subscribe to old & new instruments both\n\t\t\tconst socket = await _createSocketConnection();\n\t\t\tif (!socket) return false;\n\t\t\twebSocketRef.current?.send(_str2ab(JSON.stringify(subscriptionObj))); //subscribe to new quotes\n\n\t\t\t//since this is a new connection, here resubscribe to those quotes which were already subscribed to earlier\n\t\t\tif (Object.keys(quotesBasket.current).length > 0) {\n\t\t\t\tconst reSubscriptionObj = {\n\t\t\t\t\tguid: generateGUID(), //'somerandomguid',\n\t\t\t\t\tmethod: 'sub',\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tmode: 'ltpc',\n\t\t\t\t\t\tinstrumentKeys: Object.keys(quotesBasket.current),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\twebSocketRef.current?.send(_str2ab(JSON.stringify(reSubscriptionObj))); //subscribe to old quotes\n\t\t\t}\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.error(err);\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/**\n\t * Unsubscribes to quotes (if not already)\n\t * @param {string[]} instrumentTokenAry - An array of instrument tokens\n\t * @returns {boolean}\n\t */\n\tconst unsubscribeToQuotes = (instrumentTokenAry) => {\n\t\tif (!instrumentTokenAry) return false;\n\t\tif (instrumentTokenAry.constructor.name !== 'Array') return false;\n\t\tif (instrumentTokenAry.length < 1) return false;\n\n\t\tif (webSocketRef.current?.readyState != 1) {\n\t\t\t// setTick(0); // setQuotes({});\n\t\t\twebSocketRef.current = null;\n\t\t\tsetIsAlive(false);\n\t\t\treturn false;\n\t\t} //or perhaps instead of returning, open a new connection\n\t\ttry {\n\t\t\tconst unsubscriptionObj = {\n\t\t\t\tguid: generateGUID(), //'somerandomguid',\n\t\t\t\tmethod: 'unsub',\n\t\t\t\tdata: {\n\t\t\t\t\tmode: 'ltpc',\n\t\t\t\t\tinstrumentKeys: instrumentTokenAry,\n\t\t\t\t},\n\t\t\t};\n\t\t\twebSocketRef.current?.send(_str2ab(JSON.stringify(unsubscriptionObj)));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.error(err);\n\t\t\treturn false;\n\t\t}\n\t};\n\n\tuseEffect(() => {\n\t\t// (async () => {\n\t\t// \topenSocketConnection();\n\t\t// })();\n\t\t//here start a timer that resets 'state.isAlive' to false! We clear this timer before it timeouts, each time we receive a msg\n\t\t//Also, if 'state.isAlive' == false, at set interval, we try to create new WS connection that we can make available to our app\n\n\t\t//upon loosing connection, close the WebSocket connection\n\t\tif (!isOnline && webSocketRef.current !== null) closeSocketConnection();\n\n\t\treturn () => {\n\t\t\tcloseSocketConnection();\n\t\t};\n\t}, [isOnline]);\n\n\t// useEffect(() => {\n\t// \tconsole.log('useEffect() tick:', tick);\n\t// }, [tick]);\n\n\treturn (\n\t\t<UpstoxWebSocketContext.Provider\n\t\t\tvalue={{\n\t\t\t\tquotes: quotesBasket.current,\n\t\t\t\ttick,\n\t\t\t\tsubscribeToQuotes,\n\t\t\t\tunsubscribeToQuotes,\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</UpstoxWebSocketContext.Provider>\n\t);\n}\n","// extracted by mini-css-extract-plugin\nexport var isSelected = \"searchResults-module--isSelected--911c2\";\nexport var notFoundC = \"searchResults-module--notFoundC--bf21f\";\nexport var searchExchangeRadioC = \"searchResults-module--searchExchangeRadioC--7bf83\";\nexport var searchListFtr = \"searchResults-module--searchListFtr--0a791\";\nexport var searchListUl = \"searchResults-module--searchListUl--b612a\";\nexport var selected = \"searchResults-module--selected--751d7\";","import React, { useContext, useEffect, useRef, useState } from 'react';\n\nimport Button from '@components/ui/Button';\nimport Loading from '@components/ui/Loading';\nimport EmptyGfx from '@appSharedComponents/EmptyGfx';\nimport { ToastNotificationContext } from '@providers/ToastNotification';\n// import { UserContext } from '@providers/User';\nimport { UpstoxMasterDataContext } from '@upstoxProviders/UpstoxMasterData';\n\nimport * as styles from './searchResults.module.css';\n\n//======================+\n//\t\tTYPE-DEFS\t\t|\n//======================+\n/**\n * Upstox Instrument data\n * @typedef {import('@types_upstox').UpstoxInstrument_selective} Instrument\n */\n\n/**\n * Displays instrument search results\n * @param {Object} props React prop passed to this component\n * @param {string} props.searchQuery Search query\n * @param {()=>{}} props.cancelSearch Callback function to execute in order to cancel search and go back\n * @param {([]:Instrument)=>Promise<boolean>} props.addToWatchlist Callback function to execute in order to add selected Instruments to watchlist\n * @param {Instrument[]} props.watchlistInstrumentsAry Instruments already in the watchlist (Useful to disallow adding more than the limit or avoid duplicate entries)\n * @param {number} [props.maxNumInstrumentsPerWatchlist=10] Max number of instruments allowed in currently selected watchlist\n */\nexport default function Upstox_MarketWatch_SearchResults({\n\tsearchQuery,\n\tcancelSearch,\n\taddToWatchlist,\n\twatchlistInstrumentsAry,\n\tmaxNumInstrumentsPerWatchlist,\n}) {\n\tconst [selectedExchange, setSelectedExchange] = useState('NSE');\n\tconst [isSearchWip, setIsSearchWip] = useState(false);\n\tconst [searchResults, setSearchResults] = useState(/** @type {Instrument[]} */ ([]));\n\tconst [selectedInstrumentsObj, setSelectedInstrumentsObj] = useState(/** @type {Object.<number, Instrument>}*/ ({}));\n\tconst [isAddingOpWip, setIsAddingOpWip] = useState(false);\n\n\tconst { notify } = useContext(ToastNotificationContext);\n\tconst { searchInstruments } = useContext(UpstoxMasterDataContext);\n\n\tconst searchOpDelayTimeout = useRef(null);\n\n\t/**\n\t * Toggles instrumnet selection\n\t * @param {Instrument} instrument Instrument object\n\t */\n\tconst toggleInstrumentSelection = (instrument) => {\n\t\t// console.log('toggleInstrumentSelection() --> instrument', instrument);\n\t\tconst clonedObj = { ...selectedInstrumentsObj }; //Object.assign({}, selectedInstrumentsObj)\n\t\tif (Object.prototype.hasOwnProperty.call(clonedObj, instrument.token)) {\n\t\t\t// console.log('Deleting from state object');\n\t\t\tdelete clonedObj[instrument.token];\n\t\t} else {\n\t\t\t// console.log('Adding to state object');\n\n\t\t\t//here check if limit reached for max number of instruments allowed in watchlist it is being added to\n\t\t\tif (!watchlistInstrumentsAry || !Array.isArray(watchlistInstrumentsAry)) watchlistInstrumentsAry = [];\n\t\t\tif (watchlistInstrumentsAry.length < maxNumInstrumentsPerWatchlist) {\n\t\t\t\tclonedObj[instrument.token] = instrument;\n\t\t\t} else {\n\t\t\t\tnotify('No more instruments can be added to this watchlist');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//here check if this instrument already exists in watchlist it is being added to\n\t\t\tconst exists = watchlistInstrumentsAry.some(\n\t\t\t\t(existingInstrument) => existingInstrument.symbol === instrument.symbol && existingInstrument.segment === instrument.segment,\n\t\t\t);\n\t\t\tif (exists) {\n\t\t\t\tnotify(instrument.symbol + ' instrument already exists in the watchlist');\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tsetSelectedInstrumentsObj(clonedObj);\n\t};\n\n\tuseEffect(() => {\n\t\tif (searchQuery.trim() === '') return;\n\n\t\t//start search\n\t\tsetIsSearchWip(true);\n\t\t//use setTimeout and clearTimeout to pause a bit before searching while the user is typing\t//it's called debouncing\n\t\tclearTimeout(searchOpDelayTimeout.current);\n\t\tsearchOpDelayTimeout.current = setTimeout(() => {\n\t\t\t(async () => {\n\t\t\t\tconst searchRes = await searchInstruments(selectedExchange, searchQuery, 20);\n\t\t\t\tsetIsSearchWip(false);\n\t\t\t\tif (!searchRes) {\n\t\t\t\t\t//console.log('No items found');\n\t\t\t\t\tnotify('No Instruments found under ' + selectedExchange, 'alert');\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t// console.log('searchRes:', searchRes);\n\t\t\t\tif (Array.isArray(searchRes)) {\n\t\t\t\t\tsetSelectedInstrumentsObj({}); //empty the selected instruments bin since the search results have changed\n\t\t\t\t\tsetSearchResults(searchRes);\n\t\t\t\t}\n\t\t\t})();\n\t\t}, 1000);\n\n\t\t// return () => {};\t//cleanup if any\n\t}, [searchQuery, selectedExchange]); //runs on mount and then when either 'searchQuery' or 'selectedExchange' changes\n\n\tif (searchQuery.trim() === '') return null; //we wouldn't reach this since if this condition is met, this component won't be rendered in the first place\n\n\treturn (\n\t\t<>\n\t\t\t<div className={styles.searchExchangeRadioC}>\n\t\t\t\t{['NSE', 'BSE', 'NFO', 'CDS', 'MCX'].map((exchange, i) => (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={exchange}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetSelectedExchange(exchange);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName={selectedExchange === exchange ? styles.selected : null}\n\t\t\t\t\t\t// https://www.30secondsofcode.org/react/s/conditional-classname/\n\t\t\t\t\t>\n\t\t\t\t\t\t{exchange}\n\t\t\t\t\t</button>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t\t{searchResults.length < 1 && !isSearchWip ? (\n\t\t\t\t// <div className={styles.notFoundC}>No Instruments Found listed under {selectedExchange} exchange for your query</div>\n\t\t\t\t<EmptyGfx icon=\"search\" note={`No instruments found under ${selectedExchange} exchange for your query`} />\n\t\t\t) : (\n\t\t\t\t<ul className={styles.searchListUl}>\n\t\t\t\t\t{searchResults.map((instrument, i) => {\n\t\t\t\t\t\tconst isSelected = Object.prototype.hasOwnProperty.call(selectedInstrumentsObj, instrument.token);\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<li key={`${instrument.token}${i}${isSelected ? 'y' : 'n'}`}>\n\t\t\t\t\t\t\t\t{/* in the key, also specify whether selected or not, thus react shall optimize during rerendering if item is added in/removed from selection bin */}\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\ttoggleInstrumentSelection(instrument);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tclassName={isSelected ? styles.isSelected : null}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span>{instrument.symbol}</span>\n\t\t\t\t\t\t\t\t\t{/* <span>{instrument.segment === 'NFO' || instrument.segment === 'MCX' ? instrument.symbol : instrument.name}</span> */}\n\t\t\t\t\t\t\t\t\t<span />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</ul>\n\t\t\t)}\n\n\t\t\t<div className={styles.searchListFtr}>\n\t\t\t\t<div>\n\t\t\t\t\t<Button variant=\"tertiary\" onClick={cancelSearch}>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\t\tsetIsAddingOpWip(true);\n\t\t\t\t\t\t\tconst isAddOpSuccessfull = await addToWatchlist(\n\t\t\t\t\t\t\t\tObject.keys(selectedInstrumentsObj).map((token) => selectedInstrumentsObj[token]),\n\t\t\t\t\t\t\t).finally(() => setIsAddingOpWip(false));\n\t\t\t\t\t\t\tisAddOpSuccessfull && cancelSearch(); //effectively takes us back to watchlist page\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tisDisabled={Object.keys(selectedInstrumentsObj).length < 1}\n\t\t\t\t\t\tisWip={isAddingOpWip}\n\t\t\t\t\t\twipText=\"Adding\"\n\t\t\t\t\t>\n\t\t\t\t\t\tAdd to Watchlist\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t{isSearchWip && <Loading note=\"Searching\" />}\n\t\t</>\n\t);\n}\n","// extracted by mini-css-extract-plugin\nexport var active = \"marketWatch-module--active--3658e\";\nexport var emptyWatchListC = \"marketWatch-module--emptyWatchListC--bc108\";\nexport var instrumentCtaC = \"marketWatch-module--instrumentCtaC--8cd1e\";\nexport var mainBtn = \"marketWatch-module--mainBtn--9e6a1\";\nexport var marketWatchC = \"marketWatch-module--marketWatchC--717ab\";\nexport var marketWatchHdr = \"marketWatch-module--marketWatchHdr--0cf3c\";\nexport var marketWatchMain = \"marketWatch-module--marketWatchMain--f2cc8\";\nexport var watchListFtr = \"marketWatch-module--watchListFtr--cc8d6\";\nexport var watchlistC = \"marketWatch-module--watchlistC--53a97\";\nexport var watchlistTabsC = \"marketWatch-module--watchlistTabsC--660cd\";\nexport var wlItmsNotFoundC = \"marketWatch-module--wlItmsNotFoundC--4afcb\";","import React, { useContext, useEffect, useState } from 'react';\n\n// import ColoredNumberDisplay from '@appSharedComponents/ColoredNumberDisplay';\n// import { formatPriceInIndianStyle } from '@utils';\nimport Loading from '@components/ui/Loading';\nimport TextInput from '@components/ui/TextInput';\nimport Button from '@components/ui/Button';\nimport EmptyGfx from '@appSharedComponents/EmptyGfx';\n// import BottomSheet from '@containers/BottomSheet';\nimport WatchlistItem from '@appSharedComponents/WatchlistItem';\nimport NewTradePositionDialog from '@appSharedComponents/tradePosition/NewTradePositionDialog';\nimport Upstox_MarketWatch_SearchResults from './SearchResults/index';\n\nimport { ToastNotificationContext } from '@providers/ToastNotification';\nimport { NetworkCheckContext } from '@providers/NetworkAvailabilityCheck';\nimport { UserContext } from '@providers/User';\n\nimport { UpstoxWebSocketContext } from '@upstoxProviders/UpstoxWebSocket';\nimport { UpstoxMasterDataContext } from '@upstoxProviders/UpstoxMasterData';\nimport { AppDataIndexedDbContext } from '@appSharedProviders/AppIndexedDb';\n\nimport * as styles from './marketWatch.module.css';\n\n//==================+\n//\t\tTYPES\t\t|\n//==================+\n/** Selective attributes from the Instrument object representing the columns of the master CSV data\n * @typedef {import('@types_upstox').UpstoxInstrument_selective} Instrument\n */\n\n// /** React component to display Angel One marketwatch list and search results\n// * @param {Object} props Props passed to this component\n// * @param {?()=>{}} [props.openNewOrAddToPosition=()=>{}] Callback fn passed down by the positions component. We pass this callbck fn to the new-position dialog component in order for it to add to position\n// * @param {?()=>{}} [props.setBottomSheetTitle=()=>{}] Sets the bottom-sheet title\n// * @param {?()=>{}} [props.closeBottomSheet=()=>{}] When displayed inside bottomsheet, we use it to close sheet once trade is successfully entered\n// */\n// export default function UpstoxMarketWatch({ openNewOrAddToPosition, setBottomSheetTitle, closeBottomSheet }) { }\n\n/** React component to display Upstox marketwatch list and search results\n * @param {Object} props Props passed to this component\n * @param {?()=>{}} [props.openNewOrAddToPosition=()=>{}] Callback fn passed down by the positions component. We pass this callbck fn to the new-position dialog component in order for it to tell positions component to refresh itself\n * @param {?()=>{}} [props.setBottomSheetTitle=()=>{}] Sets the bottom-sheet title\n * @param {?()=>{}} [props.setBottomSheetDesc=()=>{}] Sets the bottom-sheet description\n * @param {?()=>{}} [props.closeBottomSheet=()=>{}] When displayed inside bottomsheet, we use it to close sheet once trade is successfully entered\n */\nexport default function UpstoxMarketWatch({ openNewOrAddToPosition, setBottomSheetTitle, setBottomSheetDesc, closeBottomSheet }) {\n\tconst [isReady, setIsReady] = useState(false); //we shall set this to true once we receive the first quote tick from WS\n\tconst [activeWatchlistIndex, setActiveWatchlistIndex] = useState(0); //index of active watchlist (Kaagzi provides 4 watchlists)\n\tconst [watchlistInstrumentsAry, setWatchlistInstrumentsAry] = useState(/** @type {Instrument[]} */ ([]));\n\tconst [watchlistInstrumentsNotFoundAry, setWatchlistInstrumentsNotFoundAry] = useState(\n\t\t/** @type {{symbol:string,exchange:('NSE'|'BSE'|'NFO'|'MCX'|'CDS')}[]} */ ([]),\n\t);\n\tconst [currentlyExpandedInstrument, setCurrentlyExpandedInstrument] = useState(/** @type {Instrument} */ ({}));\n\tconst [instrumentInvokedForTransaction, setInstrumentInvokedForTransaction] = useState(/** @type {Instrument} */ ({}));\n\tconst [searchQuery, setSearchQuery] = useState('');\n\n\tconst { notify } = useContext(ToastNotificationContext);\n\tconst isOnline = useContext(NetworkCheckContext);\n\tconst { checkIfPlanActive } = useContext(UserContext);\n\tconst { isMasterDataReady, getInstruments } = useContext(UpstoxMasterDataContext);\n\tconst { getWatchlistInstruments, setWatchlistMultipleInstruments, deleteWatchlistInstrument } = useContext(AppDataIndexedDbContext);\n\tconst { quotes, tick, subscribeToQuotes, unsubscribeToQuotes } = useContext(UpstoxWebSocketContext);\n\tconst maxNumInstrumentsPerWatchlist = 10;\n\n\tconst getWatchlist_n_loadIntoState_n_subscribeToWsLiveQuotes = async () => {\n\t\ttry {\n\t\t\t// const isPlanActive =\n\t\t\tawait checkIfPlanActive(); //this shall cause the 'PlaneExpiryGateway' component to not render this component and display plan expired dialog\n\t\t\t// if (!isPlanActive) throw new Error('Plan Expired!');\n\t\t\t//here we first read the generic broker-agnostic watchlist instruments stored in Kaagzi DB\n\t\t\tconst kaagziWatchlistInstrumentsAry = await getWatchlistInstruments(activeWatchlistIndex + 1);\n\t\t\tif (!kaagziWatchlistInstrumentsAry || !kaagziWatchlistInstrumentsAry?.length) throw new Error('No instruments listed in watchlist');\n\n\t\t\t//then resolve instrument_token (for use in WS live ticks) for each position by reading from AngelOne Master-Data DB\n\t\t\tconst mappedObj = kaagziWatchlistInstrumentsAry.reduce((acc, item) => {\n\t\t\t\t// If the exchange key doesn't exist, create it with an empty array\n\t\t\t\tif (!acc[item.xh]) {\n\t\t\t\t\tacc[item.xh] = [];\n\t\t\t\t}\n\t\t\t\t// Push the current symbol onto the array for this exchange\n\t\t\t\tacc[item.xh].push(item.sbl);\n\t\t\t\treturn acc;\n\t\t\t}, {});\n\n\t\t\tconst instrumentsFoundNotFoundObj = await getInstruments(mappedObj);\n\t\t\tif (!instrumentsFoundNotFoundObj) throw new Error('Error resolving instruments with Upstox');\n\n\t\t\tif (\n\t\t\t\t!Object.prototype.hasOwnProperty.call(instrumentsFoundNotFoundObj, 'instrumentsFound') ||\n\t\t\t\tinstrumentsFoundNotFoundObj.instrumentsFound.length < 1\n\t\t\t)\n\t\t\t\tthrow new Error('No Instruments found for watchlist-' + (activeWatchlistIndex + 1));\n\t\t\tif (\n\t\t\t\tObject.prototype.hasOwnProperty.call(instrumentsFoundNotFoundObj, 'instrumentsNotFound') &&\n\t\t\t\tinstrumentsFoundNotFoundObj.instrumentsNotFound.length > 0\n\t\t\t) {\n\t\t\t\t//list these instruments which were not found so as to allow user to delete them or delete them without asking\n\t\t\t\tsetWatchlistInstrumentsNotFoundAry(instrumentsFoundNotFoundObj.instrumentsNotFound);\n\t\t\t\tnotify(instrumentsFoundNotFoundObj.instrumentsNotFound.length + ' of the instruments not loaded!', 'err');\n\t\t\t}\n\t\t\t//here we unsubscribe old list\n\t\t\tisOnline && watchlistInstrumentsAry.length > 0 && unsubscribeToQuotes(watchlistInstrumentsAry.map(({ token }) => token));\n\t\t\t// unsubscribeToQuotes(_segregateInstrumentTokenByExchanges(watchlistInstrumentsAry));\n\t\t\tsetWatchlistInstrumentsAry(instrumentsFoundNotFoundObj.instrumentsFound);\n\t\t\t//here subscribe to newly fetched instruments from this watchlist we just switched to\n\t\t\tisOnline && (await subscribeToQuotes(instrumentsFoundNotFoundObj.instrumentsFound.map(({ token }) => token)));\n\t\t} catch (err) {\n\t\t\tisOnline && watchlistInstrumentsAry.length > 0 && unsubscribeToQuotes(watchlistInstrumentsAry.map(({ token }) => token));\n\t\t\t// unsubscribeToQuotes(_segregateInstrumentTokenByExchanges(watchlistInstrumentsAry));\n\t\t\tsetWatchlistInstrumentsAry([]);\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t// /**\n\t// * Add instruments to the watchlist\n\t// * @param {{'instrument_token':Instrument,'another_instrument_token':Instrument}} instrumentsObj Instruments to add listed in an object with instrument_token as the key\n\t// * @returns {Promise<boolean>} TRUE in case instruments added successfully, FALSE otherwise\n\t// */\n\t// const addInstruments = async (instrumentsObj) => {\n\t//\t\tif (!instrumentsObj || typeof instrumentsObj !== 'object') return false;\n\t//\t\tconst tokensAry = Object.keys(instrumentsObj);\n\t//\t\tif (tokensAry.length < 1) return false;\n\t//\t\tconst instrumentsToBeAddedAry = tokensAry.map((token) => instrumentsObj[token]);\n\t//}\n\n\t/**\n\t * Add multiple instruments to the watchlist\n\t * @param {Instrument[]} instrumentsToBeAddedAry Array of instrument objects to be added\n\t * @returns {Promise<boolean>} TRUE in case instruments added successfully, FALSE otherwise\n\t */\n\tconst addInstruments = async (instrumentsToBeAddedAry) => {\n\t\tif (!instrumentsToBeAddedAry || !Array.isArray(instrumentsToBeAddedAry) || instrumentsToBeAddedAry.length < 1) return false;\n\n\t\t//here maybe check limit for max number of allowed instruments for the currently active watchlist\n\t\tconst availableSpots = maxNumInstrumentsPerWatchlist - watchlistInstrumentsAry.length;\n\t\tif (instrumentsToBeAddedAry.length > availableSpots) {\n\t\t\tnotify('Only ' + availableSpots + ' more instruments can be added to watchlist-' + (activeWatchlistIndex + 1));\n\t\t\treturn false;\n\t\t}\n\t\ttry {\n\t\t\tconst isPlanActive = await checkIfPlanActive(); //this shall cause the 'PlaneExpiryGateway' component to not render this component and display plan expired dialog\n\t\t\tif (!isPlanActive) throw new Error('Plan Expired!');\n\t\t\t//Loop over items in the array and convert Angel One Instrument object to Kaagzi instrument object\n\t\t\t// const kiteToKaagziInstrumentFormatAry = instrumentsToBeAddedAry.map((instrumentToBeAdded) => ({\n\t\t\t// \tsbl: instrumentToBeAdded.symbol,\n\t\t\t// \txh: instrumentToBeAdded.segment,\n\t\t\t// \tx: instrumentToBeAdded.expiry,\n\t\t\t// }));\n\t\t\tconst kiteToKaagziInstrumentFormatAry = instrumentsToBeAddedAry.map((instrumentToBeAdded) => {\n\t\t\t\tconst kaagziWatchlistInstrumentObj = { sbl: instrumentToBeAdded.symbol, xh: instrumentToBeAdded.segment };\n\n\t\t\t\t//parse expiry\n\t\t\t\tif (\n\t\t\t\t\tObject.prototype.hasOwnProperty.call(instrumentToBeAdded, 'expiry') &&\n\t\t\t\t\tinstrumentToBeAdded.expiry &&\n\t\t\t\t\tinstrumentToBeAdded.expiry.toString().trim() !== ''\n\t\t\t\t) {\n\t\t\t\t\tkaagziWatchlistInstrumentObj.x = instrumentToBeAdded.expiry; //new Date(instrumentToBeAdded.expiry).getTime(); //new Date('04JUL2024').getTime();\n\t\t\t\t}\n\t\t\t\treturn kaagziWatchlistInstrumentObj;\n\t\t\t});\n\n\t\t\tconst writeOpStatus = await setWatchlistMultipleInstruments(activeWatchlistIndex + 1, kiteToKaagziInstrumentFormatAry);\n\t\t\tif (!writeOpStatus) throw new Error('Failed to add instruments to watchlist');\n\n\t\t\t////// AFTER ADDING TO DB, ADD TO STATE TOO\n\n\t\t\t//here add to state //only if it doesn't already exist\n\t\t\tconst watchlistInstrumentsAryCopy = [...watchlistInstrumentsAry]; // Create a new array to hold the new state by cloning the previous\n\t\t\t// Iterate over each of the instruments to be added and compare with items instruments already present in watchlist\n\t\t\tfor (const instrumentToBeAdded of instrumentsToBeAddedAry) {\n\t\t\t\t// Check if the instrument already exists in the watchlist\n\t\t\t\tconst exists = watchlistInstrumentsAryCopy.some(\n\t\t\t\t\t//we could just as well have iterated over 'watchlistInstrumentsAry' instead of 'watchlistInstrumentsAryCopy' since both are copies of each other\n\t\t\t\t\t(existingInstrument) =>\n\t\t\t\t\t\t// existingInstrument.tradingsymbol === instrumentToBeAdded.tradingsymbol && existingInstrument.exchange === instrumentToBeAdded.exchange,\n\t\t\t\t\t\texistingInstrument.token === instrumentToBeAdded.token, //comparing instrument token should be enough\n\t\t\t\t);\n\t\t\t\tif (!exists) watchlistInstrumentsAryCopy.push(instrumentToBeAdded); // If the instrument does not exist, add it to the new state array\n\t\t\t}\n\t\t\tsetWatchlistInstrumentsAry(watchlistInstrumentsAryCopy); // Update the state with the new array\n\n\t\t\t//here subscribe to WS live quotes //or perhaps this may not be necessary since we would be transitioning back to wathlists from search page\n\t\t\t// isOnline && (await subscribeToQuotes(_segregateInstrumentTokenByExchanges(watchlistInstrumentsAryCopy)));\n\t\t\tisOnline && (await subscribeToQuotes(watchlistInstrumentsAryCopy.map(({ token }) => token)));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tnotify(err.message || 'Error adding instruments to watchlist', 'err');\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/**\n\t * Remove an instrument from the watchlist\n\t * @param {string} tradingsymbol Trading symbol\n\t * @param {('NSE'|'BSE'|'NFO'|'CDS'|'MCX')} exchange The exchange this instrument is listed under\n\t * @param {string} instrument_token The instrument token shall be used to unsubscribe from live quotes\n\t * @returns {Promise<boolean>} TRUE in case instruments added successfully, FALSE otherwise\n\t */\n\tconst removeInstrument = async (tradingsymbol, exchange, instrument_token) => {\n\t\tif (!tradingsymbol || typeof tradingsymbol !== 'string' || tradingsymbol.trim() === '') return false;\n\t\tif (!exchange || typeof exchange !== 'string' || exchange.trim() === '') return false;\n\t\tif (!instrument_token) return false;\n\t\t// console.log('About to remove ' + tradingsymbol + ' from Indexed DB');\n\t\ttry {\n\t\t\t//here first delete from IndexedDB\n\t\t\tconst deleteOpStatus = await deleteWatchlistInstrument(activeWatchlistIndex + 1, tradingsymbol, exchange);\n\t\t\tif (!deleteOpStatus) throw new Error('Failed to remove instrument from watchlist');\n\n\t\t\t//then remove from state\n\t\t\tsetWatchlistInstrumentsAry(\n\t\t\t\t// watchlistInstrumentsAry.filter((instrument) => instrument.tradingsymbol !== tradingsymbol && instrument.exchange !== exchange),\n\t\t\t\twatchlistInstrumentsAry.filter((instrument) => instrument.token !== instrument_token),\n\t\t\t);\n\t\t\t//unsubscribe removed instrument from ws\n\t\t\tisOnline && unsubscribeToQuotes([instrument_token]);\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\treturn false;\n\t\t}\n\t};\n\t//AI example\n\t// const removeMultipleInstruments = (memberIdsToDelete) => {\n\t// \tsetMembers(members.filter((member) => !memberIdsToDelete.includes(member.id)));\n\t// };\n\t// // Example usage: removeMultipleInstruments([1, 2]); to delete members with id 1 and 2\n\n\t// const editMember = (memberId, newName) => {\n\t// \tsetMembers(members.map((member) => (member.id === memberId ? { ...member, name: newName } : member)));\n\t// };\n\n\t/**\n\t * Remove an instrument from the the not found list\n\t * @param {string} tradingsymbol Trading symbol\n\t * @param {('NSE'|'BSE'|'NFO'|'CDS'|'MCX')} exchange The exchange this instrument is listed under\n\t * @returns {Promise<boolean>} TRUE in case instrument removed successfully, FALSE otherwise\n\t */\n\tconst removeNotFoundInstrument = async (tradingsymbol, exchange) => {\n\t\tif (!tradingsymbol || typeof tradingsymbol !== 'string' || tradingsymbol.trim() === '') return false;\n\t\tif (!exchange || typeof exchange !== 'string' || exchange.trim() === '') return false;\n\t\t// console.log('About to remove ' + tradingsymbol + ' from Indexed DB');\n\t\ttry {\n\t\t\t//here first delete from IndexedDB\n\t\t\tconst deleteOpStatus = await deleteWatchlistInstrument(activeWatchlistIndex + 1, tradingsymbol, exchange);\n\t\t\tif (!deleteOpStatus) throw new Error('Failed to remove instrument from watchlist');\n\n\t\t\t//then remove from state\n\t\t\tsetWatchlistInstrumentsNotFoundAry(\n\t\t\t\t// watchlistInstrumentsAry.filter((instrument) => instrument.tradingsymbol !== tradingsymbol && instrument.exchange !== exchange),\n\t\t\t\twatchlistInstrumentsNotFoundAry.filter(({ symbol, exchange: exch }) => !(symbol === tradingsymbol && exch === exchange)),\n\t\t\t);\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t//RUNS ON MOUNT & THEN WHENEVER 'activeWatchlistIndex' CHANGES (for eg, when switching between watchlists) or whenever master-data becomes available and ready to be read\n\tuseEffect(() => {\n\t\t(async () => {\n\t\t\t// unsubscribeToQuotes(watchlistInstrumentsAry.map(({ instrument_token }) => Number(instrument_token))); //unsubscibe all quotes from outgoing list\t//map is used to convert array of strings to array of numbers\n\t\t\tif (isMasterDataReady) await getWatchlist_n_loadIntoState_n_subscribeToWsLiveQuotes(); //this will then load instruments (and subscribe to WS) for the page specified by activeWatchlistIndex\n\t\t\tsetIsReady(true);\n\t\t\tsetBottomSheetTitle(`Watchlist ${activeWatchlistIndex + 1}`);\n\t\t\tsetBottomSheetDesc('');\n\t\t})();\n\t}, [activeWatchlistIndex, isMasterDataReady]);\n\n\tuseEffect(() => {\n\t\t// setBottomSheetTitle(\n\t\t// \tObject.keys(instrumentInvokedForTransaction).length === 0\n\t\t// \t\t? `Watchlist ${activeWatchlistIndex + 1}`\n\t\t// \t\t: instrumentInvokedForTransaction.symbol + ' ' + instrumentInvokedForTransaction.segment,\n\t\t// );\n\t\tif (Object.keys(instrumentInvokedForTransaction).length === 0) {\n\t\t\tsetBottomSheetTitle(`Watchlist ${activeWatchlistIndex + 1}`);\n\t\t\tsetBottomSheetDesc('');\n\t\t} else {\n\t\t\tsetBottomSheetTitle(instrumentInvokedForTransaction.symbol + ' ' + instrumentInvokedForTransaction.segment);\n\t\t\tsetBottomSheetDesc(instrumentInvokedForTransaction.name);\n\t\t}\n\t}, [instrumentInvokedForTransaction]);\n\n\tuseEffect(() => {\n\t\t(async () => {\n\t\t\tif (isOnline && watchlistInstrumentsAry.length > 0) {\n\t\t\t\t// console.log('Watchlist: Network reconnected. Waiting 2 secs before re-subscribing to WS');\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 2000)); //wait for 2 seconds for websocket connection to be established successfully\n\t\t\t\t// console.log('Watchlist: Subscribing to quotes');\n\t\t\t\t// await subscribeToQuotes(_segregateInstrumentTokenByExchanges(watchlistInstrumentsAry));\n\t\t\t\tawait subscribeToQuotes(watchlistInstrumentsAry.map(({ token }) => token));\n\t\t\t}\n\t\t\t//foll call shall anyhow fail coz no network wud b available\n\t\t\t// else {\n\t\t\t// \tunsubscribeToQuotes(watchlistInstrumentsAry.map(({ instrument_token }) => Number(instrument_token)));;\n\t\t\t// }\n\t\t})();\n\t}, [isOnline]); //runs on mount & when 'isOnline' changes\n\n\t// let hasFirstRunOnMountFinished = false;\n\t// useEffect(() => {\n\t// \t// console.log('MrktWtch useEffect() tick:', tick);\n\t// \t// console.log('MrktWtch useEffect() quotes:', Object.keys(quotes));\n\t// \t// console.log('MarketWatch useEffect quotes:', Object.keys(quotes));\n\t// \tsetIsReady(true); //on receiving first tick quote from WS, we hide loading overlay by setting this to true (and also sets on subsequent runs but doesnt matter)\n\t// \t// hasFirstRunOnMountFinished && setIsReady(true); //on receiving first tick quote from WS, we hide loading overlay by setting this to true (and also sets on subsequent runs but doesnt matter)\n\t// \t// hasFirstRunOnMountFinished = true;\n\t// }, [tick]); //}, [quotes]); //runs on mount and then when 'tick' changes\n\n\t// useEffect(() => {\n\t// \t//here if search query goes from '' to 'something', move into search instruments mode\n\t// \t//start search\n\t// \tif (searchQuery.trim() === '') return; //or here resubscribe to MW quotes for currently active watchlist\n\t// \t(async () => {\n\t// \t\tconst searchRes = await searchInstruments('NSE', searchQuery, 20);\n\t// \t\tif (!searchRes) console.log('No items found');\n\t// \t\t// console.log('searchRes:', searchRes);\n\t// \t\tArray.isArray(searchRes) && setSearchResults(searchRes);\n\t// \t})();\n\n\t// \t// return () => {};\n\t// }, [searchQuery]); //runs on mount and then when 'searchQuery' changes\n\n\t// useEffect(() => {\n\t// \tconst activeWatchListInstrumentTokenStrAry = Object.keys(activeWatchlistInstruments_metaDataObj);\n\t// \tif (activeWatchListInstrumentTokenStrAry.length > 0) {\n\t// \t\tmode === 'search'\n\t// \t\t\t? unsubscribeToQuotes(activeWatchListInstrumentTokenStrAry.map(Number))\n\t// \t\t\t: (async () => {\n\t// \t\t\t\t\t//resubscribe to quotes\n\t// \t\t\t\t\tawait subscribeToQuotes(activeWatchListInstrumentTokenStrAry.map(Number));\n\t// \t\t\t\t})();\n\t// \t}\n\t// }, [mode]); //runs on mount and then when 'mode' changes\n\n\tif (!isMasterDataReady) return null;\n\treturn Object.keys(instrumentInvokedForTransaction).length === 0 ? (\n\t\t//when we have not moved into the BUY/SELL window yet, we show the watchlist/searchlist\n\t\t<div className={styles.marketWatchC}>\n\t\t\t<div className={styles.marketWatchHdr}>\n\t\t\t\t{/* <h2>Watchlist</h2> */}\n\t\t\t\t<TextInput\n\t\t\t\t\tplaceholder={`Add to Watchlist-${activeWatchlistIndex + 1}`}\n\t\t\t\t\ticon=\"search\"\n\t\t\t\t\tvalue={searchQuery}\n\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\tsetSearchQuery(e.target.value);\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<div className={styles.marketWatchMain}>\n\t\t\t\t{searchQuery.trim() === '' ? ( //display watchlist\n\t\t\t\t\t<>\n\t\t\t\t\t\t{watchlistInstrumentsAry.length < 1 ? (\n\t\t\t\t\t\t\tisReady && (\n\t\t\t\t\t\t\t\t// <div className={styles.emptyWatchListC}>\n\t\t\t\t\t\t\t\t// \tNo Instruments present<br></br>kindly search above for instruments to add to this list\n\t\t\t\t\t\t\t\t// </div>\n\t\t\t\t\t\t\t\t<EmptyGfx icon=\"binocular\" note={`Watchlist-${activeWatchlistIndex + 1} is empty`} />\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div className={styles.watchlistC}>\n\t\t\t\t\t\t\t\t{watchlistInstrumentsAry.map((instrument, i) => {\n\t\t\t\t\t\t\t\t\tconst { symbol, name, token, segment: exchange } = instrument;\n\t\t\t\t\t\t\t\t\tconst isExpanded = currentlyExpandedInstrument && currentlyExpandedInstrument.token === token;\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<WatchlistItem\n\t\t\t\t\t\t\t\t\t\t\twrapperElement=\"div\"\n\t\t\t\t\t\t\t\t\t\t\tkey={token}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetCurrentlyExpandedInstrument(isExpanded ? {} : instrument);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tisExpandedView={isExpanded}\n\t\t\t\t\t\t\t\t\t\t\ttradingsymbol={symbol.replace(/-EQ$/i, '')} //we trim the ending '-EQ' part for NSE instruments. For eg 'INFY-EQ' --> 'INFY'\n\t\t\t\t\t\t\t\t\t\t\tentityName={name}\n\t\t\t\t\t\t\t\t\t\t\texchange={exchange}\n\t\t\t\t\t\t\t\t\t\t\tsegment={exchange}\n\t\t\t\t\t\t\t\t\t\t\tltp={quotes?.[token]?.ltp}\n\t\t\t\t\t\t\t\t\t\t\tclosePrice={quotes?.[token]?.cp}\n\t\t\t\t\t\t\t\t\t\t\tcloseExpandedView={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetCurrentlyExpandedInstrument({});\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonBuyClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetInstrumentInvokedForTransaction(instrument);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonRemoveClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tremoveInstrument(symbol, exchange, token).then(() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tsetCurrentlyExpandedInstrument({});\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t{watchlistInstrumentsNotFoundAry.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div className={styles.wlItmsNotFoundC}>\n\t\t\t\t\t\t\t\t\t\t<h3>Instruments not found</h3>\n\t\t\t\t\t\t\t\t\t\t{watchlistInstrumentsNotFoundAry.map(({ symbol, exchange }) => (\n\t\t\t\t\t\t\t\t\t\t\t<div key={`${symbol}:${exchange}`}>\n\t\t\t\t\t\t\t\t\t\t\t\t<span>{symbol}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tisDark={true}\n\t\t\t\t\t\t\t\t\t\t\t\t\ticon=\"trash-2\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tremoveNotFoundInstrument(symbol, exchange);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// e.stopPropagation(); //prevents event on parent elm rom firing\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<div className={styles.watchListFtr}>\n\t\t\t\t\t\t\t<div className={styles.watchlistTabsC}>\n\t\t\t\t\t\t\t\t{[1, 2, 3, 4].map((pageNum, i) => (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\tkey={pageNum}\n\t\t\t\t\t\t\t\t\t\tclassName={i === activeWatchlistIndex ? styles.active : ''}\n\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\tsetActiveWatchlistIndex(i);\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{pageNum}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{/* {Object.keys(instrumentInvokedForTransaction).length > 0 && (\n\t\t\t\t\t\t\t<BottomSheet\n\t\t\t\t\t\t\t\tdoOnClose={() => {\n\t\t\t\t\t\t\t\t\tsetInstrumentInvokedForTransaction({});\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{(close) => {\n\t\t\t\t\t\t\t\t\tconst { token, symbol, name, segment: exchange, lotsize } = instrumentInvokedForTransaction;\n\t\t\t\t\t\t\t\t\tlet ltp, cp;\n\t\t\t\t\t\t\t\t\tif (exchange === 'NSE') {\n\t\t\t\t\t\t\t\t\t\tltp = nseQuotes?.[token]?.ltp;\n\t\t\t\t\t\t\t\t\t\tcp = nseQuotes?.[token]?.cp;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (exchange === 'BSE') {\n\t\t\t\t\t\t\t\t\t\tltp = bseQuotes?.[token]?.ltp;\n\t\t\t\t\t\t\t\t\t\tcp = bseQuotes?.[token]?.cp;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (exchange === 'NFO') {\n\t\t\t\t\t\t\t\t\t\tltp = nfoQuotes?.[token]?.ltp;\n\t\t\t\t\t\t\t\t\t\tcp = nfoQuotes?.[token]?.cp;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (exchange === 'MCX') {\n\t\t\t\t\t\t\t\t\t\tltp = mcxQuotes?.[token]?.ltp;\n\t\t\t\t\t\t\t\t\t\tcp = mcxQuotes?.[token]?.cp;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (exchange === 'CDS') {\n\t\t\t\t\t\t\t\t\t\tltp = cdsQuotes?.[token]?.ltp;\n\t\t\t\t\t\t\t\t\t\tcp = cdsQuotes?.[token]?.cp;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<NewTradePositionDialog\n\t\t\t\t\t\t\t\t\t\t\ttradingsymbol={exchange === 'NFO' || exchange === 'MCX' ? symbol : name}\n\t\t\t\t\t\t\t\t\t\t\texchange={exchange}\n\t\t\t\t\t\t\t\t\t\t\tlotSize={lotsize}\n\t\t\t\t\t\t\t\t\t\t\tltp={ltp}\n\t\t\t\t\t\t\t\t\t\t\tclosePrice={cp}\n\t\t\t\t\t\t\t\t\t\t\tcloseDialog={close}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t</BottomSheet>\n\t\t\t\t\t\t)} */}\n\t\t\t\t\t\t{!isReady && <Loading note=\"Loading Watchlist\" />}\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t<Upstox_MarketWatch_SearchResults\n\t\t\t\t\t\tsearchQuery={searchQuery}\n\t\t\t\t\t\tcancelSearch={() => {\n\t\t\t\t\t\t\tsetSearchQuery('');\n\t\t\t\t\t\t}}\n\t\t\t\t\t\taddToWatchlist={addInstruments}\n\t\t\t\t\t\twatchlistInstrumentsAry={watchlistInstrumentsAry}\n\t\t\t\t\t\tmaxNumInstrumentsPerWatchlist={maxNumInstrumentsPerWatchlist}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t) : (\n\t\t(() => {\n\t\t\tconst { token, symbol, name, segment: exchange, lotsize } = instrumentInvokedForTransaction;\n\t\t\treturn (\n\t\t\t\t<NewTradePositionDialog\n\t\t\t\t\ttradingsymbol={symbol} //{exchange === 'NFO' || exchange === 'MCX' ? symbol : name}\n\t\t\t\t\texchange={exchange}\n\t\t\t\t\tlotSize={lotsize}\n\t\t\t\t\tltp={quotes?.[token]?.ltp}\n\t\t\t\t\tclosePrice={quotes?.[token]?.cp}\n\t\t\t\t\topenNewOrAddToPosition={openNewOrAddToPosition}\n\t\t\t\t\tcloseDialog={closeBottomSheet}\n\t\t\t\t\tcancelOp={() => {\n\t\t\t\t\t\tsetInstrumentInvokedForTransaction({}); //brings user back to watchlist\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t);\n\t\t})()\n\t);\n}\n","// extracted by mini-css-extract-plugin\nexport var noPosEmptyC = \"positions-module--noPosEmptyC--38a75\";\nexport var positionsC = \"positions-module--positionsC--416da\";\nexport var positionsFtr = \"positions-module--positionsFtr--a7926\";\nexport var positionsListC = \"positions-module--positionsListC--71259\";\nexport var positionsNotFoundC = \"positions-module--positionsNotFoundC--9484a\";\nexport var totalPnL = \"positions-module--totalPnL--82667\";","import React, { useContext, useEffect, useState } from 'react';\n// import { createPortal } from 'react-dom';\n// import { chromeWebExtension_UUID, firefoxWebExtension_UUID } from '@webextensionConfig';\n\nimport ColoredNumberDisplay from '@appSharedComponents/ColoredNumberDisplay';\nimport PositionListItem from '@appSharedComponents/tradePosition/PositionListItem';\nimport ExitTradePositionDialog from '@appSharedComponents/tradePosition/ExitTradePositionDialog';\nimport Button from '@components/ui/Button';\nimport Loading from '@components/ui/Loading';\nimport EmptyGfx from '@appSharedComponents/EmptyGfx';\n\nimport BottomSheet from '@containers/BottomSheet';\n\nimport { ToastNotificationContext } from '@providers/ToastNotification';\nimport { NetworkCheckContext } from '@providers/NetworkAvailabilityCheck';\nimport { UserContext } from '@providers/User';\n// import { StockMarketBrokerContext } from '@providers/StockMarketBroker';\nimport { UpstoxUserContext } from '@upstoxProviders/UpstoxUser';\nimport { UpstoxMasterDataContext } from '@upstoxProviders/UpstoxMasterData';\nimport { UpstoxWebSocketContext } from '@upstoxProviders/UpstoxWebSocket';\nimport { AppDataIndexedDbContext } from '@appSharedProviders/AppIndexedDb';\n\nimport { AppHeader } from '@components/Header';\nimport UpstoxMarketWatch from '@upstoxComponents/MarketWatch';\n// import TradeHistory from '@appSharedComponents/TradeHistory';\n// import { FullWidthAppRestrictedPageLayoutContext } from '@layouts/FullWidthAppRestrictedPage';\n// import { TabsSwitcherContext } from '@containers/Tabs';\n\nimport * as styles from './positions.module.css';\n\n//==========================+\n//\t\tTYPE DEFINITIONS\t|\n//==========================+\n\n/** Active position data stored in 'positions' table with each position appended with instrument_token mapped from Upstox\n * @typedef {Object} UpstoxPosition\n * @property {?String} [id] - Trading Symbol suffixed with exchange (eg :NSE, :BSE) and further suffixed with direction (eg ':B' or ':S'). Sorting shall be by Trading Symbol\n * @property {String} sbl - Instrument name / Trading Symbol\n * @property {('NSE'|'BSE'|'NFO'|'CDS'|'MCX')} xh - Exchange\n * @property {Number} avg - Average entry price\n * @property {?Number} [sl] - Stop-loss price\n * @property {?Number} [tp] - Take-profit price\n * @property {Number} qty - Quantity\n * @property {?Number} [ltsz=1] - Lot Size\n * @property {Number} t - Timestamp in ms\n * @property {Number} [x] - Expiry timestamp in ms\n * @property {('B'|'S')} dir - Trade direction. 'B' for BUY trade | 'S' for SELL trade\n * @property {?number} instrument_token Instrument token mapped from Upstox Master Data\n */\n\n/** @typedef {import('@types_appShared').Position} KaagziPosition Broker agnostic active-position data stored in 'positions' table */\n\n//======================+\n//\t\tCOMPONENT\t\t|\n//======================+\n\nexport default function UpstoxPositions() {\n\tconst [isReady, setIsReady] = useState(false); //we shall set this to true once we receive the first quote tick from WS\n\tconst [positionsAry, setPositionsAry] = useState(/** @type {UpstoxPosition[]} */ ([]));\n\tconst [positionsNotFoundAry, setPositionsNotFoundAry] = useState(/** @type {{symbol:String,exchange:string}[]} */ ([]));\n\tconst [totalPnL, setTotalPnL] = useState(0);\n\tconst [currentlySelectedPos, setCurrentlySelectedPos] = useState(/** @type {UpstoxPosition} */ ({}));\n\tconst [isWatchListViz, setIsWatchlistViz] = useState(false);\n\n\tconst { notify } = useContext(ToastNotificationContext);\n\tconst isOnline = useContext(NetworkCheckContext);\n\tconst { checkIfPlanActive } = useContext(UserContext);\n\t// const { currentBroker } = useContext(StockMarketBrokerContext);\n\tconst { name: brokerUserName, logOut: brokerLogOut } = useContext(UpstoxUserContext);\n\tconst { quotes, tick, subscribeToQuotes, unsubscribeToQuotes } = useContext(UpstoxWebSocketContext);\n\t// const goToTab = useContext(TabsSwitcherContext);\n\tconst { isMasterDataReady, getTokenForInstruments } = useContext(UpstoxMasterDataContext);\n\tconst { getPosition, exitPosition, setPosition } = useContext(AppDataIndexedDbContext);\n\t// const appHeaderContainerElm = useContext(FullWidthAppRestrictedPageLayoutContext);\n\n\t// const { setBroker, setBrokerLoggedInUserName, setDoOnBrokerLogout, setDoOnWatchListBtnClick, isTradeHistoryViz, setIsTradeHistoryViz } = useContext(AppHeaderContext);\n\n\t// /** Gets array of tokens from array of position objects. ie. Reads tokens from each position object from positions state array into a new array\n\t// * @returns {?number[]} Array of instrument tokens\n\t// */\n\t// const _getArrayOfTokensFromArrayOfPositionObjs = () => {\n\t// \tif (positionsAry.length < 1) return null; //return [];\n\t// \tlet tokensAry_notUnique = positionsAry.map((pos) => Number(pos.instrument_token));\n\t// \treturn [...new Set(tokensAry_notUnique)]; //same as Array.from(new Set())\t// removes duplicate entries that may hav got added in above operation\n\t// \t//// NOTE: We can use a SET instead of Array --> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set\n\t// \t//// more info on above -->\thttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#remove_duplicate_elements_from_the_array\n\t// };\n\n\tconst getPositions_n_loadIntoState_n_subscribeToWsLiveQuotes = async () => {\n\t\ttry {\n\t\t\tconst isPlanActive = await checkIfPlanActive(); //this shall cause the 'PlaneExpiryGateway' component to not render this component and display plan expired dialog\n\t\t\tif (!isPlanActive) throw new Error('Plan Expired!');\n\t\t\t//here we first read the generic broker-agnostic positions stored in Kaagzi DB\n\t\t\tconst kaagziPositionsAry = await getPosition(null, null, null);\n\t\t\tif (!kaagziPositionsAry || !kaagziPositionsAry?.length) throw new Error('No positions found');\n\n\t\t\t//then resolve instrument_token (for use in WS live ticks) for each position by reading from Upstox Master-Data DB\n\t\t\tconst mappedObj = kaagziPositionsAry.reduce((acc, item) => {\n\t\t\t\t// If the exchange key doesn't exist, init it with an empty array\n\t\t\t\tif (!acc[item.xh]) {\n\t\t\t\t\tacc[item.xh] = [];\n\t\t\t\t}\n\t\t\t\t// Push the current symbol onto the array for this exchange\n\t\t\t\tacc[item.xh].push(item.sbl);\n\t\t\t\treturn acc;\n\t\t\t}, {});\n\n\t\t\tconst tokenForInstrumentsObj = await getTokenForInstruments(mappedObj);\n\t\t\tif (!tokenForInstrumentsObj) throw new Error('Error inferring tokens for positions');\n\t\t\tif (!Object.prototype.hasOwnProperty.call(tokenForInstrumentsObj, 'instrumentsAndTheirToken'))\n\t\t\t\tthrow new Error('Error inferring tokens for positions');\n\t\t\t/** @type {UpstoxPosition[]} */\n\t\t\tconst upstoxPositionsAry = [];\n\t\t\tkaagziPositionsAry.forEach((position) => {\n\t\t\t\t//only accept positions if instrument_token is found for it's symbol\n\t\t\t\tif (Object.prototype.hasOwnProperty.call(tokenForInstrumentsObj.instrumentsAndTheirToken, `${position.sbl}:${position.xh}`)) {\n\t\t\t\t\tposition.instrument_token = tokenForInstrumentsObj.instrumentsAndTheirToken[`${position.sbl}:${position.xh}`]; // || null;\n\t\t\t\t\tupstoxPositionsAry.push(position); //now this position obj also has the instrument_token\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (kaagziPositionsAry.length < 1 && tokenForInstrumentsObj?.instrumentsNotFound?.length < 1) throw new Error('No positions found');\n\n\t\t\tif (tokenForInstrumentsObj?.instrumentsNotFound?.length > 0) {\n\t\t\t\tsetPositionsNotFoundAry(tokenForInstrumentsObj.instrumentsNotFound);\n\t\t\t\tnotify(tokenForInstrumentsObj.instrumentsNotFound.length + ' of the positions could not be loaded');\n\t\t\t}\n\n\t\t\tsetPositionsAry(upstoxPositionsAry);\n\t\t\t//here subsribe to newly fetched positions\n\t\t\t// isOnline && (await subscribeToQuotes(upstoxPositionsAry.map(({ instrument_token }) => Number(instrument_token))));\n\t\t\tif (isOnline) {\n\t\t\t\t// const subscrptnResult =\n\t\t\t\tawait subscribeToQuotes(upstoxPositionsAry.map(({ instrument_token }) => instrument_token));\n\t\t\t\t// await subscribeToQuotes(_segregateInstrumentTokenByExchanges(upstoxPositionsAry));\n\t\t\t\t// console.log('subscrptnResult:', subscrptnResult);\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 1500)); //wait for 1.5 seconds for websocket to respond with the quotes\n\t\t\t\tsetIsReady(true);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\t// console.error(err);\n\t\t\t// notify(err?.message || 'Error reading positions', 'err');\n\t\t\tisOnline && positionsAry.length > 0 && unsubscribeToQuotes(positionsAry.map(({ instrument_token }) => instrument_token));\n\t\t\t// isOnline && positionsAry.length > 0 && unsubscribeToQuotes(_segregateInstrumentTokenByExchanges(positionsAry));\n\t\t\tsetPositionsAry([]);\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/** Opens new position or adds to already open position\n\t * @param {string} tradingsymbol Instrument trading symbol\n\t * @param {string} exchange Exchange\n\t * @param {Number} ltp LTP\n\t * @param {Number} qty Quantity\n\t * @param {Number} [lotSize] Lot size\n\t * @returns {Promise<?KaagziPosition>} broker agnostic position data written to DB or null\n\t */\n\tconst openNewOrAddToPosition = async (tradingsymbol, exchange, ltp, qty, lotSize) => {\n\t\t// console.log('Opeining pos for instrument ' + tradingsymbol);\n\t\t// console.table({ tradingsymbol, exchange, ltp, qty, lotSize });\n\t\tif (!tradingsymbol || typeof tradingsymbol !== 'string' || tradingsymbol.trim() === '') return null;\n\t\tif (!exchange || typeof exchange !== 'string' || exchange.trim() === '') return null;\n\t\tif (!ltp || isNaN(ltp)) return null;\n\t\tif (!qty || isNaN(qty) || !Number.isInteger(qty)) return null;\n\n\t\ttry {\n\t\t\tconst isPlanActive = await checkIfPlanActive(); //this shall cause the 'PlaneExpiryGateway' component to not render this component and display plan expired dialog\n\t\t\tif (!isPlanActive) throw new Error('Plan Expired!');\n\t\t\t/** @type {KaagziPosition} */\n\t\t\tconst posData = {\n\t\t\t\tsbl: tradingsymbol,\n\t\t\t\txh: exchange,\n\t\t\t\tavg: ltp,\n\t\t\t\t// sl: 0,\n\t\t\t\t// tp: 0,\n\t\t\t\tqty: Number(qty),\n\t\t\t\tt: Date.now(),\n\t\t\t\t// x: 'expiry datetime here',\n\t\t\t\tdir: 'B', //direction === 'B' ? 'B' : 'S',\n\t\t\t};\n\t\t\tif (lotSize && !isNaN(lotSize) && Number(lotSize) > 1) {\n\t\t\t\tposData.ltsz = Number(lotSize);\n\t\t\t}\n\t\t\tconst writtenPos = await setPosition(posData);\n\t\t\tif (!writtenPos) throw new Error('Failed to open or update position'); //in case of max positions allowed, show appropriate message\n\n\t\t\t//here update the state in positions component or provider\n\t\t\tawait getPositions_n_loadIntoState_n_subscribeToWsLiveQuotes(); //effectively refreshes positions to also display the newly-added / updated pos\n\t\t\t//note that the watchlist component unmounts after the position has been added and we may need to resubscribe to positions quotes after it has been closed, by watching for 'isWatchListViz' turning to false\n\n\t\t\tnotify('Trade position ' + tradingsymbol + ' opened successfully', 'success');\n\n\t\t\treturn writtenPos;\n\t\t} catch (err) {\n\t\t\tconsole.error(err);\n\t\t\tnotify(err.message || 'Error opening or updating position', 'err');\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/**\n\t * Close position. Mostly used when either SL or TP is hit\n\t * @param {UpstoxPosition} pos Upstox position object\n\t * @param {number} exitPrice Exit price.Could either be the LTP in case of manually closing the pos. Else SL or TP\n\t * @param {boolean} isSellTrade Whether it is a SELL trade\n\t * @returns {Promise<boolean>}\n\t */\n\tconst _closePosition = async (pos, exitPrice, isSellTrade) => {\n\t\ttry {\n\t\t\tconst isPlanActive = await checkIfPlanActive(); //this shall cause the 'PlaneExpiryGateway' component to not render this component and display plan expired dialog\n\t\t\tif (!isPlanActive) throw new Error('Plan Expired!');\n\t\t\tconst exitedPos = await exitPosition(pos.sbl, pos.xh, isSellTrade, exitPrice, pos.qty);\n\t\t\tif (!exitedPos) throw new Error('Failed to exit position');\n\t\t\t//here update the state in positions component or provider\n\t\t\t__updatePositionsAfterPosExit(exitedPos);\n\t\t} catch (err) {\n\t\t\tnotify(err.message || 'Failed to close position', 'err');\n\t\t\tconsole.error(err);\n\t\t}\n\t};\n\n\tconst __updatePositionsAfterPosExit = (exitedPos) => {\n\t\tconst positionToUpdateOrRemove = positionsAry.find((pos) => pos.sbl === exitedPos.sbl && pos.xh === exitedPos.xh && pos.dir === exitedPos.dir);\n\t\tif (positionToUpdateOrRemove) {\n\t\t\t//here if exitedQty === purchasedQty, remove position from state\n\t\t\tif (positionToUpdateOrRemove.qty === exitedPos.qty) {\n\t\t\t\t//here unsubscribe from WS\n\t\t\t\t// isOnline && unsubscribeToQuotes(_segregateInstrumentTokenByExchanges([positionToUpdateOrRemove.instrument_token]));\n\t\t\t\tisOnline && unsubscribeToQuotes([positionToUpdateOrRemove.instrument_token]);\n\t\t\t\tsetPositionsAry(positionsAry.filter((pos) => !(pos.sbl === exitedPos.sbl && pos.xh === exitedPos.xh && pos.dir === exitedPos.dir)));\n\t\t\t} else if (exitedPos.qty < positionToUpdateOrRemove.qty) {\n\t\t\t\t//else if only partial units exited, update pos with qty yet to be sold\n\t\t\t\tsetPositionsAry(\n\t\t\t\t\tpositionsAry.map((pos) => {\n\t\t\t\t\t\tif (pos.sbl === exitedPos.sbl && pos.xh === exitedPos.xh && pos.dir === exitedPos.dir) {\n\t\t\t\t\t\t\tpos.qty = pos.qty - exitedPos.qty;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn pos;\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t};\n\t// useEffect(() => {\n\t// \tsetBroker('Angel One');\n\t// \tsetBrokerLoggedInUserName(brokerUserName);\n\t// \tsetDoOnBrokerLogout(brokerLogOut);\n\t// \tsetDoOnWatchListBtnClick(() => {\n\t// \t\tsetIsWatchlistViz(true);\n\t// \t});\n\t// }, []);\n\t// useEffect(() => {\n\t// \t// getPositions_n_loadIntoState_n_subscribeToWsLiveQuotes();\n\t// \t(async () => {\n\t// \t\tawait getPositions_n_loadIntoState_n_subscribeToWsLiveQuotes();\n\t// \t})();\n\t// \treturn () => {\n\t// \t\tisOnline && positionsAry.length > 0 && unsubscribeToQuotes(positionsAry.map(({ instrument_token }) => Number(instrument_token)));\n\t// \t};\n\t// }, []);\n\tlet hasAlreadyRunOnMount = false;\n\tuseEffect(() => {\n\t\tif (isMasterDataReady) {\n\t\t\tif (hasAlreadyRunOnMount) {\n\t\t\t\t//if this is a subsequent run and not the first mount run\n\t\t\t\t(async () => {\n\t\t\t\t\tawait checkIfPlanActive(); //this shall cause the 'PlaneExpiryGateway' component to not render this component and display plan expired dialog\n\n\t\t\t\t\tif (isOnline && positionsAry.length > 0) {\n\t\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 2000)); //wait for 2 seconds for websocket connection to be established successfully\n\t\t\t\t\t\t// await subscribeToQuotes(_segregateInstrumentTokenByExchanges(positionsAry));\n\t\t\t\t\t\tawait subscribeToQuotes(positionsAry.map(({ instrument_token }) => instrument_token));\n\t\t\t\t\t}\n\t\t\t\t\t//foll call shall anyhow fail coz no network wud b available\n\t\t\t\t\t// else {\n\t\t\t\t\t// \tunsubscribeToQuotes(positionsAry.map(({ instrument_token }) => Number(instrument_token)));\n\t\t\t\t\t// }\n\t\t\t\t})();\n\t\t\t} else {\n\t\t\t\t//if this is first mount run\n\t\t\t\t(async () => {\n\t\t\t\t\tawait getPositions_n_loadIntoState_n_subscribeToWsLiveQuotes();\n\t\t\t\t\tsetIsReady(true);\n\t\t\t\t})();\n\n\t\t\t\thasAlreadyRunOnMount = true;\n\t\t\t}\n\t\t}\n\t\treturn () => {\n\t\t\t// isOnline && positionsAry.length > 0 && unsubscribeToQuotes(_segregateInstrumentTokenByExchanges(positionsAry));\n\t\t\tisOnline && positionsAry.length > 0 && unsubscribeToQuotes(positionsAry.map(({ instrument_token }) => instrument_token));\n\t\t};\n\t}, [isOnline, isMasterDataReady]); //runs on mount & when 'isOnline' or 'isMasterData' changes\n\n\t// useEffect(() => {\n\t// \tif (positionsAry.length < 1) return;\n\t// \t//here read position tokens into array\n\t// \tconst posTokensAry = _getArrayOfTokensFromArrayOfPositionObjs();\n\t// \t//note that it may be the case that 'posTokensAry' now holds one less token after order getting closed and in such case we also need to unsubscribe that token.\n\t// \t//we do so once we receive order-close confirmation message from the bg\n\t// \t//here subscribe to WS\n\t// \t(async () => {\n\t// \t\tawait subscribeToQuotes(posTokensAry);\n\t// \t})();\n\n\t// \treturn () => {\n\t// \t\t//here read position tokens into array\n\t// \t\tconst posTokensAry = _getArrayOfTokensFromArrayOfPositionObjs();\n\t// \t\t//here unsubscribe to WS\n\t// \t\tunsubscribeToQuotes(posTokensAry);\n\t// \t};\n\t// }, [positionsAry]); //run on first mount and then whenever positionsAry state changes\n\n\tuseEffect(() => {\n\t\tif (Object.keys(quotes).length < 1) return;\n\n\t\t// setIsReady(true); //on receiving first tick quote from WS, we hide loading overlay by setting this to true (and also sets on subsequent runs but doesnt matter)\n\n\t\t//here calculate total PnL\n\t\tlet totalPnL = 0;\n\t\t// console.log('quotes', quotes);\n\t\tpositionsAry.forEach((pos) => {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(quotes, pos.instrument_token)) return;\n\t\t\tconst currentPrice = quotes[pos.instrument_token].ltp;\n\n\t\t\t// const individualPositionPnL = (currentPrice - pos.avg) * pos.qty;\n\t\t\t// totalPnL += individualPositionPnL;\n\t\t\t// totalPnL += (quotes[pos.instrument_token].ltp - pos.avg) * pos.qty;\n\n\t\t\t//here check for SL or TP\n\t\t\tif (pos.dir === 'B') {\n\t\t\t\t//if it's a BUY trade\n\t\t\t\ttotalPnL += (currentPrice - pos.avg) * pos.qty;\n\n\t\t\t\tif (pos.sl !== null && pos.sl !== undefined) {\n\t\t\t\t\tif (currentPrice <= pos.sl) {\n\t\t\t\t\t\t_closePosition(pos, pos.sl, false);\n\t\t\t\t\t\tnotify(`SL hit for ${pos.xh}:${pos.sbl} buy trade`, 'alert');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (pos.tp !== null && pos.tp !== undefined) {\n\t\t\t\t\tif (currentPrice >= pos.tp) {\n\t\t\t\t\t\t_closePosition(pos, pos.tp, false);\n\t\t\t\t\t\tnotify(`TP hit for ${pos.xh}:${pos.sbl} buy trade`, 'success');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t//if it's a SELL trade\n\t\t\t\ttotalPnL += (pos.avg - currentPrice) * pos.qty;\n\n\t\t\t\tif (pos.sl !== null && pos.sl !== undefined) {\n\t\t\t\t\tif (currentPrice >= pos.sl) {\n\t\t\t\t\t\t_closePosition(pos, pos.sl, true);\n\t\t\t\t\t\tnotify(`SL hit for ${pos.xh}:${pos.sbl} sell trade`, 'alert');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (pos.tp !== null && pos.tp !== undefined) {\n\t\t\t\t\tif (currentPrice <= pos.tp) {\n\t\t\t\t\t\t_closePosition(pos, pos.tp, true);\n\t\t\t\t\t\tnotify(`TP hit for ${pos.xh}:${pos.sbl} sell trade`, 'success');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tsetTotalPnL(totalPnL);\n\t\t// }, [quotes, positionsAry]); //runs on first mount and then whenever quotes or positionsAry changes\n\t}, [tick, positionsAry]); //runs on first mount and then whenever 'tick' or positionsAry changes\n\n\treturn (\n\t\t<>\n\t\t\t{/* {appHeaderContainerElm &&\n\t\t\t\tcreatePortal(\n\t\t\t\t\t<AppHeader\n\t\t\t\t\t\tbroker=\"Angel One\"\n\t\t\t\t\t\tbrokerLoggedInUserName={brokerUserName}\n\t\t\t\t\t\tbrokerLogOut={brokerLogOut}\n\t\t\t\t\t\tdoOnWatchListBtnClick={() => {\n\t\t\t\t\t\t\tsetIsWatchlistViz(true);\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>,\n\t\t\t\t\tappHeaderContainerElm,\n\t\t\t\t)} */}\n\t\t\t<AppHeader\n\t\t\t\tbroker=\"Upstox\"\n\t\t\t\tbrokerLoggedInUserName={brokerUserName}\n\t\t\t\tbrokerLogOut={brokerLogOut}\n\t\t\t\tdoOnWatchListBtnClick={() => {\n\t\t\t\t\tsetIsWatchlistViz(true);\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t<main>\n\t\t\t\t<div className={styles.positionsC}>\n\t\t\t\t\t{!isReady ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{/* <div className={styles.noPosEmptyC}>Reading Positions</div> */}\n\t\t\t\t\t\t\t<div className={styles.noPosEmptyC} />\n\t\t\t\t\t\t\t{isMasterDataReady && <Loading note=\"Loading Positions\" />}\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : positionsAry.length < 1 ? (\n\t\t\t\t\t\t// <div className={styles.noPosEmptyC}>No open positions. Add new</div>\n\t\t\t\t\t\t<EmptyGfx\n\t\t\t\t\t\t\ticon=\"briefcase\"\n\t\t\t\t\t\t\tnote=\"No Open Positions\"\n\t\t\t\t\t\t\tctaFn={() => {\n\t\t\t\t\t\t\t\t// goToTab(0); //switches over to marketwatch tab\n\t\t\t\t\t\t\t\t// notify('Enter new position for any of the instruments from watchlist');\n\t\t\t\t\t\t\t\tsetIsWatchlistViz(true);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tctaBtnText=\"Open New Position\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div className={styles.positionsListC}>\n\t\t\t\t\t\t\t\t{positionsAry.map((pos, i) => {\n\t\t\t\t\t\t\t\t\t//here check if position is expired\n\t\t\t\t\t\t\t\t\tconst { sbl, xh, avg, qty, dir, x, instrument_token } = pos;\n\n\t\t\t\t\t\t\t\t\t//here check if instrument_token has been mapped from Kite Master Data\n\t\t\t\t\t\t\t\t\t// if(!instrument_token)return <li>mark as expired</li>\n\n\t\t\t\t\t\t\t\t\t// //here calculate pnl\n\t\t\t\t\t\t\t\t\t// const lastTradedPrice = quotes[instrument_token].ltp;\n\t\t\t\t\t\t\t\t\t// const posPnl = (dir === 'S' ? avg - lastTradedPrice : lastTradedPrice - avg) * qty;\n\n\t\t\t\t\t\t\t\t\t// return (\n\t\t\t\t\t\t\t\t\t// \t<li key={`${i}:${instrument_token}`} className={dir === 'S' ? styles.isSell : styles.isBuy}>\n\t\t\t\t\t\t\t\t\t// \t\t{/* we cannot have token alone as the key since it may be used twice (ie in case opp direction trade exists) */}\n\t\t\t\t\t\t\t\t\t// \t\t<div className={styles.dataRow}>\n\t\t\t\t\t\t\t\t\t// \t\t\t<span>{sbl}</span>\n\t\t\t\t\t\t\t\t\t// \t\t\t{/* <span className=\"isGreen amtGreen\">3,390.0</span> */}\n\t\t\t\t\t\t\t\t\t// \t\t\t<ColoredNumberDisplay currentVal={posPnl} baseVal={0} />\n\t\t\t\t\t\t\t\t\t// \t\t</div>\n\t\t\t\t\t\t\t\t\t// \t\t<div className={styles.metaDataRow}>\n\t\t\t\t\t\t\t\t\t// \t\t\t<span className={styles.qty}>{qty}</span>\n\t\t\t\t\t\t\t\t\t// \t\t\t<span className={styles.avg}>{avg}</span>\n\t\t\t\t\t\t\t\t\t// \t\t\t<span className={styles.ltp}>\n\t\t\t\t\t\t\t\t\t// \t\t\t\t<PreventRerenderIfValueInvalid value={lastTradedPrice} />\n\t\t\t\t\t\t\t\t\t// \t\t\t</span>\n\t\t\t\t\t\t\t\t\t// \t\t\t{/* Use memo for above value wherein we prevent rerender if value is null, thus displaying previous tick value instead of null*/}\n\t\t\t\t\t\t\t\t\t// \t\t</div>\n\t\t\t\t\t\t\t\t\t// \t</li>\n\t\t\t\t\t\t\t\t\t// );\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<PositionListItem\n\t\t\t\t\t\t\t\t\t\t\twrapperElement=\"div\"\n\t\t\t\t\t\t\t\t\t\t\tkey={`${i}:${instrument_token}`}\n\t\t\t\t\t\t\t\t\t\t\ttradingsymbol={sbl}\n\t\t\t\t\t\t\t\t\t\t\texchange={xh}\n\t\t\t\t\t\t\t\t\t\t\tqty={qty}\n\t\t\t\t\t\t\t\t\t\t\tavg={avg}\n\t\t\t\t\t\t\t\t\t\t\t// ltp={Object.prototype.hasOwnProperty.call(quotes, instrument_token) ? quotes[instrument_token].ltp : null}\n\t\t\t\t\t\t\t\t\t\t\tltp={quotes?.[instrument_token]?.ltp}\n\t\t\t\t\t\t\t\t\t\t\t// ltp={quotes[instrument_token].ltp}\n\t\t\t\t\t\t\t\t\t\t\tdirection={dir}\n\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetCurrentlySelectedPos(pos);\n\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t{positionsNotFoundAry.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div className={styles.positionsNotFoundC}>\n\t\t\t\t\t\t\t\t\t\t<h3>Positions not found</h3>\n\t\t\t\t\t\t\t\t\t\t<p>Foll instruments not found in Upstox</p>\n\t\t\t\t\t\t\t\t\t\t{positionsNotFoundAry.map(({ symbol, exchange }) => (\n\t\t\t\t\t\t\t\t\t\t\t<div key={`${symbol}:${exchange}`}>\n\t\t\t\t\t\t\t\t\t\t\t\t<span>{symbol}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t<span>{exchange}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t{/* <Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\t\t\t\tisDark={true}\n\t\t\t\t\t\t\t\t\t\t\ticon=\"trash-2\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\tremoveNotFoundInstrument(symbol, exchange);\n\t\t\t\t\t\t\t\t\t\t\t\t// e.stopPropagation(); //prevents event on parent elm rom firing\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/> */}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className={styles.positionsFtr}>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t// goToTab(0); //switches over to marketwatch tab\n\t\t\t\t\t\t\t\t\t\t// notify('On click we show watchlist inside bottom-sheet');\n\t\t\t\t\t\t\t\t\t\tsetIsWatchlistViz(true);\n\t\t\t\t\t\t\t\t\t\t// notify('Enter new position for any of the instruments from watchlist');\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tNew Position\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<span className={styles.totalPnL}>\n\t\t\t\t\t\t\t\t\t{/* Total: <span className=\"isGreen amtGreen\">2,651.10</span> */}\n\t\t\t\t\t\t\t\t\tTotal: <ColoredNumberDisplay currentVal={totalPnL} baseVal={0} />\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{Object.keys(currentlySelectedPos).length > 0 && (\n\t\t\t\t\t\t<BottomSheet\n\t\t\t\t\t\t\tdoOnClose={() => {\n\t\t\t\t\t\t\t\tsetCurrentlySelectedPos({});\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{/* <ExitTradePositionDialog\n\t\t\t\t\t\t\ttradingsymbol={currentlySelectedPos.sbl}\n\t\t\t\t\t\t\texchange={currentlySelectedPos.xh}\n\t\t\t\t\t\t\tpurchasdQty={currentlySelectedPos.qty}\n\t\t\t\t\t\t\tlotSize={Object.prototype.hasOwnProperty.call(currentlySelectedPos, 'ltsz') ? currentlySelectedPos.ltsz : 1}\n\t\t\t\t\t\t\tavgEntryPrice={currentlySelectedPos.avg}\n\t\t\t\t\t\t\tltp={quotes?.[currentlySelectedPos.instrument_token]?.ltp}\n\t\t\t\t\t\t\tdirection={currentlySelectedPos.dir}\n\t\t\t\t\t\t\tdoOnSuccessfulExit={(exitedPos) => {\n\t\t\t\t\t\t\t\t//here if exitedQty is === to purchasedQty, remove position from state\n\t\t\t\t\t\t\t\t//else if only partial units exited, update pos with qty yet to be sold\n\t\t\t\t\t\t\t\tconsole.log('doOnSuccessfulExit() callback --> exitedPos:', exitedPos);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/> */}\n\t\t\t\t\t\t\t{(close) => (\n\t\t\t\t\t\t\t\t<ExitTradePositionDialog\n\t\t\t\t\t\t\t\t\ttradingsymbol={currentlySelectedPos.sbl}\n\t\t\t\t\t\t\t\t\texchange={currentlySelectedPos.xh}\n\t\t\t\t\t\t\t\t\tpurchasdQty={currentlySelectedPos.qty}\n\t\t\t\t\t\t\t\t\tlotSize={Object.prototype.hasOwnProperty.call(currentlySelectedPos, 'ltsz') ? currentlySelectedPos.ltsz : 1}\n\t\t\t\t\t\t\t\t\tavgEntryPrice={currentlySelectedPos.avg}\n\t\t\t\t\t\t\t\t\t// ltp={quotes?.[currentlySelectedPos.instrument_token]?.ltp}\n\t\t\t\t\t\t\t\t\tltp={quotes?.[currentlySelectedPos.instrument_token]?.ltp}\n\t\t\t\t\t\t\t\t\tdirection={currentlySelectedPos.dir}\n\t\t\t\t\t\t\t\t\t// doOnSuccessfulExit={(exitedPos) => {\n\t\t\t\t\t\t\t\t\t// \t__updatePositionsAfterPosExit(exitedPos);\n\t\t\t\t\t\t\t\t\t// \tconsole.log('doOnSuccessfulExit() callback --> exitedPos:', exitedPos);\n\t\t\t\t\t\t\t\t\t// }}\n\t\t\t\t\t\t\t\t\tdoOnSuccessfulExit={__updatePositionsAfterPosExit}\n\t\t\t\t\t\t\t\t\tcloseDialog={close}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</BottomSheet>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</main>\n\n\t\t\t{isWatchListViz && (\n\t\t\t\t<BottomSheet\n\t\t\t\t\tdoOnClose={() => {\n\t\t\t\t\t\tsetIsWatchlistViz(false);\n\t\t\t\t\t}}\n\t\t\t\t\ttitle=\"Watchist\"\n\t\t\t\t>\n\t\t\t\t\t{/* {(close) => <p>Test</p>} */}\n\n\t\t\t\t\t{(close, setSheetTitle, setSheetDesc) => (\n\t\t\t\t\t\t<UpstoxMarketWatch\n\t\t\t\t\t\t\topenNewOrAddToPosition={openNewOrAddToPosition}\n\t\t\t\t\t\t\tsetBottomSheetTitle={setSheetTitle}\n\t\t\t\t\t\t\tsetBottomSheetDesc={setSheetDesc}\n\t\t\t\t\t\t\tcloseBottomSheet={close}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</BottomSheet>\n\t\t\t)}\n\t\t\t{/* {isTradeHistoryViz && (\n\t\t\t\t<BottomSheet\n\t\t\t\t\ttitle=\"Trade History\"\n\t\t\t\t\tdoOnClose={() => {\n\t\t\t\t\t\tsetIsTradeHistoryViz(false);\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<TradeHistory />\n\t\t\t\t</BottomSheet>\n\t\t\t)} */}\n\t\t</>\n\t);\n}\n","import React from 'react';\n\nimport UpstoxUser_ContextProvider from '@upstoxProviders/UpstoxUser';\nimport UpstoxMasterData_ContextProvider from '@upstoxProviders/UpstoxMasterData';\nimport UpstoxWebSocket_ContextProvider from '@upstoxProviders/UpstoxWebSocket';\nimport AppDataIndexedDb_ContextProvider from '@appSharedProviders/AppIndexedDb';\nimport UpstoxPositions from '@upstoxComponents/Positions';\n\nexport default function App_Upstox() {\n\treturn (\n\t\t<UpstoxUser_ContextProvider>\n\t\t\t<UpstoxMasterData_ContextProvider>\n\t\t\t\t<UpstoxWebSocket_ContextProvider>\n\t\t\t\t\t<AppDataIndexedDb_ContextProvider>\n\t\t\t\t\t\t<UpstoxPositions />\n\t\t\t\t\t</AppDataIndexedDb_ContextProvider>\n\t\t\t\t</UpstoxWebSocket_ContextProvider>\n\t\t\t</UpstoxMasterData_ContextProvider>\n\t\t</UpstoxUser_ContextProvider>\n\t);\n}\n","import React from 'react';\n\nimport FullWidthAppRestrictedPageLayout from '@layouts/FullWidthAppRestrictedPage';\nimport BrowserOnly from '@components/BrowserOnly';\nimport { Seo_noIndex } from '@components/Seo';\n\nexport default function AppUpstoxPage() {\n\treturn (\n\t\t<FullWidthAppRestrictedPageLayout>\n\t\t\t<BrowserOnly>\n\t\t\t\t{() => {\n\t\t\t\t\tconst App_Upstox = require('@upstox').default; //eslint-disable-line no-undef\n\t\t\t\t\treturn <App_Upstox />;\n\t\t\t\t}}\n\t\t\t</BrowserOnly>\n\t\t</FullWidthAppRestrictedPageLayout>\n\t);\n}\n\nexport function Head() {\n\treturn (\n\t\t// <Seo>\n\t\t// \t<meta name=\"robots\" content=\"noindex\" />\n\t\t// </Seo>\n\t\t<Seo_noIndex title=\"Kaagzi App | Upstox\" />\n\t);\n}\n"],"names":["UpstoxUserContext","createContext","id","name","email","accessToken","checkIfAccessTokenIsAlive","chkIfUpstoxUserIsLoggedIn","logOut","UpstoxUser_ContextProvider","_ref","children","isSigningInWip","setIsSigningInWip","useState","setAccessToken","setId","setName","setEmail","notify","useContext","ToastNotificationContext","isOnline","NetworkCheckContext","invokeFn","LambdaContext","authWindowRef","useRef","_reset","current","chkStoredUpstoxUser_n_updateState","async","storedUpstoxUserReadResultObj","localStorage","getItem","upstoxUserData","JSON","parse","_isAccessTokenStillAlive","t","atk","nm","eml","removeItem","lastTokenFetchTimestampMs","Object","prototype","hasOwnProperty","call","isNaN","indiaDateNow","Date","toLocaleString","timeZone","indiaToday330AM","setHours","indiaYesterday330AM","setDate","getDate","lastTokenFetchDateAsPerIndia","err","_handleMsgFromAuthPopup","event","source","location","href","startsWith","close","data","Error","upstoxAccessToken","authCode","toString","trim","access_token_resp","c","s","m","at","console","error","message","_getAccessTokenUsingAuthCode","fetchProfileAndLogin","profileResponse","fetch","headers","Authorization","Accept","catch","profileData","json","status","setItem","stringify","user_id","user_name","now","_fetchUserProfileData_n_update_storage_n_state","_handleMsgsFromContentScript","window","origin","msgFlowDirection","action","useEffect","addEventListener","removeEventListener","React","Provider","value","method","then","resp","_ref2","BrokerLogin","broker","doOnLoginClick","openAuthWindow","open","encodeURIComponent","log","referralUrlForNewSignupWithBroker","process","Loading","note","UpstoxMasterDataContext","isMasterDataReady","masterDataEpochTimestamp","getInstrument","exchange","tradingsymbol","getInstruments","getTokenForInstruments","searchInstruments","queryPrefix","limit","UpstoxMasterData_ContextProvider","isLoading","setIsLoading","setIsMasterDataReady","setMasterDataEpochTimestamp","kaagziUserId","UserContext","upstoxUserId","dbRef","exchangesAry","__setupIfNotAlreadyAndGetDbHandle","Promise","resolve","reject","_dbRef$current","constructor","_dbRef$current2","_dbRef$current3","_dbRef$current3$close","openRequest","indexedDB","onupgradeneeded","result","oldVersion","concat","forEach","storeName","objectStoreNames","contains","createObjectStore","onerror","onsuccess","onversionchange","warn","onclose","_withDbTransaction","tableOrTablesAry","mode","includes","db","tables","length","tablesAry","Array","from","isArray","i","transaction","_fetchMasterDataAndUpdateInDb","fetchRespAry","all","map","response","blobObj","blob","ds","DecompressionStream","decompressedStream","stream","pipeThrough","rows","Response","text","split","shift","row","columns","segment","csvRowData","onabort","oncomplete","table","objectStore","clear","_clearAllTables","nseTable","bseTable","nfoTable","cdsTable","mcxTable","itemsAry","index","item","put","metaDataTable","epochTimestamp","_checkValidityAndReFetchIfNecessary","request","get","lastDlEpoch","undefined","today730AM","yesterday730AM","lastDlEpochDate","Number","_checkIfMasterDataValidForToday","_upstoxInstrumentData_csvToObj","csvLine","token","symbol","expiry","lotsize","instrumenttype","instrumentObjFromCsv","exchangeSymbolsObj","reqExchangesAry","keys","instrumentsFound","instrumentsNotFound","tradingSymbol_PK","push","instrumentsAndTheirToken","toUpperCase","isInteger","cursorRequest","openCursor","IDBKeyRange","bound","instruments","count","e","cursor","target","key","continue","coverFullPage","UpstoxWebSocketContext","tick","quotes","subscribeToQuotes","instrumentTokenAry","unsubscribeToQuotes","UpstoxWebSocket_ContextProvider","isAlive","setIsAlive","setTick","quotesBasket","webSocketRef","closeSocketConnection","_webSocketRef$current2","__doOnWebSocketResponse","respData","size","arrayBuffer","aryBufr","totalBytes","byteLength","view","DataView","seekOffset","getUint8","dataNumBytesNext","dataEndsAtByte","strLength","textBytes","Uint8Array","String","fromCharCode","apply","ltp","getFloat64","closePrice","cp","tk","generateGUID","replace","r","Math","random","_str2ab","str","buf","ArrayBuffer","bufView","strLen","charCodeAt","_webSocketRef$current3","_webSocketRef$current5","subscriptionObj","guid","instrumentKeys","_webSocketRef$current4","readyState","send","_webSocketRef$current","wsUrlFetchResp_raw","wsUrlFetchResp","wsUrl","authorized_redirect_uri","socket","WebSocket","onopen","onmessage","_createSocketConnection","_webSocketRef$current6","reSubscriptionObj","_webSocketRef$current7","_webSocketRef$current8","unsubscriptionObj","searchExchangeRadioC","searchListFtr","searchListUl","selected","Upstox_MarketWatch_SearchResults","searchQuery","cancelSearch","addToWatchlist","watchlistInstrumentsAry","maxNumInstrumentsPerWatchlist","selectedExchange","setSelectedExchange","isSearchWip","setIsSearchWip","searchResults","setSearchResults","selectedInstrumentsObj","setSelectedInstrumentsObj","isAddingOpWip","setIsAddingOpWip","searchOpDelayTimeout","clearTimeout","setTimeout","searchRes","className","styles","onClick","EmptyGfx","icon","instrument","isSelected","clonedObj","some","existingInstrument","toggleInstrumentSelection","Button","variant","finally","isDisabled","isWip","wipText","active","marketWatchC","marketWatchHdr","marketWatchMain","watchListFtr","watchlistC","watchlistTabsC","wlItmsNotFoundC","UpstoxMarketWatch","openNewOrAddToPosition","setBottomSheetTitle","setBottomSheetDesc","closeBottomSheet","isReady","setIsReady","activeWatchlistIndex","setActiveWatchlistIndex","setWatchlistInstrumentsAry","watchlistInstrumentsNotFoundAry","setWatchlistInstrumentsNotFoundAry","currentlyExpandedInstrument","setCurrentlyExpandedInstrument","instrumentInvokedForTransaction","setInstrumentInvokedForTransaction","setSearchQuery","checkIfPlanActive","getWatchlistInstruments","setWatchlistMultipleInstruments","deleteWatchlistInstrument","AppDataIndexedDbContext","kaagziWatchlistInstrumentsAry","mappedObj","reduce","acc","xh","sbl","instrumentsFoundNotFoundObj","_ref3","_ref4","getWatchlist_n_loadIntoState_n_subscribeToWsLiveQuotes","_ref7","TextInput","placeholder","onChange","_quotes$token","_quotes$token2","isExpanded","WatchlistItem","wrapperElement","isExpandedView","entityName","closeExpandedView","onBuyClick","onRemoveClick","instrument_token","filter","removeInstrument","_ref8","isDark","_ref6","exch","removeNotFoundInstrument","pageNum","instrumentsToBeAddedAry","availableSpots","kiteToKaagziInstrumentFormatAry","instrumentToBeAdded","kaagziWatchlistInstrumentObj","x","watchlistInstrumentsAryCopy","_toConsumableArray","_ref5","_quotes$token3","_quotes$token4","NewTradePositionDialog","lotSize","closeDialog","cancelOp","noPosEmptyC","positionsC","positionsFtr","positionsListC","positionsNotFoundC","UpstoxPositions","positionsAry","setPositionsAry","positionsNotFoundAry","setPositionsNotFoundAry","totalPnL","setTotalPnL","currentlySelectedPos","setCurrentlySelectedPos","isWatchListViz","setIsWatchlistViz","brokerUserName","brokerLogOut","getPosition","exitPosition","setPosition","getPositions_n_loadIntoState_n_subscribeToWsLiveQuotes","_tokenForInstrumentsO","_tokenForInstrumentsO2","kaagziPositionsAry","tokenForInstrumentsObj","upstoxPositionsAry","position","qty","posData","avg","dir","ltsz","writtenPos","_closePosition","pos","exitPrice","isSellTrade","exitedPos","__updatePositionsAfterPosExit","positionToUpdateOrRemove","find","hasAlreadyRunOnMount","currentPrice","sl","tp","AppHeader","brokerLoggedInUserName","doOnWatchListBtnClick","ctaFn","ctaBtnText","_quotes$instrument_to","PositionListItem","direction","stopPropagation","ColoredNumberDisplay","currentVal","baseVal","BottomSheet","doOnClose","_quotes$currentlySele","ExitTradePositionDialog","purchasdQty","avgEntryPrice","doOnSuccessfulExit","title","setSheetTitle","setSheetDesc","App_Upstox","AppDataIndexedDb_ContextProvider","AppUpstoxPage","FullWidthAppRestrictedPageLayout","BrowserOnly","require","Head","Seo_noIndex"],"sourceRoot":""}