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:
co-authored by
Amaury Martiny
parent
7bd2fcd7f9
commit
e4a97d4efd
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -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';
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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) => {
|
||||
|
||||
@@ -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,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]));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user