From a23b3f953b2c650d99ff0986b1e01942c3ccd3d9 Mon Sep 17 00:00:00 2001 From: Jaco Date: Fri, 25 Feb 2022 11:40:35 +0100 Subject: [PATCH] Retrieve named reserves (#4602) --- CHANGELOG.md | 1 + packages/api-derive/src/balances/all.ts | 79 +++++++++++++++-------- packages/api-derive/src/balances/types.ts | 3 +- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2565d36410..a6566e6603 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Changes: - Ensure `BTreeSet` has the correct decoded length - Attach `PortableRegistry` at point of metadata set - Add `derive.chain.getBlockByNumber` +- Retrieve named reserves in `derive.balances.all` - Ensure `v13 -> v14` metadata conversion attaches primitives diff --git a/packages/api-derive/src/balances/all.ts b/packages/api-derive/src/balances/all.ts index 9f32a014dd..5aca46f95f 100644 --- a/packages/api-derive/src/balances/all.ts +++ b/packages/api-derive/src/balances/all.ts @@ -5,7 +5,7 @@ import type { Observable } from 'rxjs'; import type { QueryableStorageMultiArg } from '@polkadot/api-base/types'; 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 { PalletBalancesBalanceLock, PalletBalancesReserveData, PalletVestingVestingInfo } from '@polkadot/types/lookup'; import type { DeriveApi, DeriveBalancesAccount, DeriveBalancesAccountData, DeriveBalancesAll, DeriveBalancesAllAccountData, DeriveBalancesAllVesting } from '../types'; import { combineLatest, map, of, switchMap } from 'rxjs'; @@ -14,9 +14,7 @@ import { BN, BN_ZERO, bnMax, bnMin, isFunction } from '@polkadot/util'; import { memo } from '../util'; -type BalanceLocksEntry = Vec; -type BalanceLocks = BalanceLocksEntry[]; -type ResultBalance = [PalletVestingVestingInfo[] | null, ((PalletBalancesBalanceLock | BalanceLockTo212)[])[]]; +type ResultBalance = [PalletVestingVestingInfo[] | null, ((PalletBalancesBalanceLock | BalanceLockTo212)[])[], PalletBalancesReserveData[][]]; type Result = [DeriveBalancesAccount, BlockNumber, ResultBalance]; interface AllLocked { @@ -86,7 +84,9 @@ function calcVesting (bestNumber: BlockNumber, shared: DeriveBalancesAllAccountD return { isVesting, vestedBalance, - vestedClaimable: isVesting ? shared.vestingLocked.sub(vestingTotal.sub(vestedBalance)) : BN_ZERO, + vestedClaimable: isVesting + ? shared.vestingLocked.sub(vestingTotal.sub(vestedBalance)) + : BN_ZERO, vesting: vesting .map(({ locked, perBlock, startingBlock }, index) => ({ endBlock: locked.div(perBlock).iadd(startingBlock), @@ -100,7 +100,7 @@ function calcVesting (bestNumber: BlockNumber, shared: DeriveBalancesAllAccountD }; } -function calcBalances (api: DeriveApi, [data, bestNumber, [vesting, allLocks]]: Result): DeriveBalancesAll { +function calcBalances (api: DeriveApi, [data, bestNumber, [vesting, allLocks, namedReserves]]: Result): DeriveBalancesAll { const shared = calcShared(api, bestNumber, data, allLocks[0]); return { @@ -110,7 +110,8 @@ function calcBalances (api: DeriveApi, [data, bestNumber, [vesting, allLocks]]: accountNonce: data.accountNonce, additional: allLocks .filter((_, index) => index !== 0) - .map((l, index) => calcShared(api, bestNumber, data.additional[index], l)) + .map((l, index) => calcShared(api, bestNumber, data.additional[index], l)), + namedReserves }; } @@ -133,7 +134,8 @@ function queryOld (api: DeriveApi, accountId: AccountId): Observable(nullable: T): nullable is NonNullable => !!nullable; +function createCalls (accountId: AccountId, calls: unknown[]): [boolean[], QueryableStorageMultiArg<'rxjs'>[]] { + return [ + calls.map((c) => !c), + calls + .filter(isNonNullable) + .map((c) => [c, accountId] as unknown as QueryableStorageMultiArg<'rxjs'>) + ]; +} + // current (balances, vesting) function queryCurrent (api: DeriveApi, accountId: AccountId, balanceInstances: string[] = ['balances']): Observable { - const calls = balanceInstances.map((m): DeriveApi['query']['balances']['locks'] | undefined => - (api.derive as DeriveCustomLocks)[m]?.customLocks || api.query[m as 'balances']?.locks + const [lockEmpty, lockQueries] = createCalls( + accountId, + balanceInstances.map((m): DeriveApi['query']['balances']['locks'] | undefined => + (api.derive as DeriveCustomLocks)[m]?.customLocks || api.query[m as 'balances']?.locks + ) + ); + const [reserveEmpty, reserveQueries] = createCalls( + accountId, + balanceInstances.map((m): DeriveApi['query']['balances']['reserves'] | undefined => + api.query[m as 'balances']?.reserves + ) ); - const lockEmpty = calls.map((c) => !c); - const queries = calls.filter(isNonNullable).map((c): QueryableStorageMultiArg<'rxjs'> => [c, accountId]); - return ( + return combineLatest([ api.query.vesting?.vesting - ? api.queryMulti<[Option | Option>, ...BalanceLocks]>([[api.query.vesting.vesting, accountId], ...queries]) - // TODO We need to check module instances here as well, not only the balances module - : queries.length - ? api.queryMulti<[...(Vec)[]]>(queries).pipe( - map((r): [Option, ...BalanceLocks] => [api.registry.createType('Option'), ...r]) - ) - : of([api.registry.createType('Option')] as [Option]) - ).pipe( - map(([opt, ...locks]): ResultBalance => { - let offset = -1; + ? api.query.vesting.vesting(accountId) + : of(api.registry.createType('Option')), + lockQueries.length + ? api.queryMulti<[...(Vec)[]]>(lockQueries) + : of([] as Vec[]), + reserveQueries.length + ? api.queryMulti<[...(Vec)[]]>(reserveQueries) + : of([] as Vec[]) + ]).pipe( + map(([opt, locks, reserves]): ResultBalance => { + let offsetLock = -1; + let offsetReserve = -1; const vesting = opt.unwrapOr(null); return [ vesting - ? Array.isArray(vesting) ? vesting : [vesting] + ? Array.isArray(vesting) + ? vesting + : [vesting as PalletVestingVestingInfo] : null, - lockEmpty.map((e) => e ? api.registry.createType>('Vec') : locks[++offset]) + lockEmpty.map((e) => + e ? api.registry.createType>('Vec') : locks[++offsetLock] + ), + reserveEmpty.map((e) => + e ? api.registry.createType>('Vec') : reserves[++offsetReserve] + ) ]; }) ); @@ -202,7 +229,7 @@ export function all (instanceId: string, api: DeriveApi): (address: AccountIndex ? queryCurrent(api, account.accountId, balanceInstances) : queryOld(api, account.accountId) ]) - : of([account, api.registry.createType('BlockNumber'), [null, []]]) + : of([account, api.registry.createType('BlockNumber'), [null, [], []]]) ) ), map((result): DeriveBalancesAll => calcBalances(api, result)) diff --git a/packages/api-derive/src/balances/types.ts b/packages/api-derive/src/balances/types.ts index 75d4d0fb38..bbf811c18a 100644 --- a/packages/api-derive/src/balances/types.ts +++ b/packages/api-derive/src/balances/types.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import type { AccountId, Balance, BalanceLockTo212, Index } from '@polkadot/types/interfaces'; -import type { PalletBalancesBalanceLock } from '@polkadot/types/lookup'; +import type { PalletBalancesBalanceLock, PalletBalancesReserveData } from '@polkadot/types/lookup'; import type { BN } from '@polkadot/util'; export interface DeriveBalancesAccountData { @@ -44,6 +44,7 @@ export interface DeriveBalancesAllVesting { export interface DeriveBalancesAll extends DeriveBalancesAccount, DeriveBalancesAllAccountData, DeriveBalancesAllVesting { additional: DeriveBalancesAllAccountData[]; + namedReserves: PalletBalancesReserveData[][]; } export type DeriveBalancesMap = Record;