diff --git a/lib/keyserver-conn/call-keyserver-endpoint-provider.react.js b/lib/keyserver-conn/call-keyserver-endpoint-provider.react.js
--- a/lib/keyserver-conn/call-keyserver-endpoint-provider.react.js
+++ b/lib/keyserver-conn/call-keyserver-endpoint-provider.react.js
@@ -1,6 +1,8 @@
 // @flow
 
+import invariant from 'invariant';
 import _memoize from 'lodash/memoize.js';
+import * as React from 'react';
 import { createSelector } from 'reselect';
 
 import { setNewSession } from './keyserver-conn-types.js';
@@ -20,139 +22,25 @@
 } from '../utils/call-server-endpoint.js';
 import callServerEndpoint from '../utils/call-server-endpoint.js';
 
+export type ActionFunc<F> = (callServerEndpoint: CallServerEndpoint) => F;
+type CreateBoundServerCallsSelectorType = <F>(
+  ActionFunc<F>,
+) => BindServerCallsParams => F;
+type CallKeyserverEndpointContextType = {
+  +bindCookieAndUtilsIntoCallServerEndpoint: (
+    params: BindServerCallsParams,
+  ) => CallServerEndpoint,
+  +createBoundServerCallsSelector: CreateBoundServerCallsSelectorType,
+};
+
+const CallKeyserverEndpointContext: React.Context<?CallKeyserverEndpointContextType> =
+  React.createContext();
+
 let currentlyWaitingForNewCookie = false;
 let serverEndpointCallsWaitingForNewCookie: ((
   callServerEndpoint: ?CallServerEndpoint,
 ) => void)[] = [];
 
-// Third param is optional and gets called with newCookie if we get a new cookie
-// Necessary to propagate cookie in cookieInvalidationRecovery below
-function bindCookieAndUtilsIntoCallServerEndpoint(
-  params: BindServerCallsParams,
-): CallServerEndpoint {
-  const {
-    dispatch,
-    cookie,
-    urlPrefix,
-    sessionID,
-    currentUserInfo,
-    isSocketConnected,
-    lastCommunicatedPlatformDetails,
-    keyserverID,
-  } = params;
-  const loggedIn = !!(currentUserInfo && !currentUserInfo.anonymous && true);
-  const boundSetNewSession = (
-    sessionChange: ClientSessionChange,
-    error: ?string,
-  ) =>
-    setNewSession(
-      dispatch,
-      sessionChange,
-      {
-        currentUserInfo,
-        cookiesAndSessions: { [keyserverID]: { cookie, sessionID } },
-      },
-      error,
-      undefined,
-      keyserverID,
-    );
-  const canResolveInvalidation = canResolveKeyserverSessionInvalidation();
-  // This function gets called before callServerEndpoint sends a request,
-  // to make sure that we're not in the middle of trying to recover
-  // an invalidated cookie
-  const waitIfCookieInvalidated = () => {
-    if (!canResolveInvalidation) {
-      // If there is no way to resolve the session invalidation,
-      // just let the caller callServerEndpoint instance continue
-      return Promise.resolve(null);
-    }
-    if (!currentlyWaitingForNewCookie) {
-      // Our cookie seems to be valid
-      return Promise.resolve(null);
-    }
-    // Wait to run until we get our new cookie
-    return new Promise<?CallServerEndpoint>(r =>
-      serverEndpointCallsWaitingForNewCookie.push(r),
-    );
-  };
-  // This function is a helper for the next function defined below
-  const attemptToResolveInvalidation = async (
-    sessionChange: ClientSessionChange,
-  ) => {
-    const newAnonymousCookie = sessionChange.cookie;
-    const newSessionChange = await resolveKeyserverSessionInvalidation(
-      dispatch,
-      newAnonymousCookie,
-      urlPrefix,
-      logInActionSources.cookieInvalidationResolutionAttempt,
-      keyserverID,
-    );
-
-    currentlyWaitingForNewCookie = false;
-    const currentWaitingCalls = serverEndpointCallsWaitingForNewCookie;
-    serverEndpointCallsWaitingForNewCookie = [];
-
-    const newCallServerEndpoint = newSessionChange
-      ? bindCookieAndUtilsIntoCallServerEndpoint({
-          ...params,
-          cookie: newSessionChange.cookie,
-          sessionID: newSessionChange.sessionID,
-          currentUserInfo: newSessionChange.currentUserInfo,
-        })
-      : null;
-    for (const func of currentWaitingCalls) {
-      func(newCallServerEndpoint);
-    }
-    return newCallServerEndpoint;
-  };
-  // If this function is called, callServerEndpoint got a response invalidating
-  // its cookie, and is wondering if it should just like... give up?
-  // Or if there's a chance at redemption
-  const cookieInvalidationRecovery = (sessionChange: ClientSessionChange) => {
-    if (!canResolveInvalidation) {
-      // If there is no way to resolve the session invalidation,
-      // just let the caller callServerEndpoint instance continue
-      return Promise.resolve(null);
-    }
-    if (!loggedIn) {
-      // We don't want to attempt any use native credentials of a logged out
-      // user to log-in after a cookieInvalidation while logged out
-      return Promise.resolve(null);
-    }
-    if (currentlyWaitingForNewCookie) {
-      return new Promise<?CallServerEndpoint>(r =>
-        serverEndpointCallsWaitingForNewCookie.push(r),
-      );
-    }
-    currentlyWaitingForNewCookie = true;
-    return attemptToResolveInvalidation(sessionChange);
-  };
-
-  return (
-    endpoint: Endpoint,
-    data: Object,
-    options?: ?CallServerEndpointOptions,
-  ) =>
-    callServerEndpoint(
-      cookie,
-      boundSetNewSession,
-      waitIfCookieInvalidated,
-      cookieInvalidationRecovery,
-      urlPrefix,
-      sessionID,
-      isSocketConnected,
-      lastCommunicatedPlatformDetails,
-      socketAPIHandler,
-      endpoint,
-      data,
-      dispatch,
-      options,
-      loggedIn,
-      keyserverID,
-    );
-}
-
-export type ActionFunc<F> = (callServerEndpoint: CallServerEndpoint) => F;
 export type BindServerCallsParams = {
   +dispatch: Dispatch,
   +cookie: ?string,
@@ -164,56 +52,213 @@
   +keyserverID: string,
 };
 
