diff --git a/packages/page-staking/src/Payouts/Stash.tsx b/packages/page-staking/src/Payouts/Stash.tsx index 0eec93f75e..01b6714938 100644 --- a/packages/page-staking/src/Payouts/Stash.tsx +++ b/packages/page-staking/src/Payouts/Stash.tsx @@ -10,7 +10,7 @@ import React, { useEffect, useState } from 'react'; import { ApiPromise } from '@polkadot/api'; import { AddressSmall, TxButton } from '@polkadot/react-components'; -import { useApi, useCall } from '@polkadot/react-hooks'; +import { useApi, useCall, useTxBatch } from '@polkadot/react-hooks'; import { BlockToTime, FormatBalance } from '@polkadot/react-query'; import { useTranslation } from '../translate'; @@ -29,24 +29,22 @@ interface EraInfo { oldestEra?: BN; } -function createPrevPayoutType (api: ApiPromise, { era, isValidator, nominating }: DeriveStakerReward): SubmittableExtrinsic<'promise'> { - return isValidator - ? api.tx.staking.payoutValidator(era) - : api.tx.staking.payoutNominator(era, nominating.map(({ validatorId, validatorIndex }): [string, number] => - [validatorId, validatorIndex] - )); -} - -function createPrevPayout (api: ApiPromise, payoutRewards: DeriveStakerReward[]): SubmittableExtrinsic<'promise'> { - return payoutRewards.length === 1 - ? createPrevPayoutType(api, payoutRewards[0]) - : api.tx.utility.batch(payoutRewards.map((reward) => createPrevPayoutType(api, reward))); +// TODO This is pre Substrate 2.0, remove +function createPrevPayouts (api: ApiPromise, payoutRewards: DeriveStakerReward[]): SubmittableExtrinsic<'promise'>[] { + return payoutRewards.map(({ era, isValidator, nominating }) => + isValidator + ? api.tx.staking.payoutValidator(era) + : api.tx.staking.payoutNominator(era, nominating.map(({ validatorId, validatorIndex }): [string, number] => + [validatorId, validatorIndex] + )) + ); } function Stash ({ className = '', isDisabled, payout: { available, rewards, stashId }, stakerPayoutsAfter }: Props): React.ReactElement | null { const { t } = useTranslation(); const { api } = useApi(); - const [extrinsic, setExtrinsic] = useState | null>(null); + const [payoutTxs, setPayoutTxs] = useState[]>([]); + const batchTx = useTxBatch(payoutTxs); const [{ eraStr, oldestEra }, setEraInfo] = useState({ eraStr: '' }); const eraBlocks = useEraBlocks(oldestEra); const stakingAccount = useCall(api.derive.staking.account, [stashId]); @@ -59,15 +57,9 @@ function Stash ({ className = '', isDisabled, payout: { available, rewards, stas }, [rewards]); useEffect((): void => { - if (rewards) { - const available = rewards.filter(({ era }) => era.lt(stakerPayoutsAfter)); - - setExtrinsic( - api.tx.utility && available.length - ? createPrevPayout(api, available) - : null - ); - } + rewards && setPayoutTxs( + createPrevPayouts(api, rewards.filter(({ era }) => era.lt(stakerPayoutsAfter))) + ); }, [api, rewards, stakerPayoutsAfter]); if (available.isZero()) { @@ -91,12 +83,12 @@ function Stash ({ className = '', isDisabled, payout: { available, rewards, stas className='button' colSpan={3} > - {extrinsic && stakingAccount && ( + {batchTx && stakingAccount && ( ('Payout')} /> )} diff --git a/packages/page-staking/src/Payouts/index.tsx b/packages/page-staking/src/Payouts/index.tsx index b50c127e79..2c0fd6b445 100644 --- a/packages/page-staking/src/Payouts/index.tsx +++ b/packages/page-staking/src/Payouts/index.tsx @@ -159,7 +159,6 @@ function Payouts ({ className = '', isInElection, ownValidators }: Props): React const eraLength = useCall(api.derive.session.eraLength); const historyDepth = useCall(api.query.staking.historyDepth); const stakerPayoutsAfter = useStakerPayouts(); - const isDisabled = isInElection || !isFunction(api.tx.utility?.batch); const eraSelection = useMemo( () => getOptions(api, eraLength, historyDepth, t), @@ -205,6 +204,7 @@ function Payouts ({ className = '', isInElection, ownValidators }: Props): React ), [stashTotal]); const hasPayouts = isFunction(api.tx.staking.payoutStakers); + const isDisabled = isInElection || !isFunction(api.tx.utility?.batch); return (
@@ -222,7 +222,7 @@ function Payouts ({ className = '', isInElection, ownValidators }: Props): React /> diff --git a/packages/page-treasury/src/Tips/index.tsx b/packages/page-treasury/src/Tips/index.tsx index 8355b56708..245a962641 100644 --- a/packages/page-treasury/src/Tips/index.tsx +++ b/packages/page-treasury/src/Tips/index.tsx @@ -7,7 +7,7 @@ import BN from 'bn.js'; import React, { useCallback, useMemo, useState } from 'react'; import { Button, TxButton } from '@polkadot/react-components'; -import { useAccounts, useApi } from '@polkadot/react-hooks'; +import { useAccounts, useApi, useTxBatch } from '@polkadot/react-hooks'; import { useTranslation } from '../translate'; import TipCreate from './TipCreate'; @@ -22,14 +22,17 @@ interface Props { interface QuickTipsState { quickTips: Record; - quickTx: SubmittableExtrinsic<'promise'> | null; + quickTxs: SubmittableExtrinsic<'promise'>[]; } +const DEFAULT_TIPS = { quickTips: {}, quickTxs: [] }; + function TipsEntry ({ className, hashes, isMember, members }: Props): React.ReactElement { const { t } = useTranslation(); const { allAccounts } = useAccounts(); const { api } = useApi(); - const [{ quickTx }, setQuickTips] = useState({ quickTips: {}, quickTx: null }); + const [{ quickTxs }, setQuickTips] = useState(DEFAULT_TIPS); + const batchTxs = useTxBatch(quickTxs); const defaultId = useMemo( () => members.find((memberId) => allAccounts.includes(memberId)) || null, @@ -40,18 +43,12 @@ function TipsEntry ({ className, hashes, isMember, members }: Props): React.Reac (hash: string, isSelected: boolean, value: BN) => setQuickTips(({ quickTips }): QuickTipsState => { quickTips[hash] = isSelected ? value : null; - const available = Object - .entries(quickTips) - .map(([hash, value]) => value && (api.tx.tips || api.tx.treasury).tip(hash, value)) - .filter((value): value is SubmittableExtrinsic<'promise'> => !!value); - return { quickTips, - quickTx: available.length - ? available.length === 1 - ? available[0] - : api.tx.utility.batch(available) - : null + quickTxs: Object + .entries(quickTips) + .map(([hash, value]) => value && (api.tx.tips || api.tx.treasury).tip(hash, value)) + .filter((value): value is SubmittableExtrinsic<'promise'> => !!value) }; }), [api] @@ -63,9 +60,9 @@ function TipsEntry ({ className, hashes, isMember, members }: Props): React.Reac ('Median tip selected')} />