Adjust with current scale-info outputs (#3779)
* Adjust with current scale-info outputs * Linting * Exhaustive check for encoders
This commit is contained in:
@@ -76,13 +76,17 @@ function createHashMap (value: TypeDef, Clazz: typeof BTreeMap | typeof HashMap)
|
||||
}
|
||||
|
||||
const infoMapping: Record<TypeDefInfo, (registry: Registry, value: TypeDef) => Constructor> = {
|
||||
[TypeDefInfo.BTreeMap]: (registry: Registry, value: TypeDef): Constructor => createHashMap(value, BTreeMap),
|
||||
[TypeDefInfo.BTreeMap]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
createHashMap(value, BTreeMap),
|
||||
|
||||
[TypeDefInfo.BTreeSet]: (registry: Registry, value: TypeDef): Constructor => BTreeSet.with(getSubType(value)),
|
||||
[TypeDefInfo.BTreeSet]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
BTreeSet.with(getSubType(value)),
|
||||
|
||||
[TypeDefInfo.Compact]: (registry: Registry, value: TypeDef): Constructor => Compact.with(getSubType(value)),
|
||||
[TypeDefInfo.Compact]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
Compact.with(getSubType(value)),
|
||||
|
||||
[TypeDefInfo.DoNotConstruct]: (registry: Registry, value: TypeDef): Constructor => DoNotConstruct.with(value.displayName || value.type),
|
||||
[TypeDefInfo.DoNotConstruct]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
DoNotConstruct.with(value.displayName || value.type),
|
||||
|
||||
[TypeDefInfo.Enum]: (registry: Registry, value: TypeDef): Constructor => {
|
||||
const subs = getSubDefArray(value);
|
||||
@@ -98,9 +102,11 @@ const infoMapping: Record<TypeDefInfo, (registry: Registry, value: TypeDef) => C
|
||||
);
|
||||
},
|
||||
|
||||
[TypeDefInfo.HashMap]: (registry: Registry, value: TypeDef): Constructor => createHashMap(value, HashMap),
|
||||
[TypeDefInfo.HashMap]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
createHashMap(value, HashMap),
|
||||
|
||||
[TypeDefInfo.Int]: (registry: Registry, value: TypeDef): Constructor => createInt(value, Int),
|
||||
[TypeDefInfo.Int]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
createInt(value, Int),
|
||||
|
||||
// We have circular deps between Linkage & Struct
|
||||
[TypeDefInfo.Linkage]: (registry: Registry, value: TypeDef): Constructor => {
|
||||
@@ -118,9 +124,11 @@ const infoMapping: Record<TypeDefInfo, (registry: Registry, value: TypeDef) => C
|
||||
},
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
[TypeDefInfo.Null]: (registry: Registry, _: TypeDef): Constructor => createClass(registry, 'Null'),
|
||||
[TypeDefInfo.Null]: (registry: Registry, _: TypeDef): Constructor =>
|
||||
createClass(registry, 'Null'),
|
||||
|
||||
[TypeDefInfo.Option]: (registry: Registry, value: TypeDef): Constructor => Option.with(getSubType(value)),
|
||||
[TypeDefInfo.Option]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
Option.with(getSubType(value)),
|
||||
|
||||
[TypeDefInfo.Plain]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
registry.getOrUnknown(value.type),
|
||||
@@ -145,11 +153,17 @@ const infoMapping: Record<TypeDefInfo, (registry: Registry, value: TypeDef) => C
|
||||
);
|
||||
},
|
||||
|
||||
[TypeDefInfo.Struct]: (registry: Registry, value: TypeDef): Constructor => Struct.with(getTypeClassMap(value), value.alias),
|
||||
[TypeDefInfo.Si]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
getTypeClass(registry, registry.lookup.getTypeDef(value.index as number)),
|
||||
|
||||
[TypeDefInfo.Tuple]: (registry: Registry, value: TypeDef): Constructor => Tuple.with(getTypeClassArray(value)),
|
||||
[TypeDefInfo.Struct]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
Struct.with(getTypeClassMap(value), value.alias),
|
||||
|
||||
[TypeDefInfo.UInt]: (registry: Registry, value: TypeDef): Constructor => createInt(value, UInt),
|
||||
[TypeDefInfo.Tuple]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
Tuple.with(getTypeClassArray(value)),
|
||||
|
||||
[TypeDefInfo.UInt]: (registry: Registry, value: TypeDef): Constructor =>
|
||||
createInt(value, UInt),
|
||||
|
||||
[TypeDefInfo.Vec]: (registry: Registry, value: TypeDef): Constructor => {
|
||||
const subType = getSubType(value);
|
||||
|
||||
@@ -111,6 +111,7 @@ const encoders: Record<TypeDefInfo, (typeDef: TypeDef) => string> = {
|
||||
[TypeDefInfo.Plain]: (typeDef: TypeDef): string => typeDef.displayName || typeDef.type,
|
||||
[TypeDefInfo.Result]: (typeDef: TypeDef): string => encodeWithParams(typeDef, 'Result'),
|
||||
[TypeDefInfo.Set]: (typeDef: TypeDef): string => typeDef.type,
|
||||
[TypeDefInfo.Si]: (typeDef: TypeDef): string => typeDef.type,
|
||||
[TypeDefInfo.Struct]: (typeDef: TypeDef): string => encodeStruct(typeDef),
|
||||
[TypeDefInfo.Tuple]: (typeDef: TypeDef): string => encodeTuple(typeDef),
|
||||
[TypeDefInfo.UInt]: (typeDef: TypeDef): string => encodeUInt(typeDef, 'UInt'),
|
||||
@@ -121,13 +122,13 @@ const encoders: Record<TypeDefInfo, (typeDef: TypeDef) => string> = {
|
||||
function encodeType (typeDef: TypeDef): string {
|
||||
const encoder = encoders[typeDef.info];
|
||||
|
||||
assert(encoder, () => `Cannot encode type: ${stringify(typeDef)}`);
|
||||
assert(encoder, () => `Cannot encode type: info=${typeDef.info}, typeDef=${stringify(typeDef)}`);
|
||||
|
||||
return encoder(typeDef);
|
||||
}
|
||||
|
||||
export function encodeTypeDef (typeDef: TypeDef): string {
|
||||
assert(!isUndefined(typeDef.info), () => `Invalid type definition with no instance info, ${stringify(typeDef)}`);
|
||||
assert(!isUndefined(typeDef.info), () => `Invalid type definition with no instance info, typeDef=${stringify(typeDef)}`);
|
||||
|
||||
// In the case of contracts we do have the unfortunate situation where the displayName would
|
||||
// refer to "Option" when it is an option. For these, string it out, only using when actually
|
||||
|
||||
@@ -26,6 +26,7 @@ export enum TypeDefInfo {
|
||||
Int,
|
||||
UInt,
|
||||
DoNotConstruct,
|
||||
Si,
|
||||
// anything not fully supported (keep this as the last entry)
|
||||
Null
|
||||
}
|
||||
|
||||
@@ -4,22 +4,15 @@
|
||||
import type { Vec } from '../codec/Vec';
|
||||
import type { PortableType } from '../interfaces/metadata';
|
||||
import type { SiField, SiLookupTypeId, SiType, SiTypeDefArray, SiTypeDefCompact, SiTypeDefComposite, SiTypeDefSequence, SiTypeDefTuple, SiTypeDefVariant, SiVariant } from '../interfaces/scaleInfo';
|
||||
import type { Codec, Constructor, Registry, TypeDef } from '../types';
|
||||
import type { Registry, TypeDef } from '../types';
|
||||
|
||||
import { assert, isNumber, isString, stringCamelCase } from '@polkadot/util';
|
||||
|
||||
import { Option } from '../codec/Option';
|
||||
import { Struct } from '../codec/Struct';
|
||||
import { getTypeClass } from '../create/createClass';
|
||||
import { withTypeString } from '../create/encodeTypes';
|
||||
import { getTypeDef } from '../create/getTypeDef';
|
||||
import { TypeDefInfo } from '../types';
|
||||
|
||||
interface CreateOptions {
|
||||
blockHash?: Uint8Array | string | null;
|
||||
isOptional?: boolean;
|
||||
}
|
||||
|
||||
const PRIMITIVE_ALIAS: Record<string, string> = {
|
||||
Char: 'u32', // Rust char is 4-bytes
|
||||
Str: 'Text'
|
||||
@@ -30,7 +23,6 @@ const INK_PRIMITIVE_ALWAYS = ['AccountId', 'AccountIndex', 'Address', 'Balance']
|
||||
const LOOKUP_PREFIX = '__lookup_';
|
||||
|
||||
export class GenericPortableRegistry extends Struct {
|
||||
#classes: Record<number, Constructor> = {};
|
||||
#typeDefs: Record<number, TypeDef> = {};
|
||||
|
||||
constructor (registry: Registry, value?: Uint8Array) {
|
||||
@@ -60,34 +52,6 @@ export class GenericPortableRegistry extends Struct {
|
||||
return `${LOOKUP_PREFIX}${lookupId.toString()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description creates a type from the id
|
||||
*/
|
||||
public createType <T extends Codec> (lookupId: SiLookupTypeId | string | number, params: unknown[], { blockHash, isOptional }: CreateOptions = {}): T {
|
||||
const Clazz = this.getClass<T>(lookupId);
|
||||
const instance = new (isOptional ? Option.with(Clazz) : Clazz)(this.registry, ...params);
|
||||
|
||||
if (blockHash) {
|
||||
instance.createdAtHash = this.registry.createType('Hash', blockHash);
|
||||
}
|
||||
|
||||
return instance as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns a class from the specified id
|
||||
*/
|
||||
public getClass <T extends Codec = Codec> (lookupId: SiLookupTypeId | string | number): Constructor<T> {
|
||||
const index = this.#getSiIndex(lookupId);
|
||||
|
||||
if (!this.#classes[index]) {
|
||||
// since we may have recursive lookups, fill in empty details as a start
|
||||
this.#classes[index] = getTypeClass(this.registry, this.getTypeDef(lookupId));
|
||||
}
|
||||
|
||||
return this.#classes[index] as Constructor<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Finds a specific type in the registry
|
||||
*/
|
||||
@@ -106,22 +70,21 @@ export class GenericPortableRegistry extends Struct {
|
||||
const index = this.#getSiIndex(lookupId);
|
||||
|
||||
if (!this.#typeDefs[index]) {
|
||||
// since we may have recursive lookups, fill in empty details as a start
|
||||
this.#typeDefs[index] = { info: TypeDefInfo.DoNotConstruct, type: this.createSiString(index) };
|
||||
const typeDef = this.#extract(this.getSiType(lookupId), lookupId);
|
||||
|
||||
const siType = this.getSiType(lookupId);
|
||||
|
||||
Object.entries(this.#extract(siType, lookupId)).forEach(([k, v]): void => {
|
||||
/* eslint-disable */
|
||||
// @ts-ignore Yes... these are crappy, however we do go through key/values, so all safe
|
||||
this.#typeDefs[index][k] = v;
|
||||
/* eslint-enable */
|
||||
});
|
||||
this.#typeDefs[index] = typeDef;
|
||||
}
|
||||
|
||||
return this.#typeDefs[index];
|
||||
}
|
||||
|
||||
#createSiDef (type: SiLookupTypeId): TypeDef {
|
||||
return {
|
||||
info: TypeDefInfo.Si,
|
||||
type: this.createSiString(type)
|
||||
};
|
||||
}
|
||||
|
||||
#getSiIndex (lookupId: SiLookupTypeId | string | number): number {
|
||||
if (isString(lookupId)) {
|
||||
assert(this.isSiString(lookupId), () => `PortableRegistry: Expected a lookup string type, found ${lookupId}`);
|
||||
@@ -181,10 +144,6 @@ export class GenericPortableRegistry extends Struct {
|
||||
? { namespace: path.map((s) => s.toString()).join('::') }
|
||||
: {}
|
||||
),
|
||||
...(type.params.length > 0
|
||||
? { sub: type.params.filter(({ type }) => type.isSome).map(({ type }) => this.getTypeDef(type.unwrap())) }
|
||||
: {}
|
||||
),
|
||||
...typeDef
|
||||
});
|
||||
}
|
||||
@@ -195,14 +154,14 @@ export class GenericPortableRegistry extends Struct {
|
||||
return {
|
||||
info: TypeDefInfo.VecFixed,
|
||||
length: length.toNumber(),
|
||||
sub: this.getTypeDef(type)
|
||||
sub: this.#createSiDef(type)
|
||||
};
|
||||
}
|
||||
|
||||
#extractCompact ({ type }: SiTypeDefCompact): Omit<TypeDef, 'type'> {
|
||||
return {
|
||||
info: TypeDefInfo.Compact,
|
||||
sub: this.getTypeDef(type)
|
||||
sub: this.#createSiDef(type)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -219,23 +178,35 @@ export class GenericPortableRegistry extends Struct {
|
||||
|
||||
assert(isTuple || isStruct, 'PortableRegistry: Invalid fields type detected, expected either Tuple or Struct');
|
||||
|
||||
const sub = fields.map(({ name, type }) => ({
|
||||
...this.getTypeDef(type),
|
||||
...(name.isSome
|
||||
? { name: stringCamelCase(name.unwrap()) }
|
||||
: {}
|
||||
)
|
||||
}));
|
||||
if (isTuple) {
|
||||
if (fields.length === 0) {
|
||||
return {
|
||||
info: TypeDefInfo.Null
|
||||
};
|
||||
} else if (fields.length === 1) {
|
||||
return {
|
||||
...this.getTypeDef(fields[0].type),
|
||||
...(fields[0].name.isSome
|
||||
? { name: stringCamelCase(fields[0].name.unwrap()) }
|
||||
: {}
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return isTuple && sub.length === 1
|
||||
? sub[0]
|
||||
: {
|
||||
// check for tuple first (no fields may be available)
|
||||
info: isTuple
|
||||
? TypeDefInfo.Tuple
|
||||
: TypeDefInfo.Struct,
|
||||
sub
|
||||
};
|
||||
return {
|
||||
// check for tuple first (no fields may be available)
|
||||
info: isTuple
|
||||
? TypeDefInfo.Tuple
|
||||
: TypeDefInfo.Struct,
|
||||
sub: fields.map(({ name, type }) => ({
|
||||
...this.#createSiDef(type),
|
||||
...(name.isSome
|
||||
? { name: stringCamelCase(name.unwrap()) }
|
||||
: {}
|
||||
)
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
#extractPrimitive (type: SiType): TypeDef {
|
||||
@@ -259,7 +230,7 @@ export class GenericPortableRegistry extends Struct {
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Vec,
|
||||
sub: this.getTypeDef(type)
|
||||
sub: this.#createSiDef(type)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -268,7 +239,7 @@ export class GenericPortableRegistry extends Struct {
|
||||
? this.getTypeDef(ids[0])
|
||||
: {
|
||||
info: TypeDefInfo.Tuple,
|
||||
sub: ids.map((type) => this.getTypeDef(type))
|
||||
sub: ids.map((type) => this.#createSiDef(type))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -279,14 +250,14 @@ export class GenericPortableRegistry extends Struct {
|
||||
return specialVariant === 'Option'
|
||||
? {
|
||||
info: TypeDefInfo.Option,
|
||||
sub: this.getTypeDef(params[0].type.unwrap())
|
||||
sub: this.#createSiDef(params[0].type.unwrap())
|
||||
}
|
||||
: specialVariant === 'Result'
|
||||
? {
|
||||
info: TypeDefInfo.Result,
|
||||
sub: params.map((p, index) => ({
|
||||
name: ['Ok', 'Error'][index],
|
||||
...this.getTypeDef(p.type.unwrap())
|
||||
...this.#createSiDef(p.type.unwrap())
|
||||
}))
|
||||
}
|
||||
: {
|
||||
|
||||
@@ -385,12 +385,8 @@
|
||||
"docs": []
|
||||
}
|
||||
],
|
||||
"index": 0,
|
||||
"docs": [
|
||||
"System digest item that contains the root of changes trie at given",
|
||||
"block. It is created for every block iff runtime supports changes",
|
||||
"trie creation."
|
||||
]
|
||||
"index": 2,
|
||||
"docs": []
|
||||
},
|
||||
{
|
||||
"name": "PreRuntime",
|
||||
@@ -408,21 +404,8 @@
|
||||
"docs": []
|
||||
}
|
||||
],
|
||||
"index": 1,
|
||||
"docs": [
|
||||
"A pre-runtime digest.",
|
||||
"",
|
||||
"These are messages from the consensus engine to the runtime, although",
|
||||
"the consensus engine can (and should) read them itself to avoid",
|
||||
"code and state duplication. It is erroneous for a runtime to produce",
|
||||
"these, but this is not (yet) checked.",
|
||||
"",
|
||||
"NOTE: the runtime is not allowed to panic or fail in an `on_initialize`",
|
||||
"call if an expected `PreRuntime` digest is not present. It is the",
|
||||
"responsibility of a external block verifier to check this. Runtime API calls",
|
||||
"will initialize the block without pre-runtime digests, so initialization",
|
||||
"cannot fail when they are missing."
|
||||
]
|
||||
"index": 6,
|
||||
"docs": []
|
||||
},
|
||||
{
|
||||
"name": "Consensus",
|
||||
@@ -440,12 +423,8 @@
|
||||
"docs": []
|
||||
}
|
||||
],
|
||||
"index": 2,
|
||||
"docs": [
|
||||
"A message from the runtime to the consensus engine. This should *never*",
|
||||
"be generated by the native code of any consensus engine, but this is not",
|
||||
"checked (yet)."
|
||||
]
|
||||
"index": 4,
|
||||
"docs": []
|
||||
},
|
||||
{
|
||||
"name": "Seal",
|
||||
@@ -463,11 +442,8 @@
|
||||
"docs": []
|
||||
}
|
||||
],
|
||||
"index": 3,
|
||||
"docs": [
|
||||
"Put a Seal on it. This is only used by native code, and is never seen",
|
||||
"by runtimes."
|
||||
]
|
||||
"index": 5,
|
||||
"docs": []
|
||||
},
|
||||
{
|
||||
"name": "ChangesTrieSignal",
|
||||
@@ -479,11 +455,8 @@
|
||||
"docs": []
|
||||
}
|
||||
],
|
||||
"index": 4,
|
||||
"docs": [
|
||||
"Digest item that contains signal from changes tries manager to the",
|
||||
"native code."
|
||||
]
|
||||
"index": 7,
|
||||
"docs": []
|
||||
},
|
||||
{
|
||||
"name": "Other",
|
||||
@@ -495,18 +468,13 @@
|
||||
"docs": []
|
||||
}
|
||||
],
|
||||
"index": 5,
|
||||
"docs": [
|
||||
"Some other thing. Unsupported and experimental."
|
||||
]
|
||||
"index": 0,
|
||||
"docs": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"docs": [
|
||||
"Digest item that is able to encode/decode \\'system\\' digest items and",
|
||||
"provide opaque access to other items."
|
||||
]
|
||||
"docs": []
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user