Allow for balance/indices lookups (#596)

* Allow for balance/indices lookups

* Latest metadata

* Indices work

* Update json with actual decoded

* Update Type.ts

* Some tests updated

* Update final tests

* Remove .only from derive e2e (really skip it)
This commit is contained in:
Jaco Greeff
2019-01-17 15:11:50 +01:00
committed by GitHub
parent e228fd40ab
commit a3e421f665
19 changed files with 187 additions and 219 deletions
@@ -8,14 +8,14 @@ import { ApiInterface$Rx } from '@polkadot/api/types';
import { decodeAddress } from '@polkadot/keyring';
import { AccountId, AccountIndex } from '@polkadot/types/index';
import { accountIdToIndex } from './accountIdToIndex';
import { accountIndexToId } from './accountIndexToId';
import { idToIndex } from './idToIndex';
import { indexToId } from './indexToId';
import { drr } from '../util/drr';
export type IdAndIndex = [AccountId?, AccountIndex?];
export type AccountIdAndIndex = [AccountId?, AccountIndex?];
export function accountIdAndIndex (api: ApiInterface$Rx) {
return (address?: AccountId | AccountIndex | string | null): Observable<IdAndIndex> => {
export function idAndIndex (api: ApiInterface$Rx) {
return (address?: AccountId | AccountIndex | string | null): Observable<AccountIdAndIndex> => {
try {
// yes, this can fail, don't care too much, catch will catch it
const decoded = decodeAddress(address as any);
@@ -23,20 +23,20 @@ export function accountIdAndIndex (api: ApiInterface$Rx) {
if (decoded.length === 32) {
const accountId = new AccountId(decoded);
return accountIdToIndex(api)(accountId).pipe(
map((accountIndex) => [accountId, accountIndex] as IdAndIndex),
return idToIndex(api)(accountId).pipe(
map((accountIndex) => [accountId, accountIndex] as AccountIdAndIndex),
drr()
);
}
const accountIndex = new AccountIndex(address as string);
const accountIndex = new AccountIndex(decoded);
return accountIndexToId(api)(accountIndex).pipe(
map((accountId) => [accountId, accountIndex] as IdAndIndex),
return indexToId(api)(accountIndex).pipe(
map((accountId) => [accountId, accountIndex] as AccountIdAndIndex),
drr()
);
} catch (error) {
return of([undefined, undefined] as IdAndIndex).pipe(drr());
return of([undefined, undefined] as AccountIdAndIndex).pipe(drr());
}
};
}
@@ -7,12 +7,12 @@ import { map } from 'rxjs/operators';
import { ApiInterface$Rx } from '@polkadot/api/types';
import { AccountId, AccountIndex } from '@polkadot/types/index';
import { accountIndexes, AccountIndexes } from './accountIndexes';
import { indexes, AccountIndexes } from './indexes';
import { drr } from '../util/drr';
export function accountIdToIndex (api: ApiInterface$Rx) {
export function idToIndex (api: ApiInterface$Rx) {
return (accountId: AccountId | string): Observable<AccountIndex> =>
accountIndexes(api)()
indexes(api)()
.pipe(
map((indexes: AccountIndexes) => (indexes || {})[accountId.toString()]),
drr()
@@ -0,0 +1,8 @@
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export * from './idAndIndex';
export * from './idToIndex';
export * from './indexToId';
export * from './indexes';
@@ -11,15 +11,16 @@ import { AccountId, AccountIndex } from '@polkadot/types/index';
import { drr } from '../util/drr';
export function accountIndexToId (api: ApiInterface$Rx) {
return (accountIndex: AccountIndex | string): Observable<AccountId> => {
const _accountIndex = accountIndex instanceof AccountIndex
? accountIndex
: new AccountIndex(accountIndex);
export function indexToId (api: ApiInterface$Rx) {
return (_accountIndex: AccountIndex | string): Observable<AccountId> => {
const querySection = api.query.indices || api.query.balances;
const accountIndex = _accountIndex instanceof AccountIndex
? _accountIndex
: new AccountIndex(_accountIndex);
return (api.query.balances.enumSet(accountIndex) as Observable<Vector<AccountId>>)
return (querySection.enumSet(accountIndex.div(ENUMSET_SIZE)) as Observable<Vector<AccountId>>)
.pipe(
map((accounts) => (accounts || [])[_accountIndex.mod(ENUMSET_SIZE).toNumber()]),
map((accounts) => (accounts || [])[accountIndex.mod(ENUMSET_SIZE).toNumber()]),
drr()
);
};
@@ -2,7 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import BN from 'bn.js';
import { combineLatest, Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterface$Rx } from '@polkadot/api/types';
@@ -13,17 +12,19 @@ import { drr } from '../util/drr';
export type AccountIndexes = { [index: string]: AccountIndex };
export function accountIndexes (api: ApiInterface$Rx) {
return (): Observable<AccountIndexes> =>
(api.query.balances.nextEnumSet() as Observable<AccountIndex>)
export function indexes (api: ApiInterface$Rx) {
return (): Observable<AccountIndexes> => {
const querySection = api.query.indices || api.query.balances;
return (querySection.nextEnumSet() as Observable<AccountIndex>)
.pipe(
map((next: AccountIndex) => {
const enumRange = [...Array((next || new BN(0)).div(ENUMSET_SIZE).toNumber() + 1).keys()];
const enumRange = [...Array(next.div(ENUMSET_SIZE).toNumber() + 1).keys()];
return enumRange;
}),
switchMap((enumRange) => combineLatest(
enumRange.map((index) => (api.query.balances.enumSet(index) as Observable<any>))
enumRange.map((index) => (querySection.enumSet(index) as Observable<any>))
)),
map((all: Array<Array<AccountId> | undefined>) =>
(all || []).reduce((result, list, outerIndex) => {
@@ -37,4 +38,5 @@ export function accountIndexes (api: ApiInterface$Rx) {
}, {} as AccountIndexes)),
drr()
);
};
}
@@ -2,10 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export * from './accountIdAndIndex';
export * from './accountIdToIndex';
export * from './accountIndexToId';
export * from './accountIndexes';
export * from './fees';
export * from './validatingBalance';
export * from './validatingBalances';
@@ -7,7 +7,7 @@ import { map, switchMap } from 'rxjs/operators';
import { ApiInterface$Rx } from '@polkadot/api/types';
import { AccountId, AccountIndex, Balance } from '@polkadot/types/index';
import { accountIdAndIndex } from './accountIdAndIndex';
import { idAndIndex } from '../accounts/idAndIndex';
import { DerivedBalances } from '../types';
import { drr } from '../util/drr';
@@ -15,7 +15,7 @@ const EMPTY_ACCOUNT = new AccountId(new Uint8Array(32));
export function votingBalance (api: ApiInterface$Rx) {
return (address: AccountIndex | AccountId | string): Observable<DerivedBalances> => {
return accountIdAndIndex(api)(address).pipe(
return idAndIndex(api)(address).pipe(
switchMap(([accountId]) =>
(accountId
? combineLatest(
@@ -26,9 +26,9 @@ export function votingBalance (api: ApiInterface$Rx) {
: of([undefined, undefined, undefined])
) as Observable<[AccountId?, Balance?, Balance?]>
),
map(([accountId, freeBalance = new Balance(0), reservedBalance = new Balance(0)]) => {
map(([accountId = EMPTY_ACCOUNT, freeBalance = new Balance(0), reservedBalance = new Balance(0)]) => {
return {
accountId: accountId || EMPTY_ACCOUNT,
accountId,
freeBalance,
nominatedBalance: new Balance(0),
reservedBalance,
+5 -4
View File
@@ -38,10 +38,11 @@ describe('derive', () => {
beforeAll((done) => api.isReady.subscribe(() => done()));
testFunction(api)('balances', 'accountIdAndIndex', []);
testFunction(api)('balances', 'accountIdToIndex', []);
testFunction(api)('balances', 'accountIndexes', []);
testFunction(api)('balances', 'accountIndexToId', []);
testFunction(api)('accounts', 'idAndIndex', []);
testFunction(api)('accounts', 'idToIndex', []);
testFunction(api)('accounts', 'indexes', []);
testFunction(api)('accounts', 'indexToId', []);
testFunction(api)('balances', 'fees', []);
testFunction(api)('balances', 'validatingBalance', []);
testFunction(api)('balances', 'validatingBalances', []);
+3 -1
View File
@@ -4,6 +4,7 @@
import { ApiInterface$Rx } from '@polkadot/api/types';
import * as accounts from './accounts';
import * as balances from './balances';
import * as chain from './chain';
import * as democracy from './democracy';
@@ -12,7 +13,7 @@ import * as staking from './staking';
import { cache } from './util/cache';
// Put all derived functions in an object, for easier Object.keys()-ing.
const functions = { balances, chain, democracy, session, staking };
const functions = { accounts, balances, chain, democracy, session, staking };
/**
* T represents the section here (chain, balances...), and P represents
@@ -23,6 +24,7 @@ type ReturnTypes<T extends Record<keyof T, (...args: any[]) => any>> = {
};
export interface Derive {
accounts: ReturnTypes<typeof accounts>;
balances: ReturnTypes<typeof balances>;
chain: ReturnTypes<typeof chain>;
democracy: ReturnTypes<typeof democracy>;