Type detection with trimming (#3850)
* Type detection with trimming * Additional interface check
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
import type { Compact, Option } from './codec';
|
||||
import type { AccountId, BlockAttestations, SessionKeys7 } from './interfaces';
|
||||
import type { Bytes, u32 } from './primitive';
|
||||
import type { IOption, ITuple } from './types';
|
||||
|
||||
import { assert } from '@polkadot/util';
|
||||
|
||||
@@ -17,32 +18,34 @@ const oo1 = registry.createType<BlockAttestations>('u32');
|
||||
const oo2 = registry.createType<SessionKeys7>('u32');
|
||||
const oo3 = registry.createType<u32>('Something');
|
||||
const oo4 = registry.createType<AccountId>('Option<u32>');
|
||||
const oo5 = registry.createType<Option<u32>>('u32');
|
||||
const oo5 = registry.createType<IOption<u32>>('u32');
|
||||
const oo6 = registry.createType<Option<Compact<u32>>>('u32');
|
||||
const oo7 = registry.createType<Bytes>('u64');
|
||||
const oo8 = registry.createType<ITuple<[Bytes, u32]>>('Something');
|
||||
|
||||
assert(oo0.divn(123) && [...oo1.values()] && oo2[6].isAscii && oo3.divn(3) && oo4.isAscii && oo5.unwrap().divn(1) && oo6.unwrap().unwrap().divn(1) && oo7.isAscii, 'All ok');
|
||||
assert(oo0.divn(123) && [...oo1.values()] && oo2[6].isAscii && oo3.divn(3) && oo4.isAscii && oo5.unwrap().divn(1) && oo6.unwrap().unwrap().divn(1) && oo7.isAscii && oo8[1].toNumber(), 'All ok');
|
||||
|
||||
// There are in the interface registry
|
||||
const aa0 = registry.createType('AccountId');
|
||||
const aa0 = registry.createType(' AccountId');
|
||||
const aa1 = registry.createType('BlockAttestations');
|
||||
const aa2 = registry.createType('ExtrinsicEra');
|
||||
|
||||
assert(aa0.isAscii && aa1.receipt, 'All ok');
|
||||
assert(aa0.isAscii && aa1.receipt && aa2.isMortalEra, 'All ok');
|
||||
|
||||
// Should be Codec, we don't know this one
|
||||
const bb = registry.createType('Something');
|
||||
|
||||
assert(bb.toHuman(), 'All ok');
|
||||
|
||||
// Should be Vec<Option<Compact<u32>>>
|
||||
const ee = registry.createType('Vec<Option<Compact<u32>>>');
|
||||
// Should be Vec<Option<Compact<ReferendumIndex>>>
|
||||
const ee = registry.createType('Vec<Option<Compact<ReferendumIndex>>>');
|
||||
// Option<Bytes>
|
||||
const vb = registry.createType('Option<Vec<u8>>');
|
||||
const vb = registry.createType('Option< Vec< u8 > >');
|
||||
|
||||
assert(ee[0].unwrap().unwrap().divn(123) && vb.unwrap().bitLength(), 'All ok');
|
||||
|
||||
// Should end up as Raw
|
||||
const gg = registry.createType('[u8;678]');
|
||||
const gg = registry.createType('[ u8 ;678]');
|
||||
|
||||
assert(gg.bitLength, 'All ok');
|
||||
|
||||
@@ -52,9 +55,9 @@ 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)');
|
||||
const tt2 = registry.createType('( u32 )');
|
||||
// max number of params
|
||||
const tt3 = registry.createType('(u8,u16,u32,u64,u128)');
|
||||
// lots and lots of params
|
||||
|
||||
@@ -2,72 +2,79 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { Compact, Option, Raw, Struct, Vec, VecFixed } from '../codec';
|
||||
import type { AbstractArray } from '../codec/AbstractArray';
|
||||
import type { CompactEncodable } from '../codec/types';
|
||||
import type { Bytes } from '../primitive';
|
||||
import type { Codec, Constructor } from './codec';
|
||||
import type { ITuple } from './interfaces';
|
||||
import type { ICompact, IOption, ITuple, IU8a, IVec } from './interfaces';
|
||||
import type { InterfaceTypes } from './registry';
|
||||
|
||||
// Vec & Tuple extends AbstractArray
|
||||
export type KnownDetects = Compact<CompactEncodable> | Option<Codec> | AbstractArray<Codec> | Raw | Struct;
|
||||
|
||||
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> = K extends keyof InterfaceTypes
|
||||
? InterfaceTypes[K]
|
||||
// these are the ones we short-circuit in the wrap itself
|
||||
: T extends KnownDetects
|
||||
? T
|
||||
: // strip any leading spaces from the types...
|
||||
K extends ` ${infer I}`
|
||||
? Expand<I, T>
|
||||
// ... and any trailing spaces
|
||||
: K extends `${infer I} `
|
||||
? Expand<I, T>
|
||||
: ExpandWrap<K, T>;
|
||||
export type Expand<K extends string, T extends Codec = Codec> = __Internal<Trim<K>, T>;
|
||||
|
||||
// trim leading and trailing spaces
|
||||
export type Trim<K extends string> =
|
||||
K extends ` ${infer X}`
|
||||
? Trim<X>
|
||||
: K extends `${infer X} `
|
||||
? Trim<X>
|
||||
: K;
|
||||
|
||||
export type __DetectableTypes = CompactEncodable | ICompact<CompactEncodable> | IOption<Codec> | ITuple<Codec[]> | IU8a | IVec<Codec> | Struct;
|
||||
|
||||
export type __Internal<K extends string, T extends Codec> =
|
||||
K extends keyof InterfaceTypes
|
||||
? InterfaceTypes[K]
|
||||
: T extends __DetectableTypes
|
||||
? T
|
||||
: __Unwrap<K, T>;
|
||||
|
||||
// ensure whatever we wrap is always Compact-capable
|
||||
export type ExpandCompact<T extends Codec> = T extends CompactEncodable
|
||||
? Compact<T>
|
||||
: never;
|
||||
export type __Compact<T extends Codec> =
|
||||
T extends CompactEncodable
|
||||
? Compact<T>
|
||||
: never;
|
||||
|
||||
// currently we only support 5 levels for auto-extract
|
||||
export type ExpandTuple<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;
|
||||
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;
|
||||
|
||||
// vec support with short-circuit for u8
|
||||
export type ExpandVec<X extends string, T extends Codec> = X extends 'u8'
|
||||
? Bytes
|
||||
: Vec<Expand<X, T>>;
|
||||
export type __Vec<X extends string, T extends Codec> =
|
||||
Trim<X> extends 'u8'
|
||||
? Bytes
|
||||
: Vec<Expand<X, T>>;
|
||||
|
||||
// fixed vec support
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export type ExpandVecFixed<X extends string> = X extends `${infer Y};${infer _}`
|
||||
? Y extends 'u8'
|
||||
? Raw
|
||||
: VecFixed<Expand<Y>>
|
||||
: never;
|
||||
export type __VecFixed<X extends string> =
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
X extends `${infer Y};${infer _}`
|
||||
? Trim<Y> extends 'u8'
|
||||
? Raw
|
||||
: VecFixed<Expand<Y>>
|
||||
: never;
|
||||
|
||||
export type ExpandWrap<K extends string, T extends Codec> = K extends `Compact<${infer X}>`
|
||||
? ExpandCompact<Expand<X>>
|
||||
: K extends `Option<${infer X}>`
|
||||
? Option<Expand<X>>
|
||||
: K extends `Vec<${infer X}>`
|
||||
? ExpandVec<X, T>
|
||||
: K extends `[${infer X}]`
|
||||
? ExpandVecFixed<X>
|
||||
: K extends `(${infer X})`
|
||||
? ExpandTuple<X, T>
|
||||
: T;
|
||||
export type __Unwrap<K extends string, T extends Codec> =
|
||||
K extends `Compact<${infer X}>`
|
||||
? __Compact<Expand<X>>
|
||||
: K extends `Option<${infer X}>`
|
||||
? Option<Expand<X>>
|
||||
: K extends `Vec<${infer X}>`
|
||||
? __Vec<X, T>
|
||||
: K extends `[${infer X}]`
|
||||
? __VecFixed<X>
|
||||
: K extends `(${infer X})`
|
||||
? __Tuple<X, T>
|
||||
: T;
|
||||
|
||||
Reference in New Issue
Block a user