Add createdAtHash to Codec interface (#3276)

* Add createdAtHash to Codec interface

* Adjust linkedHash (also on )

* createdAtHash
This commit is contained in:
Jaco Greeff
2021-03-07 16:00:30 +01:00
committed by GitHub
parent 22e5488f16
commit 3c9b7de6c7
26 changed files with 154 additions and 96 deletions
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyJson, Codec, Registry } from '../types';
import { compactToU8a, u8aConcat, u8aToHex } from '@polkadot/util';
@@ -18,6 +18,8 @@ import { compareArray } from './utils';
export abstract class AbstractArray<T extends Codec> extends Array<T> implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
protected constructor (registry: Registry, ...values: T[]) {
super(...values);
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyNumber, Codec, Registry } from '../types';
import type { UIntBitLength } from './types';
@@ -67,6 +67,8 @@ function decodeAbstractInt (value: AnyNumber, bitLength: UIntBitLength, isNegati
export abstract class AbstractInt extends BN implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
readonly #bitLength: UIntBitLength;
readonly #isSigned: boolean;
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { compactFromU8a, compactToU8a, isHex, isU8a, logger, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
@@ -79,6 +79,8 @@ function decodeSet<V extends Codec = Codec> (registry: Registry, valType: Constr
export class BTreeSet<V extends Codec = Codec> extends Set<V> implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
readonly #ValClass: Constructor<V>;
constructor (registry: Registry, valType: Constructor<V> | keyof InterfaceTypes, rawValue?: Uint8Array | string | string[] | Set<any>) {
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyJson, BareOpts, Codec, Registry } from '../types';
/**
@@ -11,6 +11,8 @@ import type { AnyJson, BareOpts, Codec, Registry } from '../types';
export abstract class Base<T extends Codec> implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
protected readonly _raw: T;
protected constructor (registry: Registry, value: T) {
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces';
import type { CodecHash, Hash } from '../interfaces';
import type { AnyJson, AnyNumber, Constructor, ICompact, InterfaceTypes, Registry } from '../types';
import type { CompactEncodable, UIntBitLength } from './types';
@@ -22,6 +22,8 @@ import { typeToConstructor } from './utils';
export class Compact<T extends CompactEncodable> implements ICompact<T> {
public readonly registry: Registry;
public createdAtHash?: Hash;
readonly #Type: Constructor<T>;
readonly #raw: T;
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyNumber, Codec, Registry } from '../types';
import type { UIntBitLength } from './types';
@@ -24,6 +24,8 @@ const BITLENGTH: UIntBitLength = 64;
export class CodecDate extends Date implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
constructor (registry: Registry, value: CodecDate | Date | AnyNumber = 0) {
super(CodecDate.decodeDate(value));
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces';
import type { CodecHash, Hash } from '../interfaces';
import type { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { assert, hexToU8a, isHex, isNumber, isObject, isString, isU8a, isUndefined, stringCamelCase, stringUpperFirst, u8aConcat, u8aToHex } from '@polkadot/util';
@@ -166,6 +166,8 @@ function decodeEnum (registry: Registry, def: TypesDef, value?: any, index?: num
export class Enum implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
readonly #def: TypesDef;
readonly #entryIndex: number;
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyJson, Codec, Registry } from '../types';
import { isFunction, isUndefined } from '@polkadot/util';
@@ -24,6 +24,8 @@ function decodeJson (value?: Record<string, unknown> | null): [string, any][] {
export class Json extends Map<string, any> implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
constructor (registry: Registry, value?: Record<string, unknown> | null) {
const decoded = decodeJson(value);
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { compactFromU8a, compactToU8a, isHex, isObject, isU8a, logger, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
@@ -88,6 +88,8 @@ function decodeMap<K extends Codec = Codec, V extends Codec = Codec> (registry:
export class CodecMap<K extends Codec = Codec, V extends Codec = Codec> extends Map<K, V> implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
readonly #KeyClass: Constructor<K>;
readonly #ValClass: Constructor<V>;
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces';
import type { CodecHash, Hash } from '../interfaces';
import type { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { assert, isNull, isU8a, isUndefined, u8aToHex } from '@polkadot/util';
@@ -50,6 +50,8 @@ function decodeOption (registry: Registry, typeName: Constructor | keyof Interfa
export class Option<T extends Codec> implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
readonly #Type: Constructor<T>;
readonly #raw: T;
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyJson, AnyU8a, IU8a, Registry } from '../types';
import { assert, isAscii, isUndefined, isUtf8, u8aToHex, u8aToString, u8aToU8a } from '@polkadot/util';
@@ -18,6 +18,8 @@ import { assert, isAscii, isUndefined, isUtf8, u8aToHex, u8aToString, u8aToU8a }
export class Raw extends Uint8Array implements IU8a {
public readonly registry: Registry;
public createdAtHash?: Hash;
constructor (registry: Registry, value?: AnyU8a) {
super(u8aToU8a(value));
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { Codec, Constructor, Registry } from '../types';
import BN from 'bn.js';
@@ -80,6 +80,8 @@ function decodeSet (setValues: SetValues, value: string[] | Set<string> | Uint8A
export class CodecSet extends Set<string> implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
readonly #allowed: SetValues;
readonly #byteLength: number;
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyJson, BareOpts, Codec, Constructor, ConstructorDef, InterfaceTypes, Registry } from '../types';
import { hexToU8a, isBoolean, isFunction, isHex, isObject, isU8a, isUndefined, stringCamelCase, u8aConcat, u8aToHex } from '@polkadot/util';
@@ -135,6 +135,8 @@ export class Struct<
E extends { [K in keyof S]: string } = { [K in keyof S]: string }> extends Map<keyof S, Codec> implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
readonly #jsonMap: Map<keyof S, string>;
readonly #Types: ConstructorDef;
+34 -34
View File
@@ -4,72 +4,72 @@
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { FromReg } from './types';
import { isU8a, logger, u8aToHex } from '@polkadot/util';
import { logger } from '@polkadot/util';
import { createClass } from './createClass';
interface UnsafeOptions {
interface CreateOptions {
blockHash?: Uint8Array | string | null;
isPedantic?: boolean;
withoutLog?: boolean;
}
const l = logger('registry');
function u8aHasValue (value: Uint8Array): boolean {
return value.some((v): boolean => !!v);
}
// TODO: Fix and re-enable
// 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<T extends Codec = Codec, K extends string = string> (value: Uint8Array, created: FromReg<T, K>): void {
// the underlying type created.toRawType()
const rawType = created.toRawType();
// function checkInstance<T extends Codec = Codec, K extends string = string> (value: Uint8Array, created: FromReg<T, K>): void {
// // the underlying type created.toRawType()
// const rawType = created.toRawType();
// ignore bytes completely - this is probably a FIXME, since these are somewhat
// breaking for at least online queries - not quite sure wtf is going wrong here
if (rawType === 'Bytes') {
return;
}
// // ignore bytes completely - this is probably a FIXME, since these are somewhat
// // breaking for at least online queries - not quite sure wtf is going wrong here
// if (rawType === 'Bytes') {
// return;
// }
// the hex values for what we have
const inHex = u8aToHex(value);
const crHex = created.toHex();
// // the hex values for what we have
// const inHex = u8aToHex(value);
// const crHex = created.toHex();
// Check equality, based on some different approaches (as decoded)
const isEqual = inHex === crHex || // raw hex values, quick path
inHex === created.toHex(true) || // wrapped options
u8aToHex(value.reverse()) === crHex; // reverse (for numbers, which are BE)
// // Check equality, based on some different approaches (as decoded)
// const isEqual = inHex === crHex || // raw hex values, quick path
// inHex === created.toHex(true) || // wrapped options
// u8aToHex(value.reverse()) === crHex; // reverse (for numbers, which are BE)
// if the hex doesn't match and the value for both is non-empty, complain... bitterly
if (!isEqual && (u8aHasValue(value) || u8aHasValue(created.toU8a(true)))) {
l.warn(`${rawType}:: Input doesn't match output, received ${u8aToHex(value)}, created ${crHex}`);
}
}
// // if the hex doesn't match and the value for both is non-empty, complain... bitterly
// if (!isEqual && (u8aHasValue(value) || u8aHasValue(created.toU8a(true)))) {
// l.warn(`${rawType}:: Input doesn't match output, received ${u8aToHex(value)}, created ${crHex}`);
// }
// }
// 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: any[] = [], isPedantic?: boolean): FromReg<T, K> {
function initType<T extends Codec = Codec, K extends string = string> (registry: Registry, Type: Constructor<FromReg<T, K>>, params: any[] = [], { blockHash }: CreateOptions = {}): FromReg<T, K> {
const created = new Type(registry, ...params);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const [value] = params;
if (isPedantic && isU8a(value)) {
checkInstance(value, created);
if (blockHash) {
created.createdAtHash = createType(registry, 'Hash', blockHash);
}
// if (isPedantic && isU8a(value)) {
// checkInstance(value, created);
// }
return created;
}
// 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: any[] = [], { withoutLog }: UnsafeOptions = {}): T {
export function createTypeUnsafe<T extends Codec = Codec, K extends string = string> (registry: Registry, type: K, params: any[] = [], options: CreateOptions = {}): T {
try {
// Circle back to isPedantic when it handles all cases 100% - as of now,
// it provides false warning which is more hinderance than help
return initType(registry, createClass<T, K>(registry, type), params); // , isPedantic);
return initType(registry, createClass<T, K>(registry, type), params, options);
} catch (error) {
!withoutLog && l.error(error);
!options.withoutLog && l.error(error);
throw new Error(`createType(${type}):: ${(error as Error).message}`);
}
+8 -2
View File
@@ -4,7 +4,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import type { ExtDef } from '../extrinsic/signedExtensions/types';
import type { ChainProperties, CodecHash, DispatchErrorModule } from '../interfaces/types';
import type { ChainProperties, CodecHash, DispatchErrorModule, Hash } from '../interfaces/types';
import type { CallFunction, Codec, CodecHasher, Constructor, InterfaceTypes, RegisteredTypes, Registry, RegistryError, RegistryTypes } from '../types';
// we are attempting to avoid circular refs, hence the Metadata path import
@@ -136,11 +136,17 @@ export class TypeRegistry implements Registry {
#userExtensions?: ExtDef;
constructor () {
public createdAtHash?: Hash;
constructor (createdAtHash?: Hash | Uint8Array | string) {
this.#knownDefaults = { Json, Metadata, Raw, ...baseTypes };
this.#knownDefinitions = definitions as unknown as Record<string, { types: RegistryTypes }>;
this.init();
if (createdAtHash) {
this.createdAtHash = this.createType('Hash', createdAtHash);
}
}
public init (): this {
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { Codec, Registry } from '../types';
import { isU8a, u8aToHex } from '@polkadot/util';
@@ -26,6 +26,8 @@ function decodeBool (value: any): boolean {
export class bool extends Boolean implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
// eslint-disable-next-line @typescript-eslint/ban-types
constructor (registry: Registry, value: bool | Boolean | Uint8Array | boolean | number = false) {
super(decodeBool(value));
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { Codec, Registry } from '../types';
import { isNull } from '@polkadot/util';
@@ -14,6 +14,8 @@ import { isNull } from '@polkadot/util';
export class Null implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
constructor (registry: Registry) {
this.registry = registry;
}
+3 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { AnyU8a, Codec, Registry } from '../types';
import { assert, compactAddLength, compactFromU8a, hexToU8a, isHex, isString, stringToU8a, u8aToHex, u8aToString } from '@polkadot/util';
@@ -50,6 +50,8 @@ function decodeText (value?: null | Text | string | AnyU8a | { toString: () => s
export class Text extends String implements Codec {
public readonly registry: Registry;
public createdAtHash?: Hash;
#override: string | null = null;
constructor (registry: Registry, value?: null | Text | string | AnyU8a | { toString: () => string }) {
+7 -2
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type BN from 'bn.js';
import type { H256 } from '../interfaces/runtime';
import type { Hash } from '../interfaces/runtime';
import type { Registry } from './registry';
export type AnyJson = string | number | boolean | null | undefined | AnyJson[] | { [index: string]: AnyJson };
@@ -46,7 +46,7 @@ export interface Codec {
/**
* @description Returns a hash of the value
*/
readonly hash: H256;
readonly hash: Hash;
/**
* @description Checks if the value is an empty value
@@ -58,6 +58,11 @@ export interface Codec {
*/
readonly registry: Registry;
/**
* @description The block at which this value was retrieved/created (set to non-empty when retrieved from storage)
*/
createdAtHash?: Hash;
/**
* @description Compares the value of the input to see if there is a match
*/
+3 -1
View File
@@ -5,7 +5,7 @@ import type BN from 'bn.js';
import type { Metadata } from '@polkadot/metadata';
import type { Observable } from '@polkadot/x-rxjs';
import type { ExtDef } from '../extrinsic/signedExtensions/types';
import type { CodecHash } from '../interfaces/runtime';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { ChainProperties } from '../interfaces/system';
import type { CallFunction } from './calls';
import type { Codec, Constructor } from './codec';
@@ -101,6 +101,8 @@ export interface Registry {
readonly unknownTypes: string[];
readonly signedExtensions: string[];
createdAtHash?: Hash;
findMetaCall (callIndex: Uint8Array): CallFunction;
findMetaError (errorIndex: Uint8Array | { error: BN, index: BN }): RegistryError;
// due to same circular imports where types don't really want to import from EventData,