From 022b938f00023015b8f2e17e88ca6d8a2a27e1ea Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Fri, 17 May 2019 14:39:17 +0200 Subject: [PATCH] Show section.method on storage read error (#928) * Show section.method on storage read error * Update packages/types/src/primitive/StorageKey.ts Co-Authored-By: Amaury Martiny * Update StorageKey.ts --- packages/rpc-core/src/index.ts | 18 ++++++- packages/types/src/primitive/StorageKey.ts | 60 ++++++++++++++++++---- 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/packages/rpc-core/src/index.ts b/packages/rpc-core/src/index.ts index 99bb226c88..05cefa28e9 100644 --- a/packages/rpc-core/src/index.ts +++ b/packages/rpc-core/src/index.ts @@ -196,7 +196,15 @@ export default class Rpc implements RpcInterface { const base = createType(method.type as string, result); if (method.type === 'StorageData') { - return this.formatStorageData(params[0] as StorageKey, base, isNull(result)); + const key = params[0] as StorageKey; + + try { + return this.formatStorageData(key, base, isNull(result)); + } catch (error) { + console.error(`Unable to decode storage ${key.section}.${key.method}:`, error.message); + + throw error; + } } else if (method.type === 'StorageChangeSet') { // multiple return values (via state.storage subscription), decode the values // one at a time, all based on the query types. Three values can be returned - @@ -204,7 +212,13 @@ export default class Rpc implements RpcInterface { // - null - The storage key is empty (but in the resultset) // - undefined - The storage value is not in the resultset return (params[0] as Vector).reduce((results, key: StorageKey) => { - results.push(this.formatStorageSet(key, base as StorageChangeSet)); + try { + results.push(this.formatStorageSet(key, base as StorageChangeSet)); + } catch (error) { + console.error(`Unable to decode storage ${key.section}.${key.method}:`, error.message); + + throw error; + } return results; }, [] as Array); diff --git a/packages/types/src/primitive/StorageKey.ts b/packages/types/src/primitive/StorageKey.ts index 594c14f148..ec657429c1 100644 --- a/packages/types/src/primitive/StorageKey.ts +++ b/packages/types/src/primitive/StorageKey.ts @@ -11,13 +11,19 @@ import { StorageFunctionMetadata as MetaV4 } from '../Metadata/v4/Storage'; export interface StorageFunction { (arg?: any): Uint8Array; + headKey?: Uint8Array; meta: MetaV4; method: string; section: string; toJSON: () => any; - headKey?: Uint8Array; } +type Decoded = { + key?: Uint8Array | string; + method?: string; + section?: string; +}; + /** * @name StorageKey * @description @@ -26,27 +32,49 @@ export interface StorageFunction { */ export default class StorageKey extends Bytes { private _meta?: MetaV4; + private _method?: string; private _outputType?: string; + private _section?: string; constructor (value?: AnyU8a | StorageKey | StorageFunction | [StorageFunction, any]) { - super(StorageKey.decodeStorageKey(value)); + const { key, method, section } = StorageKey.decodeStorageKey(value); + + super(key); this._meta = StorageKey.getMeta(value as StorageKey); + this._method = method; this._outputType = StorageKey.getType(value as StorageKey); + this._section = section; } - static decodeStorageKey (value?: AnyU8a | StorageKey | StorageFunction | [StorageFunction, any]): Uint8Array | string | undefined { - if (!value || isU8a(value) || isString(value)) { + static decodeStorageKey (value?: AnyU8a | StorageKey | StorageFunction | [StorageFunction, any]): Decoded { + if (value instanceof StorageKey) { + return { + key: value, + method: value.method, + section: value.section + }; + } else if (!value || isString(value) || isU8a(value)) { // let Bytes handle these inputs - return value; + return { + key: value + }; } else if (isFunction(value)) { - return value(); + return { + key: value(), + method: value.method, + section: value.section + }; } else if (Array.isArray(value)) { - const [fn, ...arg] = value; + const [fn, ...arg]: [StorageFunction, ...Array] = value as any; assert(isFunction(fn), 'Expected function input for key construction'); - return (fn as Function)(...arg); + return { + key: fn(...arg), + method: fn.method, + section: fn.section + }; } throw new Error(`Unable to convert input ${value} to StorageKey`); @@ -81,16 +109,30 @@ export default class StorageKey extends Bytes { } /** - * @description The metadata or `null` when not available + * @description The metadata or `undefined` when not available */ get meta (): MetaV4 | undefined { return this._meta; } + /** + * @description The key method or `undefined` when not specified + */ + get method (): string | undefined { + return this._method; + } + /** * @description The output type, `null` when not available */ get outputType (): string | undefined { return this._outputType; } + + /** + * @description The key section or `undefined` when not specified + */ + get section (): string | undefined { + return this._section; + } }