DeFiCh/wallet

View on GitHub
mobile-app/app/contexts/DomainContext.tsx

Summary

Maintainability
A
0 mins
Test Coverage
import React, {
  createContext,
  useContext,
  useEffect,
  useState,
  PropsWithChildren,
} from "react";
import { useLogger } from "@shared-contexts/NativeLoggingProvider";
import { useFeatureFlagContext } from "./FeatureFlagContext";

interface DomainLoader {
  isDomainLoaded: boolean;
  domain: NonNullable<DomainType>;
}

interface DomainContextI {
  api: {
    get: () => Promise<string | null>;
    set: (domain: NonNullable<string>) => Promise<void>;
  };
}

export enum DomainType {
  DVM = "DVM",
  EVM = "EVM",
}

export function useDomain({ api }: DomainContextI): DomainLoader {
  const defaultDomain = DomainType.DVM;
  const logger = useLogger();
  const [isDomainLoaded, setIsDomainLoaded] = useState<boolean>(false);
  const [domain, setDomain] = useState<NonNullable<DomainType>>(defaultDomain);

  useEffect(() => {
    api
      .get()
      .then((l) => {
        let currentDomain: NonNullable<DomainType> = defaultDomain;
        if (l !== null && l !== undefined) {
          currentDomain = l as DomainType; // TODO fix this hardcoded typing if possible
        }
        setDomain(currentDomain);
      })
      .catch((err) => logger.error(err))
      .finally(() => setIsDomainLoaded(true));
  }, []);

  return {
    isDomainLoaded,
    domain,
  };
}

interface Domain {
  domain: NonNullable<DomainType>;
  isEvmFeatureEnabled: boolean;
  setDomain: (domain: NonNullable<DomainType>) => Promise<void>;
}

const DomainContext = createContext<Domain>(undefined as any);

export function useDomainContext(): Domain {
  return useContext(DomainContext);
}

export function DomainProvider(
  props: DomainContextI & PropsWithChildren<any>,
): JSX.Element | null {
  const { isFeatureAvailable } = useFeatureFlagContext();
  const { api } = props;
  const { domain } = useDomain({ api });
  const [currentDomain, setCurrentDomain] =
    useState<NonNullable<DomainType>>(domain);

  useEffect(() => {
    setCurrentDomain(domain);
  }, [domain]);

  useEffect(() => {
    switch (currentDomain) {
      case "EVM":
        setDomain(DomainType.EVM);
        break;
      default:
        setDomain(DomainType.DVM);
    }
  }, [currentDomain]);

  const setDomain = async (domain: DomainType): Promise<void> => {
    setCurrentDomain(domain);
    await api.set(domain);
  };

  const context: Domain = {
    domain: isFeatureAvailable("evm") ? currentDomain : DomainType.DVM,
    isEvmFeatureEnabled: isFeatureAvailable("evm"),
    setDomain,
  };

  return (
    <DomainContext.Provider value={context}>
      {props.children}
    </DomainContext.Provider>
  );
}