Rework asLatest update (#2802)

* Revert "[CI Skip] release/beta 2.4.2-10"

This reverts commit 5cb1c2d33a.

* Revert "Use asLatest in metadata extraction (#2800)"

This reverts commit 600666de1c.

* Bumps

* Expansion

* Flatten

* Metadata class imports

* Cleanup Decorate exports

* Move Metadata to top-level

* Swap logger on ABI

* Adjust imports

* Cleanups

* Updates
This commit is contained in:
Jaco Greeff
2020-10-29 11:59:37 +01:00
committed by GitHub
parent 5cb1c2d33a
commit ea3ee428d8
81 changed files with 217 additions and 234 deletions
+4 -2
View File
@@ -5,10 +5,12 @@ import { AnyJson, Codec, CodecArg } from '@polkadot/types/types';
import { ChainProperties, ContractConstructorSpec, ContractEventSpec, ContractMessageSpec, ContractMessageParamSpec, ContractProject } from '@polkadot/types/interfaces';
import { AbiConstructor, AbiEvent, AbiMessage, AbiParam, DecodedEvent, DecodedMessage } from './types';
import { assert, compactAddLength, compactStripLength, isNumber, isObject, isString, stringCamelCase, u8aConcat, u8aToHex } from '@polkadot/util';
import { assert, compactAddLength, compactStripLength, isNumber, isObject, isString, logger, stringCamelCase, u8aConcat, u8aToHex } from '@polkadot/util';
import MetaRegistry from './MetaRegistry';
const l = logger('Abi');
function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string | number): T {
const message = isNumber(messageOrId)
? list[messageOrId]
@@ -115,7 +117,7 @@ export default class Abi {
type: this.registry.getMetaTypeDef(arg.type)
};
} catch (error) {
console.error(`Error expanding argument ${index} in ${JSON.stringify(spec)}`);
l.error(`Error expanding argument ${index} in ${JSON.stringify(spec)}`);
throw error;
}
+4 -4
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Constants } from '@polkadot/metadata/Decorated/types';
import { Constants, DecoratedMeta } from '@polkadot/metadata/decorate/types';
import { RpcInterface } from '@polkadot/rpc-core/types';
import { Call, Hash, RuntimeVersion } from '@polkadot/types/interfaces';
import { AnyFunction, CallFunction, Codec, CodecArg as Arg, InterfaceTypes, Registry, RegistryTypes } from '@polkadot/types/types';
@@ -13,7 +13,7 @@ import { BehaviorSubject, Observable, combineLatest, of } from 'rxjs';
import { map, switchMap, take, tap, toArray } from 'rxjs/operators';
import decorateDerive, { ExactDerive } from '@polkadot/api-derive';
import { memo } from '@polkadot/api-derive/util';
import DecoratedMeta from '@polkadot/metadata/Decorated';
import { expandMetadata } from '@polkadot/metadata';
import RpcCore from '@polkadot/rpc-core';
import { WsProvider } from '@polkadot/rpc-provider';
import { Metadata, Option, Raw, Text, TypeRegistry, u64 } from '@polkadot/types';
@@ -171,8 +171,8 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
return this._rpcCore.provider.hasSubscriptions;
}
public injectMetadata (metadata: Metadata, fromEmpty?: boolean): void {
const decoratedMeta = new DecoratedMeta(metadata);
public injectMetadata (metadata: Metadata, fromEmpty?: boolean, registry?: Registry): void {
const decoratedMeta = expandMetadata(registry || this.#registry, metadata);
if (fromEmpty || !this._extrinsics) {
this._extrinsics = this._decorateExtrinsics(decoratedMeta, this._decorateMethod);
+2 -2
View File
@@ -204,7 +204,7 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
this._rx.runtimeVersion = version;
// update the default registry version
const thisRegistry = this.#registries.find(({ registry }) => registry === metadata.registry);
const thisRegistry = this.#registries.find(({ isDefault }) => isDefault);
assert(thisRegistry, 'Initialization error, cannot find the default registry');
@@ -216,7 +216,7 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
// clear the registry types to ensure that we override correctly
this._initRegistry(thisRegistry.registry.init(), this._runtimeChain as Text, version);
this.injectMetadata(metadata, false);
this.injectMetadata(metadata, false, thisRegistry.registry);
return true;
})
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Constants } from '@polkadot/metadata/Decorated/types';
import { Constants } from '@polkadot/metadata/decorate/types';
import { Metadata } from '@polkadot/types';
import { Registry } from '@polkadot/types/types';
+4 -5
View File
@@ -1,11 +1,10 @@
// Copyright 2017-2019 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Storage } from '@polkadot/metadata/Decorated/types';
import { Storage } from '@polkadot/metadata/decorate/types';
import storageFromMeta from '@polkadot/metadata/Decorated/storage/fromMetadata';
import Metadata from '@polkadot/metadata/Metadata';
import metaStatic from '@polkadot/metadata/Metadata/static';
import Metadata, { storageFromMeta } from '@polkadot/metadata';
import metaStatic from '@polkadot/metadata/static';
import { TypeRegistry } from '@polkadot/types';
import { extractStorageArgs } from './validate';
@@ -17,7 +16,7 @@ describe('extractStorageArgs', (): void => {
beforeEach((): void => {
const metadata = new Metadata(registry, metaStatic);
storage = storageFromMeta(registry, metadata.asLatest);
storage = storageFromMeta(registry, metadata);
});
it('validates no-arg plain', (): void => {
@@ -1,36 +0,0 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ModulesWithCalls } from '@polkadot/types/types';
import { Constants, Storage } from './types';
import { assert } from '@polkadot/util';
import Metadata from '../Metadata';
import constantsFromMeta from './consts/fromMetadata';
import extrinsicsFromMeta from './extrinsics/fromMetadata';
import storageFromMeta from './storage/fromMetadata';
/**
* This class represents a decorated wrapper over the [[Metadata]]. The
* [[Metadata]] type is a Codec type returned by the node, and `Decorated`
* composes it and populates the `.query`, `.tx` and `.consts` sections.
*/
export default class Decorated {
public readonly consts: Constants;
public readonly query: Storage;
public readonly tx: ModulesWithCalls;
constructor (value: Metadata) {
assert(value instanceof Metadata, 'You need to pass a valid Metadata instance to Decorated');
const latest = value.asLatest;
// decoration
this.tx = extrinsicsFromMeta(value.registry, latest);
this.query = storageFromMeta(value.registry, latest);
this.consts = constantsFromMeta(value.registry, latest);
}
}
@@ -1,3 +0,0 @@
# @polkadot/metadata/consts
A base interface to the parameter types
@@ -1,3 +0,0 @@
# @polkadot/metadata/extrinsics
Base extrinsic definitions & codecs
-6
View File
@@ -1,6 +0,0 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import Decorated from './Decorated';
export default Decorated;
@@ -1,3 +0,0 @@
# @polkadot/metadata/storage
A base interface to the storage layer
-6
View File
@@ -1,6 +0,0 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import Metadata from './Metadata';
export default Metadata;
@@ -1,13 +1,13 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Constants } from '../../types';
import { Constants } from '../types';
import { Metadata, TypeRegistry } from '@polkadot/types';
import rpcMetadata from '../../../Metadata/static';
import rpcMetadataV10 from '../../../Metadata/v10/static';
import fromMetadata from '../fromMetadata';
import rpcMetadata from '../../static';
import rpcMetadataV10 from '../../v10/static';
import fromMetadata from './fromMetadata';
function init (meta: string): [Constants, TypeRegistry] {
const registry = new TypeRegistry();
@@ -15,7 +15,7 @@ function init (meta: string): [Constants, TypeRegistry] {
registry.setMetadata(metadata);
return [fromMetadata(registry, metadata.asLatest), registry];
return [fromMetadata(registry, metadata), registry];
}
describe('fromMetadata', (): void => {
@@ -28,7 +28,7 @@ describe('fromMetadata', (): void => {
});
// removed from session
it('correctly handles bytes', (): void => {
it('correctly handles bytes (V10)', (): void => {
const [consts] = init(rpcMetadataV10);
// 0x34 removes as the length prefix removed
@@ -1,16 +1,17 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { MetadataLatest } from '@polkadot/types/interfaces';
import { Registry } from '@polkadot/types/types';
import { Constants, ConstantCodec, ModuleConstants } from '../../types';
import { Constants, ConstantCodec, ModuleConstants } from '../types';
import { createTypeUnsafe } from '@polkadot/types/create';
import { hexToU8a, stringCamelCase } from '@polkadot/util';
import Metadata from '../..';
/** @internal */
export default function fromMetadata (registry: Registry, { modules }: MetadataLatest): Constants {
return modules.reduce((result: Constants, moduleMetadata): Constants => {
export default function fromMetadata (registry: Registry, metadata: Metadata): Constants {
return metadata.asLatest.modules.reduce((result: Constants, moduleMetadata): Constants => {
if (moduleMetadata.constants.isEmpty) {
return result;
}
@@ -7,16 +7,12 @@ import { AnyJson, CallFunction, Registry, RegistryMetadataCall } from '@polkadot
import { assert, stringCamelCase } from '@polkadot/util';
/** @internal */
export default function createDescriptor (registry: Registry, section: string, sectionIndex: number, methodIndex: number, callMetadata: RegistryMetadataCall): CallFunction {
const callIndex = new Uint8Array([sectionIndex, methodIndex]);
export default function createDescriptor (registry: Registry, section: string, callIndex: Uint8Array, callMetadata: RegistryMetadataCall): CallFunction {
const expectedArgs = callMetadata.args;
const funcName = stringCamelCase(callMetadata.name);
const extrinsicFn = (...args: any[]): Call => {
assert(
expectedArgs.length.valueOf() === args.length,
`Extrinsic ${section}.${funcName} expects ${expectedArgs.length.valueOf()} arguments, got ${args.length}.`
);
assert(expectedArgs.length === args.length, `Extrinsic ${section}.${funcName} expects ${expectedArgs.length.valueOf()} arguments, got ${args.length}.`);
return registry.createType('Call', {
args,
@@ -3,8 +3,8 @@
import { Metadata, TypeRegistry } from '@polkadot/types';
import json from '../../../Metadata/static';
import fromMetadata from '.';
import json from '../../static';
import fromMetadata from './fromMetadata';
// Use the pre-generated metadata
const registry = new TypeRegistry();
@@ -12,7 +12,7 @@ const metadata = new Metadata(registry, json);
registry.setMetadata(metadata);
const newExtrinsics = fromMetadata(registry, metadata.asLatest);
const newExtrinsics = fromMetadata(registry, metadata);
describe('fromMetadata', (): void => {
it('should throw if an incorrect number of args is supplied', (): void => {
@@ -1,15 +1,16 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Calls, ModulesWithCalls, Registry, RegistryMetadataLatest, RegistryMetadataModule } from '@polkadot/types/types';
import { Calls, ModulesWithCalls, Registry, RegistryMetadata, RegistryMetadataModule } from '@polkadot/types/types';
import { stringCamelCase } from '@polkadot/util';
import extrinsics from '../';
import extrinsics from './';
import createUnchecked from './createUnchecked';
/** @internal */
export default function fromMetadata (registry: Registry, { modules }: RegistryMetadataLatest): ModulesWithCalls {
export default function fromMetadata (registry: Registry, metadata: RegistryMetadata): ModulesWithCalls {
const modules = metadata.asLatest.modules;
const isIndexed = modules.some(({ index }) => !index.eqn(255));
return modules
@@ -23,7 +24,7 @@ export default function fromMetadata (registry: Registry, { modules }: RegistryM
result[section] = calls.unwrap().reduce((newModule: Calls, callMetadata, methodIndex): Calls => {
const method = stringCamelCase(callMetadata.name);
newModule[method] = createUnchecked(registry, section, sectionIndex, methodIndex, callMetadata);
newModule[method] = createUnchecked(registry, section, new Uint8Array([sectionIndex, methodIndex]), callMetadata);
return newModule;
}, {});
@@ -5,7 +5,7 @@ import BN from 'bn.js';
import testingPairs from '@polkadot/keyring/testingPairs';
import { Metadata, TypeRegistry } from '@polkadot/types';
import metadataStatic from '../../Metadata/static';
import metadataStatic from '../../static';
import fromMetadata from './fromMetadata';
const keyring = testingPairs({ type: 'ed25519' }, false);
@@ -14,7 +14,7 @@ const metadata = new Metadata(registry, metadataStatic);
registry.setMetadata(metadata);
const extrinsics = fromMetadata(registry, metadata.asLatest);
const extrinsics = fromMetadata(registry, metadata);
describe('extrinsics', (): void => {
it('encodes an actual transfer (actual data)', (): void => {
@@ -4,22 +4,22 @@
import { TypeRegistry } from '@polkadot/types/create';
import { u8aToHex } from '@polkadot/util';
import Metadata from '../Metadata';
import json from '../Metadata/static';
import Decorated from './Decorated';
import Metadata from '..';
import json from '../static';
import { constantsFromMeta, extrinsicsFromMeta, storageFromMeta } from './';
const registry = new TypeRegistry();
const metadata = new Metadata(registry, json);
registry.setMetadata(metadata);
const decorated = new Decorated(metadata);
describe('Decorated', () => {
it('should correctly get Alice\'s nonce storage key (u8a)', (): void => {
const query = storageFromMeta(registry, metadata);
expect(
u8aToHex(
decorated.query.system.account('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY')
query.system.account('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY')
)
).toEqual(
'0x410126aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9de1e86a9a8c739864cf3cc5ec2bea59fd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
@@ -27,8 +27,10 @@ describe('Decorated', () => {
});
it('should return properly-encoded transactions', (): void => {
const tx = extrinsicsFromMeta(registry, metadata);
expect(
registry.createType('Extrinsic', decorated.tx.timestamp.set([10101])).toU8a()
registry.createType('Extrinsic', tx.timestamp.set([10101])).toU8a()
).toEqual(
new Uint8Array([
// length (encoded)
@@ -44,7 +46,9 @@ describe('Decorated', () => {
});
it('should return constants with the correct type and value', (): void => {
expect(decorated.consts.democracy.cooloffPeriod).toBeInstanceOf(registry.createClass('BlockNumber'));
expect(decorated.consts.democracy.cooloffPeriod.toHex()).toEqual('0x000c4e00');
const consts = constantsFromMeta(registry, metadata);
expect(consts.democracy.cooloffPeriod).toBeInstanceOf(registry.createClass('BlockNumber'));
expect(consts.democracy.cooloffPeriod.toHex()).toEqual('0x000c4e00');
});
});
+27
View File
@@ -0,0 +1,27 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Registry } from '@polkadot/types/types';
import { DecoratedMeta } from './types';
import { assert } from '@polkadot/util';
import Metadata from '..';
import constantsFromMeta from './consts/fromMetadata';
import extrinsicsFromMeta from './extrinsics/fromMetadata';
import storageFromMeta from './storage/fromMetadata';
/**
* Expands the metadata by decoration int consts, query and tx sections
*/
export default function expandMetadata (registry: Registry, value: Metadata): DecoratedMeta {
assert(value instanceof Metadata, 'You need to pass a valid Metadata instance to Decorated');
return {
consts: constantsFromMeta(registry, value),
query: storageFromMeta(registry, value),
tx: extrinsicsFromMeta(registry, value)
};
}
export { constantsFromMeta, extrinsicsFromMeta, storageFromMeta };
@@ -27,7 +27,7 @@ describe('createFunction', (): void => {
method: 'NextKeys',
prefix: 'Session',
section: 'session'
}, {});
}, { metaVersion: 9 });
expect(
u8aToHex(
@@ -15,6 +15,7 @@ import getHasher, { HasherFunction } from './getHasher';
export interface CreateItemOptions {
key?: string;
metaVersion: number;
skipHashing?: boolean; // We don't hash the keys defined in ./substrate.ts
}
@@ -30,19 +31,11 @@ interface IterFn {
meta: StorageEntryMetadataLatest;
}
type CreateArgType = boolean | string | number | null | BN | Uint8Array | Codec;
type CreateArgType = boolean | string | number | null | BN | BigInt | Uint8Array | Codec;
const EMPTY_U8A = new Uint8Array([]);
const NULL_HASHER = (value: Uint8Array): Uint8Array => value;
// with the prefix, method & options, create both the string & raw keys
/** @internal */
function expandKey ({ method, prefix }: CreateItemFn, options: CreateItemOptions): string {
return options.key
? options.key
: `${prefix} ${method}`;
}
// get the hashers, the base (and in the case of DoubleMap), the second key
/** @internal */
function getHashers ({ meta: { type } }: CreateItemFn): [HasherFunction, HasherFunction?] {
@@ -67,7 +60,7 @@ function createPrefixedKey ({ method, prefix }: CreateItemFn): Uint8Array {
// create a key for a DoubleMap type
/** @internal */
function createKeyDoubleMap (registry: Registry, itemFn: CreateItemFn, stringKey: string, args: [CreateArgType, CreateArgType], [hasher1, hasher2]: [HasherFunction, HasherFunction?]): Uint8Array {
function createKeyDoubleMap (registry: Registry, itemFn: CreateItemFn, args: [CreateArgType, CreateArgType], [hasher1, hasher2]: [HasherFunction, HasherFunction?]): Uint8Array {
const { meta: { name, type } } = itemFn;
// since we are passing an almost-unknown through, trust, but verify
@@ -91,7 +84,7 @@ function createKeyDoubleMap (registry: Registry, itemFn: CreateItemFn, stringKey
// create a key for either a map or a plain value
/** @internal */
function createKey (registry: Registry, itemFn: CreateItemFn, stringKey: string, arg: CreateArgType, hasher: (value: Uint8Array) => Uint8Array): Uint8Array {
function createKey (registry: Registry, itemFn: CreateItemFn, arg: CreateArgType, hasher: (value: Uint8Array) => Uint8Array): Uint8Array {
const { meta: { name, type } } = itemFn;
let param: Uint8Array = EMPTY_U8A;
@@ -114,7 +107,9 @@ function createKey (registry: Registry, itemFn: CreateItemFn, stringKey: string,
// attach the metadata to expand to a StorageFunction
/** @internal */
function expandWithMeta ({ meta, method, prefix, section }: CreateItemFn, storageFn: StorageEntry): StorageEntry {
function expandWithMeta ({ meta, method, prefix, section }: CreateItemFn, _storageFn: (arg?: CreateArgType | [CreateArgType?, CreateArgType?]) => Uint8Array): StorageEntry {
const storageFn = _storageFn as StorageEntry;
storageFn.meta = meta;
storageFn.method = stringLowerFirst(method);
storageFn.prefix = prefix;
@@ -148,7 +143,7 @@ function extendHeadMeta (registry: Registry, { meta: { documentation, name, type
const prefixKey = registry.createType('StorageKey', iterFn, { method, section });
return (arg?: any): StorageKey =>
return (arg?: any) =>
!isUndefined(arg) && !isNull(arg)
? registry.createType('StorageKey', iterFn(arg), { method, section })
: prefixKey;
@@ -162,41 +157,39 @@ function extendPrefixedMap (registry: Registry, itemFn: CreateItemFn, storageFn:
storageFn.iterKey = extendHeadMeta(registry, itemFn, storageFn, (arg?: any): Raw => {
assert(type.isDoubleMap || isUndefined(arg), 'Filtering arguments for keys/entries are only valid on double maps');
return type.isDoubleMap && !isUndefined(arg) && !isNull(arg)
? new Raw(registry, u8aConcat(createPrefixedKey(itemFn), getHasher(type.asDoubleMap.hasher)(registry.createType(type.asDoubleMap.key1.toString() as 'Raw', arg).toU8a())))
: new Raw(registry, createPrefixedKey(itemFn));
return new Raw(
registry,
type.isDoubleMap && !isUndefined(arg) && !isNull(arg)
? u8aConcat(
createPrefixedKey(itemFn),
getHasher(type.asDoubleMap.hasher)(
registry.createType(type.asDoubleMap.key1.toString() as 'Raw', arg).toU8a()
)
)
: createPrefixedKey(itemFn)
);
});
return storageFn;
}
// attach the full list hashing for double maps
/** @internal */
function extendDoubleMap (registry: Registry, itemFn: CreateItemFn, storageFn: StorageEntry): StorageEntry {
return extendPrefixedMap(registry, itemFn, storageFn);
}
/** @internal */
export default function createFunction (registry: Registry, itemFn: CreateItemFn, options: CreateItemOptions): StorageEntry {
const { meta: { type } } = itemFn;
const stringKey = expandKey(itemFn, options);
const [hasher, key2Hasher] = getHashers(itemFn);
// Can only have zero or one argument:
// - storage.system.account(address)
// - storage.timestamp.blockPeriod()
// For doublemap queries the params is passed in as an tuple, [key1, key2]
const _storageFn = (arg?: CreateArgType | [CreateArgType?, CreateArgType?]): Uint8Array =>
const storageFn = expandWithMeta(itemFn, (arg?: CreateArgType | [CreateArgType?, CreateArgType?]): Uint8Array =>
type.isDoubleMap
? createKeyDoubleMap(registry, itemFn, stringKey, arg as [CreateArgType, CreateArgType], [hasher, key2Hasher])
: createKey(registry, itemFn, stringKey, arg as CreateArgType, options.skipHashing ? NULL_HASHER : hasher);
? createKeyDoubleMap(registry, itemFn, arg as [CreateArgType, CreateArgType], [hasher, key2Hasher])
: createKey(registry, itemFn, arg as CreateArgType, options.skipHashing ? NULL_HASHER : hasher)
);
const storageFn = expandWithMeta(itemFn, _storageFn as StorageEntry);
if (type.isMap) {
if (type.isMap || type.isDoubleMap) {
extendPrefixedMap(registry, itemFn, storageFn);
} else if (type.isDoubleMap) {
extendDoubleMap(registry, itemFn, storageFn);
}
storageFn.keyPrefix = (arg?: any): Uint8Array =>
@@ -5,9 +5,9 @@ import testingPairs from '@polkadot/keyring/testingPairs';
import { TypeRegistry } from '@polkadot/types';
import { u8aToHex } from '@polkadot/util';
import Metadata from '../../../Metadata';
import rpcMetadata from '../../../Metadata/static';
import Decorated from '../../Decorated';
import Metadata from '../../';
import rpcMetadata from '../../static';
import { storageFromMeta } from '../';
const keyring = testingPairs({ type: 'ed25519' });
@@ -18,20 +18,20 @@ describe('fromMetadata', (): void => {
registry.setMetadata(metadata);
const decorated = new Decorated(metadata);
const query = storageFromMeta(registry, metadata);
it('should throw if the storage function expects an argument', (): void => {
expect((): any => decorated.query.balances.account()).toThrowError(/requires one argument/);
expect((): any => query.balances.account()).toThrowError(/requires one argument/);
});
it('should return a value if the storage function does not expect an argument', (): void => {
expect((): any => decorated.query.timestamp.now()).not.toThrow();
expect((): any => query.timestamp.now()).not.toThrow();
});
it('should return the correct length-prefixed storage key', (): void => {
expect(
u8aToHex(
decorated.query.system.account(keyring.alice.address)
query.system.account(keyring.alice.address)
)
).toEqual(
'0x410126aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9de1e86a9a8c739864cf3cc5ec2bea59fd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
@@ -1,18 +1,18 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { MetadataLatest } from '@polkadot/types/interfaces';
import { Registry } from '@polkadot/types/types';
import { ModuleStorage, Storage } from '../../types';
import { ModuleStorage, Storage } from '../types';
import { stringCamelCase, stringLowerFirst } from '@polkadot/util';
import Metadata from '../../Metadata';
import createFunction from './createFunction';
import getStorage from './storage';
/** @internal */
export default function fromMetadata (registry: Registry, { modules }: MetadataLatest): Storage {
return modules.reduce((result, moduleMetadata): Storage => {
export default function fromMetadata (registry: Registry, metadata: Metadata): Storage {
return metadata.asLatest.modules.reduce((result: Storage, moduleMetadata): Storage => {
if (moduleMetadata.storage.isNone) {
return result;
}
@@ -31,11 +31,11 @@ export default function fromMetadata (registry: Registry, { modules }: MetadataL
method,
prefix,
section
}, {});
}, { metaVersion: metadata.version });
return newModule;
}, {} as ModuleStorage);
return result;
}, { ...getStorage(registry) });
}, { ...getStorage(registry, metadata.version) });
}
@@ -1,6 +1,6 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import getStorage from './fromMetadata/storage';
import getStorage from './storage';
export default getStorage;
@@ -7,7 +7,7 @@ import getStorage from './storage';
describe('storage', (): void => {
const registry = new TypeRegistry();
const storage = getStorage(registry);
const storage = getStorage(registry, 8);
it('should return well known keys', (): void => {
expect(typeof storage.substrate).toBe('object');
@@ -3,17 +3,17 @@
import { StorageEntry } from '@polkadot/types/primitive/StorageKey';
import { Registry } from '@polkadot/types/types';
import { Storage } from '../../types';
import { Storage } from '../types';
import * as substrate from './substrate';
/** @internal */
export default function getStorage (registry: Registry): Storage {
export default function getStorage (registry: Registry, metaVersion: number): Storage {
return {
substrate: Object
.entries(substrate)
.reduce((storage: Record<string, StorageEntry>, [key, fn]): Record<string, StorageEntry> => {
(storage as Record<string, unknown>)[key] = fn(registry);
(storage as Record<string, unknown>)[key] = fn(registry, metaVersion);
return storage;
}, {})
@@ -15,8 +15,8 @@ interface SubstrateMetadata {
// Small helper function to factorize code on this page.
/** @internal */
function createRuntimeFunction (method: string, key: string, { documentation, type }: SubstrateMetadata): (registry: Registry) => StorageEntry {
return (registry: Registry): StorageEntry =>
function createRuntimeFunction (method: string, key: string, { documentation, type }: SubstrateMetadata): (registry: Registry, metaVersion: number) => StorageEntry {
return (registry: Registry, metaVersion: number): StorageEntry =>
createFunction(registry, {
meta: {
documentation: registry.createType('Vec<Text>', [documentation]),
@@ -27,7 +27,7 @@ function createRuntimeFunction (method: string, key: string, { documentation, ty
method,
prefix: 'Substrate',
section: 'substrate'
}, { key, skipHashing: true });
}, { key, metaVersion, skipHashing: true });
}
export const code = createRuntimeFunction('code', ':code', {
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import { AugmentedConst, QueryableConsts, QueryableModuleConsts } from '@polkadot/api/types/consts';
import { Codec } from '@polkadot/types/types';
import { Codec, ModulesWithCalls } from '@polkadot/types/types';
import { StorageEntry } from '@polkadot/types/primitive/StorageKey';
export interface ModuleStorage {
@@ -19,3 +19,9 @@ export interface Storage {
[key: string]: ModuleStorage;
substrate: ModuleStorage;
}
export interface DecoratedMeta {
consts: Constants;
query: Storage;
tx: ModulesWithCalls
}
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import expandMetadata, { constantsFromMeta, extrinsicsFromMeta, storageFromMeta } from './decorate';
import Metadata from './Metadata';
export default Metadata;
export { constantsFromMeta, expandMetadata, extrinsicsFromMeta, storageFromMeta };
@@ -7,7 +7,7 @@ import { MetadataInterface } from '../types';
import { unwrapStorageType } from '@polkadot/types/primitive/StorageKey';
import getUniqTypes from './getUniqTypes';
import Metadata from '../Metadata';
import Metadata from '..';
/** @internal */
export function decodeLatestSubstrate<Modules extends Codec> (registry: Registry, version: number, rpcData: string, staticSubstrate: Record<string, unknown>): void {
@@ -114,6 +114,24 @@ function registerOriginCaller (registry: Registry, modules: ModuleMetadataV12[])
});
}
/** @internal */
function createModule (registry: Registry, mod: ModuleMetadataV12, { calls, events, storage }: { calls: FunctionMetadataV12[] | null, events: EventMetadataV12[] | null, storage: StorageMetadataV12 | null }): ModuleMetadataLatest {
const sectionTypes = getModuleTypes(registry, stringCamelCase(mod.name));
return registry.createType('ModuleMetadataLatest', {
...mod,
calls: calls
? convertCalls(registry, calls, sectionTypes)
: null,
events: events
? convertEvents(registry, events, sectionTypes)
: null,
storage: storage
? convertStorage(registry, storage, sectionTypes)
: null
});
}
/**
* Convert the Metadata (which is an alias) to latest - effectively this _always_ get applied to the top-level &
* most-recent metadata, since it allows us a chance to actually apply call and storage specific type aliasses
@@ -124,24 +142,10 @@ export default function toLatest (registry: Registry, { extrinsic, modules }: Me
return registry.createType('MetadataLatest', {
extrinsic,
modules: modules.map((mod): ModuleMetadataLatest => {
const calls = mod.calls.unwrapOr(null);
const events = mod.events.unwrapOr(null);
const storage = mod.storage.unwrapOr(null);
const sectionTypes = getModuleTypes(registry, stringCamelCase(mod.name));
return registry.createType('ModuleMetadataLatest', {
...mod,
calls: calls
? convertCalls(registry, calls, sectionTypes)
: null,
events: events
? convertEvents(registry, events, sectionTypes)
: null,
storage: storage
? convertStorage(registry, storage, sectionTypes)
: null
});
})
modules: modules.map((mod) => createModule(registry, mod, {
calls: mod.calls.unwrapOr(null),
events: mod.events.unwrapOr(null),
storage: mod.storage.unwrapOr(null)
}))
});
}
+5 -6
View File
@@ -10,9 +10,8 @@ import { MockStateSubscriptions, MockStateSubscriptionCallback, MockStateDb } fr
import BN from 'bn.js';
import EventEmitter from 'eventemitter3';
import Decorated from '@polkadot/metadata/Decorated';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import Metadata, { storageFromMeta } from '@polkadot/metadata';
import rpcMetadata from '@polkadot/metadata/static';
import jsonrpc from '@polkadot/types/interfaces/jsonrpc';
import testKeyring from '@polkadot/keyring/testing';
import rpcHeader from '@polkadot/types/json/Header.004.json';
@@ -174,7 +173,7 @@ export default class Mock implements ProviderInterface {
this.registry.setMetadata(metadata);
const decorated = new Decorated(metadata);
const query = storageFromMeta(this.registry, metadata);
// Do something every 1 seconds
setInterval((): void => {
@@ -187,11 +186,11 @@ export default class Mock implements ProviderInterface {
// increment the balances and nonce for each account
keyring.getPairs().forEach(({ publicKey }, index): void => {
this.setStateBn(decorated.query.system.account(publicKey), newHead.number.toBn().addn(index));
this.setStateBn(query.system.account(publicKey), newHead.number.toBn().addn(index));
});
// set the timestamp for the current block
this.setStateBn(decorated.query.timestamp.now(), Math.floor(Date.now() / 1000));
this.setStateBn(query.timestamp.now(), Math.floor(Date.now() / 1000));
this.updateSubs('chain_subscribeNewHead', newHead);
// We emit connected/disconnected at intervals
+2 -2
View File
@@ -3,8 +3,8 @@
import Handlebars from 'handlebars';
import staticData from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata/Metadata';
import staticData from '@polkadot/metadata/static';
import Metadata from '@polkadot/metadata';
import { TypeRegistry } from '@polkadot/types/create';
import * as defaultDefs from '@polkadot/types/interfaces/definitions';
import { stringCamelCase } from '@polkadot/util';
+2 -2
View File
@@ -6,8 +6,8 @@ import Handlebars from 'handlebars';
import { StorageEntryMetadataLatest } from '@polkadot/types/interfaces/metadata';
import { Registry } from '@polkadot/types/types';
import staticData from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata/Metadata';
import staticData from '@polkadot/metadata/static';
import Metadata from '@polkadot/metadata';
import * as defaultDefs from '@polkadot/types/interfaces/definitions';
import { unwrapStorageType } from '@polkadot/types/primitive/StorageKey';
import { TypeRegistry } from '@polkadot/types/create';
+2 -2
View File
@@ -5,8 +5,8 @@ import Handlebars from 'handlebars';
import { Registry } from '@polkadot/types/types';
import staticData from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata/Metadata';
import staticData from '@polkadot/metadata/static';
import Metadata from '@polkadot/metadata';
import * as defaultDefs from '@polkadot/types/interfaces/definitions';
import { Text } from '@polkadot/types/primitive';
import { TypeRegistry } from '@polkadot/types/create';
+2 -2
View File
@@ -5,8 +5,8 @@ import { MetadataLatest } from '@polkadot/types/interfaces/metadata';
import { Codec, DefinitionRpcParam } from '@polkadot/types/types';
import fs from 'fs';
import Metadata from '@polkadot/metadata/Metadata';
import rpcdata from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata';
import rpcdata from '@polkadot/metadata/static';
import Call from '@polkadot/types/generic/Call';
import { unwrapStorageType } from '@polkadot/types/primitive/StorageKey';
import { TypeRegistry } from '@polkadot/types/create';
+2 -2
View File
@@ -5,8 +5,8 @@ import { VoteThreshold } from '../interfaces/elections';
import { BlockNumber } from '../interfaces/runtime';
import { CodecTo } from '../types';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata';
import rpcMetadata from '@polkadot/metadata/static';
import { TypeRegistry } from '../create';
import Text from '../primitive/Text';
+2 -2
View File
@@ -4,8 +4,8 @@
import { PropIndex } from '../interfaces/democracy';
import { Codec, CodecTo } from '../types';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata';
import rpcMetadata from '@polkadot/metadata/static';
import { createTypeUnsafe, TypeRegistry } from '../create';
import AccountId from '../generic/AccountId';
+12 -12
View File
@@ -4,9 +4,9 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import { ChainProperties, DispatchErrorModule, H256 } from '../interfaces/types';
import { CallFunction, Codec, Constructor, InterfaceTypes, RegistryError, RegistryTypes, Registry, RegistryMetadata, RegistryMetadataLatest, RegisteredTypes } from '../types';
import { CallFunction, Codec, Constructor, InterfaceTypes, RegistryError, RegistryTypes, Registry, RegistryMetadata, RegisteredTypes } from '../types';
import extrinsicsFromMeta from '@polkadot/metadata/Decorated/extrinsics/fromMetadata';
import { extrinsicsFromMeta } from '@polkadot/metadata';
import { BN_ZERO, assert, formatBalance, isFunction, isString, isU8a, isUndefined, logger, stringCamelCase, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -22,7 +22,8 @@ import { getTypeDef } from './getTypeDef';
const l = logger('registry');
// create error mapping from metadata
function decorateErrors (_: Registry, { modules }: RegistryMetadataLatest, metadataErrors: Record<string, RegistryError>): void {
function decorateErrors (_: Registry, metadata: RegistryMetadata, metadataErrors: Record<string, RegistryError>): void {
const modules = metadata.asLatest.modules;
const isIndexed = modules.some(({ index }) => !index.eqn(255));
// decorate the errors
@@ -46,7 +47,8 @@ function decorateErrors (_: Registry, { modules }: RegistryMetadataLatest, metad
}
// create event classes from metadata
function decorateEvents (registry: Registry, { modules }: RegistryMetadataLatest, metadataEvents: Record<string, Constructor<EventData>>): void {
function decorateEvents (registry: Registry, metadata: RegistryMetadata, metadataEvents: Record<string, Constructor<EventData>>): void {
const modules = metadata.asLatest.modules;
const isIndexed = modules.some(({ index }) => !index.eqn(255));
// decorate the events
@@ -81,7 +83,7 @@ function decorateEvents (registry: Registry, { modules }: RegistryMetadataLatest
}
// create extrinsic mapping from metadata
function decorateExtrinsics (registry: Registry, metadata: RegistryMetadataLatest, metadataCalls: Record<string, CallFunction>): void {
function decorateExtrinsics (registry: Registry, metadata: RegistryMetadata, metadataCalls: Record<string, CallFunction>): void {
const extrinsics = extrinsicsFromMeta(registry, metadata);
// decorate the extrinsics
@@ -363,17 +365,15 @@ export class TypeRegistry implements Registry {
// sets the metadata
public setMetadata (metadata: RegistryMetadata, signedExtensions?: string[]): void {
const latest = metadata.asLatest;
decorateExtrinsics(this, latest, this.#metadataCalls);
decorateErrors(this, latest, this.#metadataErrors);
decorateEvents(this, latest, this.#metadataEvents);
decorateExtrinsics(this, metadata, this.#metadataCalls);
decorateErrors(this, metadata, this.#metadataErrors);
decorateEvents(this, metadata, this.#metadataEvents);
// setup the available extensions
this.setSignedExtensions(
signedExtensions || (
latest.extrinsic.version.gt(BN_ZERO)
? latest.extrinsic.signedExtensions.map((key) => key.toString())
metadata.asLatest.extrinsic.version.gt(BN_ZERO)
? metadata.asLatest.extrinsic.signedExtensions.map((key) => key.toString())
: defaultExtensions
)
);
@@ -1,8 +1,8 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata';
import rpcMetadata from '@polkadot/metadata/static';
import { TypeRegistry } from '../create';
import Extrinsic from './Extrinsic';
@@ -1,8 +1,8 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata';
import rpcMetadata from '@polkadot/metadata/static';
import { TypeRegistry } from '../create';
import SignerPayload from './SignerPayload';
@@ -3,20 +3,20 @@
import BN from 'bn.js';
import testingPairs from '@polkadot/keyring/testingPairs';
import Decorated from '@polkadot/metadata/Decorated';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import Metadata, { extrinsicsFromMeta } from '@polkadot/metadata';
import rpcMetadata from '@polkadot/metadata/static';
import { TypeRegistry } from '../../create';
import Extrinsic from './Extrinsic';
const registry = new TypeRegistry();
const metadata = new Metadata(registry, rpcMetadata);
const decorated = new Decorated(metadata);
const keyring = testingPairs({ type: 'ed25519' }, false);
registry.setMetadata(metadata);
const tx = extrinsicsFromMeta(registry, metadata);
describe('ExtrinsicV4', (): void => {
it.only('constructs a sane Uint8Array (default)', (): void => {
expect(
@@ -31,7 +31,7 @@ describe('ExtrinsicV4', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969n)
tx.balances.transfer(keyring.bob.publicKey, 6969n)
).toHex()
).toEqual(
'0x' +
@@ -46,7 +46,7 @@ describe('ExtrinsicV4', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969n)
tx.balances.transfer(keyring.bob.publicKey, 6969n)
).sign(keyring.alice, {
blockHash: '0xec7afaf1cca720ce88c1d1b689d81f0583cc15a97d621cf046dd9abf605ef22f',
genesisHash: '0xdcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b',
+2 -2
View File
@@ -4,8 +4,8 @@
/* eslint-disable sort-keys */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import Metadata from '@polkadot/metadata/Metadata';
import metadataStatic from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata';
import metadataStatic from '@polkadot/metadata/static';
import { TypeRegistry } from '../create';
import block00300 from '../json/SignedBlock.003.00.json';
+2 -2
View File
@@ -1,8 +1,8 @@
// Copyright 2017-2020 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import Metadata from '@polkadot/metadata/Metadata';
import metadataStatic from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata';
import metadataStatic from '@polkadot/metadata/static';
import { TypeRegistry } from '../create';
import Call from './Call';
+2 -2
View File
@@ -1,8 +1,8 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import Metadata from '@polkadot/metadata/Metadata';
import metadataStatic from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata';
import metadataStatic from '@polkadot/metadata/static';
import { createTypeUnsafe, TypeRegistry } from './create';
import { Codec } from './types';
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as Metadata } from '@polkadot/metadata/Metadata';
export { default as Metadata } from '@polkadot/metadata';
export * from './extrinsic';
export * from './generic';
@@ -4,8 +4,8 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import Metadata from '@polkadot/metadata';
import rpcMetadata from '@polkadot/metadata/static';
import { TypeRegistry } from '../../create';
import json1 from '../../json/EventRecord.001.json';
@@ -1,9 +1,8 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import Decorated from '@polkadot/metadata/Decorated';
import Metadata from '@polkadot/metadata/Metadata';
import rpcDataV11 from '@polkadot/metadata/Metadata/v11/static';
import Metadata, { storageFromMeta } from '@polkadot/metadata';
import rpcDataV11 from '@polkadot/metadata/v11/static';
import { TypeRegistry } from '../create';
import StorageKey from './StorageKey';
@@ -16,12 +15,12 @@ describe('StorageKey', (): void => {
registry.setMetadata(metadata);
const decorated = new Decorated(metadata);
const query = storageFromMeta(registry, metadata);
it('should allow decoding of a DoubleMap key', (): void => {
const key = new StorageKey(registry, '0x5f3e4907f716ac89b6347d15ececedca8bde0a0ea8864605e3b68ed9cb2da01b66ccada06515787c10000000e535263148daaf49be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f');
key.setMeta(decorated.query.staking.erasStakers.meta);
key.setMeta(query.staking.erasStakers.meta);
expect(key.toHuman()).toEqual([
'16',
@@ -32,7 +31,7 @@ describe('StorageKey', (): void => {
it('should allow decoding of a Map key', (): void => {
const key = new StorageKey(registry, '0x426e15054d267946093858132eb537f191ca57b0c4b20b29ae7e99d6201d680cc906f7710aa165d62c709012f807af8fc3f0d2abb0c51ca9a88d4ef24d1a092bf89dacf5ce63ea1d');
key.setMeta(decorated.query.society.defenderVotes.meta);
key.setMeta(query.society.defenderVotes.meta);
expect(key.toHuman()).toEqual([
'5D4yQHKfqCQYThhHmTfN1JEDi47uyDJc1xg9eZfAG1R7FC7J'