From 2f60ba0e1c75ec200bbacd67dd5a9139c535f8d2 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 2 Oct 2018 11:10:17 +0200 Subject: [PATCH] Add method name & prefix to StorageFunction (#182) * Add methods & prefix to StorageFunction * Match method/section to exposed names * Export method/section on extrinsic & jsonrpc * PR comment prefix -> section --- packages/api-codec/src/StorageKey.ts | 2 ++ packages/api-observable/src/Base.ts | 6 +++--- packages/api-provider/src/mock/state.ts | 4 ++-- packages/api/src/index.ts | 4 ++-- packages/api/src/methodSend.spec.js | 4 ++-- packages/type-extrinsics/src/types.d.ts | 4 +++- .../type-extrinsics/src/utils/createExtrinsic.ts | 9 +++++---- packages/type-jsonrpc/src/create/method.ts | 4 ++-- packages/type-jsonrpc/src/types.d.ts | 2 +- packages/type-storage/src/fromMetadata.ts | 4 ++-- packages/type-storage/src/substrate.ts | 5 +++-- .../type-storage/src/utils/createFunction.ts | 16 +++++++++++----- 12 files changed, 38 insertions(+), 26 deletions(-) diff --git a/packages/api-codec/src/StorageKey.ts b/packages/api-codec/src/StorageKey.ts index 3118226939..00afc2121d 100644 --- a/packages/api-codec/src/StorageKey.ts +++ b/packages/api-codec/src/StorageKey.ts @@ -14,6 +14,8 @@ import { StorageFunctionMetadata } from './Metadata'; export interface StorageFunction { (arg?: any): Uint8Array; meta: StorageFunctionMetadata; + method: string; + section: string; toJSON: () => any; } diff --git a/packages/api-observable/src/Base.ts b/packages/api-observable/src/Base.ts index 089c8c3ddd..e0bbea8f08 100644 --- a/packages/api-observable/src/Base.ts +++ b/packages/api-observable/src/Base.ts @@ -37,14 +37,14 @@ export default class ApiBase { return this.api.isConnected(); } - rawCall = ({ name, section }: Method, ...params: Array): Observable => { + rawCall = ({ method, section }: Method, ...params: Array): Observable => { const apiSection = this.api[section as keyof RxApiInterface] as RxApiInterface$Section; assert(apiSection, `Unable to find 'api.${section}'`); - const fn: RxApiInterface$Method = apiSection[name]; + const fn: RxApiInterface$Method = apiSection[method]; - assert(fn, `Unable to find 'api.${section}.${name}'`); + assert(fn, `Unable to find 'api.${section}.${method}'`); return fn.apply(null, params); } diff --git a/packages/api-provider/src/mock/state.ts b/packages/api-provider/src/mock/state.ts index e24b46877c..55518d556b 100644 --- a/packages/api-provider/src/mock/state.ts +++ b/packages/api-provider/src/mock/state.ts @@ -18,8 +18,8 @@ const SUBSCRIPTIONS: string[] = Array.prototype.concat.apply( .filter((method) => method.isSubscription ) - .map(({ name, section }) => - `${section}_${name}` + .map(({ method, section }) => + `${section}_${method}` ) ) ); diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 28c72aa8ed..2427e2ec23 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -55,12 +55,12 @@ export default class Api implements ApiInterface { * * Api.signature({ name: 'test_method', params: [ { name: 'dest', type: 'Address' } ], type: 'Address' }); // => test_method (dest: Address): Address */ - static signature ({ name, params, type }: Method): string { + static signature ({ method, params, type }: Method): string { const inputs = params.map(({ name, type }) => `${name}: ${type}` ).join(', '); - return `${name} (${inputs}): ${type}`; + return `${method} (${inputs}): ${type}`; } private createInterface ({ methods, name }: Section): ApiInterface$Section { diff --git a/packages/api/src/methodSend.spec.js b/packages/api/src/methodSend.spec.js index 928078a403..239b148b7d 100644 --- a/packages/api/src/methodSend.spec.js +++ b/packages/api/src/methodSend.spec.js @@ -12,14 +12,14 @@ describe('methodSend', () => { beforeEach(() => { methods = { blah: { - name: 'blah', + method: 'blah', params: [ { name: 'foo', type: 'Bytes' } ], type: 'Bytes' }, bleh: { - name: 'bleh', + method: 'bleh', params: [], type: 'Bytes' } diff --git a/packages/type-extrinsics/src/types.d.ts b/packages/type-extrinsics/src/types.d.ts index fa21a6ce83..22d62fcc23 100644 --- a/packages/type-extrinsics/src/types.d.ts +++ b/packages/type-extrinsics/src/types.d.ts @@ -5,7 +5,9 @@ import BN from 'bn.js'; export interface ExtrinsicFunction { - (...args: any[]): void + (...args: any[]): void, + method: string, + section: string } export interface ModuleExtrinsics { diff --git a/packages/type-extrinsics/src/utils/createExtrinsic.ts b/packages/type-extrinsics/src/utils/createExtrinsic.ts index 2ef0c07525..ebfc02e986 100644 --- a/packages/type-extrinsics/src/utils/createExtrinsic.ts +++ b/packages/type-extrinsics/src/utils/createExtrinsic.ts @@ -16,8 +16,8 @@ import { ExtrinsicFunction } from '../types'; * @param index - Index of the module section in the modules array. */ export default function createExtrinsic ( - prefix: string | Text, - name: string | Text, + section: string | Text, + method: string | Text, index: number, meta: FunctionMetadata ): ExtrinsicFunction { @@ -29,7 +29,7 @@ export default function createExtrinsic ( extrinsicFn = (...args: any[]): Extrinsic => { if (expectedArgs.length.valueOf() !== args.length) { - throw new Error(`Extrinsic ${prefix}.${name} expects ${expectedArgs.length.valueOf()} arguments, got ${args.length}.`); + throw new Error(`Extrinsic ${section}.${method} expects ${expectedArgs.length.valueOf()} arguments, got ${args.length}.`); } return new Extrinsic( @@ -42,10 +42,11 @@ export default function createExtrinsic ( }) ) ); - }; extrinsicFn.meta = meta; + extrinsicFn.method = method.toString(); + extrinsicFn.section = section.toString(); return extrinsicFn as ExtrinsicFunction; } diff --git a/packages/type-jsonrpc/src/create/method.ts b/packages/type-jsonrpc/src/create/method.ts index 72231b4516..36e36e703c 100644 --- a/packages/type-jsonrpc/src/create/method.ts +++ b/packages/type-jsonrpc/src/create/method.ts @@ -6,14 +6,14 @@ import { MethodOpt, Method } from '../types'; import isUndefined from '@polkadot/util/is/undefined'; -export default function createMethod (section: string, name: string, { description, params, type, isDeprecated = false, isHidden = false, isSigned = false, subscribe }: MethodOpt): Method { +export default function createMethod (section: string, method: string, { description, params, type, isDeprecated = false, isHidden = false, isSigned = false, subscribe }: MethodOpt): Method { return { description, isDeprecated, isHidden, isSigned, isSubscription: !isUndefined(subscribe), - name, + method, params, section, subscribe: subscribe || ['', ''], diff --git a/packages/type-jsonrpc/src/types.d.ts b/packages/type-jsonrpc/src/types.d.ts index c86caf7b22..cf2052f18e 100644 --- a/packages/type-jsonrpc/src/types.d.ts +++ b/packages/type-jsonrpc/src/types.d.ts @@ -27,7 +27,7 @@ export type Method = { isHidden: boolean, isSigned: boolean, isSubscription: boolean, - name: string, + method: string, params: Array, section: string, subscribe: [string, string], diff --git a/packages/type-storage/src/fromMetadata.ts b/packages/type-storage/src/fromMetadata.ts index 17cff7f838..fbbf99a800 100644 --- a/packages/type-storage/src/fromMetadata.ts +++ b/packages/type-storage/src/fromMetadata.ts @@ -28,9 +28,9 @@ export default function fromMetadata (storage: Storage, metadata: Metadata) { return result; } - const prefix = moduleMetadata.storage.prefix.toString(); + const prefix = moduleMetadata.storage.prefix; - result[stringLowerFirst(prefix)] = moduleMetadata.storage.functions.reduce((newModule, func) => { + result[stringLowerFirst(prefix.toString())] = moduleMetadata.storage.functions.reduce((newModule, func) => { // Lowercase the 'f' in storage.balances.freeBalance newModule[stringLowerFirst(func.name.toString())] = createFunction(prefix, func.name, func); diff --git a/packages/type-storage/src/substrate.ts b/packages/type-storage/src/substrate.ts index d322e5ebc3..8382ed1386 100644 --- a/packages/type-storage/src/substrate.ts +++ b/packages/type-storage/src/substrate.ts @@ -14,13 +14,14 @@ interface SubstrateMetadata { } // Small helper function to factorize code on this page. -const createRuntimeFunction = (name: string, functionMetadata: SubstrateMetadata) => +const createRuntimeFunction = (method: string, functionMetadata: SubstrateMetadata) => // TODO The expected 2nd argument is a StorageFunctionMetadata, but we // actually only need the fields `documentation` and `type` of it, so in // order to not input other fields (byteLength, fromJSON...) we lazily cast // as any. createFunction( - '', name, + new Text('Substrate'), + new Text(method), { documentation: new Vector(Text, [functionMetadata.documentation]), modifier: new StorageFunctionModifier().fromJSON(0), diff --git a/packages/type-storage/src/utils/createFunction.ts b/packages/type-storage/src/utils/createFunction.ts index 4d9c3dc9aa..4e62219181 100644 --- a/packages/type-storage/src/utils/createFunction.ts +++ b/packages/type-storage/src/utils/createFunction.ts @@ -6,6 +6,7 @@ import { createType } from '@polkadot/api-codec/codec'; import { StorageFunctionMetadata } from '@polkadot/api-codec/Metadata'; import { StorageFunction } from '@polkadot/api-codec/StorageKey'; import { Text } from '@polkadot/api-codec/index'; +import { stringLowerFirst } from '@polkadot/util/string'; import u8aConcat from '@polkadot/util/u8a/concat'; import u8aFromUtf8 from '@polkadot/util/u8a/fromUtf8'; import xxhash from '@polkadot/util-crypto/xxhash/asU8a'; @@ -25,16 +26,19 @@ export interface CreateItemOptions { * by us manually at compile time. */ export default function createFunction ( - prefix: string | Text, - name: string | Text, + section: Text, + method: Text, 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. '', + // the actual "prefix + name" below won't work even when we have an empty prefix.) For now, this is a safe + // assumption, but will break if the base substrate keys employ hashing as well if (options.isUnhashed) { storageFn = (): Uint8Array => - u8aFromUtf8(name.toString()); + u8aFromUtf8(method.toString()); } else { // TODO Find better type than any // Can only have zero or one argument: @@ -43,7 +47,7 @@ export default function createFunction ( storageFn = (arg?: any): Uint8Array => { if (!meta.type.isMap) { return xxhash( - u8aFromUtf8(`${prefix.toString()} ${name.toString()}`), + u8aFromUtf8(`${section.toString()} ${method.toString()}`), 128 ); } @@ -56,7 +60,7 @@ export default function createFunction ( return xxhash( u8aConcat( - u8aFromUtf8(`${prefix.toString()} ${name.toString()}`), + u8aFromUtf8(`${section.toString()} ${method.toString()}`), createType(type, arg).toU8a(true) ), 128 @@ -65,6 +69,8 @@ export default function createFunction ( } storageFn.meta = meta; + storageFn.method = stringLowerFirst(method.toString()); + storageFn.section = stringLowerFirst(section.toString()); storageFn.toJSON = (): any => meta.toJSON();