@polkadot/util#BN_ONE TypeScript Examples

The following examples show how to use @polkadot/util#BN_ONE. 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: util.ts    From crust-apps with Apache License 2.0 7 votes vote down vote up
/**
 * This is where we tweak the input values, based on what was specified, be it the input number
 * or the direction and turnout adjustments
 *
 * @param votes The votes that should be adjusted, will be either aye/nay
 * @param total The actual total of applied votes (same as turnout from derived)
 * @param change The actual change value we want to affect
 * @param inc The increment to apply here
 * @param totalInc The increment for the total. 0 for conviction-only changes, 1 of 1x added conviction vote
 * @param direction The direction, either increment (1) or decrement (-1)
 */
function getDiffs (votes: BN, total: BN, change: BN, inc: BN, totalInc: 0 | 0.1 | 1, direction: 1 | -1): [BN, BN, BN] {
  // setup
  const multiplier = direction === 1 ? BN_ONE : ONEMIN;
  const voteChange = change.add(inc);

  // since we allow 0.1 as well, we first multiply by 10, before dividing by the same
  const totalChange = BN_ONE.muln(totalInc * 10).mul(voteChange).div(BN_TEN);

  // return the change, vote with change applied and the total with the same. For the total we don't want
  // to go negative (total votes/turnout), since will do sqrt on it (and negative is non-sensical anyway)
  return [
    voteChange,
    votes.add(multiplier.mul(voteChange)),
    BN.max(BN_ZERO, total.add(multiplier.mul(totalChange)))
  ];
}
Example #2
Source File: useBlockCounts.tsx    From crust-apps with Apache License 2.0 6 votes vote down vote up
export default function useBlockCounts (accountId: string, sessionRewards: SessionRewards[]): u32[] {
  const { api } = useApi();
  const mountedRef = useIsMountedRef();
  const indexes = useCall<DeriveSessionIndexes>(api.derive.session?.indexes);
  const current = useCall<u32>(api.query.imOnline?.authoredBlocks, [indexes?.currentIndex, accountId]);
  const [counts, setCounts] = useState<u32[]>([]);
  const [historic, setHistoric] = useState<u32[]>([]);

  useEffect((): void => {
    if (isFunction(api.query.imOnline?.authoredBlocks) && sessionRewards && sessionRewards.length) {
      const filtered = sessionRewards.filter(({ sessionIndex }): boolean => sessionIndex.gt(BN_ZERO));

      if (filtered.length) {
        Promise
          .all(filtered.map(({ parentHash, sessionIndex }): Promise<u32> =>
            api.query.imOnline.authoredBlocks.at(parentHash, sessionIndex.sub(BN_ONE), accountId)
          ))
          .then((historic): void => {
            mountedRef.current && setHistoric(historic);
          }).catch(console.error);
      }
    }
  }, [accountId, api, mountedRef, sessionRewards]);

  useEffect((): void => {
    setCounts([...historic, current || api.createType('u32')].slice(1));
  }, [api, current, historic]);

  return counts;
}
Example #3
Source File: useBlockTime.ts    From subscan-multisig-react with Apache License 2.0 6 votes vote down vote up
export function useBlockTime(blocks = BN_ONE, apiOverride?: ApiPromise | null): Result {
  const { t } = useTranslation();
  const { api } = useApi();

  // eslint-disable-next-line
  return useMemo((): Result => {
    const a = apiOverride || api;
    const blockTime =
      a.consts.babe?.expectedBlockTime ||
      a.consts.difficulty?.targetBlockTime ||
      // eslint-disable-next-line no-magic-numbers
      (a.consts.timestamp?.minimumPeriod as unknown as BN).muln(2) ||
      DEFAULT_TIME;
    const value = (blockTime as unknown as BN).mul(blocks).toNumber();
    const prefix = value < 0 ? '+' : '';
    const time = extractTime(Math.abs(value));
    const { days, hours, minutes, seconds } = time;
    const timeStr = [
      days ? (days > 1 ? t<string>('{{days}} days', { replace: { days } }) : t<string>('1 day')) : null,
      hours ? (hours > 1 ? t<string>('{{hours}} hrs', { replace: { hours } }) : t<string>('1 hr')) : null,
      minutes ? (minutes > 1 ? t<string>('{{minutes}} mins', { replace: { minutes } }) : t<string>('1 min')) : null,
      seconds ? (seconds > 1 ? t<string>('{{seconds}} s', { replace: { seconds } }) : t<string>('1 s')) : null,
    ]
      // eslint-disable-next-line @typescript-eslint/no-shadow
      .filter((value): value is string => !!value)
      // eslint-disable-next-line no-magic-numbers
      .slice(0, 2)
      .join(' ');

    return [(blockTime as unknown as BN).toNumber(), `${prefix}${timeStr}`, time];
  }, [api, apiOverride, blocks, t]);
}
Example #4
Source File: StakingUnbonding.tsx    From subscan-multisig-react with Apache License 2.0 6 votes vote down vote up
function extractTotals(
  stakingInfo?: DeriveStakingAccount,
  progress?: DeriveSessionProgress
): [[DeriveUnlocking, BN, BN][], BN] {
  if (!stakingInfo?.unlocking || !progress) {
    return [[], BN_ZERO];
  }

  const mapped = stakingInfo.unlocking
    .filter(({ remainingEras, value }) => value.gt(BN_ZERO) && remainingEras.gt(BN_ZERO))
    .map((unlock): [DeriveUnlocking, BN, BN] => [
      unlock,
      unlock.remainingEras,
      unlock.remainingEras.sub(BN_ONE).imul(progress.eraLength).iadd(progress.eraLength).isub(progress.eraProgress),
    ]);
  // eslint-disable-next-line @typescript-eslint/no-shadow
  const total = mapped.reduce((total, [{ value }]) => total.iadd(value), new BN(0));

  return [mapped, total];
}
Example #5
Source File: referendumApproxChanges.ts    From sdk with Apache License 2.0 6 votes vote down vote up
/**
 * This is where we tweak the input values, based on what was specified, be it the input number
 * or the direction and turnout adjustments
 *
 * @param votes The votes that should be adjusted, will be either aye/nay
 * @param total The actual total of applied votes (same as turnout from derived)
 * @param change The actual change value we want to affect
 * @param inc The increment to apply here
 * @param totalInc The increment for the total. 0 for conviction-only changes, 1 of 1x added conviction vote
 * @param direction The direction, either increment (1) or decrement (-1)
 */
