kleros/kleros-v2

View on GitHub
web/src/hooks/queries/usePopulatedDisputeData.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { useQuery } from "@tanstack/react-query";
import { HttpRequestError, RpcError } from "viem";

import { executeActions } from "@kleros/kleros-sdk/src/dataMappings/executeActions";
import { DisputeDetails } from "@kleros/kleros-sdk/src/dataMappings/utils/disputeDetailsTypes";
import { populateTemplate } from "@kleros/kleros-sdk/src/dataMappings/utils/populateTemplate";

import { useGraphqlBatcher } from "context/GraphqlBatcher";
import { debounceErrorToast } from "utils/debounceErrorToast";
import { isUndefined } from "utils/index";

import { graphql } from "src/graphql";

import { useDisputeDetailsQuery } from "./useDisputeDetailsQuery";

const disputeTemplateQuery = graphql(`
  query DisputeTemplate($id: ID!) {
    disputeTemplate(id: $id) {
      id
      templateTag
      templateData
      templateDataMappings
    }
  }
`);

export const usePopulatedDisputeData = (disputeID?: string, arbitrableAddress?: `0x${string}`) => {
  const { data: disputeData } = useDisputeDetailsQuery(disputeID);
  const { graphqlBatcher } = useGraphqlBatcher();
  const isEnabled =
    !isUndefined(disputeID) &&
    !isUndefined(disputeData) &&
    !isUndefined(disputeData?.dispute) &&
    !isUndefined(disputeData.dispute?.arbitrableChainId) &&
    !isUndefined(disputeData.dispute?.externalDisputeId) &&
    !isUndefined(disputeData.dispute?.templateId);

  return useQuery<DisputeDetails>({
    queryKey: [`DisputeTemplate${disputeID}${arbitrableAddress}${disputeData?.dispute?.externalDisputeId}`],
    enabled: isEnabled,
    staleTime: Infinity,
    queryFn: async () => {
      if (isEnabled) {
        try {
          const { disputeTemplate } = await graphqlBatcher.fetch({
            id: crypto.randomUUID(),
            document: disputeTemplateQuery,
            variables: { id: disputeData.dispute?.templateId.toString() },
            isDisputeTemplate: true,
          });

          const templateData = disputeTemplate?.templateData;
          const dataMappings = disputeTemplate?.templateDataMappings;

          const initialContext = {
            disputeID: disputeID,
            arbitrableAddress: arbitrableAddress,
            arbitrableChainID: disputeData.dispute?.arbitrableChainId,
            graphApiKey: import.meta.env.REACT_APP_GRAPH_API_KEY,
            alchemyApiKey: import.meta.env.ALCHEMY_API_KEY,
            externalDisputeID: disputeData.dispute?.externalDisputeId,
          };

          const data = dataMappings ? await executeActions(JSON.parse(dataMappings), initialContext) : {};
          const disputeDetails = populateTemplate(templateData, data);

          return disputeDetails;
        } catch (error) {
          if (error instanceof HttpRequestError || error instanceof RpcError) {
            debounceErrorToast("RPC failed!, Please avoid voting.");
            throw Error;
          }

          return {} as DisputeDetails;
        }
      } else throw Error;
    },
  });
};