diff --git a/CHANGELOG.md b/CHANGELOG.md index 395afa4f29..6b5a64b77c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ Changes: - Add `isStorageFallback` on the `Codec` interface. (`true` if entry was created from a metadata fallback value from an empty storage item) +- Ensure `api.queryMulti` returns empty result when no keys are provided +- Add explicit Array checks on `Vec/Tuple` inputs +- Align `Struct.{toU8a/toPrimitive/toHuman/toJSON}` population of results +- Apply memoization to batched API queries ## 9.11.3 Jan 15, 2023 diff --git a/packages/api/src/base/Decorate.ts b/packages/api/src/base/Decorate.ts index 7f85a81a44..4ab483ca2e 100644 --- a/packages/api/src/base/Decorate.ts +++ b/packages/api/src/base/Decorate.ts @@ -587,39 +587,44 @@ export abstract class Decorate extends Events { protected _decorateMulti (decorateMethod: DecorateMethod): QueryableStorageMulti { // eslint-disable-next-line @typescript-eslint/no-unsafe-return return decorateMethod((keys: QueryableStorageMultiArg[]): Observable => - (this.hasSubscriptions - ? this._rpcCore.state.subscribeStorage - : this._rpcCore.state.queryStorageAt - )(keys.map((args: QueryableStorageMultiArg): [StorageEntry, ...unknown[]] => - Array.isArray(args) - ? args[0].creator.meta.type.isPlain - ? [args[0].creator] - : args[0].creator.meta.type.asMap.hashers.length === 1 - ? [args[0].creator, args.slice(1)] - : [args[0].creator, ...args.slice(1)] - : [args.creator] - )) + keys.length + ? (this.hasSubscriptions + ? this._rpcCore.state.subscribeStorage + : this._rpcCore.state.queryStorageAt + )(keys.map((args: QueryableStorageMultiArg): [StorageEntry, ...unknown[]] => + Array.isArray(args) + ? args[0].creator.meta.type.isPlain + ? [args[0].creator] + : args[0].creator.meta.type.asMap.hashers.length === 1 + ? [args[0].creator, args.slice(1)] + : [args[0].creator, ...args.slice(1)] + : [args.creator] + )) + : of([]) ); } protected _decorateMultiAt (atApi: ApiDecoration, decorateMethod: DecorateMethod, blockHash: Uint8Array | string): QueryableStorageMulti { // eslint-disable-next-line @typescript-eslint/no-unsafe-return return decorateMethod((calls: QueryableStorageMultiArg[]): Observable => - this._rpcCore.state.queryStorageAt( - calls.map((args: QueryableStorageMultiArg) => { - if (Array.isArray(args)) { - const { creator } = getAtQueryFn(atApi, args[0].creator); + calls.length + ? this._rpcCore.state.queryStorageAt( + calls.map((args: QueryableStorageMultiArg) => { + if (Array.isArray(args)) { + const { creator } = getAtQueryFn(atApi, args[0].creator); - return creator.meta.type.isPlain - ? [creator] - : creator.meta.type.asMap.hashers.length === 1 - ? [creator, args.slice(1)] - : [creator, ...args.slice(1)]; - } + return creator.meta.type.isPlain + ? [creator] + : creator.meta.type.asMap.hashers.length === 1 + ? [creator, args.slice(1)] + : [creator, ...args.slice(1)]; + } - return [getAtQueryFn(atApi, args.creator).creator]; - }), - blockHash)); + return [getAtQueryFn(atApi, args.creator).creator]; + }), + blockHash) + : of([]) + ); } protected _decorateExtrinsics ({ tx }: DecoratedMeta, decorateMethod: DecorateMethod): SubmittableExtrinsics {