-// All server calls needs to include some information from the Redux state
-// (namely, the cookie). This information is used deep in the server call,
-// at the point where callServerEndpoint is called. We don't want to bother
-// propagating the cookie (and any future config info that callServerEndpoint
-// needs) through to the server calls so they can pass it to callServerEndpoint.
-// Instead, we "curry" the cookie onto callServerEndpoint within react-redux's
-// connect's mapStateToProps function, and then pass that "bound"
-// callServerEndpoint that no longer needs the cookie as a parameter on to
-// the server call.
-const baseCreateBoundServerCallsSelector = <F>(
-  actionFunc: ActionFunc<F>,
-): (BindServerCallsParams => F) =>
-  createSelector(
-    (state: BindServerCallsParams) => state.dispatch,
-    (state: BindServerCallsParams) => state.cookie,
-    (state: BindServerCallsParams) => state.urlPrefix,
-    (state: BindServerCallsParams) => state.sessionID,
-    (state: BindServerCallsParams) => state.currentUserInfo,
-    (state: BindServerCallsParams) => state.isSocketConnected,
-    (state: BindServerCallsParams) => state.lastCommunicatedPlatformDetails,
-    (state: BindServerCallsParams) => state.keyserverID,
-    (
-      dispatch: Dispatch,
-      cookie: ?string,
-      urlPrefix: string,
-      sessionID: ?string,
-      currentUserInfo: ?CurrentUserInfo,
-      isSocketConnected: boolean,
-      lastCommunicatedPlatformDetails: ?PlatformDetails,
-      keyserverID: string,
+type Props = {
+  +children: React.Node,
+};
+function CallKeyserverEndpointProvider(props: Props): React.Node {
+  const bindCookieAndUtilsIntoCallServerEndpoint: (
+    params: BindServerCallsParams,
+  ) => CallServerEndpoint = React.useCallback(params => {
+    const {
+      dispatch,
+      cookie,
+      urlPrefix,
+      sessionID,
+      currentUserInfo,
+      isSocketConnected,
+      lastCommunicatedPlatformDetails,
+      keyserverID,
+    } = params;
+    const loggedIn = !!(currentUserInfo && !currentUserInfo.anonymous && true);
+    const boundSetNewSession = (
+      sessionChange: ClientSessionChange,
+      error: ?string,
+    ) =>
+      setNewSession(
+        dispatch,
+        sessionChange,
+        {
+          currentUserInfo,
+          cookiesAndSessions: { [keyserverID]: { cookie, sessionID } },
+        },
+        error,
+        undefined,
+        keyserverID,
+      );
+    const canResolveInvalidation = canResolveKeyserverSessionInvalidation();
+    // This function gets called before callServerEndpoint sends a request,
+    // to make sure that we're not in the middle of trying to recover
+    // an invalidated cookie
+    const waitIfCookieInvalidated = () => {
+      if (!canResolveInvalidation) {
+        // If there is no way to resolve the session invalidation,
+        // just let the caller callServerEndpoint instance continue
+        return Promise.resolve(null);
+      }
+      if (!currentlyWaitingForNewCookie) {
+        // Our cookie seems to be valid
+        return Promise.resolve(null);
+      }
+      // Wait to run until we get our new cookie
+      return new Promise<?CallServerEndpoint>(r =>
+        serverEndpointCallsWaitingForNewCookie.push(r),
+      );
+    };
+    // This function is a helper for the next function defined below
+    const attemptToResolveInvalidation = async (
+      sessionChange: ClientSessionChange,
     ) => {
-      const boundCallServerEndpoint = bindCookieAndUtilsIntoCallServerEndpoint({
+      const newAnonymousCookie = sessionChange.cookie;
+      const newSessionChange = await resolveKeyserverSessionInvalidation(
         dispatch,
+        newAnonymousCookie,
+        urlPrefix,
+        logInActionSources.cookieInvalidationResolutionAttempt,
+        keyserverID,
+      );
+
+      currentlyWaitingForNewCookie = false;
+      const currentWaitingCalls = serverEndpointCallsWaitingForNewCookie;
+      serverEndpointCallsWaitingForNewCookie = [];
+
+      const newCallServerEndpoint = newSessionChange
+        ? bindCookieAndUtilsIntoCallServerEndpoint({
+            ...params,
+            cookie: newSessionChange.cookie,
+            sessionID: newSessionChange.sessionID,
+            currentUserInfo: newSessionChange.currentUserInfo,
+          })
+        : null;
+      for (const func of currentWaitingCalls) {
+        func(newCallServerEndpoint);
+      }
+      return newCallServerEndpoint;
+    };
+    // If this function is called, callServerEndpoint got a response
+    // invalidating its cookie, and is wondering if it should just like...
+    // give up? Or if there's a chance at redemption
+    const cookieInvalidationRecovery = (sessionChange: ClientSessionChange) => {
+      if (!canResolveInvalidation) {
+        // If there is no way to resolve the session invalidation,
+        // just let the caller callServerEndpoint instance continue
+        return Promise.resolve(null);
+      }
+      if (!loggedIn) {
+        // We don't want to attempt any use native credentials of a logged out
+        // user to log-in after a cookieInvalidation while logged out
+        return Promise.resolve(null);
+      }
+      if (currentlyWaitingForNewCookie) {
+        return new Promise<?CallServerEndpoint>(r =>
+          serverEndpointCallsWaitingForNewCookie.push(r),
+        );
+      }
+      currentlyWaitingForNewCookie = true;
+      return attemptToResolveInvalidation(sessionChange);
+    };
+
+    return (
+      endpoint: Endpoint,
+      data: Object,
+      options?: ?CallServerEndpointOptions,
+    ) =>
+      callServerEndpoint(
         cookie,
+        boundSetNewSession,
+        waitIfCookieInvalidated,
+        cookieInvalidationRecovery,
         urlPrefix,
         sessionID,
-        currentUserInfo,
         isSocketConnected,
         lastCommunicatedPlatformDetails,
+        socketAPIHandler,
+        endpoint,
+        data,
+        dispatch,
+        options,
+        loggedIn,
         keyserverID,
-      });
-      return actionFunc(boundCallServerEndpoint);
-    },
+      );
+  }, []);
+
+  // All server calls needs to include some information from the Redux state
+  // (namely, the cookie). This information is used deep in the server call,
+  // at the point where callServerEndpoint is called. We don't want to bother
+  // propagating the cookie (and any future config info that callServerEndpoint
+  // needs) through to the server calls so they can pass it to
+  // callServerEndpoint. Instead, we "curry" the cookie onto callServerEndpoint
+  // within react-redux's connect's mapStateToProps function, and then pass that
+  // "bound" callServerEndpoint that no longer needs the cookie as a parameter
+  // on to the server call.
+  const baseCreateBoundServerCallsSelector = React.useCallback(
+    <F>(actionFunc: ActionFunc<F>): (BindServerCallsParams => F) =>
+      createSelector(
+        (state: BindServerCallsParams) => state.dispatch,
+        (state: BindServerCallsParams) => state.cookie,
+        (state: BindServerCallsParams) => state.urlPrefix,
+        (state: BindServerCallsParams) => state.sessionID,
+        (state: BindServerCallsParams) => state.currentUserInfo,
+        (state: BindServerCallsParams) => state.isSocketConnected,
+        (state: BindServerCallsParams) => state.lastCommunicatedPlatformDetails,
+        (state: BindServerCallsParams) => state.keyserverID,
+        (
+          dispatch: Dispatch,
+          cookie: ?string,
+          urlPrefix: string,
+          sessionID: ?string,
+          currentUserInfo: ?CurrentUserInfo,
+          isSocketConnected: boolean,
+          lastCommunicatedPlatformDetails: ?PlatformDetails,
+          keyserverID: string,
+        ) => {
+          const boundCallServerEndpoint =
+            bindCookieAndUtilsIntoCallServerEndpoint({
+              dispatch,
+              cookie,
+              urlPrefix,
+              sessionID,
+              currentUserInfo,
+              isSocketConnected,
+              lastCommunicatedPlatformDetails,
+              keyserverID,
+            });
+          return actionFunc(boundCallServerEndpoint);
+        },
+      ),
+    [bindCookieAndUtilsIntoCallServerEndpoint],
   );
 
-type CreateBoundServerCallsSelectorType = <F>(
-  ActionFunc<F>,
-) => BindServerCallsParams => F;
-const createBoundServerCallsSelector: CreateBoundServerCallsSelectorType =
-  (_memoize(baseCreateBoundServerCallsSelector): any);
+  const createBoundServerCallsSelector: CreateBoundServerCallsSelectorType =
+    React.useMemo(
+      () => _memoize(baseCreateBoundServerCallsSelector),
+      [baseCreateBoundServerCallsSelector],
+    );
+
+  const value = React.useMemo(
+    () => ({
+      bindCookieAndUtilsIntoCallServerEndpoint,
+      createBoundServerCallsSelector,
+    }),
+    [bindCookieAndUtilsIntoCallServerEndpoint, createBoundServerCallsSelector],
+  );
+
+  return (
+    <CallKeyserverEndpointContext.Provider value={value}>
+      {props.children}
+    </CallKeyserverEndpointContext.Provider>
+  );
+}
+
+function useCallKeyserverEndpointContext(): CallKeyserverEndpointContextType {
+  const callKeyserverEndpointContext = React.useContext(
+    CallKeyserverEndpointContext,
+  );
+  invariant(
+    callKeyserverEndpointContext,
+    'callKeyserverEndpointContext should be set',
+  );
+  return callKeyserverEndpointContext;
+}
 
 let socketAPIHandler: ?SocketAPIHandler = null;
 function registerActiveSocket(passedSocketAPIHandler: ?SocketAPIHandler) {
@@ -221,7 +266,7 @@
 }
 
 export {
-  createBoundServerCallsSelector,
+  CallKeyserverEndpointProvider,
+  useCallKeyserverEndpointContext,
   registerActiveSocket,
-  bindCookieAndUtilsIntoCallServerEndpoint,
 };
diff --git a/lib/utils/action-utils.js b/lib/utils/action-utils.js
--- a/lib/utils/action-utils.js
+++ b/lib/utils/action-utils.js
@@ -8,7 +8,7 @@
 import {
   type ActionFunc,
   type BindServerCallsParams,
-  createBoundServerCallsSelector,
+  useCallKeyserverEndpointContext,
 } from '../keyserver-conn/call-keyserver-endpoint-provider.react.js';
 import { serverCallStateSelector } from '../selectors/server-calls.js';
 
@@ -20,6 +20,7 @@
   const serverCallState = useSelector(
     serverCallStateSelector(ashoatKeyserverID),
   );
+  const { createBoundServerCallsSelector } = useCallKeyserverEndpointContext();
   return React.useMemo(() => {
     const { urlPrefix, isSocketConnected } = serverCallState;
     invariant(
@@ -37,7 +38,13 @@
       ...paramOverride,
       keyserverID: ashoatKeyserverID,
     });
-  }, [serverCall, serverCallState, dispatch, paramOverride]);
+  }, [
+    serverCall,
+    serverCallState,
+    dispatch,
+    paramOverride,
+    createBoundServerCallsSelector,
+  ]);
 }
 
 export { useServerCall };
