@polkadot/types/interfaces#EraIndex TypeScript Examples

The following examples show how to use @polkadot/types/interfaces#EraIndex. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts    From polkadot-watcher-csv-exporter with Apache License 2.0 7 votes vote down vote up
erasLastBlock = async (indexes: EraIndex[], api: ApiPromise): Promise<EraLastBlock[]> => {

  const result = await Promise.all(indexes.map(async index => {
    return {era: index, block: await lastBlockOf(index,api)}
   }))

  return result

}
Example #2
Source File: utils.ts    From polkadot-watcher-csv-exporter with Apache License 2.0 7 votes vote down vote up
lastBlockOf = async (eraIndex: EraIndex, api: ApiPromise): Promise<number> => {

  const howManyErasAgoVar = await howManyErasAgo(eraIndex, api)
  if (howManyErasAgoVar == 0) return (await api.rpc.chain.getHeader()).number.unwrap().toNumber()

  const lastBlockPreviousEra = await firstBlockCurrentEra(api) - 1  

  const deriveSessionProgress = await api.derive.session.progress();  

  // the api result is still not reliable => guessed
  const guessedResult = lastBlockPreviousEra - ( ( howManyErasAgoVar - 1 ) * deriveSessionProgress.eraLength.toNumber() )

  const hash = await api.rpc.chain.getBlockHash(guessedResult + 50)
  const apiAt = await api.at(hash)
  const [_,firstBlockNextTargetEra] = await apiAt.query.babe.epochStart()
  
  return firstBlockNextTargetEra.toNumber() - 1
  
}
Example #3
Source File: useStakerPayouts.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
export default function useStakerPayouts (): BN {
  const { api } = useApi();
  const migrateEraOpt = useCall<Option<EraIndex>>(api.query.staking?.migrateEra);

  return useMemo(
    () => (migrateEraOpt && migrateEraOpt.isSome && migrateEraOpt.unwrap()) || (
      isFunction(api.tx.staking.payoutStakers)
        ? BN_ZERO
        : BN_BILLION
    ),
    [api, migrateEraOpt]
  );
}
Example #4
Source File: utils.ts    From polkadot-watcher-csv-exporter with Apache License 2.0 6 votes vote down vote up
howManyErasAgo = async (eraIndex: EraIndex, api: ApiPromise): Promise<number> => {

  const currentEraIndex = (await api.query.staking.activeEra()).unwrap().index;
  return currentEraIndex.toNumber() - eraIndex.toNumber()
  
}
Example #5
Source File: subscriber.ts    From polkadot-watcher-csv-exporter with Apache License 2.0 6 votes vote down vote up
private _writeEraCSVHistorical = async (): Promise<void> => {
      const network = this.chain.toString().toLowerCase()

      const erasHistoric = await this.api.derive.staking.erasHistoric(false);
      const eraIndexes = erasHistoric.slice(
        Math.max(erasHistoric.length - this.historySize, 0)
      )
      this.logger.info(`Requested Historical data for eras: ${eraIndexes.map(era => era.toString()).join(', ')}`);

      //A to big number of era indexes could make crush the API => Chunk splitting
      const size = 10
      const eraIndexesChucked: EraIndex[][] = []
      for (let i = 0; i < eraIndexes.length; i += size) {
        const chunk = eraIndexes.slice(i, i + size)
        eraIndexesChucked.push(chunk)
      }
      
      for (const chunk of eraIndexesChucked) {
        this.logger.debug(`the handled chunk size is ${chunk.length}`)
        const request = {api:this.api,network,exportDir:this.exportDir,eraIndexes:chunk}
        const chainData = await gatherChainDataHistorical(request, this.logger)
        await writeHistoricErasCSV(request, chainData, this.logger)
      }

    }
Example #6
Source File: subscriber.ts    From polkadot-watcher-csv-exporter with Apache License 2.0 5 votes vote down vote up
private _writeEraCSV = async (eraIndex: EraIndex, sessionIndex: SessionIndex, blockNumber: Compact<BlockNumber>): Promise<void> => {
      const network = this.chain.toString().toLowerCase()
      const request = {api:this.api,network,apiChunkSize:this.apiChunkSize,exportDir:this.exportDir,eraIndex,sessionIndex,blockNumber}
      const chainData = await gatherChainData(request, this.logger)
      await writeSessionCSV(request, chainData, this.logger)
      await writeEraCSV(request, chainData, this.logger)
    }