function getDiffs(
  votes: BN,
  total: BN,
  change: BN,
  inc: BN,
  totalInc: 0 | 0.1 | 1,
  direction: 1 | -1
): [BN, BN, BN] {
  // setup
  const multiplier = direction === 1 ? BN_ONE : ONEMIN;
  const voteChange = change.add(inc);

  // since we allow 0.1 as well, we first multiply by 10, before dividing by the same
  const totalChange = BN_ONE.muln(totalInc * 10)
    .mul(voteChange)
    .div(BN_TEN);

  // return the change, vote with change applied and the total with the same. For the total we don't want
  // to go negative (total votes/turnout), since will do sqrt on it (and negative is non-sensical anyway)
  return [
    voteChange,
    votes.add(multiplier.mul(voteChange)),
    BN.max(BN_ZERO, total.add(multiplier.mul(totalChange))),
  ];
}
Example #6
Source File: index.ts    From sdk with Apache License 2.0 6 votes vote down vote up
function _extractUnbondings(stakingInfo: any, progress: any) {
  if (!stakingInfo?.unlocking || !progress) {
    return { mapped: [], total: BN_ZERO };
  }

  const mapped = stakingInfo.unlocking
    .filter(
      ({ remainingEras, value }) =>
        value.gt(BN_ZERO) && remainingEras.gt(BN_ZERO)
    )
    .map((unlock: any) => [
      unlock,
      unlock.remainingEras
        .sub(BN_ONE)
        .imul(progress.eraLength)
        .iadd(progress.eraLength)
        .isub(progress.eraProgress)
        .toNumber(),
    ]);
  const total = mapped.reduce(
    (total: BN, [{ value }]) => total.iadd(value),
    new BN(0)
  );

  return {
    mapped: mapped.map((i: any) => [
      formatBalance(i[0].value, { forceUnit: "-", withSi: false }),
      i[1],
    ]),
    total,
  };
}
Example #7
Source File: index.ts    From sdk with Apache License 2.0 6 votes vote down vote up
/**
 * Query all validators info.
 */
