cyb/src/hooks/useGetMarketData.ts

import BigNumber from 'bignumber.js';
import { useCallback, useEffect, useRef, useState } from 'react';
import { BASE_DENOM, DENOM_LIQUID } from 'src/constants/config';
import { useIbcDenom } from 'src/contexts/ibcDenom';
import { useQueryClient } from 'src/contexts/queryClient';
import { convertAmount, reduceBalances } from '../utils/utils';
import useGetTotalSupply from './useGetTotalSupply';
import usePoolListInterval from './usePoolListInterval';

const defaultTokenList = {
  [BASE_DENOM]: 0,
  [DENOM_LIQUID]: 0,
  milliampere: 0,
  millivolt: 0,
  tocyb: 0,
};

const calculatePrice = (coinsPair, balances, tracesDenom) => {
  let price = 0;
  const tokenA = coinsPair[0];
  const tokenB = coinsPair[1];
  const [{ coinDecimals: coinDecimalsA }] = tracesDenom(tokenA);
  const [{ coinDecimals: coinDecimalsB }] = tracesDenom(tokenB);

  const amountA = new BigNumber(convertAmount(balances[tokenA], coinDecimalsA));
  const amountB = new BigNumber(convertAmount(balances[tokenB], coinDecimalsB));

  if (amountA.comparedTo(0) && amountB.comparedTo(0)) {
    price = amountA.dividedBy(amountB).toNumber();
  }

  return price;
};

const getPoolPrice = (data, tracesDenom) => {
  const copyObj = { ...data };
  Object.keys(copyObj).forEach((key) => {
    const element = copyObj[key];
    if (element.balances) {
      const coinsPair = element.reserveCoinDenoms;
      const { balances } = element;
      let price = 0;
      if (coinsPair[0] === DENOM_LIQUID || coinsPair[1] === DENOM_LIQUID) {
        if (coinsPair[0] === DENOM_LIQUID) {
          price = calculatePrice(coinsPair, balances, tracesDenom);
        } else {
          price = calculatePrice([...coinsPair].reverse(), balances, tracesDenom);
          copyObj[key].reserveCoinDenoms = [...coinsPair].reverse();
        }
      } else {
        price = calculatePrice(coinsPair, balances, tracesDenom);
      }
      element.price = price;
    }
  });
  return copyObj;
};

const getPoolsBalance = async (data, client) => {
  const copyObj = { ...data };
  // eslint-disable-next-line no-restricted-syntax
  for (const key in copyObj) {
    if (Object.hasOwn(copyObj, key)) {
      const element = copyObj[key];
      const { reserveAccountAddress } = element;
      // eslint-disable-next-line no-await-in-loop
      const dataBalsnce = await client.getAllBalances(reserveAccountAddress);
      const reduceDataBalances = reduceBalances(dataBalsnce);
      element.balances = reduceDataBalances;
    }
  }
  return copyObj;
};

