diff --git a/package.json b/package.json index 1f67c4238d..fa7d863b80 100644 --- a/package.json +++ b/package.json @@ -8,12 +8,12 @@ "packages/*" ], "resolutions": { - "@polkadot/api": "^1.6.0-beta.24", - "@polkadot/api-contract": "^1.6.0-beta.24", - "@polkadot/keyring": "^2.6.1", - "@polkadot/types": "^1.6.0-beta.24", - "@polkadot/util": "^2.6.1", - "@polkadot/util-crypto": "^2.6.1", + "@polkadot/api": "^1.6.0-beta.26", + "@polkadot/api-contract": "^1.6.0-beta.26", + "@polkadot/keyring": "^2.6.2", + "@polkadot/types": "^1.6.0-beta.26", + "@polkadot/util": "^2.6.2", + "@polkadot/util-crypto": "^2.6.2", "babel-core": "^7.0.0-bridge.0", "typescript": "^3.8.2" }, @@ -36,7 +36,7 @@ "@babel/core": "^7.8.7", "@babel/register": "^7.8.6", "@babel/runtime": "^7.8.7", - "@polkadot/dev": "^0.50.29", + "@polkadot/dev": "^0.50.30", "@polkadot/ts": "^0.3.7", "@types/bn.js": "^4.11.6", "@types/chart.js": "^2.9.15", diff --git a/packages/apps/package.json b/packages/apps/package.json index ac06203e51..5da1c272b7 100644 --- a/packages/apps/package.json +++ b/packages/apps/package.json @@ -15,7 +15,7 @@ "dependencies": { "@babel/polyfill": "^7.8.7", "@babel/runtime": "^7.8.7", - "@polkadot/dev": "^0.50.29", + "@polkadot/dev": "^0.50.30", "@polkadot/react-components": "0.40.0-beta.108", "@polkadot/react-signer": "0.40.0-beta.108", "query-string": "^6.11.1" diff --git a/packages/page-contracts/package.json b/packages/page-contracts/package.json index c835390afd..8fa06b5b00 100644 --- a/packages/page-contracts/package.json +++ b/packages/page-contracts/package.json @@ -12,6 +12,6 @@ "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.8.7", - "@polkadot/api-contract": "^1.6.0-beta.24" + "@polkadot/api-contract": "^1.6.0-beta.26" } } diff --git a/packages/page-parachains/src/Overview/Parachain.tsx b/packages/page-parachains/src/Overview/Parachain.tsx index d3c83607b5..326dd5c5a6 100644 --- a/packages/page-parachains/src/Overview/Parachain.tsx +++ b/packages/page-parachains/src/Overview/Parachain.tsx @@ -7,7 +7,6 @@ import { DeriveParachain } from '@polkadot/api-derive/types'; import React from 'react'; import { useHistory } from 'react-router-dom'; import styled from 'styled-components'; -import { formatNumber } from '@polkadot/util'; import { Badge, Icon } from '@polkadot/react-components'; import ParachainInfo from '../ParachainInfo'; @@ -18,7 +17,7 @@ interface Props { parachain: DeriveParachain; } -function Parachain ({ className, parachain: { didUpdate, id, info, pendingSwapId, relayDispatchQueueSize = 0, watermark } }: Props): React.ReactElement { +function Parachain ({ className, parachain: { didUpdate, id, info, pendingSwapId, relayDispatchQueueSize = 0 } }: Props): React.ReactElement { const { t } = useTranslation(); const history = useHistory(); @@ -81,10 +80,6 @@ function Parachain ({ className, parachain: { didUpdate, id, info, pendingSwapId {info?.scheduling?.toString() || t('')} - - -

#{formatNumber(watermark)}

- ); } diff --git a/packages/page-parachains/src/Parachain/index.tsx b/packages/page-parachains/src/Parachain/index.tsx index a523043c81..a66839b4d0 100644 --- a/packages/page-parachains/src/Parachain/index.tsx +++ b/packages/page-parachains/src/Parachain/index.tsx @@ -10,7 +10,7 @@ import { useHistory, useParams } from 'react-router-dom'; import styled from 'styled-components'; import { Button, CardSummary, Columar, Column, Icon, Menu, Popup, Spinner, SummaryBox } from '@polkadot/react-components'; import { useApi, useCall, useModal, useToggle } from '@polkadot/react-hooks'; -import { formatNumber, isNull, isUndefined } from '@polkadot/util'; +import { isNull, isUndefined } from '@polkadot/util'; import ParachainInfo from '../ParachainInfo'; import Deregister from './Deregister'; @@ -110,11 +110,6 @@ function Parachain ({ className, basePath, isMine, paraInfoRef, sudoKey }: Props {parachain.pendingSwapId.toString()} )} - {parachain.watermark && ( - - #{formatNumber(parachain.watermark)} - - )} diff --git a/packages/page-staking/src/Actions/Account/index.tsx b/packages/page-staking/src/Actions/Account/index.tsx index 922fdde8dd..f3ad965dc0 100644 --- a/packages/page-staking/src/Actions/Account/index.tsx +++ b/packages/page-staking/src/Actions/Account/index.tsx @@ -3,15 +3,17 @@ // of the Apache-2.0 license. See the LICENSE file for details. import { SubmittableExtrinsic } from '@polkadot/api/types'; -import { DerivedBalancesAll, DerivedStakingAccount, DerivedStakingOverview, DeriveStakerExpoure, DerivedHeartbeats } from '@polkadot/api-derive/types'; +import { DerivedBalancesAll, DerivedStakingAccount, DerivedStakingOverview, DeriveStakerReward, DerivedHeartbeats } from '@polkadot/api-derive/types'; import { AccountId, EraIndex, Exposure, StakingLedger, ValidatorPrefs } from '@polkadot/types/interfaces'; import { Codec, ITuple } from '@polkadot/types/types'; import BN from 'bn.js'; import React, { useContext, useEffect, useState } from 'react'; +import { Trans } from 'react-i18next'; import styled from 'styled-components'; import { AddressInfo, AddressMini, AddressSmall, Badge, Button, Menu, Popup, Spinner, StatusContext, TxButton } from '@polkadot/react-components'; import { useAccounts, useApi, useCall, useToggle } from '@polkadot/react-hooks'; +import { FormatBalance } from '@polkadot/react-query'; import { u8aConcat, u8aToHex } from '@polkadot/util'; import { useTranslation } from '../../translate'; @@ -35,6 +37,7 @@ interface Props { isOwnStash: boolean; isVisible: boolean; next?: string[]; + onUpdatePayout: (stashId: string, count: number) => void; onUpdateType: (stashId: string, type: 'validator' | 'nominator' | 'started' | 'other') => void; recentlyOnline?: DerivedHeartbeats; stakingOverview?: DerivedStakingOverview; @@ -92,7 +95,7 @@ function getStakeState (allAccounts: string[], allStashes: string[] | undefined, }; } -function Account ({ allStashes, className, isOwnStash, isVisible, next, onUpdateType, stakingOverview, stashId }: Props): React.ReactElement { +function Account ({ allStashes, className, isOwnStash, next, onUpdatePayout, onUpdateType, stakingOverview, stashId }: Props): React.ReactElement { const { t } = useTranslation(); const { queueExtrinsic } = useContext(StatusContext); const { api } = useApi(); @@ -101,8 +104,8 @@ function Account ({ allStashes, className, isOwnStash, isVisible, next, onUpdate const validateInfo = useCall(api.query.staking.validators, [stashId]); const balancesAll = useCall(api.derive.balances.all as any, [stashId]); const stakingAccount = useCall(api.derive.staking.account as any, [stashId]); - const stakerExposures = useCall(firstClaim && isVisible && api.derive.staking.stakerExposure as any, [stashId, firstClaim]); - const [[stakingRewards, payoutEras], setStakingRewards] = useState<[DeriveStakerExpoure[], EraIndex[]]>([[], []]); + const stakerRewards = useCall(firstClaim && api.derive.staking.stakerRewards as any, [stashId, firstClaim]); + const [[payoutRewards, payoutEras, payoutTotal], setStakingRewards] = useState<[DeriveStakerReward[], EraIndex[], BN]>([[], [], new BN(0)]); const [{ controllerId, destination, hexSessionIdQueue, hexSessionIdNext, isLoading, isOwnController, isStashNominating, isStashValidating, nominees, sessionIds, validatorPrefs }, setStakeState] = useState({ controllerId: null, destination: 0, hexSessionIdNext: null, hexSessionIdQueue: null, isLoading: true, isOwnController: false, isStashNominating: false, isStashValidating: false, sessionIds: [] }); const [activeNoms, setActiveNoms] = useState([]); const inactiveNoms = useInactives(stashId, nominees); @@ -146,25 +149,27 @@ function Account ({ allStashes, className, isOwnStash, isVisible, next, onUpdate }, [inactiveNoms, nominees]); useEffect((): void => { - if (stakerExposures && firstClaim) { - const stakingRewards = stakerExposures.filter(({ isEmpty }): boolean => !isEmpty); + if (stakerRewards && firstClaim) { + const payoutRewards = stakerRewards.filter(({ isEmpty }): boolean => !isEmpty); setStakingRewards([ - stakingRewards, - stakingRewards.map(({ era }): EraIndex => era) + payoutRewards, + payoutRewards.map(({ era }): EraIndex => era), + payoutRewards.reduce((result, { total }) => result.iadd(total), new BN(0)) ]); + onUpdatePayout(stashId, payoutRewards.length); } - }, [firstClaim, stakingAccount, stakerExposures]); + }, [firstClaim, stakingAccount, stakerRewards, stashId]); const _doPayout = (): void => { queueExtrinsic({ accountId: controllerId, - extrinsic: stakingRewards.length === 1 - ? stakingRewards[0].isValidator - ? api.tx.staking.payoutValidator(stakingRewards[0].era) - : api.tx.staking.payoutNominator(stakingRewards[0].era, stakingRewards[0].nominating) + extrinsic: payoutRewards.length === 1 + ? payoutRewards[0].isValidator + ? api.tx.staking.payoutValidator(payoutRewards[0].era) + : api.tx.staking.payoutNominator(payoutRewards[0].era, payoutRewards[0].nominating) : api.tx.utility.batch( - stakingRewards.map(({ era, isValidator, nominating }): SubmittableExtrinsic<'promise'> => + payoutRewards.map(({ era, isValidator, nominating }): SubmittableExtrinsic<'promise'> => isValidator ? api.tx.staking.payoutValidator(era) : api.tx.staking.payoutNominator(era, nominating) @@ -177,11 +182,16 @@ function Account ({ allStashes, className, isOwnStash, isVisible, next, onUpdate {api.query.staking.activeEra && ( - {!stakerExposures + {!stakerRewards ? : !!payoutEras.length && ( +
{t('Pending payouts for {{count}} eras:', { replace: { count: payoutEras.length } })}
+ + + } info={payoutEras.length} isInline isTooltip @@ -215,7 +225,7 @@ function Account ({ allStashes, className, isOwnStash, isVisible, next, onUpdate )} */} {isInjectOpen && ( @@ -399,15 +409,13 @@ function Account ({ allStashes, className, isOwnStash, isVisible, next, onUpdate disabled={payoutEras.length === 0} onClick={_doPayout} > - {t('Payout era rewards {{period}}', { - replace: { - period: payoutEras.length - ? payoutEras.length === 1 - ? `(${payoutEras[0].toHuman()})` - : `(${payoutEras[0].toHuman()}-${payoutEras[payoutEras.length - 1].toHuman()})` + + {t('Payout reward')} { + payoutEras.length + ? <>() : '' } - })} + )} void; } function getStashes (allAccounts: string[], stashTypes: Record, queryBonded?: Option[], queryLedger?: Option[]): [string, boolean][] | null { @@ -47,7 +48,7 @@ function getStashes (allAccounts: string[], stashTypes: Record, ); } -export default function Actions ({ allStashes, className, isVisible, next, recentlyOnline, stakingOverview }: Props): React.ReactElement { +export default function Actions ({ allStashes, className, isVisible, next, onUpdatePending, recentlyOnline, stakingOverview }: Props): React.ReactElement { const { t } = useTranslation(); const { api } = useApi(); const { allAccounts } = useAccounts(); @@ -59,6 +60,7 @@ export default function Actions ({ allStashes, className, isVisible, next, recen }); const queryBonded = useCall[]>(api.query.staking.bonded.multi as any, [allAccounts]); const queryLedger = useCall[]>(api.query.staking.ledger.multi as any, [allAccounts]); + const [pendingPayouts, setPendingPayouts] = useState>({}); const [isNewStakeOpen, setIsNewStateOpen] = useState(false); const [foundStashes, setFoundStashes] = useState<[string, boolean][] | null>(null); const [stashTypes, setStashTypes] = useState>({}); @@ -67,7 +69,12 @@ export default function Actions ({ allStashes, className, isVisible, next, recen setFoundStashes(getStashes(allAccounts, stashTypes, queryBonded, queryLedger)); }, [allAccounts, queryBonded, queryLedger, stashTypes]); + useEffect((): void => { + onUpdatePending(Object.values(pendingPayouts).filter((count) => !!count).length); + }, [pendingPayouts]); + const _toggleNewStake = (): void => setIsNewStateOpen(!isNewStakeOpen); + const _onUpdatePayout = (stashId: string, count: number): void => setPendingPayouts({ ...pendingPayouts, [stashId]: count }); const _onUpdateType = (stashId: string, type: 'validator' | 'nominator' | 'started' | 'other'): void => setStashTypes({ ...stashTypes, @@ -104,6 +111,7 @@ export default function Actions ({ allStashes, className, isVisible, next, recen isVisible={isVisible} key={stashId} next={next} + onUpdatePayout={_onUpdatePayout} onUpdateType={_onUpdateType} recentlyOnline={recentlyOnline} stakingOverview={stakingOverview} diff --git a/packages/page-staking/src/Query/Validator.tsx b/packages/page-staking/src/Query/Validator.tsx index 4953bc32ca..6179ccb2e4 100644 --- a/packages/page-staking/src/Query/Validator.tsx +++ b/packages/page-staking/src/Query/Validator.tsx @@ -2,7 +2,7 @@ // 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 { DeriveEraRewards, DeriveStakerExposure, DeriveStakerPoints } from '@polkadot/api-derive/types'; import BN from 'bn.js'; import React, { useEffect, useMemo, useState } from 'react'; @@ -92,7 +92,7 @@ function extractRewards (erasRewards: DeriveEraRewards[], allPoints: DeriveStake }; } -function extractStake (exposures: DeriveStakerExpoure[], divisor: BN): ChartInfo { +function extractStake (exposures: DeriveStakerExposure[], divisor: BN): ChartInfo { const labels: string[] = []; const stakeSet: LineDataEntry = []; @@ -122,7 +122,7 @@ export default function Validator ({ className, validatorId }: Props): React.Rea const [{ chart: stakeChart, labels: stakeLabels }, setStakeCharts] = useState({ chart: [], labels: [] }); const erasRewards = useCall(api.derive.staking.erasRewards as any, []); const stakerPoints = useCall(api.derive.staking.stakerPoints as any, [validatorId, true]); - const stakerExposure = useCall(api.derive.staking.stakerExposure as any, [validatorId, true]); + const stakerExposure = useCall(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')) diff --git a/packages/page-staking/src/index.tsx b/packages/page-staking/src/index.tsx index 71b5d5c0fb..2d6c1eec97 100644 --- a/packages/page-staking/src/index.tsx +++ b/packages/page-staking/src/index.tsx @@ -32,6 +32,7 @@ function StakingApp ({ basePath, className }: Props): React.ReactElement const { hasAccounts } = useAccounts(); const { pathname } = useLocation(); const [next, setNext] = useState(); + const [payoutCount, setPayoutCount] = useState(0); const allStashes = useCall(api.derive.staking.controllers, [], { transform: ([stashes]: [AccountId[]]): string[] => stashes.map((accountId): string => accountId.toString()) @@ -58,14 +59,20 @@ function StakingApp ({ basePath, className }: Props): React.ReactElement }, { name: 'actions', - text: t('Account actions') + text: t('Account actions{{count}}', { + replace: { + count: payoutCount + ? ` (${payoutCount})` + : '' + } + }) }, { hasParams: true, name: 'query', text: t('Validator stats') } - ], [t]); + ], [payoutCount, t]); const hiddenTabs = useMemo((): string[] => { const result = next ? [] : ['waiting']; @@ -113,6 +120,7 @@ function StakingApp ({ basePath, className }: Props): React.ReactElement isVisible={pathname === `${basePath}/actions`} recentlyOnline={recentlyOnline} next={next} + onUpdatePending={setPayoutCount} stakingOverview={stakingOverview} />