From 23a36699c6fed0f563a85f88e65a553c7da98085 Mon Sep 17 00:00:00 2001 From: christian harrington Date: Tue, 3 Feb 2026 13:50:39 +0000 Subject: [PATCH 01/30] prefer useEffect instead of setTimeout --- src/App.tsx | 171 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 98 insertions(+), 73 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index a1db601..56a68aa 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,15 +1,16 @@ -import { Outlet } from 'react-router-dom'; +import { useCallback, useEffect } from 'react'; +import { Outlet, useLocation } from 'react-router-dom'; import { Layout } from 'antd'; import { ModuleRegistry } from 'ag-grid-community'; import { EnterpriseCoreModule, LicenseManager } from 'ag-grid-enterprise'; import { AgCharts as AgChartsEnterprise } from 'ag-charts-enterprise'; +import { batch } from 'react-redux'; + import { useAppDispatch } from './app/hooks'; import { AppThunk } from './app/store'; import { initializeSimulationsToRun } from './features/simulationRunner/simulationRunnerSlice'; import { useLoadHistoricDailyPricesMutation } from './features/coinData/coinPriceRetrievalService'; -import { - CoinPrice, -} from './features/simulationRunConfiguration/simulationRunConfigModels'; +import { CoinPrice } from './features/simulationRunConfiguration/simulationRunConfigModels'; import { ReturnTimeStep } from './features/simulationResults/simulationResultSummaryModels'; import { updateCoinPriceHistory, @@ -18,9 +19,9 @@ import { } from './features/simulationRunConfiguration/simulationRunConfigurationSlice'; import { AntDesignThemeProvider } from './AntDesignThemeProvider'; import { MenuComponent } from './Menu'; +import { ROUTES } from './routesEnum'; import style from './app.module.scss'; -import { batch } from 'react-redux'; export interface Success { data: CoinPrice[]; @@ -28,12 +29,14 @@ export interface Success { const { Content, Header } = Layout; -// TODO: Remove and put in .env -const AG_GRID_LICENSE_KEY = - 'Using_this_{AG_Charts_and_AG_Grid}_Enterprise_key_{AG-076103}_in_excess_of_the_licence_granted_is_not_permitted___Please_report_misuse_to_legal@ag-grid.com___For_help_with_changing_this_key_please_contact_info@ag-grid.com___{Robo_Inc.}_is_granted_a_{Single_Application}_Developer_License_for_the_application_{QuantAMM_APP}_only_for_{1}_Front-End_JavaScript_developer___All_Front-End_JavaScript_developers_working_on_{QuantAMM_APP}_need_to_be_licensed___{QuantAMM_APP}_has_been_granted_a_Deployment_License_Add-on_for_{1}_Production_Environment___This_key_works_with_{AG_Charts_and_AG_Grid}_Enterprise_versions_released_before_{30_January_2026}____[v3]_[0102]_MTc2OTczMTIwMDAwMA==45158aeb0ade13e0a121e419751d0010'; +const isRoute = (value: string): value is ROUTES => + (Object.values(ROUTES) as string[]).includes(value); + + +const AG_GRID_LICENSE_KEY = process.env.AG_GRID_LICENCE_KEY ?? ''; const initialiseSimsToRun = (): AppThunk => (dispatch, getState) => { - if (getState().simRunner.simulationsToRun.length == 0) { + if (getState().simRunner.simulationsToRun.length === 0) { dispatch( initializeSimulationsToRun({ pools: getState().simConfig.simulationLiquidityPools, @@ -48,79 +51,101 @@ AgChartsEnterprise.setLicenseKey(AG_GRID_LICENSE_KEY); function App() { const dispatch = useAppDispatch(); + const location = useLocation(); const [loadHistoricPrices] = useLoadHistoricDailyPricesMutation(); - const loadPriceHistoryAsync = (): AppThunk => async (dispatch, getState) => { - const { - availableCoins, - coinPriceHistoryLoaded, - coinPriceHistoryLoadedStatus, - } = getState().simConfig; - - if (!coinPriceHistoryLoaded && coinPriceHistoryLoadedStatus === 'pending') { - dispatch(updateCoinPriceHistoryLoadedStatus('loading')); - - // 1) Fire off all the requests in parallel - const promises = availableCoins.map(async (coin) => { - const data = await loadHistoricPrices({ - coinCode: coin.coinCode, - }).unwrap(); - - const fullPriceMap = new Map(); - const timesteps = new Map(); - - data.forEach((p, i) => { - fullPriceMap.set(p.unix, p); - const ret = i === 0 ? 0 : p.close / data[i - 1].close - 1; - timesteps.set(p.unix, { date: p.date, unix: p.unix, return: ret }); - }); - - return { - coin, - dailyPriceHistory: data, - dailyPriceHistoryMap: fullPriceMap, - dailyReturns: timesteps, - }; - }); - - const results = await Promise.all(promises); - - batch(() => { - results.forEach( - ({ coin, dailyPriceHistory, dailyPriceHistoryMap, dailyReturns }) => { - dispatch( - updateCoinPriceHistory({ + const loadPriceHistoryAsync = useCallback( + (): AppThunk => + async (dispatch, getState) => { + const { + availableCoins, + coinPriceHistoryLoaded, + coinPriceHistoryLoadedStatus, + } = getState().simConfig; + + if (!coinPriceHistoryLoaded && coinPriceHistoryLoadedStatus === 'pending') { + dispatch(updateCoinPriceHistoryLoadedStatus('loading')); + + try { + // 1) Fire off all the requests in parallel + const promises = availableCoins.map(async (coin) => { + const data = await loadHistoricPrices({ coinCode: coin.coinCode, - coinName: coin.coinName, - dailyPriceHistory, - dailyPriceHistoryMap, - dailyReturns, - coinComparisons: new Map(), - deploymentByChain: coin.deploymentByChain, - }) - ); + }).unwrap(); + + const fullPriceMap = new Map(); + const timesteps = new Map(); + + data.forEach((p, i) => { + fullPriceMap.set(p.unix, p); + const ret = i === 0 ? 0 : p.close / data[i - 1].close - 1; + timesteps.set(p.unix, { + date: p.date, + unix: p.unix, + return: ret, + }); + }); + + return { + coin, + dailyPriceHistory: data, + dailyPriceHistoryMap: fullPriceMap, + dailyReturns: timesteps, + }; + }); + + const results = await Promise.all(promises); + + batch(() => { + results.forEach( + ({ coin, dailyPriceHistory, dailyPriceHistoryMap, dailyReturns }) => { + dispatch( + updateCoinPriceHistory({ + coinCode: coin.coinCode, + coinName: coin.coinName, + dailyPriceHistory, + dailyPriceHistoryMap, + dailyReturns, + coinComparisons: new Map(), + deploymentByChain: coin.deploymentByChain, + }) + ); + } + ); + dispatch(updateCoinPriceHistoryLoaded(true)); + dispatch(updateCoinPriceHistoryLoadedStatus('loaded')); + }); + } catch (e) { + dispatch(updateCoinPriceHistoryLoadedStatus('pending')); + throw e; } - ); - dispatch(updateCoinPriceHistoryLoaded(true)); - dispatch(updateCoinPriceHistoryLoadedStatus('loaded')); - }); - } - }; - - function initialisePage(page: string) { - switch (page) { - case 'simrunner': { + } + }, + [loadHistoricPrices] + ); + + const initialisePage = useCallback( + (page: string) => { + if (!isRoute(page)) { + return; + } + + if (page === ROUTES.SIMULATION_RUNNER) { dispatch(initialiseSimsToRun()); - break; } - } + }, + [dispatch] + ); + useEffect(() => { dispatch(loadPriceHistoryAsync()); - } + }, [dispatch, loadPriceHistoryAsync]); - setTimeout(() => { - dispatch(loadPriceHistoryAsync()); - }, 100); + useEffect(() => { + const segment = location.pathname.split('/')[1] ?? ''; + const page = isRoute(segment) ? segment : ROUTES.HOME; + initialisePage(page); + }, [location.pathname, initialisePage]); return ( From ee6105ade457b9840ac2c49faf429693860c1542 Mon Sep 17 00:00:00 2001 From: christian harrington Date: Tue, 3 Feb 2026 14:47:46 +0000 Subject: [PATCH 02/30] add lazy loading routes --- src/App.tsx | 144 ++++++------ src/app/hooks.ts | 1 - src/features/coinData/coinData.tsx | 5 +- src/features/documentation/about.tsx | 3 +- src/features/documentation/company.tsx | 2 +- src/features/documentation/documentation.tsx | 4 +- .../arbitrumMacro/arbitrumMacroSimView.tsx | 4 +- .../factSheets/baseMacro/baseMacroSimView.tsx | 4 +- .../factSheets/safeHaven/safeHavenSimView.tsx | 4 +- .../sonicMacro/sonicMacroSimView.tsx | 3 +- .../truflationBitcoinSimView.tsx | 4 +- .../landing/desktop/contactCompany.tsx | 6 +- src/features/documentation/research.tsx | 4 +- src/features/productDetail/productDetail.tsx | 4 +- .../productExplorer/productExplorer.tsx | 4 +- .../productExplorer/productHealthMonitor.tsx | 5 +- .../simulationSavedResultComparison.tsx | 4 +- .../simulationRunner/simulationRunner.tsx | 4 +- src/index.tsx | 5 - src/reportWebVitals.ts | 19 -- src/routeComponents.ts | 88 ++++++++ src/routes.tsx | 205 +++++++++--------- 22 files changed, 307 insertions(+), 219 deletions(-) delete mode 100644 src/reportWebVitals.ts create mode 100644 src/routeComponents.ts diff --git a/src/App.tsx b/src/App.tsx index 56a68aa..971b7bf 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect } from 'react'; +import { Suspense, useCallback, useEffect } from 'react'; import { Outlet, useLocation } from 'react-router-dom'; import { Layout } from 'antd'; import { ModuleRegistry } from 'ag-grid-community'; @@ -23,17 +23,12 @@ import { ROUTES } from './routesEnum'; import style from './app.module.scss'; -export interface Success { - data: CoinPrice[]; -} - const { Content, Header } = Layout; const isRoute = (value: string): value is ROUTES => (Object.values(ROUTES) as string[]).includes(value); - -const AG_GRID_LICENSE_KEY = process.env.AG_GRID_LICENCE_KEY ?? ''; +const AG_GRID_LICENSE_KEY = import.meta.env.AG_GRID_LICENCE_KEY ?? ''; const initialiseSimsToRun = (): AppThunk => (dispatch, getState) => { if (getState().simRunner.simulationsToRun.length === 0) { @@ -55,72 +50,79 @@ function App() { const [loadHistoricPrices] = useLoadHistoricDailyPricesMutation(); const loadPriceHistoryAsync = useCallback( - (): AppThunk => - async (dispatch, getState) => { - const { - availableCoins, - coinPriceHistoryLoaded, - coinPriceHistoryLoadedStatus, - } = getState().simConfig; - - if (!coinPriceHistoryLoaded && coinPriceHistoryLoadedStatus === 'pending') { - dispatch(updateCoinPriceHistoryLoadedStatus('loading')); - - try { - // 1) Fire off all the requests in parallel - const promises = availableCoins.map(async (coin) => { - const data = await loadHistoricPrices({ - coinCode: coin.coinCode, - }).unwrap(); - - const fullPriceMap = new Map(); - const timesteps = new Map(); - - data.forEach((p, i) => { - fullPriceMap.set(p.unix, p); - const ret = i === 0 ? 0 : p.close / data[i - 1].close - 1; - timesteps.set(p.unix, { - date: p.date, - unix: p.unix, - return: ret, - }); + (): AppThunk => async (dispatch, getState) => { + const { + availableCoins, + coinPriceHistoryLoaded, + coinPriceHistoryLoadedStatus, + } = getState().simConfig; + + if ( + !coinPriceHistoryLoaded && + coinPriceHistoryLoadedStatus === 'pending' + ) { + dispatch(updateCoinPriceHistoryLoadedStatus('loading')); + + try { + // 1) Fire off all the requests in parallel + const promises = availableCoins.map(async (coin) => { + const data = await loadHistoricPrices({ + coinCode: coin.coinCode, + }).unwrap(); + + const fullPriceMap = new Map(); + const timesteps = new Map(); + + data.forEach((p, i) => { + fullPriceMap.set(p.unix, p); + const ret = i === 0 ? 0 : p.close / data[i - 1].close - 1; + timesteps.set(p.unix, { + date: p.date, + unix: p.unix, + return: ret, }); - - return { - coin, - dailyPriceHistory: data, - dailyPriceHistoryMap: fullPriceMap, - dailyReturns: timesteps, - }; }); - const results = await Promise.all(promises); - - batch(() => { - results.forEach( - ({ coin, dailyPriceHistory, dailyPriceHistoryMap, dailyReturns }) => { - dispatch( - updateCoinPriceHistory({ - coinCode: coin.coinCode, - coinName: coin.coinName, - dailyPriceHistory, - dailyPriceHistoryMap, - dailyReturns, - coinComparisons: new Map(), - deploymentByChain: coin.deploymentByChain, - }) - ); - } - ); - dispatch(updateCoinPriceHistoryLoaded(true)); - dispatch(updateCoinPriceHistoryLoadedStatus('loaded')); - }); - } catch (e) { - dispatch(updateCoinPriceHistoryLoadedStatus('pending')); - throw e; - } + return { + coin, + dailyPriceHistory: data, + dailyPriceHistoryMap: fullPriceMap, + dailyReturns: timesteps, + }; + }); + + const results = await Promise.all(promises); + + batch(() => { + results.forEach( + ({ + coin, + dailyPriceHistory, + dailyPriceHistoryMap, + dailyReturns, + }) => { + dispatch( + updateCoinPriceHistory({ + coinCode: coin.coinCode, + coinName: coin.coinName, + dailyPriceHistory, + dailyPriceHistoryMap, + dailyReturns, + coinComparisons: new Map(), + deploymentByChain: coin.deploymentByChain, + }) + ); + } + ); + dispatch(updateCoinPriceHistoryLoaded(true)); + dispatch(updateCoinPriceHistoryLoadedStatus('loaded')); + }); + } catch (e) { + dispatch(updateCoinPriceHistoryLoadedStatus('pending')); + throw e; } - }, + } + }, [loadHistoricPrices] ); @@ -154,7 +156,9 @@ function App() { - + }> + + diff --git a/src/app/hooks.ts b/src/app/hooks.ts index 520e84e..d658a5e 100644 --- a/src/app/hooks.ts +++ b/src/app/hooks.ts @@ -1,6 +1,5 @@ import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; import type { RootState, AppDispatch } from './store'; -// Use throughout your app instead of plain `useDispatch` and `useSelector` export const useAppDispatch = () => useDispatch(); export const useAppSelector: TypedUseSelectorHook = useSelector; diff --git a/src/features/coinData/coinData.tsx b/src/features/coinData/coinData.tsx index b4eefca..fb87cce 100644 --- a/src/features/coinData/coinData.tsx +++ b/src/features/coinData/coinData.tsx @@ -61,7 +61,7 @@ export interface SeriesConfig { marker: Marker; } -export function CoinData() { +export default function CoinData() { const [currentCoin, setCurrentCoin] = useState('BTC'); const availableCoins = useAppSelector(selectAvailableCoins); const coinLoadStatus = useAppSelector(selectCoinLoadStatus); @@ -429,6 +429,5 @@ export function CoinData() { ); } -/* -*/ +export { CoinData }; diff --git a/src/features/documentation/about.tsx b/src/features/documentation/about.tsx index 14fea90..956c362 100644 --- a/src/features/documentation/about.tsx +++ b/src/features/documentation/about.tsx @@ -6,7 +6,7 @@ import { SimulationRunBreakdown } from '../simulationResults/simulationResultSum const { TabPane } = Tabs; -export function About() { +export default function About() { const [key, setKey] = useState('2'); const [breakdowns, setBreakdowns] = useState([]); const [loading, setLoading] = useState(false); @@ -117,3 +117,4 @@ export function About() { ); } +export { About }; \ No newline at end of file diff --git a/src/features/documentation/company.tsx b/src/features/documentation/company.tsx index 4669883..6242763 100644 --- a/src/features/documentation/company.tsx +++ b/src/features/documentation/company.tsx @@ -5,7 +5,7 @@ const { Title } = Typography; const { useBreakpoint } = Grid; -export function CompanyPage() { +export default function CompanyPage() { const screens = useBreakpoint(); const isMobile = !screens.lg && !screens.xl && !screens.xxl; diff --git a/src/features/documentation/documentation.tsx b/src/features/documentation/documentation.tsx index d30db4c..6b5ef9a 100644 --- a/src/features/documentation/documentation.tsx +++ b/src/features/documentation/documentation.tsx @@ -127,7 +127,7 @@ const submenuKeys = [ 'MinVariance', ]; -export function Documentation() { +export default function Documentation() { const { id } = useParams(); const [openKeys, setOpenKeys] = useState(rootSubmenuKeys); const [current, updateCurrent] = useState(id ? id : 'AutomatedMarketMakers'); @@ -213,3 +213,5 @@ export function Documentation() { ); } + +export { Documentation }; diff --git a/src/features/documentation/factSheets/arbitrumMacro/arbitrumMacroSimView.tsx b/src/features/documentation/factSheets/arbitrumMacro/arbitrumMacroSimView.tsx index 4ec6de4..67bbaf0 100644 --- a/src/features/documentation/factSheets/arbitrumMacro/arbitrumMacroSimView.tsx +++ b/src/features/documentation/factSheets/arbitrumMacro/arbitrumMacroSimView.tsx @@ -6,7 +6,7 @@ import { SimulationRunBreakdown } from '../../../simulationResults/simulationRes const { TabPane } = Tabs; -export function ArbitrumMacroSimulatorExample() { +export default function ArbitrumMacroSimulatorExample() { const [key, setKey] = useState('2'); const [breakdowns, setBreakdowns] = useState([]); const [loading, setLoading] = useState(false); @@ -116,3 +116,5 @@ export function ArbitrumMacroSimulatorExample() { ); } + +export { ArbitrumMacroSimulatorExample }; diff --git a/src/features/documentation/factSheets/baseMacro/baseMacroSimView.tsx b/src/features/documentation/factSheets/baseMacro/baseMacroSimView.tsx index 108b0b5..c8cffb3 100644 --- a/src/features/documentation/factSheets/baseMacro/baseMacroSimView.tsx +++ b/src/features/documentation/factSheets/baseMacro/baseMacroSimView.tsx @@ -6,7 +6,7 @@ import { SimulationRunBreakdown } from '../../../simulationResults/simulationRes const { TabPane } = Tabs; -export function BaseMacroSimulatorExample() { +export default function BaseMacroSimulatorExample() { const [key, setKey] = useState('2'); const [breakdowns, setBreakdowns] = useState([]); const [loading, setLoading] = useState(false); @@ -116,3 +116,5 @@ export function BaseMacroSimulatorExample() { ); } + +export { BaseMacroSimulatorExample }; diff --git a/src/features/documentation/factSheets/safeHaven/safeHavenSimView.tsx b/src/features/documentation/factSheets/safeHaven/safeHavenSimView.tsx index 5ecc14f..97911bf 100644 --- a/src/features/documentation/factSheets/safeHaven/safeHavenSimView.tsx +++ b/src/features/documentation/factSheets/safeHaven/safeHavenSimView.tsx @@ -6,7 +6,7 @@ import { SimulationRunBreakdown } from '../../../simulationResults/simulationRes const { TabPane } = Tabs; -export function SafeHavenSimulatorExample() { +export default function SafeHavenSimulatorExample() { const [key, setKey] = useState('2'); const [breakdowns, setBreakdowns] = useState([]); const [loading, setLoading] = useState(false); @@ -116,3 +116,5 @@ export function SafeHavenSimulatorExample() { ); } + +export { SafeHavenSimulatorExample }; diff --git a/src/features/documentation/factSheets/sonicMacro/sonicMacroSimView.tsx b/src/features/documentation/factSheets/sonicMacro/sonicMacroSimView.tsx index 2bc0bfb..2acee3e 100644 --- a/src/features/documentation/factSheets/sonicMacro/sonicMacroSimView.tsx +++ b/src/features/documentation/factSheets/sonicMacro/sonicMacroSimView.tsx @@ -6,7 +6,7 @@ import { SimulationRunBreakdown } from '../../../simulationResults/simulationRes const { TabPane } = Tabs; -export function SonicMacroSimulatorExample() { +export default function SonicMacroSimulatorExample() { const [key, setKey] = useState('2'); const [breakdowns, setBreakdowns] = useState([]); const [loading, setLoading] = useState(false); @@ -98,3 +98,4 @@ export function SonicMacroSimulatorExample() { ); } +export { SonicMacroSimulatorExample }; \ No newline at end of file diff --git a/src/features/documentation/factSheets/truflationBitcoin/truflationBitcoinSimView.tsx b/src/features/documentation/factSheets/truflationBitcoin/truflationBitcoinSimView.tsx index 39ed7ca..3ff5a18 100644 --- a/src/features/documentation/factSheets/truflationBitcoin/truflationBitcoinSimView.tsx +++ b/src/features/documentation/factSheets/truflationBitcoin/truflationBitcoinSimView.tsx @@ -6,7 +6,7 @@ import { SimulationRunBreakdown } from '../../../simulationResults/simulationRes const { TabPane } = Tabs; -export function TruflationBitcoinSimulatorExample() { +export default function TruflationBitcoinSimulatorExample() { const [key, setKey] = useState('2'); const [breakdowns, setBreakdowns] = useState([]); const [loading, setLoading] = useState(false); @@ -99,3 +99,5 @@ export function TruflationBitcoinSimulatorExample() { ); } + +export { TruflationBitcoinSimulatorExample }; diff --git a/src/features/documentation/landing/desktop/contactCompany.tsx b/src/features/documentation/landing/desktop/contactCompany.tsx index 3d17a4d..2529312 100644 --- a/src/features/documentation/landing/desktop/contactCompany.tsx +++ b/src/features/documentation/landing/desktop/contactCompany.tsx @@ -3,7 +3,7 @@ import { Typography } from "antd"; const { Title } = Typography; -export function ContactCompany(){ +export default function ContactCompany(){ return -} \ No newline at end of file +} + +export { ContactCompany }; \ No newline at end of file diff --git a/src/features/documentation/research.tsx b/src/features/documentation/research.tsx index 18bb455..fa415fb 100644 --- a/src/features/documentation/research.tsx +++ b/src/features/documentation/research.tsx @@ -10,7 +10,7 @@ interface ResearchProps { const { useBreakpoint } = Grid; -export function Research() { +export default function Research() { const screens = useBreakpoint(); const isMobile = !screens.lg && !screens.xl && !screens.xxl; @@ -179,3 +179,5 @@ export function Research() { ); } + +export { Research }; diff --git a/src/features/productDetail/productDetail.tsx b/src/features/productDetail/productDetail.tsx index ebfe871..18ee460 100644 --- a/src/features/productDetail/productDetail.tsx +++ b/src/features/productDetail/productDetail.tsx @@ -16,7 +16,7 @@ import TermsOfServiceGateModal from '../documentation/landing/termsOfServiceModa const { useBreakpoint } = Grid; -export const ProductDetail = () => { +export default function ProductDetail() { const { chain, id } = useParams(); const screens = useBreakpoint(); @@ -97,3 +97,5 @@ export const ProductDetail = () => { ); }; + +export { ProductDetail }; \ No newline at end of file diff --git a/src/features/productExplorer/productExplorer.tsx b/src/features/productExplorer/productExplorer.tsx index e9c0ac6..4b71ab0 100644 --- a/src/features/productExplorer/productExplorer.tsx +++ b/src/features/productExplorer/productExplorer.tsx @@ -17,7 +17,7 @@ import { ProductExplorerError } from './productExplorerError'; import { ProductItemGrid } from './productItem'; import TermsOfServiceGateModal from '../documentation/landing/termsOfServiceModal'; -export const ProductExplorer = () => { +export default function ProductExplorer() { const dispatch = useAppDispatch(); const [horizontalView, setHorizontalView] = useState(true); @@ -83,3 +83,5 @@ export const ProductExplorer = () => { ); }; +export { ProductExplorer }; + diff --git a/src/features/productExplorer/productHealthMonitor.tsx b/src/features/productExplorer/productHealthMonitor.tsx index 5092fa8..2f36bfe 100644 --- a/src/features/productExplorer/productHealthMonitor.tsx +++ b/src/features/productExplorer/productHealthMonitor.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { CURRENT_LIVE_FACTSHEETS } from '../documentation/factSheets/liveFactsheets'; import { ProductDetailHealthMonitor } from '../productDetail/productDetailHealthMonitor'; import { Grid } from 'antd'; @@ -6,7 +5,7 @@ import { Grid } from 'antd'; const { useBreakpoint } = Grid; -export const ProductHealthMonitor: React.FC = () => { +export default function ProductHealthMonitor() { const { factsheets } = CURRENT_LIVE_FACTSHEETS; const screens = useBreakpoint(); const isMobile = !screens.lg && !screens.xl && !screens.xxl; @@ -224,3 +223,5 @@ export const ProductHealthMonitor: React.FC = () => { ); }; + +export { ProductHealthMonitor }; diff --git a/src/features/simulationResults/resultComparisonTab/simulationSavedResultComparison.tsx b/src/features/simulationResults/resultComparisonTab/simulationSavedResultComparison.tsx index 3660400..5abd1b9 100644 --- a/src/features/simulationResults/resultComparisonTab/simulationSavedResultComparison.tsx +++ b/src/features/simulationResults/resultComparisonTab/simulationSavedResultComparison.tsx @@ -11,7 +11,7 @@ import { PoolDeploymentConfigReview } from '../../simulationRunner/simulationDep const { TabPane } = Tabs; -export function SimulationSavedResultComparison() { +export default function SimulationSavedResultComparison() { const savedBreakdowns = useAppSelector(selectSimulationResults); const savedSelectedBreakdowns = useAppSelector( selectSelectedSimulationResults @@ -104,3 +104,5 @@ export function SimulationSavedResultComparison() { ); } + +export { SimulationSavedResultComparison }; diff --git a/src/features/simulationRunner/simulationRunner.tsx b/src/features/simulationRunner/simulationRunner.tsx index 479b09f..ea3110f 100644 --- a/src/features/simulationRunner/simulationRunner.tsx +++ b/src/features/simulationRunner/simulationRunner.tsx @@ -41,7 +41,7 @@ import { useRef, useState } from 'react'; import { SimulatorOptions } from './simulationOptions'; -export function SimulationRunner() { +export default function SimulationRunner() { const dispatch = useAppDispatch(); const results = useAppSelector(selectSimulationRunBreakdowns); @@ -375,3 +375,5 @@ export function SimulationRunner() { ); } + +export { SimulationRunner }; diff --git a/src/index.tsx b/src/index.tsx index bc847f6..814bab2 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,7 +5,6 @@ import { Provider } from 'react-redux'; import { ApolloProvider } from '@apollo/client'; import { store } from './app/store'; import { apolloClient } from './queries/apolloClient'; -import reportWebVitals from './reportWebVitals'; import { routes } from './routes'; import './index.scss'; @@ -23,7 +22,3 @@ root.render( ); -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts deleted file mode 100644 index 325ef18..0000000 --- a/src/reportWebVitals.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ReportHandler } from 'web-vitals'; - -const reportWebVitals = (onPerfEntry?: ReportHandler) => { - if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals') - .then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }) - .catch((error) => { - console.error('Error importing web-vitals:', error); - }); - } -}; - -export default reportWebVitals; diff --git a/src/routeComponents.ts b/src/routeComponents.ts new file mode 100644 index 0000000..90eaba7 --- /dev/null +++ b/src/routeComponents.ts @@ -0,0 +1,88 @@ +import { lazy } from 'react'; + +export const CoinData = lazy(() => import('./features/coinData/coinData')); +export const SimulationRunner = lazy( + () => import('./features/simulationRunner/simulationRunner') +); + +export const ProductExplorer = lazy( + () => import('./features/productExplorer/productExplorer') +); +export const ProductDetail = lazy( + () => import('./features/productDetail/productDetail') +); + +export const About = lazy(() => import('./features/documentation/about')); +export const Documentation = lazy( + () => import('./features/documentation/documentation') +); + +export const SimulationSavedResultComparison = lazy( + () => + import( + './features/simulationResults/resultComparisonTab/simulationSavedResultComparison' + ) +); + +export const LandingPage = lazy( + () => import('./features/documentation/landing/landingPage') +); +export const Research = lazy(() => import('./features/documentation/research')); +export const CompanyPage = lazy(() => import('./features/documentation/company')); +export const ContactCompany = lazy( + () => import('./features/documentation/landing/desktop/contactCompany') +); + +export const TermsOfService = lazy( + () => import('./features/documentation/landing/newTermsOfService') +); +export const IneligibleUser = lazy( + () => import('./features/documentation/landing/IneligableUserLanding') +); + +export const SafeHavenFactSheet = lazy( + () => import('./features/documentation/factSheets/safeHaven/safeHaven') +); +export const BaseMacroFactSheet = lazy( + () => import('./features/documentation/factSheets/baseMacro/baseMacro') +); +export const SonicMacroFactSheet = lazy( + () => import('./features/documentation/factSheets/sonicMacro/sonicMacro') +); +export const ArbitrumMacroFactSheet = lazy( + () => + import('./features/documentation/factSheets/arbitrumMacro/arbitrumMacro') +); +export const TruflationBitcoinFactSheet = lazy( + () => + import( + './features/documentation/factSheets/truflationBitcoin/truflationBitcoin' + ) +); + +export const SafeHavenSimulatorExample = lazy( + () => import('./features/documentation/factSheets/safeHaven/safeHavenSimView') +); +export const BaseMacroSimulatorExample = lazy( + () => import('./features/documentation/factSheets/baseMacro/baseMacroSimView') +); +export const SonicMacroSimulatorExample = lazy( + () => + import('./features/documentation/factSheets/sonicMacro/sonicMacroSimView') +); +export const ArbitrumMacroSimulatorExample = lazy( + () => + import( + './features/documentation/factSheets/arbitrumMacro/arbitrumMacroSimView' + ) +); +export const TruflationBitcoinSimulatorExample = lazy( + () => + import( + './features/documentation/factSheets/truflationBitcoin/truflationBitcoinSimView' + ) +); + +export const ProductHealthMonitor = lazy( + () => import('./features/productExplorer/productHealthMonitor') +); \ No newline at end of file diff --git a/src/routes.tsx b/src/routes.tsx index d845ccd..1f061b2 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -1,151 +1,148 @@ -import { Navigate, createBrowserRouter } from 'react-router-dom'; +import { + About, + ArbitrumMacroFactSheet, + ArbitrumMacroSimulatorExample, + BaseMacroFactSheet, + BaseMacroSimulatorExample, + CoinData, + CompanyPage, + ContactCompany, + Documentation, + IneligibleUser, + LandingPage, + ProductDetail, + ProductExplorer, + ProductHealthMonitor, + Research, + SafeHavenFactSheet, + SafeHavenSimulatorExample, + SimulationRunner, + SimulationSavedResultComparison, + SonicMacroFactSheet, + SonicMacroSimulatorExample, + TermsOfService, + TruflationBitcoinFactSheet, + TruflationBitcoinSimulatorExample, +} from './routeComponents'; + +import { + Navigate, + createBrowserRouter, + isRouteErrorResponse, + useRouteError, +} from 'react-router-dom'; import App from './App'; -import { CoinData } from './features/coinData/coinData'; -import { SimulationRunner } from './features/simulationRunner/simulationRunner'; -import { ProductDetail, ProductExplorer } from './features'; -import { About } from './features/documentation/about'; -import { Documentation } from './features/documentation/documentation'; -import { SimulationSavedResultComparison } from './features/simulationResults/resultComparisonTab/simulationSavedResultComparison'; import { ROUTES } from './routesEnum'; -import LandingPage from './features/documentation/landing/landingPage'; -import { Research } from './features/documentation/research'; -import { CompanyPage } from './features/documentation/company'; -import { ContactCompany } from './features/documentation/landing/desktop/contactCompany'; -import TermsOfService from './features/documentation/landing/newTermsOfService'; -import InegligibleUser from './features/documentation/landing/IneligableUserLanding'; -import SafeHavenFactSheet from './features/documentation/factSheets/safeHaven/safeHaven'; -import BaseMacroFactSheet from './features/documentation/factSheets/baseMacro/baseMacro'; -import { SafeHavenSimulatorExample } from './features/documentation/factSheets/safeHaven/safeHavenSimView'; -import { BaseMacroSimulatorExample } from './features/documentation/factSheets/baseMacro/baseMacroSimView'; -import SonicMacroFactSheet from './features/documentation/factSheets/sonicMacro/sonicMacro'; -import { SonicMacroSimulatorExample } from './features/documentation/factSheets/sonicMacro/sonicMacroSimView'; -import AbritrumMacroFactSheet from './features/documentation/factSheets/arbitrumMacro/arbitrumMacro'; -import { ArbitrumMacroSimulatorExample } from './features/documentation/factSheets/arbitrumMacro/arbitrumMacroSimView'; -import { ProductHealthMonitor } from './features/productExplorer/productHealthMonitor'; -import TruflationBitcoinFactSheet from './features/documentation/factSheets/truflationBitcoin/truflationBitcoin'; -import { TruflationBitcoinSimulatorExample } from './features/documentation/factSheets/truflationBitcoin/truflationBitcoinSimView'; const BASE_ROUTE = '/'; +function RouteErrorBoundary() { + const error = useRouteError(); + + if (isRouteErrorResponse(error)) { + return ( +
+

+ {error.status} {error.statusText} +

+

+ {typeof error.data === 'string' + ? error.data + : 'Something went wrong.'} +

+
+ ); + } + + return ( +
+

Something went wrong.

+
+ ); +} + export const routes = createBrowserRouter([ { path: BASE_ROUTE, element: , + errorElement: , children: [ - { - index: true, - element: , - }, - { - path: ROUTES.HOME, - element: , - }, + { index: true, element: }, + { path: ROUTES.HOME, element: }, + { path: ROUTES.DOCUMENTATION, children: [ - { - index: true, - element: , - }, - { - path: ':id', - element: , - }, + { index: true, element: }, + { path: ':id', element: }, ], }, + { path: ROUTES.PRODUCT_EXPLORER, children: [ - { - index: true, - element: , - }, - { - path: ':chain/:id', - element: , - }, + { index: true, element: }, + { path: ':chain/:id', element: }, ], }, + { - path: 'factsheet/' + ROUTES.SAFEHAVENFACTSHEET, - element:, - }, - { - path: 'factsheet/example/' + ROUTES.SAFEHAVENFACTSHEET, - element:, - }, - { - path: 'factsheet/example/' + ROUTES.BASEMACROFACTSHEET, - element:, - }, - { - path: 'factsheet/example/' + ROUTES.SONICMACROFACTSHEET, - element:, - }, - { - path: 'factsheet/example/' + ROUTES.ARBITRUMMACROFACTSHEET, - element:, - }, - { - path: 'factsheet/example/' + ROUTES.TRUFLATIONBITCOINFACTSHEET, - element:, - }, - { - path: 'factsheet/' + ROUTES.BASEMACROFACTSHEET, - element:, - }, - { - path: 'factsheet/' + ROUTES.SONICMACROFACTSHEET, - element:, + path: `factsheet/${ROUTES.SAFEHAVENFACTSHEET}`, + element: , }, { - path: 'factsheet/' + ROUTES.ARBITRUMMACROFACTSHEET, - element:, + path: `factsheet/${ROUTES.BASEMACROFACTSHEET}`, + element: , }, { - path: 'factsheet/' + ROUTES.TRUFLATIONBITCOINFACTSHEET, - element:, + path: `factsheet/${ROUTES.SONICMACROFACTSHEET}`, + element: , }, { - path: ROUTES.EXAMPLES, - element: , + path: `factsheet/${ROUTES.ARBITRUMMACROFACTSHEET}`, + element: , }, { - path: ROUTES.COMPANY, - element: , + path: `factsheet/${ROUTES.TRUFLATIONBITCOINFACTSHEET}`, + element: , }, + { - path: ROUTES.INELIGIBLEUSER, - element: , + path: `factsheet/example/${ROUTES.SAFEHAVENFACTSHEET}`, + element: , }, { - path: ROUTES.RESEARCH, - element: , + path: `factsheet/example/${ROUTES.BASEMACROFACTSHEET}`, + element: , }, { - path: ROUTES.COINS, - element: , + path: `factsheet/example/${ROUTES.SONICMACROFACTSHEET}`, + element: , }, { - path:ROUTES.CONTACT, - element: + path: `factsheet/example/${ROUTES.ARBITRUMMACROFACTSHEET}`, + element: , }, { - path: ROUTES.SIMULATION_RUNNER, - element: , + path: `factsheet/example/${ROUTES.TRUFLATIONBITCOINFACTSHEET}`, + element: , }, + + { path: ROUTES.EXAMPLES, element: }, + { path: ROUTES.COMPANY, element: }, + { path: ROUTES.INELIGIBLEUSER, element: }, + { path: ROUTES.RESEARCH, element: }, + { path: ROUTES.COINS, element: }, + { path: ROUTES.CONTACT, element: }, + { path: ROUTES.SIMULATION_RUNNER, element: }, { path: ROUTES.SIMULATION_COMPARER, element: , }, - { - path: ROUTES.TOS, - element: , - }, - { - path: ROUTES.HEALTH_MONITOR, - element: , - } + { path: ROUTES.TOS, element: }, + { path: ROUTES.HEALTH_MONITOR, element: }, + + { path: '*', element: }, ], }, ]); From 436b7f08d7af9478ddea7797973c46a2111ae11f Mon Sep 17 00:00:00 2001 From: christian harrington Date: Thu, 5 Feb 2026 14:33:57 +0000 Subject: [PATCH 03/30] formatting and remove bad call --- src/Menu.tsx | 1 - src/queries/getCurrentPrices.graphql | 8 ++------ src/queries/getPoolEvents.graphql | 8 ++++---- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/Menu.tsx b/src/Menu.tsx index 19362e2..e2e0958 100644 --- a/src/Menu.tsx +++ b/src/Menu.tsx @@ -58,7 +58,6 @@ export const MenuComponent: FC = ({ initialise }) => { const toggleTheme = (isChecked: boolean) => { dispatch(changeTheme(isChecked || (current as ROUTES) == ROUTES.HOME)); - changeTheme(isChecked); }; const handleClick: MenuProps['onClick'] = useCallback( diff --git a/src/queries/getCurrentPrices.graphql b/src/queries/getCurrentPrices.graphql index 973ff3f..a8dbbe4 100644 --- a/src/queries/getCurrentPrices.graphql +++ b/src/queries/getCurrentPrices.graphql @@ -1,9 +1,5 @@ -query GetCurrentPrices( - $chains: [GqlChain!]! -) { - tokenGetCurrentPrices( - chains: $chains - ) { +query GetCurrentPrices($chains: [GqlChain!]!) { + tokenGetCurrentPrices(chains: $chains) { address price } diff --git a/src/queries/getPoolEvents.graphql b/src/queries/getPoolEvents.graphql index 333d996..e899ca6 100644 --- a/src/queries/getPoolEvents.graphql +++ b/src/queries/getPoolEvents.graphql @@ -12,13 +12,13 @@ query GetPoolEvents($first: Int, $skip: Int, $where: GqlPoolEventsFilter) { tx ... on GqlPoolSwapEventV3 { tokenIn { - address, - amount, + address + amount valueUSD } tokenOut { - address, - amount, + address + amount valueUSD } } From 45cb1158a295f017cd40b0b68d802944d3c90b4b Mon Sep 17 00:00:00 2001 From: christian harrington Date: Thu, 5 Feb 2026 14:58:07 +0000 Subject: [PATCH 04/30] initial clean up of coin components --- .../coinData/coinComparisonCalculator.ts | 104 ++++++++++-------- .../coinData/coinCurrentPriceSlice.ts | 14 ++- .../coinData/coinCurrentPricesPolling.tsx | 10 +- src/features/coinData/coinData.tsx | 27 +++-- 4 files changed, 92 insertions(+), 63 deletions(-) diff --git a/src/features/coinData/coinComparisonCalculator.ts b/src/features/coinData/coinComparisonCalculator.ts index 006c7d5..f81e218 100644 --- a/src/features/coinData/coinComparisonCalculator.ts +++ b/src/features/coinData/coinComparisonCalculator.ts @@ -15,35 +15,48 @@ export function CalculateCoinComparison( }; } +function getMinMaxUnix(returns: ReturnTimeStep[]) { + let min = Number.POSITIVE_INFINITY; + let max = Number.NEGATIVE_INFINITY; + + for (const item of returns) { + if (item.unix < min) min = item.unix; + if (item.unix > max) max = item.unix; + } + + return { min, max }; +} + //tracking error export function calculateTrackingError( rPortfolio: ReturnTimeStep[], rBenchmark: ReturnTimeStep[] ): number { - const rPortfolioMax = rPortfolio.sort((a, b) => (a.unix > b.unix ? -1 : 1))[0] - .unix; - const rBenchmarkMax = rBenchmark.sort((a, b) => (a.unix > b.unix ? -1 : 1))[0] - .unix; - const rPortfolioMin = rPortfolio.sort((a, b) => (a.unix < b.unix ? -1 : 1))[0] - .unix; - const rBenchmarkMin = rBenchmark.sort((a, b) => (a.unix < b.unix ? -1 : 1))[0] - .unix; - - let rangeMin = rPortfolioMin; - if (rangeMin < rBenchmarkMin) { - rangeMin = rBenchmarkMin; + if (rPortfolio.length === 0 || rBenchmark.length === 0) { + return 0; } - let rangeMax = rPortfolioMax; - if (rangeMax > rBenchmarkMax) { - rangeMax = rBenchmarkMax; + + const { min: rPortfolioMin, max: rPortfolioMax } = + getMinMaxUnix(rPortfolio); + const { min: rBenchmarkMin, max: rBenchmarkMax } = + getMinMaxUnix(rBenchmark); + + const rangeMin = Math.max(rPortfolioMin, rBenchmarkMin); + const rangeMax = Math.min(rPortfolioMax, rBenchmarkMax); + if (rangeMax <= rangeMin) { + return 0; } const comparisonRPortfolio = rPortfolio .filter((x) => rangeMin < x.unix && rangeMax > x.unix) - .sort((a, b) => (a.unix < b.unix ? -1 : 1)); - const comparionRBenchmark = rBenchmark + .sort((a, b) => a.unix - b.unix); + const comparisonRBenchmark = rBenchmark .filter((x) => rangeMin < x.unix && rangeMax > x.unix) - .sort((a, b) => (a.unix < b.unix ? -1 : 1)); + .sort((a, b) => a.unix - b.unix); + + if (comparisonRPortfolio.length === 0 || comparisonRBenchmark.length === 0) { + return 0; + } const rPortfolioMean = comparisonRPortfolio @@ -53,23 +66,23 @@ export function calculateTrackingError( }, 0) / comparisonRPortfolio.length; const rBenchmarkMean = - comparionRBenchmark + comparisonRBenchmark .map((x) => x.return) .reduce((accumulator, current) => { return accumulator + current; - }, 0) / comparionRBenchmark.length; + }, 0) / comparisonRBenchmark.length; const meanDif = rPortfolioMean - rBenchmarkMean; const numerator = comparisonRPortfolio .map((x) => { let rbEquiv = findLastAvailableReturn( - comparionRBenchmark, + comparisonRBenchmark, x.unix, 1, 604800000 /*daily*/ )?.return; - if (rbEquiv == undefined) { + if (rbEquiv === undefined) { rbEquiv = x.return; } @@ -86,31 +99,32 @@ export function calculateTrackingError( export function calculateCovariance( rPortfolio: ReturnTimeStep[], rBenchmark: ReturnTimeStep[] -) { - const rPortfolioMax = rPortfolio.sort((a, b) => (a.unix > b.unix ? -1 : 1))[0] - .unix; - const rBenchmarkMax = rBenchmark.sort((a, b) => (a.unix > b.unix ? -1 : 1))[0] - .unix; - const rPortfolioMin = rPortfolio.sort((a, b) => (a.unix < b.unix ? -1 : 1))[0] - .unix; - const rBenchmarkMin = rBenchmark.sort((a, b) => (a.unix < b.unix ? -1 : 1))[0] - .unix; - - let rangeMin = rPortfolioMin; - if (rangeMin < rBenchmarkMin) { - rangeMin = rBenchmarkMin; +): number { + if (rPortfolio.length === 0 || rBenchmark.length === 0) { + return 0; } - let rangeMax = rPortfolioMax; - if (rangeMax > rBenchmarkMax) { - rangeMax = rBenchmarkMax; + + const { min: rPortfolioMin, max: rPortfolioMax } = + getMinMaxUnix(rPortfolio); + const { min: rBenchmarkMin, max: rBenchmarkMax } = + getMinMaxUnix(rBenchmark); + + const rangeMin = Math.max(rPortfolioMin, rBenchmarkMin); + const rangeMax = Math.min(rPortfolioMax, rBenchmarkMax); + if (rangeMax <= rangeMin) { + return 0; } const comparisonRPortfolio = rPortfolio .filter((x) => rangeMin < x.unix && rangeMax > x.unix) - .sort((a, b) => (a.unix < b.unix ? -1 : 1)); - const comparionRBenchmark = rBenchmark + .sort((a, b) => a.unix - b.unix); + const comparisonRBenchmark = rBenchmark .filter((x) => rangeMin < x.unix && rangeMax > x.unix) - .sort((a, b) => (a.unix < b.unix ? -1 : 1)); + .sort((a, b) => a.unix - b.unix); + + if (comparisonRPortfolio.length === 0 || comparisonRBenchmark.length === 0) { + return 0; + } let rPortfolioMean = 0; comparisonRPortfolio.forEach((v) => { @@ -121,23 +135,23 @@ export function calculateCovariance( let rBenchmarkMean = 0; - comparionRBenchmark.forEach((v) => { + comparisonRBenchmark.forEach((v) => { rBenchmarkMean += v.return; }); - rBenchmarkMean /= comparionRBenchmark.length; + rBenchmarkMean /= comparisonRBenchmark.length; let sumRiRj = 0; comparisonRPortfolio.forEach((x) => { let rbEquiv = findLastAvailableReturn( - comparionRBenchmark, + comparisonRBenchmark, x.unix, 1, 604800000 /*daily*/ )?.return; - if (rbEquiv == undefined) { + if (rbEquiv === undefined) { rbEquiv = x.return; } diff --git a/src/features/coinData/coinCurrentPriceSlice.ts b/src/features/coinData/coinCurrentPriceSlice.ts index 60a2ad2..b66b3b7 100644 --- a/src/features/coinData/coinCurrentPriceSlice.ts +++ b/src/features/coinData/coinCurrentPriceSlice.ts @@ -12,8 +12,11 @@ import { import type { RootState, AppDispatch } from '../../app/store'; import { CURRENT_LIVE_FACTSHEETS } from '../documentation/factSheets/liveFactsheets'; -export const COIN_PRICE_CHAINS: GqlChain[] = - CURRENT_LIVE_FACTSHEETS.factsheets.map((f) => f.poolChain as GqlChain); +export const COIN_PRICE_CHAINS: GqlChain[] = Array.from( + new Set( + CURRENT_LIVE_FACTSHEETS.factsheets.map((f) => f.poolChain as GqlChain) + ) +); export interface CoinPriceEntry { address: string; @@ -83,7 +86,6 @@ export const fetchCoinCurrentPrices = createAsyncThunk< chains && chains.length > 0 ? chains : COIN_PRICE_CHAINS ).slice(); const fetchedAt = Date.now(); - console.log('fetching data'); const results = await Promise.all( usedChains.map(async (chain) => { const { data } = await client.query({ @@ -91,7 +93,6 @@ export const fetchCoinCurrentPrices = createAsyncThunk< variables: { chains: [chain] }, fetchPolicy: 'network-only', }); - console.log(data); const items = data?.tokenGetCurrentPrices ?? []; const mapForChain: Record = {}; @@ -110,7 +111,10 @@ export const fetchCoinCurrentPrices = createAsyncThunk< }) ); - const perChain: Record> = {} as any; + const perChain: Record> = {} as Record< + GqlChain, + Record + >; for (const { chain, mapForChain } of results) { perChain[chain] = mapForChain; } diff --git a/src/features/coinData/coinCurrentPricesPolling.tsx b/src/features/coinData/coinCurrentPricesPolling.tsx index a2e2750..bde276b 100644 --- a/src/features/coinData/coinCurrentPricesPolling.tsx +++ b/src/features/coinData/coinCurrentPricesPolling.tsx @@ -1,12 +1,14 @@ // CurrentPricePollingGate.tsx import { useEffect } from 'react'; -import { useDispatch } from 'react-redux'; -import type { AppDispatch } from '../../app/store'; -import { startCoinCurrentPricesPolling, stopCoinCurrentPricesPolling } from './coinCurrentPriceSlice'; +import { useAppDispatch } from '../../app/hooks'; import { apolloClient } from '../../queries/apolloClient'; +import { + startCoinCurrentPricesPolling, + stopCoinCurrentPricesPolling, +} from './coinCurrentPriceSlice'; export function CurrentPricePollingGate(): null { - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); useEffect(() => { dispatch(startCoinCurrentPricesPolling(apolloClient, 30_000)); diff --git a/src/features/coinData/coinData.tsx b/src/features/coinData/coinData.tsx index fb87cce..2fd1ab3 100644 --- a/src/features/coinData/coinData.tsx +++ b/src/features/coinData/coinData.tsx @@ -1,3 +1,4 @@ +// TODO CH split into subcomponents import { useState } from 'react'; import { AgGridReact } from 'ag-grid-react'; import { AgTimeAxisOptions } from 'ag-charts-community'; @@ -82,7 +83,9 @@ export default function CoinData() { colId: 'open', headerName: 'open', valueGetter: (params: { data: CoinPrice }) => { - return params.data.open == 1 / 0 ? undefined : params.data.open; + return params.data.open === Number.POSITIVE_INFINITY + ? undefined + : params.data.open; }, filter: 'agNumberColumnFilter', type: ['numericColumn', 'nonEditableColumn'], @@ -92,7 +95,9 @@ export default function CoinData() { colId: 'high', headerName: 'high', valueGetter: (params: { data: CoinPrice }) => { - return params.data.high == 1 / 0 ? undefined : params.data.high; + return params.data.high === Number.POSITIVE_INFINITY + ? undefined + : params.data.high; }, filter: 'agNumberColumnFilter', type: ['numericColumn', 'nonEditableColumn'], @@ -102,7 +107,9 @@ export default function CoinData() { colId: 'low', headerName: 'low', valueGetter: (params: { data: CoinPrice }) => { - return params.data.low == 1 / 0 ? undefined : params.data.low; + return params.data.low === Number.POSITIVE_INFINITY + ? undefined + : params.data.low; }, filter: 'agNumberColumnFilter', type: ['numericColumn', 'nonEditableColumn'], @@ -226,23 +233,25 @@ export default function CoinData() { const getCurrentPriceData = () => { const empty: CoinPrice[] = []; - if (currentCoin == '3mTbillDaily') { + if (currentCoin === '3mTbillDaily') { const tbillData = tBillPrices as TBillYield[]; const tBillCloseData: CoinPrice[] = tbillData.map((x) => { return { date: x.date, unix: new Date(x.date).getTime(), close: x.rate, - open: 1 / 0, - low: 1 / 0, - high: 1 / 0, + open: Number.POSITIVE_INFINITY, + low: Number.POSITIVE_INFINITY, + high: Number.POSITIVE_INFINITY, }; }); return tBillCloseData; } - const availableCoin = availableCoins.find((x) => x.coinCode == currentCoin); + const availableCoin = availableCoins.find( + (x) => x.coinCode === currentCoin + ); return availableCoin?.dailyPriceHistory ?? empty; }; @@ -312,7 +321,7 @@ export default function CoinData() { defaultSelectedKeys={[currentCoin]} items={getCoinSelections()} onClick={(x) => { - setCurrentCoin(x.key); + setCurrentCoin(String(x.key)); }} activeKey={currentCoin} /> From df1659562ac4655dd13488e6560383678e20eb11 Mon Sep 17 00:00:00 2001 From: christian harrington Date: Thu, 5 Feb 2026 15:10:53 +0000 Subject: [PATCH 05/30] additional formatting changes, fix to setters in doc slice --- src/features/documentation/documentation.tsx | 2 +- .../documentation/documentationSlice.ts | 4 +-- .../factSheets/desktop/factsheetDesktop.tsx | 26 +++++++++------- .../factSheets/mobile/factsheetMobile.tsx | 30 +++++++++++-------- .../customTruflationFactsheetDesktop.tsx | 20 +++++++++---- .../customTruflationFactsheetMobile.tsx | 17 ++++++----- .../landing/desktop/bannerProductSection.tsx | 4 +-- .../documentation/landing/desktop/faq.tsx | 6 ++-- .../landing/desktop/strategySummary.tsx | 28 +++++++++-------- .../documentation/poolTypes/quantamm.tsx | 4 +-- .../updateRules/antiMomentum.tsx | 6 ++-- .../updateRules/channelFollowing.tsx | 18 ++++++++--- .../updateRules/heatmaps/heatMapGraphs.tsx | 6 ++-- .../updateRules/minVarianceUpdateRule.tsx | 6 ++-- .../updateRules/momentumUpdateRule.tsx | 6 ++-- .../updateRules/powerChannelUpdateRule.tsx | 12 +++++--- .../truflationRegimeUpdateRule.tsx | 12 ++++---- 17 files changed, 122 insertions(+), 85 deletions(-) diff --git a/src/features/documentation/documentation.tsx b/src/features/documentation/documentation.tsx index 6b5ef9a..717ebc8 100644 --- a/src/features/documentation/documentation.tsx +++ b/src/features/documentation/documentation.tsx @@ -133,7 +133,7 @@ export default function Documentation() { const [current, updateCurrent] = useState(id ? id : 'AutomatedMarketMakers'); const onClick = (e: any) => { - if (submenuKeys.indexOf(e.key) != -1) { + if (submenuKeys.indexOf(e.key) !== -1) { updateCurrent(e.key); } }; diff --git a/src/features/documentation/documentationSlice.ts b/src/features/documentation/documentationSlice.ts index 751ec77..eff229a 100644 --- a/src/features/documentation/documentationSlice.ts +++ b/src/features/documentation/documentationSlice.ts @@ -69,13 +69,13 @@ export const documentationSlice = createSlice({ state.updateRuleTrainingFilter.startDate = action.payload; }, setTrainingWindow: (state, action: PayloadAction) => { - state.updateRuleTrainingFilter.endDate = action.payload; + state.updateRuleTrainingFilter.trainingWindow = action.payload; }, setMemorySettings: (state, action: PayloadAction) => { state.updateRuleTrainingFilter.memorySettings = action.payload; }, setTradingFunction: (state, action: PayloadAction) => { - state.updateRuleTrainingFilter.endDate = action.payload; + state.updateRuleTrainingFilter.tradingFunction = action.payload; }, setStrategyRefresh: (state, action: PayloadAction) => { state.updateRuleTrainingFilter.strategyRefresh = action.payload; diff --git a/src/features/documentation/factSheets/desktop/factsheetDesktop.tsx b/src/features/documentation/factSheets/desktop/factsheetDesktop.tsx index 888f076..a43f463 100644 --- a/src/features/documentation/factSheets/desktop/factsheetDesktop.tsx +++ b/src/features/documentation/factSheets/desktop/factsheetDesktop.tsx @@ -1,3 +1,4 @@ +// TODO CH split into subcomponents import { Button, Card, Col, Collapse, Row, Tooltip } from 'antd'; import { useEffect, useState } from 'react'; import { useMemo } from 'react'; @@ -95,10 +96,13 @@ export function FactSheetDesktop(props: FactsheetDesktopProps) { {props.model.defaultPeriod[1]} - {props.model.alternatePeriod[0] != '' ? - - {props.model.alternatePeriod[1]} - : <>} + {props.model.alternatePeriod[0] !== '' ? ( + + {props.model.alternatePeriod[1]} + + ) : ( + <> + )} ); @@ -410,13 +414,13 @@ export function FactSheetDesktop(props: FactsheetDesktopProps) { label: x.label, children: ( <> -