@@ -9,7 +9,7 @@ import type { SortedTargets, TargetSortBy, ValidatorInfo } from './types';
99
1010import { useEffect , useMemo , useState } from 'react' ;
1111
12- import { createNamedHook , useAccounts , useApi , useCall , useCallMulti , useInflation } from '@polkadot/react-hooks' ;
12+ import { createNamedHook , useAccounts , useApi , useCall , useCallMulti , useInflation , usePrevious } from '@polkadot/react-hooks' ;
1313import { AccountId32 } from '@polkadot/types/interfaces' ;
1414import { PalletStakingExposure , PalletStakingIndividualExposure } from '@polkadot/types/lookup' ;
1515import { arrayFlatten , BN , BN_HUNDRED , BN_MAX_INTEGER , BN_ONE , BN_ZERO , formatBalance } from '@polkadot/util' ;
@@ -57,10 +57,10 @@ const OPT_MULTI = {
5757 historyDepth,
5858 maxNominatorsCount : optMaxNominatorsCount && optMaxNominatorsCount . isSome
5959 ? optMaxNominatorsCount . unwrap ( )
60- : undefined ,
60+ : new BN ( 0 ) ,
6161 maxValidatorsCount : optMaxValidatorsCount && optMaxValidatorsCount . isSome
6262 ? optMaxValidatorsCount . unwrap ( )
63- : undefined ,
63+ : new BN ( 0 ) ,
6464 minNominatorBond,
6565 minValidatorBond,
6666 totalIssuance
@@ -192,7 +192,7 @@ function extractSingle (api: ApiPromise, allAccounts: string[], derive: DeriveSt
192192 rankOverall : 0 ,
193193 rankReward : 0 ,
194194 skipRewards,
195- stakedReturn : 0 ,
195+ stakedReturn : null ,
196196 stakedReturnCmp : 0 ,
197197 validatorPrefs,
198198 withReturns
@@ -212,7 +212,7 @@ function addReturns (inflation: Inflation, baseInfo: Partial<SortedTargets>): Pa
212212
213213 avgStaked && ! avgStaked . isZero ( ) && validators . forEach ( ( v ) : void => {
214214 if ( ! v . skipRewards && v . withReturns ) {
215- const adjusted = avgStaked . mul ( BN_HUNDRED ) . imuln ( inflation . stakedReturn ) . div ( v . bondTotal ) ;
215+ const adjusted = avgStaked . mul ( BN_HUNDRED ) . imuln ( inflation . stakedReturn || 0 ) . div ( v . bondTotal ) ;
216216
217217 // in some cases, we may have overflows... protect against those
218218 v . stakedReturn = ( adjusted . gt ( BN_MAX_INTEGER ) ? BN_MAX_INTEGER : adjusted ) . toNumber ( ) / BN_HUNDRED . toNumber ( ) ;
@@ -293,23 +293,43 @@ function useSortedTargetsImpl (favorites: string[], withLedger: boolean): Sorted
293293 const waitingInfo = useCall < DeriveStakingWaiting > ( api . derive . staking . waitingInfo , [ { ...DEFAULT_FLAGS_WAITING , withLedger } ] ) ;
294294 const lastEraInfo = useCall < LastEra > ( api . derive . session . info , undefined , OPT_ERA ) ;
295295 const [ stakers , setStakers ] = useState < [ StorageKey < [ u32 , AccountId32 ] > , PalletStakingExposure ] [ ] > ( [ ] ) ;
296- const [ stakersTotal , setStakersTotal ] = useState < BN | undefined > ( ) ;
297- const [ nominatorMinActiveThreshold , setNominatorMinActiveThreshold ] = useState < string > ( '' ) ;
296+ const [ stakersTotal , setStakersTotal ] = useState < BN | undefined | null > ( ) ;
297+ const [ nominatorMinActiveThreshold , setNominatorMinActiveThreshold ] = useState < string | null > ( '' ) ;
298298 const [ nominatorMaxElectingCount , setNominatorMaxElectingCount ] = useState < u32 > ( ) ;
299- const [ nominatorElectingCount , setNominatorElectingCount ] = useState < number | undefined > ( ) ;
300- const [ nominatorActiveCount , setNominatorActiveCount ] = useState < number | undefined > ( ) ;
301- const [ validatorActiveCount , setValidatorActiveCount ] = useState < number | undefined > ( ) ;
299+ const [ nominatorElectingCount , setNominatorElectingCount ] = useState < number | undefined | null > ( ) ;
300+ const [ nominatorActiveCount , setNominatorActiveCount ] = useState < number | undefined | null > ( ) ;
301+ const [ validatorActiveCount , setValidatorActiveCount ] = useState < number | undefined | null > ( ) ;
302302
303- const [ calcStakers , setCalcStakers ] = useState < boolean > ( false ) ;
303+ const [ timerDone , setTimerDone ] = useState < boolean > ( false ) ;
304+
305+ const prevStakersLength = usePrevious ( stakers . length ) ;
306+
307+ useEffect ( ( ) => {
308+ // This timer is set to wait for 10 seconds in order to identify
309+ // if api has finished loading the staking info. If at the end of this timer
310+ // the values from API are not yet loaded, then it is assumed that the
311+ // API is not returning any values (meaning probable misconfiguration).
312+ // This is for covering edge cases (e.g. staking pallet is included
313+ // in apps but not used - stakers = 0).
314+ const apiTimer = setTimeout ( ( ) => setTimerDone ( true ) , 10000 ) ;
315+
316+ return ( ) => {
317+ clearTimeout ( apiTimer ) ;
318+ } ;
319+ } , [ ] ) ;
304320
305321 useEffect ( ( ) => {
306- if ( stakers [ 0 ] && stakers [ 0 ] [ 1 ] ) {
322+ if ( prevStakersLength !== stakers . length && stakers [ 0 ] && stakers [ 0 ] [ 1 ] ) {
307323 setStakersTotal ( stakers [ 0 ] [ 1 ] . total . toBn ( ) ) ;
324+ } else if ( stakers . length === 0 ) {
325+ if ( timerDone ) {
326+ setStakersTotal ( null ) ;
327+ }
308328 }
309- } , [ stakers ] ) ;
329+ } , [ prevStakersLength , stakers , timerDone ] ) ;
310330
311331 useEffect ( ( ) => {
312- if ( stakers . length && ! calcStakers ) {
332+ if ( stakers . length !== prevStakersLength ) {
313333 const assignments : Map < string , BN > = new Map ( ) ;
314334
315335 stakers . sort ( ( a , b ) => a [ 1 ] . total . toBn ( ) . cmp ( b [ 1 ] . total . toBn ( ) ) ) . map ( ( x ) => x [ 1 ] . others ) . flat ( 1 ) . forEach ( ( x ) => {
@@ -319,20 +339,24 @@ function useSortedTargetsImpl (favorites: string[], withLedger: boolean): Sorted
319339
320340 assignments . set ( nominator , val ? amount . toBn ( ) . add ( val ) : amount . toBn ( ) ) ;
321341 } ) ;
322-
323342 const nominatorStakes = Array . from ( assignments ) ;
324343
325344 nominatorStakes . sort ( ( a , b ) => a [ 1 ] . cmp ( b [ 1 ] ) ) ;
326-
327345 setNominatorMaxElectingCount ( api . consts . electionProviderMultiPhase ?. maxElectingVoters ) ;
328-
329346 setNominatorElectingCount ( assignments . size ) ;
330347 setNominatorActiveCount ( assignments . size ) ;
331348 setNominatorMinActiveThreshold ( nominatorStakes [ 0 ] ? b ( nominatorStakes [ 0 ] [ 1 ] , api ) : '' ) ;
332349 setValidatorActiveCount ( stakers . length ) ;
333- setCalcStakers ( true ) ;
350+ } else if ( stakers . length === 0 ) {
351+ if ( timerDone ) {
352+ setNominatorMaxElectingCount ( api . consts . electionProviderMultiPhase ?. maxElectingVoters ) ;
353+ setNominatorElectingCount ( null ) ;
354+ setNominatorActiveCount ( null ) ;
355+ setNominatorMinActiveThreshold ( null ) ;
356+ setValidatorActiveCount ( null ) ;
357+ }
334358 }
335- } , [ api , calcStakers , stakers ] ) ;
359+ } , [ api , prevStakersLength , stakers , timerDone ] ) ;
336360
337361 const baseInfo = useMemo (
338362 ( ) => electedInfo && lastEraInfo && totalIssuance && waitingInfo
@@ -343,6 +367,12 @@ function useSortedTargetsImpl (favorites: string[], withLedger: boolean): Sorted
343367
344368 const inflation = useInflation ( baseInfo ?. totalStaked ) ;
345369
370+ useEffect ( ( ) => {
371+ if ( ! inflation . stakedReturn && timerDone ) {
372+ inflation . stakedReturn = null ;
373+ }
374+ } , [ inflation , inflation . stakedReturn , timerDone ] ) ;
375+
346376 const curEra = useCall < Option < u32 > > ( api . query . staking . currentEra ) ;
347377
348378 const getStakers = useMemo ( ( ) => async ( currentEra : u32 ) => {
@@ -351,7 +381,7 @@ function useSortedTargetsImpl (favorites: string[], withLedger: boolean): Sorted
351381
352382 curEra && getStakers ( curEra ?. unwrap ( ) ) ;
353383
354- const validatorMinActiveThreshold = stakersTotal ? b ( stakersTotal , api ) : '' ;
384+ const validatorMinActiveThreshold = stakersTotal ? b ( stakersTotal , api ) : null ;
355385
356386 return useMemo (
357387 ( ) : SortedTargets => ( {
@@ -372,7 +402,7 @@ function useSortedTargetsImpl (favorites: string[], withLedger: boolean): Sorted
372402 validatorActiveCount,
373403 validatorMinActiveThreshold,
374404 ...(
375- inflation && inflation . stakedReturn
405+ inflation && ( inflation . stakedReturn !== null && inflation . stakedReturn )
376406 ? addReturns ( inflation , baseInfo )
377407 : baseInfo
378408 )
0 commit comments