async function querySortedTargets(api: ApiPromise) {
 const data = await Promise.all([
  api.query.staking.historyDepth(),
  api.query.balances.totalIssuance(),
  api.derive.staking.electedInfo({withExposure: true, withPrefs: true}),
  api.derive.staking.waitingInfo({withPrefs: true}),
  api.derive.session.info(),
  api.query.staking.minNominatorBond(),
  api.query.staking.counterForNominators(),
  api.derive.session.indexes().then(({ activeEra }) => activeEra.gt(BN_ZERO) ? activeEra.sub(BN_ONE) : undefined).then(lastEra => api.query.staking.erasValidatorReward([lastEra])),
 ]);
 
 const partial = data[1] && data[2] && data[3] && data[4]
 ? _extractTargetsInfo(api, data[2], data[3], data[1] as any, _transfromEra(data[4]), data[0] as any)
 : {};
 return { inflation: { inflation: 0, stakedReturn: 0 }, medianComm: 0, ...partial, minNominatorBond: data[5], counterForNominators: data[6], lastReward: data[7] };
}
Example #8
Source File: parachain.ts    From sdk with Apache License 2.0 6 votes vote down vote up
/**
 * query winners info of active auction.
 */
 async function queryAuctionWithWinners(api: ApiPromise) {
  const minContribution = api.consts.crowdloan.minContribution as BlockNumber;
  const ranges = _getLeaseRanges(api);
  const [bestNumber, auctionInfo, fundData, leasesData, initialEntries] = await Promise.all([
    api.derive.chain.bestNumber(),
    _queryAuctionInfo(api),
    api.query.crowdloan.funds.entries(),
    api.query.slots.leases.entries(),
    api.query.auctions?.winning.entries()
  ]);

  const leases = leasesData.map(([paraId]) => paraId.toHuman()[0].replace(/,/g, ""));
  const funds = fundData.map(([paraId, info]) => _updateFund(bestNumber, minContribution, {info: (info as any).unwrapOr(null), paraId: paraId.toHuman()[0].replace(/,/g, "")}, leases)).filter(i => !!i);
  const loans = _getCrowdloanBids(auctionInfo, funds, new BN(ranges[ranges.length - 1][1]));

  const winningData = _extractData(ranges, auctionInfo, initialEntries);
  return {
    auction: !!auctionInfo.leasePeriod ? {
      ...auctionInfo,
      bestNumber: bestNumber.toString(),
      leasePeriod: auctionInfo.leasePeriod.toNumber(),
      leaseEnd: auctionInfo.leasePeriod.add(api.consts.auctions.leasePeriodsPerSlot as u32).isub(BN_ONE).toNumber()
    } : {},
    funds,
    winners: _mergeCrowdLoanBids(winningData[0]?.winners || [], loans || []),
  };
}
Example #9
Source File: useBlockTime.ts    From contracts-ui with GNU General Public License v3.0 6 votes vote down vote up
useBlockTime = (
  blocks: number | BN = BN_ONE,
  apiOverride?: ApiPromise | null
): Result => {
  const { api } = useApi();

  return useMemo((): Result => {
    const a = apiOverride || api;
    const blockTime = blockTimeMs(a);
    const value = blockTime.mul(bnToBn(blocks)).toNumber();
    const time = extractTime(Math.abs(value));
    const { days, hours, minutes, seconds } = time;
    const timeStr = [
      days ? (days > 1 ? `${days} days` : '1 day') : null,
      hours ? (hours > 1 ? `${hours} hours` : '1 hr') : null,
      minutes ? (minutes > 1 ? `${minutes} mins` : '1 min') : null,
      seconds ? (seconds > 1 ? `${seconds} s` : '1 s') : null,
    ]
      .filter((s): s is string => !!s)
      .slice(0, 2)
      .join(' ');

    return [blockTime.toNumber(), `${value < 0 ? '+' : ''}${timeStr}`, time];
  }, [api, apiOverride, blocks]);
}
Example #10
Source File: useBlockTime.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
export function useBlockTime (blocks = BN_ONE, apiOverride?: ApiPromise): Result {
  const { t } = useTranslation();
  const { api } = useApi();

  return useMemo(
    (): Result => {
      const a = apiOverride || api;
      const blockTime = (
        a.consts.babe?.expectedBlockTime ||
        a.consts.difficulty?.targetBlockTime ||
        a.consts.timestamp?.minimumPeriod.muln(2) ||
        DEFAULT_TIME
      );
      const value = blockTime.mul(blocks).toNumber();
      const prefix = value < 0 ? '+' : '';
      const time = extractTime(Math.abs(value));
      const { days, hours, minutes, seconds } = time;
      const timeStr = [
        days ? (days > 1) ? t<string>('{{days}} days', { replace: { days } }) : t<string>('1 day') : null,
        hours ? (hours > 1) ? t<string>('{{hours}} hrs', { replace: { hours } }) : t<string>('1 hr') : null,
        minutes ? (minutes > 1) ? t<string>('{{minutes}} mins', { replace: { minutes } }) : t<string>('1 min') : null,
        seconds ? (seconds > 1) ? t<string>('{{seconds}} s', { replace: { seconds } }) : t<string>('1 s') : null
      ]
        .filter((value): value is string => !!value)
        .slice(0, 2)
        .join(' ');

      return [
        blockTime.toNumber(),
        `${prefix}${timeStr}`,
        time
      ];
    },
    [api, apiOverride, blocks, t]
  );
}
Example #11
Source File: StakingUnbonding.tsx    From crust-apps with Apache License 2.0 6 votes vote down vote up
function extractTotals (stakingInfo?: DeriveStakingAccount, progress?: DeriveSessionProgress): [[DeriveUnlocking, BN, BN][], BN] {
  if (!stakingInfo?.unlocking || !progress) {
    return [[], BN_ZERO];
  }

  const mapped = stakingInfo.unlocking
    .filter(({ remainingEras, value }) => value.gt(BN_ZERO) && remainingEras.gt(BN_ZERO))
    .map((unlock): [DeriveUnlocking, BN, BN] => [
      unlock,
      unlock.remainingEras,
      unlock.remainingEras
        .sub(BN_ONE)
        .imul(progress.eraLength)
        .iadd(progress.eraLength)
        .isub(progress.eraProgress)
    ]);
  const total = mapped.reduce((total, [{ value }]) => total.iadd(value), new BN(0));

  return [mapped, total];
}
Example #12
Source File: util.tsx    From crust-apps with Apache License 2.0 6 votes vote down vote up
export function createErasString (eras: BN[]): React.ReactNode {
  if (!eras.length) {
    return '';
  }

  const parts = eras
    .sort((a, b) => a.cmp(b))
    .reduce((result: (BN | [BN, BN])[], era): (BN | [BN, BN])[] => {
      if (result.length === 0) {
        return [era];
      } else {
        const last = result[result.length - 1];

        if (isSingle(last)) {
          if (last.add(BN_ONE).eq(era)) {
            result[result.length - 1] = [last, era];
          } else {
            result.push(era);
          }
        } else {
          if (last[1].add(BN_ONE).eq(era)) {
            last[1] = era;
          } else {
            result.push(era);
          }
        }
      }

      return result;
    }, [])
    .map((entry) =>
      isSingle(entry)
        ? formatNumber(entry)
        : `${formatNumber(entry[0])}-${formatNumber(entry[1])}`
    );

  return (
    <>
      {parts.map((section, index) => (
        <React.Fragment key={section}>
          {index !== 0 && ', '}
          <span>{section}</span>
        </React.Fragment>
      ))}
    </>
  );
}
Example #13
Source File: useEraBlocks.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
export default function useEraBlocks (era?: BN): BN | undefined {
  const { api } = useApi();
  const depth = useCall<BN>(api.query.staking.historyDepth);
  const progress = useCall<DeriveSessionProgress>(api.derive.session.progress);
  const forcing = useCall<Forcing>(api.query.staking.forceEra);

  return useMemo(
    () => (depth && era && forcing && progress && progress.sessionLength.gt(BN_ONE))
      ? (
        forcing.isForceAlways
          ? progress.sessionLength
          : progress.eraLength
      ).mul(
        depth
          .sub(progress.activeEra)
          .iadd(era)
          .iadd(BN_ONE)
      ).isub(
        forcing.isForceAlways
          ? progress.sessionProgress
          : progress.eraProgress
      )
      : undefined,
    [depth, era, forcing, progress]
  );
}
Example #14
Source File: useUnbondDuration.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
export default function useUnbondDuration (): BN | undefined {
  const { api } = useApi();
  const sessionInfo = useCall<DeriveSessionInfo>(api.derive.session.info);

  return useMemo(
    () => (sessionInfo && sessionInfo.sessionLength.gt(BN_ONE))
      ? sessionInfo.eraLength.mul(api.consts.staking.bondingDuration)
      : undefined,
    [api, sessionInfo]
  );
}
Example #15
Source File: useInfo.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
optGiltInfo = {
  defaultValue: {} as GiltInfo,
  transform: ([activeTotal, queueTotals]: [ActiveGiltsTotal, [u32, BalanceOf][]]): GiltInfo => ({
    activeIndex: activeTotal.index.isZero()
      ? null
      : activeTotal.index.sub(BN_ONE),
    activeTotal,
    queueTotals: queueTotals
      .map(([numItems, balance], index): QueueTotal => ({ balance, index: index + 1, numItems }))
      .filter(({ balance }) => !balance.isZero())
  })
}
Example #16
Source File: useScheduled.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
function createReferendums (bestNumber: BlockNumber, blockTime: number, referendums: DeriveReferendumExt[]): [EntryType, EntryInfo[]][] {
  return referendums.reduce((result: [EntryType, EntryInfo[]][], { index, status }): [EntryType, EntryInfo[]][] => {
    const enactBlocks = status.end.add(status.delay).isub(bestNumber);
    const voteBlocks = status.end.sub(bestNumber).isub(BN_ONE);

    result.push(['referendumVote', [{
      ...newDate(voteBlocks, blockTime),
      blockNumber: bestNumber.add(voteBlocks),
      blocks: voteBlocks,
      info: index
    }]]);
    result.push(['referendumDispatch', [{
      ...newDate(enactBlocks, blockTime),
      blockNumber: bestNumber.add(enactBlocks),
      blocks: enactBlocks,
      info: index,
      isPending: true
    }]]);

    return result;
  }, []);
}
Example #17
Source File: useScheduled.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
function createStakingInfo (bestNumber: BlockNumber, blockTime: number, sessionInfo: DeriveSessionProgress, unapplied: SlashEntry[], slashDeferDuration?: BlockNumber): [EntryType, EntryInfo[]][] {
  const blocksEra = sessionInfo.eraLength.sub(sessionInfo.eraProgress);
  const blocksSes = sessionInfo.sessionLength.sub(sessionInfo.sessionProgress);
  const slashDuration = slashDeferDuration?.mul(sessionInfo.eraLength);
  const slashEras = slashDuration
    ? unapplied
      .filter(([, values]) => values.length)
      .map(([key]): EntryInfo => {
        const eraIndex = key.args[0];
        const blockProgress = sessionInfo.activeEra.sub(eraIndex).isub(BN_ONE).imul(sessionInfo.eraLength).iadd(sessionInfo.eraProgress);
        const blocks = slashDuration.sub(blockProgress);

        return {
          ...newDate(blocks, blockTime),
          blockNumber: bestNumber.add(blocks),
          blocks,
          info: eraIndex
        };
      })
    : [];

  return [
    ['stakingEpoch', [{
      ...newDate(blocksSes, blockTime),
      blockNumber: bestNumber.add(blocksSes),
      blocks: blocksSes,
      info: sessionInfo.currentIndex.add(BN_ONE)
    }]],
    ['stakingEra', [{
      ...newDate(blocksEra, blockTime),
      blockNumber: bestNumber.add(blocksEra),
      blocks: blocksEra,
      info: sessionInfo.activeEra.add(BN_ONE)
    }]],
    ['stakingSlash', slashEras]
  ];
}
Example #18
Source File: Summary.tsx    From crust-apps with Apache License 2.0 5 votes vote down vote up
function Summary ({ referendumCount }: Props): React.ReactElement<Props> {
  const { t } = useTranslation();
  const { api } = useApi();
  const activeProposals = useCall<unknown[]>(api.derive.democracy.proposals);
  const bestNumber = useBestNumber();
  const [publicPropCount, referendumTotal] = useCallMulti<[BN | undefined, BN | undefined]>([
    api.query.democracy.publicPropCount,
    api.query.democracy.referendumCount
  ], optMulti);

  return (
    <SummaryBox>
      <section>
        <CardSummary label={t<string>('proposals')}>
          {formatNumber(activeProposals?.length)}
        </CardSummary>
        <CardSummary label={t<string>('total')}>
          {formatNumber(publicPropCount)}
        </CardSummary>
      </section>
      <section>
        <CardSummary label={t<string>('referenda')}>
          {formatNumber(referendumCount || 0)}
        </CardSummary>
        <CardSummary label={t<string>('total')}>
          {formatNumber(referendumTotal || 0)}
        </CardSummary>
      </section>
      {bestNumber && (
        <section className='media--1100'>
          <CardSummary
            label={t<string>('launch period')}
            progress={{
              total: api.consts.democracy.launchPeriod,
              value: bestNumber.mod(api.consts.democracy.launchPeriod).iadd(BN_ONE),
              withTime: true
            }}
          />
        </section>
      )}
    </SummaryBox>
  );
}
Example #19
Source File: Info.tsx    From crust-apps with Apache License 2.0 5 votes vote down vote up
function Info ({ assetIds, className = '', defaultValue, onChange }: Props): React.ReactElement<Props> {
  const { t } = useTranslation();
  const { api } = useApi();
  const [initial] = useState(() => defaultValue);
  const [initialId] = useState(() => findAvailbleId(assetIds));
  const [accountId, setAccountId] = useState<string | null>(null);
  const [assetId, setAssetId] = useState<BN | null>(null);
  const [minBalance, setMinBalance] = useState<BN | null>(null);

  const isIdValid = useMemo(
    () => !!assetId && assetId.gt(BN_ZERO) && !assetIds.some((a) => a.eq(assetId)),
    [assetId, assetIds]
  );

  useEffect((): void => {
    onChange(
      assetId && accountId && minBalance && isIdValid && !minBalance.isZero()
        ? { accountId, assetId, createTx: api.tx.assets.create(assetId, accountId, minBalance), minBalance }
        : null
    );
  }, [api, accountId, assetId, assetIds, isIdValid, minBalance, onChange]);

  return (
    <Modal.Content className={className}>
      <Modal.Columns hint={t<string>('The account that is to be used to create this asset and setup the initial metadata.')}>
        <InputAddress
          defaultValue={initial?.accountId}
          label={t<string>('creator account')}
          onChange={setAccountId}
          type='account'
        />
      </Modal.Columns>
      <Modal.Columns hint={t<string>('The selected id for the asset. This should not match an already-existing asset id.')}>
        <InputNumber
          autoFocus
          defaultValue={initial?.assetId || initialId}
          isError={!isIdValid}
          isZeroable={false}
          label={t<string>('asset id')}
          onChange={setAssetId}
        />
      </Modal.Columns>
      <Modal.Columns hint={t<string>('The minimum balance for the asset.')}>
        <InputNumber
          defaultValue={initial?.minBalance || BN_ONE}
          isZeroable={false}
          label={t<string>('minimum balance')}
          onChange={setMinBalance}
        />
      </Modal.Columns>
    </Modal.Content>
  );
}
Example #20
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 #21
Source File: InputNumber.tsx    From subscan-multisig-react with Apache License 2.0 5 votes vote down vote up
function getGlobalMaxValue(bitLength?: number): BN {
  return BN_TWO.pow(new BN(bitLength || DEFAULT_BITLENGTH)).isub(BN_ONE);
}
Example #22
Source File: useScheduled.ts    From crust-apps with Apache License 2.0 5 votes vote down vote up
// TODO council votes, tips closing
export default function useScheduled (): EntryInfo[] {
  const { api } = useApi();
  const [blockTime] = useBlockTime();
  const bestNumber = useBestNumber();
  const councilMotions = useCall<DeriveCollectiveProposal[]>(api.derive.council?.proposals);
  const dispatches = useCall<DeriveDispatch[]>(api.derive.democracy?.dispatchQueue);
  const referendums = useCall<DeriveReferendumExt[]>(api.derive.democracy?.referendums);
  const scheduled = useCall<ScheduleEntry[]>(api.query.scheduler?.agenda?.entries);
  const sessionInfo = useCall<DeriveSessionProgress>(api.query.staking && api.derive.session?.progress);
  const slashes = useCall<SlashEntry[]>(api.query.staking?.unappliedSlashes.entries);
  const [state, setState] = useState<EntryInfoTyped[]>([]);

  useEffect((): void => {
    bestNumber && dispatches && setState((state) =>
      addFiltered(state, createDispatches(bestNumber, blockTime, dispatches))
    );
  }, [bestNumber, blockTime, dispatches]);

  useEffect((): void => {
    bestNumber && councilMotions && setState((state) =>
      addFiltered(state, createCouncilMotions(bestNumber, blockTime, councilMotions))
    );
  }, [bestNumber, blockTime, councilMotions]);

  useEffect((): void => {
    bestNumber && referendums && setState((state) =>
      addFiltered(state, createReferendums(bestNumber, blockTime, referendums))
    );
  }, [bestNumber, blockTime, referendums]);

  useEffect((): void => {
    bestNumber && scheduled && setState((state) =>
      addFiltered(state, createScheduled(bestNumber, blockTime, scheduled))
    );
  }, [bestNumber, blockTime, scheduled]);

  useEffect((): void => {
    bestNumber && sessionInfo?.sessionLength.gt(BN_ONE) && slashes && setState((state) =>
      addFiltered(state, createStakingInfo(bestNumber, blockTime, sessionInfo, slashes, api.consts.staking.slashDeferDuration))
    );
  }, [api, bestNumber, blockTime, sessionInfo, slashes]);

  useEffect((): void => {
    bestNumber && setState((state) =>
      addFiltered(state, createConstDurations(bestNumber, blockTime, [
        ['councilElection', (api.consts.elections || api.consts.electionsPhragmen)?.termDuration],
        ['democracyLaunch', api.consts.democracy?.launchPeriod],
        ['societyChallenge', api.consts.society?.challengePeriod],
        ['societyRotate', api.consts.society?.rotationPeriod],
        ['treasurySpend', api.consts.treasury?.spendPeriod]
      ]))
    );
  }, [api, bestNumber, blockTime]);

  return state;
}
Example #23
Source File: Call.tsx    From crust-apps with Apache License 2.0 5 votes vote down vote up
MAX_CALL_WEIGHT = new BN(5_000_000_000_000).isub(BN_ONE)
Example #24
Source File: index.ts    From sdk with Apache License 2.0 5 votes vote down vote up
function _extractSingleTarget (api: ApiPromise, derive: DeriveStakingElected | DeriveStakingWaiting, { activeEra, eraLength, lastEra, sessionLength }: LastEra, historyDepth?: BN): [any[], string[]] {
  const nominators: Record<string, boolean> = {};
  const emptyExposure = api.createType('Exposure');
  const earliestEra = historyDepth && lastEra.sub(historyDepth).iadd(BN_ONE);
  const list = derive.info.map(({ accountId, exposure = emptyExposure, stakingLedger, validatorPrefs }): any => {
    // some overrides (e.g. Darwinia Crab) does not have the own/total field in Exposure
    let [bondOwn, bondTotal] = exposure.total
      ? [exposure.own.unwrap(), exposure.total.unwrap()]
      : [BN_ZERO, BN_ZERO];
    const skipRewards = bondTotal.isZero();
    // some overrides (e.g. Darwinia Crab) does not have the value field in IndividualExposure
    const minNominated = (exposure.others || []).reduce((min: BN, { value = api.createType('Compact<Balance>') }): BN => {
      const actual = value.unwrap();

      return min.isZero() || actual.lt(min)
        ? actual
        : min;
    }, BN_ZERO);

    if (bondTotal.isZero()) {
      bondTotal = bondOwn = stakingLedger.total.unwrap();
    }

    const key = accountId.toString();
    const lastEraPayout = !lastEra.isZero()
      ? stakingLedger.claimedRewards[stakingLedger.claimedRewards.length - 1]
      : undefined;

    // only use if it is more recent than historyDepth
    let lastPayout: BN | undefined = earliestEra && lastEraPayout && lastEraPayout.gt(earliestEra)
      ? lastEraPayout
      : undefined;

    if (lastPayout && !sessionLength.eq(BN_ONE)) {
      lastPayout = lastEra.sub(lastPayout).mul(eraLength);
    }

    return {
      accountId,
      bondOther: bondTotal.sub(bondOwn),
      bondOwn,
      bondShare: 0,
      bondTotal,
      commissionPer: validatorPrefs.commission.unwrap().toNumber() / 10_000_000,
      exposure,
      isActive: !skipRewards,
      isBlocking: !!(validatorPrefs.blocked && validatorPrefs.blocked.isTrue),
      isElected: !_isWaitingDerive(derive) && derive.nextElected.some((e) => e.eq(accountId)),
      key,
      knownLength: activeEra.sub(stakingLedger.claimedRewards[0] || activeEra),
      lastPayout,
      minNominated,
      numNominators: (exposure.others || []).length,
      numRecentPayouts: earliestEra
        ? stakingLedger.claimedRewards.filter((era) => era.gte(earliestEra)).length
        : 0,
      rankBondOther: 0,
      rankBondOwn: 0,
      rankBondTotal: 0,
      rankNumNominators: 0,
      rankOverall: 0,
      rankReward: 0,
      skipRewards,
      stakedReturn: 0,
      stakedReturnCmp: 0
    };
  });

  return [list, Object.keys(nominators)];
}
Example #25
Source File: InputMegaGas.tsx    From crust-apps with Apache License 2.0 5 votes vote down vote up
function InputMegaGas ({ className, estimatedWeight, help, isCall, weight: { executionTime, isValid, megaGas, percentage, setIsEmpty, setMegaGas } }: Props): React.ReactElement<Props> {
  const { t } = useTranslation();
  const [withEstimate, setWithEstimate] = useState(true);

  const estimatedMg = useMemo(
    () => estimatedWeight
      ? estimatedWeight.div(BN_MILLION).iadd(BN_ONE)
      : null,
    [estimatedWeight]
  );

  useEffect((): void => {
    withEstimate && estimatedMg && setMegaGas(estimatedMg);
  }, [estimatedMg, setMegaGas, withEstimate]);

  useEffect((): void => {
    setIsEmpty(withEstimate && !!isCall);
  }, [isCall, setIsEmpty, withEstimate]);

  const isDisabled = !!estimatedMg && withEstimate;

  return (
    <div className={className}>
      <InputNumber
        defaultValue={estimatedMg && isDisabled ? estimatedMg.toString() : undefined}
        help={help}
        isDisabled={isDisabled}
        isError={!isValid}
        isZeroable={isCall}
        label={
          estimatedMg && (isCall ? !withEstimate : true)
            ? t<string>('max gas allowed (M, {{estimatedMg}} estimated)', { replace: { estimatedMg: estimatedMg.toString() } })
            : t<string>('max gas allowed (M)')
        }
        onChange={isDisabled ? undefined : setMegaGas}
        value={isDisabled ? undefined : ((isCall && withEstimate) ? BN_ZERO : megaGas)}
      >
        {(estimatedWeight || isCall) && (
          <Toggle
            isOverlay
            label={
              isCall
                ? t<string>('max read gas')
                : t<string>('use estimated gas')
            }
            onChange={setWithEstimate}
            value={withEstimate}
          />
        )}
      </InputNumber>
      <div className='contracts--InputMegaGas-meter'>
        {t<string>('{{executionTime}}s execution time', { replace: { executionTime: executionTime.toFixed(3) } })}{', '}
        {t<string>('{{percentage}}% of block weight', { replace: { percentage: percentage.toFixed(2) } })}
      </div>
    </div>
  );
}
Example #26
Source File: useBalance.ts    From contracts-ui with GNU General Public License v3.0 5 votes vote down vote up
function getGlobalMaxValue(bitLength?: number): BN {
  return BN_TWO.pow(new BN(bitLength || DEFAULT_BITLENGTH)).isub(BN_ONE);
}
Example #27
Source File: InputGas.tsx    From contracts-ui with GNU General Public License v3.0 5 votes vote down vote up
export function InputGas({
  className,
  defaultWeight,
  estimatedWeight,
  executionTime,
  isActive,
  isCall,
  isValid,
  megaGas,
  percentage,
  setIsActive,
  setMegaGas,
  weight,
  withEstimate,
  ...props
}: Props) {
  return (
    <div className={classes(className)} {...props}>
      <InputNumber
        value={megaGas}
        isDisabled={!isActive}
        onChange={value => {
          if (isActive) {
            setMegaGas(value);
          }
        }}
        placeholder="MGas"
      />
      <Meter
        accessory={
          isActive ? (
            <a
              href="#"
              onClick={e => {
                e.preventDefault();

                setIsActive(false);
              }}
              className="text-green-500"
            >
              {isCall
                ? `Use Estimated Gas (${(estimatedWeight || BN_ZERO)
                    .div(BN_MILLION)
                    .add(BN_ONE)
                    .toString()}M)`
                : 'Use Maximum Query Gas'}
            </a>
          ) : (
            <>
              {isCall ? 'Using Estimated Gas' : 'Using Maximum Query Gas'}
              &nbsp;{' ยท '}&nbsp;
              <a
                href="#"
                onClick={e => {
                  e.preventDefault();

                  setIsActive(true);
                }}
                className="text-green-500"
              >
                Use Custom
              </a>
            </>
          )
        }
        label={`${
          executionTime < 0.001 ? '<0.001' : executionTime.toFixed(3)
        }s execution time (${percentage.toFixed(2)}% of block time)}`}
        percentage={percentage}
        withAccessory={withEstimate}
      />
    </div>
  );
}
Example #28
Source File: useWinningData.ts    From crust-apps with Apache License 2.0 5 votes vote down vote up
export default function useWinningData (auctionInfo: [LeasePeriodOf, BlockNumber] | null): Winning[] | null {
  const { api } = useApi();
  const [result, setResult] = useState<Winning[] | null>(null);
  const bestNumber = useBestNumber();
  const trigger = useEventTrigger([api.events.auctions?.BidAccepted]);
  const triggerRef = useRef(trigger);
  const allEntries = useCall<[StorageKey<[BlockNumber]>, Option<WinningData>][]>(api.query.auctions?.winning.entries);
  const optFirstData = useCall<Option<WinningData>>(api.query.auctions?.winning, FIRST_PARAM);

  // should be fired once, all entries as an initial round
  useEffect((): void => {
    allEntries && setResult(
      extractData(auctionInfo && auctionInfo[1], allEntries)
    );
  }, [allEntries, auctionInfo]);

  // when block 0 changes, update (typically in non-ending-period, static otherwise)
  useEffect((): void => {
    optFirstData && setResult((prev) =>
      mergeFirst(prev, optFirstData)
    );
  }, [optFirstData]);

  // on a bid event, get the new entry (assuming the event really triggered, i.e. not just a block)
  // and add it to the list when not duplicated. Additionally we cleanup after ourselves when endBlock
  // gets cleared
  useEffect((): void => {
    const [, endBlock] = auctionInfo || [null, null];

    if (!endBlock) {
      setResult((prev) => prev && prev.length ? [] : prev);
    } else if (bestNumber && bestNumber.gt(endBlock) && triggerRef.current !== trigger) {
      const blockOffset = bestNumber.sub(endBlock).iadd(BN_ONE);

      triggerRef.current = trigger;

      api.query.auctions
        ?.winning<Option<WinningData>>(blockOffset)
        .then((optCurrent) => setResult((prev) =>
          mergeCurrent(prev, optCurrent, endBlock, blockOffset)
        ))
        .catch(console.error);
    }
  }, [api, bestNumber, auctionInfo, trigger, triggerRef]);

  return result;
}
Example #29
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;
}