Update to Metadata v5 (#991)

* add v5 folder

* Fixed typo in README

* Updated tests to v5

* added v5 methods to MetadataVersioned

* Added toV5 conversion file to v4 folder

* change from v4 to v5

* Bump up version

* Update imports in type-storage package

* Switch to v5 imports in type-extrinsics, rpc-core and rpc-provider

* 0.81.0 => 0.82.0

* Updating dependencies to 0.82.0

* update comments

* Undo version bump

* Remove release notes

* v4 to v5 conversion

* WIP tests

* Addresses Amaurys comments

* re-added conversion function

* removed unused imports

* Re-add string to HasherInput type

* addresses failing derive tests

* Fixed broken derive e2e tests

* v5 tests

* Update packages/types/src/Metadata/MetadataVersioned.ts

Co-Authored-By: Amaury Martiny <amaury.martiny@protonmail.com>

* v3->v4

* trigger hung up travis build
This commit is contained in:
Stefanie Doll
2019-06-13 14:42:44 +02:00
committed by GitHub
co-authored by Amaury Martiny
parent 7bd2fcd7f9
commit e4a97d4efd
39 changed files with 3208 additions and 100 deletions
@@ -12,10 +12,12 @@ import MetadataV1 from './v1';
import MetadataV2 from './v2';
import MetadataV3 from './v3';
import MetadataV4 from './v4';
import MetadataV5 from './v5';
import v0ToV1 from './v0/toV1';
import v1ToV2 from './v1/toV2';
import v2ToV3 from './v2/toV3';
import v3ToV4 from './v3/toV4';
import v4ToV5 from './v4/toV5';
class MetadataEnum extends Enum {
constructor (value?: any) {
@@ -24,7 +26,8 @@ class MetadataEnum extends Enum {
MetadataV1, // once rolled-out, can replace this with MetadataDeprecated
MetadataV2, // once rolled-out, can replace this with MetadataDeprecated
MetadataV3, // once rolled-out, can replace this with MetadataDeprecated
MetadataV4
MetadataV4, // once rolled-out, can replace this with MetadataDeprecated
MetadataV5
}, value);
}
@@ -73,6 +76,15 @@ class MetadataEnum extends Enum {
return this.value as MetadataV4;
}
/**
* @description Returns the wrapped values as a V5 object
*/
get asV5 (): MetadataV5 {
assert(this.isV5, `Cannot convert '${this.type}' via asV5`);
return this.value as MetadataV5;
}
/**
* @description `true` if Deprecated
*/
@@ -115,6 +127,13 @@ class MetadataEnum extends Enum {
return this.type === 'MetadataV4';
}
/**
* @description `true` if V5
*/
get isV5 (): boolean {
return this.type === 'MetadataV5';
}
/**
* @description The version this metadata represents
*/
@@ -133,6 +152,7 @@ export default class MetadataVersioned extends Struct {
private _convertedV2?: MetadataV2;
private _convertedV3?: MetadataV3;
private _convertedV4?: MetadataV4;
private _convertedV5?: MetadataV5;
constructor (value?: any) {
super({
@@ -223,14 +243,14 @@ export default class MetadataVersioned extends Struct {
}
getUniqTypes (throwError: boolean): Array<string> {
return this.asV4.getUniqTypes(throwError);
return this.asV5.getUniqTypes(throwError);
}
/**
* @description Returns the wrapped values as a V4 object
*/
get asV4 (): MetadataV4 {
assert(this.metadata.version <= 4, `Cannot convert metadata from v${this.metadata.version} to v3`);
assert(this.metadata.version <= 4, `Cannot convert metadata from v${this.metadata.version} to v4`);
if (this.metadata.version === 4) {
return this.metadata.asV4;
@@ -242,4 +262,21 @@ export default class MetadataVersioned extends Struct {
return this._convertedV4;
}
/**
* @description Returns the wrapped values as a V5 object
*/
get asV5 (): MetadataV5 {
assert(this.metadata.version <= 5, `Cannot convert metadata from v${this.metadata.version} to v5`);
if (this.metadata.version === 5) {
return this.metadata.asV5;
}
if (isUndefined(this._convertedV5)) {
this._convertedV5 = v4ToV5(this.asV4);
}
return this._convertedV5;
}
}
+4 -3
View File
@@ -2,11 +2,12 @@
1. New branch :)
2. `curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "state_getMetadata", "params":[]}' http://localhost:9933`
3. Copy the result (hex-only) into `tstaic.ts`, as of now linked to `v1/static.ts`
3. Copy the latest version folder (vx) in `types/Metadata`
3. Copy the result (hex-only) into `static.ts`, as of now linked to `v5/static.ts`
4. Rust Metadata tests, `yarn run test packages/types/src/Metadata`
5. Add new class types as required (find missing in Rust code, add)
6. Add all classes to `index.classes.ts`
6. Add all classes to `src/classes.ts`
7. Repeat 4-6 until passing
8. Update parsed JSON to actual output version, `v1/latest.*.json`
8. Update parsed JSON to actual output version, `v5/latest.*.json`
9. All tests
10. Make PR
+1 -1
View File
@@ -2,6 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import metadata from './v4/static';
import metadata from './v5/static';
export default metadata;
+6 -6
View File
@@ -31,17 +31,17 @@ export function decodeLatestSubstrate<Modules extends Codec> (
}
/**
* Given a `version`, MetadataV4 and MetadataV{version} should output the same
* Given a `version`, MetadataV5 and MetadataV{version} should output the same
* unique types.
*/
export function toV4<Modules extends Codec> (version: number, rpcData: string) {
it('converts to V4', () => {
export function toV5<Modules extends Codec> (version: number, rpcData: string) {
it('converts to V5', () => {
const metadata = new Metadata(rpcData)[`asV${version}` as keyof Metadata];
const metadataV4 = new Metadata(rpcData).asV4;
const metadataV5 = new Metadata(rpcData).asV5;
expect(
(metadata as unknown as MetadataInterface<Modules>).getUniqTypes(true)
).toEqual(metadataV4.getUniqTypes(true));
).toEqual(metadataV5.getUniqTypes(true));
});
}
@@ -53,7 +53,7 @@ export function defaultValues (rpcData: string) {
const metadata = new Metadata(rpcData);
Method.injectMethods(extrinsicsFromMeta(metadata));
metadata.asV4.modules
metadata.asV5.modules
.filter(({ storage }) => storage.isSome)
.map((mod) =>
mod.storage.unwrap().forEach(({ fallback, name, type }) => {
@@ -6,7 +6,7 @@ import MetadataV0 from './';
import Metadata from '../';
import latestSubstrateV0 from './latest.substrate.v0.json';
import rpcData from './static';
import { defaultValues, toV4 } from '../util/testUtil';
import { defaultValues, toV5 } from '../util/testUtil';
describe('Metadata', () => {
it('works with fallback', () => {
@@ -27,7 +27,7 @@ describe('Metadata', () => {
expect(json).toEqual(latestSubstrateV0);
});
toV4(0, rpcData);
toV5(0, rpcData);
defaultValues(rpcData);
});
@@ -4,12 +4,12 @@
import latestSubstrate from './latest.substrate.v1.json';
import rpcData from './static';
import { decodeLatestSubstrate, defaultValues, toV4 } from '../util/testUtil';
import { decodeLatestSubstrate, defaultValues, toV5 } from '../util/testUtil';
describe('MetadataV1', () => {
decodeLatestSubstrate(1, rpcData, latestSubstrate);
toV4(1, rpcData);
toV5(1, rpcData);
defaultValues(rpcData);
});
@@ -4,12 +4,12 @@
import latestSubstrate from './latest.substrate.v2.json';
import rpcData from './static';
import { decodeLatestSubstrate, defaultValues, toV4 } from '../util/testUtil';
import { decodeLatestSubstrate, defaultValues, toV5 } from '../util/testUtil';
describe('MetadataV2', () => {
decodeLatestSubstrate(2, rpcData, latestSubstrate);
toV4(2, rpcData);
toV5(2, rpcData);
defaultValues(rpcData);
});
@@ -4,12 +4,12 @@
import latestSubstrate from './latest.substrate.v3.json';
import rpcData from './static';
import { decodeLatestSubstrate, defaultValues, toV4 } from '../util/testUtil';
import { decodeLatestSubstrate, defaultValues, toV5 } from '../util/testUtil';
describe('MetadataV3', () => {
decodeLatestSubstrate(3, rpcData, latestSubstrate);
toV4(3, rpcData);
toV5(3, rpcData);
defaultValues(rpcData);
});
@@ -4,12 +4,12 @@
import latestSubstrate from './latest.substrate.v4.json';
import rpcData from './static';
import { decodeLatestSubstrate, defaultValues, toV4 } from '../util/testUtil';
import { decodeLatestSubstrate, defaultValues, toV5 } from '../util/testUtil';
describe('MetadataV4', () => {
decodeLatestSubstrate(4, rpcData, latestSubstrate);
toV4(4, rpcData);
toV5(4, rpcData);
defaultValues(rpcData);
});
+78
View File
@@ -0,0 +1,78 @@
// Copyright 2017-2019 @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 { Option, Vector } from '../../codec';
import Text from '../../primitive/Text';
import MetadataV4 from './Metadata';
import StorageHasher from '../../primitive/StorageHasher';
import MetadataV5 from '../v5';
import { StorageFunctionMetadata as StorageFunctionMetadataV4 } from '../v4/Storage';
import { DoubleMapType, StorageFunctionMetadata, StorageFunctionType } from '../v5/Storage';
/**
* Convert V4 StorageFunction to V5 StorageFunction
*/
function toV5StorageFunction (storageFn: StorageFunctionMetadataV4): StorageFunctionMetadata {
const { documentation, fallback, modifier, name, type } = storageFn;
function toStorageHasher (text: Text): StorageHasher {
switch (text.toString()) {
case 'blake2_128':
return new StorageHasher('Blake2_128');
case 'blake2_256':
return new StorageHasher('Blake2_256');
case 'twox_128':
return new StorageHasher('Twox128');
case 'twox_256':
return new StorageHasher('Twox256');
case 'twox_64_concat':
return new StorageHasher('Twox64Concat');
default:
throw new Error(`Invalid Storage hasher: ${text.toString()}`);
}
}
const [newType, index] = type.isPlainType
? [type, 0]
: type.isMap
? [type.asMap, 1]
: [new DoubleMapType({
hasher: type.asDoubleMap.hasher,
key1: type.asDoubleMap.key1,
key2: type.asDoubleMap.key2,
value: type.asDoubleMap.value,
key2Hasher: toStorageHasher(type.asDoubleMap.key2Hasher)
}), 2];
return new StorageFunctionMetadata({
name: name,
modifier: modifier,
type: new StorageFunctionType(newType, index),
fallback: fallback,
documentation: documentation
});
}
/**
* Convert from MetadataV4 to MetadataV5
* See https://github.com/paritytech/substrate/pull/2836/files for details
*/
export default function toV5 (metadataV4: MetadataV4): MetadataV5 {
return new MetadataV5({
modules: metadataV4.modules.map((modul) => {
return {
name: modul.name,
prefix: modul.prefix,
storage: modul.storage.isSome
? new Option(
Vector.with(StorageFunctionMetadata),
modul.storage.unwrap().map(toV5StorageFunction)
)
: undefined,
calls: modul.calls,
events: modul.events
};
})
});
}
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2017-2019 @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.
// Re-export classes that haven't changed between V4 and V5
export {
FunctionArgumentMetadata,
FunctionMetadata
} from '../v4/Calls';
+6
View File
@@ -0,0 +1,6 @@
// Copyright 2017-2019 @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.
// Re-export classes that haven't changed between V4 and V5
export { EventMetadata } from '../v4/Events';
@@ -0,0 +1,15 @@
// Copyright 2017-2019 @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 latestSubstrate from './latest.substrate.v5.json';
import rpcData from './static';
import { decodeLatestSubstrate, defaultValues, toV5 } from '../util/testUtil';
describe('MetadataV5', () => {
decodeLatestSubstrate(5, rpcData, latestSubstrate);
toV5(5, rpcData);
defaultValues(rpcData);
});
+134
View File
@@ -0,0 +1,134 @@
// Copyright 2017-2019 @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 { MetadataInterface } from '../types';
import Option from '../../codec/Option';
import Struct from '../../codec/Struct';
import Vector from '../../codec/Vector';
import Text from '../../primitive/Text';
import { flattenUniq, validateTypes } from '../util';
import { FunctionMetadata } from './Calls';
import { EventMetadata } from './Events';
import { StorageFunctionMetadata } from './Storage';
/**
* @name ModuleMetadata
* @description
* The definition of a module in the system
*/
export class ModuleMetadata extends Struct {
constructor (value?: any) {
super({
name: Text,
prefix: Text,
storage: Option.with(Vector.with(StorageFunctionMetadata)),
calls: Option.with(Vector.with(FunctionMetadata)),
events: Option.with(Vector.with(EventMetadata))
}, value);
}
/**
* @description the module calls
*/
get calls (): Option<Vector<FunctionMetadata>> {
return this.get('calls') as Option<Vector<FunctionMetadata>>;
}
/**
* @description the module events
*/
get events (): Option<Vector<EventMetadata>> {
return this.get('events') as Option<Vector<EventMetadata>>;
}
/**
* @description the module name
*/
get name (): Text {
return this.get('name') as Text;
}
/**
* @description the module prefix
*/
get prefix (): Text {
return this.get('prefix') as Text;
}
/**
* @description the associated module storage
*/
get storage (): Option<Vector<StorageFunctionMetadata>> {
return this.get('storage') as Option<Vector<StorageFunctionMetadata>>;
}
}
/**
* @name MetadataV5
* @description
* The runtime metadata as a decoded structure
*/
export default class MetadataV5 extends Struct implements MetadataInterface<ModuleMetadata> {
constructor (value?: any) {
super({
modules: Vector.with(ModuleMetadata)
}, value);
}
/**
* @description The associated modules for this structure
*/
get modules (): Vector<ModuleMetadata> {
return this.get('modules') as Vector<ModuleMetadata>;
}
private get callNames () {
return this.modules.map((mod) =>
mod.calls.isNone
? []
: mod.calls.unwrap().map((fn) =>
fn.args.map((arg) => arg.type.toString())
)
);
}
private get eventNames () {
return this.modules.map((mod) =>
mod.events.isNone
? []
: mod.events.unwrap().map((event) =>
event.args.map((arg) => arg.toString())
)
);
}
private get storageNames () {
return this.modules.map((mod) =>
mod.storage.isNone
? []
: mod.storage.unwrap().map((fn) => {
if (fn.type.isMap) {
return [fn.type.asMap.key.toString(), fn.type.asMap.value.toString()];
} else if (fn.type.isDoubleMap) {
return [fn.type.asDoubleMap.key1.toString(), fn.type.asDoubleMap.key2.toString(), fn.type.asDoubleMap.value.toString()];
} else {
return [fn.type.asType.toString()];
}
})
);
}
/**
* @description Helper to retrieve a list of all type that are found, sorted and de-deuplicated
*/
getUniqTypes (throwError: boolean): Array<string> {
const types = flattenUniq([this.callNames, this.eventNames, this.storageNames]);
validateTypes(types, throwError);
return types;
}
}
+223
View File
@@ -0,0 +1,223 @@
// Copyright 2017-2019 @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 } from '@polkadot/util';
import Enum from '../../codec/Enum';
import Struct from '../../codec/Struct';
import Vector from '../../codec/Vector';
import Bytes from '../../primitive/Bytes';
import StorageHasher from '../../primitive/StorageHasher';
import Text from '../../primitive/Text';
import Type from '../../primitive/Type';
import { MapType, PlainType, StorageFunctionModifier } from '../v4/Storage';
// Re-export classes that haven't changed between V4 and V5
export {
MapType,
PlainType,
StorageFunctionModifier
};
export class DoubleMapType extends Struct {
constructor (value?: any) {
super({
hasher: StorageHasher,
key1: Type,
key2: Type,
value: Type,
key2Hasher: StorageHasher
}, value);
}
/**
* @description The hashing algorithm used to hash keys, as [[StorageHasher]]
*/
get hasher (): StorageHasher {
return this.get('hasher') as StorageHasher;
}
/**
* @description The mapped key as [[Type]]
*/
get key1 (): Type {
return this.get('key1') as Type;
}
/**
* @description The mapped key as [[Type]]
*/
get key2 (): Type {
return this.get('key2') as Type;
}
/**
* @description The hashing algorithm used to hash key2, as [[StorageHasher]]
*/
get key2Hasher (): StorageHasher {
return this.get('key2Hasher') as StorageHasher;
}
/**
* @description The mapped key as [[Type]]
*/
get value (): Type {
return this.get('value') as Type;
}
}
export class StorageFunctionType extends Enum {
constructor (value?: any, index?: number) {
super({
PlainType,
MapType,
DoubleMapType
}, value, index);
}
/**
* @description The value as a mapped value
*/
get asDoubleMap (): DoubleMapType {
assert(this.isDoubleMap, `Cannot convert '${this.type}' via asDoubleMap`);
return this.value as DoubleMapType;
}
/**
* @description The value as a mapped value
*/
get asMap (): MapType {
assert(this.isMap, `Cannot convert '${this.type}' via asMap`);
return this.value as MapType;
}
/**
* @description The value as a [[Type]] value
*/
get asType (): PlainType {
assert(this.isPlainType, `Cannot convert '${this.type}' via asType`);
return this.value as PlainType;
}
/**
* @description `true` if the storage entry is a doublemap
*/
get isDoubleMap (): boolean {
return this.toNumber() === 2;
}
/**
* @description `true` if the storage entry is a map
*/
get isMap (): boolean {
return this.toNumber() === 1;
}
/**
* @description `true` if the storage entry is a plain type
*/
get isPlainType (): boolean {
return this.toNumber() === 0;
}
/**
* @description Returns the string representation of the value
*/
toString (): string {
if (this.isDoubleMap) {
return `DoubleMap<${this.asDoubleMap.value.toString()}>`;
}
if (this.isMap) {
if (this.asMap.isLinked) {
return `(${this.asMap.value.toString()}, Linkage<${this.asMap.key.toString()}>)`;
}
return this.asMap.value.toString();
}
return this.asType.toString();
}
}
export type StorageFunctionMetadataValue = {
name: string | Text,
modifier: StorageFunctionModifier | AnyNumber,
type: StorageFunctionType,
fallback: Bytes,
documentation: Vector<Text> | Array<string>
};
/**
* @name StorageFunctionMetadata
* @description
* The definition of a storage function
*/
export class StorageFunctionMetadata extends Struct {
constructor (value?: StorageFunctionMetadataValue | Uint8Array) {
super({
name: Text,
modifier: StorageFunctionModifier,
type: StorageFunctionType,
fallback: Bytes,
documentation: Vector.with(Text)
}, value);
}
/**
* @description The default value of the storage function
* @deprecated Use `.fallback` instead.
*/
get default (): Bytes {
return this.fallback;
}
/**
* @description The default value of the storage function
*/
get fallback (): Bytes {
return this.get('fallback') as Bytes;
}
/**
* @description The [[Text]] documentation
*/
get documentation (): Vector<Text> {
return this.get('documentation') as Vector<Text>;
}
/**
* @description The [[Text]] documentation
* @deprecated Use `.documentation` instead.
*/
get docs (): Vector<Text> {
return this.documentation;
}
/**
* @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;
}
}
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2017-2019 @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 { default as MetadataV5, ModuleMetadata as ModuleMetadataV5 } from './Metadata';
export default MetadataV5;
export {
ModuleMetadataV5
};
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -25,7 +25,7 @@ describe('types', () => {
});
});
describe('default creation (empty Bytes)', () => {
describe('default creation (empty bytes)', () => {
(Types.Method as any).injectMethods(extrinsics);
Object.keys(Types).forEach((name) => {
+6 -6
View File
@@ -11,7 +11,7 @@ import Tuple from '../codec/Tuple';
import U8aFixed from '../codec/U8aFixed';
import { TypeDef, getTypeClass, getTypeDef } from '../codec/createType';
import Metadata from '../Metadata';
import { EventMetadata as EventMetadataV4 } from '../Metadata/v4/Events';
import { EventMetadata as EventMetadataV5 } from '../Metadata/v5/Events';
import Null from './Null';
import U32 from './U32';
@@ -31,12 +31,12 @@ export class EventIndex extends U32 {
* Wrapper for the actual data that forms part of an [[Event]]
*/
export class EventData extends Tuple {
private _meta: EventMetadataV4;
private _meta: EventMetadataV5;
private _method: string;
private _section: string;
private _typeDef: Array<TypeDef>;
constructor (Types: Array<Constructor>, value: Uint8Array, typeDef: Array<TypeDef>, meta: EventMetadataV4, section: string, method: string) {
constructor (Types: Array<Constructor>, value: Uint8Array, typeDef: Array<TypeDef>, meta: EventMetadataV5, section: string, method: string) {
super(Types, value);
this._meta = meta;
@@ -48,7 +48,7 @@ export class EventData extends Tuple {
/**
* @description The wrapped [[EventMetadata]]
*/
get meta (): EventMetadataV4 {
get meta (): EventMetadataV5 {
return this._meta;
}
@@ -128,7 +128,7 @@ export default class Event extends Struct {
// This is called/injected by the API on init, allowing a snapshot of
// the available system events to be used in lookups
static injectMetadata (metadata: Metadata): void {
metadata.asV4.modules
metadata.asV5.modules
.filter((section) => section.events.isSome)
.forEach((section, sectionIndex) => {
const sectionName = stringCamelCase(section.name.toString());
@@ -165,7 +165,7 @@ export default class Event extends Struct {
/**
* @description The [[EventMetadata]] with the documentation
*/
get meta (): EventMetadataV4 {
get meta (): EventMetadataV5 {
return this.data.meta;
}
+9 -9
View File
@@ -9,7 +9,7 @@ import { assert, isHex, isObject, isU8a, hexToU8a } from '@polkadot/util';
import { getTypeDef, getTypeClass } from '../codec/createType';
import Struct from '../codec/Struct';
import U8aFixed from '../codec/U8aFixed';
import { FunctionMetadata as FunctionMetadataV4, FunctionArgumentMetadata } from '../Metadata/v4/Calls';
import { FunctionMetadata as FunctionMetadataV5, FunctionArgumentMetadata } from '../Metadata/v5/Calls';
interface DecodeMethodInput {
args: any;
@@ -18,13 +18,13 @@ interface DecodeMethodInput {
interface DecodedMethod extends DecodeMethodInput {
argsDef: ArgsDef;
meta: FunctionMetadataV4;
meta: FunctionMetadataV5;
}
export interface MethodFunction {
(...args: any[]): Method;
callIndex: Uint8Array;
meta: FunctionMetadataV4;
meta: FunctionMetadataV5;
method: string;
section: string;
toJSON: () => any;
@@ -63,9 +63,9 @@ export class MethodIndex extends U8aFixed {
* {@link https://github.com/paritytech/wiki/blob/master/Extrinsic.md#the-extrinsic-format-for-node}.
*/
export default class Method extends Struct implements IMethod {
protected _meta: FunctionMetadataV4;
protected _meta: FunctionMetadataV5;
constructor (value: any, meta?: FunctionMetadataV4) {
constructor (value: any, meta?: FunctionMetadataV5) {
const decoded = Method.decodeMethod(value, meta);
super({
@@ -86,7 +86,7 @@ export default class Method extends Struct implements IMethod {
* @param _meta - Metadata to use, so that `injectMethods` lookup is not
* necessary.
*/
private static decodeMethod (value: DecodedMethod | Uint8Array | string = new Uint8Array(), _meta?: FunctionMetadataV4): DecodedMethod {
private static decodeMethod (value: DecodedMethod | Uint8Array | string = new Uint8Array(), _meta?: FunctionMetadataV5): DecodedMethod {
if (isHex(value)) {
return Method.decodeMethod(hexToU8a(value), _meta);
} else if (isU8a(value)) {
@@ -126,7 +126,7 @@ export default class Method extends Struct implements IMethod {
}
// If the extrinsic function has an argument of type `Origin`, we ignore it
static filterOrigin (meta?: FunctionMetadataV4): Array<FunctionArgumentMetadata> {
static filterOrigin (meta?: FunctionMetadataV5): Array<FunctionArgumentMetadata> {
// FIXME should be `arg.type !== Origin`, but doesn't work...
return meta
? meta.args.filter(({ type }) =>
@@ -154,7 +154,7 @@ export default class Method extends Struct implements IMethod {
*
* @param meta - The function metadata used to get the definition.
*/
private static getArgsDef (meta: FunctionMetadataV4): ArgsDef {
private static getArgsDef (meta: FunctionMetadataV5): ArgsDef {
return Method.filterOrigin(meta).reduce((result, { name, type }) => {
const Type = getTypeClass(
getTypeDef(type)
@@ -216,7 +216,7 @@ export default class Method extends Struct implements IMethod {
/**
* @description The [[FunctionMetadata]]
*/
get meta (): FunctionMetadataV4 {
get meta (): FunctionMetadataV5 {
return this._meta;
}
@@ -6,6 +6,7 @@ import { hexToU8a } from '@polkadot/util';
import fromMetadata from '@polkadot/storage/fromMetadata';
import rpcDataV3 from '@polkadot/types/Metadata/v3/static';
import rpcDataV4 from '@polkadot/types/Metadata/v4/static';
import rpcDataV5 from '@polkadot/types/Metadata/v5/static';
import Metadata from '../Metadata';
import StorageKey from './StorageKey';
@@ -94,4 +95,32 @@ describe('StorageKey', () => {
).toEqual(Uint8Array.from([1, 1, 48, 7, 201, 255, 112, 39, 246, 89, 0, 171, 205, 252, 164, 253, 177, 7, 234, 212, 126, 42, 158, 53, 88, 224, 27, 105, 27, 15, 74, 95, 133, 24, 212, 135, 50, 102, 20, 240, 102, 65, 99, 8, 191, 106, 164, 229, 4, 29, 25, 73, 146, 142, 75, 38, 237, 233, 142, 60, 235, 179, 106, 59, 23, 38]));
});
});
describe('with MetadataV5', () => {
const storage = fromMetadata(new Metadata(rpcDataV5));
it(`should correctly get the EventTopics double map storage key (hex)`, () => {
expect(
new StorageKey([
storage
.system
.eventTopics,
['any', [1, 2, 3]]
])
.toHex()
).toBe('0x3007c9ff7027f65900abcdfca4fdb107ead47e2a9e3558e01b691b0f4a5f8518d487326614f066416308bf6aa4e5041d1949928e4b26ede98e3cebb36a3b1726');
});
it(`should correctly get the EventTopics double map storage key (u8a)`, () => {
expect(
new StorageKey([
storage
.system
.eventTopics,
['any', [1, 2, 3]]
])
.toU8a()
).toEqual(Uint8Array.from([1, 1, 48, 7, 201, 255, 112, 39, 246, 89, 0, 171, 205, 252, 164, 253, 177, 7, 234, 212, 126, 42, 158, 53, 88, 224, 27, 105, 27, 15, 74, 95, 133, 24, 212, 135, 50, 102, 20, 240, 102, 65, 99, 8, 191, 106, 164, 229, 4, 29, 25, 73, 146, 142, 75, 38, 237, 233, 142, 60, 235, 179, 106, 59, 23, 38]));
});
});
});
+5 -5
View File
@@ -4,14 +4,14 @@
import { assert, isFunction, isString, isU8a } from '@polkadot/util';
import { StorageFunctionMetadata as MetaV4 } from '../Metadata/v4/Storage';
import { StorageFunctionMetadata as MetaV5 } from '../Metadata/v5/Storage';
import { AnyU8a } from '../types';
import Bytes from './Bytes';
export interface StorageFunction {
(arg?: any): Uint8Array;
headKey?: Uint8Array;
meta: MetaV4;
meta: MetaV5;
method: string;
section: string;
toJSON: () => any;
@@ -30,7 +30,7 @@ type Decoded = {
* constructed by passing in a raw key or a StorageFunction with (optional) arguments.
*/
export default class StorageKey extends Bytes {
private _meta?: MetaV4;
private _meta?: MetaV5;
private _method?: string;
private _outputType?: string;
private _section?: string;
@@ -79,7 +79,7 @@ export default class StorageKey extends Bytes {
throw new Error(`Unable to convert input ${value} to StorageKey`);
}
static getMeta (value: StorageKey | StorageFunction | [StorageFunction, any]): MetaV4 | undefined {
static getMeta (value: StorageKey | StorageFunction | [StorageFunction, any]): MetaV5 | undefined {
if (value instanceof StorageKey) {
return value.meta;
} else if (isFunction(value)) {
@@ -110,7 +110,7 @@ export default class StorageKey extends Bytes {
/**
* @description The metadata or `undefined` when not available
*/
get meta (): MetaV4 | undefined {
get meta (): MetaV5 | undefined {
return this._meta;
}
+8 -8
View File
@@ -9,7 +9,7 @@ import interfaces from '../../../type-jsonrpc/src';
import Method from '../primitive/Method';
import Metadata from '../Metadata';
import rpcdata from '../Metadata/static';
import MetadataV4 from '../Metadata/v4';
import MetadataV5 from '../Metadata/v5';
const ANCHOR_TOP = '';
const LINK_BACK_TO_TOP = '';
@@ -67,7 +67,7 @@ function sortByName<T extends { name: any }> (a: T, b: T): number {
return nameA.localeCompare(nameB);
}
function addEvents (metadata: MetadataV4) {
function addEvents (metadata: MetadataV5) {
const renderHeading = `## ${ANCHOR_TOP}Events${DESC_EVENTS}`;
const orderedSections = metadata.modules.sort(sortByName);
let renderAnchors = '';
@@ -100,7 +100,7 @@ function addEvents (metadata: MetadataV4) {
return renderHeading + renderAnchors + sections;
}
function addExtrinsics (metadata: MetadataV4) {
function addExtrinsics (metadata: MetadataV5) {
const renderHeading = `## ${ANCHOR_TOP}Extrinsics${DESC_EXTRINSICS}`;
const orderedSections = metadata.modules.map((i) => i).sort(sortByName);
let renderAnchors = '';
@@ -132,7 +132,7 @@ function addExtrinsics (metadata: MetadataV4) {
return renderHeading + renderAnchors + sections;
}
function addStorage (metadata: MetadataV4) {
function addStorage (metadata: MetadataV5) {
const renderHeading = `## ${ANCHOR_TOP}Storage${DESC_STORAGE}`;
const orderedSections = metadata.modules.sort(sortByName);
let renderAnchors = '';
@@ -184,22 +184,22 @@ function writeToRpcMd () {
writeFile('docs/METHODS_RPC.md', addRpc());
}
function writeToStorageMd (metadata: MetadataV4) {
function writeToStorageMd (metadata: MetadataV5) {
const options = { flags: 'r', encoding: 'utf8' };
const data = fs.readFileSync('packages/types/src/scripts/METHODS_STORAGE_SUBSTRATE.md', options);
writeFile('docs/METHODS_STORAGE.md', addStorage(metadata), data);
}
function writeToExtrinsicsMd (metadata: MetadataV4) {
function writeToExtrinsicsMd (metadata: MetadataV5) {
writeFile('docs/METHODS_EXTRINSICS.md', addExtrinsics(metadata));
}
function writeToEventsMd (metadata: MetadataV4) {
function writeToEventsMd (metadata: MetadataV5) {
writeFile('docs/METHODS_EVENTS.md', addEvents(metadata));
}
const metadata = new Metadata(rpcdata).asV4;
const metadata = new Metadata(rpcdata).asV5;
writeToRpcMd();
writeToStorageMd(metadata);
+1 -1
View File
@@ -9,7 +9,7 @@ import { blake2AsU8a } from '@polkadot/util-crypto';
import Compact from '../codec/Compact';
import Struct from '../codec/Struct';
import { FunctionMetadata } from '../Metadata/v4/Calls';
import { FunctionMetadata } from '../Metadata/v5/Calls';
import Method from '../primitive/Method';
import Address from '../primitive/Address';
import Hash from '../primitive/Hash';
+1 -1
View File
@@ -5,7 +5,7 @@
import BN from 'bn.js';
import U8a from './codec/U8a';
import { FunctionMetadata } from './Metadata/v4/Calls';
import { FunctionMetadata } from './Metadata/v5/Calls';
import Method from './primitive/Method';
import Address from './primitive/Address';