Expose queryMulti on api (#909)
* Expose queryMulti on api * Convert contract fees to queryMulti
This commit is contained in:
@@ -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 { Observable, combineLatest } from 'rxjs';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiInterface$Rx } from '@plugnet/api/types';
|
||||
|
||||
@@ -12,12 +12,12 @@ import { drr } from '../util/drr';
|
||||
|
||||
export function fees (api: ApiInterface$Rx) {
|
||||
return (): Observable<DerivedFees> => {
|
||||
return (combineLatest([
|
||||
api.query.balances.creationFee(),
|
||||
api.query.balances.existentialDeposit(),
|
||||
api.query.balances.transactionBaseFee(),
|
||||
api.query.balances.transactionByteFee(),
|
||||
api.query.balances.transferFee()
|
||||
return (api.queryMulti([
|
||||
api.query.balances.creationFee,
|
||||
api.query.balances.existentialDeposit,
|
||||
api.query.balances.transactionBaseFee,
|
||||
api.query.balances.transactionByteFee,
|
||||
api.query.balances.transferFee
|
||||
]) as any as Observable<[BN, BN, BN, BN, BN]>).pipe(
|
||||
map(([creationFee, existentialDeposit, transactionBaseFee, transactionByteFee, transferFee]) => ({
|
||||
creationFee,
|
||||
|
||||
@@ -2,43 +2,31 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterface$Rx, QueryableStorageFunctionBase } from '@plugnet/api/types';
|
||||
import { Codec } from '@plugnet/types/types';
|
||||
import { ApiInterface$Rx } from '@plugnet/api/types';
|
||||
import { DerivedContractFees } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
// TODO The contracts API is still in flux, so some of these may disappear or re-appear or get replaced. Instead of
|
||||
// failing here, do best effort - if something does not exist, return 0 for the specific value. Should be removed
|
||||
// when actually stable and no more changes expected
|
||||
function nonexistentZero (fn: QueryableStorageFunctionBase<Observable<Codec>, Observable<Codec>>): Observable<BN> {
|
||||
return fn
|
||||
? fn() as any as Observable<BN>
|
||||
: of(new BN(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the balances for all intentions and their nominators
|
||||
* Retrieves all the contract fees
|
||||
*/
|
||||
export function fees (api: ApiInterface$Rx) {
|
||||
// TODO Once we have muti support for disjointed queries, add here (so we make a single
|
||||
// query for all these to the node).
|
||||
return (): Observable<DerivedContractFees> => {
|
||||
return (combineLatest([
|
||||
nonexistentZero(api.query.contract.callBaseFee),
|
||||
nonexistentZero(api.query.contract.contractFee),
|
||||
nonexistentZero(api.query.contract.createBaseFee),
|
||||
nonexistentZero(api.query.contract.creationFee),
|
||||
nonexistentZero(api.query.contract.rentByteFee),
|
||||
nonexistentZero(api.query.contract.rentDepositOffset),
|
||||
nonexistentZero(api.query.contract.transactionBaseFee),
|
||||
nonexistentZero(api.query.contract.transactionByteFee),
|
||||
nonexistentZero(api.query.contract.transferFee),
|
||||
nonexistentZero(api.query.contract.tombstoneDeposit)
|
||||
return (api.queryMulti([
|
||||
api.query.contract.callBaseFee,
|
||||
api.query.contract.contractFee,
|
||||
api.query.contract.createBaseFee,
|
||||
api.query.contract.creationFee,
|
||||
api.query.contract.rentByteFee,
|
||||
api.query.contract.rentDepositOffset,
|
||||
api.query.contract.transactionBaseFee,
|
||||
api.query.contract.transactionByteFee,
|
||||
api.query.contract.transferFee,
|
||||
api.query.contract.tombstoneDeposit
|
||||
]) as any as Observable<Array<BN>>).pipe(
|
||||
map(([callBaseFee, contractFee, createBaseFee, creationFee, rentByteFee, rentDepositOffset, transactionBaseFee, transactionByteFee, transferFee, tombstoneDeposit]) => {
|
||||
return {
|
||||
|
||||
@@ -6,8 +6,8 @@ import ApiPromise from '@plugnet/api/promise/Api';
|
||||
import { BlockNumber } from '@plugnet/types';
|
||||
import { WsProvider } from '@plugnet/rpc-provider';
|
||||
|
||||
// const WS = 'ws://127.0.0.1:9944/';
|
||||
const WS = 'wss://poc3-rpc.polkadot.io/';
|
||||
const WS = 'ws://127.0.0.1:9944/';
|
||||
// const WS = 'wss://poc3-rpc.polkadot.io/';
|
||||
|
||||
describe.skip('derive e2e', () => {
|
||||
let api: ApiPromise;
|
||||
@@ -39,4 +39,12 @@ describe.skip('derive e2e', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('retrieves the fees (api.queryMulti)', (done) => {
|
||||
return api.derive.balances.fees((fees) => {
|
||||
console.error('fees', JSON.stringify(fees));
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
DecoratedRpc, DecoratedRpc$Method, DecoratedRpc$Section,
|
||||
Derive, DeriveSection, HashResult, U64Result,
|
||||
OnCallDefinition, OnCallFunction,
|
||||
QueryableModuleStorage, QueryableStorage, QueryableStorageFunction,
|
||||
QueryableModuleStorage, QueryableStorage, QueryableStorageFunction, QueryableStorageMulti, QueryableStorageMultiArg, QueryableStorageMultiArgs,
|
||||
SubmittableExtrinsicFunction, SubmittableExtrinsics, SubmittableModuleExtrinsics, Signer
|
||||
} from './types';
|
||||
|
||||
@@ -59,11 +59,7 @@ try {
|
||||
* Put the `this.onCall` function of ApiRx here, because it is needed by
|
||||
* `api._rx`.
|
||||
*/
|
||||
function rxOnCall (
|
||||
method: OnCallFunction<RxResult, RxResult>,
|
||||
params: Array<CodecArg> = [],
|
||||
_callback?: CodecCallback
|
||||
): RxResult {
|
||||
function rxOnCall (method: OnCallFunction<RxResult, RxResult>, params: Array<CodecArg> = [], _callback?: CodecCallback): RxResult {
|
||||
return method(...params);
|
||||
}
|
||||
|
||||
@@ -75,6 +71,7 @@ export default abstract class ApiBase<CodecResult, SubscriptionResult> implement
|
||||
private _isReady: boolean = false;
|
||||
protected readonly _options: ApiOptions;
|
||||
private _query?: QueryableStorage<CodecResult, SubscriptionResult>;
|
||||
private _queryMulti: QueryableStorageMulti<CodecResult, SubscriptionResult>;
|
||||
private _rpc: DecoratedRpc<CodecResult, SubscriptionResult>;
|
||||
protected _rpcBase: RpcBase; // FIXME These two could be merged
|
||||
protected _rpcRx: RpcRx; // FIXME These two could be merged
|
||||
@@ -119,6 +116,8 @@ export default abstract class ApiBase<CodecResult, SubscriptionResult> implement
|
||||
this._rpcRx = new RpcRx(thisProvider);
|
||||
this._rpc = this.decorateRpc(this._rpcRx, this.onCall) as any; // FIXME 3.4.1
|
||||
this._rx.rpc = this.decorateRpc(this._rpcRx, rxOnCall);
|
||||
this._queryMulti = this.decorateMulti(this.onCall) as any; // as above :(
|
||||
this._rx.queryMulti = this.decorateMulti(rxOnCall);
|
||||
this._rx.signer = options.signer;
|
||||
|
||||
// we only re-register the types (global) if this is not a cloned instance
|
||||
@@ -222,6 +221,30 @@ export default abstract class ApiBase<CodecResult, SubscriptionResult> implement
|
||||
return this._query as QueryableStorage<CodecResult, SubscriptionResult>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Allows for the querying of multiple storage entries and the combination thereof into a single result. This is a very optimal way to make multiple queries since it only makes a single connection to the node and retrieves the data over one subscription.
|
||||
*
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* api.queryMulti(
|
||||
* [
|
||||
* // you can include the storage without any parameters
|
||||
* api.query.balances.existentialDeposit,
|
||||
* // or you can pass parameters to the storage query
|
||||
* [api.query.balances.freeBalance, '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY']
|
||||
* ],
|
||||
* ([existential, balance]) => {
|
||||
* console.log(`You have ${balance.sub(existential)} more than the existential deposit`);
|
||||
* }
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
get queryMulti (): QueryableStorageMulti<CodecResult, SubscriptionResult> {
|
||||
return this._queryMulti;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Contains all the raw rpc sections and their subsequent methods in the API as defined by the jsonrpc interface definitions. Unlike the dynamic `api.query` and `api.tx` sections, these methods are fixed (although extensible with node upgrades) and not determined by the runtime.
|
||||
*
|
||||
@@ -469,6 +492,22 @@ export default abstract class ApiBase<CodecResult, SubscriptionResult> implement
|
||||
}, {} as DecoratedRpc<C, S>);
|
||||
}
|
||||
|
||||
private decorateMulti<C, S> (onCall: OnCallDefinition<C, S>): QueryableStorageMulti<C, S> {
|
||||
return ((calls: QueryableStorageMultiArgs<C, S>, callback?: CodecCallback): S => {
|
||||
const mapped = calls.map((arg: QueryableStorageMultiArg<C, S>): [QueryableStorageFunction<CodecResult, SubscriptionResult>, ...Array<CodecArg>] =>
|
||||
Array.isArray(arg)
|
||||
? arg
|
||||
: [arg] as any
|
||||
);
|
||||
|
||||
return onCall(
|
||||
() => this._rpcRx.state.subscribeStorage(mapped),
|
||||
[],
|
||||
callback
|
||||
) as S;
|
||||
}) as QueryableStorageMulti<C, S>;
|
||||
}
|
||||
|
||||
private decorateExtrinsics<C, S> (extrinsics: ModulesWithMethods, onCall: OnCallDefinition<C, S>): SubmittableExtrinsics<C, S> {
|
||||
return Object.keys(extrinsics).reduce((result, sectionName) => {
|
||||
const section = extrinsics[sectionName];
|
||||
|
||||
@@ -70,6 +70,25 @@ export interface QueryableModuleStorage<CodecResult, SubscriptionResult> {
|
||||
[index: string]: QueryableStorageFunction<CodecResult, SubscriptionResult>;
|
||||
}
|
||||
|
||||
export type QueryableStorageMultiArg<CodecResult, SubscriptionResult> =
|
||||
QueryableStorageFunction<CodecResult, SubscriptionResult> |
|
||||
[QueryableStorageFunction<CodecResult, SubscriptionResult>, ...Array<CodecArg>];
|
||||
|
||||
export type QueryableStorageMultiArgs<CodecResult, SubscriptionResult> = Array<QueryableStorageMultiArg<CodecResult, SubscriptionResult>>;
|
||||
|
||||
export interface QueryableStorageMultiBase<CodecResult, SubscriptionResult> {
|
||||
(calls: QueryableStorageMultiArgs<CodecResult, SubscriptionResult>): SubscriptionResult;
|
||||
}
|
||||
|
||||
export interface QueryableStorageMultiPromise<CodecResult, SubscriptionResult> {
|
||||
(calls: QueryableStorageMultiArgs<CodecResult, SubscriptionResult>, callback: CodecCallback): SubscriptionResult;
|
||||
}
|
||||
|
||||
export type QueryableStorageMulti<CodecResult, SubscriptionResult> =
|
||||
CodecResult extends Observable<any>
|
||||
? QueryableStorageMultiBase<CodecResult, SubscriptionResult>
|
||||
: QueryableStorageMultiPromise<CodecResult, SubscriptionResult>;
|
||||
|
||||
export interface QueryableStorage<CodecResult, SubscriptionResult> {
|
||||
[index: string]: QueryableModuleStorage<CodecResult, SubscriptionResult>;
|
||||
}
|
||||
@@ -149,6 +168,7 @@ export interface ApiInterface$Decorated<CodecResult, SubscriptionResult> {
|
||||
runtimeVersion: RuntimeVersion;
|
||||
derive: Derive<CodecResult, SubscriptionResult>;
|
||||
query: QueryableStorage<CodecResult, SubscriptionResult>;
|
||||
queryMulti: QueryableStorageMulti<CodecResult, SubscriptionResult>;
|
||||
rpc: DecoratedRpc<CodecResult, SubscriptionResult>;
|
||||
tx: SubmittableExtrinsics<CodecResult, SubscriptionResult>;
|
||||
signer?: Signer;
|
||||
|
||||
Reference in New Issue
Block a user