Show time remaining to claim payouts (#2584)

This commit is contained in:
Jaco Greeff 2020-04-19 12:13:13 +02:00 committed by GitHub
parent 07027f01b6
commit 93575c60fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 8 deletions

View File

@ -11,10 +11,11 @@ import React, { useEffect, useState } from 'react';
import ApiPromise from '@polkadot/api/promise';
import { AddressMini, Badge, TxButton } from '@polkadot/react-components';
import { useApi, useCall } from '@polkadot/react-hooks';
import { FormatBalance } from '@polkadot/react-query';
import { BlockToTime, FormatBalance } from '@polkadot/react-query';
import { useTranslation } from '../translate';
import { createErasString } from './util';
import useEraBlocks from './useEraBlocks';
interface Props {
className?: string;
@ -23,6 +24,11 @@ interface Props {
stakerPayoutsAfter: BN;
}
interface EraInfo {
eraStr: string;
oldestEra?: BN;
}
function createPrevPayoutType (api: ApiPromise, { era, isValidator, nominating }: DeriveStakerReward): SubmittableExtrinsic<'promise'> {
return isValidator
? api.tx.staking.payoutValidator(era)
@ -41,13 +47,15 @@ function Stash ({ className, isDisabled, payout: { available, rewards, stashId }
const { t } = useTranslation();
const { api } = useApi();
const [extrinsic, setExtrinsic] = useState<SubmittableExtrinsic<'promise'> | null>(null);
const [eraStr, setEraStr] = useState('');
const [{ eraStr, oldestEra }, setEraInfo] = useState<EraInfo>({ eraStr: '' });
const eraBlocks = useEraBlocks(oldestEra);
const stakingAccount = useCall<DeriveStakingAccount>(api.derive.staking.account, [stashId]);
useEffect((): void => {
rewards && setEraStr(
createErasString(rewards.map(({ era }): BN => era))
);
rewards && setEraInfo({
eraStr: createErasString(rewards.map(({ era }): BN => era)),
oldestEra: rewards[0]?.era
});
}, [rewards]);
useEffect((): void => {
@ -78,6 +86,7 @@ function Stash ({ className, isDisabled, payout: { available, rewards, stashId }
<span className='payout-eras'>{eraStr}</span>
</td>
<td className='number'><FormatBalance value={available} /></td>
<td className='number'>{eraBlocks && <BlockToTime blocks={eraBlocks} />}</td>
<td
className='button'
colSpan={3}

View File

@ -7,11 +7,12 @@ import { PayoutValidator } from './types';
import BN from 'bn.js';
import React, { useEffect, useState } from 'react';
import { AddressMini, Badge, Expander } from '@polkadot/react-components';
import { FormatBalance } from '@polkadot/react-query';
import { BlockToTime, FormatBalance } from '@polkadot/react-query';
import { useTranslation } from '../translate';
import PayButton from './PayButton';
import { createErasString } from './util';
import useEraBlocks from './useEraBlocks';
interface Props {
className?: string;
@ -23,15 +24,17 @@ interface State {
eraStr: string;
nominators: Record<string, BN>;
numNominators: number;
oldestEra?: BN;
}
function Payout ({ className, isDisabled, payout }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [{ eraStr, nominators, numNominators }, setState] = useState<State>({
const [{ eraStr, nominators, numNominators, oldestEra }, setState] = useState<State>({
eraStr: '',
nominators: {},
numNominators: 0
});
const eraBlocks = useEraBlocks(oldestEra);
useEffect((): void => {
const eraStr = createErasString(payout.eras.map(({ era }) => era));
@ -47,7 +50,7 @@ function Payout ({ className, isDisabled, payout }: Props): React.ReactElement<P
return nominators;
}, {});
setState({ eraStr, nominators, numNominators: Object.keys(nominators).length });
setState({ eraStr, nominators, numNominators: Object.keys(nominators).length, oldestEra: payout.eras[0]?.era });
}, [payout]);
return (
@ -62,6 +65,7 @@ function Payout ({ className, isDisabled, payout }: Props): React.ReactElement<P
<span className='payout-eras'>{eraStr}</span>
</td>
<td className='number'><FormatBalance value={payout.available} /></td>
<td className='number'>{eraBlocks && <BlockToTime blocks={eraBlocks} />}</td>
<td
className='start'
colSpan={2}

View File

@ -117,6 +117,7 @@ function Payouts ({ className, isInElection }: Props): React.ReactElement<Props>
[t('payout/stash'), 'start'],
[t('eras'), 'start'],
[t('available')],
[('remaining')],
[undefined, undefined, 3]
]}
isFixed
@ -137,6 +138,7 @@ function Payouts ({ className, isInElection }: Props): React.ReactElement<Props>
[t('payout/validator'), 'start'],
[t('eras'), 'start'],
[t('total')],
[('remaining')],
[undefined, undefined, 3]
]}
isFixed

View File

@ -0,0 +1,32 @@
// Copyright 2017-2020 @polkadot/app-staking authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { DeriveSessionProgress } from '@polkadot/api-derive/types';
import BN from 'bn.js';
import { useEffect, useState } from 'react';
import { useApi, useCall } from '@polkadot/react-hooks';
const ONE = new BN(1);
export default function useEraBlocks (era?: BN): BN | undefined {
const { api } = useApi();
const depth = useCall<BN>(api.query.staking.historyDepth, []);
const progress = useCall<DeriveSessionProgress>(api.derive.session.progress, []);
const [duration, setDuration] = useState<BN | undefined>();
useEffect((): void => {
depth && era && progress?.sessionLength.gt(ONE) && setDuration(
progress.eraLength
.mul(
depth
.sub(progress.activeEra.sub(era))
.add(ONE)
)
.sub(progress.eraProgress)
);
}, [api, depth, era, progress]);
return duration;
}