diff --git a/lib/utils/keyserver-call.js b/lib/utils/keyserver-call.js
--- a/lib/utils/keyserver-call.js
+++ b/lib/utils/keyserver-call.js
@@ -12,7 +12,7 @@
 import { useSelector, useDispatch } from './redux-utils.js';
 import { useDerivedObject } from '../hooks/objects.js';
 import {
-  bindCookieAndUtilsIntoCallServerEndpoint,
+  useCallKeyserverEndpointContext,
   type BindServerCallsParams,
 } from '../keyserver-conn/call-keyserver-endpoint-provider.react.js';
 import type { PlatformDetails } from '../types/device-types.js';
@@ -39,6 +39,9 @@
 // The first argument of the memoized function is used as the map cache key.
 const baseCreateBoundServerCallsSelector = (
   keyserverID: string,
+  bindCookieAndUtilsIntoCallServerEndpoint: (
+    params: BindServerCallsParams,
+  ) => CallServerEndpoint,
 ): (BindServerCallsParams => CallServerEndpoint) =>
   createSelector(
     (state: BindServerCallsParams) => state.dispatch,
@@ -71,6 +74,9 @@
 
 type CreateBoundServerCallsSelectorType = (
   keyserverID: string,
+  bindCookieAndUtilsIntoCallServerEndpoint: (
+    params: BindServerCallsParams,
+  ) => CallServerEndpoint,
 ) => BindServerCallsParams => CallServerEndpoint;
 const createBoundServerCallsSelector: CreateBoundServerCallsSelectorType =
   _memoize(baseCreateBoundServerCallsSelector);
@@ -130,6 +136,8 @@
   currentUserInfo: ?CurrentUserInfo,
   keyserverCallInfos: { +[keyserverID: string]: KeyserverCallInfo },
 ): BindCallKeyserverSelector {
+  const { bindCookieAndUtilsIntoCallServerEndpoint } =
+    useCallKeyserverEndpointContext();
   return React.useMemo(
     () =>
       _memoize(
@@ -152,6 +160,7 @@
 
               const boundCallServerEndpoint = createBoundServerCallsSelector(
                 keyserverID,
+                bindCookieAndUtilsIntoCallServerEndpoint,
               )({
                 dispatch,
                 currentUserInfo,
@@ -180,7 +189,12 @@
           return keyserverCall(callKeyserverEndpoint, keyserverIDs);
         },
       ),
-    [dispatch, currentUserInfo, keyserverCallInfos],
+    [
+      dispatch,
+      currentUserInfo,
+      keyserverCallInfos,
+      bindCookieAndUtilsIntoCallServerEndpoint,
+    ],
   );
 }
 
diff --git a/native/root.react.js b/native/root.react.js
--- a/native/root.react.js
+++ b/native/root.react.js
@@ -29,6 +29,7 @@
 import IntegrityHandler from 'lib/components/integrity-handler.react.js';
 import KeyserverConnectionsHandler from 'lib/components/keyserver-connections-handler.js';
 import { MediaCacheProvider } from 'lib/components/media-cache-provider.react.js';
+import { CallKeyserverEndpointProvider } from 'lib/keyserver-conn/call-keyserver-endpoint-provider.react.js';
 import { TunnelbrokerProvider } from 'lib/tunnelbroker/tunnelbroker-context.js';
 import { actionLogger } from 'lib/utils/action-logger.js';
 
@@ -296,64 +297,66 @@
   }
   return (
     <GestureHandlerRootView style={styles.app}>
-      <StaffContextProvider>
-        <IdentityServiceContextProvider>
-          <TunnelbrokerProvider
-            initMessage={tunnelbrokerInitMessage}
-            peerToPeerMessageHandler={peerToPeerMessageHandler}
-          >
-            <FeatureFlagsProvider>
-              <NavContext.Provider value={navContext}>
-                <RootContext.Provider value={rootContext}>
-                  <InputStateContainer>
-                    <MessageEditingContextProvider>
-                      <SafeAreaProvider initialMetrics={initialWindowMetrics}>
-                        <ActionSheetProvider>
-                          <ENSCacheProvider provider={provider}>
-                            <MediaCacheProvider
-                              persistence={filesystemMediaCache}
-                            >
-                              <EditUserAvatarProvider>
-                                <NativeEditThreadAvatarProvider>
-                                  <MarkdownContextProvider>
-                                    <MessageSearchProvider>
-                                      <BottomSheetProvider>
-                                        <RegistrationContextProvider>
-                                          <SQLiteDataHandler />
-                                          <ConnectedStatusBar />
-                                          <ReduxPersistGate
-                                            persistor={getPersistor()}
-                                          >
-                                            {gated}
-                                          </ReduxPersistGate>
-                                          <PersistedStateGate>
-                                            <KeyserverConnectionsHandler
-                                              socketComponent={Socket}
-                                              detectUnsupervisedBackgroundRef={
-                                                detectUnsupervisedBackgroundRef
-                                              }
-                                            />
-                                            <VersionSupportedChecker />
-                                          </PersistedStateGate>
-                                          {navigation}
-                                        </RegistrationContextProvider>
-                                      </BottomSheetProvider>
-                                    </MessageSearchProvider>
-                                  </MarkdownContextProvider>
-                                </NativeEditThreadAvatarProvider>
-                              </EditUserAvatarProvider>
-                            </MediaCacheProvider>
-                          </ENSCacheProvider>
-                        </ActionSheetProvider>
-                      </SafeAreaProvider>
-                    </MessageEditingContextProvider>
-                  </InputStateContainer>
-                </RootContext.Provider>
-              </NavContext.Provider>
-            </FeatureFlagsProvider>
-          </TunnelbrokerProvider>
-        </IdentityServiceContextProvider>
-      </StaffContextProvider>
+      <CallKeyserverEndpointProvider>
+        <StaffContextProvider>
+          <IdentityServiceContextProvider>
+            <TunnelbrokerProvider
+              initMessage={tunnelbrokerInitMessage}
+              peerToPeerMessageHandler={peerToPeerMessageHandler}
+            >
+              <FeatureFlagsProvider>
+                <NavContext.Provider value={navContext}>
+                  <RootContext.Provider value={rootContext}>
+                    <InputStateContainer>
+                      <MessageEditingContextProvider>
+                        <SafeAreaProvider initialMetrics={initialWindowMetrics}>
+                          <ActionSheetProvider>
+                            <ENSCacheProvider provider={provider}>
+                              <MediaCacheProvider
+                                persistence={filesystemMediaCache}
+                              >
+                                <EditUserAvatarProvider>
+                                  <NativeEditThreadAvatarProvider>
+                                    <MarkdownContextProvider>
+                                      <MessageSearchProvider>
+                                        <BottomSheetProvider>
+                                          <RegistrationContextProvider>
+                                            <SQLiteDataHandler />
+                                            <ConnectedStatusBar />
+                                            <ReduxPersistGate
+                                              persistor={getPersistor()}
+                                            >
+                                              {gated}
+                                            </ReduxPersistGate>
+                                            <PersistedStateGate>
+                                              <KeyserverConnectionsHandler
+                                                socketComponent={Socket}
+                                                detectUnsupervisedBackgroundRef={
+                                                  detectUnsupervisedBackgroundRef
+                                                }
+                                              />
+                                              <VersionSupportedChecker />
+                                            </PersistedStateGate>
+                                            {navigation}
+                                          </RegistrationContextProvider>
+                                        </BottomSheetProvider>
+                                      </MessageSearchProvider>
+                                    </MarkdownContextProvider>
+                                  </NativeEditThreadAvatarProvider>
+                                </EditUserAvatarProvider>
+                              </MediaCacheProvider>
+                            </ENSCacheProvider>
+                          </ActionSheetProvider>
+                        </SafeAreaProvider>
+                      </MessageEditingContextProvider>
+                    </InputStateContainer>
+                  </RootContext.Provider>
+                </NavContext.Provider>
+              </FeatureFlagsProvider>
+            </TunnelbrokerProvider>
+          </IdentityServiceContextProvider>
+        </StaffContextProvider>
+      </CallKeyserverEndpointProvider>
     </GestureHandlerRootView>
   );
 }
