import { useCallback, useEffect, useState } from 'react';
import { BASE_DENOM, BECH32_PREFIX_VALOPER, DENOM_LIQUID } from 'src/constants/config';
import { useQueryClient } from 'src/contexts/queryClient';
import { useCyberClient } from 'src/contexts/queryCyberClient';
import { getDelegatorDelegations } from 'src/features/staking/delegation/getDelegatorDelegations';
import useGetSlots from '../../../../../containers/mint/useGetSlots';
import { coinDecimals, fromBech32 } from '../../../../../utils/utils';
const initValue = {
available: 0,
delegation: 0,
unbonding: 0,
rewards: 0,
total: 0,
};
const initValueTokens = {
liquid: 0,
vested: 0,
total: 0,
};
const initValueToken = {
[DENOM_LIQUID]: { ...initValueTokens },
milliampere: { ...initValueTokens },
millivolt: { ...initValueTokens },
};
function useGetBalance(address, updateAddress) {
const queryClient = useQueryClient();
const { rpc } = useCyberClient();
const [addressActive, setAddressActive] = useState(null);
const [loadingBalanceInfo, setLoadingBalanceInfo] = useState(true);
const [loadingBalanceToken, setLoadingBalanceToken] = useState(true);
const [balance, setBalance] = useState(initValue);
const [balanceToken, setBalanceToken] = useState(initValueToken);
const { vested, originalVesting, loadingAuthAccounts } = useGetSlots(
addressActive,
updateAddress
);
useEffect(() => {
if (address) {
if (address.bech32) {
setAddressActive(address.bech32);
} else {
setAddressActive(address);
}
}
}, [address]);
useEffect(() => {
const getBalance = async () => {
try {
if (queryClient && addressActive !== null && rpc) {
setBalance(initValue);
setLoadingBalanceInfo(true);
const availablePromise = await queryClient.getBalance(addressActive, BASE_DENOM);
setBalance((item) => ({
...item,
available: parseFloat(availablePromise.amount),
total: item.total + parseFloat(availablePromise.amount),
}));
const delegationResponses = await getDelegatorDelegations(rpc, addressActive);
let delegationsAmount = 0;
if (delegationResponses.length) {
delegationResponses.forEach((itemDelegation) => {
delegationsAmount += parseFloat(itemDelegation.balance.amount);
});
}
setBalance((item) => ({
...item,
delegation: parseFloat(delegationsAmount),
total: item.total + parseFloat(delegationsAmount),
}));
const unbondingPromise = await queryClient.delegatorUnbondingDelegations(addressActive);
if (
unbondingPromise.unbondingResponses &&
unbondingPromise.unbondingResponses.length > 0
) {
const { unbondingResponses } = unbondingPromise;
unbondingResponses.forEach((unbond, _i) => {
unbond.entries.forEach((entry, _j) => {
setBalance((item) => ({
...item,
unbonding: Math.floor(item.unbonding + parseFloat(entry.balance)),
total: Math.floor(item.total + parseFloat(entry.balance)),
}));
});
});
}
const rewardsPropsise = await queryClient.delegationTotalRewards(addressActive);
if (rewardsPropsise.total && rewardsPropsise.total.length > 0) {
setBalance((item) => ({
...item,
rewards: Math.floor(coinDecimals(parseFloat(rewardsPropsise.total[0].amount))),
total: Math.floor(
item.total + coinDecimals(parseFloat(rewardsPropsise.total[0].amount))
),
}));
}
const dataValidatorAddress = fromBech32(addressActive, BECH32_PREFIX_VALOPER);
const resultGetDistribution = await queryClient.validatorCommission(dataValidatorAddress);
if (resultGetDistribution.commission.commission.length > 0) {
const { commission } = resultGetDistribution;
setBalance((item) => ({
...item,
commission: Math.floor(coinDecimals(parseFloat(commission.commission[0].amount))),
total: Math.floor(
item.total + coinDecimals(parseFloat(commission.commission[0].amount))
),
}));
}
} else {
setBalance(initValue);
}
setLoadingBalanceInfo(false);
} catch (e) {
console.log(e);
setLoadingBalanceInfo(false);
setBalance(initValue);
}
};
getBalance();
}, [queryClient, rpc, addressActive]);
const getCalculationBalance = useCallback((data) => {
const balances = {};
if (Object.keys(data).length > 0) {
data.forEach((item) => {
balances[item.denom] = parseFloat(item.amount);
});
}
return balances;
}, []);
useEffect(() => {
const getBalance = async () => {
const initValueTokenAmount = {
[DENOM_LIQUID]: {
...initValueTokens,
},
milliampere: {
...initValueTokens,
},
millivolt: {
...initValueTokens,
},
tocyb: 0,
};
if (queryClient && addressActive !== null && !loadingAuthAccounts) {
try {
setBalanceToken(initValueToken);
setLoadingBalanceToken(true);
const getAllBalancesPromise = await queryClient.getAllBalances(addressActive);
const balancesToken = getCalculationBalance(getAllBalancesPromise);
if (Object.keys(balancesToken).length > 0) {
Object.keys(balancesToken).forEach((key) => {
if (Object.hasOwn(balancesToken, key) && key !== BASE_DENOM) {
const elementBalancesToken = balancesToken[key];
if (
Object.hasOwn(initValueTokenAmount, key) &&
Object.hasOwn(initValueTokenAmount[key], 'total')
) {
initValueTokenAmount[key].total = elementBalancesToken;
initValueTokenAmount[key].liquid = elementBalancesToken;
} else {
initValueTokenAmount[key] = elementBalancesToken;
}
if (Object.hasOwn(originalVesting, key) && Object.hasOwn(vested, key)) {
const vestedTokens = parseFloat(originalVesting[key]) - parseFloat(vested[key]);
const liquidAmount = elementBalancesToken - vestedTokens;
initValueTokenAmount[key].liquid = liquidAmount > 0 ? liquidAmount : 0;
initValueTokenAmount[key].vested = vestedTokens;
}
}
});
}
} catch (e) {
console.error('getBalance tokens error:', e);
}
}
setBalanceToken(initValueTokenAmount);
setLoadingBalanceToken(false);
};
getBalance();
}, [
queryClient,
addressActive,
vested,
originalVesting,
loadingAuthAccounts,
getCalculationBalance,
]);
return { balance, loadingBalanceInfo, balanceToken, loadingBalanceToken };
}
export default useGetBalance;