Metadata v16 (#6130)

* Initial scafolding

* metadatav16 generated types

* Correct registry setSignedExtension

* toV16() impl

* Remove references to MetadataV15

* Fix toV16() conversion

* Progress on deprecation notice

* Add deprecationInfo to code generation

* Fix compilation issues

* lint

* Remove console.log()

* Update metadata DeprecationInfo

* Add PalletViewFunctionMetadataV16 and PalletAssociatedTypeMetadataV16

* Add view functions and associatedTypes in toV16

* lint

* Remove u32::max from supported versions

* Tweak v16 types

* Address feedback
This commit is contained in:
Valentin Fernandez
2025-05-16 09:06:40 -03:00
committed by GitHub
parent 08d373ea2c
commit 4e9c3d1978
23 changed files with 728 additions and 94 deletions
+12 -2
View File
@@ -4,7 +4,6 @@
import type { Metadata } from '@polkadot/types/metadata/Metadata';
import type { Definitions } from '@polkadot/types/types';
import type { HexString } from '@polkadot/util/types';
import type { ExtraTypes } from './types.js';
import Handlebars from 'handlebars';
@@ -14,6 +13,7 @@ import { stringCamelCase } from '@polkadot/util';
import { compareName, createImports, formatType, initMeta, readTemplate, setImports, writeFile } from '../util/index.js';
import { ignoreUnusedLookups } from './lookup.js';
import { type ExtraTypes, getDeprecationNotice } from './types.js';
const generateForMetaTemplate = Handlebars.compile(readTemplate('consts'));
@@ -45,10 +45,20 @@ function generateForMeta (meta: Metadata, dest: string, extraTypes: ExtraTypes,
}
const items = constants
.map(({ docs, name, type }) => {
.map(({ deprecationInfo, docs, name, type }) => {
const typeDef = lookup.getTypeDef(type);
const returnType = typeDef.lookupName || formatType(registry, allDefs, typeDef, imports);
if (!deprecationInfo.isNotDeprecated) {
const deprecationNotice = getDeprecationNotice(deprecationInfo, stringCamelCase(name), 'Constant');
const items = docs.length
? ['', deprecationNotice]
: [deprecationNotice];
docs.push(...items.map((text) => registry.createType('Text', text)));
}
// Add the type to the list of used types
if (!(imports.primitiveTypes[returnType])) {
usedTypes.add(returnType);
+30 -10
View File
@@ -1,15 +1,16 @@
// Copyright 2017-2025 @polkadot/typegen authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { VariantDeprecationInfoV16 } from '@polkadot/types/interfaces';
import type { Metadata } from '@polkadot/types/metadata/Metadata';
import type { HexString } from '@polkadot/util/types';
import type { ExtraTypes } from './types.js';
import Handlebars from 'handlebars';
import { stringCamelCase } from '@polkadot/util';
import { compareName, createImports, initMeta, readTemplate, writeFile } from '../util/index.js';
import { type ExtraTypes, getDeprecationNotice } from './types.js';
const generateForMetaTemplate = Handlebars.compile(readTemplate('errors'));
@@ -20,15 +21,34 @@ function generateForMeta (meta: Metadata, dest: string, isStrict: boolean): void
const { lookup, pallets } = meta.asLatest;
const modules = pallets
.filter(({ errors }) => errors.isSome)
.map(({ errors, name }) => ({
items: lookup.getSiType(errors.unwrap().type).def.asVariant.variants
.map(({ docs, name }) => ({
docs,
name: name.toString()
}))
.sort(compareName),
name: stringCamelCase(name)
}))
.map((data) => {
const name = data.name;
const errors = data.errors.unwrap();
const deprecationInfo = errors.deprecationInfo.toJSON();
return {
items: lookup.getSiType(errors.type).def.asVariant.variants
.map(({ docs, index, name }) => {
const rawStatus = deprecationInfo?.[index.toNumber()];
if (rawStatus) {
const deprecationVariantInfo: VariantDeprecationInfoV16 = meta.registry.createTypeUnsafe('VariantDeprecationInfoV16', [rawStatus]);
const deprecationNotice = getDeprecationNotice(deprecationVariantInfo, name.toString());
const notice = docs.length ? ['', deprecationNotice] : [deprecationNotice];
docs.push(...notice.map((text) => meta.registry.createType('Text', text)));
}
return {
docs,
name: name.toString()
};
})
.sort(compareName),
name: stringCamelCase(name)
};
})
.sort(compareName);
return generateForMetaTemplate({
+46 -29
View File
@@ -1,10 +1,10 @@
// Copyright 2017-2025 @polkadot/typegen authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { VariantDeprecationInfoV16 } from '@polkadot/types/interfaces';
import type { Metadata } from '@polkadot/types/metadata/Metadata';
import type { Definitions } from '@polkadot/types/types';
import type { HexString } from '@polkadot/util/types';
import type { ExtraTypes } from './types.js';
import Handlebars from 'handlebars';
@@ -14,6 +14,7 @@ import { stringCamelCase } from '@polkadot/util';
import { compareName, createImports, formatType, initMeta, readTemplate, setImports, writeFile } from '../util/index.js';
import { ignoreUnusedLookups } from './lookup.js';
import { type ExtraTypes, getDeprecationNotice } from './types.js';
const generateForMetaTemplate = Handlebars.compile(readTemplate('events'));
@@ -82,39 +83,55 @@ function generateForMeta (meta: Metadata, dest: string, extraTypes: ExtraTypes,
const usedTypes = new Set<string>([]);
const modules = pallets
.filter(({ events }) => events.isSome)
.map(({ events, name }) => ({
items: lookup.getSiType(events.unwrap().type).def.asVariant.variants
.map(({ docs, fields, name }) => {
const args = fields
.map(({ type }) => lookup.getTypeDef(type))
.map((typeDef) => {
const arg = typeDef.lookupName || formatType(registry, allDefs, typeDef, imports);
.map((data) => {
const name = data.name;
const events = data.events.unwrap();
const deprecationInfo = events.deprecationInfo.toJSON();
// Add the type to the list of used types
if (!(imports.primitiveTypes[arg])) {
usedTypes.add(arg);
}
return {
items: lookup.getSiType(events.type).def.asVariant.variants
.map(({ docs, fields, index, name }) => {
const rawStatus = deprecationInfo?.[index.toNumber()];
return arg;
});
if (rawStatus) {
const deprecationVariantInfo: VariantDeprecationInfoV16 = meta.registry.createTypeUnsafe('VariantDeprecationInfoV16', [rawStatus]);
const deprecationNotice = getDeprecationNotice(deprecationVariantInfo, name.toString());
const notice = docs.length ? ['', deprecationNotice] : [deprecationNotice];
const names = fields
.map(({ name }) => registry.lookup.sanitizeField(name)[0])
.filter((n): n is string => !!n);
docs.push(...notice.map((text) => meta.registry.createType('Text', text)));
}
setImports(allDefs, imports, args);
const args = fields
.map(({ type }) => lookup.getTypeDef(type))
.map((typeDef) => {
const arg = typeDef.lookupName || formatType(registry, allDefs, typeDef, imports);
return {
docs,
name: name.toString(),
type: names.length !== 0 && names.length === args.length
? `[${names.map((n, i) => `${ALIAS.includes(n) ? `${n}_` : n}: ${args[i]}`).join(', ')}], { ${names.map((n, i) => `${n}: ${args[i]}`).join(', ')} }`
: `[${args.join(', ')}]`
};
})
.sort(compareName),
name: stringCamelCase(name)
}))
// Add the type to the list of used types
if (!(imports.primitiveTypes[arg])) {
usedTypes.add(arg);
}
return arg;
});
const names = fields
.map(({ name }) => registry.lookup.sanitizeField(name)[0])
.filter((n): n is string => !!n);
setImports(allDefs, imports, args);
return {
docs,
name: name.toString(),
type: names.length !== 0 && names.length === args.length
? `[${names.map((n, i) => `${ALIAS.includes(n) ? `${n}_` : n}: ${args[i]}`).join(', ')}], { ${names.map((n, i) => `${n}: ${args[i]}`).join(', ')} }`
: `[${args.join(', ')}]`
};
})
.sort(compareName),
name: stringCamelCase(name)
};
})
.sort(compareName);
// filter out the unused lookup types from imports
+12 -2
View File
@@ -6,7 +6,6 @@ import type { Metadata, PortableRegistry } from '@polkadot/types/metadata';
import type { Definitions, Registry } from '@polkadot/types/types';
import type { HexString } from '@polkadot/util/types';
import type { ModuleTypes, TypeImports } from '../util/imports.js';
import type { ExtraTypes } from './types.js';
import Handlebars from 'handlebars';
@@ -17,6 +16,7 @@ import { stringCamelCase } from '@polkadot/util';
import { compareName, createImports, formatType, getSimilarTypes, initMeta, readTemplate, setImports, writeFile } from '../util/index.js';
import { ignoreUnusedLookups } from './lookup.js';
import { type ExtraTypes, getDeprecationNotice } from './types.js';
const generateForMetaTemplate = Handlebars.compile(readTemplate('query'));
@@ -93,8 +93,18 @@ function generateForMeta (registry: Registry, meta: Metadata, dest: string, extr
.map(({ name, storage }) => {
const items = storage.unwrap().items
.map((storageEntry) => {
const { deprecationInfo, docs, name } = storageEntry;
const [isOptional, args, params, _returnType] = entrySignature(lookup, allDefs, registry, name.toString(), storageEntry, imports);
if (!deprecationInfo.isNotDeprecated) {
const deprecationNotice = getDeprecationNotice(deprecationInfo, stringCamelCase(name));
const items = docs.length
? ['', deprecationNotice]
: [deprecationNotice];
docs.push(...items.map((text) => registry.createType('Text', text)));
}
// Add the type and args to the list of used types
if (!(imports.primitiveTypes[_returnType])) {
usedTypes.add(_returnType);
@@ -110,7 +120,7 @@ function generateForMeta (registry: Registry, meta: Metadata, dest: string, extr
return {
args,
docs: storageEntry.docs,
docs,
entryType: 'AugmentedQuery',
name: stringCamelCase(storageEntry.name),
params,
+13 -5
View File
@@ -1,12 +1,11 @@
// Copyright 2017-2025 @polkadot/typegen authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { RuntimeApiMethodMetadataV15, SiLookupTypeId } from '@polkadot/types/interfaces';
import type { RuntimeApiMethodMetadataV16, SiLookupTypeId } from '@polkadot/types/interfaces';
import type { Metadata } from '@polkadot/types/metadata/Metadata';
import type { DefinitionCall, DefinitionCallNamed, Definitions, DefinitionsCall, Registry } from '@polkadot/types/types';
import type { Vec } from '@polkadot/types-codec';
import type { HexString } from '@polkadot/util/types';
import type { ExtraTypes } from './types.js';
import Handlebars from 'handlebars';
@@ -16,6 +15,7 @@ import { objectSpread, stringCamelCase } from '@polkadot/util';
import { blake2AsHex } from '@polkadot/util-crypto';
import { createImports, formatType, getSimilarTypes, initMeta, readTemplate, setImports, writeFile } from '../util/index.js';
import { type ExtraTypes, getDeprecationNotice } from './types.js';
type Apis = [HexString, number][];
@@ -53,14 +53,22 @@ const getTypesViaAlias = (registry: Registry, id: SiLookupTypeId) => {
};
/** @internal */
function getMethods (registry: Registry, methods: Vec<RuntimeApiMethodMetadataV15>) {
function getMethods (registry: Registry, methods: Vec<RuntimeApiMethodMetadataV16>) {
const result: Record<string, DefinitionCall> = {};
methods.forEach((m) => {
const { docs, inputs, name, output } = m;
const { deprecationInfo, docs, inputs, name, output } = m;
let description = docs.map((d) => d.toString()).join();
if (!deprecationInfo.isNotDeprecated) {
const deprecationNotice = getDeprecationNotice(deprecationInfo, stringCamelCase(name));
const notice = description.length ? `\n * ${deprecationNotice}` : ` * ${deprecationNotice}`;
description += notice;
}
result[name.toString()] = {
description: docs.map((d) => d.toString()).join(),
description,
params: inputs.map(({ name, type }) => {
return { name: name.toString(), type: getTypesViaAlias(registry, type) };
}),
+20 -4
View File
@@ -1,11 +1,11 @@
// Copyright 2017-2025 @polkadot/typegen authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { VariantDeprecationInfoV16 } from '@polkadot/types/interfaces';
import type { Metadata } from '@polkadot/types/metadata/Metadata';
import type { Text } from '@polkadot/types/primitive';
import type { Definitions, Registry } from '@polkadot/types/types';
import type { HexString } from '@polkadot/util/types';
import type { ExtraTypes } from './types.js';
import Handlebars from 'handlebars';
@@ -15,6 +15,7 @@ import { stringCamelCase } from '@polkadot/util';
import { compareName, createImports, formatType, getSimilarTypes, initMeta, readTemplate, setImports, writeFile } from '../util/index.js';
import { ignoreUnusedLookups } from './lookup.js';
import { type ExtraTypes, getDeprecationNotice } from './types.js';
const MAPPED_NAMES: Record<string, string> = {
class: 'clazz',
@@ -51,12 +52,26 @@ function generateForMeta (registry: Registry, meta: Metadata, dest: string, extr
const modules = pallets
.sort(compareName)
.filter(({ calls }) => calls.isSome)
.map(({ calls, name }) => {
.map((data) => {
const name = data.name;
const calls = data.calls.unwrap();
const deprecationInfo = calls.deprecationInfo.toJSON();
setImports(allDefs, imports, ['SubmittableExtrinsic']);
const sectionName = stringCamelCase(name);
const items = lookup.getSiType(calls.unwrap().type).def.asVariant.variants
.map(({ docs, fields, name }) => {
const items = lookup.getSiType(calls.type).def.asVariant.variants
.map(({ docs, fields, index, name }) => {
const rawStatus = deprecationInfo?.[index.toNumber()];
if (rawStatus) {
const deprecationVariantInfo: VariantDeprecationInfoV16 = meta.registry.createTypeUnsafe('VariantDeprecationInfoV16', [rawStatus]);
const deprecationNotice = getDeprecationNotice(deprecationVariantInfo, name.toString(), 'Call');
const notice = docs.length ? ['', deprecationNotice] : [deprecationNotice];
docs.push(...notice.map((text) => meta.registry.createType('Text', text)));
}
const typesInfo = fields.map(({ name, type, typeName }, index): [string, string, string] => {
const typeDef = registry.lookup.getTypeDef(type);
@@ -72,6 +87,7 @@ function generateForMeta (registry: Registry, meta: Metadata, dest: string, extr
: typeDef.lookupName || typeDef.type
];
});
const params = typesInfo
.map(([name,, typeStr]) => {
const similarTypes = getSimilarTypes(registry, allDefs, typeStr, imports);
+19
View File
@@ -1,7 +1,26 @@
// Copyright 2017-2025 @polkadot/typegen authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Option, Text } from '@polkadot/types-codec';
export type ExtraTypes = Record<string, Record<string, {
runtime?: Record<string, any>;
types: Record<string, any>;
}>>;
export function getDeprecationNotice<T extends { isDeprecated: boolean; asDeprecated: { note: Text; since: Option<Text> }}> (deprecationInfo: T, name: string, label?: string): string {
let deprecationNotice = '@deprecated';
if (deprecationInfo.isDeprecated) {
const { note, since } = deprecationInfo.asDeprecated;
const sinceText = since.isSome ? ` Since ${since.unwrap().toString()}.` : '';
deprecationNotice += ` ${note.toString()}${sinceText}`;
} else {
const labelText = label ? `${label} ` : '';
deprecationNotice += ` ${labelText}${name} has been deprecated`;
}
return deprecationNotice;
}
+1
View File
@@ -3,6 +3,7 @@
import type { HexString } from '@polkadot/util/types';
// TODO: replace v15 to v16 once metadata is updated
import kusama from '@polkadot/types-support/metadata/v15/kusama-hex';
import polkadot from '@polkadot/types-support/metadata/v15/polkadot-hex';
import substrate from '@polkadot/types-support/metadata/v15/substrate-hex';
+3 -3
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2025 @polkadot/typegen authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { MetadataLatest, RuntimeApiMethodMetadataV15, SiLookupTypeId } from '@polkadot/types/interfaces';
import type { MetadataLatest, RuntimeApiMethodMetadataV16, SiLookupTypeId } from '@polkadot/types/interfaces';
import type { PortableRegistry } from '@polkadot/types/metadata';
import type { Text } from '@polkadot/types/primitive';
import type { Codec, DefinitionCall, DefinitionRpcParam, DefinitionsCall, Registry } from '@polkadot/types/types';
@@ -255,7 +255,7 @@ function addRpc (_runtimeDesc: string, rpcMethods?: string[]): string {
}
/** @internal */
function getMethods (registry: Registry, methods: Vec<RuntimeApiMethodMetadataV15>) {
function getMethods (registry: Registry, methods: Vec<RuntimeApiMethodMetadataV16>) {
const result: Record<string, DefinitionCall> = {};
methods.forEach((m) => {
@@ -614,7 +614,7 @@ function extractDeriveExample (tags: Spec[]) {
let example = '';
const inCodeBlock = { done: false, found: false };
// / Obtain code block from example tag.
// Obtain code block from example tag.
exampleTag.source.forEach((line) => {
if (inCodeBlock.done) {
return;