diff --git a/web/root.js b/web/root.js
--- a/web/root.js
+++ b/web/root.js
@@ -11,6 +11,7 @@
 
 import IntegrityHandler from 'lib/components/integrity-handler.react.js';
 import KeyserverConnectionsHandler from 'lib/components/keyserver-connections-handler.js';
+import { CallKeyserverEndpointProvider } from 'lib/keyserver-conn/call-keyserver-endpoint-provider.react.js';
 import { reduxLoggerMiddleware } from 'lib/utils/action-logger.js';
 
 import {
@@ -42,20 +43,22 @@
 const RootProvider = (): React.Node => (
   <Provider store={store}>
     <ErrorBoundary>
-      <InitialReduxStateGate persistor={persistor}>
-        <GetOrCreateCryptoStoreProvider>
-          <IdentityServiceContextProvider>
-            <WebNotificationsSessionCreatorProvider>
-              <Router history={history.getHistoryObject()}>
-                <Route path="*" component={App} />
-              </Router>
-              <KeyserverConnectionsHandler socketComponent={Socket} />
-              <SQLiteDataHandler />
-              <IntegrityHandler />
-            </WebNotificationsSessionCreatorProvider>
-          </IdentityServiceContextProvider>
-        </GetOrCreateCryptoStoreProvider>
-      </InitialReduxStateGate>
+      <CallKeyserverEndpointProvider>
+        <InitialReduxStateGate persistor={persistor}>
+          <GetOrCreateCryptoStoreProvider>
+            <IdentityServiceContextProvider>
+              <WebNotificationsSessionCreatorProvider>
+                <Router history={history.getHistoryObject()}>
+                  <Route path="*" component={App} />
+                </Router>
+                <KeyserverConnectionsHandler socketComponent={Socket} />
+                <SQLiteDataHandler />
+                <IntegrityHandler />
+              </WebNotificationsSessionCreatorProvider>
+            </IdentityServiceContextProvider>
+          </GetOrCreateCryptoStoreProvider>
+        </InitialReduxStateGate>
+      </CallKeyserverEndpointProvider>
     </ErrorBoundary>
   </Provider>
 );