import { useState, useEffect } from 'react'; import { LocalStorage } from '@vegaprotocol/react-helpers'; import { ErrorType } from '../types'; import type { Environment, Configuration, Networks } from '../types'; import { validateConfiguration } from '../utils/validate-configuration'; export const LOCAL_STORAGE_NETWORK_KEY = 'vegaNetworkConfig'; export type EnvironmentWithOptionalUrl = Partial & Omit; const compileHosts = (hosts: string[], envUrl?: string) => { if (envUrl && !hosts.includes(envUrl)) { return [...hosts, envUrl]; } return hosts; }; const getCacheKey = (env: Networks) => `${LOCAL_STORAGE_NETWORK_KEY}-${env}`; const getCachedConfig = (env: Networks) => { const cacheKey = getCacheKey(env); const value = LocalStorage.getItem(cacheKey); if (value) { try { const config = JSON.parse(value) as Configuration; const hasError = validateConfiguration(config); if (hasError) { throw new Error('Invalid configuration found in the storage.'); } return config; } catch (err) { LocalStorage.removeItem(cacheKey); console.warn( 'Malformed data found for network configuration. Removed cached configuration, continuing...' ); } } return undefined; }; export const useConfig = ( environment: EnvironmentWithOptionalUrl, onError: (errorType: ErrorType) => void ) => { const [loading, setLoading] = useState(false); const [config, setConfig] = useState( getCachedConfig(environment.VEGA_ENV) ); useEffect(() => { let isMounted = true; (async () => { if (!config && environment.VEGA_CONFIG_URL) { isMounted && setLoading(true); try { const response = await fetch(environment.VEGA_CONFIG_URL); const configData: Configuration = await response.json(); if (validateConfiguration(configData)) { onError(ErrorType.CONFIG_VALIDATION_ERROR); isMounted && setLoading(false); return; } const hosts = compileHosts(configData.hosts, environment.VEGA_URL); isMounted && setConfig({ hosts }); LocalStorage.setItem( getCacheKey(environment.VEGA_ENV), JSON.stringify({ hosts }) ); isMounted && setLoading(false); } catch (err) { if (isMounted) { setLoading(false); setConfig({ hosts: [] }); } onError(ErrorType.CONFIG_LOAD_ERROR); } } })(); return () => { isMounted = false; }; // load config only once per runtime // eslint-disable-next-line react-hooks/exhaustive-deps }, [environment.VEGA_CONFIG_URL, !!config, onError, setLoading]); return { loading, config, }; };