diff --git a/packages/types/src/checkTypes.manual.ts b/packages/types/src/checkTypes.manual.ts index cbca02c057..c0cc9ffbf0 100644 --- a/packages/types/src/checkTypes.manual.ts +++ b/packages/types/src/checkTypes.manual.ts @@ -55,14 +55,12 @@ const hh = registry.createType('[u128; 32]'); assert(hh[0].bitLength(), 'All ok'); // tuple! ITuple<[u32, Compact, u128, Codec]> -const tt1 = registry.createType('(u32, Compact< u64 >,u128, Something)'); +const tt1 = registry.createType('(u32, Compact< u64 >, u128 , Something)'); // unwraps into a u32 const tt2 = registry.createType('( u32 )'); -// max number of params -const tt3 = registry.createType('(u8,u16,u32,u64,u128)'); // lots and lots of params -const tt4 = registry.createType('(u8,u16,u32,u64,u8,u16,u32,u64,u8,u16,u32,u64,u8,u16,u32,u64)'); +const tt4 = registry.createType('(u8,u16,u32,u64,u128,u256,Break,u256,u128,u64,u32,u16,u8)'); // empty const tt5 = registry.createType('()'); -assert(tt1[2].bitLength() && tt2.bitLength() && tt3[4].bitLength() && tt4[3].bitLength() && tt5.isEmpty, 'All ok'); +assert(tt1[2].bitLength() && tt2.bitLength() && tt4[3].bitLength() && tt5.isEmpty, 'All ok'); diff --git a/packages/types/src/codec/AbstractInt.ts b/packages/types/src/codec/AbstractInt.ts index de6c6124b4..0ad8ff979c 100644 --- a/packages/types/src/codec/AbstractInt.ts +++ b/packages/types/src/codec/AbstractInt.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import type { CodecHash, Hash } from '../interfaces/runtime'; -import type { AnyNumber, Codec, Registry } from '../types'; +import type { AnyNumber, INumber, Registry } from '../types'; import type { UIntBitLength } from './types'; import { assert, BN, BN_BILLION, BN_HUNDRED, BN_MILLION, BN_QUINTILL, BN_ZERO, bnToBn, bnToHex, bnToU8a, formatBalance, formatNumber, hexToBn, isHex, isString, isU8a, stringify, u8aToBn } from '@polkadot/util'; @@ -60,7 +60,7 @@ function decodeAbstractInt (value: AnyNumber, bitLength: UIntBitLength, isNegati * @ignore * @noInheritDoc */ -export abstract class AbstractInt extends BN implements Codec { +export abstract class AbstractInt extends BN implements INumber { public readonly registry: Registry; public createdAtHash?: Hash; diff --git a/packages/types/src/codec/Compact.ts b/packages/types/src/codec/Compact.ts index fc1a22c7a7..a110b758b8 100644 --- a/packages/types/src/codec/Compact.ts +++ b/packages/types/src/codec/Compact.ts @@ -3,8 +3,7 @@ import type { BN } from '@polkadot/util'; import type { CodecHash, Hash } from '../interfaces'; -import type { AnyJson, AnyNumber, Constructor, ICompact, Registry } from '../types'; -import type { CompactEncodable } from './types'; +import type { AnyJson, AnyNumber, Constructor, ICompact, INumber, Registry } from '../types'; import { compactFromU8a, compactToU8a, isBigInt, isBn, isNumber, isString } from '@polkadot/util'; @@ -18,7 +17,7 @@ import { typeToConstructor } from './utils'; * used by other types to add length-prefixed encoding, or in the case of wrapped types, taking * a number and making the compact representation thereof */ -export class Compact implements ICompact { +export class Compact implements ICompact { public readonly registry: Registry; public createdAtHash?: Hash; @@ -33,7 +32,7 @@ export class Compact implements ICompact { this.#raw = Compact.decodeCompact(registry, this.#Type, value) as T; } - public static with (Type: Constructor | string): Constructor> { + public static with (Type: Constructor | string): Constructor> { return class extends Compact { constructor (registry: Registry, value?: Compact | AnyNumber) { super(registry, Type, value); @@ -42,7 +41,7 @@ export class Compact implements ICompact { } /** @internal */ - public static decodeCompact (registry: Registry, Type: Constructor, value: Compact | AnyNumber): CompactEncodable { + public static decodeCompact (registry: Registry, Type: Constructor, value: Compact | AnyNumber): INumber { if (value instanceof Compact) { return new Type(registry, value.#raw); } else if (isString(value) || isNumber(value) || isBn(value) || isBigInt(value)) { diff --git a/packages/types/src/codec/Enum.ts b/packages/types/src/codec/Enum.ts index c3cfaf8dde..cb08741709 100644 --- a/packages/types/src/codec/Enum.ts +++ b/packages/types/src/codec/Enum.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import type { CodecHash, Hash } from '../interfaces'; -import type { AnyJson, Codec, Constructor, Registry } from '../types'; +import type { AnyJson, Codec, Constructor, IEnum, Registry } from '../types'; import { assert, hexToU8a, isHex, isNumber, isObject, isString, isU8a, isUndefined, stringCamelCase, stringify, stringUpperFirst, u8aConcat, u8aToHex } from '@polkadot/util'; @@ -160,10 +160,7 @@ function decodeEnum (registry: Registry, def: TypesDef, value?: any, index?: num * This implements an enum, that based on the value wraps a different type. It is effectively * an extension to enum where the value type is determined by the actual index. */ -// TODO: -// - As per Enum, actually use TS enum -// - It should rather probably extend Enum instead of copying code -export class Enum implements Codec { +export class Enum implements IEnum { public readonly registry: Registry; public createdAtHash?: Hash; diff --git a/packages/types/src/codec/Struct.ts b/packages/types/src/codec/Struct.ts index 81d630aab1..eed2d4ff27 100644 --- a/packages/types/src/codec/Struct.ts +++ b/packages/types/src/codec/Struct.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import type { CodecHash, Hash } from '../interfaces/runtime'; -import type { AnyJson, BareOpts, Codec, Constructor, ConstructorDef, Registry } from '../types'; +import type { AnyJson, BareOpts, Codec, Constructor, ConstructorDef, IStruct, Registry } from '../types'; import { assert, hexToU8a, isBoolean, isFunction, isHex, isObject, isU8a, isUndefined, stringCamelCase, stringify, u8aConcat, u8aToHex } from '@polkadot/util'; @@ -136,7 +136,7 @@ export class Struct< // input values, mapped by key can be anything (construction) V extends { [K in keyof S]: any } = { [K in keyof S]: any }, // type names, mapped by key, name of Class in S - E extends { [K in keyof S]: string } = { [K in keyof S]: string }> extends Map implements Codec { + E extends { [K in keyof S]: string } = { [K in keyof S]: string }> extends Map implements IStruct { public readonly registry: Registry; public createdAtHash?: Hash; diff --git a/packages/types/src/codec/types.ts b/packages/types/src/codec/types.ts index bdaf5ddc72..e84cecaadf 100644 --- a/packages/types/src/codec/types.ts +++ b/packages/types/src/codec/types.ts @@ -1,16 +1,6 @@ // Copyright 2017-2021 @polkadot/types authors & contributors // SPDX-License-Identifier: Apache-2.0 -import type { BN } from '@polkadot/util'; -import type { Codec } from '../types'; - -export interface CompactEncodable extends Codec { - bitLength (): number; - toBigInt (): bigint; - toBn (): BN; - toNumber (): number; -} - export type UIntBitLength = 8 | 16 | 32 | 64 | 128 | 256; // The 520 here is a weird one - it is explicitly for a [u8; 65] as found as a EcdsaSignature, diff --git a/packages/types/src/types/detect.ts b/packages/types/src/types/detect.ts index 11b19e6273..c98897bea3 100644 --- a/packages/types/src/types/detect.ts +++ b/packages/types/src/types/detect.ts @@ -1,18 +1,15 @@ // Copyright 2017-2021 @polkadot/types authors & contributors // SPDX-License-Identifier: Apache-2.0 -import type { Compact, Option, Raw, Struct, Vec, VecFixed } from '../codec'; -import type { CompactEncodable } from '../codec/types'; +import type { Compact, Option, Raw, Vec, VecFixed } from '../codec'; import type { Bytes } from '../primitive'; import type { Codec, Constructor } from './codec'; -import type { ICompact, IOption, ITuple, IU8a, IVec } from './interfaces'; +import type { ICompact, IEnum, INumber, IOption, IStruct, ITuple, IU8a, IVec } from './interfaces'; import type { InterfaceTypes } from './registry'; -export type DetectCodec = Expand; +export type DetectCodec = __Expand; -export type DetectConstructor = Constructor>; - -export type Expand = __Internal, T>; +export type DetectConstructor = Constructor<__Expand>; // trim leading and trailing spaces export type Trim = @@ -22,40 +19,37 @@ export type Trim = ? Trim : K; -export type __DetectableTypes = CompactEncodable | ICompact | IOption | ITuple | IU8a | IVec | Struct; +export type __Expand = __Internal, T>; export type __Internal = K extends keyof InterfaceTypes ? InterfaceTypes[K] - : T extends __DetectableTypes + : T extends ICompact | IEnum | INumber | IOption | IStruct | ITuple | IU8a | IVec ? T : __Unwrap; // ensure whatever we wrap is always Compact-capable export type __Compact = - T extends CompactEncodable + T extends INumber ? Compact : never; -// currently we only support 5 levels for auto-extract +export type __Params = + X extends `${infer A},${infer B}` + ? [__Expand, ...__Params] + : [__Expand]; + export type __Tuple = - X extends `${infer A},${infer B},${infer C},${infer D},${infer E}` - ? ITuple<[Expand, Expand, Expand, Expand, Expand]> - : X extends `${infer A},${infer B},${infer C},${infer D}` - ? ITuple<[Expand, Expand, Expand, Expand]> - : X extends `${infer A},${infer B},${infer C}` - ? ITuple<[Expand, Expand, Expand]> - : X extends `${infer A},${infer B}` - ? ITuple<[Expand, Expand]> - : X extends `${infer A}` - ? Expand - : T; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + X extends `${infer A},${infer B}` + ? ITuple<__Params> + : __Expand; // vec support with short-circuit for u8 export type __Vec = Trim extends 'u8' ? Bytes - : Vec>; + : Vec<__Expand>; // fixed vec support export type __VecFixed = @@ -63,14 +57,14 @@ export type __VecFixed = X extends `${infer Y};${infer _}` ? Trim extends 'u8' ? Raw - : VecFixed> + : VecFixed<__Expand> : never; export type __Unwrap = K extends `Compact<${infer X}>` - ? __Compact> + ? __Compact<__Expand> : K extends `Option<${infer X}>` - ? Option> + ? Option<__Expand> : K extends `Vec<${infer X}>` ? __Vec : K extends `[${infer X}]` diff --git a/packages/types/src/types/interfaces.ts b/packages/types/src/types/interfaces.ts index f95175b61d..9a74665206 100644 --- a/packages/types/src/types/interfaces.ts +++ b/packages/types/src/types/interfaces.ts @@ -7,14 +7,30 @@ import type { FunctionMetadataLatest, StorageEntryMetadataLatest } from '../inte import type { Hash } from '../interfaces/runtime'; import type { AnyTuple, ArgsDef, Codec } from './codec'; -export interface ICompact extends Codec { +export interface ICompact extends Codec { toBigInt (): bigint; toBn (): BN; toNumber (): number; unwrap (): T; } -export interface IOption extends Codec { +export interface IEnum extends Codec { + index: number; + isBasic: boolean + type: string; + value: Codec; + + toNumber (): number; +} + +export interface INumber extends Codec { + bitLength (): number; + toBigInt (): bigint; + toBn (): BN; + toNumber (): number; +} + +export interface IOption extends Codec { isNone: boolean; isSome: boolean; value: Codec; @@ -24,9 +40,11 @@ export interface IOption extends Codec { unwrapOrDefault (): T; } +export interface IStruct extends Map, Codec {} + // A type alias for [Type1, Type2] & Codec, representing a tuple (Type1, Type2) // FIXME Implement this generic on Tuple.ts itself. -export type ITuple = S & Codec; +export type ITuple = S & Codec; export interface IU8a extends Uint8Array, Codec { bitLength (): number; @@ -34,7 +52,7 @@ export interface IU8a extends Uint8Array, Codec { toJSON (): any; } -export type IVec = Array & Codec; +export interface IVec extends Array, Codec {} export interface IKeyringPair { address: string;