Allow conversion of v15 metadata (#5631)

* Allow conversion of v15 metadata

* Don't output toCallsOnly in latest known

* Adjust asV* inside metadata conversions

* typo

* CHANGELOG

* CHANGELOG
This commit is contained in:
Jaco
2023-05-07 12:25:40 +03:00
committed by GitHub
parent d436e42bb0
commit 3a3680194d
15 changed files with 68813 additions and 25 deletions
@@ -14,6 +14,7 @@ import { v11 } from './v11.js';
import { v12 } from './v12.js';
import { v13 } from './v13.js';
import { v14 } from './v14.js';
import { v15 } from './v15.js';
export { AllHashers };
@@ -21,26 +22,32 @@ export default {
rpc: {},
runtime,
types: {
// all known
...v9,
...v10,
...v11,
...v12,
...v13,
...v14,
...v15,
// latest mappings
// NOTE: For v15, we only added the runtime defintions,
// hence latest for most pointing to the previous V14
ErrorMetadataLatest: 'ErrorMetadataV14',
EventMetadataLatest: 'EventMetadataV14',
ExtrinsicMetadataLatest: 'ExtrinsicMetadataV14',
FunctionArgumentMetadataLatest: 'FunctionArgumentMetadataV14',
FunctionMetadataLatest: 'FunctionMetadataV14',
MetadataLatest: 'MetadataV14',
MetadataLatest: 'MetadataV15',
PalletCallMetadataLatest: 'PalletCallMetadataV14',
PalletConstantMetadataLatest: 'PalletConstantMetadataV14',
PalletErrorMetadataLatest: 'PalletErrorMetadataV14',
PalletEventMetadataLatest: 'PalletEventMetadataV14',
PalletMetadataLatest: 'PalletMetadataV14',
PalletMetadataLatest: 'PalletMetadataV15',
PalletStorageMetadataLatest: 'PalletStorageMetadataV14',
PortableType: 'PortableTypeV14',
RuntimeApiMetadataLatest: 'RuntimeApiMetadataV15',
SignedExtensionMetadataLatest: 'SignedExtensionMetadataV14',
StorageEntryMetadataLatest: 'StorageEntryMetadataV14',
StorageEntryModifierLatest: 'StorageEntryModifierV14',
@@ -68,7 +75,8 @@ export default {
V11: 'MetadataV11',
V12: 'MetadataV12',
V13: 'MetadataV13',
V14: 'MetadataV14'
V14: 'MetadataV14',
V15: 'MetadataV15'
}
}
}
@@ -161,11 +161,13 @@ export interface MetadataAll extends Enum {
readonly asV13: MetadataV13;
readonly isV14: boolean;
readonly asV14: MetadataV14;
readonly type: 'V0' | 'V1' | 'V2' | 'V3' | 'V4' | 'V5' | 'V6' | 'V7' | 'V8' | 'V9' | 'V10' | 'V11' | 'V12' | 'V13' | 'V14';
readonly isV15: boolean;
readonly asV15: MetadataV15;
readonly type: 'V0' | 'V1' | 'V2' | 'V3' | 'V4' | 'V5' | 'V6' | 'V7' | 'V8' | 'V9' | 'V10' | 'V11' | 'V12' | 'V13' | 'V14' | 'V15';
}
/** @name MetadataLatest */
export interface MetadataLatest extends MetadataV14 {}
export interface MetadataLatest extends MetadataV15 {}
/** @name MetadataV10 */
export interface MetadataV10 extends Struct {
@@ -198,6 +200,15 @@ export interface MetadataV14 extends Struct {
readonly type: SiLookupTypeId;
}
/** @name MetadataV15 */
export interface MetadataV15 extends Struct {
readonly lookup: PortableRegistry;
readonly pallets: Vec<PalletMetadataV15>;
readonly extrinsic: ExtrinsicMetadataV14;
readonly type: SiLookupTypeId;
readonly apis: Vec<RuntimeApiMetadataV15>;
}
/** @name MetadataV9 */
export interface MetadataV9 extends Struct {
readonly modules: Vec<ModuleMetadataV9>;
@@ -314,7 +325,7 @@ export interface PalletEventMetadataV14 extends Struct {
}
/** @name PalletMetadataLatest */
export interface PalletMetadataLatest extends PalletMetadataV14 {}
export interface PalletMetadataLatest extends PalletMetadataV15 {}
/** @name PalletMetadataV14 */
export interface PalletMetadataV14 extends Struct {
@@ -327,6 +338,18 @@ export interface PalletMetadataV14 extends Struct {
readonly index: u8;
}
/** @name PalletMetadataV15 */
export interface PalletMetadataV15 extends Struct {
readonly name: Text;
readonly storage: Option<PalletStorageMetadataV14>;
readonly calls: Option<PalletCallMetadataV14>;
readonly events: Option<PalletEventMetadataV14>;
readonly constants: Vec<PalletConstantMetadataV14>;
readonly errors: Option<PalletErrorMetadataV14>;
readonly index: u8;
readonly docs: Vec<Text>;
}
/** @name PalletStorageMetadataLatest */
export interface PalletStorageMetadataLatest extends PalletStorageMetadataV14 {}
@@ -345,6 +368,30 @@ export interface PortableTypeV14 extends Struct {
readonly type: Si1Type;
}
/** @name RuntimeApiMetadataLatest */
export interface RuntimeApiMetadataLatest extends RuntimeApiMetadataV15 {}
/** @name RuntimeApiMetadataV15 */
export interface RuntimeApiMetadataV15 extends Struct {
readonly name: Text;
readonly methods: Vec<RuntimeApiMethodMetadataV15>;
readonly docs: Vec<Text>;
}
/** @name RuntimeApiMethodMetadataV15 */
export interface RuntimeApiMethodMetadataV15 extends Struct {
readonly name: Text;
readonly inputs: Vec<RuntimeApiMethodParamMetadataV15>;
readonly output: SiLookupTypeId;
readonly docs: Vec<Text>;
}
/** @name RuntimeApiMethodParamMetadataV15 */
export interface RuntimeApiMethodParamMetadataV15 extends Struct {
readonly name: Text;
readonly type: SiLookupTypeId;
}
/** @name SignedExtensionMetadataLatest */
export interface SignedExtensionMetadataLatest extends SignedExtensionMetadataV14 {}
@@ -0,0 +1,45 @@
// Copyright 2017-2023 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
// order important in structs... :)
/* eslint-disable sort-keys */
import type { DefinitionsTypes } from '../../types/index.js';
export const v15: DefinitionsTypes = {
// new/adjusted in v15
PalletMetadataV15: {
name: 'Text',
storage: 'Option<PalletStorageMetadataV14>',
calls: 'Option<PalletCallMetadataV14>',
events: 'Option<PalletEventMetadataV14>',
constants: 'Vec<PalletConstantMetadataV14>',
errors: 'Option<PalletErrorMetadataV14>',
index: 'u8',
docs: 'Vec<Text>'
},
RuntimeApiMetadataV15: {
name: 'Text',
methods: 'Vec<RuntimeApiMethodMetadataV15>',
docs: 'Vec<Text>'
},
RuntimeApiMethodMetadataV15: {
name: 'Text',
inputs: 'Vec<RuntimeApiMethodParamMetadataV15>',
output: 'SiLookupTypeId',
docs: 'Vec<Text>'
},
RuntimeApiMethodParamMetadataV15: {
name: 'Text',
type: 'SiLookupTypeId'
},
// actual v15 definition
MetadataV15: {
lookup: 'PortableRegistry',
pallets: 'Vec<PalletMetadataV15>',
extrinsic: 'ExtrinsicMetadataV14',
type: 'SiLookupTypeId',
apis: 'Vec<RuntimeApiMetadataV15>'
}
};
+9 -1
View File
@@ -29,9 +29,17 @@ for (const type of ['kusama', 'polkadot', 'substrate'] as const) {
});
it('has a sane toCallsOnly', (): void => {
const test = metadata.asCallsOnly;
// it has a useful length
expect(
metadata.asCallsOnly.toU8a().length > 65536
test.toU8a().length > 65536
).toBe(true);
// it sets it to the correct version
expect(
test.version
).toEqual(14);
});
});
}
-2
View File
@@ -26,8 +26,6 @@ function decodeU8a (registry: Registry, u8a: Uint8Array): MetadataVersioned | Ui
return new MetadataVersioned(registry, u8a);
} catch {
u8a[VERSION_IDX] = 10;
return u8a;
}
}
@@ -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 } from '../interfaces/metadata/index.js';
import type { MetadataAll, MetadataLatest, MetadataV9, MetadataV10, MetadataV11, MetadataV12, MetadataV13, MetadataV14, MetadataV15 } from '../interfaces/metadata/index.js';
import type { Registry } from '../types/index.js';
import { Struct } from '@polkadot/types-codec';
@@ -14,18 +14,26 @@ import { toV11 } from './v10/toV11.js';
import { toV12 } from './v11/toV12.js';
import { toV13 } from './v12/toV13.js';
import { toV14 } from './v13/toV14.js';
import { toLatest } from './v14/toLatest.js';
import { toV15 } from './v14/toV15.js';
import { toLatest } from './v15/toLatest.js';
import { MagicNumber } from './MagicNumber.js';
// Use these to generate all the Meta* types below via template keys
// NOTE: Keep from latest -> earliest, see the LATEST_VERSION 0 index
const KNOWN_VERSIONS = [14, 13, 12, 11, 10, 9] as const;
const KNOWN_VERSIONS = [15, 14, 13, 12, 11, 10, 9] as const;
const LATEST_VERSION = KNOWN_VERSIONS[0];
// This is part of migration. The toCallsOnly would be usede for esxtensions,
// i.e. they need to be updated. To ensure that they are passed a known version
// we actually set this to a known-working version
//
// NOTE: This would only work on compatible types, i.e. v14 & v15 comply
const TO_CALLS_VERSION = 14; // LATEST_VERSION;
type MetaAll = typeof KNOWN_VERSIONS[number];
type MetaAsX = `asV${MetaAll}`;
type MetaMapped = MetadataAll[MetaAsX];
type MetaVersions = MetaAll | 'latest';
type MetaVersions = Exclude<MetaAll, 9> | 'latest';
/**
* @name MetadataVersioned
@@ -55,16 +63,17 @@ export class MetadataVersioned extends Struct {
};
#getVersion = <T extends MetaMapped, F extends MetaMapped>(version: MetaVersions, fromPrev: (registry: Registry, input: F, metaVersion: number) => T): T => {
const asCurr = `asV${version}` as MetaAsX;
const asPrev = version === 'latest'
? `asV${LATEST_VERSION}` as MetaAsX
: `asV${version - 1}` as MetaAsX;
if (version !== 'latest' && this.#assertVersion(version)) {
const asCurr: MetaAsX = `asV${version}`;
return this.#metadata()[asCurr] as T;
}
if (!this.#converted.has(version)) {
const asPrev: MetaAsX = version === 'latest'
? `asV${LATEST_VERSION}`
: `asV${(version - 1) as MetaAll}`;
this.#converted.set(version, fromPrev(this.registry, this[asPrev] as F, this.version));
}
@@ -84,7 +93,7 @@ export class MetadataVersioned extends Struct {
public get asCallsOnly (): MetadataVersioned {
return new MetadataVersioned(this.registry, {
magicNumber: this.magicNumber,
metadata: this.registry.createTypeUnsafe('MetadataAll', [toCallsOnly(this.registry, this.asLatest), LATEST_VERSION])
metadata: this.registry.createTypeUnsafe('MetadataAll', [toCallsOnly(this.registry, this.asLatest), TO_CALLS_VERSION])
});
}
@@ -132,6 +141,13 @@ export class MetadataVersioned extends Struct {
return this.#getVersion(14, toV14);
}
/**
* @description Returns the wrapped values as a V14 object
*/
public get asV15 (): MetadataV15 {
return this.#getVersion(15, toV15);
}
/**
* @description Returns the wrapped values as a latest version object
*/
+2 -2
View File
@@ -7,6 +7,6 @@ import type { MetadataV12, MetadataV13 } from '../../interfaces/metadata/index.j
/**
* @internal
**/
export function toV13 (registry: Registry, metadata: MetadataV12): MetadataV13 {
return registry.createTypeUnsafe('MetadataV13', [metadata]);
export function toV13 (registry: Registry, v12: MetadataV12): MetadataV13 {
return registry.createTypeUnsafe('MetadataV13', [v12]);
}
+20
View File
@@ -0,0 +1,20 @@
// Copyright 2017-2023 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { MetadataV14, MetadataV15 } from '../../interfaces/metadata/index.js';
import type { Registry } from '../../types/index.js';
/**
* Convert the Metadata to v15
* @internal
**/
export function toV15 (registry: Registry, v14: MetadataV14, _: number): MetadataV15 {
// V15 is mostly equivalent to v14 however it does add
//
// 1. The top-level apis entry - it is assumed that in usage we would
// just check for all-empty (like this would construct)
// 2. A docs param on the pallet itself
//
// A straight conversion with createTypeUndafe magic fills in details
return registry.createTypeUnsafe('MetadataV15', [v14]);
}
@@ -0,0 +1,12 @@
// Copyright 2017-2023 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import substrateData from '@polkadot/types-support/metadata/v15/substrate-hex';
import { testMeta } from '../util/testUtil.js';
testMeta(15, {
substrate: {
data: substrateData
}
});
@@ -2,12 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
import type { Registry } from '@polkadot/types-codec/types';
import type { MetadataLatest, MetadataV14 } from '../../interfaces/metadata/index.js';
import type { MetadataLatest, MetadataV15 } from '../../interfaces/metadata/index.js';
/**
* Convert the Metadata (which is an alias) to latest
* @internal
**/
export function toLatest (_registry: Registry, v14: MetadataV14, _metaVersion: number): MetadataLatest {
return v14;
export function toLatest (_registry: Registry, v15: MetadataV15, _metaVersion: number): MetadataLatest {
return v15;
}