From cb65fb450f90ea267f027bc962eb1f6d0f726e59 Mon Sep 17 00:00:00 2001 From: Jaco Date: Wed, 13 Oct 2021 16:31:41 +0300 Subject: [PATCH] Return multiple vesting schedules (#4057) * Display multiple vesting schedules * Derive with multiple vesting schedules * Update --- packages/api-derive/src/balances/all.ts | 53 +++++++++++++++-------- packages/api-derive/src/balances/types.ts | 27 ++++++++---- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/packages/api-derive/src/balances/all.ts b/packages/api-derive/src/balances/all.ts index 40f6a6b20d..4e7c415d15 100644 --- a/packages/api-derive/src/balances/all.ts +++ b/packages/api-derive/src/balances/all.ts @@ -6,11 +6,11 @@ import type { ApiInterfaceRx, QueryableStorageMultiArg } from '@polkadot/api/typ import type { Option, Vec } from '@polkadot/types'; import type { AccountId, AccountIndex, Address, Balance, BalanceLockTo212, BlockNumber, VestingSchedule } from '@polkadot/types/interfaces'; import type { PalletBalancesBalanceLock, PalletVestingVestingInfo } from '@polkadot/types/lookup'; -import type { DeriveBalancesAccount, DeriveBalancesAccountData, DeriveBalancesAll, DeriveBalancesAllAccountData } from '../types'; +import type { DeriveBalancesAccount, DeriveBalancesAccountData, DeriveBalancesAll, DeriveBalancesAllAccountData, DeriveBalancesAllVesting } from '../types'; import { combineLatest, map, of, switchMap } from 'rxjs'; -import { BN, bnMax, isFunction } from '@polkadot/util'; +import { BN, BN_ZERO, bnMax, bnMin, isFunction } from '@polkadot/util'; import { memo } from '../util'; @@ -69,29 +69,48 @@ function calcShared (api: ApiInterfaceRx, bestNumber: BlockNumber, data: DeriveB }; } -function calcBalances (api: ApiInterfaceRx, [data, bestNumber, [vesting, allLocks]]: Result): DeriveBalancesAll { - const shared = calcShared(api, bestNumber, data, allLocks[0]); +function calcVesting (bestNumber: BlockNumber, shared: DeriveBalancesAllAccountData, _vesting: PalletVestingVestingInfo[] | null): DeriveBalancesAllVesting { // Calculate the vesting balances, // - offset = balance locked at startingBlock // - perBlock is the unlock amount - const emptyVest = api.registry.createType('VestingInfo'); - const { locked: vestingTotal, perBlock, startingBlock } = vesting ? vesting[0] : emptyVest; - const isStarted = bestNumber.gt(startingBlock); - const vestedNow = isStarted ? perBlock.mul(bestNumber.sub(startingBlock)) : new BN(0); - const vestedBalance = vestedNow.gt(vestingTotal) ? vestingTotal : api.registry.createType('Balance', vestedNow); - const isVesting = isStarted && !shared.vestingLocked.isZero(); + const vesting = _vesting || []; + const isVesting = !shared.vestingLocked.isZero(); + const vestedBalances = vesting.map(({ locked, perBlock, startingBlock }) => + bestNumber.gt(startingBlock) + ? bnMin(locked, perBlock.mul(bestNumber.sub(startingBlock))) + : BN_ZERO + ); + const vestedBalance = vestedBalances.reduce((all, value) => all.iadd(value), new BN(0)); + const vestingTotal = vesting.reduce((all, { locked }) => all.iadd(locked), new BN(0)); + + return { + isVesting, + vestedBalance, + vestedClaimable: isVesting ? shared.vestingLocked.sub(vestingTotal.sub(vestedBalance)) : BN_ZERO, + vesting: vesting + .map(({ locked, perBlock, startingBlock }, index) => ({ + endBlock: locked.div(perBlock).iadd(startingBlock), + locked, + perBlock, + startingBlock, + vested: vestedBalances[index] + })) + .filter(({ locked }) => !locked.isZero()), + vestingTotal + }; +} + +function calcBalances (api: ApiInterfaceRx, [data, bestNumber, [vesting, allLocks]]: Result): DeriveBalancesAll { + const shared = calcShared(api, bestNumber, data, allLocks[0]); return { ...shared, + ...calcVesting(bestNumber, shared, vesting), accountId: data.accountId, accountNonce: data.accountNonce, - additional: allLocks.filter((_, index) => index !== 0).map((l, index) => calcShared(api, bestNumber, data.additional[index], l)), - isVesting, - vestedBalance, - vestedClaimable: api.registry.createType('Balance', isVesting ? shared.vestingLocked.sub(vestingTotal.sub(vestedBalance)) : 0), - vestingEndBlock: api.registry.createType('BlockNumber', isVesting ? vestingTotal.div(perBlock).add(startingBlock) : 0), - vestingPerBlock: perBlock, - vestingTotal + additional: allLocks + .filter((_, index) => index !== 0) + .map((l, index) => calcShared(api, bestNumber, data.additional[index], l)) }; } diff --git a/packages/api-derive/src/balances/types.ts b/packages/api-derive/src/balances/types.ts index a84b7b6c2d..5e54b0fc24 100644 --- a/packages/api-derive/src/balances/types.ts +++ b/packages/api-derive/src/balances/types.ts @@ -1,8 +1,9 @@ // Copyright 2017-2021 @polkadot/api-derive authors & contributors // SPDX-License-Identifier: Apache-2.0 -import type { AccountId, Balance, BalanceLockTo212, BlockNumber, Index } from '@polkadot/types/interfaces'; +import type { AccountId, Balance, BalanceLockTo212, Index } from '@polkadot/types/interfaces'; import type { PalletBalancesBalanceLock } from '@polkadot/types/lookup'; +import type { BN } from '@polkadot/util'; export interface DeriveBalancesAccountData { freeBalance: Balance; @@ -25,14 +26,24 @@ export interface DeriveBalancesAllAccountData extends DeriveBalancesAccountData vestingLocked: Balance; } -export interface DeriveBalancesAll extends DeriveBalancesAccount, DeriveBalancesAllAccountData { - additional: DeriveBalancesAllAccountData[]; +export interface DeriveBalancesVesting { + startingBlock: BN; + endBlock: BN; + perBlock: BN; + locked: BN; + vested: BN; +} + +export interface DeriveBalancesAllVesting { isVesting: boolean; - vestedBalance: Balance; - vestedClaimable: Balance; - vestingEndBlock: BlockNumber; - vestingPerBlock: Balance; - vestingTotal: Balance; + vestedBalance: BN; + vestedClaimable: BN; + vesting: DeriveBalancesVesting[]; + vestingTotal: BN; +} + +export interface DeriveBalancesAll extends DeriveBalancesAccount, DeriveBalancesAllAccountData, DeriveBalancesAllVesting { + additional: DeriveBalancesAllAccountData[]; } export type DeriveBalancesMap = Record;