From ca2d7d1f8bf20c0a40f7181f96b59c28e9fb4123 Mon Sep 17 00:00:00 2001 From: demoncoder-crypto Date: Thu, 8 May 2025 03:29:13 +0530 Subject: [PATCH] feat: Add initial support for Metadata V16 view_functions --- packages/api/src/types/index.ts | 43 ++++++- .../types/src/interfaces/metadata/index.ts | 10 ++ .../types/src/interfaces/metadata/types.ts | 109 ++++++++++++++++-- packages/types/src/interfaces/metadata/v16.ts | 34 ++++++ .../types/src/metadata/MetadataVersioned.ts | 22 +++- packages/types/src/metadata/decorate/types.ts | 35 +++++- .../metadata/decorate/viewFunctions/index.ts | 61 ++++++++++ packages/types/src/metadata/v15/toLatest.ts | 13 --- packages/types/src/metadata/v15/toV16.ts | 31 +++++ packages/types/src/metadata/v16/toLatest.ts | 14 +++ packages/types/src/metadata/versions.ts | 2 +- 11 files changed, 334 insertions(+), 40 deletions(-) create mode 100644 packages/types/src/interfaces/metadata/v16.ts create mode 100644 packages/types/src/metadata/decorate/viewFunctions/index.ts delete mode 100644 packages/types/src/metadata/v15/toLatest.ts create mode 100644 packages/types/src/metadata/v15/toV16.ts create mode 100644 packages/types/src/metadata/v16/toLatest.ts diff --git a/packages/api/src/types/index.ts b/packages/api/src/types/index.ts index 57664d1bfa02..1a6c037720f9 100644 --- a/packages/api/src/types/index.ts +++ b/packages/api/src/types/index.ts @@ -17,6 +17,12 @@ import type { HexString } from '@polkadot/util/types'; import type { ApiBase } from '../base/index.js'; import type { SubmittableExtrinsic } from '../types/submittable.js'; import type { AllDerives } from '../util/decorate.js'; +import type { Observable } from 'rxjs'; +import type { DecoratedMeta } from '@polkadot/types/metadata/decorate/types'; +import type { StorageKey } from '@polkadot/types'; +import type { Codec, IMethod, AnyTuple, IEventLike } from '@polkadot/types/types'; +import type { DecoratedRpc } from './rpc.js'; +import type { DecoratedViewFunction } from '@polkadot/types/metadata/decorate/types'; // types export type { Signer, SignerResult } from '@polkadot/types/types'; @@ -43,6 +49,14 @@ export * from '@polkadot/api-base/types'; // A smaller interface of ApiRx, used in derive and in SubmittableExtrinsic export interface ApiInterfaceRx extends ApiInterfaceBase { derive: AllDerives<'rxjs'>; + readonly query: QueryableStorage<'rxjs'>; + readonly queryAt: QueryableStorageAt<'rxjs'>; + readonly queryMulti: QueryableStorageMulti<'rxjs'>; + readonly registry: Registry; + readonly rpc: DecoratedRpc<'rxjs', RpcInterface>; + readonly runtimeVersion: RuntimeVersion; + readonly tx: SubmittableExtrinsics<'rxjs'>; + readonly view: QueryableViewFunctions<'rxjs'>; } export interface ApiOptions extends RegisteredTypes { @@ -117,6 +131,25 @@ export interface SignerOptions extends SignatureOptions { genesisHash: Hash; } +export interface QueryableCalls { + [section: string]: { + [method: string]: AugmentedCall; + }; +} + +// New Type: Represents a single decorated view function +export interface AugmentedViewFunction extends IMethod { + (...args: any[]): Observable; + meta: DecoratedViewFunction; +} + +// New Type: Represents the `api.view` section holding all view functions +export interface QueryableViewFunctions { + [section: string]: { + [method: string]: AugmentedViewFunction; + }; +} + export interface ApiDecoration { call: QueryableCalls; consts: QueryableConsts; @@ -124,12 +157,10 @@ export interface ApiDecoration { events: DecoratedEvents; query: QueryableStorage; registry: Registry; - runtimeVersion: RuntimeVersionPartial; - rx: { - call: QueryableCalls<'rxjs'>; - query: QueryableStorage<'rxjs'>; - }; - tx: (extrinsic: Call | Extrinsic | Uint8Array | string) => SubmittableExtrinsic; + runtimeVersion: RuntimeVersion; + rx: ApiInterfaceRx; + tx: SubmittableExtrinsics; + view: QueryableViewFunctions; findCall (callIndex: Uint8Array | string): CallFunction; findError (errorIndex: Uint8Array | string): RegistryError; diff --git a/packages/types/src/interfaces/metadata/index.ts b/packages/types/src/interfaces/metadata/index.ts index 7f1de782f76f..f5fc6c8c345c 100644 --- a/packages/types/src/interfaces/metadata/index.ts +++ b/packages/types/src/interfaces/metadata/index.ts @@ -1,4 +1,14 @@ // Auto-generated via `yarn polkadot-types-from-defs`, do not edit /* eslint-disable */ +export * from './definitions.js'; +export * from './latest.js'; export * from './types.js'; +export * from './v9.js'; +export * from './v10.js'; +export * from './v11.js'; +export * from './v12.js'; +export * from './v13.js'; +export * from './v14.js'; +export * from './v15.js'; +export * from './v16.js'; diff --git a/packages/types/src/interfaces/metadata/types.ts b/packages/types/src/interfaces/metadata/types.ts index b60cd7bc8891..57eb06f4dbfc 100644 --- a/packages/types/src/interfaces/metadata/types.ts +++ b/packages/types/src/interfaces/metadata/types.ts @@ -184,11 +184,13 @@ export interface MetadataAll extends Enum { readonly asV14: MetadataV14; readonly isV15: boolean; readonly asV15: MetadataV15; - readonly type: 'V0' | 'V1' | 'V2' | 'V3' | 'V4' | 'V5' | 'V6' | 'V7' | 'V8' | 'V9' | 'V10' | 'V11' | 'V12' | 'V13' | 'V14' | 'V15'; + readonly isV16: boolean; + readonly asV16: MetadataV16; + readonly type: 'V0' | 'V1' | 'V2' | 'V3' | 'V4' | 'V5' | 'V6' | 'V7' | 'V8' | 'V9' | 'V10' | 'V11' | 'V12' | 'V13' | 'V14' | 'V15' | 'V16'; } /** @name MetadataLatest */ -export interface MetadataLatest extends MetadataV15 {} +export interface MetadataLatest extends MetadataV16 {} /** @name MetadataV10 */ export interface MetadataV10 extends Struct { @@ -219,6 +221,9 @@ export interface MetadataV14 extends Struct { readonly pallets: Vec; readonly extrinsic: ExtrinsicMetadataV14; readonly type: SiLookupTypeId; + readonly apis: Vec; + readonly outerEnums: OuterEnums; + readonly custom: CustomMetadata; } /** @name MetadataV15 */ @@ -228,8 +233,17 @@ export interface MetadataV15 extends Struct { readonly extrinsic: ExtrinsicMetadataV15; readonly type: SiLookupTypeId; readonly apis: Vec; - readonly outerEnums: OuterEnums15; - readonly custom: CustomMetadata15; + readonly custom: CustomMetadata; +} + +/** @name MetadataV16 */ +export interface MetadataV16 extends Struct { + readonly lookup: PortableRegistry; + readonly pallets: Vec; + readonly extrinsic: ExtrinsicMetadataLatest; + readonly type: SiLookupTypeId; + readonly apis: Vec; + readonly custom: CustomMetadata; } /** @name MetadataV9 */ @@ -312,11 +326,11 @@ export interface ModuleMetadataV9 extends Struct { /** @name OpaqueMetadata */ export interface OpaqueMetadata extends WrapperOpaque {} -/** @name OuterEnums15 */ -export interface OuterEnums15 extends Struct { - readonly callType: SiLookupTypeId; - readonly eventType: SiLookupTypeId; - readonly errorType: SiLookupTypeId; +/** @name OuterEnums */ +export interface OuterEnums extends Struct { + readonly callEnumType: SiLookupTypeId; + readonly errorEnumType: SiLookupTypeId; + readonly eventEnumType: SiLookupTypeId; } /** @name PalletCallMetadataLatest */ @@ -355,7 +369,7 @@ export interface PalletEventMetadataV14 extends Struct { } /** @name PalletMetadataLatest */ -export interface PalletMetadataLatest extends PalletMetadataV15 {} +export interface PalletMetadataLatest extends PalletMetadataV16 {} /** @name PalletMetadataV14 */ export interface PalletMetadataV14 extends Struct { @@ -694,4 +708,79 @@ export interface StorageMetadataV9 extends Struct { readonly items: Vec; } +/** @name CustomMetadata */ +export interface CustomMetadata extends Struct { + readonly map: Vec; +} + +/** @name CustomMetadataTuple */ +export type CustomMetadataTuple = [Text, CustomValueMetadata]; + +/** @name CustomValueMetadata */ +export interface CustomValueMetadata extends Struct { + readonly type: SiLookupTypeId; + readonly value: Bytes; +} + +/** @name PortableRegistry */ +export interface PortableRegistry extends Struct { + readonly types: Vec; +} + +/** @name PortableType */ +export interface PortableType extends Struct { + readonly id: SiLookupTypeId; + readonly type: SiType; +} + +/** @name RuntimeApiMetadataLatest */ +export interface RuntimeApiMetadataLatest extends RuntimeApiMetadataV15 {} + +/** @name RuntimeApiMethodMetadataLatest */ +export interface RuntimeApiMethodMetadataLatest extends RuntimeApiMethodMetadataV15 {} + +/** @name RuntimeApiMethodParamMetadataLatest */ +export interface RuntimeApiMethodParamMetadataLatest extends Struct { + readonly name: Text; + readonly type: SiLookupTypeId; +} + +/** @name SignedExtensionMetadataLatest */ +export interface SignedExtensionMetadataLatest extends SignedExtensionMetadataV14 {} + +/** @name StorageEntryModifierLatest */ +export interface StorageEntryModifierLatest extends StorageEntryModifierV14 {} + +/** @name StorageEntryTypeLatest */ +export interface StorageEntryTypeLatest extends StorageEntryTypeV14 {} + +/** @name StorageHasherLatest */ +export interface StorageHasherLatest extends StorageHasherV14 {} + +/** @name MetadataEnum */ +export interface MetadataEnum extends Struct { + readonly V0: MetadataV0; + readonly V1: MetadataV1; + readonly V2: MetadataV2; + readonly V3: MetadataV3; + readonly V4: MetadataV4; + readonly V5: MetadataV5; + readonly V6: MetadataV6; + readonly V7: MetadataV7; + readonly V8: MetadataV8; + readonly V9: MetadataV9; + readonly V10: MetadataV10; + readonly V11: MetadataV11; + readonly V12: MetadataV12; + readonly V13: MetadataV13; + readonly V14: MetadataV14; + readonly V15: MetadataV15; + readonly V16: MetadataV16; +} + +/** @name MetadataAll */ +export type MetadataAll = MetadataV0 | MetadataV1 | MetadataV2 | MetadataV3 | MetadataV4 | MetadataV5 | MetadataV6 | MetadataV7 | MetadataV8 | MetadataV9 | MetadataV10 | MetadataV11 | MetadataV12 | MetadataV13 | MetadataV14 | MetadataV15 | MetadataV16; + +export interface MetadataLatest extends MetadataV16 {} + export type PHANTOM_METADATA = 'metadata'; diff --git a/packages/types/src/interfaces/metadata/v16.ts b/packages/types/src/interfaces/metadata/v16.ts new file mode 100644 index 000000000000..45486a15f7a0 --- /dev/null +++ b/packages/types/src/interfaces/metadata/v16.ts @@ -0,0 +1,34 @@ +// Copyright 2017-2025 @polkadot/types authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +// import type { SiLookupTypeId } from '../../primitive/types.js'; +// import type { PalletCallMetadataV14, PalletConstantMetadataV14, PalletErrorMetadataV14, PalletEventMetadataV14, PalletStorageMetadataV14 } from './v14.js'; + +// NOTE: The imports above are commented out as they might not be directly needed +// if v16 reuses v15 structures or has its own complete definitions. +// This will need to be adjusted based on the actual V16 spec. + +export interface PalletViewFunctionArgumentMetadataV16 extends Struct { + readonly name: Text; + readonly type: SiLookupTypeId; // Assuming it uses SiLookupTypeId like other metadata parts + // readonly typeName: Option; // Optionally, if type name is directly included +} + +export interface PalletViewFunctionMetadataV16 extends Struct { + readonly name: Text; + readonly args: Vec; + readonly returnType: SiLookupTypeId; // Assuming it uses SiLookupTypeId + // readonly returnTypeName: Option; // Optionally, if type name is directly included + readonly docs: Vec; +} + +export interface PalletMetadataV16 extends Struct { + readonly name: Text; + readonly storage: Option; // Assuming V14/V15 structure for now + readonly calls: Option; // Assuming V14/V15 structure for now + readonly events: Option; // Assuming V14/V15 structure for now + readonly constants: Vec; // Assuming V14/V15 structure for now + readonly errors: Option; // Assuming V14/V15 structure for now + readonly viewFunctions: Vec; // The new field + readonly index: u8; +} \ No newline at end of file diff --git a/packages/types/src/metadata/MetadataVersioned.ts b/packages/types/src/metadata/MetadataVersioned.ts index 8ae3a3d2dd13..b7125a900e58 100644 --- a/packages/types/src/metadata/MetadataVersioned.ts +++ b/packages/types/src/metadata/MetadataVersioned.ts @@ -3,7 +3,7 @@ import type { AnyJson } from '@polkadot/types-codec/types'; import type { HexString } from '@polkadot/util/types'; -import type { MetadataAll, MetadataLatest, MetadataV9, MetadataV10, MetadataV11, MetadataV12, MetadataV13, MetadataV14, MetadataV15 } from '../interfaces/metadata/index.js'; +import type { MetadataAll, MetadataLatest, MetadataV9, MetadataV10, MetadataV11, MetadataV12, MetadataV13, MetadataV14, MetadataV15, MetadataV16 } from '../interfaces/metadata/index.js'; import type { Registry } from '../types/index.js'; import type { MetaVersionAll, MetaVersionAsX } from './versions.js'; @@ -16,7 +16,8 @@ import { toV12 } from './v11/toV12.js'; import { toV13 } from './v12/toV13.js'; import { toV14 } from './v13/toV14.js'; import { toV15 } from './v14/toV15.js'; -import { toLatest } from './v15/toLatest.js'; +import { toV16 } from './v15/toV16.js'; +import { toLatest } from './v16/toLatest.js'; import { MagicNumber } from './MagicNumber.js'; import { LATEST_VERSION, TO_CALLS_VERSION } from './versions.js'; @@ -61,8 +62,12 @@ export class MetadataVersioned extends Struct { const asPrev: MetaVersionAsX = version === 'latest' ? `asV${LATEST_VERSION}` : `asV${(version - 1) as MetaVersionAll}`; + + const prevInput = version === 'latest' + ? this.asV16 as F + : this[asPrev] as F; - this.#converted.set(version, fromPrev(this.registry, this[asPrev] as F, this.version)); + this.#converted.set(version, fromPrev(this.registry, prevInput, this.version)); } return this.#converted.get(version) as T; @@ -130,17 +135,24 @@ export class MetadataVersioned extends Struct { } /** - * @description Returns the wrapped values as a V14 object + * @description Returns the wrapped values as a V15 object */ public get asV15 (): MetadataV15 { return this.#getVersion(15, toV15); } + /** + * @description Returns the wrapped values as a V16 object + */ + public get asV16 (): MetadataV16 { + return this.#getVersion(16, toV16); + } + /** * @description Returns the wrapped values as a latest version object */ public get asLatest (): MetadataLatest { - return this.#getVersion('latest', toLatest); + return this.#getVersion('latest', toLatest as (registry: Registry, input: MetadataV16, metaVersion: number) => MetadataLatest); } /** diff --git a/packages/types/src/metadata/decorate/types.ts b/packages/types/src/metadata/decorate/types.ts index 3dbf954d07a5..b9563bfc1fe8 100644 --- a/packages/types/src/metadata/decorate/types.ts +++ b/packages/types/src/metadata/decorate/types.ts @@ -5,6 +5,10 @@ import type { AnyTuple, Codec, Registry } from '@polkadot/types-codec/types'; import type { DispatchErrorModule, DispatchErrorModuleU8, DispatchErrorModuleU8a, ErrorMetadataLatest, EventMetadataLatest, PalletConstantMetadataLatest } from '../../interfaces/index.js'; import type { StorageEntry } from '../../primitive/types.js'; import type { CallFunction, IEvent, IEventLike } from '../../types/index.js'; +import type { Text } from '@polkadot/types'; +import type { TypeDef } from '@polkadot/types/types'; +import type { PalletViewFunctionMetadataV16 } from '@polkadot/types/interfaces/metadata/v16'; +import type { PalletConstantMeta, PalletErrorMeta, PalletEventMeta, PalletStorageMeta } from '@polkadot/types/interfaces/metadata/types'; export interface ConstantCodec extends Codec { readonly meta: PalletConstantMetadataLatest; @@ -43,10 +47,31 @@ export type Extrinsics = Record export type Storage = Record; export interface DecoratedMeta { - readonly consts: Constants; - readonly errors: Errors; - readonly events: Events; - readonly query: Storage; + readonly consts: Record>; + readonly errors: Record>; + readonly events: Record>; + readonly query: Record>; readonly registry: Registry; - readonly tx: Extrinsics + readonly tx: Record>; + readonly view: DecoratedView; } + +// New types for View Functions +export interface DecoratedViewFunctionArg { + name: string; + typeDef: TypeDef; + typeName?: Text; // Optional: May not always be available directly +} + +export interface DecoratedViewFunction { + args: DecoratedViewFunctionArg[]; + docs: string[]; + meta: PalletViewFunctionMetadataV16; + method: string; // camelCase name + name: string; // original name + pallet: string; // camelCase pallet name + returnTypeDef: TypeDef; + section: string; // camelCase pallet name +} + +export type DecoratedView = Record>; diff --git a/packages/types/src/metadata/decorate/viewFunctions/index.ts b/packages/types/src/metadata/decorate/viewFunctions/index.ts new file mode 100644 index 000000000000..058791bbad7c --- /dev/null +++ b/packages/types/src/metadata/decorate/viewFunctions/index.ts @@ -0,0 +1,61 @@ +// Copyright 2017-2025 @polkadot/types authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { Registry } from '@polkadot/types-codec/types'; +import type { MetadataLatest, PalletMetadataV16, PalletViewFunctionMetadataV16 } from '../../interfaces/metadata/index.js'; +import type { Text } from '@polkadot/types'; +import type { DecoratedView, DecoratedViewFunction } from '../types.js'; + +import { stringCamelCase } from '@polkadot/util'; + +/** @internal */ +function getLookup (registry: Registry) { + // Helper to get the PortableRegistry lookup interface + return registry.lookup; +} + +/** @internal */ +export function decorateViewFunctions (registry: Registry, metadata: MetadataLatest, _version: number): DecoratedView { + const result: DecoratedView = {}; + const lookup = getLookup(registry); + const pallets = metadata.pallets; + + for (let i = 0; i < pallets.length; i++) { + const pallet = pallets[i] as PalletMetadataV16; // Cast here, assuming metadata is V16 + + // Check if the pallet has viewFunctions (only V16+ will) + // Need a safer check if MetadataLatest could contain older pallet types + if (pallet.viewFunctions && pallet.viewFunctions.length > 0) { + const palletName = stringCamelCase(pallet.name); + const section: Record = {}; + + for (let j = 0; j < pallet.viewFunctions.length; j++) { + const viewMeta = pallet.viewFunctions[j]; + const functionName = stringCamelCase(viewMeta.name); + + section[functionName] = { + args: viewMeta.args.map(({ name, type }) => ({ + name: name.toString(), + // Get type definition from lookup + typeDef: lookup.getTypeDef(type), + typeName: name // Pass the Text name + })), + docs: viewMeta.docs.map((d) => d.toString()), + meta: viewMeta, // Store the raw metadata + method: functionName, + name: viewMeta.name.toString(), // Original name + pallet: palletName, + // Get return type definition from lookup + returnTypeDef: lookup.getTypeDef(viewMeta.returnType), + section: palletName + }; + } + + if (Object.keys(section).length !== 0) { + result[palletName] = section; + } + } + } + + return result; +} \ No newline at end of file diff --git a/packages/types/src/metadata/v15/toLatest.ts b/packages/types/src/metadata/v15/toLatest.ts deleted file mode 100644 index 646e8a1f2c35..000000000000 --- a/packages/types/src/metadata/v15/toLatest.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017-2025 @polkadot/types authors & contributors -// SPDX-License-Identifier: Apache-2.0 - -import type { Registry } from '@polkadot/types-codec/types'; -import type { MetadataLatest, MetadataV15 } from '../../interfaces/metadata/index.js'; - -/** - * Convert the Metadata (which is an alias) to latest - * @internal - **/ -export function toLatest (_registry: Registry, v15: MetadataV15, _metaVersion: number): MetadataLatest { - return v15; -} diff --git a/packages/types/src/metadata/v15/toV16.ts b/packages/types/src/metadata/v15/toV16.ts new file mode 100644 index 000000000000..0110ae5a0446 --- /dev/null +++ b/packages/types/src/metadata/v15/toV16.ts @@ -0,0 +1,31 @@ +// Copyright 2017-2025 @polkadot/types authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { Registry } from '@polkadot/types-codec/types'; +import type { MetadataV15, MetadataV16, PalletMetadataV16 } from '../../interfaces/metadata/index.js'; + +/** + * Convert V15 to V16 Metadata + * @internal + **/ +export function toV16 (registry: Registry, v15: MetadataV15, _metaVersion: number): MetadataV16 { + // Pallets will need to be converted individually if their structure changes for V16 + // For now, assuming PalletMetadataV15 can be cast or mapped to PalletMetadataV16 + // with the addition of an empty viewFunctions Vec. + const pallets_V16 = v15.pallets.map((pallet_v15) => { + return registry.createTypeUnsafe('PalletMetadataV16', [{ + ...pallet_v15.toPrimitive(), // Convert PalletMetadataV15 to a plain object + viewFunctions: registry.createTypeUnsafe('Vec', [[]]) + }]); + }); + + return registry.createTypeUnsafe('MetadataV16', [{ + lookup: v15.lookup, + pallets: pallets_V16, + extrinsic: v15.extrinsic, + type: v15.type, + apis: v15.apis, + custom: v15.custom + // NOTE: viewFunctions are part of PalletMetadataV16, not MetadataV16 directly + }]); +} \ No newline at end of file diff --git a/packages/types/src/metadata/v16/toLatest.ts b/packages/types/src/metadata/v16/toLatest.ts new file mode 100644 index 000000000000..54dc7b16b77a --- /dev/null +++ b/packages/types/src/metadata/v16/toLatest.ts @@ -0,0 +1,14 @@ +// Copyright 2017-2025 @polkadot/types authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { Registry } from '@polkadot/types-codec/types'; +import type { MetadataLatest, MetadataV16 } from '../../interfaces/metadata/index.js'; + +/** + * Convert V16 to Latest (which is V16) + * @internal + **/ +export function toLatest (registry: Registry, v16: MetadataV16, metaVersion: number): MetadataLatest { + // V16 is the latest, so we just return it as MetadataLatest + return v16 as MetadataLatest; +} \ No newline at end of file diff --git a/packages/types/src/metadata/versions.ts b/packages/types/src/metadata/versions.ts index 33877d49e17b..0abf5400f704 100644 --- a/packages/types/src/metadata/versions.ts +++ b/packages/types/src/metadata/versions.ts @@ -3,7 +3,7 @@ // Use these to generate all the Meta* types below via template keys // NOTE: Keep from latest -> earliest, see the LATEST_VERSION 0 index -export const KNOWN_VERSIONS = [15, 14, 13, 12, 11, 10, 9] as const; +export const KNOWN_VERSIONS = [16, 15, 14, 13, 12, 11, 10, 9] as const; export const LATEST_VERSION = KNOWN_VERSIONS[0]; // This is part of migration. The toCallsOnly would be usede for esxtensions,