From d9e581fbdc35fea7b33103837a2379b337319583 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Fri, 3 May 2019 13:54:05 +0200 Subject: [PATCH] Basic same-type multi queries (#866) * Basic same-type multi queries * Remove extra map, straight to switchMap --- packages/api-derive/src/accounts/indexToId.ts | 4 +++- packages/api-derive/src/accounts/indexes.ts | 15 ++++++--------- packages/api-derive/src/balances/fees.ts | 1 + packages/api-derive/src/democracy/votes.ts | 1 + packages/api-derive/src/staking/controllers.ts | 1 + packages/api/src/Base.ts | 14 ++++++++++---- packages/api/src/types.ts | 1 + packages/api/test/e2e/promise-queries.spec.js | 15 +++++++++++++++ 8 files changed, 38 insertions(+), 14 deletions(-) diff --git a/packages/api-derive/src/accounts/indexToId.ts b/packages/api-derive/src/accounts/indexToId.ts index 83e26daa68..36e0ba1e88 100644 --- a/packages/api-derive/src/accounts/indexToId.ts +++ b/packages/api-derive/src/accounts/indexToId.ts @@ -20,7 +20,9 @@ export function indexToId (api: ApiInterface$Rx) { return (querySection.enumSet(accountIndex.div(ENUMSET_SIZE)) as Observable>) .pipe( startWith([]), - map((accounts) => (accounts || [])[accountIndex.mod(ENUMSET_SIZE).toNumber()]), + map((accounts) => + (accounts || [])[accountIndex.mod(ENUMSET_SIZE).toNumber()] + ), drr() ); }; diff --git a/packages/api-derive/src/accounts/indexes.ts b/packages/api-derive/src/accounts/indexes.ts index 0d428994d0..42746532b1 100644 --- a/packages/api-derive/src/accounts/indexes.ts +++ b/packages/api-derive/src/accounts/indexes.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { combineLatest, Observable } from 'rxjs'; +import { Observable } from 'rxjs'; import { map, switchMap } from 'rxjs/operators'; import { ApiInterface$Rx } from '@plugnet/api/types'; import { ENUMSET_SIZE } from '@plugnet/types/type/AccountIndex'; @@ -24,15 +24,12 @@ export function indexes (api: ApiInterface$Rx) { return (api.query.indices.nextEnumSet() as Observable) .pipe( // use the nextEnumSet (which is a counter of the number of sets) to construct - // a range of values to query [0, 1, 2, ...] - map((next: AccountIndex) => - [...Array(next.toNumber() + 1).keys()] + // a range of values to query [0, 1, 2, ...]. Retrieve the full enum set for the + // specific index - each query can return up to ENUMSET_SIZE (64) records, each + // containing an AccountId + switchMap((next: AccountIndex) => + api.query.indices.enumSet.multi([...Array(next.toNumber() + 1).keys()]) as Observable ), - switchMap((enumRange) => combineLatest( - // retrieve the full enum set for the specific index - each query can return - // up to ENUMSET_SIZE (64) records, each containing an AccountId - enumRange.map((index) => (api.query.indices.enumSet(index) as Observable)) - )), map((all: Array | undefined>) => (all || []).reduce((result, list, outerIndex) => { (list || []).forEach((accountId, innerIndex) => { diff --git a/packages/api-derive/src/balances/fees.ts b/packages/api-derive/src/balances/fees.ts index 91ecb6690d..49507e568d 100644 --- a/packages/api-derive/src/balances/fees.ts +++ b/packages/api-derive/src/balances/fees.ts @@ -12,6 +12,7 @@ import { drr } from '../util/drr'; export function fees (api: ApiInterface$Rx) { return (): Observable => { + // FIXME Remove fees checks, only use balances (fees is a removed module now) return (combineLatest([ api.query.balances.creationFee(), api.query.balances.existentialDeposit(), diff --git a/packages/api-derive/src/democracy/votes.ts b/packages/api-derive/src/democracy/votes.ts index 4d3c4bc29f..23abc66637 100644 --- a/packages/api-derive/src/democracy/votes.ts +++ b/packages/api-derive/src/democracy/votes.ts @@ -14,6 +14,7 @@ export function votes (api: ApiInterface$Rx) { return !accountIds || !accountIds.length ? of([]).pipe(drr()) : combineLatest( + // FIXME Convert to multi accountIds.map( (accountId) => api.query.democracy.voteOf([referendumId, accountId]) as Observable ) diff --git a/packages/api-derive/src/staking/controllers.ts b/packages/api-derive/src/staking/controllers.ts index 77f7c4f231..beb4c78967 100644 --- a/packages/api-derive/src/staking/controllers.ts +++ b/packages/api-derive/src/staking/controllers.ts @@ -11,6 +11,7 @@ import { drr } from '../util/drr'; function allBonds (api: ApiInterface$Rx, stashIds: Array) { return combineLatest( + // FIXME Convert to multi stashIds.map((id) => (api.query.staking.bonded(id) as Observable>) ) diff --git a/packages/api/src/Base.ts b/packages/api/src/Base.ts index 509e88e40b..c9fa9a2e2d 100644 --- a/packages/api/src/Base.ts +++ b/packages/api/src/Base.ts @@ -548,16 +548,22 @@ export default abstract class ApiBase implement [arg] ) as unknown as HashResult; - // FIXME as above... + decorated.key = (arg?: CodecArg): string => + u8aToHex(compactStripLength(method(arg))[1]); + + decorated.multi = (args: Array, callback?: CodecCallback): S => + onCall( + () => this._rpcRx.state.subscribeStorage(args.map((arg) => [method, arg])), + [], + callback + ) as unknown as S; + decorated.size = (arg?: CodecArg): U64Result => onCall( (arg: CodecArg) => this._rpcRx.state.getStorageSize([method, arg]), [arg] ) as unknown as U64Result; - decorated.key = (arg?: CodecArg): string => - u8aToHex(compactStripLength(method(arg))[1]); - return this.decorateFunctionMeta(method, decorated) as QueryableStorageFunction; } diff --git a/packages/api/src/types.ts b/packages/api/src/types.ts index 33f22b2894..7119bae340 100644 --- a/packages/api/src/types.ts +++ b/packages/api/src/types.ts @@ -52,6 +52,7 @@ export interface QueryableStorageFunctionBase e at: (hash: Hash | Uint8Array | string, arg?: CodecArg) => CodecResult; hash: (arg?: CodecArg) => HashResult; key: (arg?: CodecArg) => string; + multi: (args: Array, callback?: CodecCallback) => SubscriptionResult; size: (arg?: CodecArg) => U64Result; } diff --git a/packages/api/test/e2e/promise-queries.spec.js b/packages/api/test/e2e/promise-queries.spec.js index 4e58bb7fd8..b808771afe 100644 --- a/packages/api/test/e2e/promise-queries.spec.js +++ b/packages/api/test/e2e/promise-queries.spec.js @@ -78,6 +78,21 @@ describe.skip('e2e queries', () => { }); }); + it('subscribes to multiple results (freeBalance.multi)', (done) => { + api.query.balances.freeBalance.multi([ + keyring.alice.address(), + keyring.bob.address(), + keyring.ferdie.address(), + '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE' + ], (balances) => { + expect(balances).toHaveLength(4); + + console.error(balances); + + done(); + }); + }); + it('makes a query at a specific block', async () => { const header = await api.rpc.chain.getHeader(); const events = await api.query.system.events.at(header.hash);