diff --git a/cashtab/package-lock.json b/cashtab/package-lock.json
--- a/cashtab/package-lock.json
+++ b/cashtab/package-lock.json
@@ -45,7 +45,9 @@
                 "@types/lodash.debounce": "^4.0.9",
                 "@types/randombytes": "^2.0.3",
                 "@types/react": "^18.3.12",
+                "@types/react-dom": "^18.3.1",
                 "@types/styled-components": "^5.1.34",
+                "@types/webpack-env": "^1.18.5",
                 "@types/wif": "^2.0.5",
                 "assert": "^2.0.0",
                 "babel-jest": "^29.7.0",
@@ -110,7 +112,7 @@
             }
         },
         "../modules/chronik-client": {
-            "version": "1.4.0",
+            "version": "2.0.0",
             "license": "MIT",
             "dependencies": {
                 "@types/ws": "^8.2.1",
@@ -2858,7 +2860,7 @@
             }
         },
         "../modules/ecash-agora": {
-            "version": "0.1.1",
+            "version": "0.2.0",
             "license": "MIT",
             "dependencies": {
                 "chronik-client": "file:../chronik-client",
@@ -6890,7 +6892,7 @@
             }
         },
         "../modules/ecash-lib": {
-            "version": "0.2.1",
+            "version": "1.1.0",
             "license": "MIT",
             "dependencies": {
                 "ecashaddrjs": "file:../ecashaddrjs"
@@ -24077,6 +24079,16 @@
                 "csstype": "^3.0.2"
             }
         },
+        "node_modules/@types/react-dom": {
+            "version": "18.3.1",
+            "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
+            "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@types/react": "*"
+            }
+        },
         "node_modules/@types/resolve": {
             "version": "1.17.1",
             "dev": true,
@@ -24155,6 +24167,13 @@
             "dev": true,
             "license": "MIT"
         },