function useGetMarketData() {
  const queryClient = useQueryClient();
  const { tracesDenom } = useIbcDenom();
  // const [fetchDataWorker] = useWorker(getMarketData);
  const [dataTotal, setDataTotal] = useState({});
  const [poolsTotal, setPoolsTotal] = useState([]);
  const [marketData, setMarketData] = useState({});
  const { totalSupplyAll: dataTotalSupply } = useGetTotalSupply({
    refetchInterval: 1000 * 60 * 3,
  });
  const dataPools = usePoolListInterval();
  // const dataPools = usePoolListInterval({ refetchInterval: 1000 * 60 * 3 });

  useEffect(() => {
    const marketDataLS = localStorage.getItem('marketData');
    if (marketDataLS !== null) {
      const marketDataLSPObj = JSON.parse(marketDataLS);
      setMarketData({ ...marketDataLSPObj });
    }
  }, []);

  useEffect(() => {
    try {
      if (dataTotalSupply && Object.keys(dataTotalSupply).length > 0) {
        setDataTotal({ ...defaultTokenList, ...dataTotalSupply });
      }
    } catch (error) {
      console.log('error', error);
      setDataTotal([]);
    }
  }, [dataTotalSupply]);

  useEffect(() => {
    const getPpools = async () => {
      try {
        if (dataPools && dataPools.length > 0) {
          const reduceObj = dataPools.reduce(
            (obj, item) => ({
              ...obj,
              [item.poolCoinDenom]: {
                ...item,
              },
            }),
            {}
          );
          const poolsBalance = await getPoolsBalance(reduceObj, queryClient);
          const poolPriceObj = getPoolPrice(poolsBalance, tracesDenom);
          setPoolsTotal(poolPriceObj);
        }
      } catch (error) {
        console.log('error', error);
        setPoolsTotal([]);
      }
    };
    getPpools();
  }, [dataPools, queryClient, tracesDenom]);

  const dataTotalRef = useRef(dataTotal);
  dataTotalRef.current = dataTotal;
  const poolsTotalRef = useRef(poolsTotal);
  poolsTotalRef.current = poolsTotal;

  const getMarketDataPool = useCallback(
    (data) => {
      try {
        const tempMarketData = {};
        const currentDataTotal = dataTotalRef.current;
        const currentPoolsTotal = poolsTotalRef.current;
        if (Object.keys(currentDataTotal).length > 0) {
          const filteredDataTotalSupply = Object.keys(currentDataTotal).filter((item) =>
            item.includes('pool')
          );

          filteredDataTotalSupply.forEach((key) => {
            if (Object.hasOwn(currentPoolsTotal, key)) {
              const { reserveCoinDenoms, balances } = currentPoolsTotal[key];

              if (Object.hasOwn(data, reserveCoinDenoms[0])) {
                let marketCapTemp = 0;
                reserveCoinDenoms.forEach((itemJ) => {
                  if (data[itemJ] && balances[itemJ]) {
                    const marketDataPrice = data[itemJ];
                    const [{ coinDecimals }] = tracesDenom(itemJ);
                    const balancesConvert = convertAmount(balances[itemJ], coinDecimals);
                    const marketCapaTemp = marketDataPrice * balancesConvert;
                    marketCapTemp += marketCapaTemp;
                  }
                });
                if (marketCapTemp > 0) {
                  const total = currentDataTotal[key];
                  const price = marketCapTemp / total;
                  tempMarketData[key] = price;
                }
              }
            }
          });
        }
        return tempMarketData;
      } catch (error) {
        console.log('error', error);
        return {};
      }
    },
    [tracesDenom]
  );

  useEffect(() => {
    try {
      if (Object.keys(dataTotal).length > 0 && Object.keys(poolsTotal).length > 0) {
        const marketDataObj = {};
        marketDataObj[DENOM_LIQUID] = 1;
        Object.keys(dataTotal).forEach((keyI) => {
          Object.keys(poolsTotal).forEach((keyJ) => {
            const itemJ = poolsTotal[keyJ];
            const { reserveCoinDenoms } = itemJ;
            if (reserveCoinDenoms[0] === DENOM_LIQUID && reserveCoinDenoms[1] === keyI) {
              marketDataObj[keyI] = itemJ.price;
            }
          });
        });
        const tempdataPool = getMarketDataPool(marketDataObj);
        const resultMarketDataObj = { ...marketDataObj, ...tempdataPool };
        setMarketData(resultMarketDataObj);
        if (Object.keys(resultMarketDataObj).length > 0) {
          localStorage.setItem('marketData', JSON.stringify(resultMarketDataObj));
        }
      }
    } catch (error) {
      console.log('error', error);
    }
  }, [dataTotal, poolsTotal, getMarketDataPool]);

  return { marketData, dataTotal };
}

export default useGetMarketData;

Synonyms

pussy-ts/src/hooks/useGetMarketData.ts

Neighbours