cyb/src/hooks/getBalances.ts

import { useCallback, useEffect, useRef, useState } from 'react';
import { DENOM_LIQUID } from 'src/constants/config';
import { useQueryClient } from 'src/contexts/queryClient';
import { authAccounts } from '../utils/search/utils';
import { reduceBalances } from '../utils/utils';

const MILLISECONDS_IN_SECOND = 1000;

const getVestingPeriodsData = (data, startTime) => {
  let length = parseFloat(startTime);
  const vestedAmount = {
    [DENOM_LIQUID]: 0,
    millivolt: 0,
    milliampere: 0,
  };

  if (data.length > 0) {
    data.forEach((item) => {
      let amount = {};
      length += parseFloat(item.length);
      const lengthMs = length * MILLISECONDS_IN_SECOND;
      const d = Date.parse(new Date());
      amount = reduceBalances(item.amount);
      if (lengthMs < d) {
        if (Object.keys(amount).length > 0) {
          // eslint-disable-next-line no-restricted-syntax
          for (const key in amount) {
            if (Object.hasOwn(amount, key)) {
              const element = amount[key];
              if (Object.hasOwn(vestedAmount, key)) {
                vestedAmount[key] += element;
              }
            }
          }
        }
      }
    });
  }

  return vestedAmount;
};

function useGetBalances(addressActive: string | undefined) {
  const queryClient = useQueryClient();
  const [allBalances, setAllBalances] = useState(null);
  const [vestedAmount, setVestedAmount] = useState(null);
  const [liquidBalances, setLiquidBalances] = useState(null);
  const [_update, setUpdate] = useState(0);

  const pollingRef = useRef<ReturnType<typeof setInterval>>();
  const snapshotRef = useRef<string | null>(null);

  const stopPolling = useCallback(() => {
    if (pollingRef.current) {
      clearInterval(pollingRef.current);
      pollingRef.current = undefined;
    }
  }, []);

  const fetchBalances = useCallback(async () => {
    if (!queryClient || !addressActive) return null;
    const result = await queryClient.getAllBalances(addressActive);
    return reduceBalances(result);
  }, [queryClient, addressActive]);

  const refresh = useCallback(() => {
    setUpdate((item) => item + 1);

    // Snapshot current balance for change detection
    if (allBalances) {
      snapshotRef.current = JSON.stringify(allBalances);
    }

    stopPolling();
    let count = 0;
    pollingRef.current = setInterval(async () => {
      count++;
      const balances = await fetchBalances();
      if (balances && JSON.stringify(balances) !== snapshotRef.current) {
        setAllBalances(balances);
        stopPolling();
        return;
      }
      if (count >= 30) {
        stopPolling();
      }
    }, 10000);
  }, [allBalances, fetchBalances, stopPolling]);

  // Cleanup polling on unmount
  useEffect(() => () => stopPolling(), [stopPolling]);

  useEffect(() => {
    const getAllBalances = async () => {
      if (queryClient && addressActive) {
        const getAllBalancesPromise = await queryClient.getAllBalances(addressActive);
        const balances = reduceBalances(getAllBalancesPromise);
        setAllBalances(balances);
      }
    };
    getAllBalances();
  }, [addressActive, queryClient, _update]);

  useEffect(() => {
    (async () => {
      if (!addressActive) {
        return;
      }

      const vested = {
        [DENOM_LIQUID]: 0,
        millivolt: 0,
        milliampere: 0,
      };

      const getAccount = await authAccounts(addressActive);
      if (
        getAccount?.account?.vesting_periods &&
        getAccount.account.base_vesting_account?.original_vesting
      ) {
        const { vesting_periods: vestingPeriods } = getAccount.account;
        const { original_vesting: originalVestingAmount } = getAccount.account.base_vesting_account;
        const { start_time: startTime } = getAccount.account;
        const reduceOriginalVestingAmount = reduceBalances(originalVestingAmount);
        // eslint-disable-next-line no-restricted-syntax
        for (const key in reduceOriginalVestingAmount) {
          if (Object.hasOwn(reduceOriginalVestingAmount, key)) {
            const element = reduceOriginalVestingAmount[key];
            if (Object.hasOwn(vested, key)) {
              vested[key] += element;
            }
          }
        }

        const vestedAmountReduce = getVestingPeriodsData(vestingPeriods, startTime);
        // eslint-disable-next-line no-restricted-syntax
        for (const key in vestedAmountReduce) {
          if (Object.hasOwn(vestedAmountReduce, key)) {
            const element = vestedAmountReduce[key];
            if (Object.hasOwn(vested, key)) {
              vested[key] -= element;
            }
          }
        }
      }
      setVestedAmount(vested);
    })();
  }, [addressActive]);

  useEffect(() => {
    if (allBalances !== null && vestedAmount !== null) {
      const liquid = { ...allBalances };
      // eslint-disable-next-line no-restricted-syntax
      for (const key in vestedAmount) {
        if (Object.hasOwn(vestedAmount, key)) {
          const elementVestedAmount = vestedAmount[key];
          if (Object.hasOwn(liquid, key)) {
            const liquidAmount = liquid[key] - elementVestedAmount;
            // if (key === 'millivolt' || key === 'milliampere') {
            //   liquidAmount = liquidAmount;
            // }
            liquid[key] = liquidAmount > 0 ? liquidAmount : 0;
          }
        }
      }
      setLiquidBalances(liquid);
    }
  }, [allBalances, vestedAmount]);

  return { liquidBalances, refresh };
}

export default useGetBalances;

Synonyms

pussy-ts/src/hooks/getBalances.ts

Neighbours