Example #7
Source File: subscriberEraScanner.ts    From polkadot-watcher-csv-exporter with Apache License 2.0 5 votes vote down vote up
private _handleEraChange = async (newEra: EraIndex): Promise<void> =>{
      this.eraIndex = newEra
      this._requestNewScan()
    }
Example #8
Source File: subscriberEraScanner.ts    From polkadot-watcher-csv-exporter with Apache License 2.0 5 votes vote down vote up
private eraIndex: EraIndex;
Example #9
Source File: subscriber.ts    From polkadot-watcher-csv-exporter with Apache License 2.0 5 votes vote down vote up
private _handleEraChange = async (newEra: EraIndex, newSession: SessionIndex): Promise<void> =>{
      this.eraIndex = newEra
      await this._handleSessionChange(newSession)
    }
Example #10
Source File: subscriber.ts    From polkadot-watcher-csv-exporter with Apache License 2.0 5 votes vote down vote up
private _writeSessionCSV = async (eraIndex: EraIndex, sessionIndex: SessionIndex, blockNumber: Compact<BlockNumber>): Promise<void> => {
      const network = this.chain.toString().toLowerCase()
      const request = {api:this.api,network,apiChunkSize:this.apiChunkSize,exportDir:this.exportDir,eraIndex,sessionIndex,blockNumber}
      const chainData = await gatherChainData(request, this.logger)
      await writeSessionCSV(request, chainData, this.logger)
    }
Example #11
Source File: api.ts    From community-repo with GNU General Public License v3.0 5 votes vote down vote up
getEraStake = async (
  api: ApiPromise,
  hash: Hash,
  era: EraIndex | number
): Promise<number> =>
  (await api.query.staking.erasTotalStake.at(hash, era)).toNumber()
