diff --git a/CHANGELOG.md b/CHANGELOG.md index a4b9bb96a2..19acb61b2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,13 @@ Contributed: Changes: +- Ecah module now exposes the Substrate-added `palletVersion` storage item - Adjust Websocket `maxReceivedFrameSize` under Node +- `TypeDef` structures now contain the `typeName` from metadata v14 on fields - Fix browser bundle imports for xcm-mapping (move to `types-known`) - Expose all extracted type names in `PortableRegistry` +- Adjust `api.rpc.*.*.raw(..args)` return to the actual over-the-wire JSON result +- Remove `api.rpc.*.*.json(..args)` since it now overlaps with new `.raw` ## 6.4.2 Oct 18, 2021 diff --git a/packages/api/src/base/Decorate.ts b/packages/api/src/base/Decorate.ts index 5e7b92bee6..d88534d485 100644 --- a/packages/api/src/base/Decorate.ts +++ b/packages/api/src/base/Decorate.ts @@ -366,8 +366,6 @@ export abstract class Decorate extends Events { if (this.hasSubscriptions || !(methodName.startsWith('subscribe') || methodName.startsWith('unsubscribe'))) { (section as Record)[methodName] = decorateMethod(method, { methodName }) as unknown; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - (section as Record)[methodName].json = decorateMethod(method.json, { methodName }) as unknown; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access (section as Record)[methodName].raw = decorateMethod(method.raw, { methodName }) as unknown; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access (section as Record)[methodName].meta = method.meta; @@ -622,9 +620,9 @@ export abstract class Decorate extends Events { return this._rpcCore.state .queryStorage<[Option]>([decorated.key(...args)], ...range) .pipe(map((result: [Hash, [Option]][]): [Hash, Codec][] => - result.map(([blockHash, [value]]): [Hash, Codec] => [ + result.map(([blockHash, [value]]) => [ blockHash, - this.createType(outputType, value.isSome ? value.unwrap().toHex() : undefined) + this.createType(outputType, value.isSome ? value.unwrap().toHex() : undefined) ]) )); } diff --git a/packages/api/src/base/Init.ts b/packages/api/src/base/Init.ts index cc276d0673..04f7ae4e81 100644 --- a/packages/api/src/base/Init.ts +++ b/packages/api/src/base/Init.ts @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 import type { Observable, Subscription } from 'rxjs'; -import type { RpcInterfaceMethod } from '@polkadot/rpc-core/types'; import type { Text } from '@polkadot/types'; import type { ChainProperties, Hash, RuntimeVersion } from '@polkadot/types/interfaces'; import type { Registry } from '@polkadot/types/types'; @@ -130,7 +129,7 @@ export abstract class Init extends Decorate { const header = this.registry.createType('HeaderPartial', this._genesisHash.eq(blockHash) ? { number: BN_ZERO, parentHash: this._genesisHash } - : await firstValueFrom((this._rpcCore.chain.getHeader as RpcInterfaceMethod).json(blockHash)) + : await firstValueFrom(this._rpcCore.chain.getHeader.raw(blockHash)) ); assert(!header.parentHash.isEmpty, 'Unable to retrieve header and parent from supplied hash'); @@ -140,11 +139,11 @@ export abstract class Init extends Decorate { const version = this.registry.createType('RuntimeVersionPartial', (firstVersion && (lastVersion || firstVersion.specVersion.eq(this._runtimeVersion.specVersion))) ? { specName: this._runtimeVersion.specName, specVersion: firstVersion.specVersion } - : await firstValueFrom((this._rpcCore.state.getRuntimeVersion as RpcInterfaceMethod).json(header.parentHash)) + : await firstValueFrom(this._rpcCore.state.getRuntimeVersion.raw(header.parentHash)) ); // check for pre-existing registries. We also check specName, e.g. it - // could be changed like in Westmint with upgrade from shell -> westmint + // could be changed like in Westmint with upgrade from shell -> westmint const existingViaVersion = this.#registries.find(({ specName, specVersion }) => specName.eq(version.specName) && specVersion.eq(version.specVersion) @@ -159,7 +158,7 @@ export abstract class Init extends Decorate { // nothing has been found, construct new const registry = new TypeRegistry(blockHash); const metadata = new Metadata(registry, - await firstValueFrom((this._rpcCore.state.getMetadata as RpcInterfaceMethod).raw(header.parentHash)) + await firstValueFrom(this._rpcCore.state.getMetadata.raw(header.parentHash)) ); this._initRegistry(registry, this._runtimeChain as Text, version, metadata); diff --git a/packages/api/src/base/capabilities.ts b/packages/api/src/base/capabilities.ts index d8d139894f..1853f0d1e7 100644 --- a/packages/api/src/base/capabilities.ts +++ b/packages/api/src/base/capabilities.ts @@ -182,7 +182,7 @@ export function detectedCapabilities (api: ApiInterfaceRx, blockHash?: Uint8Arra }, extractResults(cResults, consts), extractResults(qResults, queries), - extractResults(rResults, raws) + extractResults(rResults.map((r) => api.registry.createType('Raw', r)), raws) ) ), take(1), diff --git a/packages/api/src/checkTypes.manual.ts b/packages/api/src/checkTypes.manual.ts index 27c5629245..57bfd2c051 100644 --- a/packages/api/src/checkTypes.manual.ts +++ b/packages/api/src/checkTypes.manual.ts @@ -177,12 +177,10 @@ async function rpc (api: ApiPromise): Promise { }); // using json & raw - await api.rpc.chain.getBlock.json('0x123456'); await api.rpc.chain.getBlock.raw('0x123456'); // using raw subs - // eslint-disable-next-line @typescript-eslint/no-floating-promises - api.rpc.chain.subscribeNewHeads.raw((result: Uint8Array): void => { + await api.rpc.chain.subscribeNewHeads.raw((result: Uint8Array): void => { console.log(result); }); } diff --git a/packages/api/src/types/rpc.ts b/packages/api/src/types/rpc.ts index ac24360ec1..c5720017ec 100644 --- a/packages/api/src/types/rpc.ts +++ b/packages/api/src/types/rpc.ts @@ -2,23 +2,19 @@ // SPDX-License-Identifier: Apache-2.0 import type { Observable } from 'rxjs'; -import type { Json, Raw } from '@polkadot/types/codec'; import type { AnyFunction, Callback, DefinitionRpc } from '@polkadot/types/types'; // eslint-disable-next-line @typescript-eslint/no-unused-vars import { ApiTypes, PromiseResult, Push, RxResult, UnsubscribePromise } from './base'; export interface RpcRxResult extends RxResult { - json (...args: Parameters): Observable; - raw (...args: Parameters): Observable; + raw (...args: Parameters): Observable; meta: DefinitionRpc; } export interface RpcPromiseResult extends PromiseResult { - json (...args: Parameters): Promise; - json (...args: Push, Callback>): UnsubscribePromise; - raw (...args: Parameters): Promise; - raw (...args: Push, Callback>): UnsubscribePromise; + raw (...args: Parameters): Promise; + raw (...args: Push, Callback>): UnsubscribePromise; meta: DefinitionRpc; } diff --git a/packages/rpc-core/src/bundle.ts b/packages/rpc-core/src/bundle.ts index 32f91b2229..41bc0ebae1 100644 --- a/packages/rpc-core/src/bundle.ts +++ b/packages/rpc-core/src/bundle.ts @@ -24,8 +24,6 @@ interface StorageChangeSetJSON { changes: [string, string | null][]; } -type OutputType = 'json' | 'raw' | 'scale'; - const l = logger('rpc-core'); const EMPTY_META = { @@ -183,44 +181,46 @@ export class RpcCore { }, {} as RpcInterface[Section]); } - private _memomize (creator: (outputAs: OutputType) => (...values: unknown[]) => Observable, def: DefinitionRpc): Memoized { - const memoized = memoize(creator('scale') as RpcInterfaceMethod, { - getInstanceId: () => this.#instanceId - }); + private _memomize (creator: (isScale: boolean) => (...values: unknown[]) => Observable, def: DefinitionRpc): Memoized { + const memoOpts = { getInstanceId: () => this.#instanceId }; + const memoized = memoize(creator(true) as RpcInterfaceMethod, memoOpts); - memoized.json = creator('json'); - memoized.raw = creator('raw'); + memoized.raw = memoize(creator(false), memoOpts); memoized.meta = def; return memoized; } + private _formatResult (isScale: boolean, registry: Registry, blockHash: string | Uint8Array | null | undefined, method: string, def: DefinitionRpc, params: Codec[], result: unknown): T { + return isScale + ? this._formatOutput(registry, blockHash, method, def, params, result) as unknown as T + : result as T; + } + private _createMethodSend (section: string, method: string, def: DefinitionRpc): RpcInterfaceMethod { const rpcName = def.endpoint || `${section}_${method}`; const hashIndex = def.params.findIndex(({ isHistoric }) => isHistoric); let memoized: null | Memoized = null; // execute the RPC call, doing a registry swap for historic as applicable - const callWithRegistry = async (outputAs: OutputType, values: unknown[]): Promise => { + const callWithRegistry = async (isScale: boolean, values: unknown[]): Promise => { const blockHash = hashIndex === -1 ? null : values[hashIndex] as (Uint8Array | string | null | undefined); - const { registry } = outputAs === 'scale' && blockHash && this.#getBlockRegistry + const { registry } = isScale && blockHash && this.#getBlockRegistry ? await this.#getBlockRegistry(u8aToU8a(blockHash)) : { registry: this.#registryDefault }; const params = this._formatInputs(registry, null, def, values); - const data = await this.provider.send(rpcName, params.map((param) => param.toJSON())); + const result = await this.provider.send(rpcName, params.map((p) => p.toJSON())); - return outputAs === 'scale' - ? this._formatOutput(registry, blockHash, method, def, params, data) as unknown as T - : registry.createType(outputAs === 'raw' ? 'Raw' : 'Json', data) as unknown as T; + return this._formatResult(isScale, registry, blockHash, method, def, params, result); }; - const creator = (outputAs: OutputType) => (...values: unknown[]): Observable => { - const isDelayed = outputAs === 'scale' && hashIndex !== -1 && !!values[hashIndex]; + const creator = (isScale: boolean) => (...values: unknown[]): Observable => { + const isDelayed = isScale && hashIndex !== -1 && !!values[hashIndex]; return new Observable((observer: Observer): VoidCallback => { - callWithRegistry(outputAs, values) + callWithRegistry(isScale, values) .then((value): void => { observer.next(value); observer.complete(); @@ -269,7 +269,7 @@ export class RpcCore { const subType = `${section}_${updateType}`; let memoized: null | Memoized = null; - const creator = (outputAs: OutputType) => (...values: unknown[]): Observable => { + const creator = (isScale: boolean) => (...values: unknown[]): Observable => { return new Observable((observer: Observer): VoidCallback => { // Have at least an empty promise, as used in the unsubscribe let subscriptionPromise: Promise = Promise.resolve(null); @@ -283,9 +283,9 @@ export class RpcCore { try { const params = this._formatInputs(registry, null, def, values); - const paramsJson = params.map((param) => param.toJSON()); + const paramsJson = params.map((p) => p.toJSON()); - const update = (error?: Error | null, result?: T): void => { + const update = (error?: Error | null, result?: unknown): void => { if (error) { logErrorMessage(method, def, error); @@ -293,11 +293,7 @@ export class RpcCore { } try { - observer.next( - outputAs === 'scale' - ? this._formatOutput(registry, null, method, def, params, result) as unknown as T - : registry.createType(outputAs === 'raw' ? 'Raw' : 'Json', result) as unknown as T - ); + observer.next(this._formatResult(isScale, registry, null, method, def, params, result)); } catch (error) { observer.error(error); } diff --git a/packages/rpc-core/src/types.jsonrpc.ts b/packages/rpc-core/src/types.jsonrpc.ts index f0133276df..eecf588d9c 100644 --- a/packages/rpc-core/src/types.jsonrpc.ts +++ b/packages/rpc-core/src/types.jsonrpc.ts @@ -3,9 +3,12 @@ // FIXME, this whole file needs to move to API +import type { Observable } from 'rxjs'; import type { AnyFunction } from '@polkadot/types/types'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface RpcInterface {} -export type AugmentedRpc = F; +export type AugmentedRpc = F & { + raw: (...params: Parameters) => Observable; +}; diff --git a/packages/rpc-core/src/types.ts b/packages/rpc-core/src/types.ts index b6e06ead27..75048b8e26 100644 --- a/packages/rpc-core/src/types.ts +++ b/packages/rpc-core/src/types.ts @@ -2,14 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 import type { Observable } from 'rxjs'; -import type { Json, Raw } from '@polkadot/types'; import type { Codec, DefinitionRpc } from '@polkadot/types/types'; export * from './types.jsonrpc'; export interface RpcInterfaceMethod { (...params: unknown[]): Observable; - json (...params: unknown[]): Observable; - raw (...params: unknown[]): Observable; + raw (...params: unknown[]): Observable; meta: DefinitionRpc; } diff --git a/packages/types-known/src/bundle.ts b/packages/types-known/src/bundle.ts index e66275c019..c84db6cf6f 100644 --- a/packages/types-known/src/bundle.ts +++ b/packages/types-known/src/bundle.ts @@ -121,7 +121,7 @@ export function getUpgradeVersion (genesisHash: Hash, blockNumber: BN): [ChainUp return known ? [ - known.versions.reduce((last: ChainUpgradeVersion | undefined, version): ChainUpgradeVersion | undefined => { + known.versions.reduce((last, version) => { return blockNumber.gt(version.blockNumber) ? version : last;