RPC-core createType swap (#3786)

* RPC-core createType swap

* CHANGELOG

* createType complexity
This commit is contained in:
Jaco
2021-07-21 11:36:10 +02:00
committed by GitHub
parent 9309e9f3a1
commit 0be1d46be9
7 changed files with 55 additions and 42 deletions
+8 -22
View File
@@ -11,7 +11,7 @@ import type { RpcInterface, RpcInterfaceMethod } from './types';
import { Observable, publishReplay, refCount } from 'rxjs';
import { createClass, createTypeUnsafe, Option, rpcDefinitions } from '@polkadot/types';
import { rpcDefinitions } from '@polkadot/types';
import { assert, hexToU8a, isFunction, isNull, isUndefined, logger, memoize, u8aToU8a } from '@polkadot/util';
import { drr, refCountDelay } from './util';
@@ -339,7 +339,7 @@ export class RpcCore {
assert(inputs.length >= reqArgCount && inputs.length <= def.params.length, () => `Expected ${def.params.length} parameters${optText}, ${inputs.length} found instead`);
return inputs.map((input, index): Codec =>
createTypeUnsafe(registry, def.params[index].type, [input], { blockHash })
registry.createTypeUnsafe(def.params[index].type, [input], { blockHash })
);
}
@@ -366,7 +366,7 @@ export class RpcCore {
: mapped as unknown as Codec[];
}
return createTypeUnsafe(registry, rpc.type, [result], { blockHash });
return registry.createTypeUnsafe(rpc.type, [result], { blockHash });
}
private _formatStorageData (registry: Registry, blockHash: Uint8Array | string | null | undefined, key: StorageKey, value: string | null): Codec {
@@ -432,29 +432,15 @@ export class RpcCore {
: ` entry ${entryIndex}:`;
try {
if (meta.modifier.isOptional) {
let inner = null;
if (!isEmpty) {
inner = createTypeUnsafe(registry, type, [input], { blockHash, isPedantic: true });
}
const option = new Option(registry, createClass(registry, type), inner);
if (blockHash) {
option.createdAtHash = registry.createType('Hash', blockHash);
}
return option;
}
return createTypeUnsafe(registry, type, [
return registry.createTypeUnsafe(type, [
isEmpty
? meta.fallback
? hexToU8a(meta.fallback.toHex())
: undefined
: input
], { blockHash, isPedantic: true });
: meta.modifier.isOptional
? registry.createTypeUnsafe(type, [input], { blockHash, isPedantic: true })
: input
], { blockHash, isOptional: meta.modifier.isOptional, isPedantic: !meta.modifier.isOptional });
} catch (error) {
throw new Error(`Unable to decode storage ${key.section || 'unknown'}.${key.method || 'unknown'}:${entryNum}: ${(error as Error).message}`);
}
+5 -2
View File
@@ -9,5 +9,8 @@ export * from './imports';
export * from './initMeta';
export * from './register';
export const compareName = (a: { name: { toString(): string } }, b: { name: { toString(): string } }): number =>
a.name.toString().localeCompare(b.name.toString());
type Cmp = { name: { toString(): string } };
export function compareName (a: Cmp, b: Cmp): number {
return a.name.toString().localeCompare(b.name.toString());
}
+16 -16
View File
@@ -3,20 +3,16 @@
import type { Bytes } from '../primitive/Bytes';
import type { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import type { FromReg } from './types';
import type { CreateOptions, FromReg } from './types';
import { assert, isHex, isU8a, u8aEq, u8aToHex, u8aToU8a } from '@polkadot/util';
import { Option } from '../codec/Option';
import { createClass } from './createClass';
interface CreateOptions {
blockHash?: Uint8Array | string | null;
isPedantic?: boolean;
}
// 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 {
function checkInstance (created: FromReg<Codec, string>, value: Uint8Array): void {
const u8a = created.toU8a();
const rawType = created.toRawType();
@@ -30,25 +26,29 @@ function checkInstance<T extends Codec = Codec, K extends string = string> (valu
);
}
// 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: unknown[] = [], { blockHash, isPedantic }: CreateOptions = {}): FromReg<T, K> {
const created = new Type(registry, ...params);
const value = params[0];
function checkPedantic (created: FromReg<Codec, string>, [value]: unknown[], isPedantic = false): void {
if (isPedantic) {
if (isU8a(value)) {
checkInstance(value, created);
checkInstance(created, value);
} else if (isHex(value)) {
checkInstance(u8aToU8a(value), created);
checkInstance(created, u8aToU8a(value));
}
}
}
// 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: unknown[] = [], { blockHash, isOptional, isPedantic }: CreateOptions = {}): FromReg<T, K> {
const created = new (isOptional ? Option.with(Type) : Type)(registry, ...params);
checkPedantic(created, params, isPedantic);
if (blockHash) {
created.createdAtHash = createType(registry, 'Hash', blockHash);
}
return created;
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return created as any;
}
// An unsafe version of the `createType` below. It's unsafe because the `type`
+10 -2
View File
@@ -6,6 +6,7 @@
import type { ExtDef } from '../extrinsic/signedExtensions/types';
import type { ChainProperties, CodecHash, DispatchErrorModule, Hash, MetadataLatest, PortableRegistry, SiLookupTypeId } from '../interfaces/types';
import type { CallFunction, Codec, CodecHasher, Constructor, InterfaceTypes, RegisteredTypes, Registry, RegistryError, RegistryTypes } from '../types';
import type { CreateOptions } from './types';
import { assert, assertReturn, BN_ZERO, formatBalance, isFunction, isString, isU8a, logger, stringCamelCase, stringify, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -20,7 +21,7 @@ import * as definitions from '../interfaces/definitions';
import { decorateConstants, decorateExtrinsics } from '../metadata/decorate';
import { Metadata } from '../metadata/Metadata';
import { createClass, getTypeClass } from './createClass';
import { createType } from './createType';
import { createTypeUnsafe } from './createType';
import { getTypeDef } from './getTypeDef';
const l = logger('registry');
@@ -247,7 +248,14 @@ export class TypeRegistry implements Registry {
* @description Creates an instance of a type as registered
*/
public createType <K extends keyof InterfaceTypes> (type: K, ...params: unknown[]): InterfaceTypes[K] {
return createType(this, type, ...params);
return createTypeUnsafe(this, type, params);
}
/**
* @description Creates an instance of a type as registered
*/
public createTypeUnsafe <T extends Codec = Codec, K extends string = string> (type: K, params: unknown[], options?: CreateOptions): T {
return createTypeUnsafe(this, type, params, options);
}
// find a specific call
+6
View File
@@ -43,3 +43,9 @@ export interface TypeDef {
sub?: TypeDef | TypeDef[];
type: string;
}
export interface CreateOptions {
blockHash?: Uint8Array | string | null;
isOptional?: boolean;
isPedantic?: boolean;
}
+2
View File
@@ -3,6 +3,7 @@
import type { Observable } from 'rxjs';
import type { BN } from '@polkadot/util';
import type { CreateOptions } from '../create/types';
import type { ExtDef } from '../extrinsic/signedExtensions/types';
import type { MetadataLatest, PortableRegistry } from '../interfaces/metadata';
import type { CodecHash, Hash } from '../interfaces/runtime';
@@ -120,6 +121,7 @@ export interface Registry {
createClass <K extends keyof InterfaceTypes> (type: K): Constructor<InterfaceTypes[K]>;
createType <K extends keyof InterfaceTypes> (type: K, ...params: unknown[]): InterfaceTypes[K];
createTypeUnsafe <T extends Codec = Codec, K extends string = string> (type: K, params: unknown[], options?: CreateOptions): T;
get <T extends Codec = Codec> (name: string, withUnknown?: boolean): Constructor<T> | undefined;
getChainProperties (): ChainProperties | undefined;
getClassName (clazz: Constructor): string | undefined;