Re-add validator queries (#2362)
* Re-add validator queries * Bumps * Pending only * Remove unused
This commit is contained in:
parent
591ffa3e0f
commit
42aaa0dcf5
@ -8,10 +8,10 @@
|
||||
"packages/*"
|
||||
],
|
||||
"resolutions": {
|
||||
"@polkadot/api": "^1.6.0-beta.19",
|
||||
"@polkadot/api-contract": "^1.6.0-beta.19",
|
||||
"@polkadot/api": "^1.6.0-beta.21",
|
||||
"@polkadot/api-contract": "^1.6.0-beta.21",
|
||||
"@polkadot/keyring": "^2.6.1",
|
||||
"@polkadot/types": "^1.6.0-beta.19",
|
||||
"@polkadot/types": "^1.6.0-beta.21",
|
||||
"@polkadot/util": "^2.6.1",
|
||||
"@polkadot/util-crypto": "^2.6.1",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
|
||||
@ -12,6 +12,6 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"@polkadot/api-contract": "^1.6.0-beta.19"
|
||||
"@polkadot/api-contract": "^1.6.0-beta.21"
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { BlockNumber, Hash, ReferendumIndex } from '@polkadot/types/interfaces';
|
||||
|
||||
import React from 'react';
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { Spinner, Table } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
@ -27,22 +27,24 @@ export default function DispatchQueue ({ className }: Props): React.ReactElement
|
||||
return (
|
||||
<div className={className}>
|
||||
<h1>{t('dispatch queue')}</h1>
|
||||
{queued?.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Body>
|
||||
{queued.map(([blockNumber, hash, referendumIndex]): React.ReactNode => (
|
||||
<DispatchEntry
|
||||
blockNumber={blockNumber}
|
||||
hash={hash}
|
||||
key={referendumIndex.toString()}
|
||||
referendumIndex={referendumIndex}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('nothing queued to be executed')
|
||||
{queued
|
||||
? queued.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Body>
|
||||
{queued.map(([blockNumber, hash, referendumIndex]): React.ReactNode => (
|
||||
<DispatchEntry
|
||||
blockNumber={blockNumber}
|
||||
hash={hash}
|
||||
key={referendumIndex.toString()}
|
||||
referendumIndex={referendumIndex}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('nothing queued to be executed')
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { DeriveProposal } from '@polkadot/api-derive/types';
|
||||
|
||||
import React from 'react';
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { Spinner, Table } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
import ProposalDisplay from './Proposal';
|
||||
@ -23,20 +23,22 @@ export default function Proposals ({ className }: Props): React.ReactElement<Pro
|
||||
return (
|
||||
<div className={`proposalSection ${className}`}>
|
||||
<h1>{t('proposals')}</h1>
|
||||
{proposals?.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Body>
|
||||
{proposals.map((proposal): React.ReactNode => (
|
||||
<ProposalDisplay
|
||||
key={proposal.index.toString()}
|
||||
value={proposal}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No active proposals')
|
||||
{proposals
|
||||
? proposals.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Body>
|
||||
{proposals.map((proposal): React.ReactNode => (
|
||||
<ProposalDisplay
|
||||
key={proposal.index.toString()}
|
||||
value={proposal}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No active proposals')
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { DerivedReferendum } from '@polkadot/api-derive/types';
|
||||
|
||||
import React from 'react';
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { Spinner, Table } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
import Referendum from './Referendum';
|
||||
@ -23,21 +23,23 @@ export default function Referendums ({ className }: Props): React.ReactElement<P
|
||||
return (
|
||||
<div className={`proposalSection ${className}`}>
|
||||
<h1>{t('referenda')}</h1>
|
||||
{referendums?.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Body>
|
||||
{referendums.map((referendum): React.ReactNode => (
|
||||
<Referendum
|
||||
idNumber={referendum.index}
|
||||
key={referendum.index.toString()}
|
||||
value={referendum}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No active referendums')
|
||||
{referendums
|
||||
? referendums.length
|
||||
? (
|
||||
<Table>
|
||||
<Table.Body>
|
||||
{referendums.map((referendum): React.ReactNode => (
|
||||
<Referendum
|
||||
idNumber={referendum.index}
|
||||
key={referendum.index.toString()}
|
||||
value={referendum}
|
||||
/>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
: t('No active referendums')
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -97,11 +97,11 @@ function Account ({ allStashes, className, isOwnStash, isVisible, next, onUpdate
|
||||
const { queueExtrinsic } = useContext(StatusContext);
|
||||
const { api } = useApi();
|
||||
const { allAccounts } = useAccounts();
|
||||
const [lastClaim, setLastClaim] = useState<BN | undefined>();
|
||||
const [firstClaim, setFirstClaim] = useState<BN | undefined>();
|
||||
const validateInfo = useCall<ValidatorInfo>(api.query.staking.validators, [stashId]);
|
||||
const balancesAll = useCall<DerivedBalancesAll>(api.derive.balances.all as any, [stashId]);
|
||||
const stakingAccount = useCall<DerivedStakingAccount>(isVisible && api.derive.staking.account as any, [stashId]);
|
||||
const stakerExposures = useCall<DeriveStakerExpoure[]>(lastClaim && isVisible && api.derive.staking.stakerExposure as any, [stashId, lastClaim]);
|
||||
const stakingAccount = useCall<DerivedStakingAccount>(api.derive.staking.account as any, [stashId]);
|
||||
const stakerExposures = useCall<DeriveStakerExpoure[]>(firstClaim && isVisible && api.derive.staking.stakerExposure as any, [stashId, firstClaim]);
|
||||
const [[stakingRewards, payoutEras], setStakingRewards] = useState<[DeriveStakerExpoure[], EraIndex[]]>([[], []]);
|
||||
const [{ controllerId, destination, hexSessionIdQueue, hexSessionIdNext, isLoading, isOwnController, isStashNominating, isStashValidating, nominees, sessionIds, validatorPrefs }, setStakeState] = useState<StakeState>({ controllerId: null, destination: 0, hexSessionIdNext: null, hexSessionIdQueue: null, isLoading: true, isOwnController: false, isStashNominating: false, isStashValidating: false, sessionIds: [] });
|
||||
const [activeNoms, setActiveNoms] = useState<string[]>([]);
|
||||
@ -119,7 +119,7 @@ function Account ({ allStashes, className, isOwnStash, isVisible, next, onUpdate
|
||||
|
||||
useEffect((): void => {
|
||||
if (stakingAccount?.stakingLedger?.lastReward) {
|
||||
setLastClaim(stakingAccount.stakingLedger.lastReward.unwrapOr(new BN(-1)));
|
||||
setFirstClaim(stakingAccount.stakingLedger.lastReward.unwrapOr(new BN(-1)).addn(1));
|
||||
}
|
||||
}, [stakingAccount]);
|
||||
|
||||
@ -146,17 +146,15 @@ function Account ({ allStashes, className, isOwnStash, isVisible, next, onUpdate
|
||||
}, [inactiveNoms, nominees]);
|
||||
|
||||
useEffect((): void => {
|
||||
if (stakerExposures && lastClaim) {
|
||||
const stakingRewards = stakerExposures.filter(({ era, isEmpty }): boolean =>
|
||||
!isEmpty && era.gt(lastClaim)
|
||||
);
|
||||
if (stakerExposures && firstClaim) {
|
||||
const stakingRewards = stakerExposures.filter(({ isEmpty }): boolean => !isEmpty);
|
||||
|
||||
setStakingRewards([
|
||||
stakingRewards,
|
||||
stakingRewards.map(({ era }): EraIndex => era)
|
||||
]);
|
||||
}
|
||||
}, [lastClaim, stakingAccount, stakerExposures]);
|
||||
}, [firstClaim, stakingAccount, stakerExposures]);
|
||||
|
||||
const _doPayout = (): void => {
|
||||
queueExtrinsic({
|
||||
@ -177,20 +175,22 @@ function Account ({ allStashes, className, isOwnStash, isVisible, next, onUpdate
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td>
|
||||
{!stakerExposures
|
||||
? <Spinner variant='mini' />
|
||||
: (payoutEras.length !== 0 && (
|
||||
<Badge
|
||||
hover={t('payouts for {{count}} eras pending', { replace: { count: payoutEras.length } })}
|
||||
info={payoutEras.length}
|
||||
isInline
|
||||
isTooltip
|
||||
type='counter'
|
||||
/>
|
||||
))
|
||||
}
|
||||
</td>
|
||||
{api.query.staking.activeEra && (
|
||||
<td>
|
||||
{!stakerExposures
|
||||
? <Spinner variant='mini' />
|
||||
: !!payoutEras.length && (
|
||||
<Badge
|
||||
hover={t('Pending payouts for {{count}} eras', { replace: { count: payoutEras.length } })}
|
||||
info={payoutEras.length}
|
||||
isInline
|
||||
isTooltip
|
||||
type='counter'
|
||||
/>
|
||||
)
|
||||
}
|
||||
</td>
|
||||
)}
|
||||
<td>
|
||||
<BondExtra
|
||||
controllerId={controllerId}
|
||||
|
||||
@ -113,7 +113,7 @@ export default function CurrentList ({ authorsMap, hasQueries, isIntentions, isV
|
||||
address={address}
|
||||
defaultName={defaultName}
|
||||
filterName={nameFilter}
|
||||
hasQueries={false && hasQueries}
|
||||
hasQueries={hasQueries}
|
||||
heartbeat={
|
||||
isMain && recentlyOnline
|
||||
? recentlyOnline[address]
|
||||
|
||||
@ -2,10 +2,12 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { DeriveEraRewards, DeriveStakerExpoure, DeriveStakerPoints } from '@polkadot/api-derive/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { Chart, Columar, Column } from '@polkadot/react-components';
|
||||
// import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { Chart, Columar, Column, Spinner } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { formatBalance } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
@ -37,109 +39,153 @@ interface ChartInfo {
|
||||
// const COLORS_OTHER = ['#acacac'];
|
||||
|
||||
const COLORS_REWARD = ['#8c2200', '#008c22', '#acacac'];
|
||||
const COLORS_BLOCKS = [undefined, '#acacac'];
|
||||
const COLORS_POINTS = [undefined, '#acacac'];
|
||||
|
||||
function balanceToNumber (amount: BN, divisor: BN): number {
|
||||
return amount.muln(1000).div(divisor).toNumber() / 1000;
|
||||
}
|
||||
|
||||
function extractCharts (validatorId: string, divisor: BN, rewards: any[] = []): [ChartInfo, ChartInfo, ChartInfo] {
|
||||
function extractPoints (points: DeriveStakerPoints[]): ChartInfo {
|
||||
const labels: string[] = [];
|
||||
const blockAvgSet: LineDataEntry = [];
|
||||
const blockIdxSet: LineDataEntry = [];
|
||||
const slashSet: LineDataEntry = [];
|
||||
const rewardSet: LineDataEntry = [];
|
||||
const rewardAvgSet: LineDataEntry = [];
|
||||
const stakeSet: LineDataEntry = [];
|
||||
let blockTotal = 0;
|
||||
let rewardTotal = 0;
|
||||
|
||||
rewards.forEach(({ era, eraPoints, eraReward, validators }, index): void => {
|
||||
const points = validators[validatorId]?.points || new BN(0);
|
||||
const myReward = eraPoints.gtn(0)
|
||||
? balanceToNumber(
|
||||
points
|
||||
.mul(eraReward)
|
||||
.div(eraPoints),
|
||||
divisor
|
||||
)
|
||||
: 0;
|
||||
|
||||
blockTotal += points.toNumber();
|
||||
rewardTotal += myReward;
|
||||
const avgSet: LineDataEntry = [];
|
||||
const idxSet: LineDataEntry = [];
|
||||
let total = 0;
|
||||
|
||||
points.forEach(({ era, points }, index): void => {
|
||||
total += points.toNumber();
|
||||
labels.push(era.toHuman());
|
||||
|
||||
blockAvgSet.push(Math.ceil(blockTotal * 100 / (index + 1)) / 100);
|
||||
blockIdxSet.push(points);
|
||||
avgSet.push(Math.ceil(total * 100 / (index + 1)) / 100);
|
||||
idxSet.push(points);
|
||||
});
|
||||
|
||||
rewardSet.push(myReward);
|
||||
rewardAvgSet.push(Math.ceil(rewardTotal * 100 / (index + 1)) / 100);
|
||||
return {
|
||||
chart: [idxSet, avgSet],
|
||||
labels
|
||||
};
|
||||
}
|
||||
|
||||
function extractRewards (erasRewards: DeriveEraRewards[], allPoints: DeriveStakerPoints[], divisor: BN): ChartInfo {
|
||||
const labels: string[] = [];
|
||||
const slashSet: LineDataEntry = [];
|
||||
const rewardSet: LineDataEntry = [];
|
||||
const avgSet: LineDataEntry = [];
|
||||
let total = 0;
|
||||
|
||||
erasRewards.forEach(({ era, eraReward }, index): void => {
|
||||
const points = allPoints.find((points) => points.era.eq(era));
|
||||
const reward = points?.eraPoints.gtn(0)
|
||||
? balanceToNumber(points.points.mul(eraReward).div(points.eraPoints), divisor)
|
||||
: 0;
|
||||
|
||||
total += reward;
|
||||
labels.push(era.toHuman());
|
||||
|
||||
rewardSet.push(reward);
|
||||
avgSet.push(Math.ceil(total * 100 / (index + 1)) / 100);
|
||||
slashSet.push(0); // TODO
|
||||
});
|
||||
|
||||
return {
|
||||
chart: [slashSet, rewardSet, avgSet],
|
||||
labels
|
||||
};
|
||||
}
|
||||
|
||||
function extractStake (exposures: DeriveStakerExpoure[], divisor: BN): ChartInfo {
|
||||
const labels: string[] = [];
|
||||
const stakeSet: LineDataEntry = [];
|
||||
|
||||
exposures.forEach(({ era, isValidator, validators }): void => {
|
||||
labels.push(era.toHuman());
|
||||
stakeSet.push(
|
||||
balanceToNumber(validators[validatorId]?.exposure.total.toBn() || new BN(0), divisor)
|
||||
balanceToNumber(
|
||||
isValidator
|
||||
? Object.values(validators)[0].total.toBn()
|
||||
: new BN(0),
|
||||
divisor
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return [
|
||||
{ chart: [blockIdxSet, blockAvgSet], labels },
|
||||
{ chart: [slashSet, rewardSet, rewardAvgSet], labels },
|
||||
{ chart: [stakeSet], labels }
|
||||
];
|
||||
return {
|
||||
chart: [stakeSet],
|
||||
labels
|
||||
};
|
||||
}
|
||||
|
||||
export default function Validator ({ className, validatorId }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
// const { api } = useApi();
|
||||
const [[{ chart: blockChart, labels: blockLabels }, { chart: rewardChart, labels: rewardLabels }, { chart: stakeChart, labels: stakeLabels }], setCharts] = useState<[ChartInfo, ChartInfo, ChartInfo]>([{ chart: [], labels: [] }, { chart: [], labels: [] }, { chart: [], labels: [] }]);
|
||||
const stakerRewards = undefined; // useCall<DeriveStakerReward[]>(api.derive.staking.stakerRewards as any, [validatorId, true]);
|
||||
const { api } = useApi();
|
||||
const [{ chart: pointChart, labels: pointLabels }, setPointChart] = useState<ChartInfo>({ chart: [], labels: [] });
|
||||
const [{ chart: rewardChart, labels: rewardLabels }, setRewardChart] = useState<ChartInfo>({ chart: [], labels: [] });
|
||||
const [{ chart: stakeChart, labels: stakeLabels }, setStakeCharts] = useState<ChartInfo>({ chart: [], labels: [] });
|
||||
const erasRewards = useCall<DeriveEraRewards[]>(api.derive.staking.erasRewards as any, []);
|
||||
const stakerPoints = useCall<DeriveStakerPoints[]>(api.derive.staking.stakerPoints as any, [validatorId, true]);
|
||||
const stakerExposure = useCall<DeriveStakerExpoure[]>(api.derive.staking.stakerExposure as any, [validatorId, true]);
|
||||
const { currency, divisor } = useMemo((): { currency: string; divisor: BN } => ({
|
||||
currency: formatBalance.getDefaults().unit,
|
||||
divisor: new BN('1'.padEnd(formatBalance.getDefaults().decimals + 1, '0'))
|
||||
}), [formatBalance]);
|
||||
|
||||
useEffect((): void => {
|
||||
setCharts(extractCharts(validatorId, divisor, stakerRewards));
|
||||
}, [stakerRewards, validatorId]);
|
||||
stakerPoints && setPointChart(extractPoints(stakerPoints));
|
||||
}, [stakerPoints]);
|
||||
|
||||
useEffect((): void => {
|
||||
erasRewards && stakerPoints && setRewardChart(extractRewards(erasRewards, stakerPoints, divisor));
|
||||
}, [erasRewards, stakerPoints]);
|
||||
|
||||
useEffect((): void => {
|
||||
stakerExposure && setStakeCharts(extractStake(stakerExposure, divisor));
|
||||
}, [stakerExposure]);
|
||||
|
||||
return (
|
||||
<Columar className={className}>
|
||||
<Column emptyText={t('Loading block data')}>
|
||||
{!!blockChart.length && (
|
||||
<div className='staking--Chart'>
|
||||
<h1>{t('blocks produced')}</h1>
|
||||
<Chart.Line
|
||||
colors={COLORS_BLOCKS}
|
||||
labels={blockLabels}
|
||||
legends={[t('blocks'), t('average')]}
|
||||
values={blockChart}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{!!rewardChart.length && (
|
||||
<div className='staking--Chart'>
|
||||
<h1>{t('rewards & slashes')}</h1>
|
||||
<Chart.Line
|
||||
colors={COLORS_REWARD}
|
||||
labels={rewardLabels}
|
||||
legends={[t('{{currency}} slashed', { replace: { currency } }), t('{{currency}} rewards', { replace: { currency } }), t('{{currency}} average', { replace: { currency } })]}
|
||||
values={rewardChart}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<Column>
|
||||
<div className='staking--Chart'>
|
||||
<h1>{t('era points')}</h1>
|
||||
{pointChart.length
|
||||
? (
|
||||
<Chart.Line
|
||||
colors={COLORS_POINTS}
|
||||
labels={pointLabels}
|
||||
legends={[t('points'), t('average')]}
|
||||
values={pointChart}
|
||||
/>
|
||||
)
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
<div className='staking--Chart'>
|
||||
<h1>{t('rewards & slashes')}</h1>
|
||||
{rewardChart.length
|
||||
? (
|
||||
<Chart.Line
|
||||
colors={COLORS_REWARD}
|
||||
labels={rewardLabels}
|
||||
legends={[t('{{currency}} slashed', { replace: { currency } }), t('{{currency}} rewards', { replace: { currency } }), t('{{currency}} average', { replace: { currency } })]}
|
||||
values={rewardChart}
|
||||
/>
|
||||
)
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
</Column>
|
||||
<Column emptyText={t('Loading staker data')}>
|
||||
{stakeChart && !!stakeChart[0]?.length && (
|
||||
<div className='staking--Chart'>
|
||||
<h1>{t('elected stake')}</h1>
|
||||
<Chart.Line
|
||||
labels={stakeLabels}
|
||||
legends={[t('{{currency}} total', { replace: { currency } }), t('{{currency}} own', { replace: { currency } }), t('{{currency}} other', { replace: { currency } })]}
|
||||
values={stakeChart}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<Column>
|
||||
<div className='staking--Chart'>
|
||||
<h1>{t('elected stake')}</h1>
|
||||
{stakeChart && !!stakeChart[0]?.length
|
||||
? (
|
||||
<Chart.Line
|
||||
labels={stakeLabels}
|
||||
legends={[t('{{currency}} total', { replace: { currency } }), t('{{currency}} own', { replace: { currency } }), t('{{currency}} other', { replace: { currency } })]}
|
||||
values={stakeChart}
|
||||
/>
|
||||
)
|
||||
: <Spinner />
|
||||
}
|
||||
</div>
|
||||
</Column>
|
||||
</Columar>
|
||||
);
|
||||
|
||||
@ -67,7 +67,7 @@ function StakingApp ({ basePath, className }: Props): React.ReactElement<Props>
|
||||
}
|
||||
], [t]);
|
||||
const hiddenTabs = useMemo((): string[] => {
|
||||
const result = next ? ['query'] : ['waiting', 'query'];
|
||||
const result = next ? [] : ['waiting'];
|
||||
|
||||
if (!hasAccounts) {
|
||||
result.push('actions', 'query');
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
"homepage": "https://github.com/polkadot-js/ui/tree/master/packages/ui-reactive#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"@polkadot/api": "^1.6.0-beta.19",
|
||||
"@polkadot/api": "^1.6.0-beta.21",
|
||||
"@polkadot/extension-dapp": "^0.22.1",
|
||||
"rxjs-compat": "^6.5.4"
|
||||
}
|
||||
|
||||
@ -5,21 +5,27 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useTranslation } from './translate';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
variant?: 'app' | 'push' | 'mini';
|
||||
}
|
||||
|
||||
function Spinner ({ className, variant = 'app' }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
const strokeWidth = variant === 'app' ? 2 : 4;
|
||||
|
||||
return (
|
||||
<div className={[className, 'ui--Spinner', variant].join(' ')}>
|
||||
<div className="loader">
|
||||
<div className={`${className} ui--Spinner ${variant}`}>
|
||||
<div className='loader'>
|
||||
<svg className="circular" viewBox="25 25 50 50">
|
||||
<circle className="path" cx="50" cy="50" r="20" fill="none" strokeWidth={strokeWidth} strokeMiterlimit="10"/>
|
||||
</svg>
|
||||
</div>
|
||||
{variant === 'app' && (
|
||||
<div className='text'>{t('Retrieving data')}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -29,6 +35,7 @@ export default styled(Spinner)`
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
width: 64px;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: block;
|
||||
@ -36,6 +43,12 @@ export default styled(Spinner)`
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
margin: 0.25rem auto 1.5rem auto;
|
||||
opacity: 0.6;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.circular {
|
||||
animation: rotate 2s linear infinite;
|
||||
height: 100%;
|
||||
|
||||
@ -69,8 +69,7 @@ export default function BlockToTime ({ blocks, children, className, label, style
|
||||
time[1] ? (time[1] > 1) ? t('{{h}} hrs', { replace: { h: time[1] } }) : t('1 hr') : null,
|
||||
time[2] ? (time[2] > 1) ? t('{{m}} mins', { replace: { m: time[2] } }) : t('1 min') : null,
|
||||
time[3] ? (time[3] > 1) ? t('{{s}} s', { replace: { s: time[3] } }) : t('1 s') : null
|
||||
].filter((value): value is string => !!value)
|
||||
.join(' ');
|
||||
].filter((value): value is string => !!value).slice(0, 2).join(' ');
|
||||
}, [api, blocks, t]);
|
||||
|
||||
return (
|
||||
|
||||
@ -36,19 +36,19 @@ function getDisplayValue (now = 0, value: BN | Date | number = 0): string {
|
||||
? (value as Date).getTime()
|
||||
: bnToBn(value as number).toNumber()
|
||||
) || 0;
|
||||
let display = '0.0s';
|
||||
let display = '0.0 s';
|
||||
|
||||
if (now && tsValue) {
|
||||
const elapsed = Math.max(Math.abs(now - tsValue), 0) / 1000;
|
||||
|
||||
if (elapsed < 15) {
|
||||
display = `${elapsed.toFixed(1)}s`;
|
||||
display = `${elapsed.toFixed(1)} s`;
|
||||
} else if (elapsed < 60) {
|
||||
display = `${elapsed | 0}s`;
|
||||
display = `${elapsed | 0} s`;
|
||||
} else if (elapsed < 3600) {
|
||||
display = `${elapsed / 60 | 0}m`;
|
||||
display = `${elapsed / 60 | 0} min`;
|
||||
} else {
|
||||
display = `${elapsed / 3600 | 0}h`;
|
||||
display = `${elapsed / 3600 | 0} hr`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
112
yarn.lock
112
yarn.lock
@ -2765,56 +2765,56 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@polkadot/api-contract@npm:^1.6.0-beta.19":
|
||||
version: 1.6.0-beta.19
|
||||
resolution: "@polkadot/api-contract@npm:1.6.0-beta.19"
|
||||
"@polkadot/api-contract@npm:^1.6.0-beta.21":
|
||||
version: 1.6.0-beta.21
|
||||
resolution: "@polkadot/api-contract@npm:1.6.0-beta.21"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.8.4
|
||||
"@polkadot/api": 1.6.0-beta.19
|
||||
"@polkadot/rpc-core": 1.6.0-beta.19
|
||||
"@polkadot/types": 1.6.0-beta.19
|
||||
"@polkadot/api": 1.6.0-beta.21
|
||||
"@polkadot/rpc-core": 1.6.0-beta.21
|
||||
"@polkadot/types": 1.6.0-beta.21
|
||||
"@polkadot/util": ^2.6.1
|
||||
bn.js: ^5.1.1
|
||||
rxjs: ^6.5.4
|
||||
checksum: 2/77ce8b5675b3e6eaa6397aa8b4950f95fdec5035acc681315982bd314a927b413078e86f206d86d8e42508c7e49dc319408a258a1b58bb360f4e560e56b748cf
|
||||
checksum: 2/548190e7c3423797e4e4cd5d55015a82f7629ebbe2b08754a50ea5567783f0e7f940a48650126287309d11bb7babd09695475958778411c322b5b6699b137091
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@polkadot/api-derive@npm:1.6.0-beta.19":
|
||||
version: 1.6.0-beta.19
|
||||
resolution: "@polkadot/api-derive@npm:1.6.0-beta.19"
|
||||
"@polkadot/api-derive@npm:1.6.0-beta.21":
|
||||
version: 1.6.0-beta.21
|
||||
resolution: "@polkadot/api-derive@npm:1.6.0-beta.21"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.8.4
|
||||
"@polkadot/api": 1.6.0-beta.19
|
||||
"@polkadot/rpc-core": 1.6.0-beta.19
|
||||
"@polkadot/rpc-provider": 1.6.0-beta.19
|
||||
"@polkadot/types": 1.6.0-beta.19
|
||||
"@polkadot/api": 1.6.0-beta.21
|
||||
"@polkadot/rpc-core": 1.6.0-beta.21
|
||||
"@polkadot/rpc-provider": 1.6.0-beta.21
|
||||
"@polkadot/types": 1.6.0-beta.21
|
||||
"@polkadot/util": ^2.6.1
|
||||
"@polkadot/util-crypto": ^2.6.1
|
||||
bn.js: ^5.1.1
|
||||
memoizee: ^0.4.14
|
||||
rxjs: ^6.5.4
|
||||
checksum: 2/c323a5288387de8ffd05c6131bb8ad78ab2098cc81da076ac9599c84c9918975a158fb342199998e7e5bb7b0e9e155eef7257981f6e01c3c2fee49138d0fe00d
|
||||
checksum: 2/7a4c5fd978939942edb2ea2531bab6d1cd60a937d45e809a41e129d3ab707eecd9aae505ec78e383175672d3b4731693da46b42bb0239f8d65221b9705697ee2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@polkadot/api@npm:^1.6.0-beta.19":
|
||||
version: 1.6.0-beta.19
|
||||
resolution: "@polkadot/api@npm:1.6.0-beta.19"
|
||||
"@polkadot/api@npm:^1.6.0-beta.21":
|
||||
version: 1.6.0-beta.21
|
||||
resolution: "@polkadot/api@npm:1.6.0-beta.21"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.8.4
|
||||
"@polkadot/api-derive": 1.6.0-beta.19
|
||||
"@polkadot/api-derive": 1.6.0-beta.21
|
||||
"@polkadot/keyring": ^2.6.1
|
||||
"@polkadot/metadata": 1.6.0-beta.19
|
||||
"@polkadot/rpc-core": 1.6.0-beta.19
|
||||
"@polkadot/rpc-provider": 1.6.0-beta.19
|
||||
"@polkadot/types": 1.6.0-beta.19
|
||||
"@polkadot/metadata": 1.6.0-beta.21
|
||||
"@polkadot/rpc-core": 1.6.0-beta.21
|
||||
"@polkadot/rpc-provider": 1.6.0-beta.21
|
||||
"@polkadot/types": 1.6.0-beta.21
|
||||
"@polkadot/util": ^2.6.1
|
||||
"@polkadot/util-crypto": ^2.6.1
|
||||
bn.js: ^5.1.1
|
||||
eventemitter3: ^4.0.0
|
||||
rxjs: ^6.5.4
|
||||
checksum: 2/5ee9faf612bc98740ef2784dd453c46d051dffe34d309537952ab50e5b4b1be6053426d37a892a7f490149b72822891f5049b2a55f96f68c79a89c12ca13a1da
|
||||
checksum: 2/dbeb96c03ac28e47f2c3feb73d99df6f9c3820d143aca97c437e1e13caa0e889fb76751af4ab2348e89d11d4050eaa699fc2bd4645af21066ece83fa8c863f8e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -2864,7 +2864,7 @@ __metadata:
|
||||
resolution: "@polkadot/app-contracts@workspace:packages/page-contracts"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.8.7
|
||||
"@polkadot/api-contract": ^1.6.0-beta.19
|
||||
"@polkadot/api-contract": ^1.6.0-beta.21
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -3176,14 +3176,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@polkadot/jsonrpc@npm:1.6.0-beta.19":
|
||||
version: 1.6.0-beta.19
|
||||
resolution: "@polkadot/jsonrpc@npm:1.6.0-beta.19"
|
||||
"@polkadot/jsonrpc@npm:1.6.0-beta.21":
|
||||
version: 1.6.0-beta.21
|
||||
resolution: "@polkadot/jsonrpc@npm:1.6.0-beta.21"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.8.4
|
||||
"@polkadot/types": 1.6.0-beta.19
|
||||
"@polkadot/types": 1.6.0-beta.21
|
||||
"@polkadot/util": ^2.6.1
|
||||
checksum: 2/95861a02237971978caaa2b7f5ca85a2dc7951a88a24f83a39907789ce81e2ca7424e5c83103d961733eb44308110fdf245a5d93a9f491bed503898208b0a655
|
||||
checksum: 2/832b1470785788117c0302ad7c36811a054a037bbbe8609d25cfc140d4eb29d051004ceeeab1492c0aebf0c205fad83fa5204fa82ce81bba0daaf0d01a6b65dc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -3198,16 +3198,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@polkadot/metadata@npm:1.6.0-beta.19":
|
||||
version: 1.6.0-beta.19
|
||||
resolution: "@polkadot/metadata@npm:1.6.0-beta.19"
|
||||
"@polkadot/metadata@npm:1.6.0-beta.21":
|
||||
version: 1.6.0-beta.21
|
||||
resolution: "@polkadot/metadata@npm:1.6.0-beta.21"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.8.4
|
||||
"@polkadot/types": 1.6.0-beta.19
|
||||
"@polkadot/types": 1.6.0-beta.21
|
||||
"@polkadot/util": ^2.6.1
|
||||
"@polkadot/util-crypto": ^2.6.1
|
||||
bn.js: ^5.1.1
|
||||
checksum: 2/a2dded0bc63062ad6bf00501464bca90e168812e25f98b94664f798b0a151f78d672c1366ed5c60b212c27ae0bc557497a482af7b8617f11f831c51fe63ab6d4
|
||||
checksum: 2/12f600495e9fd5a9304e24837f40cc525dd1a51f84468199adacff5f56dc8822cc31bbbaa6f29eb739b06798d6b73fbc0816b6b37c6d5090f364121c1e06cc1c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -3216,7 +3216,7 @@ __metadata:
|
||||
resolution: "@polkadot/react-api@workspace:packages/react-api"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.8.7
|
||||
"@polkadot/api": ^1.6.0-beta.19
|
||||
"@polkadot/api": ^1.6.0-beta.21
|
||||
"@polkadot/extension-dapp": ^0.22.1
|
||||
rxjs-compat: ^6.5.4
|
||||
languageName: unknown
|
||||
@ -3328,37 +3328,37 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@polkadot/rpc-core@npm:1.6.0-beta.19":
|
||||
version: 1.6.0-beta.19
|
||||
resolution: "@polkadot/rpc-core@npm:1.6.0-beta.19"
|
||||
"@polkadot/rpc-core@npm:1.6.0-beta.21":
|
||||
version: 1.6.0-beta.21
|
||||
resolution: "@polkadot/rpc-core@npm:1.6.0-beta.21"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.8.4
|
||||
"@polkadot/jsonrpc": 1.6.0-beta.19
|
||||
"@polkadot/metadata": 1.6.0-beta.19
|
||||
"@polkadot/rpc-provider": 1.6.0-beta.19
|
||||
"@polkadot/types": 1.6.0-beta.19
|
||||
"@polkadot/jsonrpc": 1.6.0-beta.21
|
||||
"@polkadot/metadata": 1.6.0-beta.21
|
||||
"@polkadot/rpc-provider": 1.6.0-beta.21
|
||||
"@polkadot/types": 1.6.0-beta.21
|
||||
"@polkadot/util": ^2.6.1
|
||||
memoizee: ^0.4.14
|
||||
rxjs: ^6.5.4
|
||||
checksum: 2/b569ce533b374089788f297a72e4f902f6750d4aa809fd7f426b54600c857fd3d1b36c89d2043f135958b1a96d79ebe5665948c58756767881e48dcf984118b4
|
||||
checksum: 2/c7f06fd071329bfe88eca194e84231bf991594100f4911486faf22465f74635f352352cd5e7b18d656a0cd36b6c9160a1f4911a1722972dbf4b74b0c5a06dfea
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@polkadot/rpc-provider@npm:1.6.0-beta.19":
|
||||
version: 1.6.0-beta.19
|
||||
resolution: "@polkadot/rpc-provider@npm:1.6.0-beta.19"
|
||||
"@polkadot/rpc-provider@npm:1.6.0-beta.21":
|
||||
version: 1.6.0-beta.21
|
||||
resolution: "@polkadot/rpc-provider@npm:1.6.0-beta.21"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.8.4
|
||||
"@polkadot/jsonrpc": 1.6.0-beta.19
|
||||
"@polkadot/metadata": 1.6.0-beta.19
|
||||
"@polkadot/types": 1.6.0-beta.19
|
||||
"@polkadot/jsonrpc": 1.6.0-beta.21
|
||||
"@polkadot/metadata": 1.6.0-beta.21
|
||||
"@polkadot/types": 1.6.0-beta.21
|
||||
"@polkadot/util": ^2.6.1
|
||||
"@polkadot/util-crypto": ^2.6.1
|
||||
bn.js: ^5.1.1
|
||||
eventemitter3: ^4.0.0
|
||||
isomorphic-fetch: ^2.2.1
|
||||
websocket: ^1.0.31
|
||||
checksum: 2/b50edfd7609657c3d3a02f7040878eca5bd9ea46f44e6dca6c93c5d60e9060cd54207029c1c2fe47384b3ebc078b54e410f4f48948e890db8154d32312707349
|
||||
checksum: 2/79eaa8f1a10d4b4922f1e15ece40da1981205640f0ce7ab69240dc20907fcbf9c333d293eda50aeea992ba813646374750916a5fddf198a1cb20759247c4ca3e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -3371,19 +3371,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@polkadot/types@npm:^1.6.0-beta.19":
|
||||
version: 1.6.0-beta.19
|
||||
resolution: "@polkadot/types@npm:1.6.0-beta.19"
|
||||
"@polkadot/types@npm:^1.6.0-beta.21":
|
||||
version: 1.6.0-beta.21
|
||||
resolution: "@polkadot/types@npm:1.6.0-beta.21"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.8.4
|
||||
"@polkadot/metadata": 1.6.0-beta.19
|
||||
"@polkadot/metadata": 1.6.0-beta.21
|
||||
"@polkadot/util": ^2.6.1
|
||||
"@polkadot/util-crypto": ^2.6.1
|
||||
"@types/bn.js": ^4.11.6
|
||||
bn.js: ^5.1.1
|
||||
memoizee: ^0.4.14
|
||||
rxjs: ^6.5.4
|
||||
checksum: 2/8d073b06cddc3817cfa48e31fd3e01646046bf9aff27ff3b903d9b22e111372177813bb921528ceea640ac9ff35d22deb247462dbe0dff1c3b62d05d6d711030
|
||||
checksum: 2/9460fe59f068f5ec3d6675245e395d8f88ace621133aa44aeb04372e40cfbbf51a27901edb6dd4a157a24c14a4934332aa754f51cfdc2a27912ba22d3646a261
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user