api.at(blockHash).{consts, errors, events, query} (#3710)
* api.at(blockHash).{consts, errors, events, query}
* Manual tests for apiAt
* Adjust helpers... not perfect, but best for now
* Expand decorated return
* Re-add compable injectMetadata
* CHANGELOG
* Bump jest global timeout
This commit is contained in:
@@ -14,7 +14,7 @@ export function createApiWithAugmentations (): ApiPromise {
|
||||
|
||||
const api = new ApiPromise({ provider: new WsProvider('ws://', false), registry });
|
||||
|
||||
api.injectMetadata(metadata, true);
|
||||
api.injectMetadata(metadata, true, registry);
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import type { Call, Hash, RpcMethods, RuntimeVersion } from '@polkadot/types/int
|
||||
import type { StorageEntry } from '@polkadot/types/primitive/types';
|
||||
import type { AnyFunction, AnyTuple, CallFunction, Codec, CodecArg as Arg, DefinitionRpc, DefinitionRpcSub, IMethod, InterfaceTypes, IStorageKey, Registry, RegistryTypes } from '@polkadot/types/types';
|
||||
import type { SubmittableExtrinsic } from '../submittable/types';
|
||||
import type { ApiInterfaceRx, ApiOptions, ApiTypes, DecoratedErrors, DecoratedEvents, DecoratedRpc, DecoratedRpcSection, DecorateMethod, PaginationOptions, QueryableConsts, QueryableModuleStorage, QueryableStorage, QueryableStorageEntry, QueryableStorageMulti, QueryableStorageMultiArg, SubmittableExtrinsicFunction, SubmittableExtrinsics, SubmittableModuleExtrinsics } from '../types';
|
||||
import type { ApiDecoration, ApiInterfaceRx, ApiOptions, ApiTypes, DecoratedErrors, DecoratedEvents, DecoratedRpc, DecoratedRpcSection, DecorateMethod, PaginationOptions, QueryableConsts, QueryableModuleStorage, QueryableModuleStorageAt, QueryableStorage, QueryableStorageAt, QueryableStorageEntry, QueryableStorageEntryAt, QueryableStorageMulti, QueryableStorageMultiArg, SubmittableExtrinsicFunction, SubmittableExtrinsics, SubmittableModuleExtrinsics } from '../types';
|
||||
import type { VersionedRegistry } from './types';
|
||||
|
||||
import { decorateDerive, ExactDerive } from '@polkadot/api-derive';
|
||||
import { memo } from '@polkadot/api-derive/util';
|
||||
@@ -18,7 +19,7 @@ import { WsProvider } from '@polkadot/rpc-provider';
|
||||
import { TypeRegistry } from '@polkadot/types/create';
|
||||
import { DEFAULT_VERSION as EXTRINSIC_DEFAULT_VERSION } from '@polkadot/types/extrinsic/constants';
|
||||
import { unwrapStorageType } from '@polkadot/types/primitive/StorageKey';
|
||||
import { arrayChunk, arrayFlatten, assert, BN, compactStripLength, logger, u8aToHex } from '@polkadot/util';
|
||||
import { arrayChunk, arrayFlatten, assert, BN, BN_ZERO, compactStripLength, logger, u8aToHex } from '@polkadot/util';
|
||||
import { BehaviorSubject, combineLatest, Observable, of } from '@polkadot/x-rxjs';
|
||||
import { map, switchMap, tap, toArray } from '@polkadot/x-rxjs/operators';
|
||||
|
||||
@@ -36,6 +37,11 @@ interface MetaDecoration {
|
||||
toJSON: () => any;
|
||||
}
|
||||
|
||||
interface FullDecoration<ApiType extends ApiTypes> {
|
||||
decoratedApi: ApiDecoration<ApiType>;
|
||||
decoratedMeta: DecoratedMeta;
|
||||
}
|
||||
|
||||
// the max amount of keys/values that we will retrieve at once
|
||||
const PAGE_SIZE_K = 1000; // limit aligned with the 1k on the node (trie lookups are heavy)
|
||||
const PAGE_SIZE_V = 250; // limited since the data may be very large (e.g. misfiring elections)
|
||||
@@ -186,8 +192,43 @@ export abstract class Decorate<ApiType extends ApiTypes> extends Events {
|
||||
return this._rpcCore.provider.hasSubscriptions || !!this._rpcCore.state.queryStorageAt;
|
||||
}
|
||||
|
||||
public injectMetadata (metadata: Metadata, fromEmpty?: boolean, registry?: Registry): void {
|
||||
const decoratedMeta = expandMetadata(registry || this.#registry, metadata);
|
||||
protected _injectDecorated (registry: VersionedRegistry<ApiType>, fromEmpty?: boolean, blockHash?: Uint8Array): FullDecoration<ApiType> {
|
||||
const decoratedMeta = expandMetadata(registry.registry, registry.metadata);
|
||||
|
||||
// clear the decoration, we are redoing it here
|
||||
if (fromEmpty || !registry.decoration) {
|
||||
registry.decoration = {
|
||||
consts: {},
|
||||
errors: {},
|
||||
events: {},
|
||||
query: {}
|
||||
} as ApiDecoration<ApiType>;
|
||||
}
|
||||
|
||||
// adjust the versioned registry
|
||||
augmentObject('consts', decoratedMeta.consts, registry.decoration.consts, fromEmpty);
|
||||
augmentObject('errors', decoratedMeta.errors, registry.decoration.errors, fromEmpty);
|
||||
augmentObject('events', decoratedMeta.events, registry.decoration.events, fromEmpty);
|
||||
|
||||
const storage = blockHash
|
||||
? this._decorateStorageAt(decoratedMeta, this._decorateMethod, blockHash)
|
||||
: this._decorateStorage(decoratedMeta, this._decorateMethod);
|
||||
|
||||
augmentObject('query', storage, registry.decoration.query, fromEmpty);
|
||||
|
||||
return {
|
||||
decoratedApi: registry.decoration,
|
||||
decoratedMeta
|
||||
};
|
||||
}
|
||||
|
||||
protected _injectMetadata (registry: VersionedRegistry<ApiType>, fromEmpty?: boolean): void {
|
||||
const { decoratedApi, decoratedMeta } = this._injectDecorated(registry, fromEmpty);
|
||||
|
||||
this._consts = decoratedApi.consts;
|
||||
this._errors = decoratedApi.errors;
|
||||
this._events = decoratedApi.events;
|
||||
this._query = decoratedApi.query;
|
||||
|
||||
if (fromEmpty || !this._extrinsics) {
|
||||
this._extrinsics = this._decorateExtrinsics(decoratedMeta, this._decorateMethod);
|
||||
@@ -197,17 +238,19 @@ export abstract class Decorate<ApiType extends ApiTypes> extends Events {
|
||||
augmentObject(null, this._decorateExtrinsics(decoratedMeta, this._rxDecorateMethod), this._rx.tx, false);
|
||||
}
|
||||
|
||||
// this API
|
||||
augmentObject('query', this._decorateStorage(decoratedMeta, this._decorateMethod), this._query, fromEmpty);
|
||||
augmentObject('consts', decoratedMeta.consts, this._consts, fromEmpty);
|
||||
augmentObject('errors', decoratedMeta.errors, this._errors, fromEmpty);
|
||||
augmentObject('events', decoratedMeta.events, this._events, fromEmpty);
|
||||
|
||||
// rx
|
||||
augmentObject(null, this._decorateStorage(decoratedMeta, this._rxDecorateMethod), this._rx.query, fromEmpty);
|
||||
augmentObject(null, decoratedMeta.consts, this._rx.consts, fromEmpty);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* backwards compatible endpoint for metadata injection, may be removed in the future (However, it is still useful for testing injection)
|
||||
*/
|
||||
public injectMetadata (metadata: Metadata, fromEmpty?: boolean, registry?: Registry): void {
|
||||
this._injectMetadata({ metadata, registry: registry || this.#registry, specVersion: BN_ZERO }, fromEmpty);
|
||||
}
|
||||
|
||||
private _decorateFunctionMeta (input: MetaDecoration, output: MetaDecoration): MetaDecoration {
|
||||
output.meta = input.meta;
|
||||
output.method = input.method;
|
||||
@@ -353,6 +396,18 @@ export abstract class Decorate<ApiType extends ApiTypes> extends Events {
|
||||
}, {} as QueryableStorage<ApiType>);
|
||||
}
|
||||
|
||||
protected _decorateStorageAt<ApiType extends ApiTypes> ({ query }: DecoratedMeta, decorateMethod: DecorateMethod<ApiType>, blockHash: Uint8Array): QueryableStorageAt<ApiType> {
|
||||
return Object.entries(query).reduce((out, [name, section]): QueryableStorageAt<ApiType> => {
|
||||
out[name] = Object.entries(section).reduce((out, [name, method]): QueryableModuleStorageAt<ApiType> => {
|
||||
out[name] = this._decorateStorageEntryAt(method, decorateMethod, blockHash);
|
||||
|
||||
return out;
|
||||
}, {} as QueryableModuleStorageAt<ApiType>);
|
||||
|
||||
return out;
|
||||
}, {} as QueryableStorageAt<ApiType>);
|
||||
}
|
||||
|
||||
private _decorateStorageEntry<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): QueryableStorageEntry<ApiType> {
|
||||
// get the storage arguments, with DoubleMap as an array entry, otherwise spread
|
||||
const getArgs = (args: unknown[]): unknown[] => extractStorageArgs(creator, args);
|
||||
@@ -371,7 +426,8 @@ export abstract class Decorate<ApiType extends ApiTypes> extends Events {
|
||||
this._rpcCore.state.getStorageHash(getArgs(args)));
|
||||
|
||||
decorated.is = <A extends AnyTuple> (key: IStorageKey<AnyTuple>): key is IStorageKey<A> =>
|
||||
key.section === creator.section && key.method === creator.method;
|
||||
key.section === creator.section &&
|
||||
key.method === creator.method;
|
||||
|
||||
decorated.key = (...args: Arg[]): string =>
|
||||
u8aToHex(compactStripLength(creator(
|
||||
@@ -435,6 +491,59 @@ export abstract class Decorate<ApiType extends ApiTypes> extends Events {
|
||||
return this._decorateFunctionMeta(creator as any, decorated) as unknown as QueryableStorageEntry<ApiType>;
|
||||
}
|
||||
|
||||
private _decorateStorageEntryAt<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>, blockHash: Uint8Array): QueryableStorageEntryAt<ApiType> {
|
||||
// get the storage arguments, with DoubleMap as an array entry, otherwise spread
|
||||
const getArgs = (args: unknown[]): unknown[] => extractStorageArgs(creator, args);
|
||||
|
||||
// Disable this where it occurs for each field we are decorating
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment */
|
||||
|
||||
const decorated = decorateMethod((...args: Arg[]): Observable<Codec> =>
|
||||
this._rpcCore.state.getStorage(getArgs(args), blockHash));
|
||||
|
||||
decorated.creator = creator;
|
||||
|
||||
decorated.hash = decorateMethod((...args: Arg[]): Observable<Hash> =>
|
||||
this._rpcCore.state.getStorageHash(getArgs(args), blockHash));
|
||||
|
||||
decorated.is = <A extends AnyTuple> (key: IStorageKey<AnyTuple>): key is IStorageKey<A> =>
|
||||
key.section === creator.section &&
|
||||
key.method === creator.method;
|
||||
|
||||
decorated.key = (...args: Arg[]): string =>
|
||||
u8aToHex(compactStripLength(creator(
|
||||
creator.meta.type.isPlain
|
||||
? undefined
|
||||
: creator.meta.type.isMap
|
||||
? args[0]
|
||||
: creator.meta.type.isDoubleMap
|
||||
? [args[0], args[1]]
|
||||
: args
|
||||
))[1]);
|
||||
|
||||
decorated.keyPrefix = (...keys: Arg[]): string =>
|
||||
u8aToHex(creator.keyPrefix(...keys));
|
||||
|
||||
decorated.size = decorateMethod((...args: Arg[]): Observable<u64> =>
|
||||
this._rpcCore.state.getStorageSize(getArgs(args), blockHash));
|
||||
|
||||
// FIXME NMap support
|
||||
// .keys() & .entries() only available on map types
|
||||
if (creator.iterKey && (creator.meta.type.isMap || creator.meta.type.isDoubleMap)) {
|
||||
decorated.entries = decorateMethod(
|
||||
memo(this.#instanceId, (...args: Arg[]): Observable<[StorageKey, Codec][]> =>
|
||||
this._retrieveMapEntries(creator, blockHash, args)));
|
||||
|
||||
decorated.keys = decorateMethod(
|
||||
memo(this.#instanceId, (...args: Arg[]): Observable<StorageKey[]> =>
|
||||
this._retrieveMapKeys(creator, blockHash, args)));
|
||||
}
|
||||
|
||||
/* eslint-enable @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment */
|
||||
|
||||
return this._decorateFunctionMeta(creator as any, decorated) as unknown as QueryableStorageEntry<ApiType>;
|
||||
}
|
||||
|
||||
// Decorate the base storage call. In the case or rxjs or promise-without-callback (await)
|
||||
// we make a subscription, alternatively we push this through a single-shot query
|
||||
private _decorateStorageCall<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): ReturnType<DecorateMethod<ApiType>> {
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { Metadata } from '@polkadot/metadata';
|
||||
import type { RpcInterface } from '@polkadot/rpc-core/types';
|
||||
import type { Text } from '@polkadot/types';
|
||||
import type { Hash, RuntimeVersion } from '@polkadot/types/interfaces';
|
||||
import type { ApiInterfaceRx, ApiTypes, DecoratedErrors, DecoratedEvents, DecoratedRpc, QueryableConsts, QueryableStorage, QueryableStorageMulti, SubmittableExtrinsics } from '../types';
|
||||
import type { ApiDecoration, ApiInterfaceRx, ApiTypes, DecoratedErrors, DecoratedEvents, DecoratedRpc, QueryableConsts, QueryableStorage, QueryableStorageMulti, SubmittableExtrinsics } from '../types';
|
||||
|
||||
import { assertReturn } from '@polkadot/util';
|
||||
|
||||
@@ -21,7 +21,7 @@ function assertResult<T> (value: T | undefined): T {
|
||||
return assertReturn(value, 'Api needs to be initialized before using, listen on \'ready\'');
|
||||
}
|
||||
|
||||
export abstract class Getters<ApiType extends ApiTypes> extends Init<ApiType> {
|
||||
export abstract class Getters<ApiType extends ApiTypes> extends Init<ApiType> implements ApiDecoration<ApiType> {
|
||||
/**
|
||||
* @description Contains the parameter types (constants) of all modules.
|
||||
*
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { ChainProperties, Hash, RuntimeVersion } from '@polkadot/types/inte
|
||||
import type { Registry } from '@polkadot/types/types';
|
||||
import type { BN } from '@polkadot/util';
|
||||
import type { Observable, Subscription } from '@polkadot/x-rxjs';
|
||||
import type { ApiBase, ApiOptions, ApiTypes, DecorateMethod } from '../types';
|
||||
import type { ApiBase, ApiDecoration, ApiOptions, ApiTypes, DecorateMethod } from '../types';
|
||||
import type { VersionedRegistry } from './types';
|
||||
|
||||
import { Metadata } from '@polkadot/metadata';
|
||||
@@ -28,7 +28,7 @@ const l = logger('api/init');
|
||||
export abstract class Init<ApiType extends ApiTypes> extends Decorate<ApiType> {
|
||||
#healthTimer: NodeJS.Timeout | null = null;
|
||||
|
||||
#registries: VersionedRegistry[] = [];
|
||||
#registries: VersionedRegistry<ApiType>[] = [];
|
||||
|
||||
#updateSub?: Subscription | null = null;
|
||||
|
||||
@@ -44,7 +44,7 @@ export abstract class Init<ApiType extends ApiTypes> extends Decorate<ApiType> {
|
||||
if (!options.source) {
|
||||
this.registerTypes(options.types);
|
||||
} else {
|
||||
this.#registries = options.source.#registries;
|
||||
this.#registries = options.source.#registries as VersionedRegistry<ApiType>[];
|
||||
}
|
||||
|
||||
this._rpc = this._decorateRpc(this._rpcCore, this._decorateMethod);
|
||||
@@ -98,10 +98,34 @@ export abstract class Init<ApiType extends ApiTypes> extends Decorate<ApiType> {
|
||||
return registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the default versioned registry
|
||||
*/
|
||||
private _getDefaultRegistry (): VersionedRegistry<ApiType> {
|
||||
// get the default registry version
|
||||
const thisRegistry = this.#registries.find(({ isDefault }) => isDefault);
|
||||
|
||||
assert(thisRegistry, 'Initialization error, cannot find the default registry');
|
||||
|
||||
return thisRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns a decorated API instance at a specific point in time
|
||||
*/
|
||||
public async at (blockHash: Uint8Array | string): Promise<ApiDecoration<ApiType>> {
|
||||
const u8aHash = u8aToU8a(blockHash);
|
||||
const registry = await this.getBlockRegistry(u8aHash);
|
||||
|
||||
return registry.decoration
|
||||
? registry.decoration
|
||||
: this._injectDecorated(registry, true, u8aHash).decoratedApi;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Sets up a registry based on the block hash defined
|
||||
*/
|
||||
public async getBlockRegistry (blockHash: Uint8Array): Promise<VersionedRegistry> {
|
||||
public async getBlockRegistry (blockHash: Uint8Array): Promise<VersionedRegistry<ApiType>> {
|
||||
const existingViaHash = this.#registries.find(({ lastBlockHash }) =>
|
||||
lastBlockHash && u8aEq(lastBlockHash, blockHash)
|
||||
);
|
||||
@@ -147,7 +171,7 @@ export abstract class Init<ApiType extends ApiTypes> extends Decorate<ApiType> {
|
||||
const registry = this._initRegistry(new TypeRegistry(blockHash), this._runtimeChain as Text, version, metadata);
|
||||
|
||||
// add our new registry
|
||||
const result = { isDefault: false, lastBlockHash: blockHash, metadata, metadataConsts: null, registry, specVersion: version.specVersion };
|
||||
const result = { lastBlockHash: blockHash, metadata, registry, specVersion: version.specVersion };
|
||||
|
||||
this.#registries.push(result);
|
||||
|
||||
@@ -230,18 +254,15 @@ export abstract class Init<ApiType extends ApiTypes> extends Decorate<ApiType> {
|
||||
this._rx.runtimeVersion = version;
|
||||
|
||||
// update the default registry version
|
||||
const thisRegistry = this.#registries.find(({ isDefault }) => isDefault);
|
||||
|
||||
assert(thisRegistry, 'Initialization error, cannot find the default registry');
|
||||
const thisRegistry = this._getDefaultRegistry();
|
||||
|
||||
// setup the data as per the current versions
|
||||
thisRegistry.metadata = metadata;
|
||||
thisRegistry.metadataConsts = null;
|
||||
thisRegistry.specVersion = version.specVersion;
|
||||
|
||||
// clear the registry types to ensure that we override correctly
|
||||
this._initRegistry(thisRegistry.registry.init(), this._runtimeChain as Text, version, metadata);
|
||||
this.injectMetadata(metadata, false, thisRegistry.registry);
|
||||
this._injectMetadata(thisRegistry, false);
|
||||
|
||||
return this._detectCapabilities(thisRegistry.registry);
|
||||
})
|
||||
@@ -282,7 +303,7 @@ export abstract class Init<ApiType extends ApiTypes> extends Decorate<ApiType> {
|
||||
|
||||
// setup the initial registry, when we have none
|
||||
if (!this.#registries.length) {
|
||||
this.#registries.push({ isDefault: true, lastBlockHash: null, metadata, metadataConsts: null, registry: this.registry, specVersion: runtimeVersion.specVersion });
|
||||
this.#registries.push({ isDefault: true, metadata, registry: this.registry, specVersion: runtimeVersion.specVersion });
|
||||
}
|
||||
|
||||
// get unique types & validate
|
||||
@@ -298,7 +319,7 @@ export abstract class Init<ApiType extends ApiTypes> extends Decorate<ApiType> {
|
||||
this._rx.runtimeVersion = this._runtimeVersion as RuntimeVersion; // must be set here
|
||||
|
||||
// inject metadata and adjust the types as detected
|
||||
this.injectMetadata(metadata, true);
|
||||
this._injectMetadata(this._getDefaultRegistry(), true);
|
||||
|
||||
// derive is last, since it uses the decorated rx
|
||||
this._rx.derive = this._decorateDeriveRx(this._rxDecorateMethod);
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { Metadata } from '@polkadot/metadata';
|
||||
import type { Constants } from '@polkadot/metadata/decorate/types';
|
||||
import type { Registry } from '@polkadot/types/types';
|
||||
import type { BN } from '@polkadot/util';
|
||||
import type { ApiDecoration, ApiTypes } from '../types';
|
||||
|
||||
export interface VersionedRegistry {
|
||||
isDefault: boolean;
|
||||
lastBlockHash: Uint8Array | null;
|
||||
export interface VersionedRegistry<ApiType extends ApiTypes> {
|
||||
decoration?: ApiDecoration<ApiType> | null;
|
||||
isDefault?: boolean;
|
||||
lastBlockHash?: Uint8Array | null;
|
||||
metadata: Metadata;
|
||||
metadataConsts: Constants | null;
|
||||
registry: Registry;
|
||||
specVersion: BN;
|
||||
}
|
||||
|
||||
@@ -239,6 +239,16 @@ async function tx (api: ApiPromise, pairs: TestKeyringMap): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
async function at (api: ApiPromise): Promise<void> {
|
||||
const apiAt = await api.at('0x1234');
|
||||
|
||||
// get old balances
|
||||
console.log(await apiAt.query.balances.freeBalance('0x1234'));
|
||||
|
||||
// get some constants
|
||||
console.log(apiAt.consts.balances.existentialDeposit);
|
||||
}
|
||||
|
||||
async function main (): Promise<void> {
|
||||
const api = await ApiPromise.create();
|
||||
const pairs = createTestPairs();
|
||||
@@ -253,7 +263,8 @@ async function main (): Promise<void> {
|
||||
queryExtra(api, pairs),
|
||||
rpc(api),
|
||||
types(api),
|
||||
tx(api, pairs)
|
||||
tx(api, pairs),
|
||||
at(api)
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,10 @@ import type { DefinitionRpc, DefinitionRpcSub, RegisteredTypes, Registry, Signat
|
||||
import type { BN } from '@polkadot/util';
|
||||
import type { ApiBase } from '../base';
|
||||
import type { DeriveAllSections } from '../util/decorate';
|
||||
import type { ApiTypes } from './base';
|
||||
import type { QueryableConsts } from './consts';
|
||||
import type { DecoratedErrors } from './errors';
|
||||
import type { DecoratedEvents } from './events';
|
||||
import type { DecoratedRpc } from './rpc';
|
||||
import type { QueryableStorage, QueryableStorageMulti } from './storage';
|
||||
import type { SubmittableExtrinsics } from './submittable';
|
||||
@@ -103,3 +106,10 @@ export interface SignerOptions extends SignatureOptions {
|
||||
blockNumber: BN;
|
||||
genesisHash: Hash;
|
||||
}
|
||||
|
||||
export interface ApiDecoration<ApiType extends ApiTypes> {
|
||||
consts: QueryableConsts<ApiType>;
|
||||
errors: DecoratedErrors<ApiType>;
|
||||
events: DecoratedEvents<ApiType>;
|
||||
query: QueryableStorage<ApiType>;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,11 @@ export interface StorageEntryPromiseOverloads {
|
||||
<T extends Codec>(arg1: CodecArg, arg2: CodecArg, arg3: CodecArg, callback: Callback<T>): UnsubscribePromise;
|
||||
}
|
||||
|
||||
export interface StorageEntryPromiseOverloadsAt {
|
||||
(arg1?: CodecArg, arg2?: CodecArg, arg3?: CodecArg): Promise<Codec>;
|
||||
<T extends Codec>(arg1?: CodecArg, arg2?: CodecArg, arg3?: CodecArg): Promise<T>;
|
||||
}
|
||||
|
||||
// This is the most generic typings we can have for a storage entry function
|
||||
type GenericStorageEntryFunction = (...args: CodecArg[]) => Observable<Codec>
|
||||
|
||||
@@ -36,6 +41,17 @@ export type QueryableStorageEntry<ApiType extends ApiTypes, A extends AnyTuple =
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
: AugmentedQuery<'promise', GenericStorageEntryFunction, A> & StorageEntryPromiseOverloads;
|
||||
|
||||
export type QueryableStorageEntryAt<ApiType extends ApiTypes, A extends AnyTuple = AnyTuple> =
|
||||
ApiType extends 'rxjs'
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
? AugmentedQueryAt<'rxjs', GenericStorageEntryFunction, A>
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
: AugmentedQueryAt<'promise', GenericStorageEntryFunction, A> & StorageEntryPromiseOverloadsAt;
|
||||
|
||||
export interface QueryableStorageAt<ApiType extends ApiTypes> extends AugmentedQueries<ApiType> {
|
||||
[key: string]: QueryableModuleStorageAt<ApiType>;
|
||||
}
|
||||
|
||||
export interface StorageEntryBase<ApiType extends ApiTypes, F extends AnyFunction, A extends AnyTuple = AnyTuple> {
|
||||
at: <T extends Codec | any = ObsInnerType<ReturnType<F>>>(hash: Hash | Uint8Array | string, ...args: Parameters<F>) => PromiseOrObs<ApiType, T>;
|
||||
creator: StorageEntry;
|
||||
@@ -56,10 +72,24 @@ export interface StorageEntryBase<ApiType extends ApiTypes, F extends AnyFunctio
|
||||
multi: ApiType extends 'rxjs' ? StorageEntryObservableMulti : StorageEntryPromiseMulti;
|
||||
}
|
||||
|
||||
export interface StorageEntryBaseAt<ApiType extends ApiTypes, F extends AnyFunction, A extends AnyTuple = AnyTuple> {
|
||||
entries: <T extends Codec | any = ObsInnerType<ReturnType<F>>, K extends AnyTuple = A>(...args: DropLast<Parameters<F>>) => PromiseOrObs<ApiType, [StorageKey<K>, T][]>;
|
||||
hash: (...args: Parameters<F>) => PromiseOrObs<ApiType, Hash>;
|
||||
is: (key: IStorageKey<AnyTuple>) => key is IStorageKey<A>;
|
||||
key: (...args: Parameters<F>) => string;
|
||||
keyPrefix: (...args: DropLast<Parameters<F>>) => string;
|
||||
keys: <K extends AnyTuple = A> (...args: DropLast<Parameters<F>>) => PromiseOrObs<ApiType, StorageKey<K>[]>;
|
||||
size: (...args: Parameters<F>) => PromiseOrObs<ApiType, u64>;
|
||||
}
|
||||
|
||||
export interface QueryableModuleStorage<ApiType extends ApiTypes> {
|
||||
[index: string]: QueryableStorageEntry<ApiType, AnyTuple>;
|
||||
}
|
||||
|
||||
export interface QueryableModuleStorageAt<ApiType extends ApiTypes> {
|
||||
[index: string]: QueryableStorageEntryAt<ApiType, AnyTuple>;
|
||||
}
|
||||
|
||||
export type QueryableStorageMultiArg<ApiType extends ApiTypes> =
|
||||
QueryableStorageEntry<ApiType> |
|
||||
[QueryableStorageEntry<ApiType>, ...CodecArg[]];
|
||||
@@ -83,5 +113,7 @@ export interface AugmentedQueries<ApiType extends ApiTypes> { }
|
||||
|
||||
export type AugmentedQuery<ApiType extends ApiTypes, F extends AnyFunction, A extends AnyTuple = AnyTuple> = MethodResult<ApiType, F> & StorageEntryBase<ApiType, F, A>;
|
||||
|
||||
export type AugmentedQueryAt<ApiType extends ApiTypes, F extends AnyFunction, A extends AnyTuple = AnyTuple> = MethodResult<ApiType, F> & StorageEntryBaseAt<ApiType, F, A>;
|
||||
|
||||
// backwards compatibility-only
|
||||
export type AugmentedQueryDoubleMap<ApiType extends ApiTypes, F extends AnyFunction, A extends AnyTuple = AnyTuple> = AugmentedQuery<ApiType, F, A>;
|
||||
|
||||
Reference in New Issue
Block a user