Example #12
Source File: subscriber.ts    From polkadot-watcher-csv-exporter with Apache License 2.0 5 votes vote down vote up
private eraIndex: EraIndex;
Example #13
Source File: useOwnEraRewards.ts    From subscan-multisig-react with Apache License 2.0 5 votes vote down vote up
export function useOwnEraRewards(maxEras?: number, ownValidators?: StakerState[]): State {
  const { api } = useApi();
  const mountedRef = useIsMountedRef();
  const stashIds = useOwnStashIds();
  const allEras = useCall<EraIndex[]>(api.derive.staking?.erasHistoric);
  const [{ filteredEras, validatorEras }, setFiltered] = useState<Filtered>({ filteredEras: [], validatorEras: [] });
  const [state, setState] = useState<State>({ isLoadingRewards: true, rewardCount: 0 });
  const stakerRewards = useCall<[[string[]], DeriveStakerReward[][]]>(
    !ownValidators?.length && !!filteredEras.length && stashIds && api.derive.staking?.stakerRewardsMultiEras,
    [stashIds, filteredEras],
    { withParams: true }
  );
  const erasPoints = useCall<DeriveEraPoints[]>(
    !!validatorEras.length && !!filteredEras.length && api.derive.staking._erasPoints,
    [filteredEras, false]
  );
  const erasRewards = useCall<DeriveEraRewards[]>(
    !!validatorEras.length && !!filteredEras.length && api.derive.staking._erasRewards,
    [filteredEras, false]
  );

  useEffect((): void => {
    setState({ allRewards: null, isLoadingRewards: true, rewardCount: 0 });
  }, [maxEras, ownValidators]);

  useEffect((): void => {
    if (allEras && maxEras) {
      // eslint-disable-next-line
      const filteredEras = allEras.slice(-1 * maxEras);
      // eslint-disable-next-line
      const validatorEras: ValidatorWithEras[] = [];

      if (allEras.length === 0) {
        setState({
          allRewards: {},
          isLoadingRewards: false,
          rewardCount: 0,
        });
        setFiltered({ filteredEras, validatorEras });
      } else if (ownValidators?.length) {
        ownValidators.forEach(({ stakingLedger, stashId }): void => {
          if (stakingLedger) {
            const eras = filteredEras.filter((era) => !stakingLedger.claimedRewards.some((c) => era.eq(c)));

            if (eras.length) {
              validatorEras.push({ eras, stashId });
            }
          }
        });

        // When we have just claimed, we have filtered eras, but no validator eras - set accordingly
        if (filteredEras.length && !validatorEras.length) {
          setState({
            allRewards: {},
            isLoadingRewards: false,
            rewardCount: 0,
          });
        }
      }

      setFiltered({ filteredEras, validatorEras });
    }
  }, [allEras, maxEras, ownValidators]);

  useEffect((): void => {
    // eslint-disable-next-line
    mountedRef.current && stakerRewards && !ownValidators && setState(getRewards(stakerRewards));
  }, [mountedRef, ownValidators, stakerRewards]);

  useEffect((): void => {
    // eslint-disable-next-line
    mountedRef &&
      erasPoints &&
      erasRewards &&
      ownValidators &&
      setState(getValRewards(api, validatorEras, erasPoints, erasRewards));
  }, [api, erasPoints, erasRewards, mountedRef, ownValidators, validatorEras]);

  return state;
}
Example #14
Source File: useAvailableSlashes.ts    From subscan-multisig-react with Apache License 2.0 5 votes vote down vote up
export function useAvailableSlashes(): [BN, UnappliedSlash[]][] {
  const { api } = useApi();
  const indexes = useCall<DeriveSessionIndexes>(api.derive.session?.indexes);
  const earliestSlash = useCall<Option<EraIndex>>(api.query.staking?.earliestUnappliedSlash);
  const mountedRef = useIsMountedRef();
  const [slashes, setSlashes] = useState<[BN, UnappliedSlash[]][]>([]);

  // eslint-disable-next-line
  useEffect((): Unsub => {
    let unsub: Unsub | undefined;

    if (mountedRef.current && indexes && earliestSlash && earliestSlash.isSome) {
      const from = earliestSlash.unwrap();
      const range: BN[] = [];
      let start = new BN(from);

      // any <= activeEra (we include activeEra since slashes are immediately reflected)
      while (start.lte(indexes.activeEra)) {
        range.push(start);
        start = start.add(BN_ONE);
      }

      if (range.length) {
        (async (): Promise<void> => {
          unsub = await api.query.staking.unappliedSlashes.multi<Vec<UnappliedSlash>>(range, (values): void => {
            // eslint-disable-next-line
            mountedRef.current &&
              setSlashes(
                values
                  .map((value, index): [BN, UnappliedSlash[]] => [from.addn(index), value])
                  // eslint-disable-next-line
                  .filter(([, slashes]) => slashes.length)
              );
          });
        })().catch(console.error);
      }
    }

    return (): void => {
      // eslint-disable-next-line
      unsub && unsub();
    };
  }, [api, earliestSlash, indexes, mountedRef]);

  return slashes;
}
Example #15
Source File: useAvailableSlashes.ts    From crust-apps with Apache License 2.0 5 votes vote down vote up
export function useAvailableSlashes (): [BN, UnappliedSlash[]][] {
  const { api } = useApi();
  const indexes = useCall<DeriveSessionIndexes>(api.derive.session?.indexes);
  const earliestSlash = useCall<Option<EraIndex>>(api.query.staking?.earliestUnappliedSlash);
  const mountedRef = useIsMountedRef();
  const [slashes, setSlashes] = useState<[BN, UnappliedSlash[]][]>([]);

  useEffect((): Unsub => {
    let unsub: Unsub | undefined;

    if (mountedRef.current && indexes && earliestSlash && earliestSlash.isSome) {
      const from = earliestSlash.unwrap();
      const range: BN[] = [];
      let start = new BN(from);

      // any <= activeEra (we include activeEra since slashes are immediately reflected)
      while (start.lte(indexes.activeEra)) {
        range.push(start);
        start = start.add(BN_ONE);
      }

      if (range.length) {
        (async (): Promise<void> => {
          unsub = await api.query.staking.unappliedSlashes.multi<Vec<UnappliedSlash>>(range, (values): void => {
            mountedRef.current && setSlashes(
              values
                .map((value, index): [BN, UnappliedSlash[]] => [from.addn(index), value])
                .filter(([, slashes]) => slashes.length)
            );
          });
        })().catch(console.error);
      }
    }

    return (): void => {
      unsub && unsub();
    };
  }, [api, earliestSlash, indexes, mountedRef]);

  return slashes;
}
Example #16
Source File: useInactives.ts    From crust-apps with Apache License 2.0 5 votes vote down vote up
function extractState (api: ApiPromise, stashId: string, slashes: Option<SlashingSpans>[], nominees: string[], { activeEra }: DeriveSessionIndexes, submittedIn: EraIndex, exposures: Exposure[]): Inactives {
  const max = api.consts.staking?.maxNominatorRewardedPerValidator;

  // chilled
  const nomsChilled = nominees.filter((_, index): boolean => {
    if (slashes[index].isNone) {
      return false;
    }

    const { lastNonzeroSlash } = slashes[index].unwrap();

    return !lastNonzeroSlash.isZero() && lastNonzeroSlash.gte(submittedIn);
  });

  // all nominations that are oversubscribed
  const nomsOver = exposures
    .map(({ others }) => others.sort((a, b) => b.value.unwrap().cmp(a.value.unwrap())))
    .map((others, index) =>
      !max || max.gtn(others.map(({ who }) => who.toString()).indexOf(stashId))
        ? null
        : nominees[index]
    )
    .filter((nominee): nominee is string => !!nominee && !nomsChilled.includes(nominee));

  // first a blanket find of nominations not in the active set
  let nomsInactive = exposures
    .map((exposure, index) =>
      exposure.others.some(({ who }) => who.eq(stashId))
        ? null
        : nominees[index]
    )
    .filter((nominee): nominee is string => !!nominee);

  // waiting if validator is inactive or we have not submitted long enough ago
  const nomsWaiting = exposures
    .map((exposure, index) =>
      exposure.total.unwrap().isZero() || (
        nomsInactive.includes(nominees[index]) &&
        // it could be activeEra + 1 (currentEra for last session)
        submittedIn.gte(activeEra)
      )
        ? nominees[index]
        : null
    )
    .filter((nominee): nominee is string => !!nominee)
    .filter((nominee) => !nomsChilled.includes(nominee) && !nomsOver.includes(nominee));

  // filter based on all inactives
  const nomsActive = nominees.filter((nominee) => !nomsInactive.includes(nominee) && !nomsChilled.includes(nominee) && !nomsOver.includes(nominee));

  // inactive also contains waiting, remove those
  nomsInactive = nomsInactive.filter((nominee) => !nomsWaiting.includes(nominee) && !nomsChilled.includes(nominee) && !nomsOver.includes(nominee));

  return {
    nomsActive,
    nomsChilled,
    nomsInactive,
    nomsOver,
    nomsWaiting
  };
}
Example #17
Source File: useOwnEraRewards.ts    From crust-apps with Apache License 2.0 4 votes vote down vote up
export function useOwnEraRewards (maxEras?: number, ownValidators?: StakerState[]): State {
  const { api } = useApi();
  const mountedRef = useIsMountedRef();
  const stashIds = useOwnStashIds();
  const allEras = useCall<EraIndex[]>(api.derive.staking?.erasHistoric);
  const [{ filteredEras, validatorEras }, setFiltered] = useState<Filtered>({ filteredEras: [], validatorEras: [] });
  const [state, setState] = useState<State>({ isLoadingRewards: true, rewardCount: 0 });
  const stakerRewards = useCall<[[string[]], DeriveStakerReward[][]]>(!ownValidators?.length && !!filteredEras.length && stashIds && api.derive.staking?.stakerRewardsMultiEras, [stashIds, filteredEras], { withParams: true });
  const erasPoints = useCall<DeriveEraPoints[]>(!!validatorEras.length && !!filteredEras.length && api.derive.staking._erasPoints, [filteredEras, false]);
  const erasRewards = useCall<DeriveEraRewards[]>(!!validatorEras.length && !!filteredEras.length && api.derive.staking._erasRewards, [filteredEras, false]);
  const stakingOverview = useCall<DeriveStakingOverview>(api.derive.staking.overview);
  const waitingInfo = useCall<DeriveStakingWaiting>(api.derive.staking.waitingInfo);
  const allValidators = stakingOverview && waitingInfo && [...waitingInfo.waiting, ...stakingOverview.nextElected];
  const stakingAccounts = useCall<DeriveStakingAccount[]>(allValidators && api.derive.staking.accounts, [allValidators]);
  const [eraStashExposure, setEraStashExposure] = useState<EraStashExposure[]>([]);
  const [eraStakingPayouts, setEraStakingPayouts] = useState<EraStakingPayout[]>();

  useEffect(() => {
    let unsub: (() => void) | undefined;

    if (allValidators && filteredEras && mountedRef.current) {
      const query: [EraIndex, string][] = [];

      for (const v of allValidators) {
        filteredEras.forEach((era) => query.push([era, v.toString()]));
      }

      const fns: any[] = [
        [api.query.staking.erasStakers.multi as any, query]
      ];

      api.combineLatest<Exposure[]>(fns, ([exposures]): void => {
        const tmp: EraStashExposure[] = [];

        if (Array.isArray(exposures) && mountedRef.current && exposures.length && exposures.length === query.length) {
          for (const [index, a] of query.entries()) {
            tmp.push({
              era: a[0],
              stashId: a[1],
              exposure: exposures[index]
            });
          }

          setEraStashExposure(tmp);
        }
      }).then((_unsub): void => {
        unsub = _unsub;
      }).catch(console.error);
    }

    return (): void => {
      unsub && unsub();
    };
  }, [filteredEras, allValidators]);

  useEffect(() => {
    let unsub: (() => void) | undefined;

    if (filteredEras && mountedRef.current) {
      const query: number[] = [];
      filteredEras.forEach((era) => query.push(era.toNumber()));

      const fns: any[] = [
        [api.query.staking.erasStakingPayout.multi as any, query]
      ];

      api.combineLatest<BalanceOf[]>(fns, ([balanceOfs]): void => {
        const tmp: EraStakingPayout[] = [];
        const result = JSON.parse(JSON.stringify(balanceOfs))

        if (Array.isArray(result) && mountedRef.current && result.length && result.length === query.length) {
          for (const [index, a] of query.entries()) {
            tmp.push({
              era: a,
              hasReward: !!result[index]
            });
          }

          setEraStakingPayouts(tmp);
        }
      }).then((_unsub): void => {
        unsub = _unsub;
      }).catch(console.error);
    }

    return (): void => {
      unsub && unsub();
    };
  }, [filteredEras]);

  useEffect((): void => {
    setState({ allRewards: null, isLoadingRewards: true, rewardCount: 0 });
  }, [maxEras, ownValidators]);

  useEffect((): void => {
    if (allEras && maxEras) {
      const filteredEras = allEras.slice(-1 * maxEras);
      const validatorEras: ValidatorWithEras[] = [];

      if (allEras.length === 0) {
        setState({
          allRewards: {},
          isLoadingRewards: false,
          rewardCount: 0
        });
        setFiltered({ filteredEras, validatorEras });
      } else if (ownValidators?.length) {
        ownValidators.forEach(({ stakingLedger, stashId }): void => {
          if (stakingLedger) {
            const eras = filteredEras.filter((era) => !stakingLedger.claimedRewards.some((c) => era.eq(c)));

            if (eras.length) {
              validatorEras.push({ eras, stashId });
            }
          }
        });

        // When we have just claimed, we have filtered eras, but no validator eras - set accordingly
        if (filteredEras.length && !validatorEras.length) {
          setState({
            allRewards: {},
            isLoadingRewards: false,
            rewardCount: 0
          });
        }
      }

      setFiltered({ filteredEras, validatorEras });
    }
  }, [allEras, maxEras, ownValidators]);

  useEffect((): void => {
    mountedRef.current && stakerRewards && !ownValidators && stakingAccounts && eraStakingPayouts && setState(
      getRewards(stakerRewards, stakingAccounts, eraStakingPayouts)
    );
  }, [mountedRef, ownValidators, stakerRewards, stakingAccounts, eraStakingPayouts]);

  useEffect((): void => {
    mountedRef && erasPoints && erasRewards && ownValidators && eraStashExposure && eraStakingPayouts && setState(
      getValRewards(api, validatorEras, erasPoints, erasRewards, eraStashExposure, eraStakingPayouts)
    );
  }, [api, erasPoints, erasRewards, mountedRef, ownValidators, validatorEras, eraStashExposure, eraStakingPayouts]);

  return state;
}