Cater for higher-order tuples (#3851)

* Cater for higher-order tuples

* IEnum
This commit is contained in:
Jaco
2021-08-06 13:42:50 +02:00
committed by GitHub
parent 9ab662881f
commit 54bb965537
8 changed files with 55 additions and 59 deletions
+3 -5
View File
@@ -55,14 +55,12 @@ const hh = registry.createType('[u128; 32]');
assert(hh[0].bitLength(), 'All ok');
// tuple! ITuple<[u32, Compact<u64>, 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');
+2 -2
View File
@@ -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;
+4 -5
View File
@@ -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<T extends CompactEncodable> implements ICompact<T> {
export class Compact<T extends INumber> implements ICompact<T> {
public readonly registry: Registry;
public createdAtHash?: Hash;
@@ -33,7 +32,7 @@ export class Compact<T extends CompactEncodable> implements ICompact<T> {
this.#raw = Compact.decodeCompact<T>(registry, this.#Type, value) as T;
}
public static with<T extends CompactEncodable> (Type: Constructor<T> | string): Constructor<Compact<T>> {
public static with<T extends INumber> (Type: Constructor<T> | string): Constructor<Compact<T>> {
return class extends Compact<T> {
constructor (registry: Registry, value?: Compact<T> | AnyNumber) {
super(registry, Type, value);
@@ -42,7 +41,7 @@ export class Compact<T extends CompactEncodable> implements ICompact<T> {
}
/** @internal */
public static decodeCompact<T extends CompactEncodable> (registry: Registry, Type: Constructor<T>, value: Compact<T> | AnyNumber): CompactEncodable {
public static decodeCompact<T extends INumber> (registry: Registry, Type: Constructor<T>, value: Compact<T> | AnyNumber): INumber {
if (value instanceof Compact) {
return new Type(registry, value.#raw);
} else if (isString(value) || isNumber(value) || isBn(value) || isBigInt(value)) {
+2 -5
View File
@@ -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;
+2 -2
View File
@@ -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<keyof S, Codec> implements Codec {
E extends { [K in keyof S]: string } = { [K in keyof S]: string }> extends Map<keyof S, Codec> implements IStruct {
public readonly registry: Registry;
public createdAtHash?: Hash;
-10
View File
@@ -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,
+20 -26
View File
@@ -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<T extends Codec, K extends string> = Expand<K, T>;
export type DetectCodec<T extends Codec, K extends string> = __Expand<K, T>;
export type DetectConstructor<T extends Codec, K extends string> = Constructor<Expand<K, T>>;
export type Expand<K extends string, T extends Codec = Codec> = __Internal<Trim<K>, T>;
export type DetectConstructor<T extends Codec, K extends string> = Constructor<__Expand<K, T>>;
// trim leading and trailing spaces
export type Trim<K extends string> =
@@ -22,40 +19,37 @@ export type Trim<K extends string> =
? Trim<X>
: K;
export type __DetectableTypes = CompactEncodable | ICompact<CompactEncodable> | IOption<Codec> | ITuple<Codec[]> | IU8a | IVec<Codec> | Struct;
export type __Expand<K extends string, T extends Codec = Codec> = __Internal<Trim<K>, T>;
export type __Internal<K extends string, T extends Codec> =
K extends keyof InterfaceTypes
? InterfaceTypes[K]
: T extends __DetectableTypes
: T extends ICompact | IEnum | INumber | IOption | IStruct | ITuple | IU8a | IVec
? T
: __Unwrap<K, T>;
// ensure whatever we wrap is always Compact-capable
export type __Compact<T extends Codec> =
T extends CompactEncodable
T extends INumber
? Compact<T>
: never;
// currently we only support 5 levels for auto-extract
export type __Params<X extends string> =
X extends `${infer A},${infer B}`
? [__Expand<A>, ...__Params<B>]
: [__Expand<X>];
export type __Tuple<X extends string, T extends Codec> =
X extends `${infer A},${infer B},${infer C},${infer D},${infer E}`
? ITuple<[Expand<A>, Expand<B>, Expand<C>, Expand<D>, Expand<E>]>
: X extends `${infer A},${infer B},${infer C},${infer D}`
? ITuple<[Expand<A>, Expand<B>, Expand<C>, Expand<D>]>
: X extends `${infer A},${infer B},${infer C}`
? ITuple<[Expand<A>, Expand<B>, Expand<C>]>
: X extends `${infer A},${infer B}`
? ITuple<[Expand<A>, Expand<B>]>
: X extends `${infer A}`
? Expand<A>
: T;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
X extends `${infer A},${infer B}`
? ITuple<__Params<X>>
: __Expand<X, T>;
// vec support with short-circuit for u8
export type __Vec<X extends string, T extends Codec> =
Trim<X> extends 'u8'
? Bytes
: Vec<Expand<X, T>>;
: Vec<__Expand<X, T>>;
// fixed vec support
export type __VecFixed<X extends string> =
@@ -63,14 +57,14 @@ export type __VecFixed<X extends string> =
X extends `${infer Y};${infer _}`
? Trim<Y> extends 'u8'
? Raw
: VecFixed<Expand<Y>>
: VecFixed<__Expand<Y>>
: never;
export type __Unwrap<K extends string, T extends Codec> =
K extends `Compact<${infer X}>`
? __Compact<Expand<X>>
? __Compact<__Expand<X>>
: K extends `Option<${infer X}>`
? Option<Expand<X>>
? Option<__Expand<X>>
: K extends `Vec<${infer X}>`
? __Vec<X, T>
: K extends `[${infer X}]`
+22 -4
View File
@@ -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<T extends Codec> extends Codec {
export interface ICompact<T extends INumber = INumber> extends Codec {
toBigInt (): bigint;
toBn (): BN;
toNumber (): number;
unwrap (): T;
}
export interface IOption<T extends Codec> 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<T extends Codec = Codec> extends Codec {
isNone: boolean;
isSome: boolean;
value: Codec;
@@ -24,9 +40,11 @@ export interface IOption<T extends Codec> extends Codec {
unwrapOrDefault (): T;
}
export interface IStruct extends Map<unknown, Codec>, Codec {}
// A type alias for [Type1, Type2] & Codec, representing a tuple (Type1, Type2)
// FIXME Implement this generic <Sub> on Tuple.ts itself.
export type ITuple<S extends AnyTuple> = S & Codec;
export type ITuple<S extends AnyTuple = Codec[]> = 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<S extends Codec> = Array<S> & Codec;
export interface IVec<S extends Codec = Codec> extends Array<S>, Codec {}
export interface IKeyringPair {
address: string;