Adjust Registry createType return detection (#3844)

* Adjust Registry createType return detection

* type as 'OtherType' cast removal

* Use createClass via registry
This commit is contained in:
Jaco
2021-08-05 09:15:06 +02:00
committed by GitHub
parent fd7c80bd8a
commit e0ecaccb09
33 changed files with 152 additions and 138 deletions
+33
View File
@@ -0,0 +1,33 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { u32 } from './primitive';
import type { Registry } from './types/registry';
import { assert } from '@polkadot/util';
import { TypeRegistry } from './create';
function registryCheck (registry: Registry): void {
// Should be AccountId
const aa = registry.createType('AccountId');
assert(aa.isAscii, 'All ok');
// Should be Codec
const bb = registry.createType('Something');
assert(bb.toHuman(), 'All ok');
// Should be u32
const cc = registry.createType('Something' as 'u32');
assert(cc.divn(123), 'All ok');
// Should be u32
const dd = registry.createType<u32>('Something');
assert(dd.divn(123), 'All ok');
}
registryCheck(new TypeRegistry());
+1 -1
View File
@@ -69,7 +69,7 @@ describe('BTreeMap', (): void => {
it('decodes within more complicated types', (): void => {
const s = new Struct(registry, {
placeholder: U32,
value: 'BTreeMap<Text, U32>' as 'u32'
value: 'BTreeMap<Text, U32>'
});
s.set('value', new (BTreeMap.with(Text, U32))(registry, mockU32TextMap));
+2 -2
View File
@@ -1,12 +1,12 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { Codec, Constructor, Registry } from '../types';
import { CodecMap } from './Map';
export class BTreeMap<K extends Codec = Codec, V extends Codec = Codec> extends CodecMap<K, V> {
public static with<K extends Codec, V extends Codec> (keyType: Constructor<K> | keyof InterfaceTypes, valType: Constructor<V> | keyof InterfaceTypes): Constructor<CodecMap<K, V>> {
public static with<K extends Codec, V extends Codec> (keyType: Constructor<K> | string, valType: Constructor<V> | string): Constructor<CodecMap<K, V>> {
return class extends BTreeMap<K, V> {
constructor (registry: Registry, value?: Uint8Array | string | Map<any, any>) {
super(registry, keyType, valType, value, 'BTreeMap');
+4 -4
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { AnyJson, Codec, Constructor, Registry } from '../types';
import { compactFromU8a, compactToU8a, isHex, isU8a, logger, stringify, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
@@ -60,7 +60,7 @@ function decodeSetFromSet<V extends Codec = Codec> (registry: Registry, ValClass
* @param jsonSet
* @internal
*/
function decodeSet<V extends Codec = Codec> (registry: Registry, valType: Constructor<V> | keyof InterfaceTypes, value?: Uint8Array | string | string[] | Set<any>): Set<V> {
function decodeSet<V extends Codec = Codec> (registry: Registry, valType: Constructor<V> | string, value?: Uint8Array | string | string[] | Set<any>): Set<V> {
if (!value) {
return new Set<V>();
}
@@ -83,14 +83,14 @@ export class BTreeSet<V extends Codec = Codec> extends Set<V> implements Codec {
readonly #ValClass: Constructor<V>;
constructor (registry: Registry, valType: Constructor<V> | keyof InterfaceTypes, rawValue?: Uint8Array | string | string[] | Set<any>) {
constructor (registry: Registry, valType: Constructor<V> | string, rawValue?: Uint8Array | string | string[] | Set<any>) {
super(sortSet(decodeSet(registry, valType, rawValue)));
this.registry = registry;
this.#ValClass = typeToConstructor(registry, valType);
}
public static with<V extends Codec> (valType: Constructor<V> | keyof InterfaceTypes): Constructor<BTreeSet<V>> {
public static with<V extends Codec> (valType: Constructor<V> | string): Constructor<BTreeSet<V>> {
return class extends BTreeSet<V> {
constructor (registry: Registry, value?: Uint8Array | string | Set<any>) {
super(registry, valType, value);
+3 -3
View File
@@ -3,7 +3,7 @@
import type { BN } from '@polkadot/util';
import type { CodecHash, Hash } from '../interfaces';
import type { AnyJson, AnyNumber, Constructor, ICompact, InterfaceTypes, Registry } from '../types';
import type { AnyJson, AnyNumber, Constructor, ICompact, Registry } from '../types';
import type { CompactEncodable } from './types';
import { compactFromU8a, compactToU8a, isBigInt, isBn, isNumber, isString } from '@polkadot/util';
@@ -27,13 +27,13 @@ export class Compact<T extends CompactEncodable> implements ICompact<T> {
readonly #raw: T;
constructor (registry: Registry, Type: Constructor<T> | keyof InterfaceTypes, value: Compact<T> | AnyNumber = 0) {
constructor (registry: Registry, Type: Constructor<T> | string, value: Compact<T> | AnyNumber = 0) {
this.registry = registry;
this.#Type = typeToConstructor(registry, Type);
this.#raw = Compact.decodeCompact<T>(registry, this.#Type, value) as T;
}
public static with<T extends CompactEncodable> (Type: Constructor<T> | keyof InterfaceTypes): Constructor<Compact<T>> {
public static with<T extends CompactEncodable> (Type: Constructor<T> | string): Constructor<Compact<T>> {
return class extends Compact<T> {
constructor (registry: Registry, value?: Compact<T> | AnyNumber) {
super(registry, Type, value);
+5 -5
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash, Hash } from '../interfaces';
import type { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { AnyJson, Codec, Constructor, Registry } from '../types';
import { assert, hexToU8a, isHex, isNumber, isObject, isString, isU8a, isUndefined, stringCamelCase, stringify, stringUpperFirst, u8aConcat, u8aToHex } from '@polkadot/util';
@@ -27,7 +27,7 @@ interface Decoded {
value: Codec;
}
function isRustEnum (def: Record<string, keyof InterfaceTypes | Constructor> | Record<string, number>): def is Record<string, keyof InterfaceTypes | Constructor> {
function isRustEnum (def: Record<string, string | Constructor> | Record<string, number>): def is Record<string, string | Constructor> {
const defValues = Object.values(def);
if (defValues.some((v) => isNumber(v))) {
@@ -39,7 +39,7 @@ function isRustEnum (def: Record<string, keyof InterfaceTypes | Constructor> | R
return true;
}
function extractDef (registry: Registry, _def: Record<string, keyof InterfaceTypes | Constructor> | Record<string, number> | string[]): { def: TypesDef; isBasic: boolean; isIndexed: boolean } {
function extractDef (registry: Registry, _def: Record<string, string | Constructor> | Record<string, number> | string[]): { def: TypesDef; isBasic: boolean; isIndexed: boolean } {
if (Array.isArray(_def)) {
return {
def: _def.reduce((def: TypesDef, key, index): TypesDef => {
@@ -180,7 +180,7 @@ export class Enum implements Codec {
readonly #raw: Codec;
constructor (registry: Registry, def: Record<string, keyof InterfaceTypes | Constructor> | Record<string, number> | string[], value?: unknown, index?: number) {
constructor (registry: Registry, def: Record<string, string | Constructor> | Record<string, number> | string[], value?: unknown, index?: number) {
const defInfo = extractDef(registry, def);
const decoded = decodeEnum(registry, defInfo.def, value, index);
@@ -193,7 +193,7 @@ export class Enum implements Codec {
this.#raw = decoded.value;
}
public static with (Types: Record<string, keyof InterfaceTypes | Constructor> | Record<string, number> | string[]): EnumConstructor<Enum> {
public static with (Types: Record<string, string | Constructor> | Record<string, number> | string[]): EnumConstructor<Enum> {
return class extends Enum {
constructor (registry: Registry, value?: unknown, index?: number) {
super(registry, Types, value, index);
+2 -2
View File
@@ -1,12 +1,12 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { Codec, Constructor, Registry } from '../types';
import { CodecMap } from './Map';
export class HashMap<K extends Codec = Codec, V extends Codec = Codec> extends CodecMap<K, V> {
public static with<K extends Codec, V extends Codec> (keyType: Constructor<K> | keyof InterfaceTypes, valType: Constructor<V> | keyof InterfaceTypes): Constructor<CodecMap<K, V>> {
public static with<K extends Codec, V extends Codec> (keyType: Constructor<K> | string, valType: Constructor<V> | string): Constructor<CodecMap<K, V>> {
return class extends HashMap<K, V> {
constructor (registry: Registry, value?: Uint8Array | string | Map<any, any>) {
super(registry, keyType, valType, value);
+2 -2
View File
@@ -25,7 +25,7 @@ describe('Linkage', (): void => {
).toEqual(LINKA);
expect(
registry.createType(
'Linkage<AccountId>' as 'u32',
'Linkage<AccountId>',
'0x0001da30b68f54f686f586ddb29de12b682dd8bd1404566fb8a8db5dec20aa5b6b36'
).toHuman()
).toEqual(LINKA);
@@ -33,7 +33,7 @@ describe('Linkage', (): void => {
// actual check
expect(
registry.createType(
'(ValidatorPrefsWithCommission, Linkage<AccountId>)' as 'u32',
'(ValidatorPrefsWithCommission, Linkage<AccountId>)',
'0x0284d7170001da30b68f54f686f586ddb29de12b682dd8bd1404566fb8a8db5dec20aa5b6b36'
).toHuman()
).toEqual([PREFS, LINKA]);
+3 -3
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { Codec, Constructor, Registry } from '../types';
import { Option } from './Option';
import { Struct } from './Struct';
@@ -17,7 +17,7 @@ const EMPTY = new Uint8Array();
* @description The wrapper for the result from a LinkedMap
*/
export class Linkage<T extends Codec> extends Struct {
constructor (registry: Registry, Type: Constructor | keyof InterfaceTypes, value?: unknown) {
constructor (registry: Registry, Type: Constructor | string, value?: unknown) {
super(registry, {
previous: Option.with(Type),
// eslint-disable-next-line sort-keys
@@ -25,7 +25,7 @@ export class Linkage<T extends Codec> extends Struct {
}, value as string);
}
public static withKey<O extends Codec> (Type: Constructor | keyof InterfaceTypes): Constructor<Linkage<O>> {
public static withKey<O extends Codec> (Type: Constructor | string): Constructor<Linkage<O>> {
return class extends Linkage<O> {
constructor (registry: Registry, value?: unknown) {
super(registry, Type, value);
+3 -3
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { AnyJson, Codec, Constructor, Registry } from '../types';
import { compactFromU8a, compactToU8a, isHex, isObject, isU8a, logger, stringify, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
@@ -75,7 +75,7 @@ function decodeMapFromMap<K extends Codec = Codec, V extends Codec = Codec> (reg
* @param jsonMap
* @internal
*/
function decodeMap<K extends Codec = Codec, V extends Codec = Codec> (registry: Registry, keyType: Constructor<K> | keyof InterfaceTypes, valType: Constructor<V> | keyof InterfaceTypes, value?: Uint8Array | string | Map<any, any>): Map<K, V> {
function decodeMap<K extends Codec = Codec, V extends Codec = Codec> (registry: Registry, keyType: Constructor<K> | string, valType: Constructor<V> | string, value?: Uint8Array | string | Map<any, any>): Map<K, V> {
const KeyClass = typeToConstructor(registry, keyType);
const ValClass = typeToConstructor(registry, valType);
@@ -103,7 +103,7 @@ export class CodecMap<K extends Codec = Codec, V extends Codec = Codec> extends
readonly #type: string;
constructor (registry: Registry, keyType: Constructor<K> | keyof InterfaceTypes, valType: Constructor<V> | keyof InterfaceTypes, rawValue: Uint8Array | string | Map<any, any> | undefined, type: 'BTreeMap' | 'HashMap' = 'HashMap') {
constructor (registry: Registry, keyType: Constructor<K> | string, valType: Constructor<V> | string, rawValue: Uint8Array | string | Map<any, any> | undefined, type: 'BTreeMap' | 'HashMap' = 'HashMap') {
const decoded = decodeMap(registry, keyType, valType, rawValue);
super(type === 'BTreeMap' ? sortMap(decoded) : decoded);
+4 -4
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash, Hash } from '../interfaces';
import type { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { AnyJson, Codec, Constructor, Registry } from '../types';
import { assert, isNull, isU8a, isUndefined, u8aToHex } from '@polkadot/util';
@@ -17,7 +17,7 @@ function decodeOptionU8a (registry: Registry, Type: Constructor, value: Uint8Arr
}
/** @internal */
function decodeOption (registry: Registry, typeName: Constructor | keyof InterfaceTypes, value?: unknown): Codec {
function decodeOption (registry: Registry, typeName: Constructor | string, value?: unknown): Codec {
if (isNull(value) || isUndefined(value) || value instanceof Null) {
return new Null(registry);
}
@@ -56,13 +56,13 @@ export class Option<T extends Codec> implements Codec {
readonly #raw: T;
constructor (registry: Registry, typeName: Constructor<T> | keyof InterfaceTypes, value?: unknown) {
constructor (registry: Registry, typeName: Constructor<T> | string, value?: unknown) {
this.registry = registry;
this.#Type = typeToConstructor(registry, typeName);
this.#raw = decodeOption(registry, typeName, value) as T;
}
public static with<O extends Codec> (Type: Constructor<O> | keyof InterfaceTypes): Constructor<Option<O>> {
public static with<O extends Codec> (Type: Constructor<O> | string): Constructor<Option<O>> {
return class extends Option<O> {
constructor (registry: Registry, value?: unknown) {
super(registry, Type, value);
+3 -3
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { Codec, Constructor, Registry } from '../types';
import { assert } from '@polkadot/util';
@@ -13,13 +13,13 @@ import { Enum } from './Enum';
* A Result maps to the Rust Result type, that can either wrap a success or error value
*/
export class Result<O extends Codec, E extends Codec> extends Enum {
constructor (registry: Registry, Ok: Constructor<O> | keyof InterfaceTypes, Err: Constructor<E> | keyof InterfaceTypes, value?: unknown) {
constructor (registry: Registry, Ok: Constructor<O> | string, Err: Constructor<E> | string, value?: unknown) {
// NOTE This is order-dependent, Ok (with index 0) needs to be first
// eslint-disable-next-line sort-keys
super(registry, { Ok, Err }, value);
}
public static override with<O extends Codec, E extends Codec> (Types: { Ok: Constructor<O> | keyof InterfaceTypes; Err: Constructor<E> | keyof InterfaceTypes }): Constructor<Result<O, E>> {
public static override with<O extends Codec, E extends Codec> (Types: { Ok: Constructor<O> | string; Err: Constructor<E> | string }): Constructor<Result<O, E>> {
return class extends Result<O, E> {
constructor (registry: Registry, value?: unknown) {
super(registry, Types.Ok, Types.Err, value);
+2 -2
View File
@@ -2,13 +2,13 @@
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyJson, BareOpts, Codec, Constructor, ConstructorDef, InterfaceTypes, Registry } from '../types';
import type { AnyJson, BareOpts, Codec, Constructor, ConstructorDef, Registry } from '../types';
import { assert, hexToU8a, isBoolean, isFunction, isHex, isObject, isU8a, isUndefined, stringCamelCase, stringify, u8aConcat, u8aToHex } from '@polkadot/util';
import { compareMap, decodeU8a, mapToTypeMap } from './utils';
type TypesDef<T = Codec> = Record<string, keyof InterfaceTypes | Constructor<T>>;
type TypesDef<T = Codec> = Record<string, string | Constructor<T>>;
/** @internal */
function decodeStructFromObject <T> (registry: Registry, Types: ConstructorDef, value: any, jsonMap: Map<any, string>): T {
+1 -1
View File
@@ -51,7 +51,7 @@ describe('Tuple', (): void => {
it('decodes properly from complex types', (): void => {
const INPUT = '0xcc0200000000';
const test = registry.createType('(u32, [u32; 0], u16)' as 'u32', INPUT);
const test = registry.createType('(u32, [u32; 0], u16)', INPUT);
expect(test.encodedLength).toEqual(4 + 0 + 2);
expect(test.toHex()).toEqual(INPUT);
+3 -3
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { AnyNumber, AnyString, AnyU8a, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { AnyNumber, AnyString, AnyU8a, Codec, Constructor, Registry } from '../types';
import { isHex, isU8a, stringify, u8aConcat, u8aToU8a } from '@polkadot/util';
@@ -14,8 +14,8 @@ type TupleConstructors = Constructor[] | {
[index: string]: Constructor;
};
type TupleTypes = (Constructor | keyof InterfaceTypes)[] | {
[index: string]: Constructor | keyof InterfaceTypes;
type TupleTypes = (Constructor | string)[] | {
[index: string]: Constructor | string;
};
/** @internal */
+7 -8
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { PropIndex } from '../interfaces/democracy';
import type { Codec, CodecTo } from '../types';
import type { Codec, CodecTo, ITuple } from '../types';
import rpcMetadata from '@polkadot/types-support/metadata/static-substrate';
import { randomAsU8a } from '@polkadot/util-crypto';
@@ -11,7 +11,7 @@ import { createTypeUnsafe, TypeRegistry } from '../create';
import { GenericAccountId as AccountId } from '../generic';
import { Metadata } from '../metadata';
import { Text } from '../primitive';
import { Tuple, Vec } from '.';
import { Vec } from '.';
const registry = new TypeRegistry();
const metadata = new Metadata(registry, rpcMetadata);
@@ -69,20 +69,19 @@ describe('Vec', (): void => {
});
it('decodes a complex type via construction', (): void => {
const test = createTypeUnsafe(registry, 'Vec<(PropIndex, AccountId)>', [new Uint8Array([
const test = createTypeUnsafe<Vec<ITuple<[PropIndex, AccountId]>>>(registry, 'Vec<(PropIndex, AccountId)>', [new Uint8Array([
4, 10, 0, 0, 0, 209, 114, 167, 76, 218, 76, 134, 89, 18, 195, 43, 160, 168, 10, 87, 174, 105, 171, 174, 65, 14, 92, 203, 89, 222, 232, 78, 47, 68, 50, 219, 79
])]);
const first = (test as Vec<Codec>)[0] as Tuple;
expect((first[0] as PropIndex).toNumber()).toEqual(10);
expect((first[1] as AccountId).toString()).toEqual('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua');
expect(test[0][0].toNumber()).toEqual(10);
expect(test[0][1].toString()).toEqual('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua');
});
it('decodes a complex type via construction', (): void => {
const INPUT = '0x08cc0200000000ce0200000001';
const test = createTypeUnsafe(registry, 'Vec<(u32, [u32; 0], u16)>' as any, [INPUT]);
const test = createTypeUnsafe<Vec<Codec>>(registry, 'Vec<(u32, [u32; 0], u16)>', [INPUT]);
expect((test as Vec<any>).length).toEqual(2);
expect(test).toHaveLength(2);
expect(test.toHex()).toEqual(INPUT);
});
+3 -3
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { Codec, Constructor, Registry } from '../types';
import { assert, compactFromU8a, logger, u8aToU8a } from '@polkadot/util';
@@ -22,7 +22,7 @@ const l = logger('Vec');
export class Vec<T extends Codec> extends AbstractArray<T> {
private _Type: Constructor<T>;
constructor (registry: Registry, Type: Constructor<T> | keyof InterfaceTypes, value: Vec<Codec> | Uint8Array | string | unknown[] = []) {
constructor (registry: Registry, Type: Constructor<T> | string, value: Vec<Codec> | Uint8Array | string | unknown[] = []) {
const Clazz = typeToConstructor<T>(registry, Type);
super(registry, ...Vec.decodeVec(registry, Clazz, value));
@@ -55,7 +55,7 @@ export class Vec<T extends Codec> extends AbstractArray<T> {
return decodeU8a(registry, u8a.subarray(offset), new Array(length.toNumber()).fill(Type)) as T[];
}
public static with<O extends Codec> (Type: Constructor<O> | keyof InterfaceTypes): Constructor<Vec<O>> {
public static with<O extends Codec> (Type: Constructor<O> | string): Constructor<Vec<O>> {
return class extends Vec<O> {
constructor (registry: Registry, value?: any[]) {
super(registry, Type, value);
+3 -3
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { Codec, Constructor, Registry } from '../types';
import { assert, compactToU8a, isHex, isU8a, u8aConcat } from '@polkadot/util';
@@ -36,7 +36,7 @@ function decodeVecFixed<T extends Codec> (registry: Registry, Type: Constructor<
export class VecFixed<T extends Codec> extends AbstractArray<T> {
private _Type: Constructor<T>;
constructor (registry: Registry, Type: Constructor<T> | keyof InterfaceTypes, length: number, value: VecFixed<any> | Uint8Array | string | any[] = [] as any[]) {
constructor (registry: Registry, Type: Constructor<T> | string, length: number, value: VecFixed<any> | Uint8Array | string | any[] = [] as any[]) {
const Clazz = typeToConstructor<T>(registry, Type);
super(registry, ...decodeVecFixed(registry, Clazz, length, value));
@@ -44,7 +44,7 @@ export class VecFixed<T extends Codec> extends AbstractArray<T> {
this._Type = Clazz;
}
public static with<O extends Codec> (Type: Constructor<O> | keyof InterfaceTypes, length: number): Constructor<VecFixed<O>> {
public static with<O extends Codec> (Type: Constructor<O> | string, length: number): Constructor<VecFixed<O>> {
return class extends VecFixed<O> {
constructor (registry: Registry, value?: any[]) {
super(registry, Type, length, value);
@@ -1,14 +1,14 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Constructor, InterfaceTypes, Registry } from '../../types';
import type { Constructor, Registry } from '../../types';
import { typeToConstructor } from './typeToConstructor';
/**
* @description takes an input map of the form `{ [string]: string | Constructor }` and returns a map of `{ [string]: Constructor }`
*/
export function mapToTypeMap (registry: Registry, input: Record<string, keyof InterfaceTypes | Constructor>): Record<string, Constructor> {
export function mapToTypeMap (registry: Registry, input: Record<string, string | Constructor>): Record<string, Constructor> {
return Object
.entries(input)
.reduce((output: Record<string, Constructor>, [key, type]): Record<string, Constructor> => {
@@ -1,11 +1,11 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Codec, Constructor, InterfaceTypes, Registry } from '../../types';
import type { Codec, Constructor, Registry } from '../../types';
import { isString } from '@polkadot/util';
export function typeToConstructor <T = Codec> (registry: Registry, type: keyof InterfaceTypes | Constructor<T>): Constructor<T> {
export function typeToConstructor <T = Codec> (registry: Registry, type: string | Constructor<T>): Constructor<T> {
return (
isString(type)
? registry.createClass(type)
+13 -29
View File
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
import type { U8aBitLength, UIntBitLength } from '../codec/types';
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { FromReg, TypeDef } from './types';
import type { Codec, Constructor, DetectConstructor, Registry } from '../types';
import type { TypeDef } from './types';
import { assert, isNumber, isUndefined, stringify } from '@polkadot/util';
@@ -12,9 +12,8 @@ import { Bytes, Null } from '../primitive';
import { getTypeDef } from './getTypeDef';
import { TypeDefInfo } from './types';
export function createClass<T extends Codec = Codec, K extends string = string> (registry: Registry, type: K): Constructor<FromReg<T, K>> {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return getTypeClass<FromReg<T, K>>(
export function createClass<T extends Codec = Codec, K extends string = string> (registry: Registry, type: K): DetectConstructor<T, K> {
return getTypeClass(
registry,
registry.isLookupType(type)
? registry.lookup.getTypeDef(type)
@@ -22,21 +21,6 @@ export function createClass<T extends Codec = Codec, K extends string = string>
);
}
// An unsafe version of the `createType` below. It's unsafe because the `type`
// argument here can be any string, which, if it cannot be parsed, it will yield
// a runtime error.
export function ClassOfUnsafe<T extends Codec = Codec, K extends string = string> (registry: Registry, name: K): Constructor<FromReg<T, K>> {
return createClass<T, K>(registry, name);
}
// alias for createClass
export function ClassOf<K extends keyof InterfaceTypes> (registry: Registry, name: K): Constructor<InterfaceTypes[K]> {
// TS2589: Type instantiation is excessively deep and possibly infinite.
// The above happens with as Constructor<InterfaceTypes[K]>;
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return ClassOfUnsafe<Codec, K>(registry, name) as any;
}
function getSubDefArray (value: TypeDef): TypeDef[] {
assert(value.sub && Array.isArray(value.sub), () => `Expected subtype as TypeDef[] in ${stringify(value)}`);
@@ -49,24 +33,24 @@ function getSubDef (value: TypeDef): TypeDef {
return value.sub;
}
function getSubType (value: TypeDef): keyof InterfaceTypes {
return getSubDef(value).type as keyof InterfaceTypes;
function getSubType (value: TypeDef): string {
return getSubDef(value).type;
}
// create a maps of type string constructors from the input
function getTypeClassMap (value: TypeDef): Record<string, keyof InterfaceTypes> {
const result: Record<string, keyof InterfaceTypes> = {};
function getTypeClassMap (value: TypeDef): Record<string, string> {
const result: Record<string, string> = {};
return getSubDefArray(value).reduce<Record<string, keyof InterfaceTypes>>((result, sub) => {
result[sub.name as string] = sub.type as keyof InterfaceTypes;
return getSubDefArray(value).reduce<Record<string, string>>((result, sub) => {
result[sub.name as string] = sub.type;
return result;
}, result);
}
// create an array of type string constructors from the input
function getTypeClassArray (value: TypeDef): (keyof InterfaceTypes)[] {
return getSubDefArray(value).map(({ type }) => type as keyof InterfaceTypes);
function getTypeClassArray (value: TypeDef): string[] {
return getSubDefArray(value).map(({ type }) => type);
}
function createInt ({ displayName, length }: TypeDef, Clazz: typeof Int | typeof UInt): Constructor {
@@ -184,7 +168,7 @@ const infoMapping: Record<TypeDefInfo, (registry: Registry, value: TypeDef) => C
[TypeDefInfo.VecFixed]: (registry: Registry, { displayName, length, sub }: TypeDef): Constructor => {
assert(isNumber(length) && !isUndefined(sub), 'Expected length & type information for fixed vector');
const subType = (sub as TypeDef).type as keyof InterfaceTypes;
const subType = (sub as TypeDef).type;
return (
subType === 'u8'
+9 -9
View File
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
import type { Bytes } from '../primitive/Bytes';
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { CreateOptions, FromReg } from './types';
import type { Codec, Constructor, DetectCodec, Registry } from '../types';
import type { CreateOptions } from './types';
import { assert, isHex, isU8a, u8aEq, u8aToHex, u8aToU8a } from '@polkadot/util';
@@ -12,7 +12,7 @@ import { createClass } from './createClass';
// With isPedantic, actually check that the encoding matches that supplied. This
// is much slower, but verifies that we have the correct types defined
function checkInstance (created: FromReg<Codec, string>, value: Uint8Array): void {
function checkInstance (created: Codec, value: Uint8Array): void {
const u8a = created.toU8a();
const rawType = created.toRawType();
@@ -26,7 +26,7 @@ function checkInstance (created: FromReg<Codec, string>, value: Uint8Array): voi
);
}
function checkPedantic (created: FromReg<Codec, string>, [value]: unknown[], isPedantic = false): void {
function checkPedantic (created: Codec, [value]: unknown[], isPedantic = false): void {
if (isPedantic) {
if (isU8a(value)) {
checkInstance(created, value);
@@ -38,7 +38,7 @@ function checkPedantic (created: FromReg<Codec, string>, [value]: unknown[], isP
// Initializes a type with a value. This also checks for fallbacks and in the cases
// where isPedantic is specified (storage decoding), also check the format/structure
function initType<T extends Codec = Codec, K extends string = string> (registry: Registry, Type: Constructor<FromReg<T, K>>, params: unknown[] = [], { blockHash, isOptional, isPedantic }: CreateOptions = {}): FromReg<T, K> {
function initType<T extends Codec = Codec, K extends string = string> (registry: Registry, Type: Constructor, params: unknown[] = [], { blockHash, isOptional, isPedantic }: CreateOptions = {}): DetectCodec<T, K> {
const created = new (isOptional ? Option.with(Type) : Type)(registry, ...params);
checkPedantic(created, params, isPedantic);
@@ -54,8 +54,8 @@ function initType<T extends Codec = Codec, K extends string = string> (registry:
// An unsafe version of the `createType` below. It's unsafe because the `type`
// argument here can be any string, which, when it cannot parse, will yield a
// runtime error.
export function createTypeUnsafe<T extends Codec = Codec, K extends string = string> (registry: Registry, type: K, params: unknown[] = [], options: CreateOptions = {}): T {
let Clazz: Constructor<FromReg<T, K>> | null = null;
export function createTypeUnsafe<T extends Codec = Codec, K extends string = string> (registry: Registry, type: K, params: unknown[] = [], options: CreateOptions = {}): DetectCodec<T, K> {
let Clazz: Constructor | null = null;
let firstError: Error | null = null;
try {
@@ -85,6 +85,6 @@ export function createTypeUnsafe<T extends Codec = Codec, K extends string = str
* instance from
* @param params - The value to instantiate the type with
*/
export function createType<K extends keyof InterfaceTypes> (registry: Registry, type: K, ...params: unknown[]): InterfaceTypes[K] {
return createTypeUnsafe<InterfaceTypes[K], K>(registry, type, params);
export function createType<T extends Codec = Codec, K extends string = string> (registry: Registry, type: K, ...params: unknown[]): DetectCodec<T, K> {
return createTypeUnsafe<T, K>(registry, type, params);
}
+1 -1
View File
@@ -512,7 +512,7 @@ describe('getTypeDef', (): void => {
}
});
const raw = registry.createType('Recursive' as 'u32').toRawType();
const raw = registry.createType('Recursive').toRawType();
expect(
getTypeDef(raw)
+12 -13
View File
@@ -5,7 +5,7 @@
import type { ExtDef } from '../extrinsic/signedExtensions/types';
import type { ChainProperties, CodecHash, DispatchErrorModule, Hash, MetadataLatest, PortableRegistry, SiLookupTypeId } from '../interfaces/types';
import type { CallFunction, Codec, CodecHasher, Constructor, InterfaceTypes, RegisteredTypes, Registry, RegistryError, RegistryTypes } from '../types';
import type { CallFunction, Codec, CodecHasher, Constructor, DetectCodec, DetectConstructor, InterfaceTypes, RegisteredTypes, Registry, RegistryError, RegistryTypes } from '../types';
import type { CreateOptions } from './types';
import { assert, assertReturn, BN_ZERO, formatBalance, isFunction, isString, isU8a, logger, stringCamelCase, stringify, u8aToHex } from '@polkadot/util';
@@ -241,22 +241,21 @@ export class TypeRegistry implements Registry {
/**
* @describe Creates an instance of the class
*/
public createClass <K extends keyof InterfaceTypes> (type: K): Constructor<InterfaceTypes[K]> {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return createClass(this, type) as any;
public createClass <T extends Codec = Codec, K extends string = string> (type: K): DetectConstructor<T, K> {
return createClass(this, type);
}
/**
* @description Creates an instance of a type as registered
*/
public createType <K extends keyof InterfaceTypes> (type: K, ...params: unknown[]): InterfaceTypes[K] {
public createType <T extends Codec = Codec, K extends string = string> (type: K, ...params: unknown[]): DetectCodec<T, K> {
return createTypeUnsafe(this, type, params);
}
/**
* @description Creates an instance of a type as registered
*/
public createTypeUnsafe <T extends Codec = Codec, K extends string = string> (type: K, params: unknown[], options?: CreateOptions): T {
public createTypeUnsafe <T extends Codec = Codec, K extends string = string> (type: K, params: unknown[], options?: CreateOptions): DetectCodec<T, K> {
return createTypeUnsafe(this, type, params, options);
}
@@ -284,13 +283,13 @@ export class TypeRegistry implements Registry {
return assertReturn(this.#metadataEvents[hexIndex], `findMetaEvent: Unable to find Event with index ${hexIndex}/[${eventIndex.toString()}]`);
}
public get <T extends Codec = Codec> (name: string, withUnknown?: boolean): Constructor<T> | undefined {
public get <T extends Codec = Codec, K extends string = string> (name: K, withUnknown?: boolean): DetectConstructor<T, K> | undefined {
let Type = this.#classes.get(name);
// we have not already created the type, attempt it
if (!Type) {
const definition = this.#definitions.get(name);
let BaseType: Constructor<Codec> | undefined;
let BaseType: Constructor | undefined;
// we have a definition, so create the class now (lazily)
if (definition) {
@@ -312,7 +311,7 @@ export class TypeRegistry implements Registry {
}
}
return Type as Constructor<T>;
return Type as DetectConstructor<T, K>;
}
public getChainProperties (): ChainProperties | undefined {
@@ -335,12 +334,12 @@ export class TypeRegistry implements Registry {
return this.#knownTypes?.typesBundle?.spec?.[specName]?.instances?.[moduleName];
}
public getOrThrow <T extends Codec = Codec> (name: string, msg?: string): Constructor<T> {
return assertReturn(this.get<T>(name), msg || `type ${name} not found`);
public getOrThrow <T extends Codec = Codec, K extends string = string> (name: K, msg?: string): DetectConstructor<T, K> {
return assertReturn(this.get<T, K>(name), msg || `type ${name} not found`);
}
public getOrUnknown <T extends Codec = Codec> (name: string): Constructor<T> {
return this.get<T>(name, true) as Constructor<T>;
public getOrUnknown <T extends Codec = Codec, K extends string = string> (name: K): DetectConstructor<T, K> {
return this.get<T, K>(name, true) as DetectConstructor<T, K>;
}
public getSignedExtensionExtra (): Record<string, keyof InterfaceTypes> {
-7
View File
@@ -1,13 +1,6 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Codec, InterfaceTypes } from '../types';
// Type which says: if `K` is in the InterfaceTypes, then return InterfaceTypes[K], else fallback to T
export type FromReg<T extends Codec, K extends string> = K extends keyof InterfaceTypes
? InterfaceTypes[K]
: T;
export enum TypeDefInfo {
BTreeMap,
BTreeSet,
+3 -3
View File
@@ -4,7 +4,7 @@
import type { EcdsaSignature, Ed25519Signature, ExtrinsicUnknown, ExtrinsicV4, Sr25519Signature } from '../interfaces/extrinsics';
import type { FunctionMetadataLatest } from '../interfaces/metadata/types';
import type { Address, Balance, Call, Index } from '../interfaces/runtime';
import type { AnyJson, AnyTuple, AnyU8a, ArgsDef, CallBase, ExtrinsicPayloadValue, IExtrinsic, IKeyringPair, IMethod, InterfaceTypes, Registry, SignatureOptions } from '../types';
import type { AnyJson, AnyTuple, AnyU8a, ArgsDef, CallBase, ExtrinsicPayloadValue, IExtrinsic, IKeyringPair, IMethod, Registry, SignatureOptions } from '../types';
import type { GenericExtrinsicEra } from './ExtrinsicEra';
import type { ExtrinsicValueV4 } from './v4/Extrinsic';
@@ -24,7 +24,7 @@ interface CreateOptions {
type ExtrinsicVx = ExtrinsicV4;
type ExtrinsicValue = ExtrinsicValueV4;
const VERSIONS: (keyof InterfaceTypes)[] = [
const VERSIONS = [
'ExtrinsicUnknown', // v0 is unknown
'ExtrinsicUnknown',
'ExtrinsicUnknown',
@@ -183,7 +183,7 @@ export class GenericExtrinsic<A extends AnyTuple = AnyTuple> extends ExtrinsicBa
// we cast here since the VERSION definition is incredibly broad - we don't have a
// slice for "only add extrinsic types", and more string definitions become unwieldy
return registry.createType(type, value, { isSigned, version }) as ExtrinsicVx;
return registry.createType(type, value, { isSigned, version });
}
/** @internal */
@@ -3,7 +3,7 @@
import type { ExtrinsicPayloadV4 } from '../interfaces/extrinsics';
import type { Balance, Hash, Index } from '../interfaces/runtime';
import type { AnyJson, BareOpts, ExtrinsicPayloadValue, IKeyringPair, InterfaceTypes, Registry } from '../types';
import type { AnyJson, BareOpts, ExtrinsicPayloadValue, IKeyringPair, Registry } from '../types';
import { u8aToHex } from '@polkadot/util';
@@ -21,7 +21,7 @@ interface ExtrinsicPayloadOptions {
// all our known types that can be returned
type ExtrinsicPayloadVx = ExtrinsicPayloadV4;
const VERSIONS: (keyof InterfaceTypes)[] = [
const VERSIONS = [
'ExtrinsicPayloadUnknown', // v0 is unknown
'ExtrinsicPayloadUnknown',
'ExtrinsicPayloadUnknown',
@@ -46,7 +46,7 @@ export class GenericExtrinsicPayload extends Base<ExtrinsicPayloadVx> {
return value._raw;
}
return registry.createType(VERSIONS[version] || VERSIONS[0], value, { version }) as ExtrinsicPayloadVx;
return registry.createType(VERSIONS[version] || VERSIONS[0], value, { version });
}
/**
@@ -26,7 +26,7 @@ function mapCalls (registry: Registry, _calls: Option<Vec<FunctionMetadataLatest
const calls = _calls.unwrapOr(null);
return registry.createType(
'Option<Vec<FunctionMetadataLatest>>' as any,
'Option<Vec<FunctionMetadataLatest>>',
calls
? calls.map(({ args, docs, name }) =>
registry.createType('FunctionMetadataLatest', {
@@ -36,7 +36,7 @@ function mapCalls (registry: Registry, _calls: Option<Vec<FunctionMetadataLatest
})
)
: null
) as Option<Vec<FunctionMetadataLatest>>;
);
}
/** @internal */
+12 -6
View File
@@ -17,6 +17,12 @@ import type { DefinitionRpc, DefinitionRpcSub } from './definitions';
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface InterfaceTypes { }
export type DetectCodec<T extends Codec, K extends string> = K extends keyof InterfaceTypes
? InterfaceTypes[K]
: T;
export type DetectConstructor<T extends Codec, K extends string> = Constructor<DetectCodec<T, K>>;
export type CodecHasher = (data: Uint8Array) => Uint8Array;
export interface ChainUpgradeVersion {
@@ -119,16 +125,16 @@ export interface Registry {
isLookupType (value: string): boolean;
createLookupType (lookupId: SiLookupTypeId | number): string;
createClass <K extends keyof InterfaceTypes> (type: K): Constructor<InterfaceTypes[K]>;
createType <K extends keyof InterfaceTypes> (type: K, ...params: unknown[]): InterfaceTypes[K];
createTypeUnsafe <T extends Codec = Codec, K extends string = string> (type: K, params: unknown[], options?: CreateOptions): T;
get <T extends Codec = Codec> (name: string, withUnknown?: boolean): Constructor<T> | undefined;
createClass <T extends Codec = Codec, K extends string = string> (type: K): DetectConstructor<T, K>;
createType <T extends Codec = Codec, K extends string = string> (type: K, ...params: unknown[]): DetectCodec<T, K>;
createTypeUnsafe <T extends Codec = Codec, K extends string = string> (type: K, params: unknown[], options?: CreateOptions): DetectCodec<T, K>;
get <T extends Codec = Codec, K extends string = string> (name: K, withUnknown?: boolean): DetectConstructor<T, K> | undefined;
getChainProperties (): ChainProperties | undefined;
getClassName (clazz: Constructor): string | undefined;
getDefinition (typeName: string): string | undefined;
getModuleInstances (specName: string, moduleName: string): string[] | undefined;
getOrThrow <T extends Codec = Codec> (name: string, msg?: string): Constructor<T>;
getOrUnknown <T extends Codec = Codec> (name: string): Constructor<T>;
getOrThrow <T extends Codec = Codec, K extends string = string> (name: K, msg?: string): DetectConstructor<T, K>;
getOrUnknown <T extends Codec = Codec, K extends string = string> (name: K): DetectConstructor<T, K>;
setKnownTypes (types: RegisteredTypes): void;
getSignedExtensionExtra (): Record<string, keyof InterfaceTypes>;
getSignedExtensionTypes (): Record<string, keyof InterfaceTypes>;