From ac8c7cc41081cf590d7ba5789615507cb90ccc4e Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Wed, 11 Mar 2020 17:30:01 +0100 Subject: [PATCH] Add global reward alert for payouts (#2370) --- package.json | 6 +- packages/apps-routing/src/staking.ts | 3 +- packages/page-contracts/package.json | 2 +- .../src/Actions/Account/index.tsx | 67 +++++------ packages/page-staking/src/Actions/index.tsx | 56 +++------ packages/page-staking/src/index.tsx | 14 ++- packages/page-staking/src/useCounter.ts | 11 ++ packages/react-api/package.json | 2 +- packages/react-components/src/AddressInfo.tsx | 2 +- packages/react-hooks/src/index.ts | 2 + packages/react-hooks/src/types.ts | 3 +- packages/react-hooks/src/useAccounts.tsx | 2 +- packages/react-hooks/src/useAddresses.tsx | 2 +- packages/react-hooks/src/useCall.tsx | 17 ++- packages/react-hooks/src/useMembers.tsx | 2 +- packages/react-hooks/src/useOwnEraRewards.tsx | 68 +++++++++++ packages/react-hooks/src/useOwnStashes.tsx | 61 ++++++++++ packages/react-query/src/FormatBalance.tsx | 2 +- yarn.lock | 112 +++++++++--------- 19 files changed, 274 insertions(+), 160 deletions(-) create mode 100644 packages/page-staking/src/useCounter.ts create mode 100644 packages/react-hooks/src/useOwnEraRewards.tsx create mode 100644 packages/react-hooks/src/useOwnStashes.tsx diff --git a/package.json b/package.json index fa7d863b80..ecf974b9f0 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,10 @@ "packages/*" ], "resolutions": { - "@polkadot/api": "^1.6.0-beta.26", - "@polkadot/api-contract": "^1.6.0-beta.26", + "@polkadot/api": "^1.6.0-beta.28", + "@polkadot/api-contract": "^1.6.0-beta.28", "@polkadot/keyring": "^2.6.2", - "@polkadot/types": "^1.6.0-beta.26", + "@polkadot/types": "^1.6.0-beta.28", "@polkadot/util": "^2.6.2", "@polkadot/util-crypto": "^2.6.2", "babel-core": "^7.0.0-bridge.0", diff --git a/packages/apps-routing/src/staking.ts b/packages/apps-routing/src/staking.ts index a84cf1e9fa..86ede2741d 100644 --- a/packages/apps-routing/src/staking.ts +++ b/packages/apps-routing/src/staking.ts @@ -4,11 +4,12 @@ import { Routes } from './types'; -import Staking from '@polkadot/app-staking'; +import Staking, { useCounter } from '@polkadot/app-staking'; export default ([ { Component: Staking, + useCounter, display: { needsApi: [ [ diff --git a/packages/page-contracts/package.json b/packages/page-contracts/package.json index 5af516ca61..b405f5f5d0 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.26" + "@polkadot/api-contract": "^1.6.0-beta.28" } } diff --git a/packages/page-staking/src/Actions/Account/index.tsx b/packages/page-staking/src/Actions/Account/index.tsx index f3ad965dc0..5659f1f405 100644 --- a/packages/page-staking/src/Actions/Account/index.tsx +++ b/packages/page-staking/src/Actions/Account/index.tsx @@ -11,6 +11,7 @@ import BN from 'bn.js'; import React, { useContext, useEffect, useState } from 'react'; import { Trans } from 'react-i18next'; import styled from 'styled-components'; +import { ApiPromise } from '@polkadot/api'; 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'; @@ -37,9 +38,9 @@ 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; + rewards?: DeriveStakerReward[]; stakingOverview?: DerivedStakingOverview; stashId: string; } @@ -95,16 +96,28 @@ function getStakeState (allAccounts: string[], allStashes: string[] | undefined, }; } -function Account ({ allStashes, className, isOwnStash, next, onUpdatePayout, onUpdateType, stakingOverview, stashId }: Props): React.ReactElement { +function createPayout (api: ApiPromise, payoutRewards: DeriveStakerReward[]): SubmittableExtrinsic<'promise'> { + return 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( + payoutRewards.map(({ era, isValidator, nominating }): SubmittableExtrinsic<'promise'> => + isValidator + ? api.tx.staking.payoutValidator(era) + : api.tx.staking.payoutNominator(era, nominating) + ) + ); +} + +function Account ({ allStashes, className, isOwnStash, next, onUpdateType, rewards, stakingOverview, stashId }: Props): React.ReactElement { const { t } = useTranslation(); const { queueExtrinsic } = useContext(StatusContext); const { api } = useApi(); const { allAccounts } = useAccounts(); - const [firstClaim, setFirstClaim] = useState(); 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 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([]); @@ -120,12 +133,6 @@ function Account ({ allStashes, className, isOwnStash, next, onUpdatePayout, onU const [isUnbondOpen, toggleUnbond] = useToggle(); const [isValidateOpen, toggleValidate] = useToggle(); - useEffect((): void => { - if (stakingAccount?.stakingLedger?.lastReward) { - setFirstClaim(stakingAccount.stakingLedger.lastReward.unwrapOr(new BN(-1)).addn(1)); - } - }, [stakingAccount]); - useEffect((): void => { if (stakingAccount && validateInfo) { const state = getStakeState(allAccounts, allStashes, stakingAccount, stashId, validateInfo); @@ -143,46 +150,30 @@ function Account ({ allStashes, className, isOwnStash, next, onUpdatePayout, onU }, [allStashes, stakingAccount, stashId, validateInfo]); useEffect((): void => { - if (nominees) { - setActiveNoms(nominees.filter((id): boolean => !inactiveNoms.includes(id))); - } + nominees && setActiveNoms( + nominees.filter((id): boolean => !inactiveNoms.includes(id)) + ); }, [inactiveNoms, nominees]); useEffect((): void => { - if (stakerRewards && firstClaim) { - const payoutRewards = stakerRewards.filter(({ isEmpty }): boolean => !isEmpty); + rewards && setStakingRewards([ + rewards, + rewards.map(({ era }): EraIndex => era), + rewards.reduce((result, { total }) => result.iadd(total), new BN(0)) + ]); + }, [rewards]); - setStakingRewards([ - payoutRewards, - payoutRewards.map(({ era }): EraIndex => era), - payoutRewards.reduce((result, { total }) => result.iadd(total), new BN(0)) - ]); - onUpdatePayout(stashId, payoutRewards.length); - } - }, [firstClaim, stakingAccount, stakerRewards, stashId]); - - const _doPayout = (): void => { + const _doPayout = (): void => queueExtrinsic({ accountId: controllerId, - 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( - payoutRewards.map(({ era, isValidator, nominating }): SubmittableExtrinsic<'promise'> => - isValidator - ? api.tx.staking.payoutValidator(era) - : api.tx.staking.payoutNominator(era, nominating) - ) - ) + extrinsic: createPayout(api, payoutRewards) }); - }; return ( {api.query.staking.activeEra && ( - {!stakerRewards + {!rewards ? : !!payoutEras.length && ( ; allStashes?: string[]; className?: string; isVisible: boolean; recentlyOnline?: DerivedHeartbeats; next?: string[]; stakingOverview?: DerivedStakingOverview; - onUpdatePending: (count: number) => void; } -function getStashes (allAccounts: string[], stashTypes: Record, queryBonded?: Option[], queryLedger?: Option[]): [string, boolean][] | null { - const result: [string, boolean][] = []; - - if (!queryBonded || !queryLedger) { - return null; - } - - queryBonded.forEach((value, index): void => { - value.isSome && result.push([allAccounts[index], true]); - }); - - queryLedger.forEach((ledger): void => { - if (ledger.isSome) { - const stashId = ledger.unwrap().stash.toString(); - - !result.some(([accountId]): boolean => accountId === stashId) && result.push([stashId, false]); - } - }); - - return result.sort((a, b): number => - (stashTypes[a[0]] || 99) - (stashTypes[b[0]] || 99) - ); -} - -export default function Actions ({ allStashes, className, isVisible, next, onUpdatePending, recentlyOnline, stakingOverview }: Props): React.ReactElement { +export default function Actions ({ allRewards, allStashes, className, isVisible, next, recentlyOnline, stakingOverview }: Props): React.ReactElement { const { t } = useTranslation(); const { api } = useApi(); - const { allAccounts } = useAccounts(); - const activeEra = useCall(api.query.staking.activeEra, [], { + const activeEra = useCall(api.query.staking?.activeEra, [], { transform: (activeEra: Option): EraIndex | undefined => activeEra.isSome ? activeEra.unwrap().index : undefined }); - 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 ownStashes = useOwnStashes(); const [isNewStakeOpen, setIsNewStateOpen] = useState(false); const [foundStashes, setFoundStashes] = useState<[string, boolean][] | null>(null); const [stashTypes, setStashTypes] = useState>({}); useEffect((): void => { - setFoundStashes(getStashes(allAccounts, stashTypes, queryBonded, queryLedger)); - }, [allAccounts, queryBonded, queryLedger, stashTypes]); - - useEffect((): void => { - onUpdatePending(Object.values(pendingPayouts).filter((count) => !!count).length); - }, [pendingPayouts]); + ownStashes && setFoundStashes( + ownStashes.sort((a, b): number => + (stashTypes[a[0]] || 99) - (stashTypes[b[0]] || 99) + ) + ); + }, [ownStashes, stashTypes]); 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, @@ -111,9 +83,9 @@ export default function Actions ({ allStashes, className, isVisible, next, onUpd isVisible={isVisible} key={stashId} next={next} - onUpdatePayout={_onUpdatePayout} onUpdateType={_onUpdateType} recentlyOnline={recentlyOnline} + rewards={allRewards && allRewards[stashId]} stakingOverview={stakingOverview} stashId={stashId} /> diff --git a/packages/page-staking/src/index.tsx b/packages/page-staking/src/index.tsx index 2d6c1eec97..261b7446ad 100644 --- a/packages/page-staking/src/index.tsx +++ b/packages/page-staking/src/index.tsx @@ -12,7 +12,7 @@ import { useLocation } from 'react-router-dom'; import styled from 'styled-components'; import { HelpOverlay } from '@polkadot/react-components'; import Tabs from '@polkadot/react-components/Tabs'; -import { useCall, useAccounts, useApi } from '@polkadot/react-hooks'; +import { useAccounts, useApi, useCall, useOwnEraRewards } from '@polkadot/react-hooks'; import basicMd from './md/basic.md'; import Actions from './Actions'; @@ -22,6 +22,8 @@ import Query from './Query'; import Targets from './Targets'; import { useTranslation } from './translate'; +export { default as useCounter } from './useCounter'; + function reduceNominators (nominators: string[], additional: string[]): string[] { return nominators.concat(...additional.filter((nominator): boolean => !nominators.includes(nominator))); } @@ -31,8 +33,8 @@ function StakingApp ({ basePath, className }: Props): React.ReactElement const { api } = useApi(); const { hasAccounts } = useAccounts(); const { pathname } = useLocation(); + const { allRewards, rewardCount } = useOwnEraRewards(); 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()) @@ -61,8 +63,8 @@ function StakingApp ({ basePath, className }: Props): React.ReactElement name: 'actions', text: t('Account actions{{count}}', { replace: { - count: payoutCount - ? ` (${payoutCount})` + count: rewardCount + ? ` (${rewardCount})` : '' } }) @@ -72,7 +74,7 @@ function StakingApp ({ basePath, className }: Props): React.ReactElement name: 'query', text: t('Validator stats') } - ], [payoutCount, t]); + ], [rewardCount, t]); const hiddenTabs = useMemo((): string[] => { const result = next ? [] : ['waiting']; @@ -116,11 +118,11 @@ function StakingApp ({ basePath, className }: Props): React.ReactElement (
{amount.isMax() - ? t('all available') + ? t('everything') : formatBalance(amount, { forceUnit: '-' }) }
{reasons.toString()}
diff --git a/packages/react-hooks/src/index.ts b/packages/react-hooks/src/index.ts index 96b95924fd..01c2656886 100644 --- a/packages/react-hooks/src/index.ts +++ b/packages/react-hooks/src/index.ts @@ -14,6 +14,8 @@ export { default as useFavorites } from './useFavorites'; export { default as useIsMountedRef } from './useIsMountedRef'; export { default as useMembers } from './useMembers'; export { default as useModal } from './useModal'; +export { default as useOwnEraRewards } from './useOwnEraRewards'; +export { default as useOwnStashes, useOwnStashIds } from './useOwnStashes'; export { default as usePassword } from './usePassword'; export { default as useSudo } from './useSudo'; export { default as useToggle } from './useToggle'; diff --git a/packages/react-hooks/src/types.ts b/packages/react-hooks/src/types.ts index 6fc4292abd..98d5219c92 100644 --- a/packages/react-hooks/src/types.ts +++ b/packages/react-hooks/src/types.ts @@ -9,13 +9,14 @@ import { SubmittableExtrinsic } from '@polkadot/api/promise/types'; export type CallParam = any; -export type CallParams = [] | [CallParam] | [CallParam, CallParam] | [CallParam, CallParam, CallParam]; +export type CallParams = [] | [CallParam] | [CallParam, CallParam] | [CallParam, CallParam, CallParam] | any[]; export interface CallOptions { defaultValue?: T; isSingle?: boolean; paramMap?: (params: any) => CallParams; transform?: (value: any) => T; + withParams?: boolean; } export type TxDef = [string, any[] | ConstructTxFn]; diff --git a/packages/react-hooks/src/useAccounts.tsx b/packages/react-hooks/src/useAccounts.tsx index d5907bb586..0a0bb651f1 100644 --- a/packages/react-hooks/src/useAccounts.tsx +++ b/packages/react-hooks/src/useAccounts.tsx @@ -27,7 +27,7 @@ export default function useAccounts (): UseAccounts { }); return (): void => { - subscription.unsubscribe(); + setTimeout(() => subscription.unsubscribe(), 0); }; }, []); diff --git a/packages/react-hooks/src/useAddresses.tsx b/packages/react-hooks/src/useAddresses.tsx index cb4c78fde7..b2a5809f3e 100644 --- a/packages/react-hooks/src/useAddresses.tsx +++ b/packages/react-hooks/src/useAddresses.tsx @@ -27,7 +27,7 @@ export default function useAccounts (): UseAccounts { }); return (): void => { - subscription.unsubscribe(); + setTimeout(() => subscription.unsubscribe(), 0); }; }, []); diff --git a/packages/react-hooks/src/useCall.tsx b/packages/react-hooks/src/useCall.tsx index 3f605b67ab..e0806ecb35 100644 --- a/packages/react-hooks/src/useCall.tsx +++ b/packages/react-hooks/src/useCall.tsx @@ -59,13 +59,15 @@ function unsubscribe (tracker: TrackerRef): void { tracker.current.isActive = false; if (tracker.current.subscriber) { - tracker.current.subscriber.then((unsubFn): void => unsubFn()); + tracker.current.subscriber.then((unsubFn): void => { + setTimeout(unsubFn, 0); + }); tracker.current.subscriber = null; } } -// subscribe, tyring to play nice with the browser threads -function subscribe (mounted: MountedRef, tracker: TrackerRef, fn: TrackFn | undefined, params: CallParams, setValue: (value: T) => void, { isSingle, transform = transformIdentity }: CallOptions): void { +// subscribe, trying to play nice with the browser threads +function subscribe (mounted: MountedRef, tracker: TrackerRef, fn: TrackFn | undefined, params: CallParams, setValue: (value: T) => void, { isSingle, transform = transformIdentity, withParams }: CallOptions): void { const validParams = params.filter((p): boolean => !isUndefined(p)); unsubscribe(tracker); @@ -84,7 +86,10 @@ function subscribe (mounted: MountedRef, tracker: TrackerRef, fn: TrackFn | // since .subscriber may not be set on immeditae callback) if (mounted.current && tracker.current.isActive && (!isSingle || !tracker.current.count)) { tracker.current.count++; - setValue(transform(value)); + + ((transformed: any): void => { + setTimeout(() => setValue(transformed), 0); + })(withParams ? [params, transform(value)] : transform(value)); } }); } else { @@ -103,10 +108,10 @@ export default function useCall (fn: TrackFn | undefined | null | false, par const tracker = useRef({ isActive: false, count: 0, serialized: null, subscriber: null }); const [value, setValue] = useState(options.defaultValue); - // initial effect, we need an unsubscription + // initial effect, we need an un-subscription useEffect((): () => void => { return (): void => { - unsubscribe(tracker); + setTimeout(() => unsubscribe(tracker), 0); }; }, []); diff --git a/packages/react-hooks/src/useMembers.tsx b/packages/react-hooks/src/useMembers.tsx index ceb80aee52..9de417699d 100644 --- a/packages/react-hooks/src/useMembers.tsx +++ b/packages/react-hooks/src/useMembers.tsx @@ -29,7 +29,7 @@ export default function useMembers (collective: 'council' | 'technicalCommittee' }) : useCall(api.query.technicalCommittee.members, [], { transform: (accounts: AccountId[]): Result => - getResult(allAccounts, accounts.map(accountId => accountId.toString())) + getResult(allAccounts, accounts.map((accountId) => accountId.toString())) }) ) || { isMember: false, members: [] }; diff --git a/packages/react-hooks/src/useOwnEraRewards.tsx b/packages/react-hooks/src/useOwnEraRewards.tsx new file mode 100644 index 0000000000..7d8352617d --- /dev/null +++ b/packages/react-hooks/src/useOwnEraRewards.tsx @@ -0,0 +1,68 @@ +// Copyright 2017-2020 @polkadot/react-hooks 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 { DerivedStakingQuery, DeriveStakerReward } from '@polkadot/api-derive/types'; +import { EraIndex } from '@polkadot/types/interfaces'; + +import { useEffect, useState } from 'react'; + +import BN from 'bn.js'; +import useApi from './useApi'; +import useCall from './useCall'; +import { useOwnStashIds } from './useOwnStashes'; + +interface OwnRewards { + allRewards?: Record; + rewardCount: number; +} + +function useNextPayouts (): [string, EraIndex][] | undefined { + const { api } = useApi(); + const stashIds = useOwnStashIds(); + const allInfo = useCall(stashIds && api.derive.staking?.queryMulti, stashIds); + const [rewards, setRewards] = useState<[string, EraIndex][] | undefined>(); + + useEffect((): void => { + stashIds && allInfo && setRewards( + allInfo + .map(({ stakingLedger }, index) => [stashIds[index], stakingLedger?.lastReward?.unwrapOr(new BN(-1)).addn(1)]) + .filter((value): value is [string, EraIndex] => !!value[1]) + ); + }, [allInfo, stashIds]); + + return rewards; +} + +function getRewards ([theseParams, theseRewards]: [[string, EraIndex][], DeriveStakerReward[][]], nextParams: [string, EraIndex][]): OwnRewards { + const allRewards = theseRewards.reduce((result: Record, rewards, index): Record => { + const [stashId] = theseParams[index]; + const nextPayout = nextParams.find(([thisId]) => thisId === stashId); + + if (nextPayout) { + result[stashId] = rewards.filter(({ era, isEmpty }) => !isEmpty && era.gte(nextPayout[1])); + } + + return result; + }, {}); + + return { + allRewards, + rewardCount: Object.values(allRewards).filter((rewards) => !!rewards.length).length + }; +} + +export default function useOwnEraRewards (): OwnRewards { + const { api } = useApi(); + const nextParams = useNextPayouts(); + const available = useCall<[[string, EraIndex][], DeriveStakerReward[][]]>(nextParams && api.derive.staking?.stakerRewardsMulti, nextParams, { withParams: true }); + const [state, setState] = useState({ rewardCount: 0 }); + + useEffect((): void => { + if (available && nextParams) { + setState(getRewards(available, nextParams)); + } + }, [available, nextParams]); + + return state; +} diff --git a/packages/react-hooks/src/useOwnStashes.tsx b/packages/react-hooks/src/useOwnStashes.tsx new file mode 100644 index 0000000000..b1223842a5 --- /dev/null +++ b/packages/react-hooks/src/useOwnStashes.tsx @@ -0,0 +1,61 @@ +// Copyright 2017-2020 @polkadot/react-hooks 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 { AccountId, StakingLedger } from '@polkadot/types/interfaces'; + +import { useEffect, useState } from 'react'; +import { Option } from '@polkadot/types'; + +import useAccounts from './useAccounts'; +import useApi from './useApi'; +import useCall from './useCall'; + +type IsInKeyring = boolean; + +function getStashes (allAccounts: string[], ownBonded: Option[], ownLedger: Option[]): [string, IsInKeyring][] { + const result: [string, IsInKeyring][] = []; + + ownBonded.forEach((value, index): void => { + value.isSome && result.push([allAccounts[index], true]); + }); + + ownLedger.forEach((ledger): void => { + if (ledger.isSome) { + const stashId = ledger.unwrap().stash.toString(); + + !result.some(([accountId]): boolean => accountId === stashId) && result.push([stashId, false]); + } + }); + + return result; +} + +export default function useOwnStashes (): [string, IsInKeyring][] | undefined { + const { allAccounts } = useAccounts(); + const { api } = useApi(); + const ownBonded = useCall[]>(api.query.staking?.bonded.multi as any, [allAccounts]); + const ownLedger = useCall[]>(api.query.staking?.ledger.multi as any, [allAccounts]); + const [state, setState] = useState<[string, IsInKeyring][] | undefined>(); + + useEffect((): void => { + allAccounts && ownBonded && ownLedger && setState( + getStashes(allAccounts, ownBonded, ownLedger) + ); + }, [allAccounts, ownBonded, ownLedger]); + + return state; +} + +export function useOwnStashIds (): string[] | undefined { + const ownStashes = useOwnStashes(); + const [stashIds, setStashIds] = useState(); + + useEffect((): void => { + ownStashes && setStashIds( + ownStashes.map(([stashId]) => stashId) + ); + }, [ownStashes]); + + return stashIds; +} diff --git a/packages/react-query/src/FormatBalance.tsx b/packages/react-query/src/FormatBalance.tsx index 75e235d3ae..f029ab3d59 100644 --- a/packages/react-query/src/FormatBalance.tsx +++ b/packages/react-query/src/FormatBalance.tsx @@ -56,7 +56,7 @@ function FormatBalance ({ children, className, label, value, withSi }: Props): R {label || ''}{ value ? value === 'all' - ? t('all available') + ? t('everything') : format(value, currency, withSi) : '-' }{children} diff --git a/yarn.lock b/yarn.lock index e6d4840e28..e1e235c182 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2765,56 +2765,56 @@ __metadata: languageName: node linkType: hard -"@polkadot/api-contract@npm:^1.6.0-beta.26": - version: 1.6.0-beta.26 - resolution: "@polkadot/api-contract@npm:1.6.0-beta.26" +"@polkadot/api-contract@npm:^1.6.0-beta.28": + version: 1.6.0-beta.28 + resolution: "@polkadot/api-contract@npm:1.6.0-beta.28" dependencies: "@babel/runtime": ^7.8.4 - "@polkadot/api": 1.6.0-beta.26 - "@polkadot/rpc-core": 1.6.0-beta.26 - "@polkadot/types": 1.6.0-beta.26 + "@polkadot/api": 1.6.0-beta.28 + "@polkadot/rpc-core": 1.6.0-beta.28 + "@polkadot/types": 1.6.0-beta.28 "@polkadot/util": ^2.6.2 bn.js: ^5.1.1 rxjs: ^6.5.4 - checksum: 2/04d88c7d980fad55da69b5714a949818d06e7a8af7020df8fb52eed7b93279cf3cddc68fada89b1b308db63c6dcc436093566e6be1d399b0f5f91b7276f7a4a8 + checksum: 2/f199f996c521be7c88a5754565842b6f30029bcca41a5a19c91f667fe458543d052c854d19ee9b4c991991e2d4a39df4c79d2c10d45592fabc875e1b043cd29b languageName: node linkType: hard -"@polkadot/api-derive@npm:1.6.0-beta.26": - version: 1.6.0-beta.26 - resolution: "@polkadot/api-derive@npm:1.6.0-beta.26" +"@polkadot/api-derive@npm:1.6.0-beta.28": + version: 1.6.0-beta.28 + resolution: "@polkadot/api-derive@npm:1.6.0-beta.28" dependencies: "@babel/runtime": ^7.8.4 - "@polkadot/api": 1.6.0-beta.26 - "@polkadot/rpc-core": 1.6.0-beta.26 - "@polkadot/rpc-provider": 1.6.0-beta.26 - "@polkadot/types": 1.6.0-beta.26 + "@polkadot/api": 1.6.0-beta.28 + "@polkadot/rpc-core": 1.6.0-beta.28 + "@polkadot/rpc-provider": 1.6.0-beta.28 + "@polkadot/types": 1.6.0-beta.28 "@polkadot/util": ^2.6.2 "@polkadot/util-crypto": ^2.6.2 bn.js: ^5.1.1 memoizee: ^0.4.14 rxjs: ^6.5.4 - checksum: 2/03dcebaf7cbc88dfbc6f7e90d9a24d6cdbbf8f789e8ff3c4fc2c01c67e259da9ea28ace7f5d6f0e3d266557c0c5e4e619bc0fe83d55ad4da8946d4433b6a3933 + checksum: 2/0bf002a4e2a3e4e1cae760e50980a54974b026271421bfb2436ac3505c9802319b72818592ff79893abb65e09c4e835df89f8b9d8486f93a80dc9737dd527c87 languageName: node linkType: hard -"@polkadot/api@npm:^1.6.0-beta.26": - version: 1.6.0-beta.26 - resolution: "@polkadot/api@npm:1.6.0-beta.26" +"@polkadot/api@npm:^1.6.0-beta.28": + version: 1.6.0-beta.28 + resolution: "@polkadot/api@npm:1.6.0-beta.28" dependencies: "@babel/runtime": ^7.8.4 - "@polkadot/api-derive": 1.6.0-beta.26 + "@polkadot/api-derive": 1.6.0-beta.28 "@polkadot/keyring": ^2.6.2 - "@polkadot/metadata": 1.6.0-beta.26 - "@polkadot/rpc-core": 1.6.0-beta.26 - "@polkadot/rpc-provider": 1.6.0-beta.26 - "@polkadot/types": 1.6.0-beta.26 + "@polkadot/metadata": 1.6.0-beta.28 + "@polkadot/rpc-core": 1.6.0-beta.28 + "@polkadot/rpc-provider": 1.6.0-beta.28 + "@polkadot/types": 1.6.0-beta.28 "@polkadot/util": ^2.6.2 "@polkadot/util-crypto": ^2.6.2 bn.js: ^5.1.1 eventemitter3: ^4.0.0 rxjs: ^6.5.4 - checksum: 2/3906cf905c8ad268bc5d70766c0b5ae14422337367fc05e2e7de3269b472e218191b3b63af5f4bc001af921dfd9750b78322253f1807096a7f8eeaaf44c25912 + checksum: 2/b539969aa9a502da96f52042d8a1a5041d10c9bb18f3a3275ecba2d85daade5bf6b63c70d3e0ae8723af6cf3e2e80f54a4eb983572c32b63cb660abc53f86a59 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.26 + "@polkadot/api-contract": ^1.6.0-beta.28 languageName: unknown linkType: soft @@ -3176,14 +3176,14 @@ __metadata: languageName: node linkType: hard -"@polkadot/jsonrpc@npm:1.6.0-beta.26": - version: 1.6.0-beta.26 - resolution: "@polkadot/jsonrpc@npm:1.6.0-beta.26" +"@polkadot/jsonrpc@npm:1.6.0-beta.28": + version: 1.6.0-beta.28 + resolution: "@polkadot/jsonrpc@npm:1.6.0-beta.28" dependencies: "@babel/runtime": ^7.8.4 - "@polkadot/types": 1.6.0-beta.26 + "@polkadot/types": 1.6.0-beta.28 "@polkadot/util": ^2.6.2 - checksum: 2/b82d18c3d444557993e97cf9a0751f50b76c4176337b21bf76ffdfd3cb48ce9e17e9c404930c3ca5b4feb3e475edcc2f249c8851d3b6ca7381108039b28abe40 + checksum: 2/fef65b236a5deb741bd022b8c45422133785957b0e1f50cd8596bdc6026430df7c3e32847e20e09a07daf6494bca67f4c79ed5b0213cb9aaf1ad91fba19313a6 languageName: node linkType: hard @@ -3198,16 +3198,16 @@ __metadata: languageName: node linkType: hard -"@polkadot/metadata@npm:1.6.0-beta.26": - version: 1.6.0-beta.26 - resolution: "@polkadot/metadata@npm:1.6.0-beta.26" +"@polkadot/metadata@npm:1.6.0-beta.28": + version: 1.6.0-beta.28 + resolution: "@polkadot/metadata@npm:1.6.0-beta.28" dependencies: "@babel/runtime": ^7.8.4 - "@polkadot/types": 1.6.0-beta.26 + "@polkadot/types": 1.6.0-beta.28 "@polkadot/util": ^2.6.2 "@polkadot/util-crypto": ^2.6.2 bn.js: ^5.1.1 - checksum: 2/390b0d6a3f0b1a22504ada19b1b2993c98146acf79fa1714b524e8e7b91d1b4235d3e111924a48dc7bd5d4023e0bd611e5fee7b74785323a843faf3dc664d636 + checksum: 2/1cceff15745c5a8b81fff1731f7cff69db624dc42fb593e969b68e2313531141700d64dfb05ce8469fe281e9dd94f17e5268cd4b3b2866a01da971134ca7d779 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.26 + "@polkadot/api": ^1.6.0-beta.28 "@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.26": - version: 1.6.0-beta.26 - resolution: "@polkadot/rpc-core@npm:1.6.0-beta.26" +"@polkadot/rpc-core@npm:1.6.0-beta.28": + version: 1.6.0-beta.28 + resolution: "@polkadot/rpc-core@npm:1.6.0-beta.28" dependencies: "@babel/runtime": ^7.8.4 - "@polkadot/jsonrpc": 1.6.0-beta.26 - "@polkadot/metadata": 1.6.0-beta.26 - "@polkadot/rpc-provider": 1.6.0-beta.26 - "@polkadot/types": 1.6.0-beta.26 + "@polkadot/jsonrpc": 1.6.0-beta.28 + "@polkadot/metadata": 1.6.0-beta.28 + "@polkadot/rpc-provider": 1.6.0-beta.28 + "@polkadot/types": 1.6.0-beta.28 "@polkadot/util": ^2.6.2 memoizee: ^0.4.14 rxjs: ^6.5.4 - checksum: 2/be942ae0416f89ea224d8e74434b3482e42af282996cb5d6ad5c25307185a2b76b2662adcf9d165201df4b3db816074ea74a640d7def2dd8e89e2ff3de369d24 + checksum: 2/70f0c58a0b17dd64ac721d2687fc1a3c958d751123a1486ade7a820c1f202d8809c412e5f6f4f5fa3d51ec8cae4350f361086f7a1e0a4097947315ae9c4af17d languageName: node linkType: hard -"@polkadot/rpc-provider@npm:1.6.0-beta.26": - version: 1.6.0-beta.26 - resolution: "@polkadot/rpc-provider@npm:1.6.0-beta.26" +"@polkadot/rpc-provider@npm:1.6.0-beta.28": + version: 1.6.0-beta.28 + resolution: "@polkadot/rpc-provider@npm:1.6.0-beta.28" dependencies: "@babel/runtime": ^7.8.4 - "@polkadot/jsonrpc": 1.6.0-beta.26 - "@polkadot/metadata": 1.6.0-beta.26 - "@polkadot/types": 1.6.0-beta.26 + "@polkadot/jsonrpc": 1.6.0-beta.28 + "@polkadot/metadata": 1.6.0-beta.28 + "@polkadot/types": 1.6.0-beta.28 "@polkadot/util": ^2.6.2 "@polkadot/util-crypto": ^2.6.2 bn.js: ^5.1.1 eventemitter3: ^4.0.0 isomorphic-fetch: ^2.2.1 websocket: ^1.0.31 - checksum: 2/0bbde7518b9b5f12e2f5247e1eb4ad55e6a61f6920ae7838d15f6bb423105425ede34fc60d5e8f043f3ee32614132040094925a2dd9cc16129935e75eac893a6 + checksum: 2/ed3c826c87a38d6e147398d1ab997ea8acd72bdde260c668f0370ef49b56f54bf7d37575ba1d3e9d12149730e5b824f957e1e060959ff3d8d14765cebc10fdd2 languageName: node linkType: hard @@ -3371,19 +3371,19 @@ __metadata: languageName: node linkType: hard -"@polkadot/types@npm:^1.6.0-beta.26": - version: 1.6.0-beta.26 - resolution: "@polkadot/types@npm:1.6.0-beta.26" +"@polkadot/types@npm:^1.6.0-beta.28": + version: 1.6.0-beta.28 + resolution: "@polkadot/types@npm:1.6.0-beta.28" dependencies: "@babel/runtime": ^7.8.4 - "@polkadot/metadata": 1.6.0-beta.26 + "@polkadot/metadata": 1.6.0-beta.28 "@polkadot/util": ^2.6.2 "@polkadot/util-crypto": ^2.6.2 "@types/bn.js": ^4.11.6 bn.js: ^5.1.1 memoizee: ^0.4.14 rxjs: ^6.5.4 - checksum: 2/1318129dabcfd973e2d7e0f3062cefff26504c11c0c2aa3e02858362c21ebb15d01c3f02177ba2ec7ccb9e7c304485c0860929e7b7811de54ed0327ce026a7be + checksum: 2/58faa8d0ce629037a61d16029aa80cca9775dc181f7e5480daef2a5665eb8a53ed811afd66fd4a47acf70add4337e8bcbbaba92a69935fde5e0abbf85558c07e languageName: node linkType: hard