+        "node_modules/@types/webpack-env": {
+            "version": "1.18.5",
+            "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.5.tgz",
+            "integrity": "sha512-wz7kjjRRj8/Lty4B+Kr0LN6Ypc/3SymeCCGSbaXp2leH0ZVg/PriNiOwNj4bD4uphI7A8NXS4b6Gl373sfO5mA==",
+            "dev": true,
+            "license": "MIT"
+        },
         "node_modules/@types/wif": {
             "version": "2.0.5",
             "resolved": "https://registry.npmjs.org/@types/wif/-/wif-2.0.5.tgz",
diff --git a/cashtab/package.json b/cashtab/package.json
--- a/cashtab/package.json
+++ b/cashtab/package.json
@@ -62,7 +62,9 @@
         "@types/lodash.debounce": "^4.0.9",
         "@types/randombytes": "^2.0.3",
         "@types/react": "^18.3.12",
+        "@types/react-dom": "^18.3.1",
         "@types/styled-components": "^5.1.34",
+        "@types/webpack-env": "^1.18.5",
         "@types/wif": "^2.0.5",
         "assert": "^2.0.0",
         "babel-jest": "^29.7.0",
diff --git a/cashtab/src/components/Common/GoogleAnalytics.js b/cashtab/src/components/Common/GoogleAnalytics.js
deleted file mode 100644
--- a/cashtab/src/components/Common/GoogleAnalytics.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2024 The Bitcoin developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-import { useEffect } from 'react';
-import { useLocation } from 'react-router-dom';
-
-let ReactGA;
-if (process.env.REACT_APP_BUILD_ENV !== 'extension') {
-    ReactGA = require('react-ga');
-}
-
-const RouteTracker = () => {
-    const location = useLocation();
-    useEffect(() => {
-        ReactGA.pageview(location.pathname + location.search);
-    }, [location]);
-};
-
-const init =
-    process.env.REACT_APP_BUILD_ENV !== 'extension'
-        ? () => {
-              const isGAEnabled = process.env.NODE_ENV === 'production';
-              if (isGAEnabled) {
-                  ReactGA.initialize(process.env.REACT_APP_GOOGLE_ANALYTICS);
-              }
-
-              return isGAEnabled;
-          }
-        : // We return a new function if we are building the extension, because
-          // in this case ReactGA is undefined and will not have an initialize method
-          () => {
-              return false;
-          };
-
-export const Event =
-    process.env.REACT_APP_BUILD_ENV !== 'extension'
-        ? // If you are not building the extension, export GA event tracking function
-          (category, action, label) => {
-              ReactGA.event({
-                  category: category,
-                  action: action,
-                  label: label,
-              });
-          }
-        : // If you are building the extension, export function that does nothing
-          // Note: it's not practical to conditionally remove calls to this function from all screens
-          // So, more practical to just define it as a do-nothing function for the extension
-          () => undefined;
-
-export default process.env.REACT_APP_BUILD_ENV !== 'extension'
-    ? {
-          RouteTracker,
-          init,
-      }
-    : {
-          RouteTracker: () => undefined,
-          init,
-      };
diff --git a/cashtab/src/components/Common/GoogleAnalytics.ts b/cashtab/src/components/Common/GoogleAnalytics.ts
new file mode 100644
--- /dev/null
+++ b/cashtab/src/components/Common/GoogleAnalytics.ts
@@ -0,0 +1,71 @@
+// Copyright (c) 2024 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import React, { useEffect } from 'react';
+import { useLocation } from 'react-router-dom';
+
+interface ReactGA {
+    pageview: (path: string) => void;
+    initialize: (trackingID: string) => void;
+    event: (event: {
+        category: string;
+        action: string;
+        label?: string;
+    }) => void;
+}
+
+let ReactGA: ReactGA | undefined;
+if (process.env.REACT_APP_BUILD_ENV !== 'extension') {
+    ReactGA = require('react-ga');
+}
+
+const RouteTracker: React.FC | (() => undefined) =
+    typeof ReactGA === 'undefined'
+        ? () => undefined
+        : () => {
+              const location = useLocation();
+              useEffect(() => {
+                  ReactGA.pageview(location.pathname + location.search);
+              }, [location]);
+              return null;
+          };
+
+const init =
+    typeof ReactGA === 'undefined'
+        ? // We return false here to prevent rendering route tracker in non-prod and extension
+          // see top level index.tsx
+          // in this case ReactGA is undefined and will not have an initialize method
+          () => {
+              return false;
+          }
+        : () => {
+              const isGAEnabled = process.env.NODE_ENV === 'production';
+              if (isGAEnabled) {
+                  ReactGA.initialize(
+                      process.env.REACT_APP_GOOGLE_ANALYTICS as string,
+                  );
+              }
+
+              return isGAEnabled;
+          };
+
+export const Event =
+    typeof ReactGA === 'undefined'
+        ? // If you are building the extension, export function that does nothing
+          // Note: it's not practical to conditionally remove calls to this function from all screens
+          // So, more practical to just define it as a do-nothing function for the extension
+          () => undefined
+        : // If you are not building the extension, export GA event tracking function
+          (category: string, action: string, label: string) => {
+              ReactGA.event({
+                  category,
+                  action,
+                  label,
+              });
+          };
+
+export default {
+    RouteTracker,
+    init,
+};
diff --git a/cashtab/src/index.js b/cashtab/src/index.js
deleted file mode 100644
--- a/cashtab/src/index.js
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2024 The Bitcoin developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-import React from 'react';
-import { createRoot } from 'react-dom/client';
-import App from 'components/App/App';
-import { WalletProvider } from 'wallet/context';
-import { HashRouter as Router } from 'react-router-dom';
-import GA from 'components/Common/GoogleAnalytics';
-import { ChronikClient } from 'chronik-client';
-import { chronik as chronikConfig } from 'config/chronik';
-import { Ecc, initWasm } from 'ecash-lib';
-import { Agora } from 'ecash-agora';
-
-// Initialize wasm (activate ecash-lib) at app startup
-initWasm()
-    .then(() => {
-        // Initialize Ecc (used for signing txs) at app startup
-        const ecc = new Ecc();
-        // Initialize chronik-client at app startup
-        const chronik = new ChronikClient(chronikConfig.urls);
-        // Initialize new Agora chronik wrapper at app startup
-        const agora = new Agora(chronik);
-
-        const container = document.getElementById('root');
-        const root = createRoot(container);
-        root.render(
-            <WalletProvider chronik={chronik} agora={agora} ecc={ecc}>
-                <Router>
-                    {GA.init() && <GA.RouteTracker />}
-                    <App />
-                </Router>
-            </WalletProvider>,
-        );
-    })
-    .catch(console.error);
-
-if (module.hot) {
-    module.hot.accept();
-}
diff --git a/cashtab/src/index.tsx b/cashtab/src/index.tsx
new file mode 100644
--- /dev/null
+++ b/cashtab/src/index.tsx
@@ -0,0 +1,49 @@
+// Copyright (c) 2024 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import React, { useEffect } from 'react';
+import { createRoot } from 'react-dom/client';
+import App from 'components/App/App';
+import { WalletProvider } from 'wallet/context';
+import { HashRouter as Router } from 'react-router-dom';
+import GA from 'components/Common/GoogleAnalytics';
+import { ChronikClient } from 'chronik-client';
+import { chronik as chronikConfig } from 'config/chronik';
+import { Ecc, initWasm } from 'ecash-lib';
+import { Agora } from 'ecash-agora';
+
+const AppWrapper: React.FC = () => {
+    useEffect(() => {
+        const initializeApp = async () => {
+            await initWasm();
+        };
+
+        initializeApp().catch(console.error);
+    }, []);
+
+    return (
+        <WalletProvider
+            chronik={new ChronikClient(chronikConfig.urls)}
+            agora={new Agora(new ChronikClient(chronikConfig.urls))}
+            ecc={new Ecc()}
+        >
+            <Router>
+                {GA.init() && <GA.RouteTracker />}
+                <App />
+            </Router>
+        </WalletProvider>
+    );
+};
+
+const container = document.getElementById('root');
+if (container) {
+    const root = createRoot(container);
+    root.render(<AppWrapper />);
+} else {
+    console.error('Root container not found');
+}
+
+if (module.hot) {
+    module.hot.accept();
+}
diff --git a/cashtab/src/wallet/context.js b/cashtab/src/wallet/context.js
deleted file mode 100644
--- a/cashtab/src/wallet/context.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2024 The Bitcoin developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-import React from 'react';
-import PropTypes from 'prop-types';
-import useWallet from 'wallet/useWallet';
-
-export const WalletContext = React.createContext();
-
-export const WalletProvider = ({ chronik, agora, ecc, children }) => {
-    const wallet = useWallet(chronik, agora, ecc);
-    return (
-        <WalletContext.Provider value={wallet}>
-            {children}
-        </WalletContext.Provider>
-    );
-};
-
-WalletProvider.propTypes = {
-    chronik: PropTypes.object,
-    agora: PropTypes.object,
-    ecc: PropTypes.object,
-    children: PropTypes.node,
-};
diff --git a/cashtab/src/wallet/context.tsx b/cashtab/src/wallet/context.tsx
new file mode 100644
--- /dev/null
+++ b/cashtab/src/wallet/context.tsx
@@ -0,0 +1,74 @@
+// Copyright (c) 2024 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import React from 'react';
+import useWallet, { UseWalletReturnType } from 'wallet/useWallet';
+import { ChronikClient } from 'chronik-client';
+import { Agora } from 'ecash-agora';
+import { Ecc } from 'ecash-lib';
+
+interface NullDefaultUseWalletReturnType {
+    chronik: undefined;
+    agora: undefined;
+    ecc: undefined;
+    chaintipBlockheight: undefined;
+    fiatPrice: undefined;
+    cashtabLoaded: undefined;
+    loading: undefined;
+    apiError: undefined;
+    refreshAliases: undefined;
+    aliases: undefined;
+    setAliases: undefined;
+    aliasServerError: undefined;
+    setAliasServerError: undefined;
+    aliasPrices: undefined;
+    setAliasPrices: undefined;
+    updateCashtabState: undefined;
+    processChronikWsMsg: undefined;
+    cashtabState: undefined;
+}
+
+const nullDefaultUseWalletReturnType: NullDefaultUseWalletReturnType = {
+    chronik: undefined,
+    agora: undefined,
+    ecc: undefined,
+    chaintipBlockheight: undefined,
+    fiatPrice: undefined,
+    cashtabLoaded: undefined,
+    loading: undefined,
+    apiError: undefined,
+    refreshAliases: undefined,
+    aliases: undefined,
+    setAliases: undefined,
+    aliasServerError: undefined,
+    setAliasServerError: undefined,
+    aliasPrices: undefined,
+    setAliasPrices: undefined,
+    updateCashtabState: undefined,
+    processChronikWsMsg: undefined,
+    cashtabState: undefined,
+};
+
+export const WalletContext = React.createContext<
+    UseWalletReturnType | NullDefaultUseWalletReturnType
+>(nullDefaultUseWalletReturnType);
+
+interface WalletProviderProps {
+    chronik: ChronikClient;
+    agora: Agora;
+    ecc: Ecc;
+    children: React.ReactNode;
+}
+export const WalletProvider: React.FC<WalletProviderProps> = ({
+    chronik,
+    agora,
+    ecc,
+    children,
+}) => {
+    return (
+        <WalletContext.Provider value={useWallet(chronik, agora, ecc)}>
+            {children}
+        </WalletContext.Provider>
+    );
+};
diff --git a/cashtab/src/wallet/useWallet.ts b/cashtab/src/wallet/useWallet.ts
--- a/cashtab/src/wallet/useWallet.ts
+++ b/cashtab/src/wallet/useWallet.ts
@@ -61,6 +61,42 @@
 import CashtabCache from 'config/CashtabCache';
 import { ToastIcon } from 'react-toastify/dist/types';
 
+export interface UseWalletReturnType {
+    chronik: ChronikClient;
+    agora: Agora;
+    ecc: Ecc;
+    chaintipBlockheight: number;
+    fiatPrice: number | null;
+    cashtabLoaded: boolean;
+    loading: boolean;
+    apiError: boolean;
+    refreshAliases: (address: string) => Promise<void>;
+    aliases: AddressAliasStatus;
+    setAliases: React.Dispatch<React.SetStateAction<AddressAliasStatus>>;
+    aliasServerError: false | string;
+    setAliasServerError: React.Dispatch<React.SetStateAction<false | string>>;
+    aliasPrices: null | AliasPrices;
+    setAliasPrices: React.Dispatch<React.SetStateAction<null | AliasPrices>>;
+    updateCashtabState: (
+        key: string,
+        value:
+            | CashtabWallet[]
+            | CashtabCache
+            | CashtabContact[]
+            | CashtabSettings
+            | CashtabCacheJson
+            | StoredCashtabWallet[]
+            | (LegacyCashtabWallet | StoredCashtabWallet)[],
+    ) => Promise<boolean>;
+    processChronikWsMsg: (
+        msg: WsMsgClient,
+        cashtabState: CashtabState,
+        fiatPrice: null | number,
+        aliasesEnabled: boolean,
+    ) => Promise<boolean>;
+    cashtabState: CashtabState;
+}
+
 const useWallet = (chronik: ChronikClient, agora: Agora, ecc: Ecc) => {
     const [cashtabLoaded, setCashtabLoaded] = useState<boolean>(false);
     const [ws, setWs] = useState<null | WsEndpoint>(null);
@@ -1145,7 +1181,7 @@
         updateCashtabState,
         processChronikWsMsg,
         cashtabState,
-    };
+    } as UseWalletReturnType;
 };
 
 export default useWallet;