From 448a729d704b13edaac9af2e017246a503bc0481 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Sat, 8 Dec 2018 15:31:54 +0100 Subject: [PATCH] Fix some Codeclimate smells (#450) * Fix some Codeclimate smells * Cleanup Metadata complexity * Cleanup uniqueTypes * Bump deps --- packages/rpc-core/package.json | 2 +- packages/rpc-provider/package.json | 6 +- packages/rpc-provider/src/ws/index.ts | 8 +- packages/type-extrinsics/package.json | 2 +- ...mMetadata.spec.js => fromMetadata.spec.ts} | 2 +- packages/type-extrinsics/src/fromMetadata.ts | 2 +- .../src/{index.spec.js => index.spec.ts} | 3 +- packages/type-extrinsics/src/static.ts | 2 +- .../src/utils/createUnchecked.ts | 2 +- packages/type-storage/package.json | 6 +- ...mMetadata.spec.js => fromMetadata.spec.ts} | 2 +- packages/type-storage/src/static.ts | 2 +- .../src/{storage.spec.js => storage.spec.ts} | 0 .../{substrate.spec.js => substrate.spec.ts} | 0 packages/type-storage/src/substrate.ts | 2 +- ...unction.spec.js => createFunction.spec.ts} | 4 +- .../type-storage/src/utils/createFunction.ts | 28 +- packages/types/package.json | 4 +- packages/types/src/Event.ts | 3 +- packages/types/src/EventRecord.spec.ts | 2 +- packages/types/src/Extrinsic.ts | 2 +- packages/types/src/Metadata.ts | 572 ------------------ packages/types/src/Metadata/Calls.ts | 62 ++ packages/types/src/Metadata/Events.ts | 86 +++ .../types/src/{ => Metadata}/Metadata.spec.ts | 10 +- packages/types/src/Metadata/Modules.ts | 290 +++++++++ packages/types/src/Metadata/index.ts | 161 +++++ .../latest.json} | 0 .../{Metadata.rpc.ts => Metadata/static.ts} | 0 packages/types/src/Method.ts | 18 +- packages/types/src/StorageKey.ts | 2 +- packages/types/src/Type.ts | 4 +- packages/types/src/codec/Struct.ts | 48 +- packages/types/src/codec/createType.ts | 18 +- .../types/src/scripts/MetadataJsonDecode.ts | 2 +- packages/types/src/scripts/MetadataMd.ts | 2 +- yarn.lock | 30 +- 37 files changed, 691 insertions(+), 698 deletions(-) rename packages/type-extrinsics/src/{fromMetadata.spec.js => fromMetadata.spec.ts} (95%) rename packages/type-extrinsics/src/{index.spec.js => index.spec.ts} (98%) rename packages/type-storage/src/{fromMetadata.spec.js => fromMetadata.spec.ts} (95%) rename packages/type-storage/src/{storage.spec.js => storage.spec.ts} (100%) rename packages/type-storage/src/{substrate.spec.js => substrate.spec.ts} (100%) rename packages/type-storage/src/utils/{createFunction.spec.js => createFunction.spec.ts} (93%) delete mode 100644 packages/types/src/Metadata.ts create mode 100644 packages/types/src/Metadata/Calls.ts create mode 100644 packages/types/src/Metadata/Events.ts rename packages/types/src/{ => Metadata}/Metadata.spec.ts (78%) create mode 100644 packages/types/src/Metadata/Modules.ts create mode 100644 packages/types/src/Metadata/index.ts rename packages/types/src/{Metadata.latest.json => Metadata/latest.json} (100%) rename packages/types/src/{Metadata.rpc.ts => Metadata/static.ts} (100%) diff --git a/packages/rpc-core/package.json b/packages/rpc-core/package.json index 649acc99fb..8d93422ec3 100644 --- a/packages/rpc-core/package.json +++ b/packages/rpc-core/package.json @@ -33,6 +33,6 @@ "@polkadot/jsonrpc": "^0.33.5", "@polkadot/rpc-provider": "^0.33.5", "@polkadot/types": "^0.33.5", - "@polkadot/util": "^0.33.9" + "@polkadot/util": "^0.33.11" } } diff --git a/packages/rpc-provider/package.json b/packages/rpc-provider/package.json index 3cd0bf44e2..024a60e6b7 100644 --- a/packages/rpc-provider/package.json +++ b/packages/rpc-provider/package.json @@ -30,10 +30,10 @@ "homepage": "https://github.com/polkadot-js/api/tree/master/packages/rpc-provider#readme", "dependencies": { "@babel/runtime": "^7.1.5", - "@polkadot/keyring": "^0.33.9", + "@polkadot/keyring": "^0.33.11", "@polkadot/storage": "^0.33.5", - "@polkadot/util": "^0.33.9", - "@polkadot/util-crypto": "^0.33.9", + "@polkadot/util": "^0.33.11", + "@polkadot/util-crypto": "^0.33.11", "@types/nock": "^9.3.0", "eventemitter3": "^3.1.0", "isomorphic-fetch": "^2.2.1", diff --git a/packages/rpc-provider/src/ws/index.ts b/packages/rpc-provider/src/ws/index.ts index dd92b04748..60ea41e9f1 100644 --- a/packages/rpc-provider/src/ws/index.ts +++ b/packages/rpc-provider/src/ws/index.ts @@ -149,11 +149,9 @@ export default class WsProvider implements WSProviderInterface { const json = this.coder.encodeJson(method, params); const id = this.coder.getId(); const callback = (error?: Error | null, result?: any) => { - if (error) { - reject(error); - } else { - resolve(result); - } + error + ? reject(error) + : resolve(result); }; l.debug(() => ['calling', method, params, json, !!subscription]); diff --git a/packages/type-extrinsics/package.json b/packages/type-extrinsics/package.json index 7cde0a3a69..9522b7c599 100644 --- a/packages/type-extrinsics/package.json +++ b/packages/type-extrinsics/package.json @@ -12,6 +12,6 @@ "dependencies": { "@babel/runtime": "^7.1.5", "@polkadot/types": "^0.33.5", - "@polkadot/util": "^0.33.9" + "@polkadot/util": "^0.33.11" } } diff --git a/packages/type-extrinsics/src/fromMetadata.spec.js b/packages/type-extrinsics/src/fromMetadata.spec.ts similarity index 95% rename from packages/type-extrinsics/src/fromMetadata.spec.js rename to packages/type-extrinsics/src/fromMetadata.spec.ts index 1654cc90bd..52b42ad136 100644 --- a/packages/type-extrinsics/src/fromMetadata.spec.js +++ b/packages/type-extrinsics/src/fromMetadata.spec.ts @@ -3,7 +3,7 @@ // of the Apache-2.0 license. See the LICENSE file for details. import Metadata from '@polkadot/types/Metadata'; -import json from '@polkadot/types/Metadata.rpc'; +import json from '@polkadot/types/Metadata/static'; import fromMetadata from './fromMetadata'; diff --git a/packages/type-extrinsics/src/fromMetadata.ts b/packages/type-extrinsics/src/fromMetadata.ts index f231b724fe..ef628592ce 100644 --- a/packages/type-extrinsics/src/fromMetadata.ts +++ b/packages/type-extrinsics/src/fromMetadata.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { RuntimeModuleMetadata } from '@polkadot/types/Metadata'; +import { RuntimeModuleMetadata } from '@polkadot/types/Metadata/Modules'; import { Extrinsics, ModuleExtrinsics } from '@polkadot/types/Method'; import { Metadata } from '@polkadot/types/index'; diff --git a/packages/type-extrinsics/src/index.spec.js b/packages/type-extrinsics/src/index.spec.ts similarity index 98% rename from packages/type-extrinsics/src/index.spec.js rename to packages/type-extrinsics/src/index.spec.ts index 0dcb336506..ced690b69d 100644 --- a/packages/type-extrinsics/src/index.spec.js +++ b/packages/type-extrinsics/src/index.spec.ts @@ -16,7 +16,8 @@ describe('extrinsics', () => { 10101 ).sign( keyring.nobody, - 1234 + 1234, + new Uint8Array() ).toU8a(true) ).toEqual( new Uint8Array([ diff --git a/packages/type-extrinsics/src/static.ts b/packages/type-extrinsics/src/static.ts index 2b2c93874e..26d8677347 100644 --- a/packages/type-extrinsics/src/static.ts +++ b/packages/type-extrinsics/src/static.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import metadataRpc from '@polkadot/types/Metadata.rpc'; +import metadataRpc from '@polkadot/types/Metadata/static'; import Metadata from '@polkadot/types/Metadata'; import fromMetadata from './fromMetadata'; diff --git a/packages/type-extrinsics/src/utils/createUnchecked.ts b/packages/type-extrinsics/src/utils/createUnchecked.ts index 7f9381f7d0..5251afc055 100644 --- a/packages/type-extrinsics/src/utils/createUnchecked.ts +++ b/packages/type-extrinsics/src/utils/createUnchecked.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { FunctionMetadata } from '@polkadot/types/Metadata'; +import { FunctionMetadata } from '@polkadot/types/Metadata/Modules'; import { ExtrinsicFunction } from '@polkadot/types/Method'; import { Extrinsic, Method } from '@polkadot/types/index'; import { assert } from '@polkadot/util'; diff --git a/packages/type-storage/package.json b/packages/type-storage/package.json index e6d3a6c487..5977afd02d 100644 --- a/packages/type-storage/package.json +++ b/packages/type-storage/package.json @@ -30,9 +30,9 @@ "homepage": "https://github.com/polkadot-js/api/tree/master/packages/type-storage#readme", "dependencies": { "@babel/runtime": "^7.1.5", - "@polkadot/keyring": "^0.33.9", + "@polkadot/keyring": "^0.33.11", "@polkadot/types": "^0.33.5", - "@polkadot/util": "^0.33.9", - "@polkadot/util-crypto": "^0.33.9" + "@polkadot/util": "^0.33.11", + "@polkadot/util-crypto": "^0.33.11" } } diff --git a/packages/type-storage/src/fromMetadata.spec.js b/packages/type-storage/src/fromMetadata.spec.ts similarity index 95% rename from packages/type-storage/src/fromMetadata.spec.js rename to packages/type-storage/src/fromMetadata.spec.ts index e4517c08bf..085f883902 100644 --- a/packages/type-storage/src/fromMetadata.spec.js +++ b/packages/type-storage/src/fromMetadata.spec.ts @@ -3,7 +3,7 @@ // of the Apache-2.0 license. See the LICENSE file for details. import Metadata from '@polkadot/types/Metadata'; -import json from '@polkadot/types/Metadata.rpc'; +import json from '@polkadot/types/Metadata/static'; import fromMetadata from './fromMetadata'; diff --git a/packages/type-storage/src/static.ts b/packages/type-storage/src/static.ts index 71c385808a..447fdb428e 100644 --- a/packages/type-storage/src/static.ts +++ b/packages/type-storage/src/static.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import metadataRpc from '@polkadot/types/Metadata.rpc'; +import metadataRpc from '@polkadot/types/Metadata/static'; import Metadata from '@polkadot/types/Metadata'; import fromMetadata from './fromMetadata'; diff --git a/packages/type-storage/src/storage.spec.js b/packages/type-storage/src/storage.spec.ts similarity index 100% rename from packages/type-storage/src/storage.spec.js rename to packages/type-storage/src/storage.spec.ts diff --git a/packages/type-storage/src/substrate.spec.js b/packages/type-storage/src/substrate.spec.ts similarity index 100% rename from packages/type-storage/src/substrate.spec.js rename to packages/type-storage/src/substrate.spec.ts diff --git a/packages/type-storage/src/substrate.ts b/packages/type-storage/src/substrate.ts index 73041688d6..4965281fbe 100644 --- a/packages/type-storage/src/substrate.ts +++ b/packages/type-storage/src/substrate.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { StorageFunctionMetadata, StorageFunctionModifier, StorageFunctionType } from '@polkadot/types/Metadata'; +import { StorageFunctionMetadata, StorageFunctionModifier, StorageFunctionType } from '@polkadot/types/Metadata/Modules'; import { StorageFunction } from '@polkadot/types/StorageKey'; import Text from '@polkadot/types/Text'; import Vector from '@polkadot/types/codec/Vector'; diff --git a/packages/type-storage/src/utils/createFunction.spec.js b/packages/type-storage/src/utils/createFunction.spec.ts similarity index 93% rename from packages/type-storage/src/utils/createFunction.spec.js rename to packages/type-storage/src/utils/createFunction.spec.ts index 6d263c8481..f3ee7e4333 100644 --- a/packages/type-storage/src/utils/createFunction.spec.js +++ b/packages/type-storage/src/utils/createFunction.spec.ts @@ -10,7 +10,7 @@ describe('createFunction', () => { createFunction( 'Timestamp', 'Now', - { type: {} } + { type: {} } as any )() ).toEqual( Uint8Array.from([64, 14, 73, 68, 207, 217, 141, 111, 76, 195, 116, 209, 111, 90, 78, 63, 156]) // Length-prefixed @@ -22,7 +22,7 @@ describe('createFunction', () => { createFunction( 'Substrate', ':auth:len', - { type: {} }, + { type: {} } as any, { isUnhashed: true, method: 'authorityCount' diff --git a/packages/type-storage/src/utils/createFunction.ts b/packages/type-storage/src/utils/createFunction.ts index a642aa60a1..9036e51f75 100644 --- a/packages/type-storage/src/utils/createFunction.ts +++ b/packages/type-storage/src/utils/createFunction.ts @@ -4,7 +4,7 @@ import Compact from '@polkadot/types/codec/Compact'; import { createType } from '@polkadot/types/codec'; -import { StorageFunctionMetadata } from '@polkadot/types/Metadata'; +import { StorageFunctionMetadata } from '@polkadot/types/Metadata/Modules'; import { StorageFunction } from '@polkadot/types/StorageKey'; import { Text } from '@polkadot/types/index'; import { assert, isNull, isUndefined, stringLowerFirst, stringToU8a, u8aConcat } from '@polkadot/util'; @@ -25,12 +25,7 @@ export interface CreateItemOptions { * are not known at runtime (from state_getMetadata), they need to be supplied * by us manually at compile time. */ -export default function createFunction ( - section: Text, - method: Text, - meta: StorageFunctionMetadata, - options: CreateItemOptions = {} -): StorageFunction { +export default function createFunction (section: Text | string, method: Text | string, meta: StorageFunctionMetadata, options: CreateItemOptions = {}): StorageFunction { let storageFn: any; // NOTE Here we assume everything in the 'Substrate' prefix is unhashed. (Despite not passing empty, i.e. '', @@ -45,28 +40,22 @@ export default function createFunction ( // - storage.balances.freeBalance(address) // - storage.timestamp.blockPeriod() storageFn = (arg?: any): Uint8Array => { + const key = stringToU8a(`${section.toString()} ${method.toString()}`); + if (!meta.type.isMap) { return Compact.addLengthPrefix( - xxhashAsU8a( - stringToU8a(`${section.toString()} ${method.toString()}`), - 128 - ) + xxhashAsU8a(key, 128) ); } assert(!isUndefined(arg) && !isNull(arg), `${meta.name} expects one argument`); const type = meta.type.asMap.key.toString(); // Argument type, as string + const param = createType(type, arg).toU8a(true); // StorageKey is a Bytes, so is length-prefixed return Compact.addLengthPrefix( - xxhashAsU8a( - u8aConcat( - stringToU8a(`${section.toString()} ${method.toString()}`), - createType(type, arg).toU8a(true) - ), - 128 - ) + xxhashAsU8a(u8aConcat(key, param), 128) ); }; } @@ -74,8 +63,7 @@ export default function createFunction ( storageFn.meta = meta; storageFn.method = stringLowerFirst((options.method || method).toString()); storageFn.section = stringLowerFirst(section.toString()); - storageFn.toJSON = (): any => - meta.toJSON(); + storageFn.toJSON = (): any => meta.toJSON(); return storageFn as StorageFunction; } diff --git a/packages/types/package.json b/packages/types/package.json index 8667ef1991..a5b102fdd0 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -30,7 +30,7 @@ "homepage": "https://github.com/polkadot-js/api/tree/master/packages/types#readme", "dependencies": { "@babel/runtime": "^7.1.5", - "@polkadot/keyring": "^0.33.9", - "@polkadot/util": "^0.33.9" + "@polkadot/keyring": "^0.33.11", + "@polkadot/util": "^0.33.11" } } diff --git a/packages/types/src/Event.ts b/packages/types/src/Event.ts index 4e59b26424..dbe1153da9 100644 --- a/packages/types/src/Event.ts +++ b/packages/types/src/Event.ts @@ -10,7 +10,8 @@ import Struct from './codec/Struct'; import Tuple from './codec/Tuple'; import U8aFixed from './codec/U8aFixed'; import { TypeDef, getTypeClass, getTypeDef } from './codec/createType'; -import Metadata, { EventMetadata } from './Metadata'; +import Metadata from './Metadata'; +import { EventMetadata } from './Metadata/Events'; const EventTypes: { [index: string]: Constructor } = {}; diff --git a/packages/types/src/EventRecord.spec.ts b/packages/types/src/EventRecord.spec.ts index e2f7226f37..29bf92f1e3 100644 --- a/packages/types/src/EventRecord.spec.ts +++ b/packages/types/src/EventRecord.spec.ts @@ -10,7 +10,7 @@ import AccountId from './AccountId'; import Event from './Event'; import EventRecord from './EventRecord'; import Metadata from './Metadata'; -import metadataRpc from './/Metadata.rpc'; +import metadataRpc from './Metadata/static'; describe('EventRecord', () => { beforeEach(() => { diff --git a/packages/types/src/Extrinsic.ts b/packages/types/src/Extrinsic.ts index 5129afa606..0bcfe62083 100644 --- a/packages/types/src/Extrinsic.ts +++ b/packages/types/src/Extrinsic.ts @@ -13,7 +13,7 @@ import Struct from './codec/Struct'; import Address from './Address'; import ExtrinsicSignature from './ExtrinsicSignature'; import Hash from './Hash'; -import { FunctionMetadata } from './Metadata'; +import { FunctionMetadata } from './Metadata/Modules'; import Method from './Method'; type ExtrinsicValue = { diff --git a/packages/types/src/Metadata.ts b/packages/types/src/Metadata.ts deleted file mode 100644 index 859db7e32e..0000000000 --- a/packages/types/src/Metadata.ts +++ /dev/null @@ -1,572 +0,0 @@ -// Copyright 2017-2018 @polkadot/types authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import { AnyNumber } from './types'; - -import { assert, hexToU8a, isHex, isU8a, isUndefined } from '@polkadot/util'; - -import { getTypeDef, TypeDef, TypeDefInfo } from './codec/createType'; -import Compact from './codec/Compact'; -import Enum from './codec/Enum'; -import EnumType from './codec/EnumType'; -import Option from './codec/Option'; -import Struct from './codec/Struct'; -import Tuple from './codec/Tuple'; -import Vector from './codec/Vector'; -import Text from './Text'; -import Type from './Type'; -import U16 from './U16'; -import * as allTypes from './index'; - -// Decodes the runtime metadata as passed through from the `state_getMetadata` call. This -// file is probably best understood from the bottom-up, i.e. start reading right at the -// end and work up. (Just so we don't use before definition) - -// Quick and dirty flatten (.flat() not available) -function flattenUniq (list: Array): Array { - const flat = list.reduce((result, entry) => { - return result.concat( - Array.isArray(entry) - ? flattenUniq(entry) - : entry - ); - }, []); - - return [...new Set(flat)] - .filter((value: any) => value) - .sort(); -} - -export class OuterDispatchCall extends Struct { - constructor (value?: any) { - super({ - name: Text, - prefix: Text, - index: U16 - }, value); - } - - /** - * @description The [[U16]] index for the call - */ - get index (): U16 { - return this.get('index') as U16; - } - - /** - * @description The name for the call - */ - get name (): Text { - return this.get('name') as Text; - } - - /** - * @description The call prefix (or section) - */ - get prefix (): Text { - return this.get('prefix') as Text; - } -} - -export class OuterDispatchMetadata extends Struct { - constructor (value?: any) { - super({ - name: Text, - calls: Vector.with(OuterDispatchCall) - }, value); - } - - /** - * @description The [[OuterDispathCall]] wrapped - */ - get calls (): Vector { - return this.get('calls') as Vector; - } - - /** - * @description The name for the dispatch - */ - get name (): Text { - return this.get('name') as Text; - } -} - -export class EventMetadata extends Struct { - constructor (value?: any) { - super({ - name: Text, - arguments: Vector.with(Type), - documentation: Vector.with(Text) - }, value); - } - - /** - * @description The arguments of [[Type]] - */ - get arguments (): Vector { - return this.get('arguments') as Vector; - } - - /** - * @description The [[Text]] documentation - */ - get documentation (): Vector { - return this.get('documentation') as Vector; - } - - /** - * @description The name for the event - */ - get name (): Text { - return this.get('name') as Text; - } -} - -export class OuterEventMetadataEvent extends Tuple { - constructor (value?: any) { - super([ - Text, - Vector.with(EventMetadata) - ], value); - } - - /** - * @description The [[EventMetadata]] - */ - get events (): Vector { - return this[1] as Vector; - } - - /** - * @description The name of the section - */ - get name (): Text { - return this[0] as Text; - } -} - -export class OuterEventMetadata extends Struct { - constructor (value?: any) { - super({ - name: Text, - events: Vector.with(OuterEventMetadataEvent) - }, value); - } - - /** - * @description The [[OuterEventMetadataEvent]] - */ - get events (): Vector { - return this.get('events') as Vector; - } - - /** - * @description The name of the event - */ - get name (): Text { - return this.get('name') as Text; - } -} - -export class FunctionArgumentMetadata extends Struct { - constructor (value?: any) { - super({ - name: Text, - type: Type - }, value); - } - - /** - * @description The argument name - */ - get name (): Text { - return this.get('name') as Text; - } - - /** - * @description The [[Type]] - */ - get type (): Type { - return this.get('type') as Type; - } -} - -export class FunctionMetadata extends Struct { - constructor (value?: any) { - super({ - id: U16, - name: Text, - arguments: Vector.with(FunctionArgumentMetadata), - documentation: Vector.with(Text) - }, value); - } - - /** - * @description The [[FunctionArgumentMetadata]] for arguments - */ - get arguments (): Vector { - return this.get('arguments') as Vector; - } - - /** - * @description The [[Text]] documentation - */ - get documentation (): Vector { - return this.get('documentation') as Vector; - } - - /** - * @description The `[sectionIndex, methodIndex]` call id - */ - get id (): U16 { - return this.get('id') as U16; - } - - /** - * @description The call name - */ - get name (): Text { - return this.get('name') as Text; - } -} - -export class CallMetadata extends Struct { - constructor (value?: any) { - super({ - name: Text, - functions: Vector.with(FunctionMetadata) - }, value); - } - - /** - * @description The functions available as [[FunctionMetadata]] - */ - get functions (): Vector { - return this.get('functions') as Vector; - } - - /** - * @description The section name - */ - get name (): Text { - return this.get('name') as Text; - } -} - -export class ModuleMetadata extends Struct { - constructor (value?: any) { - super({ - name: Text, - call: CallMetadata - }, value); - } - - /** - * @description The calls as [[CallMetadata]] - */ - get call (): CallMetadata { - return this.get('call') as CallMetadata; - } - - /** - * @description The name - */ - get name (): Text { - return this.get('name') as Text; - } -} - -export class StorageFunctionModifier extends Enum { - constructor (value?: any) { - super(['None', 'Default', 'Required'], value); - } -} - -export class StorageFunctionType$Map extends Struct { - constructor (value?: any) { - super({ - key: Type, - value: Type - }, value); - } - - /** - * @description The mapped key as [[Type]] - */ - get key (): Type { - return this.get('key') as Type; - } - - /** - * @description The mapped value as [[Type]] - */ - get value (): Type { - return this.get('value') as Type; - } -} - -export class StorageFunctionType extends EnumType { - constructor (value?: any, index?: number) { - super([ - Type, - StorageFunctionType$Map - ], value, index); - } - - /** - * @description `true` if the storage entry is a map - */ - get isMap (): boolean { - return this.toNumber() === 1; - } - - /** - * @description The value as a mapped value - */ - get asMap (): StorageFunctionType$Map { - return this.value as StorageFunctionType$Map; - } - - /** - * @description The value as a [[Type]] value - */ - get asType (): Type { - return this.value as Type; - } - - /** - * @description Returns the string representation of the value - */ - toString (): string { - return this.isMap - ? this.asMap.value.toString() - : this.asType.toString(); - } -} - -type StorageFunctionMetadataValue = { - name?: string | Text, - modifier?: StorageFunctionModifier | AnyNumber, - type?: StorageFunctionType, - documentation?: Vector | Array -}; - -export class StorageFunctionMetadata extends Struct { - constructor (value?: StorageFunctionMetadataValue) { - super({ - name: Text, - modifier: StorageFunctionModifier, - type: StorageFunctionType, - documentation: Vector.with(Text) - }, value); - } - - /** - * @description The [[Text]] documentation - */ - get documentation (): Vector { - return this.get('documentation') as Vector; - } - - /** - * @description The key name - */ - get name (): Text { - return this.get('name') as Text; - } - - /** - * @description The modifier - */ - get modifier (): StorageFunctionModifier { - return this.get('modifier') as StorageFunctionModifier; - } - - /** - * @description The [[StorageFunctionType]] - */ - get type (): StorageFunctionType { - return this.get('type') as StorageFunctionType; - } -} - -export class StorageMetadata extends Struct { - constructor (value?: any) { - super({ - prefix: Text, - functions: Vector.with(StorageFunctionMetadata) - }, value); - } - - /** - * @description The [[StorageFunctionMetadata]] for the section - */ - get functions (): Vector { - return this.get('functions') as Vector; - } - - /** - * @description The section prefix - */ - get prefix (): Text { - return this.get('prefix') as Text; - } -} - -export class RuntimeModuleMetadata extends Struct { - constructor (value?: any) { - super({ - prefix: Text, - module: ModuleMetadata, - storage: Option.with(StorageMetadata) - }, value); - } - - /** - * @description The [[ModuleMetadata]] - */ - get module (): ModuleMetadata { - return this.get('module') as ModuleMetadata; - } - - /** - * @description The prefix - */ - get prefix (): Text { - return this.get('prefix') as Text; - } - - /** - * @description The optional [[StorageMetadata]] - */ - get storage (): Option { - return this.get('storage') as Option; - } -} - -/** - * @name Metadata - * @description - * The runtime metadata as a decoded structure - */ -export default class Metadata extends Struct { - constructor (value?: any) { - super({ - outerEvent: OuterEventMetadata, - modules: Vector.with(RuntimeModuleMetadata), - outerDispatch: OuterDispatchMetadata - }, Metadata.decodeMetadata(value)); - } - - static decodeMetadata (value: string | Uint8Array | object): object | Uint8Array { - if (isHex(value)) { - // We receive this as an hex in the JSON output from the Node. - // Convert to u8a and use the U8a version to do the actual parsing. - return Metadata.decodeMetadata(hexToU8a(value)); - } else if (isU8a(value)) { - // HACK 13 Oct 2018 - For current running BBQ nodes, Metadata is not properly - // encoded, it does not have a length prefix. For latest substrate master, it - // is properly encoded. Here we pull the prefix, check it agianst the length - - // if matches, then we have the length, otherwise we assume it is an older node - // and use the whole buffer - const [offset, length] = Compact.decodeU8a(value); - - return value.length === (offset + length.toNumber()) - ? value.subarray(offset) - : value; - } - - // Decode as normal struct - return value; - } - - /** - * @description Wrapped [[OuterDispatchCall]] - */ - get calls (): Vector { - return (this.get('outerDispatch') as OuterDispatchMetadata).calls; - } - - /** - * @description Wrapped [[OuterEventMetadataEvent]] - */ - get events (): Vector { - return (this.get('outerEvent') as OuterEventMetadata).events; - } - - /** - * @description Wrapped [[RuntimeModuleMetadata]] - */ - get modules (): Vector { - return this.get('modules') as Vector; - } - - /** - * @description Helper to retrieve a list of all type that are found, sorted and de-deuplicated - */ - getUniqTypes (): Array { - const events = this.events.map((module) => - module.events.map((event) => - event.arguments.map((argument) => - argument.toString() - ) - ) - ); - - const storages = this.modules.map((module) => - module.storage.isSome - ? module.storage.unwrap().functions.map((fn) => - fn.type.isMap - ? [fn.type.asMap.key.toString(), fn.type.asMap.value.toString()] - : [fn.type.asType.toString()] - ) - : [] - ); - - const args = this.modules.map((module) => - module.module.call.functions.map((fn) => - fn.arguments.map((argument) => - argument.type.toString() - ) - ) - ); - - const types = flattenUniq([events, storages, args]); - - this.validateTypes(types); - - return types; - } - - private validateTypes (types: Array): void { - const extractTypes = (types: Array): Array => { - return types.map((type) => { - const decoded = getTypeDef(type); - - switch (decoded.info) { - case TypeDefInfo.Plain: - return decoded.type; - - case TypeDefInfo.Compact: - case TypeDefInfo.Vector: - return extractTypes([(decoded.sub as TypeDef).type]); - - case TypeDefInfo.Tuple: - return extractTypes( - (decoded.sub as Array).map((sub) => sub.type) - ); - - default: - throw new Error('Unreachable'); - } - }); - }; - - const missing = flattenUniq(extractTypes(types)).filter((type) => - isUndefined((allTypes as any)[type]) - ); - - assert(missing.length === 0, `Unknown types found, no types for ${missing}`); - } -} diff --git a/packages/types/src/Metadata/Calls.ts b/packages/types/src/Metadata/Calls.ts new file mode 100644 index 0000000000..1d7c0a8062 --- /dev/null +++ b/packages/types/src/Metadata/Calls.ts @@ -0,0 +1,62 @@ +// Copyright 2017-2018 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import Struct from '../codec/Struct'; +import Vector from '../codec/Vector'; +import Text from '../Text'; +import U16 from '../U16'; + +export class OuterDispatchCall extends Struct { + constructor (value?: any) { + super({ + name: Text, + prefix: Text, + index: U16 + }, value); + } + + /** + * @description The [[U16]] index for the call + */ + get index (): U16 { + return this.get('index') as U16; + } + + /** + * @description The name for the call + */ + get name (): Text { + return this.get('name') as Text; + } + + /** + * @description The call prefix (or section) + */ + get prefix (): Text { + return this.get('prefix') as Text; + } +} + +export class OuterDispatchMetadata extends Struct { + constructor (value?: any) { + super({ + name: Text, + calls: Vector.with(OuterDispatchCall) + }, value); + } + + /** + * @description The [[OuterDispathCall]] wrapped + */ + get calls (): Vector { + return this.get('calls') as Vector; + } + + /** + * @description The name for the dispatch + */ + get name (): Text { + return this.get('name') as Text; + } +} diff --git a/packages/types/src/Metadata/Events.ts b/packages/types/src/Metadata/Events.ts new file mode 100644 index 0000000000..71a3dd6a7d --- /dev/null +++ b/packages/types/src/Metadata/Events.ts @@ -0,0 +1,86 @@ +// Copyright 2017-2018 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import Struct from '../codec/Struct'; +import Tuple from '../codec/Tuple'; +import Vector from '../codec/Vector'; +import Text from '../Text'; +import Type from '../Type'; + +export class EventMetadata extends Struct { + constructor (value?: any) { + super({ + name: Text, + arguments: Vector.with(Type), + documentation: Vector.with(Text) + }, value); + } + + /** + * @description The arguments of [[Type]] + */ + get arguments (): Vector { + return this.get('arguments') as Vector; + } + + /** + * @description The [[Text]] documentation + */ + get documentation (): Vector { + return this.get('documentation') as Vector; + } + + /** + * @description The name for the event + */ + get name (): Text { + return this.get('name') as Text; + } +} + +export class OuterEventMetadataEvent extends Tuple { + constructor (value?: any) { + super([ + Text, + Vector.with(EventMetadata) + ], value); + } + + /** + * @description The [[EventMetadata]] + */ + get events (): Vector { + return this[1] as Vector; + } + + /** + * @description The name of the section + */ + get name (): Text { + return this[0] as Text; + } +} + +export class OuterEventMetadata extends Struct { + constructor (value?: any) { + super({ + name: Text, + events: Vector.with(OuterEventMetadataEvent) + }, value); + } + + /** + * @description The [[OuterEventMetadataEvent]] + */ + get events (): Vector { + return this.get('events') as Vector; + } + + /** + * @description The name of the event + */ + get name (): Text { + return this.get('name') as Text; + } +} diff --git a/packages/types/src/Metadata.spec.ts b/packages/types/src/Metadata/Metadata.spec.ts similarity index 78% rename from packages/types/src/Metadata.spec.ts rename to packages/types/src/Metadata/Metadata.spec.ts index 6b0d87ed49..8537d58cf1 100644 --- a/packages/types/src/Metadata.spec.ts +++ b/packages/types/src/Metadata/Metadata.spec.ts @@ -2,11 +2,11 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import bbqBirch from './json/Metadata.bbq.json'; -import compacted from './json/Metadata.latest.json'; -import Metadata from './Metadata'; -import rpcdata from './Metadata.rpc'; -import latestParsed from './Metadata.latest.json'; +import bbqBirch from '../json/Metadata.bbq.json'; +import compacted from '../json/Metadata.latest.json'; +import Metadata from './index'; +import rpcdata from './static'; +import latestParsed from './latest.json'; describe('Metadata', () => { it('decodes properly', () => { diff --git a/packages/types/src/Metadata/Modules.ts b/packages/types/src/Metadata/Modules.ts new file mode 100644 index 0000000000..09617719f5 --- /dev/null +++ b/packages/types/src/Metadata/Modules.ts @@ -0,0 +1,290 @@ +// Copyright 2017-2018 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { AnyNumber } from '../types'; + +import Enum from '../codec/Enum'; +import EnumType from '../codec/EnumType'; +import Option from '../codec/Option'; +import Struct from '../codec/Struct'; +import Vector from '../codec/Vector'; +import Text from '../Text'; +import Type from '../Type'; +import U16 from '../U16'; + +export class FunctionArgumentMetadata extends Struct { + constructor (value?: any) { + super({ + name: Text, + type: Type + }, value); + } + + /** + * @description The argument name + */ + get name (): Text { + return this.get('name') as Text; + } + + /** + * @description The [[Type]] + */ + get type (): Type { + return this.get('type') as Type; + } +} + +export class FunctionMetadata extends Struct { + constructor (value?: any) { + super({ + id: U16, + name: Text, + arguments: Vector.with(FunctionArgumentMetadata), + documentation: Vector.with(Text) + }, value); + } + + /** + * @description The [[FunctionArgumentMetadata]] for arguments + */ + get arguments (): Vector { + return this.get('arguments') as Vector; + } + + /** + * @description The [[Text]] documentation + */ + get documentation (): Vector { + return this.get('documentation') as Vector; + } + + /** + * @description The `[sectionIndex, methodIndex]` call id + */ + get id (): U16 { + return this.get('id') as U16; + } + + /** + * @description The call name + */ + get name (): Text { + return this.get('name') as Text; + } +} + +export class CallMetadata extends Struct { + constructor (value?: any) { + super({ + name: Text, + functions: Vector.with(FunctionMetadata) + }, value); + } + + /** + * @description The functions available as [[FunctionMetadata]] + */ + get functions (): Vector { + return this.get('functions') as Vector; + } + + /** + * @description The section name + */ + get name (): Text { + return this.get('name') as Text; + } +} + +export class ModuleMetadata extends Struct { + constructor (value?: any) { + super({ + name: Text, + call: CallMetadata + }, value); + } + + /** + * @description The calls as [[CallMetadata]] + */ + get call (): CallMetadata { + return this.get('call') as CallMetadata; + } + + /** + * @description The name + */ + get name (): Text { + return this.get('name') as Text; + } +} + +export class StorageFunctionModifier extends Enum { + constructor (value?: any) { + super(['None', 'Default', 'Required'], value); + } +} + +export class StorageFunctionType$Map extends Struct { + constructor (value?: any) { + super({ + key: Type, + value: Type + }, value); + } + + /** + * @description The mapped key as [[Type]] + */ + get key (): Type { + return this.get('key') as Type; + } + + /** + * @description The mapped value as [[Type]] + */ + get value (): Type { + return this.get('value') as Type; + } +} + +export class StorageFunctionType extends EnumType { + constructor (value?: any, index?: number) { + super([ + Type, + StorageFunctionType$Map + ], value, index); + } + + /** + * @description `true` if the storage entry is a map + */ + get isMap (): boolean { + return this.toNumber() === 1; + } + + /** + * @description The value as a mapped value + */ + get asMap (): StorageFunctionType$Map { + return this.value as StorageFunctionType$Map; + } + + /** + * @description The value as a [[Type]] value + */ + get asType (): Type { + return this.value as Type; + } + + /** + * @description Returns the string representation of the value + */ + toString (): string { + return this.isMap + ? this.asMap.value.toString() + : this.asType.toString(); + } +} + +type StorageFunctionMetadataValue = { + name?: string | Text, + modifier?: StorageFunctionModifier | AnyNumber, + type?: StorageFunctionType, + documentation?: Vector | Array +}; + +export class StorageFunctionMetadata extends Struct { + constructor (value?: StorageFunctionMetadataValue) { + super({ + name: Text, + modifier: StorageFunctionModifier, + type: StorageFunctionType, + documentation: Vector.with(Text) + }, value); + } + + /** + * @description The [[Text]] documentation + */ + get documentation (): Vector { + return this.get('documentation') as Vector; + } + + /** + * @description The key name + */ + get name (): Text { + return this.get('name') as Text; + } + + /** + * @description The modifier + */ + get modifier (): StorageFunctionModifier { + return this.get('modifier') as StorageFunctionModifier; + } + + /** + * @description The [[StorageFunctionType]] + */ + get type (): StorageFunctionType { + return this.get('type') as StorageFunctionType; + } +} + +export class StorageMetadata extends Struct { + constructor (value?: any) { + super({ + prefix: Text, + functions: Vector.with(StorageFunctionMetadata) + }, value); + } + + /** + * @description The [[StorageFunctionMetadata]] for the section + */ + get functions (): Vector { + return this.get('functions') as Vector; + } + + /** + * @description The section prefix + */ + get prefix (): Text { + return this.get('prefix') as Text; + } +} + +export class RuntimeModuleMetadata extends Struct { + constructor (value?: any) { + super({ + prefix: Text, + module: ModuleMetadata, + storage: Option.with(StorageMetadata) + }, value); + } + + /** + * @description The [[ModuleMetadata]] + */ + get module (): ModuleMetadata { + return this.get('module') as ModuleMetadata; + } + + /** + * @description The prefix + */ + get prefix (): Text { + return this.get('prefix') as Text; + } + + /** + * @description The optional [[StorageMetadata]] + */ + get storage (): Option { + return this.get('storage') as Option; + } +} diff --git a/packages/types/src/Metadata/index.ts b/packages/types/src/Metadata/index.ts new file mode 100644 index 0000000000..8aa192a23f --- /dev/null +++ b/packages/types/src/Metadata/index.ts @@ -0,0 +1,161 @@ +// Copyright 2017-2018 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { assert, hexToU8a, isHex, isU8a, isUndefined } from '@polkadot/util'; + +import { getTypeDef, TypeDef, TypeDefInfo } from '../codec/createType'; +import Compact from '../codec/Compact'; +import Struct from '../codec/Struct'; +import Vector from '../codec/Vector'; +import { OuterDispatchMetadata, OuterDispatchCall } from './Calls'; +import { OuterEventMetadata, OuterEventMetadataEvent } from './Events'; +import { RuntimeModuleMetadata } from './Modules'; + +// Decodes the runtime metadata as passed through from the `state_getMetadata` call. This +// file is probably best understood from the bottom-up, i.e. start reading right at the +// end and work up. (Just so we don't use before definition) + +// Quick and dirty flatten (.flat() not available) +function flattenUniq (list: Array): Array { + const flat = list.reduce((result, entry) => { + return result.concat( + Array.isArray(entry) + ? flattenUniq(entry) + : entry + ); + }, []); + + return [...new Set(flat)] + .filter((value: any) => value) + .sort(); +} + +/** + * @name Metadata + * @description + * The runtime metadata as a decoded structure + */ +export default class Metadata extends Struct { + constructor (value?: any) { + super({ + outerEvent: OuterEventMetadata, + modules: Vector.with(RuntimeModuleMetadata), + outerDispatch: OuterDispatchMetadata + }, Metadata.decodeMetadata(value)); + } + + static decodeMetadata (value: string | Uint8Array | object): object | Uint8Array { + if (isHex(value)) { + // We receive this as an hex in the JSON output from the Node. + // Convert to u8a and use the U8a version to do the actual parsing. + return Metadata.decodeMetadata(hexToU8a(value)); + } else if (isU8a(value)) { + // HACK 13 Oct 2018 - For current running BBQ nodes, Metadata is not properly + // encoded, it does not have a length prefix. For latest substrate master, it + // is properly encoded. Here we pull the prefix, check it agianst the length - + // if matches, then we have the length, otherwise we assume it is an older node + // and use the whole buffer + const [offset, length] = Compact.decodeU8a(value); + + return value.length === (offset + length.toNumber()) + ? value.subarray(offset) + : value; + } + + // Decode as normal struct + return value; + } + + /** + * @description Wrapped [[OuterDispatchCall]] + */ + get calls (): Vector { + return (this.get('outerDispatch') as OuterDispatchMetadata).calls; + } + + /** + * @description Wrapped [[OuterEventMetadataEvent]] + */ + get events (): Vector { + return (this.get('outerEvent') as OuterEventMetadata).events; + } + + /** + * @description Wrapped [[RuntimeModuleMetadata]] + */ + get modules (): Vector { + return this.get('modules') as Vector; + } + + private get argNames () { + return this.modules.map((module) => + module.module.call.functions.map((fn) => + fn.arguments.map((argument) => argument.type.toString()) + ) + ); + } + + private get eventNames () { + return this.events.map((module) => + module.events.map((event) => + event.arguments.map((argument) => argument.toString()) + ) + ); + } + + private get storageNames () { + return this.modules.map((module) => + module.storage.isSome + ? module.storage.unwrap().functions.map((fn) => + fn.type.isMap + ? [fn.type.asMap.key.toString(), fn.type.asMap.value.toString()] + : [fn.type.asType.toString()] + ) + : [] + ); + } + + /** + * @description Helper to retrieve a list of all type that are found, sorted and de-deuplicated + */ + getUniqTypes (): Array { + const types = flattenUniq([this.argNames, this.eventNames, this.storageNames]); + + this.validateTypes(types); + + return types; + } + + private validateTypes (types: Array): void { + const extractTypes = (types: Array): Array => { + return types.map((type) => { + const decoded = getTypeDef(type); + + switch (decoded.info) { + case TypeDefInfo.Plain: + return decoded.type; + + case TypeDefInfo.Compact: + case TypeDefInfo.Vector: + return extractTypes([(decoded.sub as TypeDef).type]); + + case TypeDefInfo.Tuple: + return extractTypes( + (decoded.sub as Array).map((sub) => sub.type) + ); + + default: + throw new Error('Unreachable'); + } + }); + }; + + const allTypes = require('../index'); + const missing = flattenUniq(extractTypes(types)).filter((type) => + isUndefined(allTypes[type]) + ); + + assert(missing.length === 0, `Unknown types found, no types for ${missing}`); + } +} diff --git a/packages/types/src/Metadata.latest.json b/packages/types/src/Metadata/latest.json similarity index 100% rename from packages/types/src/Metadata.latest.json rename to packages/types/src/Metadata/latest.json diff --git a/packages/types/src/Metadata.rpc.ts b/packages/types/src/Metadata/static.ts similarity index 100% rename from packages/types/src/Metadata.rpc.ts rename to packages/types/src/Metadata/static.ts diff --git a/packages/types/src/Method.ts b/packages/types/src/Method.ts index cf65515b3c..5413f2d4b7 100644 --- a/packages/types/src/Method.ts +++ b/packages/types/src/Method.ts @@ -10,7 +10,7 @@ import { getTypeDef, getTypeClass } from './codec/createType'; import Struct from './codec/Struct'; import U8aFixed from './codec/U8aFixed'; import Extrinsic from './Extrinsic'; -import { FunctionMetadata, FunctionArgumentMetadata } from './Metadata'; +import { FunctionMetadata, FunctionArgumentMetadata } from './Metadata/Modules'; const FN_UNKNOWN = { method: 'unknown', @@ -101,20 +101,13 @@ export default class Method extends Struct { // Find metadata with callIndex const meta = _meta || Method.findFunction(callIndex).meta; - // Get Struct definition of the arguments - const argsDef = Method.getArgsDef(meta); - return { args: value.subarray(2), - argsDef, + argsDef: Method.getArgsDef(meta), callIndex, meta }; - } else if ( - isObject(value) && - value.callIndex && - value.args - ) { + } else if (isObject(value) && value.callIndex && value.args) { // destructure value, we only pass args/methodsIndex out const { args, callIndex } = value; @@ -126,12 +119,9 @@ export default class Method extends Struct { // Find metadata with callIndex const meta = _meta || Method.findFunction(lookupIndex).meta; - // Get Struct definition of the arguments - const argsDef = Method.getArgsDef(meta); - return { args, - argsDef, + argsDef: Method.getArgsDef(meta), meta, callIndex }; diff --git a/packages/types/src/StorageKey.ts b/packages/types/src/StorageKey.ts index 410298c12c..b1d0e20336 100644 --- a/packages/types/src/StorageKey.ts +++ b/packages/types/src/StorageKey.ts @@ -7,7 +7,7 @@ import { AnyU8a } from './types'; import { isFunction } from '@polkadot/util'; import Bytes from './Bytes'; -import { StorageFunctionMetadata } from './Metadata'; +import { StorageFunctionMetadata } from './Metadata/Modules'; export interface StorageFunction { (arg?: any): Uint8Array; diff --git a/packages/types/src/Type.ts b/packages/types/src/Type.ts index ce220fb746..cf51e9ea17 100644 --- a/packages/types/src/Type.ts +++ b/packages/types/src/Type.ts @@ -90,9 +90,9 @@ export default class Type extends Text { if (value[index] === '>') { if (!depth) { return index; - } else { - depth--; } + + depth--; } else if (value[index] === '<') { depth++; } diff --git a/packages/types/src/codec/Struct.ts b/packages/types/src/codec/Struct.ts index 8dab9e30ab..fb427af156 100644 --- a/packages/types/src/codec/Struct.ts +++ b/packages/types/src/codec/Struct.ts @@ -78,36 +78,30 @@ export default class Struct< // used to track at which index we are currently parsing in that array. let currentIndex = 0; - return (Object - .keys(Types) as Array) - .reduce((raw: T, key, index) => { - // The key in the JSON can be snake_case (or other cases), but in our - // Types, result or any other maps, it's camelCase - const jsonKey = (jsonMap.get(key as any) && !value[key]) ? jsonMap.get(key as any) : key; + return Object.keys(Types).reduce((raw: T, key: keyof S, index) => { + // The key in the JSON can be snake_case (or other cases), but in our + // Types, result or any other maps, it's camelCase + const jsonKey = (jsonMap.get(key as any) && !value[key]) ? jsonMap.get(key as any) : key; - if (isU8a(value)) { - raw[key] = new Types[key]( - value.subarray( - currentIndex - ) - ); + if (isU8a(value)) { + raw[key] = new Types[key](value.subarray(currentIndex)); - // Move the currentIndex forward - currentIndex += raw[key].encodedLength; - } else if (Array.isArray(value)) { - raw[key] = value[index] instanceof Types[key] - ? value[index] - : new Types[key](value[index]); - } else if (isObject(value)) { - raw[key] = value[jsonKey as string] instanceof Types[key] - ? value[jsonKey as string] - : new Types[key](value[jsonKey as string]); - } else { - throw new Error(`Struct: cannot decode type "${Types[key].name}" with value "${JSON.stringify(value)}".`); - } + // Move the currentIndex forward + currentIndex += raw[key].encodedLength; + } else if (Array.isArray(value)) { + raw[key] = value[index] instanceof Types[key] + ? value[index] + : new Types[key](value[index]); + } else if (isObject(value)) { + raw[key] = value[jsonKey as string] instanceof Types[key] + ? value[jsonKey as string] + : new Types[key](value[jsonKey as string]); + } else { + throw new Error(`Struct: cannot decode type ${Types[key].name} with value ${JSON.stringify(value)}`); + } - return raw; - }, {} as T); + return raw; + }, {} as T); } static with< diff --git a/packages/types/src/codec/createType.ts b/packages/types/src/codec/createType.ts index 1370dbcb87..c3508a4a32 100644 --- a/packages/types/src/codec/createType.ts +++ b/packages/types/src/codec/createType.ts @@ -117,28 +117,22 @@ export function getTypeDef (_type: Text | string): TypeDef { // Returns the type Class for construction export function getTypeClass (value: TypeDef): Constructor { if (value.info === TypeDefInfo.Tuple) { - if (!Array.isArray(value.sub)) { - throw new Error(`Expected nested subtypes for Tuple`); - } + assert(Array.isArray(value.sub), 'Expected nested subtypes for Tuple'); return Tuple.with( - value.sub.map(getTypeClass) + (value.sub as Array).map(getTypeClass) ); } else if (value.info === TypeDefInfo.Compact) { - if (!value.sub || Array.isArray(value.sub)) { - throw new Error(`Expected subtype for Compact`); - } + assert(value.sub && !Array.isArray(value.sub), 'Expected subtype for Compact'); return Compact.with( - getTypeClass(value.sub) as Constructor + getTypeClass(value.sub as TypeDef) as Constructor ); } else if (value.info === TypeDefInfo.Vector) { - if (!value.sub || Array.isArray(value.sub)) { - throw new Error(`Expected subtype for Vector`); - } + assert(value.sub && !Array.isArray(value.sub), 'Expected subtype for Vector'); return Vector.with( - getTypeClass(value.sub) + getTypeClass(value.sub as TypeDef) ); } diff --git a/packages/types/src/scripts/MetadataJsonDecode.ts b/packages/types/src/scripts/MetadataJsonDecode.ts index 587c5ac4d1..012b11ce7c 100644 --- a/packages/types/src/scripts/MetadataJsonDecode.ts +++ b/packages/types/src/scripts/MetadataJsonDecode.ts @@ -5,7 +5,7 @@ const fs = require('fs'); import Metadata from '../Metadata'; -import rpcdata from '../Metadata.rpc'; +import rpcdata from '../Metadata/static'; function metadataStringifyAsJson () { const decoded = new Metadata(rpcdata); diff --git a/packages/types/src/scripts/MetadataMd.ts b/packages/types/src/scripts/MetadataMd.ts index 25102b5ca7..6067a9b08a 100644 --- a/packages/types/src/scripts/MetadataMd.ts +++ b/packages/types/src/scripts/MetadataMd.ts @@ -7,7 +7,7 @@ import { stringCamelCase, stringLowerFirst } from '@polkadot/util'; import interfaces from '../../../type-jsonrpc/src'; import Metadata from '../Metadata'; -import rpcdata from '../Metadata.rpc'; +import rpcdata from '../Metadata/static'; import Method from '../Method'; const ANCHOR_TOP = ``; diff --git a/yarn.lock b/yarn.lock index 3a653dd505..84bcba4a46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1349,14 +1349,14 @@ typedoc-plugin-no-inherit "^1.0.2" typescript "^3.2.1" -"@polkadot/keyring@^0.33.9": - version "0.33.9" - resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-0.33.9.tgz#d192ec400a0ba6f0c4825bf2e6a9f3e180c68a0f" - integrity sha512-nXyXBMdG8SIwyUmOCCaCdvJAbcftzq6ElWHgZFa84VxFYwviWMbRicPSkrvZr+KTrn7av86h7bJsnUbi/j3phQ== +"@polkadot/keyring@^0.33.11": + version "0.33.11" + resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-0.33.11.tgz#79c6174e9b27147ff69a2375f39a2462b2d581c7" + integrity sha512-AP98VfGbcdXo9Bp650klh0l734kcmrYM1kzDs+mpGmpwMQtjRrEuitWwAvb84Sl6Snq6qMOadLXVAxU8PtOtgA== dependencies: "@babel/runtime" "^7.1.5" - "@polkadot/util" "^0.33.9" - "@polkadot/util-crypto" "^0.33.9" + "@polkadot/util" "^0.33.11" + "@polkadot/util-crypto" "^0.33.11" "@types/bs58" "^3.0.30" bs58 "^4.0.1" @@ -1365,13 +1365,13 @@ resolved "https://registry.yarnpkg.com/@polkadot/ts/-/ts-0.1.41.tgz#647b44b038f94a7acf76633b25cb72df897872fc" integrity sha512-/vYpjqKU+QKHNAlFdLgFZAAr54wxQMgIuszZ5BxaayUoq7ukDlvCPhUGQ3fNoyBSEaL7uTCZ/5SVRc363IehoA== -"@polkadot/util-crypto@^0.33.9": - version "0.33.9" - resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-0.33.9.tgz#6f465604b1c5947d1a06fd4c84c845913d45a016" - integrity sha512-6beNVnvsuYd3V9LPU6yNSxjC6rzsXIWVQn4IzLUsQk7S8NEIgVSTl7xVP9OnRX6VzKSjs2DhqUe8p0ZqBygjNg== +"@polkadot/util-crypto@^0.33.11": + version "0.33.11" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-0.33.11.tgz#25b30e69a4da1f6a42d3680536130ca4f9480db6" + integrity sha512-jL1TzlqHGKRu9SN80e0K/0H1ZZ6fRTv96s2f6s27GrGt6+tcPEVcmaQK5vjEDMw2pT9+b5TPwcx2gLwh56GLVg== dependencies: "@babel/runtime" "^7.1.5" - "@polkadot/util" "^0.33.9" + "@polkadot/util" "^0.33.11" "@types/bip39" "^2.4.1" bip39 "^2.5.0" blakejs "^1.1.0" @@ -1379,10 +1379,10 @@ tweetnacl "^1.0.0" xxhashjs "^0.2.2" -"@polkadot/util@^0.33.9": - version "0.33.9" - resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-0.33.9.tgz#65c745cad3a9583fb6a68f734f10d12318611e89" - integrity sha512-F4doCg/l1TfrM0iNxBaxmwtbaNKcKOdKEX99Uj37So2Rwxg/XVenXa0sctA+4Vk3nauQ6kJRTUPLqiBdKAdmsg== +"@polkadot/util@^0.33.11": + version "0.33.11" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-0.33.11.tgz#3e2433e556ee14c685ebc5920c229cb76e0b985b" + integrity sha512-Tn+WYU+RxOaJhrUsPjBOk77MDKb6bsqVkcs5ysSc1HUDIRqZwGABnX1rhP2/DipS91hj8DQ2HZE18S7mCBv1bQ== dependencies: "@babel/runtime" "^7.1.5" "@types/bn.js" "^4.11.3"