Force reward retrieval to single-shot (#2013)
* Force reward retrieval to single-shot * Remove inner setTimeout
This commit is contained in:
parent
6380cd021f
commit
0402d0e10f
@ -9,7 +9,7 @@ import React from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { registry } from '@polkadot/react-api';
|
||||
import { Button } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { createType } from '@polkadot/types';
|
||||
|
||||
import Candidates from './Candidates';
|
||||
@ -33,9 +33,9 @@ const NULL_INFO: DerivedElectionsInfo = {
|
||||
|
||||
export default function Overview ({ className }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const bestNumber = useStream<BlockNumber>(api.derive.chain.bestNumber, []);
|
||||
const _electionsInfo = useStream<DerivedElectionsInfo>(api.derive.elections.info, []);
|
||||
const allVotes = useStream<Record<string, AccountId[]>>(api.query.electionsPhragmen?.votesOf, [], {
|
||||
const bestNumber = useCall<BlockNumber>(api.derive.chain.bestNumber, []);
|
||||
const _electionsInfo = useCall<DerivedElectionsInfo>(api.derive.elections.info, []);
|
||||
const allVotes = useCall<Record<string, AccountId[]>>(api.query.electionsPhragmen?.votesOf, [], {
|
||||
transform: ([voters, casted]: [AccountId[], AccountId[][]]): Record<string, AccountId[]> =>
|
||||
voters.reduce((result: Record<string, AccountId[]>, voter, index): Record<string, AccountId[]> => {
|
||||
casted[index].forEach((candidate): void => {
|
||||
|
||||
@ -10,7 +10,7 @@ import { Route, Switch } from 'react-router';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
import { Tabs } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
import Overview from './Overview';
|
||||
import Motions from './Motions';
|
||||
@ -23,7 +23,7 @@ interface Props extends AppProps, BareProps, I18nProps {}
|
||||
function App ({ basePath, className, t }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const { pathname } = useLocation();
|
||||
const motions = useStream<Hash[]>(api.query.council.proposals, []);
|
||||
const motions = useCall<Hash[]>(api.query.council.proposals, []);
|
||||
|
||||
return (
|
||||
<main className={className}>
|
||||
|
||||
@ -5,11 +5,11 @@
|
||||
import { Hash } from '@polkadot/types/interfaces';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
export default function useCounter (): number {
|
||||
const { api, isApiReady } = useApi();
|
||||
const motions = useStream<Hash[]>(isApiReady ? api.query.council?.proposals : undefined, []);
|
||||
const motions = useCall<Hash[]>(isApiReady ? api.query.council?.proposals : undefined, []);
|
||||
const [counter, setCounter] = useState(0);
|
||||
|
||||
useEffect((): void => {
|
||||
|
||||
@ -7,7 +7,7 @@ import { AccountId, Balance, BlockNumber, Hash, Proposal, ReferendumIndex } from
|
||||
import { ITuple } from '@polkadot/types/types';
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { Bytes, Option } from '@polkadot/types';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
@ -22,7 +22,7 @@ interface Props extends I18nProps {
|
||||
|
||||
function DispatchEntry ({ blockNumber, hash, referendumIndex, t }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const preimage = useStream<Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>
|
||||
const preimage = useCall<Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>
|
||||
>(api.query.democracy.preimages, [hash]);
|
||||
const [proposal, setProposal] = useState<Proposal | undefined>();
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ import { ITuple } from '@polkadot/types/types';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { Option, StorageKey, Vec } from '@polkadot/types';
|
||||
import { u8aToHex } from '@polkadot/util';
|
||||
|
||||
@ -18,7 +18,7 @@ import DispatchBlock from './DispatchBlock';
|
||||
function DispatchQueue ({ className, t }: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useApi();
|
||||
const [keyPrefix] = useState(u8aToHex(api.query.democracy.dispatchQueue.creator.iterKey));
|
||||
const queued = useStream<[StorageKey, Option<Vec<Option<ITuple<[Hash, ReferendumIndex]>>>>
|
||||
const queued = useCall<[StorageKey, Option<Vec<Option<ITuple<[Hash, ReferendumIndex]>>>>
|
||||
][]>(api.query.democracy.dispatchQueue.entries as any, []);
|
||||
|
||||
if (!queued?.length) {
|
||||
|
||||
@ -8,7 +8,7 @@ import { I18nProps as Props } from '@polkadot/react-components/types';
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { AddressSmall, Table } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
import { Bytes, Option } from '@polkadot/types';
|
||||
|
||||
@ -17,10 +17,10 @@ import ProposalCell from './ProposalCell';
|
||||
|
||||
function Externals ({ className, t }: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useApi();
|
||||
const external = useStream<Option<ITuple<[Hash, VoteThreshold]>>>(api.query.democracy.nextExternal, []);
|
||||
const external = useCall<Option<ITuple<[Hash, VoteThreshold]>>>(api.query.democracy.nextExternal, []);
|
||||
const [hash, setHash] = useState<Hash | null>(null);
|
||||
const [expanded, setExpanded] = useState<{ at: BlockNumber; balance: Balance; proposer: AccountId; proposal: Proposal } | null>(null);
|
||||
const preimage = useStream<Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>>(api.query.democracy.preimages, [hash]);
|
||||
const preimage = useCall<Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>>(api.query.democracy.preimages, [hash]);
|
||||
|
||||
useEffect((): void => {
|
||||
setHash(
|
||||
|
||||
@ -7,14 +7,14 @@ import { I18nProps as Props } from '@polkadot/react-components/types';
|
||||
|
||||
import React from 'react';
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
import ProposalDisplay from './Proposal';
|
||||
import translate from '../translate';
|
||||
|
||||
function Proposals ({ className, t }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const proposals = useStream<DeriveProposal[]>(api.derive.democracy.proposals, []);
|
||||
const proposals = useCall<DeriveProposal[]>(api.derive.democracy.proposals, []);
|
||||
|
||||
return (
|
||||
<div className={`proposalSection ${className}`}>
|
||||
|
||||
@ -7,14 +7,14 @@ import { I18nProps as Props } from '@polkadot/react-components/types';
|
||||
|
||||
import React from 'react';
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
import Referendum from './Referendum';
|
||||
import translate from '../translate';
|
||||
|
||||
function Referendums ({ className, t }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const referendums = useStream<DerivedReferendum[]>(api.derive.democracy.referendums, []);
|
||||
const referendums = useCall<DerivedReferendum[]>(api.derive.democracy.referendums, []);
|
||||
|
||||
return (
|
||||
<div className={`proposalSection ${className}`}>
|
||||
|
||||
@ -8,7 +8,7 @@ import { I18nProps } from '@polkadot/react-components/types';
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { SummaryBox, CardSummary } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { withCalls } from '@polkadot/react-api';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
@ -23,7 +23,7 @@ interface Props extends I18nProps {
|
||||
|
||||
function Summary (props: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const activeProposals = useStream<any[]>(api.derive.democracy.proposals, []);
|
||||
const activeProposals = useCall<any[]>(api.derive.democracy.proposals, []);
|
||||
|
||||
const {
|
||||
chain_bestNumber,
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
export default function useCounter (): number {
|
||||
const { api, isApiReady } = useApi();
|
||||
const proposals = useStream<any[]>(isApiReady ? api.derive.democracy.proposals : undefined, []);
|
||||
const referenda = useStream<any[]>(isApiReady ? api.derive.democracy.referendums : undefined, []);
|
||||
const proposals = useCall<any[]>(isApiReady ? api.derive.democracy.proposals : undefined, []);
|
||||
const referenda = useCall<any[]>(isApiReady ? api.derive.democracy.referendums : undefined, []);
|
||||
const [counter, setCounter] = useState(0);
|
||||
|
||||
useEffect((): void => {
|
||||
|
||||
@ -10,7 +10,7 @@ import { AccountId, StakingLedger } from '@polkadot/types/interfaces';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Button, CardGrid } from '@polkadot/react-components';
|
||||
import { useStream, useApi, useAccounts } from '@polkadot/react-hooks';
|
||||
import { useCall, useApi, useAccounts } from '@polkadot/react-hooks';
|
||||
import { AccountName } from '@polkadot/react-query';
|
||||
import { Option } from '@polkadot/types';
|
||||
import createOption from '@polkadot/ui-keyring/options/item';
|
||||
@ -50,8 +50,8 @@ function getStashes (allAccounts: string[], queryBonded?: Option<AccountId>[], q
|
||||
function Actions ({ allStashes, className, isVisible, recentlyOnline, t }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const { allAccounts } = useAccounts();
|
||||
const queryBonded = useStream<Option<AccountId>[]>(api.query.staking.bonded.multi as any, [allAccounts]);
|
||||
const queryLedger = useStream<Option<StakingLedger>[]>(api.query.staking.ledger.multi as any, [allAccounts]);
|
||||
const queryBonded = useCall<Option<AccountId>[]>(api.query.staking.bonded.multi as any, [allAccounts]);
|
||||
const queryLedger = useCall<Option<StakingLedger>[]>(api.query.staking.ledger.multi as any, [allAccounts]);
|
||||
const [isNewStakeOpen, setIsNewStateOpen] = useState(false);
|
||||
const [foundStashes, setFoundStashes] = useState<[string, boolean][] | null>(null);
|
||||
const [stashOptions, setStashOptions] = useState<KeyringSectionOption[]>([]);
|
||||
|
||||
@ -11,7 +11,7 @@ import BN from 'bn.js';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { AddressMini, AddressSmall, Badge, Icon } from '@polkadot/react-components';
|
||||
import { useStream, useApi } from '@polkadot/react-hooks';
|
||||
import { useCall, useApi } from '@polkadot/react-hooks';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
@ -51,7 +51,7 @@ interface StakingState {
|
||||
function Address ({ address, authorsMap, className, filter, hasQueries, isElected, isFavorite, lastAuthors, myAccounts, points, recentlyOnline, t, toggleFavorite, withNominations = true }: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useApi();
|
||||
// FIXME Any horrors, caused by derive type mismatches
|
||||
const stakingInfo = useStream<DerivedStaking>(api.derive.staking.info as any, [address]);
|
||||
const stakingInfo = useCall<DerivedStaking>(api.derive.staking.info as any, [address]);
|
||||
const [hasActivity, setHasActivity] = useState(true);
|
||||
const [{ commission, hasNominators, isNominatorMe, nominators, stashId, stakeOwn, stakeOther, validatorPayment }, setStakingState] = useState<StakingState>({
|
||||
hasNominators: false,
|
||||
|
||||
@ -8,7 +8,7 @@ import { I18nProps } from '@polkadot/react-components/types';
|
||||
import BN from 'bn.js';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { SummaryBox, CardSummary } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { formatBalance } from '@polkadot/util';
|
||||
|
||||
import translate from '../translate';
|
||||
@ -25,7 +25,7 @@ interface StakeInfo {
|
||||
|
||||
function Summary ({ lastReward, t, totalStaked }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const totalInsurance = useStream<Balance>(api.query.balances.totalIssuance, []);
|
||||
const totalInsurance = useCall<Balance>(api.query.balances.totalIssuance, []);
|
||||
const [{ percentage, staked }, setStakeInfo] = useState<StakeInfo>({ percentage: '-', staked: null });
|
||||
const [total, setTotal] = useState<string | null>(null);
|
||||
|
||||
|
||||
@ -9,11 +9,11 @@ import { SessionRewards } from '../types';
|
||||
import { ValidatorInfo } from './types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { registry } from '@polkadot/react-api';
|
||||
import { InputBalance, Table } from '@polkadot/react-components';
|
||||
import { useAccounts, useApi, useDebounce, useFavorites, useStream } from '@polkadot/react-hooks';
|
||||
import { useAccounts, useApi, useDebounce, useFavorites, useCall } from '@polkadot/react-hooks';
|
||||
import { createType } from '@polkadot/types';
|
||||
|
||||
import { STORE_FAVS_BASE } from '../constants';
|
||||
@ -150,14 +150,23 @@ function Targets ({ className, sessionRewards, t }: Props): React.ReactElement<P
|
||||
const { api } = useApi();
|
||||
const { allAccounts } = useAccounts();
|
||||
const [_amount, setAmount] = useState<BN | undefined>(new BN(1000));
|
||||
const electedInfo = useStream<DerivedStakingElected>(api.derive.staking.electedInfo, []);
|
||||
const electedInfo = useCall<DerivedStakingElected>(api.derive.staking.electedInfo, [], { isSingle: true });
|
||||
const [favorites, toggleFavorite] = useFavorites(STORE_FAVS_BASE);
|
||||
const [lastReward, setLastReward] = useState(new BN(0));
|
||||
const lastBase = useRef<number>(0);
|
||||
const [baseInfo, setBaseInfo] = useState<BaseInfo[]>([]);
|
||||
const [baseInfo, setBaseInfo] = useState<BaseInfo[] | undefined>();
|
||||
const [{ validators, totalStaked }, setWorkable] = useState<AllInfo>({ totalStaked: new BN(0), validators: [] });
|
||||
const amount = useDebounce(_amount);
|
||||
|
||||
useEffect((): void => {
|
||||
if (electedInfo) {
|
||||
setBaseInfo(
|
||||
electedInfo.info.map(({ accountId, stakers, validatorPrefs }) => ({
|
||||
accountId, stakers, validatorPrefs
|
||||
}))
|
||||
);
|
||||
}
|
||||
}, [electedInfo]);
|
||||
|
||||
useEffect((): void => {
|
||||
if (sessionRewards && sessionRewards.length) {
|
||||
const lastRewardSession = sessionRewards.filter(({ reward }): boolean => reward.gtn(0));
|
||||
@ -171,19 +180,9 @@ function Targets ({ className, sessionRewards, t }: Props): React.ReactElement<P
|
||||
}, [sessionRewards]);
|
||||
|
||||
useEffect((): void => {
|
||||
if (electedInfo && lastBase.current !== electedInfo.info.length) {
|
||||
lastBase.current = electedInfo.info.length;
|
||||
|
||||
setBaseInfo(
|
||||
electedInfo.info.map(({ accountId, stakers, validatorPrefs }) => ({
|
||||
accountId, stakers, validatorPrefs
|
||||
}))
|
||||
);
|
||||
if (baseInfo) {
|
||||
setWorkable(extractInfo(allAccounts, amount, baseInfo, favorites, lastReward));
|
||||
}
|
||||
}, [electedInfo]);
|
||||
|
||||
useEffect((): void => {
|
||||
setWorkable(extractInfo(allAccounts, amount, baseInfo, favorites, lastReward));
|
||||
}, [allAccounts, amount, baseInfo, favorites, lastReward]);
|
||||
|
||||
return (
|
||||
|
||||
@ -13,7 +13,7 @@ import styled from 'styled-components';
|
||||
import { Option } from '@polkadot/types';
|
||||
import { HelpOverlay } from '@polkadot/react-components';
|
||||
import Tabs from '@polkadot/react-components/Tabs';
|
||||
import { useStream, useAccounts, useApi } from '@polkadot/react-hooks';
|
||||
import { useCall, useAccounts, useApi } from '@polkadot/react-hooks';
|
||||
|
||||
import basicMd from './md/basic.md';
|
||||
import Actions from './Actions';
|
||||
@ -45,12 +45,12 @@ function App ({ basePath, className, t }: Props): React.ReactElement<Props> {
|
||||
const { hasAccounts } = useAccounts();
|
||||
const { pathname } = useLocation();
|
||||
const [next, setNext] = useState<string[]>([]);
|
||||
const [allStashes, allControllers] = (useStream<[string[], string[]]>(api.derive.staking.controllers, [], {
|
||||
const [allStashes, allControllers] = (useCall<[string[], string[]]>(api.derive.staking.controllers, [], {
|
||||
defaultValue: EMPTY_ALL,
|
||||
transform: transformStakingControllers
|
||||
}) as [string[], string[]]);
|
||||
const recentlyOnline = useStream<DerivedHeartbeats>(api.derive.imOnline.receivedHeartbeats, []);
|
||||
const stakingOverview = useStream<DerivedStakingOverview>(api.derive.staking.overview, []);
|
||||
const recentlyOnline = useCall<DerivedHeartbeats>(api.derive.imOnline.receivedHeartbeats, []);
|
||||
const stakingOverview = useCall<DerivedStakingOverview>(api.derive.staking.overview, []);
|
||||
const sessionRewards = useSessionRewards(MAX_SESSIONS);
|
||||
const hasQueries = hasAccounts && !!(api.query.imOnline?.authoredBlocks);
|
||||
const validators = stakingOverview?.validators;
|
||||
|
||||
@ -6,15 +6,15 @@ import { SessionIndex } from '@polkadot/types/interfaces';
|
||||
import { SessionRewards } from './types';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { u32 } from '@polkadot/types';
|
||||
|
||||
export default function useBlockCounts (accountId: string, sessionRewards: SessionRewards[]): u32[] {
|
||||
const { api } = useApi();
|
||||
const [counts, setCounts] = useState<u32[]>([]);
|
||||
const [historic, setHistoric] = useState<u32[]>([]);
|
||||
const sessionIndex = useStream<SessionIndex>(api.query.session.currentIndex, []);
|
||||
const current = useStream<u32>(api.query.imOnline?.authoredBlocks, [sessionIndex, accountId]);
|
||||
const sessionIndex = useCall<SessionIndex>(api.query.session.currentIndex, []);
|
||||
const current = useCall<u32>(api.query.imOnline?.authoredBlocks, [sessionIndex, accountId]);
|
||||
|
||||
useEffect((): void => {
|
||||
if (api.query.imOnline?.authoredBlocks && sessionRewards && sessionRewards.length) {
|
||||
|
||||
@ -9,7 +9,7 @@ import { ComponentProps } from './types';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Route, Switch } from 'react-router';
|
||||
import { Icon, Tabs } from '@polkadot/react-components';
|
||||
import { useStream, useAccounts, useApi } from '@polkadot/react-hooks';
|
||||
import { useCall, useAccounts, useApi } from '@polkadot/react-hooks';
|
||||
|
||||
import SetKey from './SetKey';
|
||||
import Sudo from './Sudo';
|
||||
@ -21,7 +21,7 @@ interface Props extends AppProps, I18nProps {
|
||||
|
||||
function App ({ basePath, t }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const sudoKey = useStream<string>(api.query.sudo.key, [], { transform: (k): string => k.toString() });
|
||||
const sudoKey = useCall<string>(api.query.sudo.key, [], { transform: (k): string => k.toString() });
|
||||
const { allAccounts } = useAccounts();
|
||||
const [isMine, setIsMine] = useState(false);
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ import { ComponentProps } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import { SummaryBox, CardSummary } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { u32 } from '@polkadot/types';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
@ -18,7 +18,7 @@ interface Props extends ComponentProps, I18nProps {}
|
||||
|
||||
function Summary ({ className, members, proposals, t }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const proposalCount = useStream<u32>(api.query.technicalCommittee.proposalCount, []);
|
||||
const proposalCount = useCall<u32>(api.query.technicalCommittee.proposalCount, []);
|
||||
|
||||
return (
|
||||
<SummaryBox className={className}>
|
||||
|
||||
@ -7,7 +7,7 @@ import { I18nProps } from '@polkadot/react-components/types';
|
||||
|
||||
import React from 'react';
|
||||
import { AddressMini } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import ProposalCell from '@polkadot/app-democracy/Overview/ProposalCell';
|
||||
import { Option } from '@polkadot/types';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
@ -21,8 +21,8 @@ interface Props extends I18nProps {
|
||||
|
||||
function Proposal ({ className, hash, t }: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useApi();
|
||||
const optProposal = useStream<Option<ProposalType>>(api.query.technicalCommittee.proposalOf, [hash]);
|
||||
const votes = useStream<Option<Votes>>(api.query.technicalCommittee.voting, [hash]);
|
||||
const optProposal = useCall<Option<ProposalType>>(api.query.technicalCommittee.proposalOf, [hash]);
|
||||
const votes = useCall<Option<Votes>>(api.query.technicalCommittee.voting, [hash]);
|
||||
|
||||
if (!optProposal?.isSome || !votes?.isSome) {
|
||||
return null;
|
||||
|
||||
@ -7,7 +7,7 @@ import { AppProps, BareProps, I18nProps } from '@polkadot/react-components/types
|
||||
|
||||
import React from 'react';
|
||||
import { Route, Switch } from 'react-router';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { Tabs } from '@polkadot/react-components';
|
||||
|
||||
import Overview from './Overview';
|
||||
@ -20,8 +20,8 @@ interface Props extends AppProps, BareProps, I18nProps {}
|
||||
|
||||
function App ({ basePath, className, t }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const members = useStream<AccountId[]>(api.query.technicalCommittee.members, []);
|
||||
const proposals = useStream<Hash[]>(api.query.technicalCommittee.proposals, []);
|
||||
const members = useCall<AccountId[]>(api.query.technicalCommittee.members, []);
|
||||
const proposals = useCall<Hash[]>(api.query.technicalCommittee.proposals, []);
|
||||
|
||||
return (
|
||||
<main className={className}>
|
||||
|
||||
@ -5,11 +5,11 @@
|
||||
import { Hash } from '@polkadot/types/interfaces';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
export default function useCounter (): number {
|
||||
const { api, isApiReady } = useApi();
|
||||
const proposals = useStream<Hash[]>(isApiReady ? api.query.technicalCommittee && api.query.technicalCommittee.proposals : undefined, []);
|
||||
const proposals = useCall<Hash[]>(isApiReady ? api.query.technicalCommittee && api.query.technicalCommittee.proposals : undefined, []);
|
||||
const [counter, setCounter] = useState(0);
|
||||
|
||||
useEffect((): void => {
|
||||
|
||||
@ -9,7 +9,7 @@ import BN from 'bn.js';
|
||||
import React, { useEffect } from 'react';
|
||||
import { Option } from '@polkadot/types';
|
||||
import { AddressMini, AddressSmall } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { FormatBalance } from '@polkadot/react-query';
|
||||
import { formatNumber } from '@polkadot/util';
|
||||
|
||||
@ -24,7 +24,7 @@ interface Props extends I18nProps {
|
||||
|
||||
function ProposalDisplay ({ className, onPopulate, proposalId, t }: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useApi();
|
||||
const proposal = useStream<TreasuryProposal | null>(api.query.treasury.proposals, [proposalId], {
|
||||
const proposal = useCall<TreasuryProposal | null>(api.query.treasury.proposals, [proposalId], {
|
||||
transform: (value: Option<TreasuryProposal>): TreasuryProposal | null =>
|
||||
value.unwrapOr(null)
|
||||
});
|
||||
|
||||
@ -7,7 +7,7 @@ import { I18nProps } from '@polkadot/react-components/types';
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { SummaryBox, CardSummary } from '@polkadot/react-components';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { formatBalance, formatNumber, stringToU8a } from '@polkadot/util';
|
||||
|
||||
import translate from '../translate';
|
||||
@ -21,8 +21,8 @@ interface Props extends I18nProps {
|
||||
|
||||
function Summary ({ approvalCount, proposalCount, t }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const pot = useStream<BN>(api.query.treasury.pot, []);
|
||||
const treasuryBalance = useStream<BN>(api.query.balances.freeBalance, [TREASURY_ACCOUNT]);
|
||||
const pot = useCall<BN>(api.query.treasury.pot, []);
|
||||
const treasuryBalance = useCall<BN>(api.query.balances.freeBalance, [TREASURY_ACCOUNT]);
|
||||
|
||||
const value = treasuryBalance?.gtn(0)
|
||||
? treasuryBalance.toString()
|
||||
|
||||
@ -6,7 +6,7 @@ import { AppProps, BareProps, I18nProps } from '@polkadot/react-components/types
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
import Summary from './Summary';
|
||||
import Proposals from './Proposals';
|
||||
@ -16,8 +16,8 @@ interface Props extends AppProps, BareProps, I18nProps {}
|
||||
|
||||
export default function Overview ({ className }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const approvalIds = useStream<BN[]>(api.query.treasury.approvals, []);
|
||||
const proposalCount = useStream<BN>(api.query.treasury.proposalCount, []);
|
||||
const approvalIds = useCall<BN[]>(api.query.treasury.approvals, []);
|
||||
const proposalCount = useCall<BN>(api.query.treasury.proposalCount, []);
|
||||
const [proposalIds, setProposalIds] = useState<BN[]>([]);
|
||||
|
||||
useEffect((): void => {
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="initial-scale=1">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
|
||||
@ -13,7 +13,7 @@ import styled from 'styled-components';
|
||||
import { Responsive } from 'semantic-ui-react';
|
||||
import routing from '@polkadot/apps-routing';
|
||||
import { Button, ChainImg, Icon, Menu, media } from '@polkadot/react-components';
|
||||
import { useStream, useApi } from '@polkadot/react-hooks';
|
||||
import { useCall, useApi } from '@polkadot/react-hooks';
|
||||
import { classes } from '@polkadot/react-components/util';
|
||||
import { BestNumber, Chain } from '@polkadot/react-query';
|
||||
|
||||
@ -33,7 +33,7 @@ interface Props extends I18nProps {
|
||||
|
||||
function SideBar ({ className, collapse, handleResize, isCollapsed, toggleMenu, menuOpen }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const runtimeVersion = useStream<RuntimeVersion>(api.rpc.state.subscribeRuntimeVersion, []);
|
||||
const runtimeVersion = useCall<RuntimeVersion>(api.rpc.state.subscribeRuntimeVersion, []);
|
||||
const [modals, setModals] = useState<Record<string, boolean>>(
|
||||
routing.routes.reduce((result: Record<string, boolean>, route): Record<string, boolean> => {
|
||||
if (route && route.Modal) {
|
||||
|
||||
@ -2,12 +2,11 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export { default as usePromise } from './track/usePromise';
|
||||
export { default as useStream } from './track/useStream';
|
||||
export { default as useAccounts } from './useAccounts';
|
||||
export { default as useAddresses } from './useAddresses';
|
||||
export { default as useApi } from './useApi';
|
||||
export { default as useCacheKey } from './useCacheKey';
|
||||
export { default as useCall } from './useCall';
|
||||
export { default as useForm } from './useForm';
|
||||
export { default as useDebounce } from './useDebounce';
|
||||
export { default as useFavorites } from './useFavorites';
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
// Copyright 2017-2019 @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.
|
||||
|
||||
export type Param = any;
|
||||
|
||||
export type Params = [] | [Param] | [Param, Param] | [Param, Param, Param];
|
||||
|
||||
export interface Options <T> {
|
||||
defaultValue?: T;
|
||||
isDebug?: boolean;
|
||||
paramMap?: (params: any) => Params;
|
||||
transform?: (value: any) => T;
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
// Copyright 2017-2019 @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 { Options, Param, Params } from './types';
|
||||
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { extractParams, transformIdentity } from './util';
|
||||
|
||||
interface TrackFn <T> {
|
||||
(a: Param, b: Param, c: Param): Promise<T>;
|
||||
(a: Param, b: Param): Promise<T>;
|
||||
(a: Param): Promise<T>;
|
||||
(): Promise<T>;
|
||||
}
|
||||
|
||||
// tracks a promise, typically an api.* call (query, query.at, rpc) that
|
||||
// - returns a promise with the value
|
||||
// FIXME The typings here need some serious TLC
|
||||
export default function usePromise <T> (fn: TrackFn<T> | undefined, params: Params, { defaultValue, paramMap = transformIdentity, transform = transformIdentity }: Options<T> = {}): T | undefined {
|
||||
const [value, setValue] = useState<T | undefined>(defaultValue);
|
||||
const tracker = useRef<{ serialized: string | null }>({ serialized: null });
|
||||
|
||||
const _subscribe = (params: Params): void => {
|
||||
setImmediate((): void => {
|
||||
if (fn) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
||||
// @ts-ignore We tried to get the typings right, close but no cigar...
|
||||
fn(...params).then((value: any): void => setValue(transform(value)));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// on changes, re-get
|
||||
useEffect((): void => {
|
||||
if (fn) {
|
||||
const [serialized, mappedParams] = extractParams(fn, params, paramMap);
|
||||
|
||||
if (mappedParams && serialized !== tracker.current.serialized) {
|
||||
tracker.current.serialized = serialized;
|
||||
|
||||
_subscribe(mappedParams);
|
||||
}
|
||||
}
|
||||
}, [fn, params]);
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
// Copyright 2017-2019 @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 { Codec } from '@polkadot/types/types';
|
||||
import { Options, Param, Params } from './types';
|
||||
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { isUndefined } from '@polkadot/util';
|
||||
|
||||
import { extractParams, transformIdentity } from './util';
|
||||
|
||||
interface TrackFnCallback {
|
||||
(value: Codec): void;
|
||||
}
|
||||
|
||||
type TrackFnResult = Promise<() => void>;
|
||||
|
||||
interface TrackFn {
|
||||
(a: Param, b: Param, c: Param, cb: TrackFnCallback): TrackFnResult;
|
||||
(a: Param, b: Param, cb: TrackFnCallback): TrackFnResult;
|
||||
(a: Param, cb: TrackFnCallback): TrackFnResult;
|
||||
(cb: TrackFnCallback): TrackFnResult;
|
||||
meta?: {
|
||||
type: {
|
||||
isDoubleMap: boolean;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// tracks a stream, typically an api.* call (derive, rpc, query) that
|
||||
// - returns a promise with an unsubscribe function
|
||||
// - has a callback to set the value
|
||||
// FIXME The typings here need some serious TLC
|
||||
export default function useStream <T> (fn: TrackFn | undefined, params: Params, { defaultValue, isDebug, paramMap = transformIdentity, transform = transformIdentity }: Options<T> = {}): T | undefined {
|
||||
const [value, setValue] = useState<T | undefined>(defaultValue);
|
||||
const tracker = useRef<{ serialized: string | null; subscriber: TrackFnResult | null }>({ serialized: null, subscriber: null });
|
||||
|
||||
const _debug = (fn: () => any[]): void => {
|
||||
isDebug && console.log(...fn());
|
||||
};
|
||||
const _unsubscribe = (): void => {
|
||||
if (tracker.current.subscriber) {
|
||||
_debug(() => ['unsubscribe', fn?.name]);
|
||||
|
||||
tracker.current.subscriber.then((unsubFn): void => unsubFn());
|
||||
tracker.current.subscriber = null;
|
||||
}
|
||||
};
|
||||
const _subscribe = (params: Params): void => {
|
||||
_debug(() => ['subscribe', fn?.name]);
|
||||
|
||||
const validParams = params.filter((p): boolean => !isUndefined(p));
|
||||
|
||||
_unsubscribe();
|
||||
|
||||
setImmediate((): void => {
|
||||
tracker.current.subscriber = fn && (!fn.meta || !fn.meta.type?.isDoubleMap || validParams.length === 2)
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
||||
// @ts-ignore We tried to get the typings right, close but no cigar...
|
||||
? fn(...params, (value: any): void => {
|
||||
_debug(() => ['setValue', JSON.stringify({ value })]);
|
||||
setValue(transform(value));
|
||||
})
|
||||
: null;
|
||||
});
|
||||
};
|
||||
|
||||
// initial effect, we need an unsubscription
|
||||
useEffect((): () => void => {
|
||||
return _unsubscribe;
|
||||
}, []);
|
||||
|
||||
// on changes, re-subscribe
|
||||
useEffect((): void => {
|
||||
if (fn) {
|
||||
const [serialized, mappedParams] = extractParams(fn, params, paramMap);
|
||||
|
||||
if (mappedParams && serialized !== tracker.current.serialized) {
|
||||
_debug(() => ['_createSubscription', fn?.name, serialized]);
|
||||
|
||||
tracker.current.serialized = serialized;
|
||||
|
||||
_subscribe(mappedParams);
|
||||
}
|
||||
}
|
||||
}, [fn, params]);
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -7,6 +7,17 @@ import { AccountId, Balance, BlockNumber, Call, Hash, SessionIndex } from '@polk
|
||||
import { IExtrinsic } from '@polkadot/types/types';
|
||||
import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
|
||||
|
||||
export type CallParam = any;
|
||||
|
||||
export type CallParams = [] | [CallParam] | [CallParam, CallParam] | [CallParam, CallParam, CallParam];
|
||||
|
||||
export interface CallOptions <T> {
|
||||
defaultValue?: T;
|
||||
isSingle?: boolean;
|
||||
paramMap?: (params: any) => CallParams;
|
||||
transform?: (value: any) => T;
|
||||
}
|
||||
|
||||
export type TxDef = [string, any[] | ConstructTxFn];
|
||||
|
||||
export type TxDefs = SubmittableExtrinsic | IExtrinsic | Call | TxDef | null;
|
||||
|
||||
104
packages/react-hooks/src/useCall.tsx
Normal file
104
packages/react-hooks/src/useCall.tsx
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2017-2019 @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 { Codec } from '@polkadot/types/types';
|
||||
import { CallOptions, CallParam, CallParams } from './types';
|
||||
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { isUndefined } from '@polkadot/util';
|
||||
|
||||
import { extractParams, transformIdentity } from './util';
|
||||
|
||||
interface TrackFnCallback {
|
||||
(value: Codec): void;
|
||||
}
|
||||
|
||||
type TrackFnResult = Promise<() => void>;
|
||||
|
||||
interface TrackFn {
|
||||
(a: CallParam, b: CallParam, c: CallParam, cb: TrackFnCallback): TrackFnResult;
|
||||
(a: CallParam, b: CallParam, cb: TrackFnCallback): TrackFnResult;
|
||||
(a: CallParam, cb: TrackFnCallback): TrackFnResult;
|
||||
(cb: TrackFnCallback): TrackFnResult;
|
||||
meta?: {
|
||||
type: {
|
||||
isDoubleMap: boolean;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
interface Tracker {
|
||||
isActive: boolean;
|
||||
count: number;
|
||||
serialized: string | null;
|
||||
subscriber: TrackFnResult | null;
|
||||
}
|
||||
|
||||
interface TrackerRef {
|
||||
current: Tracker;
|
||||
}
|
||||
|
||||
// unsubscribe and remove from the tracker
|
||||
function unsubscribe (tracker: TrackerRef): void {
|
||||
if (tracker.current.subscriber) {
|
||||
tracker.current.isActive = false;
|
||||
tracker.current.subscriber.then((unsubFn): void => unsubFn());
|
||||
tracker.current.subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
// subscribe, tyring to play nice with the browser threads
|
||||
function subscribe <T> (tracker: TrackerRef, fn: TrackFn | undefined, params: CallParams, setValue: (value: T) => void, { isSingle, transform = transformIdentity }: CallOptions<T>): void {
|
||||
const validParams = params.filter((p): boolean => !isUndefined(p));
|
||||
|
||||
unsubscribe(tracker);
|
||||
|
||||
setTimeout((): void => {
|
||||
tracker.current.isActive = true;
|
||||
tracker.current.count = 0;
|
||||
tracker.current.subscriber = fn && (!fn.meta || !fn.meta.type?.isDoubleMap || validParams.length === 2)
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
||||
// @ts-ignore We tried to get the typings right, close but no cigar...
|
||||
? fn(...params, (value: any): void => {
|
||||
// when we don't have an active sub, or single-shot, ignore (we use the isActive flag here
|
||||
// since .subscriber may not be set on immeditae callback)
|
||||
if (tracker.current.isActive && (!isSingle || !tracker.current.count)) {
|
||||
tracker.current.count++;
|
||||
setValue(transform(value));
|
||||
}
|
||||
})
|
||||
: null;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// tracks a stream, typically an api.* call (derive, rpc, query) that
|
||||
// - returns a promise with an unsubscribe function
|
||||
// - has a callback to set the value
|
||||
// FIXME The typings here need some serious TLC
|
||||
export default function useCall <T> (fn: TrackFn | undefined, params: CallParams, options: CallOptions<T> = {}): T | undefined {
|
||||
const [value, setValue] = useState<T | undefined>(options.defaultValue);
|
||||
const tracker = useRef<Tracker>({ isActive: false, count: 0, serialized: null, subscriber: null });
|
||||
|
||||
// initial effect, we need an unsubscription
|
||||
useEffect((): () => void => {
|
||||
return (): void => {
|
||||
unsubscribe(tracker);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// on changes, re-subscribe
|
||||
useEffect((): void => {
|
||||
if (fn) {
|
||||
const [serialized, mappedParams] = extractParams(fn, params, options.paramMap || transformIdentity);
|
||||
|
||||
if (mappedParams && serialized !== tracker.current.serialized) {
|
||||
tracker.current.serialized = serialized;
|
||||
|
||||
subscribe(tracker, fn, mappedParams, setValue, options);
|
||||
}
|
||||
}
|
||||
}, [fn, params]);
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -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 { Params } from './types';
|
||||
import { CallParams } from './types';
|
||||
|
||||
import { isNull, isUndefined } from '@polkadot/util';
|
||||
|
||||
@ -15,7 +15,7 @@ export function transformIdentity (value: any): any {
|
||||
}
|
||||
|
||||
// extract the serialized and mapped params, all ready for use in our call
|
||||
export function extractParams (fn: any, params: any[], paramMap: (params: any[]) => any): [string, Params | null] {
|
||||
export function extractParams (fn: any, params: any[], paramMap: (params: any[]) => any): [string, CallParams | null] {
|
||||
return [
|
||||
JSON.stringify({ f: fn?.name, p: params }),
|
||||
params.length === 0 || !params.some((param): boolean => isNull(param) || isUndefined(null))
|
||||
@ -7,7 +7,7 @@ import { DeriveAccountInfo } from '@polkadot/api-derive/types';
|
||||
import { BareProps } from '@polkadot/react-api/types';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useApi, useStream } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
|
||||
interface Props extends BareProps {
|
||||
children?: React.ReactNode;
|
||||
@ -16,9 +16,9 @@ interface Props extends BareProps {
|
||||
params?: string | AccountId | Address | null;
|
||||
}
|
||||
|
||||
export default function AccountIndexDisplay ({ children, className, defaultValue = '-', label = '', params, style }: Props): React.ReactElement<Props> {
|
||||
export default function AccountIndexDisplay ({ children, className, defaultValue, label, params, style }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const info = useStream<DeriveAccountInfo>(api.derive.accounts.info as any, [params]);
|
||||
const info = useCall<DeriveAccountInfo>(api.derive.accounts.info as any, [params]);
|
||||
const [accountIndex, setAccountIndex] = useState<string | null>(null);
|
||||
|
||||
useEffect((): void => {
|
||||
@ -34,7 +34,7 @@ export default function AccountIndexDisplay ({ children, className, defaultValue
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label}{accountIndex || defaultValue}{children}
|
||||
{label || ''}{accountIndex || defaultValue || '-'}{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { getAddressName } from '@polkadot/react-components/util';
|
||||
import { useStream, useApi } from '@polkadot/react-hooks';
|
||||
import { useCall, useApi } from '@polkadot/react-hooks';
|
||||
|
||||
interface Props extends BareProps {
|
||||
children?: React.ReactNode;
|
||||
@ -43,9 +43,9 @@ function defaultOrAddr (defaultName = '', _address?: AccountId | AccountIndex |
|
||||
return extracted;
|
||||
}
|
||||
|
||||
export default function AccountName ({ children, className, defaultName, label = '', onClick, override, params, style, toggle, withShort }: Props): React.ReactElement<Props> {
|
||||
export default function AccountName ({ children, className, defaultName, label, onClick, override, params, style, toggle, withShort }: Props): React.ReactElement<Props> {
|
||||
const { api } = useApi();
|
||||
const info = useStream<DeriveAccountInfo>(api.derive.accounts.info as any, [params]);
|
||||
const info = useCall<DeriveAccountInfo>(api.derive.accounts.info as any, [params]);
|
||||
const [name, setName] = useState(defaultOrAddr(defaultName, params));
|
||||
|
||||
useEffect((): void => {
|
||||
@ -71,7 +71,7 @@ export default function AccountName ({ children, className, defaultName, label =
|
||||
}
|
||||
style={style}
|
||||
>
|
||||
{label}{override || name}{children}
|
||||
{label || ''}{override || name}{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -16,13 +16,13 @@ interface Props extends BareProps, CallProps {
|
||||
chain_bestNumberFinalized?: BlockNumber;
|
||||
}
|
||||
|
||||
export function BestFinalized ({ children, className, label = '', style, chain_bestNumberFinalized }: Props): React.ReactElement<Props> {
|
||||
export function BestFinalized ({ children, className, label, style, chain_bestNumberFinalized }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label}{
|
||||
{label || ''}{
|
||||
chain_bestNumberFinalized
|
||||
? formatNumber(chain_bestNumberFinalized)
|
||||
: '-'
|
||||
|
||||
@ -16,13 +16,13 @@ interface Props extends BareProps, CallProps {
|
||||
chain_bestNumber?: BlockNumber;
|
||||
}
|
||||
|
||||
export function BestNumber ({ children, className, label = '', style, chain_bestNumber }: Props): React.ReactElement<Props> {
|
||||
export function BestNumber ({ children, className, label, style, chain_bestNumber }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label}{
|
||||
{label || ''}{
|
||||
chain_bestNumber
|
||||
? formatNumber(chain_bestNumber)
|
||||
: '-'
|
||||
|
||||
@ -19,7 +19,7 @@ interface Props extends BareProps, CallProps {
|
||||
staking_ledger?: StakingLedger | null;
|
||||
}
|
||||
|
||||
export function BondedDisplay ({ children, className, label = '', staking_ledger }: Props): React.ReactElement<Props> {
|
||||
export function BondedDisplay ({ children, className, label, staking_ledger }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<FormatBalance
|
||||
className={className}
|
||||
|
||||
@ -13,7 +13,7 @@ interface Props extends BareProps {
|
||||
label?: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function Chain ({ children, className, label = '', style }: Props): React.ReactElement<Props> {
|
||||
export default function Chain ({ children, className, label, style }: Props): React.ReactElement<Props> {
|
||||
const { systemChain } = useApi();
|
||||
|
||||
return (
|
||||
@ -21,7 +21,7 @@ export default function Chain ({ children, className, label = '', style }: Props
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label}{systemChain}{children}
|
||||
{label || ''}{systemChain}{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -30,12 +30,12 @@ function format (value: Compact<any> | BN | string, currency: string): React.Rea
|
||||
return <>{prefix}.<span className='balance-postfix'>{`000${postfix || ''}`.slice(-3)}</span> {currency}</>;
|
||||
}
|
||||
|
||||
function FormatBalance ({ children, className, label = '', value }: Props): React.ReactElement<Props> {
|
||||
function FormatBalance ({ children, className, label, value }: Props): React.ReactElement<Props> {
|
||||
const [currency] = useState(formatBalance.getDefaults().unit);
|
||||
|
||||
return (
|
||||
<div className={`ui--FormatBalance ${className}`}>
|
||||
{label}{
|
||||
{label || ''}{
|
||||
value
|
||||
? format(value, currency)
|
||||
: '-'
|
||||
|
||||
@ -18,7 +18,7 @@ interface Props extends BareProps, CallProps {
|
||||
electionsPhragmen_stakeOf?: BalanceOf;
|
||||
}
|
||||
|
||||
export function LockedVote ({ children, className, electionsPhragmen_stakeOf, label = '' }: Props): React.ReactElement<Props> {
|
||||
export function LockedVote ({ children, className, electionsPhragmen_stakeOf, label }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<FormatBalance
|
||||
className={className}
|
||||
|
||||
@ -13,7 +13,7 @@ interface Props extends BareProps {
|
||||
label?: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function NodeName ({ children, className, label = '', style }: Props): React.ReactElement<Props> {
|
||||
export default function NodeName ({ children, className, label, style }: Props): React.ReactElement<Props> {
|
||||
const { systemName } = useApi();
|
||||
|
||||
return (
|
||||
@ -21,7 +21,7 @@ export default function NodeName ({ children, className, label = '', style }: Pr
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label}{systemName}{children}
|
||||
{label || ''}{systemName}{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ interface Props extends BareProps {
|
||||
label?: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function NodeVersion ({ children, className, label = '', style }: Props): React.ReactElement<Props> {
|
||||
export default function NodeVersion ({ children, className, label, style }: Props): React.ReactElement<Props> {
|
||||
const { systemVersion } = useApi();
|
||||
|
||||
return (
|
||||
@ -21,7 +21,7 @@ export default function NodeVersion ({ children, className, label = '', style }:
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label}{systemVersion}{children}
|
||||
{label || ''}{systemVersion}{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -18,10 +18,10 @@ interface Props extends BareProps, CallProps {
|
||||
params?: string | null;
|
||||
}
|
||||
|
||||
export function Nonce ({ accountNonce, children, className, label = '' }: Props): React.ReactElement<Props> {
|
||||
export function Nonce ({ accountNonce, children, className, label }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<div className={className}>
|
||||
{label}{
|
||||
{label || ''}{
|
||||
accountNonce
|
||||
? formatNumber(accountNonce)
|
||||
: '0'
|
||||
|
||||
@ -17,7 +17,7 @@ interface Props extends BareProps, CallProps {
|
||||
timestamp_now?: Moment;
|
||||
}
|
||||
|
||||
export function TimeNow ({ children, className, isSubstrateV2, label = '', style, timestamp_now }: Props): React.ReactElement<Props> {
|
||||
export function TimeNow ({ children, className, isSubstrateV2, label, style, timestamp_now }: Props): React.ReactElement<Props> {
|
||||
const value = isSubstrateV2 || !timestamp_now
|
||||
? timestamp_now
|
||||
: timestamp_now.muln(1000); // for 1.x, timestamps are in seconds
|
||||
@ -27,7 +27,7 @@ export function TimeNow ({ children, className, isSubstrateV2, label = '', style
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label}
|
||||
{label || ''}
|
||||
<Elapsed value={value} />
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@ -17,13 +17,13 @@ interface Props extends BareProps, CallProps {
|
||||
timestamp_minimumPeriod?: Moment;
|
||||
}
|
||||
|
||||
export function TimePeriod ({ babe_expectedBlockTime, children, className, label = '', style, timestamp_minimumPeriod }: Props): React.ReactElement<Props> {
|
||||
export function TimePeriod ({ babe_expectedBlockTime, children, className, label, style, timestamp_minimumPeriod }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label}{
|
||||
{label || ''}{
|
||||
babe_expectedBlockTime
|
||||
? `${formatNumber(babe_expectedBlockTime.toNumber() / 1000)}s`
|
||||
: timestamp_minimumPeriod
|
||||
|
||||
@ -16,7 +16,7 @@ interface Props extends BareProps, CallProps {
|
||||
balances_totalIssuance?: Balance;
|
||||
}
|
||||
|
||||
export function TotalIssuance ({ children, className, label = '', style, balances_totalIssuance }: Props): React.ReactElement<Props> {
|
||||
export function TotalIssuance ({ children, className, label, style, balances_totalIssuance }: Props): React.ReactElement<Props> {
|
||||
const value = balances_totalIssuance
|
||||
? balances_totalIssuance.toString()
|
||||
: null;
|
||||
@ -26,7 +26,7 @@ export function TotalIssuance ({ children, className, label = '', style, balance
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
{label}{
|
||||
{label || ''}{
|
||||
value
|
||||
? `${formatBalance(value, false)}${formatBalance.calcSi(value).value}`
|
||||
: '-'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user