From edea20dad81f88e591a42e5ed35d482e09caaa13 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Fri, 12 Jul 2019 11:22:14 +0200 Subject: [PATCH] Export storage prefix on StorageEntry (#1106) --- .../fromMetadata/createFunction.spec.ts | 71 +++++++++++-------- .../storage/fromMetadata/createFunction.ts | 24 +++++-- .../src/storage/fromMetadata/index.ts | 12 +++- .../src/storage/fromMetadata/substrate.ts | 17 +++-- packages/types/src/primitive/StorageKey.ts | 5 +- 5 files changed, 81 insertions(+), 48 deletions(-) diff --git a/packages/api-metadata/src/storage/fromMetadata/createFunction.spec.ts b/packages/api-metadata/src/storage/fromMetadata/createFunction.spec.ts index ebfde0cec1..5eab6c81ed 100644 --- a/packages/api-metadata/src/storage/fromMetadata/createFunction.spec.ts +++ b/packages/api-metadata/src/storage/fromMetadata/createFunction.spec.ts @@ -11,11 +11,12 @@ import createFunction from './createFunction'; describe('createFunction', () => { it('should create timestamp.now correctly', () => { expect( - createFunction( - 'Timestamp', - 'Now', - { type: {} } as any - )() + createFunction({ + prefix: 'Timestamp', + section: 'timestamp', + method: 'Now', + meta: { 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 ); @@ -24,9 +25,12 @@ describe('createFunction', () => { it('allows overrides on key (keeping name)', () => { expect( createFunction( - 'Substrate', - 'authorityCount', - { type: {} } as any, + { + prefix: 'Substrate', + section: 'substrate', + method: 'authorityCount', + meta: { type: {} } as any + }, { key: ':auth:len', skipHashing: true @@ -40,9 +44,12 @@ describe('createFunction', () => { expect( createFunction( - 'Substrate', - 'authorityCount', - { type: {} } as any, + { + prefix: 'Substrate', + section: 'substrate', + method: 'authorityCount', + meta: { type: {} } as any + }, { key, skipHashing: true @@ -59,9 +66,11 @@ describe('createFunction', () => { describe('the created double map function', () => { let storageFn: StorageEntry; beforeAll(() => { - storageFn = createFunction( - 'GenericAsset', - 'FreeBalance', { + storageFn = createFunction({ + prefix: 'GenericAsset', + section: 'genericAsset', + method: 'FreeBalance', + meta: { name: 'metaName', type: { isDoubleMap: true, @@ -74,7 +83,7 @@ describe('createFunction', () => { } } } as any - ); + }); }); it('should return correct key', () => { @@ -90,22 +99,24 @@ describe('createFunction', () => { }); it('allows creates double map function with a Null type key', () => { - const storageFn = createFunction( - 'System', - 'EventTopics', - { - type: { - isDoubleMap: true, - asDoubleMap: { - hasher: new StorageHasher('Blake2_256'), - key1: new Text('Null'), - key2: new Text('Hash'), - value: new Text('Vec<(BlockNumber,EventIndex)>'), - key2Hasher: new Text('blake2_256') - } + const storageFn = createFunction({ + prefix: 'System', + section: 'system', + method: 'EventTopics', + meta: { + type: { + isDoubleMap: true, + asDoubleMap: { + hasher: new StorageHasher('Blake2_256'), + key1: new Text('Null'), + key2: new Text('Hash'), + value: new Text('Vec<(BlockNumber,EventIndex)>'), + key2Hasher: new Text('blake2_256') } - } as any - ); + } + } as any + }); + // the value of the Null type key does not effect the result expect(u8aToHex(storageFn(['any', [1, 2, 3]]))).toEqual(u8aToHex(storageFn([[1, 2, 3], [1, 2, 3]]))); // the value of the not Null type key does effect the result diff --git a/packages/api-metadata/src/storage/fromMetadata/createFunction.ts b/packages/api-metadata/src/storage/fromMetadata/createFunction.ts index 195f237377..228c6cbd9a 100644 --- a/packages/api-metadata/src/storage/fromMetadata/createFunction.ts +++ b/packages/api-metadata/src/storage/fromMetadata/createFunction.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 { createType, Bytes, Compact, StorageKey, Text, U8a } from '@polkadot/types'; +import { createType, Bytes, Compact, StorageKey, U8a } from '@polkadot/types'; import { PlainType, StorageEntryMetadata, StorageEntryModifier, StorageEntryType } from '@polkadot/types/Metadata/v6/Storage'; import { StorageEntry } from '@polkadot/types/primitive/StorageKey'; import { assert, isNull, isUndefined, stringLowerFirst, stringToU8a, u8aConcat } from '@polkadot/util'; @@ -14,6 +14,13 @@ export interface CreateItemOptions { skipHashing?: boolean; // We don't hash the keys defined in ./substrate.ts } +export interface CreateItemFn { + meta: StorageEntryMetadata; + method: string; + prefix: string; + section: string; +} + /** * From the schema of a function in the module's storage, generate the function * that will return the correct storage key. @@ -24,10 +31,10 @@ 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 | string, method: Text | string, meta: StorageEntryMetadata, options: CreateItemOptions = {}): StorageEntry { +export default function createFunction ({ meta, method, prefix, section }: CreateItemFn, options: CreateItemOptions = {}): StorageEntry { const stringKey = options.key ? options.key - : `${section.toString()} ${method.toString()}`; + : `${prefix} ${method}`; const rawKey = stringToU8a(stringKey); // Get the hashing function @@ -46,7 +53,7 @@ export default function createFunction (section: Text | string, method: Text | s // Can only have zero or one argument: // - storage.balances.freeBalance(address) // - storage.timestamp.blockPeriod() - const storageFn = (arg?: any): Uint8Array => { + const _storageFn = (arg?: any): Uint8Array => { let key = rawKey; if (meta.type.isDoubleMap) { @@ -78,6 +85,8 @@ export default function createFunction (section: Text | string, method: Text | s ); }; + const storageFn = _storageFn as StorageEntry; + if (meta.type.isMap && meta.type.asMap.isLinked) { const keyHash = new U8a(hasher(`head of ${stringKey}`)); const keyFn: any = () => keyHash; @@ -92,9 +101,10 @@ export default function createFunction (section: Text | string, method: Text | s } storageFn.meta = meta; - storageFn.method = stringLowerFirst(method.toString()); - storageFn.section = stringLowerFirst(section.toString()); + storageFn.method = stringLowerFirst(method); + storageFn.prefix = prefix; + storageFn.section = section; storageFn.toJSON = (): any => meta.toJSON(); - return storageFn as StorageEntry; + return storageFn; } diff --git a/packages/api-metadata/src/storage/fromMetadata/index.ts b/packages/api-metadata/src/storage/fromMetadata/index.ts index f9137363ee..5bb320fb33 100644 --- a/packages/api-metadata/src/storage/fromMetadata/index.ts +++ b/packages/api-metadata/src/storage/fromMetadata/index.ts @@ -22,10 +22,18 @@ export default function fromMetadata (metadata: Metadata): Storage { } const { name, prefix } = moduleMetadata; + const section = stringCamelCase(name.toString()); // For access, we change the index names, i.e. Balances.FreeBalance -> balances.freeBalance - result[stringCamelCase(name.toString())] = moduleMetadata.storage.unwrap().reduce((newModule, storageFnMeta) => { - newModule[stringLowerFirst(storageFnMeta.name.toString())] = createFunction(prefix, storageFnMeta.name, storageFnMeta); + result[section] = moduleMetadata.storage.unwrap().reduce((newModule, meta) => { + const method = meta.name.toString(); + + newModule[stringLowerFirst(method)] = createFunction({ + meta, + method, + prefix: prefix.toString(), + section + }); return newModule; }, {} as ModuleStorage); diff --git a/packages/api-metadata/src/storage/fromMetadata/substrate.ts b/packages/api-metadata/src/storage/fromMetadata/substrate.ts index f4a26ee87d..fef97d629c 100644 --- a/packages/api-metadata/src/storage/fromMetadata/substrate.ts +++ b/packages/api-metadata/src/storage/fromMetadata/substrate.ts @@ -16,14 +16,17 @@ interface SubstrateMetadata { // Small helper function to factorize code on this page. const createRuntimeFunction = (method: string, key: string, { documentation, type }: SubstrateMetadata): StorageEntry => createFunction( - new Text('Substrate'), - new Text(method), { - documentation: new Vector(Text, [documentation]), - modifier: new StorageEntryModifier(1), // default - type: new StorageEntryType(type, 0), - toJSON: (): any => key - } as StorageEntryMetadata, + meta: { + documentation: new Vector(Text, [documentation]), + modifier: new StorageEntryModifier(1), // default + type: new StorageEntryType(type, 0), + toJSON: (): any => key + } as StorageEntryMetadata, + method, + prefix: 'Substrate', + section: 'substrate' + }, { key, skipHashing: true diff --git a/packages/types/src/primitive/StorageKey.ts b/packages/types/src/primitive/StorageKey.ts index c5b0232fb4..899f80b9ad 100644 --- a/packages/types/src/primitive/StorageKey.ts +++ b/packages/types/src/primitive/StorageKey.ts @@ -13,15 +13,16 @@ export interface StorageEntry { headKey?: Uint8Array; meta: MetaV6; method: string; + prefix: string; section: string; toJSON: () => any; } -type Decoded = { +interface Decoded { key?: Uint8Array | string; method?: string; section?: string; -}; +} /** * @name StorageKey