Cleanup contracts type registry (#1497)
* Cleanup contracts type registry * Remove some ! compiler overrides * More mappy lookups * Empty check
This commit is contained in:
@@ -14,7 +14,7 @@ describe('MetaRegistry', (): void => {
|
||||
describe('construction', (): void => {
|
||||
it('initializes from a contract ABI (ERC20)', (): void => {
|
||||
const metaRegistry = new MetaRegistry(erc20Abi);
|
||||
fs.writeFile(path.join(__dirname, 'erc20.test.json'), JSON.stringify(metaRegistry.typeDefs, null, 2), function (err): void {
|
||||
fs.writeFile(path.join(__dirname, '../test/compare/erc20.test.json'), JSON.stringify(metaRegistry.typeDefs, null, 2), function (err): void {
|
||||
if (err) throw err;
|
||||
});
|
||||
|
||||
@@ -23,7 +23,7 @@ describe('MetaRegistry', (): void => {
|
||||
|
||||
it('initializes from a contract ABI (SharedVec)', (): void => {
|
||||
const metaRegistry = new MetaRegistry(sharedVecAbi);
|
||||
fs.writeFile(path.join(__dirname, 'shared-vec.test.json'), JSON.stringify(metaRegistry.typeDefs, null, 2), function (err): void {
|
||||
fs.writeFile(path.join(__dirname, '../test/compare/shared-vec.test.json'), JSON.stringify(metaRegistry.typeDefs, null, 2), function (err): void {
|
||||
if (err) throw err;
|
||||
});
|
||||
|
||||
|
||||
@@ -7,134 +7,110 @@ import { MetaRegistryItem, MetaRegistryJson, MetaTypeDefClikeEnum, MetaType, Met
|
||||
import { assert } from '@polkadot/util';
|
||||
import { displayType, withTypeString } from '@polkadot/types';
|
||||
|
||||
const {
|
||||
BuiltinPlain,
|
||||
BuiltinTuple,
|
||||
BuiltinVec,
|
||||
BuiltinVecFixed,
|
||||
ClikeEnum,
|
||||
Enum,
|
||||
Struct,
|
||||
TupleStruct,
|
||||
Null
|
||||
} = MetaTypeInfo;
|
||||
const builtinMap: [(id: any) => boolean, MetaTypeInfo][] = [
|
||||
[(id: any): boolean => typeof id === 'string', MetaTypeInfo.BuiltinPlain],
|
||||
[(id: any): boolean => Array.isArray(id), MetaTypeInfo.BuiltinTuple],
|
||||
[(id: any): boolean => !!(id['array.type']), MetaTypeInfo.BuiltinVecFixed],
|
||||
[(id: any): boolean => !!(id['slice.type']), MetaTypeInfo.BuiltinVec]
|
||||
];
|
||||
|
||||
const {
|
||||
String,
|
||||
Type,
|
||||
TypeDef: TypeDefItem
|
||||
} = MetaRegistryItem;
|
||||
const typeMap: [string, MetaTypeInfo][] = [
|
||||
['enum.variants', MetaTypeInfo.Enum],
|
||||
['clike_enum.variants', MetaTypeInfo.ClikeEnum],
|
||||
['struct.fields', MetaTypeInfo.Struct],
|
||||
['tuple_struct.types', MetaTypeInfo.TupleStruct]
|
||||
];
|
||||
|
||||
export default class MetaRegistry {
|
||||
private static detectedType ({ def, id }: MetaType): MetaTypeInfo {
|
||||
assert(!(def as MetaTypeDefUnion)['union.fields'], 'Invalid union type definition found');
|
||||
function detectedType ({ def, id }: MetaType): MetaTypeInfo {
|
||||
assert(!(def as MetaTypeDefUnion)['union.fields'], 'Invalid union type definition found');
|
||||
|
||||
let metaTypeInfo = MetaTypeInfo.Null;
|
||||
if (def === 'builtin') {
|
||||
if (typeof id === 'string') {
|
||||
metaTypeInfo = MetaTypeInfo.BuiltinPlain;
|
||||
}
|
||||
if (Array.isArray(id)) {
|
||||
metaTypeInfo = MetaTypeInfo.BuiltinTuple;
|
||||
}
|
||||
if ((id as MetaTypeIdVec)['slice.type']) {
|
||||
metaTypeInfo = MetaTypeInfo.BuiltinVec;
|
||||
}
|
||||
if ((id as MetaTypeIdVecFixed)['array.type']) {
|
||||
metaTypeInfo = MetaTypeInfo.BuiltinVecFixed;
|
||||
}
|
||||
}
|
||||
const lookup = def === 'builtin'
|
||||
? builtinMap.find(([test]): boolean => test(id))
|
||||
: typeMap.find(([test]): boolean => !!(def as any)[test]);
|
||||
|
||||
if ((def as MetaTypeDefEnum)['enum.variants']) {
|
||||
metaTypeInfo = MetaTypeInfo.Enum;
|
||||
}
|
||||
return lookup
|
||||
? lookup[1]
|
||||
: MetaTypeInfo.Null;
|
||||
}
|
||||
|
||||
if ((def as MetaTypeDefClikeEnum)['clike_enum.variants']) {
|
||||
metaTypeInfo = MetaTypeInfo.ClikeEnum;
|
||||
}
|
||||
class MetadataRegistryLookup {
|
||||
protected _strings: string[] = [];
|
||||
|
||||
if ((def as MetaTypeDefStruct)['struct.fields']) {
|
||||
metaTypeInfo = MetaTypeInfo.Struct;
|
||||
}
|
||||
|
||||
if ((def as MetaTypeDefTupleStruct)['tuple_struct.types']) {
|
||||
metaTypeInfo = MetaTypeInfo.TupleStruct;
|
||||
}
|
||||
|
||||
return metaTypeInfo;
|
||||
}
|
||||
|
||||
private _strings: string[] = [];
|
||||
|
||||
private _types: MetaType[] = [];
|
||||
protected _types: MetaType[] = [];
|
||||
|
||||
public typeDefs: TypeDef[] = [];
|
||||
|
||||
public constructor ({ registry: { strings, types } }: MetaRegistryJson) {
|
||||
this._strings = strings;
|
||||
this._types = types;
|
||||
}
|
||||
|
||||
protected hasItemAt (index: number, variant: MetaRegistryItem): boolean {
|
||||
switch (variant) {
|
||||
case MetaRegistryItem.String:
|
||||
return this._strings && !!this._strings[index - 1];
|
||||
case MetaRegistryItem.Type:
|
||||
return this._types && !!this._types[index - 1];
|
||||
case MetaRegistryItem.TypeDef:
|
||||
return this.typeDefs && !!this.typeDefs[index - 1];
|
||||
}
|
||||
}
|
||||
|
||||
protected itemAt (index: number, variant: MetaRegistryItem): any {
|
||||
assert(this.hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`);
|
||||
|
||||
switch (variant) {
|
||||
case MetaRegistryItem.String:
|
||||
return this._strings[index - 1];
|
||||
case MetaRegistryItem.Type:
|
||||
return this._types[index - 1];
|
||||
case MetaRegistryItem.TypeDef:
|
||||
return this.typeDefs[index - 1];
|
||||
}
|
||||
}
|
||||
|
||||
protected itemsAt (indices: number[], variant: MetaRegistryItem): any[] {
|
||||
return indices.map((index: number): string => this.itemAt(index, variant));
|
||||
}
|
||||
|
||||
protected stringAt (index: StringIndex): string {
|
||||
return this.itemAt(index, MetaRegistryItem.String);
|
||||
}
|
||||
|
||||
public stringsAt (indices: StringIndex[]): string[] {
|
||||
return this.itemsAt(indices, MetaRegistryItem.String);
|
||||
}
|
||||
|
||||
public typeAt (index: TypeIndex): MetaType {
|
||||
return this.itemAt(index, MetaRegistryItem.Type);
|
||||
}
|
||||
|
||||
public typesAt (indices: TypeIndex[]): MetaType[] {
|
||||
return this.itemsAt(indices, MetaRegistryItem.Type);
|
||||
}
|
||||
|
||||
public hasTypeDefAt (index: TypeIndex): boolean {
|
||||
return this.hasItemAt(index, MetaRegistryItem.TypeDef);
|
||||
}
|
||||
|
||||
public typeDefAt (index: TypeIndex, extra: Pick<TypeDef, never> = {}): TypeDef {
|
||||
return {
|
||||
...this.itemAt(index, MetaRegistryItem.TypeDef),
|
||||
...extra
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
public constructor (json: MetaRegistryJson) {
|
||||
super(json);
|
||||
|
||||
// Generate TypeDefs for each provided registry type
|
||||
this._types.forEach((_, index: number): void => this.setTypeDefAtIndex(index + 1));
|
||||
}
|
||||
|
||||
private hasItemAt (index: number, variant: MetaRegistryItem): boolean {
|
||||
switch (variant) {
|
||||
case String:
|
||||
return this._strings && !!this._strings[index - 1];
|
||||
case Type:
|
||||
return this._types && !!this._types[index - 1];
|
||||
case TypeDefItem:
|
||||
return this.typeDefs && !!this.typeDefs[index - 1];
|
||||
}
|
||||
}
|
||||
|
||||
private itemAt (index: number, variant: MetaRegistryItem): any {
|
||||
assert(this.hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`);
|
||||
|
||||
switch (variant) {
|
||||
case String:
|
||||
return this._strings[index - 1];
|
||||
case Type:
|
||||
return this._types[index - 1];
|
||||
case TypeDefItem:
|
||||
return this.typeDefs[index - 1];
|
||||
}
|
||||
}
|
||||
|
||||
private itemsAt (indices: number[], variant: MetaRegistryItem): any[] {
|
||||
return indices.map(
|
||||
(index: number): string => {
|
||||
return this.itemAt(index, variant);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public stringAt (index: StringIndex): string {
|
||||
return this.itemAt(index, String);
|
||||
}
|
||||
|
||||
public stringsAt (indices: StringIndex[]): string[] {
|
||||
return this.itemsAt(indices, String);
|
||||
}
|
||||
|
||||
public typeAt (index: TypeIndex): MetaType {
|
||||
return this.itemAt(index, Type);
|
||||
}
|
||||
|
||||
public typesAt (indices: TypeIndex[]): MetaType[] {
|
||||
return this.itemsAt(indices, Type);
|
||||
}
|
||||
|
||||
public hasTypeDefAt (index: TypeIndex): boolean {
|
||||
return this.hasItemAt(index, TypeDefItem);
|
||||
}
|
||||
|
||||
public typeDefAt (index: TypeIndex, extra: Pick<TypeDef, never> = {}): TypeDef {
|
||||
return {
|
||||
...this.itemAt(index, TypeDefItem),
|
||||
...extra
|
||||
};
|
||||
public setTypeDefAtIndex (typeIndex: TypeIndex): void {
|
||||
this.typeDefs[typeIndex - 1] = this.typeDefFromMetaType(this.typeAt(typeIndex), typeIndex);
|
||||
}
|
||||
|
||||
private typeDefIdFields ({ id }: MetaType): Pick<TypeDef, never> {
|
||||
@@ -146,79 +122,73 @@ export default class MetaRegistry {
|
||||
|
||||
return {
|
||||
name: this.stringAt(nameIndex),
|
||||
...(
|
||||
namespaceIndices && namespaceIndices.length
|
||||
? { namespace: this.stringsAt(namespaceIndices).join('::') }
|
||||
: {}
|
||||
...(namespaceIndices && namespaceIndices.length
|
||||
? { namespace: this.stringsAt(namespaceIndices).join('::') }
|
||||
: {}
|
||||
),
|
||||
...(
|
||||
paramsIndices && paramsIndices.length
|
||||
? { params: this.typesAt(paramsIndices).map((type): TypeDef => this.typeDefFromMetaType(type)) }
|
||||
: {}
|
||||
...(paramsIndices && paramsIndices.length
|
||||
? { params: this.typesAt(paramsIndices).map((type): TypeDef => this.typeDefFromMetaType(type)) }
|
||||
: {}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefDefFields (metaType: MetaType, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||
let typeDef;
|
||||
switch (MetaRegistry.detectedType(metaType)) {
|
||||
case BuiltinPlain:
|
||||
|
||||
switch (detectedType(metaType)) {
|
||||
case MetaTypeInfo.BuiltinPlain:
|
||||
typeDef = this.typeDefForBuiltinPlain(metaType.id as string);
|
||||
break;
|
||||
case BuiltinTuple:
|
||||
case MetaTypeInfo.BuiltinTuple:
|
||||
typeDef = this.typeDefForBuiltinTuple(metaType.id as TypeIndex[]);
|
||||
break;
|
||||
case BuiltinVec:
|
||||
case MetaTypeInfo.BuiltinVec:
|
||||
typeDef = this.typeDefForBuiltinVec(metaType.id as MetaTypeIdVec, typeIndex);
|
||||
break;
|
||||
case BuiltinVecFixed:
|
||||
case MetaTypeInfo.BuiltinVecFixed:
|
||||
typeDef = this.typeDefForBuiltinVecFixed(metaType.id as MetaTypeIdVecFixed, typeIndex);
|
||||
break;
|
||||
case Enum:
|
||||
case MetaTypeInfo.Enum:
|
||||
typeDef = this.typeDefForEnum(metaType.def as MetaTypeDefEnum, metaType.id as MetaTypeIdCustom, typeIndex);
|
||||
break;
|
||||
case ClikeEnum:
|
||||
case MetaTypeInfo.ClikeEnum:
|
||||
typeDef = this.typeDefForClikeEnum(metaType.def as MetaTypeDefClikeEnum);
|
||||
break;
|
||||
case Struct:
|
||||
case MetaTypeInfo.Struct:
|
||||
typeDef = this.typeDefForStruct(metaType.def as MetaTypeDefStruct);
|
||||
break;
|
||||
case TupleStruct:
|
||||
case MetaTypeInfo.TupleStruct:
|
||||
typeDef = this.typeDefForTupleStruct(metaType.def as MetaTypeDefTupleStruct);
|
||||
break;
|
||||
case Null:
|
||||
case MetaTypeInfo.Null:
|
||||
default:
|
||||
throw new Error(`Invalid type detected at index ${typeIndex}`);
|
||||
}
|
||||
|
||||
return typeDef;
|
||||
}
|
||||
|
||||
public typeDefFromMetaType (metaType: MetaType, typeIndex?: TypeIndex): TypeDef {
|
||||
const typeDef: TypeDef = {
|
||||
return withTypeString({
|
||||
info: TypeDefInfo.Null,
|
||||
type: '',
|
||||
...this.typeDefDefFields(metaType, typeIndex),
|
||||
...this.typeDefIdFields(metaType)
|
||||
};
|
||||
|
||||
return withTypeString(typeDef) as TypeDef;
|
||||
}
|
||||
|
||||
public setTypeDefAtIndex (typeIndex: TypeIndex): void {
|
||||
const metaType = this.typeAt(typeIndex);
|
||||
|
||||
this.typeDefs[typeIndex - 1] = this.typeDefFromMetaType(metaType, typeIndex);
|
||||
}) as TypeDef;
|
||||
}
|
||||
|
||||
public typeDefFromMetaTypeAt (typeIndex: TypeIndex): TypeDef {
|
||||
if (!this.hasTypeDefAt(typeIndex)) {
|
||||
this.setTypeDefAtIndex(typeIndex);
|
||||
}
|
||||
return this.typeDefAt(typeIndex)!;
|
||||
|
||||
return this.typeDefAt(typeIndex);
|
||||
}
|
||||
|
||||
private typeDefForEnumVariant (variant: MetaTypeDefEnumVariant): Pick<TypeDef, any> {
|
||||
const { 'unit_variant.name': unitNameIndex } = variant as MetaTypeDefEnumVariantUnit;
|
||||
|
||||
if (unitNameIndex) {
|
||||
return {
|
||||
info: TypeDefInfo.Plain,
|
||||
@@ -228,11 +198,13 @@ export default class MetaRegistry {
|
||||
}
|
||||
|
||||
const { 'tuple_struct_variant.name': tupleStructVariantNameIndex } = variant as MetaTypeDefEnumVariantTupleStruct;
|
||||
|
||||
if (tupleStructVariantNameIndex) {
|
||||
return this.typeDefForTupleStruct(variant as MetaTypeDefEnumVariantTupleStruct);
|
||||
}
|
||||
|
||||
const { 'struct_variant.name': structVariantNameIndex } = variant as MetaTypeDefEnumVariantStruct;
|
||||
|
||||
if (structVariantNameIndex) {
|
||||
return this.typeDefForStruct(variant as MetaTypeDefEnumVariantStruct);
|
||||
}
|
||||
@@ -252,6 +224,7 @@ export default class MetaRegistry {
|
||||
|
||||
private typeDefForBuiltinTuple (id: TypeIndex[]): Pick<TypeDef, never> {
|
||||
const sub = id.map((tupleTypeIndex: number): TypeDef => this.typeDefFromMetaTypeAt(tupleTypeIndex));
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Tuple,
|
||||
sub
|
||||
@@ -310,25 +283,19 @@ export default class MetaRegistry {
|
||||
}
|
||||
|
||||
private typeDefForClikeEnum (def: MetaTypeDefClikeEnum): Pick<TypeDef, never> {
|
||||
const sub = def['clike_enum.variants'].map(
|
||||
({ name: nameIndex, discriminant }): TypeDef => {
|
||||
return {
|
||||
ext: { discriminant },
|
||||
info: TypeDefInfo.Plain,
|
||||
name: this.stringAt(nameIndex),
|
||||
type: 'Null'
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Enum,
|
||||
sub
|
||||
sub: def['clike_enum.variants'].map(({ name: nameIndex, discriminant }): TypeDef => ({
|
||||
ext: { discriminant },
|
||||
info: TypeDefInfo.Plain,
|
||||
name: this.stringAt(nameIndex),
|
||||
type: 'Null'
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
public typeDefForOption (id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
|
||||
assert(id['custom.params']![0], `Invalid Option type defined at index ${typeIndex}`);
|
||||
assert(id['custom.params'] && id['custom.params'][0], `Invalid Option type defined at index ${typeIndex}`);
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Option,
|
||||
@@ -337,7 +304,7 @@ export default class MetaRegistry {
|
||||
}
|
||||
|
||||
public typeDefForResult (id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
|
||||
assert(id['custom.params']![0] && id['custom.params']![1], `Invalid Result type defined at index ${typeIndex}`);
|
||||
assert(id['custom.params'] && id['custom.params'][0] && id['custom.params'][1], `Invalid Result type defined at index ${typeIndex}`);
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Result,
|
||||
@@ -348,51 +315,34 @@ export default class MetaRegistry {
|
||||
public typeDefForStruct (def: MetaTypeDefStruct | MetaTypeDefEnumVariantStruct): Pick<TypeDef, any> {
|
||||
const structFields = (def as MetaTypeDefStruct)['struct.fields'] || (def as MetaTypeDefEnumVariantStruct)['struct_variant.fields'];
|
||||
const structNameIndex = (def as MetaTypeDefEnumVariantStruct)['struct_variant.name'];
|
||||
const sub = structFields.map(
|
||||
(field: MetaTypeDefStructField): TypeDef => {
|
||||
const { name: nameIndex, type: fieldTypeIndex } = field;
|
||||
return {
|
||||
...this.typeDefFromMetaTypeAt(fieldTypeIndex),
|
||||
name: this.stringAt(nameIndex)
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
return withTypeString({
|
||||
info: TypeDefInfo.Struct,
|
||||
...(
|
||||
structNameIndex
|
||||
? {
|
||||
name: this.stringAt(structNameIndex)
|
||||
}
|
||||
: {}
|
||||
...(structNameIndex
|
||||
? { name: this.stringAt(structNameIndex) }
|
||||
: {}
|
||||
),
|
||||
sub
|
||||
sub: structFields.map((field: MetaTypeDefStructField): TypeDef => ({
|
||||
...this.typeDefFromMetaTypeAt(field.type),
|
||||
name: this.stringAt(field.name)
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
private typeDefForTupleStruct (def: MetaTypeDefTupleStruct | MetaTypeDefEnumVariantTupleStruct): Pick<TypeDef, any> {
|
||||
const tupleStructTypes = (def as MetaTypeDefTupleStruct)['tuple_struct.types'] || (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.types'];
|
||||
const tupleStructNameIndex = (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.name'];
|
||||
const sub: TypeDef[] = tupleStructTypes.map(
|
||||
(tupleStructFieldTypeIndex: number, index: number): TypeDef => {
|
||||
return {
|
||||
...this.typeDefFromMetaTypeAt(tupleStructFieldTypeIndex),
|
||||
index
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
return withTypeString({
|
||||
info: TypeDefInfo.Tuple,
|
||||
...(
|
||||
tupleStructNameIndex
|
||||
? {
|
||||
name: this.stringAt(tupleStructNameIndex)
|
||||
}
|
||||
: {}
|
||||
...(tupleStructNameIndex
|
||||
? { name: this.stringAt(tupleStructNameIndex) }
|
||||
: {}
|
||||
),
|
||||
sub
|
||||
sub: tupleStructTypes.map((fieldIndex: number, index: number): TypeDef => ({
|
||||
...this.typeDefFromMetaTypeAt(fieldIndex),
|
||||
index
|
||||
}))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user