import { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { useParams } from 'react-router-dom';
import { useDevice } from 'src/contexts/device';
import { useQueryClient } from 'src/contexts/queryClient';
import { fromBech32, formatNumber, asyncForEach } from '../../utils/utils';
import { Loading } from '../../components';
import ActionBarContainer from './ActionBarContainer';
import { TableHeroes, TableItem, InfoBalance } from './components';
import getHeroes from './getHeroesHook';
import { BOND_STATUS } from '../../utils/config';
import { useGetBalance } from '../../pages/robot/_refactor/account/hooks';
import useSetActiveAddress from '../../hooks/useSetActiveAddress';
import { getDelegatorDelegations } from 'src/utils/search/utils';
import { useAdviser } from 'src/features/adviser/context';
import { DenomArr } from 'src/components';
import styles from './Validators.module.scss';
function Validators({ defaultAccount }) {
const { isMobile: mobile } = useDevice();
const { status = 'active' } = useParams();
const queryClient = useQueryClient();
const [updatePage, setUpdatePage] = useState(0);
const { addressActive } = useSetActiveAddress(defaultAccount);
const { balance, loadingBalanceInfo, balanceToken } = useGetBalance(
addressActive,
updatePage
);
const { validators, loadingValidators } = getHeroes();
const [loadingSelf, setLoadingSelf] = useState(true);
const [loadingBond, setLoadingBond] = useState(true);
const [bondedTokens, setBondedTokens] = useState(0);
const [validatorSelect, setValidatorSelect] = useState([]);
const [selectedIndex, setSelectedIndex] = useState('');
const [unStake, setUnStake] = useState(false);
const [delegationsData, setDelegationsData] = useState([]);
const [validatorsData, setValidatorsData] = useState([]);
// FIXME: use useGetHeroes hook instead
const { setAdviser } = useAdviser();
useEffect(() => {
setAdviser(
<div className={styles.info}>
the current undelegation period is <strong>42 days</strong>
<br />
you need to burn 1 <DenomArr denomValue="hydrogen" onlyImg /> to unstake
1 <DenomArr denomValue="boot" onlyImg />
</div>
);
}, [setAdviser]);
useEffect(() => {
setValidatorsData(validators);
setSelectedIndex('');
}, [validators]);
const updateFnc = () => {
setUpdatePage((item) => item + 1);
setValidatorSelect([]);
};
useEffect(() => {
if (addressActive !== null) {
setLoadingBond(true);
setLoadingSelf(true);
}
}, [addressActive]);
useEffect(() => {
const feachPool = async () => {
if (queryClient) {
const response = await queryClient.stakingPool();
if (response.pool.bondedTokens) {
setBondedTokens(response.pool.bondedTokens);
}
}
};
feachPool();
}, [queryClient]);
useEffect(() => {
try {
const feachDelegatorDelegations = async () => {
let delegationsDataTemp = [];
if (addressActive !== null && queryClient) {
const responseDelegatorDelegations = await getDelegatorDelegations(
queryClient,
addressActive.bech32
);
delegationsDataTemp = responseDelegatorDelegations;
}
setDelegationsData(delegationsDataTemp);
};
feachDelegatorDelegations();
} catch (e) {
console.log(`e`, e);
setDelegationsData([]);
}
}, [addressActive, queryClient, updatePage]);
useEffect(() => {
if (validators.length > 0 && delegationsData.length > 0) {
const tempValidators = [...validators];
const tempDelegationsData = [...delegationsData];
tempDelegationsData.forEach((item) => {
tempValidators.forEach((itemValidators, j) => {
if (
itemValidators.operatorAddress === item.delegation.validatorAddress
) {
tempValidators[j].delegation = item.balance;
}
});
});
setValidatorsData(tempValidators);
setLoadingBond(false);
} else {
setLoadingBond(true);
}
}, [delegationsData, validators]);
useEffect(() => {
const selfDelegation = async () => {
if (queryClient && validatorsData.length > 0) {
await asyncForEach(
Array.from(Array(validatorsData.length).keys()),
async (item) => {
const delegatorAddress = fromBech32(
validatorsData[item].operatorAddress
);
let shares = 0;
try {
const getSelfDelegation = await queryClient.delegation(
delegatorAddress,
validatorsData[item].operatorAddress
);
const { delegationResponse } = getSelfDelegation;
if (
delegationResponse.balance.amount &&
validatorsData[item].delegatorShares > 0
) {
const selfShares = delegationResponse.balance.amount;
const delegatorShares =
validatorsData[item].delegatorShares * 10 ** -18;
shares = (selfShares / delegatorShares) * 100;
}
} catch (error) {
shares = 0;
}
validatorsData[item].shares = formatNumber(
Math.floor(shares * 100) / 100,
2
);
}
);
setLoadingSelf(false);
}
};
selfDelegation();
}, [validatorsData, queryClient]);
const selectValidators = (validator, index) => {
let selectValidator = {};
let stake = false;
if (selectedIndex === index) {
setSelectedIndex('');
} else {
setSelectedIndex(index);
}
if (validatorSelect !== validator) {
selectValidator = validator;
if (selectValidator.delegation) {
if (parseFloat(selectValidator.delegation.amount) > 0) {
stake = true;
}
}
}
setValidatorSelect(selectValidator);
setUnStake(stake);
};
if (loadingValidators) {
return (
<div
style={{
width: '100%',
height: '50vh',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column',
}}
>
<Loading />
<div style={{ color: '#fff', marginTop: 20, fontSize: 20 }}>
Loading
</div>
</div>
);
}
return (
<div>
<main className="block-body" style={{ paddingTop: 0 }}>
<InfoBalance
balance={balance}
loadingBalanceInfo={loadingBalanceInfo}
balanceToken={balanceToken}
/>
<TableHeroes mobile={mobile} showJailed={status === 'jailed'}>
{validatorsData
.filter((validator) =>
status === 'jailed'
? BOND_STATUS[validator.status] < 3
: BOND_STATUS[validator.status] === 3
)
.map((validator, index) => {
const commission = formatNumber(
validator.commission.commissionRates.rate * 10 ** -18 * 100,
2
);
const staking = formatNumber(
Math.floor((validator.tokens / bondedTokens) * 100 * 100) / 100,
2
);
return (
<TableItem
key={validator.operator_address}
staking={staking}
commission={commission}
item={validator}
index={index + 1}
selected={index === selectedIndex}
selectValidators={() => selectValidators(validator, index)}
mobile={mobile}
showJailed={status === 'jailed'}
loadingSelf={loadingSelf}
loadingBond={loadingBond}
/>
);
})}
</TableHeroes>
</main>
<ActionBarContainer
updateFnc={updateFnc}
validators={validatorSelect}
addressPocket={addressActive}
unStake={unStake}
mobile={mobile}
balance={balance}
loadingBalanceInfo={loadingBalanceInfo}
balanceToken={balanceToken}
/>
</div>
);
}
const mapStateToProps = (store) => {
return {
defaultAccount: store.pocket.defaultAccount,
};
};
export default connect(mapStateToProps)(Validators);