diff --git a/packages/api-derive/src/democracy/dispatchQueue.ts b/packages/api-derive/src/democracy/dispatchQueue.ts index 55979cdce8..79bf235093 100644 --- a/packages/api-derive/src/democracy/dispatchQueue.ts +++ b/packages/api-derive/src/democracy/dispatchQueue.ts @@ -10,6 +10,7 @@ import type { DeriveApi, DeriveDispatch, DeriveProposalImage } from '../types'; import { catchError, combineLatest, map, of, switchMap } from 'rxjs'; +import { Enum } from '@polkadot/types'; import { isFunction, stringToHex } from '@polkadot/util'; import { memo } from '../util'; @@ -24,7 +25,7 @@ interface SchedulerInfo { function isMaybeHashed (call: FrameSupportScheduleMaybeHashed | Call): call is FrameSupportScheduleMaybeHashed { // check for enum - return (call as FrameSupportScheduleMaybeHashed).isBasic === false; + return call instanceof Enum; } function queryQueue (api: DeriveApi): Observable { diff --git a/packages/types-codec/src/abstract/AbstractArray.ts b/packages/types-codec/src/abstract/AbstractArray.ts index 3e12b2208f..dd92d1bb95 100644 --- a/packages/types-codec/src/abstract/AbstractArray.ts +++ b/packages/types-codec/src/abstract/AbstractArray.ts @@ -73,14 +73,14 @@ export abstract class AbstractArray extends Array implements /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { return { inner: this.inspectInner(), outer: [compactToU8a(this.length)] }; } - inspectInner (): Inspect[] { + public inspectInner (): Inspect[] { const inner = new Array(this.length); for (let i = 0; i < this.length; i++) { diff --git a/packages/types-codec/src/abstract/AbstractInt.ts b/packages/types-codec/src/abstract/AbstractInt.ts index c650398a00..7dbf8967eb 100644 --- a/packages/types-codec/src/abstract/AbstractInt.ts +++ b/packages/types-codec/src/abstract/AbstractInt.ts @@ -4,7 +4,7 @@ import type { HexString } from '@polkadot/util/types'; import type { AnyNumber, Inspect, INumber, IU8a, Registry, UIntBitLength } from '../types'; -import { assert, BN, BN_BILLION, BN_HUNDRED, BN_MILLION, BN_QUINTILL, BN_ZERO, bnToBn, bnToHex, bnToU8a, formatBalance, formatNumber, hexToBn, isBn, isHex, isNumber, isString, isU8a, u8aToBn } from '@polkadot/util'; +import { assert, BN, BN_BILLION, BN_HUNDRED, BN_MILLION, BN_QUINTILL, BN_ZERO, bnToBn, bnToHex, bnToU8a, formatBalance, formatNumber, hexToBn, isBn, isHex, isNumber, isString, isU8a, u8aToBn, u8aToNumber } from '@polkadot/util'; export const DEFAULT_UINT_BITS = 64; @@ -55,27 +55,29 @@ export abstract class AbstractInt extends BN implements INumber { public createdAtHash?: IU8a; - readonly encodedLength: number; + public readonly encodedLength: number; + + public readonly isUnsigned: boolean; readonly #bitLength: UIntBitLength; - readonly #isSigned: boolean; - constructor (registry: Registry, value: AnyNumber = 0, bitLength: UIntBitLength = DEFAULT_UINT_BITS, isSigned = false) { - // Construct via a string, which will be passed in the BN constructor. + // Construct via a string/number, which will be passed in the BN constructor. // It would be ideal to actually return a BN, but there is an issue: // https://github.com/indutny/bn.js/issues/206 super( // shortcut isU8a as used in SCALE decoding isU8a(value) - ? u8aToBn(value.subarray(0, bitLength / 8), { isLe: true, isNegative: isSigned }).toString() + ? bitLength <= 48 + ? u8aToNumber(value.subarray(0, bitLength / 8), { isNegative: isSigned }) + : u8aToBn(value.subarray(0, bitLength / 8), { isLe: true, isNegative: isSigned }).toString() : decodeAbstractInt(value, isSigned) ); this.registry = registry; this.#bitLength = bitLength; this.encodedLength = this.#bitLength / 8; - this.#isSigned = isSigned; + this.isUnsigned = !isSigned; const isPositive = this.gte(BN_ZERO); const maxBits = bitLength - (isSigned && isPositive ? 1 : 0); @@ -98,13 +100,6 @@ export abstract class AbstractInt extends BN implements INumber { return this.isZero(); } - /** - * @description Checks if the value is an unsigned type - */ - public get isUnsigned (): boolean { - return !this.#isSigned; - } - /** * @description Returns the number of bits in the value */ @@ -121,7 +116,7 @@ export abstract class AbstractInt extends BN implements INumber { // number and BN inputs (no `.eqn` needed) - numbers will be converted return super.eq( isHex(other) - ? hexToBn(other.toString(), { isLe: false, isNegative: this.#isSigned }) + ? hexToBn(other.toString(), { isLe: false, isNegative: !this.isUnsigned }) : bnToBn(other as string) ); } @@ -129,7 +124,7 @@ export abstract class AbstractInt extends BN implements INumber { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { return { outer: [this.toU8a()] }; diff --git a/packages/types-codec/src/base/Base.ts b/packages/types-codec/src/base/Base.ts index 59aaa11bf1..3197549b8a 100644 --- a/packages/types-codec/src/base/Base.ts +++ b/packages/types-codec/src/base/Base.ts @@ -9,18 +9,18 @@ import type { AnyJson, BareOpts, Codec, Inspect, IU8a, Registry } from '../types * @description A type extends the Base class, when it holds a value */ export abstract class Base implements Codec { - readonly #registry: Registry; - public createdAtHash?: IU8a; - readonly initialU8aLength?: number; + public readonly initialU8aLength?: number; + + public readonly registry: Registry; readonly #raw: T; protected constructor (registry: Registry, value: T, initialU8aLength?: number) { - this.#registry = registry; this.#raw = value; this.initialU8aLength = initialU8aLength; + this.registry = registry; } /** @@ -48,10 +48,6 @@ export abstract class Base implements Codec { return this.#raw.isEmpty; } - public get registry (): Registry { - return this.#registry; - } - /** * @description Compares the value of the input to see if there is a match */ @@ -62,7 +58,7 @@ export abstract class Base implements Codec { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { return this.#raw.inspect(); } diff --git a/packages/types-codec/src/base/Compact.ts b/packages/types-codec/src/base/Compact.ts index cf84b6ca02..13399578a6 100644 --- a/packages/types-codec/src/base/Compact.ts +++ b/packages/types-codec/src/base/Compact.ts @@ -18,6 +18,26 @@ function noopSetDefinition (d: CodecClass): CodecClass { return d; } +function decodeCompact (registry: Registry, Type: CodecClass, value: Compact | AnyNumber): [T, number] { + if (isU8a(value)) { + const [decodedLength, bn] = (value[0] & 0b11) < 0b11 + ? compactFromU8aLim(value) + : compactFromU8a(value); + + return [new Type(registry, bn), decodedLength]; + } else if (value instanceof Compact) { + const raw = value.unwrap(); + + return raw instanceof Type + ? [raw, 0] + : [new Type(registry, raw), 0]; + } else if (value instanceof Type) { + return [value, 0]; + } + + return [new Type(registry, value), 0]; +} + /** * @name Compact * @description @@ -41,7 +61,7 @@ export class Compact implements ICompact { this.registry = registry; this.#Type = definition || setDefinition(typeToConstructor(registry, Type)); - const [raw, decodedLength] = Compact.decodeCompact(registry, this.#Type, value); + const [raw, decodedLength] = decodeCompact(registry, this.#Type, value); this.initialU8aLength = decodedLength; this.#raw = raw; @@ -61,25 +81,6 @@ export class Compact implements ICompact { }; } - /** @internal */ - public static decodeCompact (registry: Registry, Type: CodecClass, value: Compact | AnyNumber): [T, number] { - if (isU8a(value)) { - const [decodedLength, bn] = (value[0] & 0b11) < 0b11 - ? compactFromU8aLim(value) - : compactFromU8a(value); - - return [new Type(registry, bn), decodedLength]; - } else if (value instanceof Compact) { - return value.#raw instanceof Type - ? [value.#raw, 0] - : [new Type(registry, value.#raw), 0]; - } else if (value instanceof Type) { - return [value, 0]; - } - - return [new Type(registry, value), 0]; - } - /** * @description The length of the value when encoded as a Uint8Array */ @@ -122,7 +123,7 @@ export class Compact implements ICompact { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { return { outer: [this.toU8a()] }; diff --git a/packages/types-codec/src/base/DoNotConstruct.ts b/packages/types-codec/src/base/DoNotConstruct.ts index cd1a3a1a62..39d9c8396f 100644 --- a/packages/types-codec/src/base/DoNotConstruct.ts +++ b/packages/types-codec/src/base/DoNotConstruct.ts @@ -56,7 +56,7 @@ export class DoNotConstruct implements Codec { throw this.#neverError; } - inspect (): Inspect { + public inspect (): Inspect { throw this.#neverError; } diff --git a/packages/types-codec/src/base/Enum.ts b/packages/types-codec/src/base/Enum.ts index 5cbad80160..197838982d 100644 --- a/packages/types-codec/src/base/Enum.ts +++ b/packages/types-codec/src/base/Enum.ts @@ -4,7 +4,7 @@ import type { HexString } from '@polkadot/util/types'; import type { AnyJson, Codec, CodecClass, IEnum, Inspect, IU8a, Registry } from '../types'; -import { assert, isCodec, isHex, isNumber, isObject, isString, isU8a, isUndefined, objectProperties, stringCamelCase, stringify, stringPascalCase, u8aConcatStrict, u8aToHex, u8aToU8a } from '@polkadot/util'; +import { assert, isHex, isNumber, isObject, isString, isU8a, isUndefined, objectProperties, stringCamelCase, stringify, stringPascalCase, u8aConcatStrict, u8aToHex, u8aToU8a } from '@polkadot/util'; import { mapToTypeMap, typesToMap } from '../utils'; import { Null } from './Null'; @@ -101,7 +101,7 @@ function createFromValue (registry: Registry, def: TypesDef, index = 0, value?: return { index, - value: isCodec(value) && value instanceof entry.Type + value: value instanceof entry.Type ? value : new entry.Type(registry, value) }; @@ -189,7 +189,7 @@ export class Enum implements IEnum { this.#isBasic = isBasic; this.#isIndexed = isIndexed; this.#indexes = Object.values(def).map(({ index }) => index); - this.#entryIndex = this.#indexes.indexOf(decoded.index) || 0; + this.#entryIndex = this.#indexes.indexOf(decoded.index); this.#raw = decoded.value; if (this.#raw.initialU8aLength) { @@ -205,7 +205,7 @@ export class Enum implements IEnum { const isKeys = new Array(keys.length); for (let i = 0; i < keys.length; i++) { - const name = stringPascalCase(keys[i].replace(' ', '_')); + const name = stringPascalCase(keys[i]); asKeys[i] = `as${name}`; isKeys[i] = `is${name}`; @@ -329,7 +329,7 @@ export class Enum implements IEnum { return this.type === other; } else if (isHex(other)) { return this.toHex() === other; - } else if (isCodec(other) && other instanceof Enum) { + } else if (other instanceof Enum) { return this.index === other.index && this.value.eq(other.value); } else if (isObject(other)) { return this.value.eq(other[this.type]); @@ -342,8 +342,8 @@ export class Enum implements IEnum { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { - if (this.isBasic) { + public inspect (): Inspect { + if (this.#isBasic) { return { outer: [new Uint8Array([this.index])] }; } diff --git a/packages/types-codec/src/base/Null.ts b/packages/types-codec/src/base/Null.ts index 8f075cf019..8bd4af2922 100644 --- a/packages/types-codec/src/base/Null.ts +++ b/packages/types-codec/src/base/Null.ts @@ -12,6 +12,10 @@ import { isNull } from '@polkadot/util'; * Implements a type that does not contain anything (apart from `null`) */ export class Null implements Codec { + public readonly encodedLength = 0; + + public readonly isEmpty = true; + public readonly registry: Registry; public createdAtHash?: IU8a; @@ -23,13 +27,6 @@ export class Null implements Codec { this.registry = registry; } - /** - * @description The length of the value when encoded as a Uint8Array - */ - public get encodedLength (): number { - return 0; - } - /** * @description returns a hash of the contents */ @@ -37,13 +34,6 @@ export class Null implements Codec { throw new Error('.hash is not implemented on Null'); } - /** - * @description Checks if the value is an empty value (always true) - */ - public get isEmpty (): boolean { - return true; - } - /** * @description Compares the value of the input to see if there is a match */ @@ -54,7 +44,7 @@ export class Null implements Codec { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { return {}; } diff --git a/packages/types-codec/src/base/Option.ts b/packages/types-codec/src/base/Option.ts index 45f6da8b9e..ea88140604 100644 --- a/packages/types-codec/src/base/Option.ts +++ b/packages/types-codec/src/base/Option.ts @@ -70,9 +70,9 @@ export class Option implements IOption { public createdAtHash?: IU8a; - readonly #Type: CodecClass; + public initialU8aLength?: number; - readonly #initialU8aLength?: number; + readonly #Type: CodecClass; readonly #raw: T; @@ -89,7 +89,7 @@ export class Option implements IOption { this.#raw = decoded as T; if (decoded && decoded.initialU8aLength) { - this.#initialU8aLength = 1 + decoded.initialU8aLength; + this.initialU8aLength = 1 + decoded.initialU8aLength; } } @@ -117,13 +117,6 @@ export class Option implements IOption { return 1 + this.#raw.encodedLength; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public get initialU8aLength (): number | undefined { - return this.#initialU8aLength; - } - /** * @description returns a hash of the contents */ @@ -173,7 +166,7 @@ export class Option implements IOption { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { if (this.isNone) { return { outer: [new Uint8Array([0])] }; } diff --git a/packages/types-codec/src/base/Tuple.ts b/packages/types-codec/src/base/Tuple.ts index 7d50786b9d..a65e132dfd 100644 --- a/packages/types-codec/src/base/Tuple.ts +++ b/packages/types-codec/src/base/Tuple.ts @@ -26,7 +26,7 @@ function noopSetDefinition (d: Definition): Definition { } /** @internal */ -function decodeTuple (registry: Registry, result: Codec[], Classes: Definition, value?: Exclude): [Codec[], number] { +function decodeTuple (registry: Registry, result: Codec[], value: Exclude | undefined, Classes: Definition): [Codec[], number] { if (isU8a(value) || isHex(value)) { return decodeU8a(registry, result, u8aToU8a(value), Classes); } @@ -70,11 +70,11 @@ export class Tuple extends AbstractArray implements ITuple { super(registry, Classes[0].length); - const [, decodedLength] = isU8a(value) - ? decodeU8a(registry, this, value, Classes, false) - : decodeTuple(registry, this, Classes, value); - - this.initialU8aLength = decodedLength; + this.initialU8aLength = ( + isU8a(value) + ? decodeU8a(registry, this, value, Classes) + : decodeTuple(registry, this, value, Classes) + )[1]; this.#Types = Classes; } @@ -117,7 +117,7 @@ export class Tuple extends AbstractArray implements ITuple { /** * @description Returns a breakdown of the hex encoding for this Codec */ - override inspect (): Inspect { + public override inspect (): Inspect { return { inner: this.inspectInner() }; diff --git a/packages/types-codec/src/base/Vec.ts b/packages/types-codec/src/base/Vec.ts index f714e86eb1..c2abf10df1 100644 --- a/packages/types-codec/src/base/Vec.ts +++ b/packages/types-codec/src/base/Vec.ts @@ -78,11 +78,11 @@ export class Vec extends AbstractArray { this.#Type = definition || setDefinition(typeToConstructor(registry, Type)); - const [decodedLength] = isU8a(decodeFrom) - ? decodeU8aVec(registry, this, decodeFrom, startAt, this.#Type) - : decodeVec(registry, this, decodeFrom, startAt, this.#Type); - - this.initialU8aLength = decodedLength; + this.initialU8aLength = ( + isU8a(decodeFrom) + ? decodeU8aVec(registry, this, decodeFrom, startAt, this.#Type) + : decodeVec(registry, this, decodeFrom, startAt, this.#Type) + )[0]; } public static with (Type: CodecClass | string): CodecClass> { diff --git a/packages/types-codec/src/base/VecFixed.ts b/packages/types-codec/src/base/VecFixed.ts index d134f8bf91..d282c35b7d 100644 --- a/packages/types-codec/src/base/VecFixed.ts +++ b/packages/types-codec/src/base/VecFixed.ts @@ -34,11 +34,11 @@ export class VecFixed extends AbstractArray { this.#Type = definition || setDefinition(typeToConstructor(registry, Type)); - const [, decodedLengthNoOffset] = isU8a(value) - ? decodeU8aVec(registry, this, value, 0, this.#Type) - : decodeVec(registry, this, value, 0, this.#Type); - - this.initialU8aLength = decodedLengthNoOffset; + this.initialU8aLength = ( + isU8a(value) + ? decodeU8aVec(registry, this, value, 0, this.#Type) + : decodeVec(registry, this, value, 0, this.#Type) + )[1]; } public static with (Type: CodecClass | string, length: number): CodecClass> { @@ -78,7 +78,7 @@ export class VecFixed extends AbstractArray { /** * @description Returns a breakdown of the hex encoding for this Codec */ - override inspect (): Inspect { + public override inspect (): Inspect { return { inner: this.inspectInner() }; diff --git a/packages/types-codec/src/extended/BTreeSet.ts b/packages/types-codec/src/extended/BTreeSet.ts index 2f270ab34e..19c721cbab 100644 --- a/packages/types-codec/src/extended/BTreeSet.ts +++ b/packages/types-codec/src/extended/BTreeSet.ts @@ -140,7 +140,7 @@ export class BTreeSet extends Set implements ISet /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { const inner = new Array(); for (const v of this.values()) { diff --git a/packages/types-codec/src/extended/BitVec.ts b/packages/types-codec/src/extended/BitVec.ts index aeed798f9e..9d92862292 100644 --- a/packages/types-codec/src/extended/BitVec.ts +++ b/packages/types-codec/src/extended/BitVec.ts @@ -65,7 +65,7 @@ export class BitVec extends Raw { /** * @description Returns a breakdown of the hex encoding for this Codec */ - override inspect (): Inspect { + public override inspect (): Inspect { return { outer: [compactToU8a(this.#decodedLength), super.toU8a()] }; diff --git a/packages/types-codec/src/extended/Bytes.ts b/packages/types-codec/src/extended/Bytes.ts index 2587bdcc7f..ee6eb1b3b4 100644 --- a/packages/types-codec/src/extended/Bytes.ts +++ b/packages/types-codec/src/extended/Bytes.ts @@ -3,7 +3,7 @@ import type { AnyU8a, Inspect, Registry } from '../types'; -import { assert, compactAddLength, compactFromU8aLim, compactToU8a, isCodec, isString, isU8a, u8aToU8a } from '@polkadot/util'; +import { assert, compactAddLength, compactFromU8aLim, compactToU8a, isString, isU8a, u8aToU8a } from '@polkadot/util'; import { Raw } from '../native/Raw'; @@ -35,7 +35,7 @@ function decodeBytesU8a (value: Uint8Array): [Uint8Array, number] { */ export class Bytes extends Raw { constructor (registry: Registry, value?: AnyU8a) { - const [u8a, decodedLength] = isU8a(value) && !(isCodec(value) && value instanceof Raw) + const [u8a, decodedLength] = isU8a(value) && !(value instanceof Raw) ? decodeBytesU8a(value) : Array.isArray(value) || isString(value) ? [u8aToU8a(value), 0] @@ -54,7 +54,7 @@ export class Bytes extends Raw { /** * @description Returns a breakdown of the hex encoding for this Codec */ - override inspect (isBare?: boolean): Inspect { + public override inspect (isBare?: boolean): Inspect { const clength = compactToU8a(this.length); return { diff --git a/packages/types-codec/src/extended/Map.ts b/packages/types-codec/src/extended/Map.ts index d8b24669cf..4f535f43a2 100644 --- a/packages/types-codec/src/extended/Map.ts +++ b/packages/types-codec/src/extended/Map.ts @@ -154,7 +154,7 @@ export class CodecMap extends /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { const inner = new Array(); for (const [k, v] of this.entries()) { diff --git a/packages/types-codec/src/extended/OptionBool.ts b/packages/types-codec/src/extended/OptionBool.ts index f9adc66c90..b58fddafaa 100644 --- a/packages/types-codec/src/extended/OptionBool.ts +++ b/packages/types-codec/src/extended/OptionBool.ts @@ -32,6 +32,8 @@ export class OptionBool extends Option { ? decodeU8a(registry, u8aToU8a(value)) : value ); + + this.initialU8aLength = 1; } /** @@ -41,13 +43,6 @@ export class OptionBool extends Option { return 1; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public override get initialU8aLength (): number { - return 1; - } - /** * @description Checks if the value is an empty value (always false) */ @@ -69,7 +64,7 @@ export class OptionBool extends Option { /** * @description Returns a breakdown of the hex encoding for this Codec */ - override inspect (): Inspect { + public override inspect (): Inspect { return { outer: [this.toU8a()] }; } diff --git a/packages/types-codec/src/extended/WrapperKeepOpaque.ts b/packages/types-codec/src/extended/WrapperKeepOpaque.ts index 57bbc1fb6b..2f05147a31 100644 --- a/packages/types-codec/src/extended/WrapperKeepOpaque.ts +++ b/packages/types-codec/src/extended/WrapperKeepOpaque.ts @@ -70,7 +70,7 @@ export class WrapperKeepOpaque extends Bytes { /** * @description Returns a breakdown of the hex encoding for this Codec */ - override inspect (): Inspect { + public override inspect (): Inspect { return this.#decoded ? { inner: [this.#decoded.inspect()], diff --git a/packages/types-codec/src/native/Bool.ts b/packages/types-codec/src/native/Bool.ts index d41852f75f..80ed54da98 100644 --- a/packages/types-codec/src/native/Bool.ts +++ b/packages/types-codec/src/native/Bool.ts @@ -78,7 +78,7 @@ export class bool extends Boolean implements Codec { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { return { outer: [this.toU8a()] }; diff --git a/packages/types-codec/src/native/Date.ts b/packages/types-codec/src/native/Date.ts index 066d93a210..1962919824 100644 --- a/packages/types-codec/src/native/Date.ts +++ b/packages/types-codec/src/native/Date.ts @@ -81,7 +81,7 @@ export class CodecDate extends Date implements INumber { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { return { outer: [this.toU8a()] }; diff --git a/packages/types-codec/src/native/Raw.ts b/packages/types-codec/src/native/Raw.ts index 54fdcd7cb8..06defdb7c6 100644 --- a/packages/types-codec/src/native/Raw.ts +++ b/packages/types-codec/src/native/Raw.ts @@ -16,11 +16,11 @@ import { assert, isAscii, isUndefined, isUtf8, u8aToHex, u8aToString, u8aToU8a } * @noInheritDoc */ export class Raw extends Uint8Array implements IU8a { - readonly registry: Registry; - public createdAtHash?: IU8a; - readonly initialU8aLength?: number; + public readonly initialU8aLength?: number; + + public readonly registry: Registry; constructor (registry: Registry, value?: AnyU8a, initialU8aLength?: number) { super(u8aToU8a(value)); @@ -94,7 +94,7 @@ export class Raw extends Uint8Array implements IU8a { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { return { outer: [this.toU8a()] }; diff --git a/packages/types-codec/src/native/Set.ts b/packages/types-codec/src/native/Set.ts index b1f37e4ae1..9f02c76894 100644 --- a/packages/types-codec/src/native/Set.ts +++ b/packages/types-codec/src/native/Set.ts @@ -187,7 +187,7 @@ export class CodecSet extends Set implements ISet { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { return { outer: [this.toU8a()] }; diff --git a/packages/types-codec/src/native/Struct.ts b/packages/types-codec/src/native/Struct.ts index cf01968b21..99cc67e3ea 100644 --- a/packages/types-codec/src/native/Struct.ts +++ b/packages/types-codec/src/native/Struct.ts @@ -6,7 +6,7 @@ import type { AnyJson, BareOpts, Codec, CodecClass, Inspect, IStruct, IU8a, Regi import { assert, isBoolean, isFunction, isHex, isObject, isU8a, isUndefined, objectProperties, stringCamelCase, stringify, u8aConcatStrict, u8aToHex, u8aToU8a } from '@polkadot/util'; -import { compareMap, decodeU8a, mapToTypeMap, typesToMap } from '../utils'; +import { compareMap, decodeU8aStruct, mapToTypeMap, typesToMap } from '../utils'; type TypesDef = Record>; @@ -100,11 +100,11 @@ export class Struct< 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 IStruct { - #registry: Registry; - public createdAtHash?: IU8a; - readonly initialU8aLength?: number; + public readonly initialU8aLength?: number; + + public readonly registry: Registry; readonly #jsonMap: Map; @@ -113,15 +113,15 @@ export class Struct< constructor (registry: Registry, Types: S, value?: V | Map | unknown[] | HexString | null, jsonMap = new Map(), { definition, setDefinition = noopSetDefinition }: Options = {}) { const typeMap = definition || setDefinition(mapToTypeMap(registry, Types)); const [decoded, decodedLength] = isU8a(value) || isHex(value) - ? decodeU8a(registry, new Array(typeMap[0].length), u8aToU8a(value), typeMap, true) + ? decodeU8aStruct(registry, new Array<[string, Codec]>(typeMap[0].length), u8aToU8a(value), typeMap) : value instanceof Struct ? [value as Iterable<[string, Codec]>, 0] : decodeStructFromObject(registry, typeMap, value || {}, jsonMap); super(decoded); - this.#registry = registry; this.initialU8aLength = decodedLength; + this.registry = registry; this.#jsonMap = jsonMap; this.#Types = typeMap; } @@ -202,10 +202,6 @@ export class Struct< return this.registry.hash(this.toU8a()); } - public get registry (): Registry { - return this.#registry; - } - /** * @description Compares the value of the input to see if there is a match */ @@ -231,7 +227,7 @@ export class Struct< /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (isBare?: BareOpts): Inspect { + public inspect (isBare?: BareOpts): Inspect { const inner = new Array(); for (const [k, v] of this.entries()) { diff --git a/packages/types-codec/src/native/Text.ts b/packages/types-codec/src/native/Text.ts index de36ad21c9..608df159b3 100644 --- a/packages/types-codec/src/native/Text.ts +++ b/packages/types-codec/src/native/Text.ts @@ -46,11 +46,11 @@ function decodeText (value?: null | AnyString | AnyU8a | { toString: () => strin * @noInheritDoc */ export class Text extends String implements IText { - public readonly registry: Registry; - public createdAtHash?: IU8a; - readonly #initialU8aLength?: number; + public readonly initialU8aLength?: number; + + public readonly registry: Registry; #override: string | null = null; @@ -60,7 +60,7 @@ export class Text extends String implements IText { super(str); this.registry = registry; - this.#initialU8aLength = decodedLength; + this.initialU8aLength = decodedLength; } /** @@ -70,13 +70,6 @@ export class Text extends String implements IText { return this.toU8a().length; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public get initialU8aLength (): number | undefined { - return this.#initialU8aLength; - } - /** * @description returns a hash of the contents */ @@ -111,7 +104,7 @@ export class Text extends String implements IText { /** * @description Returns a breakdown of the hex encoding for this Codec */ - inspect (): Inspect { + public inspect (): Inspect { const value = stringToU8a(super.toString()); return { diff --git a/packages/types-codec/src/types/interfaces.ts b/packages/types-codec/src/types/interfaces.ts index 7bc97b2a8d..7346e1bf7f 100644 --- a/packages/types-codec/src/types/interfaces.ts +++ b/packages/types-codec/src/types/interfaces.ts @@ -17,7 +17,7 @@ export interface IEnum extends Codec { readonly defIndexes: number[]; readonly defKeys: string[]; readonly index: number; - readonly isBasic: boolean + readonly isBasic: boolean; readonly type: string; readonly value: Codec; diff --git a/packages/types-codec/src/utils/decodeU8a.ts b/packages/types-codec/src/utils/decodeU8a.ts index 14aa6a8057..f6a10ae0fe 100644 --- a/packages/types-codec/src/utils/decodeU8a.ts +++ b/packages/types-codec/src/utils/decodeU8a.ts @@ -5,19 +5,22 @@ import type { Codec, CodecClass, Registry } from '../types'; import { u8aToHex } from '@polkadot/util'; -function formatFailure (error: Error, type: string | null, u8a: Uint8Array, key?: string): string { - return `decodeU8a: failed at ${u8aToHex(u8a)}…${key ? ` on ${key}` : ''}${type ? `: ${type}` : ''}:: ${error.message}`; -} +/** @internal */ +function formatFailure (registry: Registry, { message }: Error, u8a: Uint8Array, i: number, count: number, Type: CodecClass, key?: string): string { + let type = ''; -function getRawType (registry: Registry, Type: CodecClass): string | null { try { - return new Type(registry).toRawType(); + type = `: ${new Type(registry).toRawType()}`; } catch { - return null; + // ignore } + + return `decodeU8a: failed at ${u8aToHex(u8a.subarray(0, 16))}…${key ? ` on ${key}` : ''} (index ${i}/${count})${type}:: ${message}`; } /** + * @internal + * * Given an u8a, and an array of Type constructors, decode the u8a against the * types, and return an array of decoded values. * @@ -25,50 +28,73 @@ function getRawType (registry: Registry, Type: CodecClass): string | null { * @param result - The result array (will be returned with values pushed) * @param types - The array of CodecClass to decode the U8a against. */ -export function decodeU8a (registry: Registry, result: unknown[], u8a: Uint8Array, [Types, keys]: [CodecClass[], string[]], withZip?: boolean): [E[], number] { +export function decodeU8a (registry: Registry, result: T[], u8a: Uint8Array, [Types, keys]: [CodecClass[], string[]]): [T[], number] { const count = result.length; let offset = 0; + let i = 0; - for (let i = 0; i < count; i++) { - try { + try { + while (i < count) { const value = new Types[i](registry, u8a.subarray(offset)); offset += value.initialU8aLength || value.encodedLength; - result[i] = withZip - ? [keys[i], value] - : value; - } catch (error) { - throw new Error(formatFailure( - error as Error, - getRawType(registry, Types[i]), - u8a.subarray(offset, offset + 16), - keys[i] - )); + result[i] = value; + i++; } + } catch (error) { + throw new Error(formatFailure(registry, error as Error, u8a.subarray(offset), i, count, Types[i], keys[i])); } - return [result as E[], offset]; + return [result, offset]; } -// Split from decodeU8a since this is specialized to 1 instance ... yes duplication, but -// since we have to do less checks (and these are intensive anyway), much faster +/** + * @internal + * + * Split from decodeU8a since this is specialized to zip returns ... while we duplicate, this + * is all on the hot-path, so it is not great, however there is (some) method behind the madness + */ +export function decodeU8aStruct (registry: Registry, result: [string, Codec][], u8a: Uint8Array, [Types, keys]: [CodecClass[], string[]]): [[string, Codec][], number] { + const count = result.length; + let offset = 0; + let i = 0; + + try { + while (i < count) { + const value = new Types[i](registry, u8a.subarray(offset)); + + offset += value.initialU8aLength || value.encodedLength; + result[i] = [keys[i], value]; + i++; + } + } catch (error) { + throw new Error(formatFailure(registry, error as Error, u8a.subarray(offset), i, count, Types[i], keys[i])); + } + + return [result, offset]; +} + +/** + * @internal + * + * Split from decodeU8a since this is specialized to 1 instance ... while we duplicate, this + * is all on the hot-path, so it is not great, however there is (some) method behind the madness + */ export function decodeU8aVec (registry: Registry, result: unknown[], u8a: Uint8Array, startAt: number, Type: CodecClass): [number, number] { const count = result.length; let offset = startAt; + let i = 0; - for (let i = 0; i < count; i++) { - try { + try { + while (i < count) { const value = new Type(registry, u8a.subarray(offset)); offset += value.initialU8aLength || value.encodedLength; result[i] = value; - } catch (error) { - throw new Error(formatFailure( - error as Error, - getRawType(registry, Type), - u8a.subarray(offset, offset + 16) - )); + i++; } + } catch (error) { + throw new Error(formatFailure(registry, error as Error, u8a.subarray(offset), i, count, Type)); } return [offset, offset - startAt]; diff --git a/packages/types-codec/src/utils/index.ts b/packages/types-codec/src/utils/index.ts index 79e134a940..ab7dc9f65d 100644 --- a/packages/types-codec/src/utils/index.ts +++ b/packages/types-codec/src/utils/index.ts @@ -4,7 +4,7 @@ export { compareArray } from './compareArray'; export { compareMap } from './compareMap'; export { compareSet } from './compareSet'; -export { decodeU8a, decodeU8aVec } from './decodeU8a'; +export { decodeU8a, decodeU8aStruct, decodeU8aVec } from './decodeU8a'; export { mapToTypeMap } from './mapToTypeMap'; export { typeToConstructor } from './typeToConstructor'; export { sanitize } from './sanitize'; diff --git a/packages/types-codec/src/utils/mapToTypeMap.ts b/packages/types-codec/src/utils/mapToTypeMap.ts index 1063dca9e7..0cbdb1dbf1 100644 --- a/packages/types-codec/src/utils/mapToTypeMap.ts +++ b/packages/types-codec/src/utils/mapToTypeMap.ts @@ -13,7 +13,7 @@ export function mapToTypeMap (registry: Registry, input: Record(count), new Array(count)]; - for (let i = 0; i < entries.length; i++) { + for (let i = 0; i < count; i++) { output[1][i] = entries[i][0]; output[0][i] = typeToConstructor(registry, entries[i][1]); } diff --git a/packages/types/src/extrinsic/Extrinsic.ts b/packages/types/src/extrinsic/Extrinsic.ts index 5665ce0c7c..8d600e52de 100644 --- a/packages/types/src/extrinsic/Extrinsic.ts +++ b/packages/types/src/extrinsic/Extrinsic.ts @@ -167,10 +167,6 @@ abstract class ExtrinsicBase extends Base extends Struct implement return this.registry.findMetaCall(this.callIndex).method; } - public override get registry (): Registry { - return super.registry; - } - /** * @description Returns the module containing the method */ diff --git a/packages/types/src/metadata/MetadataVersioned.ts b/packages/types/src/metadata/MetadataVersioned.ts index 97d4ba0fac..021bf58be5 100644 --- a/packages/types/src/metadata/MetadataVersioned.ts +++ b/packages/types/src/metadata/MetadataVersioned.ts @@ -73,10 +73,6 @@ export class MetadataVersioned extends Struct { return this.getT('metadata'); }; - public override get registry (): Registry { - return super.registry; - } - /** * @description Returns the wrapped metadata as a limited calls-only (latest) version */