mirror of
https://github.com/pezkuwichain/pezkuwi-apps.git
synced 2026-06-14 06:21:13 +00:00
159 lines
4.3 KiB
TypeScript
159 lines
4.3 KiB
TypeScript
// Copyright 2017-2026 @pezkuwi/app-staking authors & contributors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
import type { Option } from '@pezkuwi/types';
|
|
import type { Balance } from '@pezkuwi/types/interfaces';
|
|
import type { BN } from '@pezkuwi/util';
|
|
|
|
import React, { useMemo } from 'react';
|
|
|
|
import { CardSummary, styled, SummaryBox } from '@pezkuwi/react-components';
|
|
import { useApi, useCall } from '@pezkuwi/react-hooks';
|
|
import { FormatBalance } from '@pezkuwi/react-query';
|
|
import { BN_THREE, BN_TWO, BN_ZERO } from '@pezkuwi/util';
|
|
|
|
import { useTranslation } from '../translate.js';
|
|
|
|
interface Props {
|
|
avgStaked?: BN;
|
|
className?: string;
|
|
lastEra?: BN;
|
|
lowStaked?: BN;
|
|
minNominated?: BN;
|
|
minNominatorBond?: BN;
|
|
numNominators?: number;
|
|
numValidators?: number;
|
|
stakedReturn: number;
|
|
totalIssuance?: BN;
|
|
totalStaked?: BN;
|
|
}
|
|
|
|
interface ProgressInfo {
|
|
hideValue: true;
|
|
isBlurred: boolean;
|
|
total: BN;
|
|
value: BN;
|
|
}
|
|
|
|
const OPT_REWARD = {
|
|
transform: (optBalance: Option<Balance>) =>
|
|
optBalance.unwrapOrDefault()
|
|
};
|
|
|
|
function getProgressInfo (value?: BN, total?: BN): ProgressInfo {
|
|
return {
|
|
hideValue: true,
|
|
isBlurred: !(value && total),
|
|
total: (value && total) ? total : BN_THREE,
|
|
value: (value && total) ? value : BN_TWO
|
|
};
|
|
}
|
|
|
|
function Summary ({ avgStaked, className, lastEra, lowStaked, minNominated, minNominatorBond, stakedReturn, totalIssuance, totalStaked }: Props): React.ReactElement<Props> {
|
|
const { t } = useTranslation();
|
|
const { api } = useApi();
|
|
const lastReward = useCall<BN>(lastEra && api.query.staking.erasValidatorReward, [lastEra], OPT_REWARD);
|
|
|
|
const progressStake = useMemo(
|
|
() => getProgressInfo(totalStaked, totalIssuance),
|
|
[totalIssuance, totalStaked]
|
|
);
|
|
|
|
const progressAvg = useMemo(
|
|
() => getProgressInfo(lowStaked, avgStaked),
|
|
[avgStaked, lowStaked]
|
|
);
|
|
|
|
const percent = <span className='percent'>%</span>;
|
|
|
|
return (
|
|
<StyledSummaryBox className={className}>
|
|
<section className='media--800'>
|
|
<CardSummary
|
|
label={t('total staked')}
|
|
progress={progressStake}
|
|
>
|
|
<FormatBalance
|
|
className={progressStake.isBlurred ? '--tmp' : ''}
|
|
value={progressStake.value}
|
|
withSi
|
|
/>
|
|
</CardSummary>
|
|
</section>
|
|
<section className='media--800'>
|
|
<CardSummary label={t('returns')}>
|
|
{totalIssuance && (stakedReturn > 0)
|
|
? Number.isFinite(stakedReturn)
|
|
? <>{stakedReturn.toFixed(1)}{percent}</>
|
|
: '-.-%'
|
|
: <span className='--tmp'>0.0{percent}</span>
|
|
}
|
|
</CardSummary>
|
|
</section>
|
|
<section className='media--1000'>
|
|
<CardSummary
|
|
label={`${t('lowest / avg staked')}`}
|
|
progress={progressAvg}
|
|
>
|
|
<span className={progressAvg.isBlurred ? '--tmp' : ''}>
|
|
<FormatBalance
|
|
value={progressAvg.value}
|
|
withCurrency={false}
|
|
withSi
|
|
/>
|
|
/
|
|
<FormatBalance
|
|
className={progressAvg.isBlurred ? '--tmp' : ''}
|
|
value={progressAvg.total}
|
|
withSi
|
|
/>
|
|
</span>
|
|
</CardSummary>
|
|
</section>
|
|
<section className='media--1600'>
|
|
{minNominated?.gt(BN_ZERO) && (
|
|
<CardSummary
|
|
className='media--1600'
|
|
label={
|
|
minNominatorBond
|
|
? t('min nominated / threshold')
|
|
: t('min nominated')}
|
|
>
|
|
<FormatBalance
|
|
value={minNominated}
|
|
withCurrency={!minNominatorBond}
|
|
withSi
|
|
/>
|
|
{minNominatorBond && (
|
|
<>
|
|
/
|
|
<FormatBalance
|
|
value={minNominatorBond}
|
|
withSi
|
|
/>
|
|
</>
|
|
)}
|
|
</CardSummary>
|
|
)}
|
|
</section>
|
|
<section>
|
|
<CardSummary label={t('last reward')}>
|
|
<FormatBalance
|
|
className={lastReward ? '' : '--tmp'}
|
|
value={lastReward || 1}
|
|
withSi
|
|
/>
|
|
</CardSummary>
|
|
</section>
|
|
</StyledSummaryBox>
|
|
);
|
|
}
|
|
|
|
const StyledSummaryBox = styled(SummaryBox)`
|
|
.percent {
|
|
font-size: var(--font-percent-tiny);
|
|
}
|
|
`;
|
|
|
|
export default React.memo(Summary);
|