Support new versioned metadata format (#632)
* Start something... * Parsing via proxy (everything still all-ok) * Imp[ort order (minor) * WIP expanding the structure * Adjust V1 structure * Parsing seems to do the trick... * Add CodeHash and Schedule types * //v0/ -> /v0/ * Update Extrinsic.ts * Updated with compact outerDispatch, non-throw construction * v1 to V0 conversion * Bubble non-magic errors in constructor * Update e2e after testing them * Bump version with CHANGELOG (potentially breaking change)
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
# 0.41.1
|
||||
|
||||
- Support the V1 metadata specification from Substrate in addition to the currently testnet-active V0 version
|
||||
|
||||
# 0.40.1
|
||||
|
||||
- The API interfaces now require a WS-compatible provider, e.g. subscription support is a must. Previously the HTTPProvider could be use (although it was very limited in the interactions).
|
||||
|
||||
+1
-1
@@ -9,5 +9,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "0.40.26"
|
||||
"version": "0.41.0"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/api-derive",
|
||||
"version": "0.40.26",
|
||||
"version": "0.41.0",
|
||||
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -31,8 +31,8 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@polkadot/api": "^0.40.26",
|
||||
"@polkadot/types": "^0.40.26",
|
||||
"@polkadot/api": "^0.41.0",
|
||||
"@polkadot/types": "^0.41.0",
|
||||
"@types/memoizee": "^0.4.2",
|
||||
"@types/rx": "^4.1.1",
|
||||
"memoizee": "^0.4.14",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/api",
|
||||
"version": "0.40.26",
|
||||
"version": "0.41.0",
|
||||
"description": "An RxJS wrapper around the Polkadot JS RPC",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -30,12 +30,12 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@polkadot/api-derive": "^0.40.26",
|
||||
"@polkadot/extrinsics": "^0.40.26",
|
||||
"@polkadot/rpc-provider": "^0.40.26",
|
||||
"@polkadot/rpc-rx": "^0.40.26",
|
||||
"@polkadot/storage": "^0.40.26",
|
||||
"@polkadot/types": "^0.40.26",
|
||||
"@polkadot/api-derive": "^0.41.0",
|
||||
"@polkadot/extrinsics": "^0.41.0",
|
||||
"@polkadot/rpc-provider": "^0.41.0",
|
||||
"@polkadot/rpc-rx": "^0.41.0",
|
||||
"@polkadot/storage": "^0.41.0",
|
||||
"@polkadot/types": "^0.41.0",
|
||||
"@types/rx": "^4.1.1",
|
||||
"rxjs": "^6.3.3"
|
||||
}
|
||||
|
||||
@@ -300,8 +300,8 @@ export default abstract class ApiBase<OnCall> implements ApiBaseInterface<OnCall
|
||||
this._runtimeVersion = await this._rpcBase.chain.getRuntimeVersion();
|
||||
this._genesisHash = await this._rpcBase.chain.getBlockHash(0);
|
||||
|
||||
const extrinsics = extrinsicsFromMeta(this.runtimeMetadata);
|
||||
const storage = storageFromMeta(this.runtimeMetadata);
|
||||
const extrinsics = extrinsicsFromMeta(this.runtimeMetadata.asV0);
|
||||
const storage = storageFromMeta(this.runtimeMetadata.asV0);
|
||||
|
||||
this._extrinsics = this.decorateExtrinsics(extrinsics, this.onCall);
|
||||
this._query = this.decorateStorage(storage, this.onCall);
|
||||
@@ -312,7 +312,7 @@ export default abstract class ApiBase<OnCall> implements ApiBaseInterface<OnCall
|
||||
this._rx.query = this.decorateStorage(storage, rxOnCall);
|
||||
this._rx.derive = this.decorateDerive(this._rx as ApiInterface$Rx, rxOnCall);
|
||||
|
||||
Event.injectMetadata(this.runtimeMetadata);
|
||||
Event.injectMetadata(this.runtimeMetadata.asV0);
|
||||
Method.injectMethods(extrinsics);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -54,7 +54,7 @@ describe.skip('e2e queries', () => {
|
||||
|
||||
it('subscribes to queries (default)', (done) => {
|
||||
api.query.staking.validatorPreferences(keyring.ferdie.address(), (prefs) => {
|
||||
expect(prefs.unstakeThreshold.toNumber()).toBe(12);
|
||||
expect(prefs.unstakeThreshold.toNumber()).toBe(3);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/rpc-core",
|
||||
"version": "0.40.26",
|
||||
"version": "0.41.0",
|
||||
"description": "A JavaScript wrapper for the Polkadot JsonRPC interface",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -30,9 +30,9 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/rpc-core#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@polkadot/jsonrpc": "^0.40.26",
|
||||
"@polkadot/rpc-provider": "^0.40.26",
|
||||
"@polkadot/types": "^0.40.26",
|
||||
"@polkadot/jsonrpc": "^0.41.0",
|
||||
"@polkadot/rpc-provider": "^0.41.0",
|
||||
"@polkadot/types": "^0.41.0",
|
||||
"@polkadot/util": "^0.33.36"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/rpc-provider",
|
||||
"version": "0.40.26",
|
||||
"version": "0.41.0",
|
||||
"description": "Transport providers for the API",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -31,7 +31,7 @@
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@polkadot/keyring": "^0.33.36",
|
||||
"@polkadot/storage": "^0.40.26",
|
||||
"@polkadot/storage": "^0.41.0",
|
||||
"@polkadot/util": "^0.33.36",
|
||||
"@polkadot/util-crypto": "^0.33.36",
|
||||
"@types/nock": "^9.3.0",
|
||||
|
||||
@@ -11,7 +11,7 @@ import interfaces from '@polkadot/jsonrpc/index';
|
||||
import testKeyring from '@polkadot/keyring/testing';
|
||||
import storage from '@polkadot/storage/static';
|
||||
import { Codec } from '@polkadot/types/types';
|
||||
import metadata from '@polkadot/types/Metadata/static';
|
||||
import metadata from '@polkadot/types/Metadata/v0/static';
|
||||
import { Header } from '@polkadot/types/index';
|
||||
import { bnToU8a, logger, u8aToHex } from '@polkadot/util';
|
||||
import { randomAsU8a } from '@polkadot/util-crypto';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/rpc-rx",
|
||||
"version": "0.40.26",
|
||||
"version": "0.41.0",
|
||||
"description": "An RxJs wrapper around the Polkadot JS API",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -30,8 +30,8 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/rpc-rx#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@polkadot/rpc-core": "^0.40.26",
|
||||
"@polkadot/rpc-provider": "^0.40.26",
|
||||
"@polkadot/rpc-core": "^0.41.0",
|
||||
"@polkadot/rpc-provider": "^0.41.0",
|
||||
"@types/rx": "^4.1.1",
|
||||
"rxjs": "^6.3.3"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/extrinsics",
|
||||
"version": "0.40.26",
|
||||
"version": "0.41.0",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/api.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
@@ -11,7 +11,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@polkadot/types": "^0.40.26",
|
||||
"@polkadot/types": "^0.41.0",
|
||||
"@polkadot/util": "^0.33.36"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { Extrinsic, Metadata } from '@polkadot/types/index';
|
||||
import json from '@polkadot/types/Metadata/static';
|
||||
import json from '@polkadot/types/Metadata/v0/static';
|
||||
|
||||
import fromMetadata from './fromMetadata';
|
||||
|
||||
// Use the pre-generated metadata
|
||||
const metadata = new Metadata(json);
|
||||
const metadata = new Metadata(json).asV0;
|
||||
const newExtrinsics = fromMetadata(metadata);
|
||||
|
||||
describe('fromMetadata', () => {
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { RuntimeModuleMetadata } from '@polkadot/types/Metadata/Modules';
|
||||
import { RuntimeModuleMetadata } from '@polkadot/types/Metadata/v0/Modules';
|
||||
import { Methods, ModulesWithMethods } from '@polkadot/types/Method';
|
||||
import { Metadata } from '@polkadot/types/index';
|
||||
import MetadataV0 from '@polkadot/types/Metadata/v0';
|
||||
|
||||
import { stringCamelCase } from '@polkadot/util';
|
||||
|
||||
@@ -18,7 +18,7 @@ import extrinsics from './index';
|
||||
* @param extrinsics - An extrinsics object to be extended.
|
||||
* @param metadata - The metadata to extend the storage object against.
|
||||
*/
|
||||
export default function fromMetadata (metadata: Metadata): ModulesWithMethods {
|
||||
export default function fromMetadata (metadata: MetadataV0): ModulesWithMethods {
|
||||
let indexCount = -1;
|
||||
|
||||
const findIndex = (prefix: string): number => {
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import metadataRpc from '@polkadot/types/Metadata/static';
|
||||
import Metadata from '@polkadot/types/Metadata';
|
||||
import { Metadata } from '@polkadot/types/index';
|
||||
import metadataRpc from '@polkadot/types/Metadata/v0/static';
|
||||
|
||||
import fromMetadata from './fromMetadata';
|
||||
|
||||
export default fromMetadata(
|
||||
new Metadata(metadataRpc)
|
||||
new Metadata(metadataRpc).asV0
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { FunctionMetadata } from '@polkadot/types/Metadata/Modules';
|
||||
import { FunctionMetadata } from '@polkadot/types/Metadata/v0/Modules';
|
||||
import { MethodFunction } from '@polkadot/types/Method';
|
||||
import { Method } from '@polkadot/types/index';
|
||||
import { assert } from '@polkadot/util';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/jsonrpc",
|
||||
"version": "0.40.26",
|
||||
"version": "0.41.0",
|
||||
"description": "Method definitions for the Polkadot RPC layer",
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/storage",
|
||||
"version": "0.40.26",
|
||||
"version": "0.41.0",
|
||||
"description": "Generic wrapper wrapper around state storage",
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
@@ -31,7 +31,7 @@
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@polkadot/keyring": "^0.33.36",
|
||||
"@polkadot/types": "^0.40.26",
|
||||
"@polkadot/types": "^0.41.0",
|
||||
"@polkadot/util": "^0.33.36",
|
||||
"@polkadot/util-crypto": "^0.33.36"
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
// 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 '@polkadot/types/Metadata';
|
||||
import json from '@polkadot/types/Metadata/static';
|
||||
import { Metadata } from '@polkadot/types/index';
|
||||
import json from '@polkadot/types/Metadata/v0/static';
|
||||
|
||||
import fromMetadata from './fromMetadata';
|
||||
|
||||
// Use the pre-generated metadata
|
||||
const metadata = new Metadata(json);
|
||||
const metadata = new Metadata(json).asV0;
|
||||
const newStorage = fromMetadata(metadata);
|
||||
|
||||
describe('fromMetadata', () => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import { ModuleStorage, Storage } from './types';
|
||||
|
||||
import Metadata from '@polkadot/types/Metadata';
|
||||
import MetadataV0 from '@polkadot/types/Metadata/v0';
|
||||
import { stringLowerFirst } from '@polkadot/util';
|
||||
|
||||
import createFunction from './utils/createFunction';
|
||||
@@ -17,7 +17,7 @@ import storage from './index';
|
||||
* @param storage - A storage object to be extended.
|
||||
* @param metadata - The metadata to extend the storage object against.
|
||||
*/
|
||||
export default function fromMetadata (metadata: Metadata): Storage {
|
||||
export default function fromMetadata (metadata: MetadataV0): Storage {
|
||||
return metadata.modules.reduce((result, moduleMetadata) => {
|
||||
if (moduleMetadata.storage.isNone) {
|
||||
return result;
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import metadataRpc from '@polkadot/types/Metadata/static';
|
||||
import Metadata from '@polkadot/types/Metadata';
|
||||
import { Metadata } from '@polkadot/types/index';
|
||||
import metadataRpc from '@polkadot/types/Metadata/v0/static';
|
||||
|
||||
import fromMetadata from './fromMetadata';
|
||||
|
||||
export default fromMetadata(
|
||||
new Metadata(metadataRpc)
|
||||
new Metadata(metadataRpc).asV0
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { StorageFunctionMetadata, StorageFunctionModifier, StorageFunctionType } from '@polkadot/types/Metadata/Modules';
|
||||
import { StorageFunctionMetadata, StorageFunctionModifier, StorageFunctionType } from '@polkadot/types/Metadata/v0/Modules';
|
||||
import { StorageFunction } from '@polkadot/types/StorageKey';
|
||||
import Text from '@polkadot/types/Text';
|
||||
import Vector from '@polkadot/types/codec/Vector';
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import Compact from '@polkadot/types/codec/Compact';
|
||||
import { createType } from '@polkadot/types/codec';
|
||||
import { StorageFunctionMetadata } from '@polkadot/types/Metadata/Modules';
|
||||
import { StorageFunctionMetadata } from '@polkadot/types/Metadata/v0/Modules';
|
||||
import { StorageFunction } from '@polkadot/types/StorageKey';
|
||||
import { Text } from '@polkadot/types/index';
|
||||
import { assert, isNull, isUndefined, stringLowerFirst, stringToU8a, u8aConcat } from '@polkadot/util';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/types",
|
||||
"version": "0.40.26",
|
||||
"version": "0.41.0",
|
||||
"description": "Implementation of the Parity codec",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
|
||||
@@ -10,8 +10,8 @@ import Struct from './codec/Struct';
|
||||
import Tuple from './codec/Tuple';
|
||||
import U8aFixed from './codec/U8aFixed';
|
||||
import { TypeDef, getTypeClass, getTypeDef } from './codec/createType';
|
||||
import Metadata from './Metadata';
|
||||
import { EventMetadata } from './Metadata/Events';
|
||||
import MetadataV0 from './Metadata/v0';
|
||||
import { EventMetadata } from './Metadata/v0/Events';
|
||||
import Null from './Null';
|
||||
|
||||
const EventTypes: { [index: string]: Constructor<EventData> } = {};
|
||||
@@ -119,7 +119,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 {
|
||||
static injectMetadata (metadata: MetadataV0): void {
|
||||
metadata.events.forEach((section, sectionIndex) => {
|
||||
const sectionName = stringCamelCase(section.name.toString());
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ import AccountId from './AccountId';
|
||||
import Event from './Event';
|
||||
import EventRecord from './EventRecord';
|
||||
import Metadata from './Metadata';
|
||||
import metadataRpc from './Metadata/static';
|
||||
import metadataRpc from './Metadata/v0/static';
|
||||
|
||||
describe('EventRecord', () => {
|
||||
beforeEach(() => {
|
||||
Event.injectMetadata(
|
||||
new Metadata(metadataRpc)
|
||||
new Metadata(metadataRpc).asV0
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import Struct from './codec/Struct';
|
||||
import Address from './Address';
|
||||
import ExtrinsicSignature from './ExtrinsicSignature';
|
||||
import Hash from './Hash';
|
||||
import { FunctionMetadata } from './Metadata/Modules';
|
||||
import { FunctionMetadata } from './Metadata/v0/Modules';
|
||||
import Method from './Method';
|
||||
|
||||
type ExtrinsicValue = {
|
||||
|
||||
@@ -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 MagicNumber, { MAGIC_NUMBER } from './MagicNumber';
|
||||
|
||||
describe('MagicNumber', () => {
|
||||
it('succeeds when the magic number matches', () => {
|
||||
expect(() => new MagicNumber(MAGIC_NUMBER)).not.toThrow();
|
||||
});
|
||||
|
||||
it('fails when the magic number missmatches', () => {
|
||||
expect(() => new MagicNumber(0x12345)).toThrow(/MagicNumber/);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
// 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 U32 from '../U32';
|
||||
import { assert } from '@polkadot/util';
|
||||
|
||||
export const MAGIC_NUMBER = new U32(0x6174656d); // `meta`, reversed for LE encoding
|
||||
export const MAGIC_ERROR = -61746;
|
||||
|
||||
export default class MagicNumber extends U32 {
|
||||
constructor (value?: any) {
|
||||
super(value);
|
||||
|
||||
assert(this.eq(MAGIC_NUMBER), `MagicNumber: expected ${MAGIC_NUMBER.toHex()}, found ${this.toHex()}`, MAGIC_ERROR);
|
||||
}
|
||||
}
|
||||
@@ -8,27 +8,27 @@ import createType from '../codec/createType';
|
||||
import Method from '../Method';
|
||||
|
||||
import Metadata from './index';
|
||||
import latestParsed from './latest.substrate.json';
|
||||
import latestParsed from './v1/latest.substrate.v1.json';
|
||||
import rpcData from './static';
|
||||
|
||||
describe('Metadata', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
|
||||
it('decodes latest properly', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
const str = JSON.stringify(metadata.toJSON());
|
||||
|
||||
console.error(str);
|
||||
console.error(metadata.getUniqTypes());
|
||||
|
||||
expect(metadata.events.length).not.toBe(0);
|
||||
expect(metadata.version).toBe(1);
|
||||
expect(metadata.asV1.modules.length).not.toBe(0);
|
||||
expect(str).toEqual(JSON.stringify(latestParsed));
|
||||
});
|
||||
|
||||
describe('storage with default values', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
Method.injectMethods(extrinsicsFromMeta(metadata.asV0));
|
||||
|
||||
Method.injectMethods(extrinsicsFromMeta(metadata));
|
||||
|
||||
metadata.modules.forEach((mod) => {
|
||||
metadata.asV1.modules.forEach((mod) => {
|
||||
if (mod.storage.isNone) {
|
||||
return;
|
||||
}
|
||||
@@ -42,4 +42,13 @@ describe('Metadata', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('converts v1 to V0', () => {
|
||||
const v0 = metadata.asV0;
|
||||
const str = JSON.stringify(metadata.toJSON());
|
||||
|
||||
console.error(str);
|
||||
|
||||
expect(metadata.getUniqTypes()).toEqual(v0.getUniqTypes());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
// 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 { assert, isUndefined } from '@polkadot/util';
|
||||
|
||||
import EnumType from '../codec/EnumType';
|
||||
import Struct from '../codec/Struct';
|
||||
import Null from '../Null';
|
||||
import MetadataV0 from './v0';
|
||||
import MetadataV1 from './v1';
|
||||
import v1ToV0 from './v1/toV0';
|
||||
import MagicNumber from './MagicNumber';
|
||||
|
||||
class MetadataEnum extends EnumType<Null | MetadataV1> {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
MetadataV0, // once rolled-out, can replace this with Null
|
||||
MetadataV1
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the wrapped values as a V0 object
|
||||
*/
|
||||
get asV0 (): MetadataV0 {
|
||||
return this.value as MetadataV0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the wrapped values as a V1 object
|
||||
*/
|
||||
get asV1 (): MetadataV1 {
|
||||
return this.value as MetadataV1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The version this metadata represents
|
||||
*/
|
||||
get version (): number {
|
||||
return this.index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name MetadataVersioned
|
||||
* @description
|
||||
* The versioned runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class MetadataVersioned extends Struct implements MetadataInterface {
|
||||
private _convertedV0?: MetadataV0;
|
||||
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
magicNumber: MagicNumber,
|
||||
metadata: MetadataEnum
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
*/
|
||||
get magicNumber (): MagicNumber {
|
||||
return this.get('magicNumber') as MagicNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the metadata wrapped
|
||||
*/
|
||||
private get metadata (): MetadataEnum {
|
||||
return this.get('metadata') as MetadataEnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the metadata version this structure represents
|
||||
*/
|
||||
get version (): number {
|
||||
return this.metadata.index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the wrapped metadata as a V0 object
|
||||
*/
|
||||
get asV0 (): MetadataV0 {
|
||||
if (this.metadata.version === 0) {
|
||||
return this.metadata.asV0;
|
||||
}
|
||||
|
||||
assert(this.metadata.version === 1, `Cannot convert metadata from v${this.metadata.version} to v0`);
|
||||
|
||||
if (isUndefined(this._convertedV0)) {
|
||||
this._convertedV0 = v1ToV0(this.metadata.asV1);
|
||||
}
|
||||
|
||||
return this._convertedV0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the wrapped values as a V1 object
|
||||
*/
|
||||
get asV1 (): MetadataV1 {
|
||||
assert(this.metadata.version === 1, `Cannot convert metadata from v${this.metadata.version} to v1`);
|
||||
|
||||
return this.metadata.asV1;
|
||||
}
|
||||
|
||||
getUniqTypes (): Array<string> {
|
||||
return (this.metadata.value as any as MetadataInterface).getUniqTypes();
|
||||
}
|
||||
}
|
||||
@@ -2,161 +2,43 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { assert, hexToU8a, isHex, isU8a, isUndefined } from '@polkadot/util';
|
||||
import { isHex, hexToU8a, u8aConcat } from '@polkadot/util';
|
||||
|
||||
import { getTypeDef, TypeDef, TypeDefInfo } from '../codec/createType';
|
||||
import Compact from '../codec/Compact';
|
||||
import Struct from '../codec/Struct';
|
||||
import Vector from '../codec/Vector';
|
||||
import { OuterDispatchMetadata, OuterDispatchCall } from './Calls';
|
||||
import { OuterEventMetadata, OuterEventMetadataEvent } from './Events';
|
||||
import { RuntimeModuleMetadata } from './Modules';
|
||||
|
||||
// Decodes the runtime metadata as passed through from the `state_getMetadata` call. This
|
||||
// file is probably best understood from the bottom-up, i.e. start reading right at the
|
||||
// end and work up. (Just so we don't use before definition)
|
||||
|
||||
// Quick and dirty flatten (.flat() not available)
|
||||
function flattenUniq (list: Array<any>): Array<any> {
|
||||
const flat = list.reduce((result, entry) => {
|
||||
return result.concat(
|
||||
Array.isArray(entry)
|
||||
? flattenUniq(entry)
|
||||
: entry
|
||||
);
|
||||
}, []);
|
||||
|
||||
return [...new Set(flat)]
|
||||
.filter((value: any) => value)
|
||||
.sort();
|
||||
}
|
||||
import { MAGIC_ERROR, MAGIC_NUMBER } from './MagicNumber';
|
||||
import MetadataVersioned from './MetadataVersioned';
|
||||
|
||||
/**
|
||||
* @name Metadata
|
||||
* @description
|
||||
* The runtime metadata as a decoded structure
|
||||
* The versioned runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class Metadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
outerEvent: OuterEventMetadata,
|
||||
modules: Vector.with(RuntimeModuleMetadata),
|
||||
outerDispatch: OuterDispatchMetadata
|
||||
}, Metadata.decodeMetadata(value));
|
||||
export default class Metadata extends MetadataVersioned {
|
||||
constructor (value?: Uint8Array | string) {
|
||||
super(Metadata.decodeMetadata(value));
|
||||
}
|
||||
|
||||
static decodeMetadata (value: string | Uint8Array | object): object | Uint8Array {
|
||||
if (isHex(value)) {
|
||||
// We receive this as an hex in the JSON output from the Node.
|
||||
// Convert to u8a and use the U8a version to do the actual parsing.
|
||||
return Metadata.decodeMetadata(hexToU8a(value));
|
||||
} else if (isU8a(value)) {
|
||||
// HACK 13 Oct 2018 - For current running BBQ nodes, Metadata is not properly
|
||||
// encoded, it does not have a length prefix. For latest substrate master, it
|
||||
// is properly encoded. Here we pull the prefix, check it agianst the length -
|
||||
// if matches, then we have the length, otherwise we assume it is an older node
|
||||
// and use the whole buffer
|
||||
const [offset, length] = Compact.decodeU8a(value);
|
||||
// first we try and parse using the versioned structure, if this does fail,
|
||||
// we adjust with the magic number and a manual version and re-try. As soon as
|
||||
// we remove support for V0, we will just do a new here
|
||||
private static decodeMetadata (_value: Uint8Array | string = new Uint8Array()): MetadataVersioned {
|
||||
const value = isHex(_value)
|
||||
? hexToU8a(_value)
|
||||
: _value;
|
||||
|
||||
return value.length === (offset + length.toNumber())
|
||||
? value.subarray(offset)
|
||||
: value;
|
||||
try {
|
||||
return new MetadataVersioned(value);
|
||||
} catch (error) {
|
||||
if (error.code !== MAGIC_ERROR) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Decode as normal struct
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Wrapped [[OuterDispatchCall]]
|
||||
*/
|
||||
get calls (): Vector<OuterDispatchCall> {
|
||||
return (this.get('outerDispatch') as OuterDispatchMetadata).calls;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Wrapped [[OuterEventMetadataEvent]]
|
||||
*/
|
||||
get events (): Vector<OuterEventMetadataEvent> {
|
||||
return (this.get('outerEvent') as OuterEventMetadata).events;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Wrapped [[RuntimeModuleMetadata]]
|
||||
*/
|
||||
get modules (): Vector<RuntimeModuleMetadata> {
|
||||
return this.get('modules') as Vector<RuntimeModuleMetadata>;
|
||||
}
|
||||
|
||||
private get argNames () {
|
||||
return this.modules.map((module) =>
|
||||
module.module.call.functions.map((fn) =>
|
||||
fn.arguments.map((argument) => argument.type.toString())
|
||||
return new MetadataVersioned(
|
||||
u8aConcat(
|
||||
MAGIC_NUMBER.toU8a(), // manually add the magic number
|
||||
Uint8Array.from([0]), // add the version for the original
|
||||
value // the actual data as retrieved
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private get eventNames () {
|
||||
return this.events.map((module) =>
|
||||
module.events.map((event) =>
|
||||
event.arguments.map((argument) => argument.toString())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private get storageNames () {
|
||||
return this.modules.map((module) =>
|
||||
module.storage.isSome
|
||||
? module.storage.unwrap().functions.map((fn) =>
|
||||
fn.type.isMap
|
||||
? [fn.type.asMap.key.toString(), fn.type.asMap.value.toString()]
|
||||
: [fn.type.asType.toString()]
|
||||
)
|
||||
: []
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Helper to retrieve a list of all type that are found, sorted and de-deuplicated
|
||||
*/
|
||||
getUniqTypes (): Array<string> {
|
||||
const types = flattenUniq([this.argNames, this.eventNames, this.storageNames]);
|
||||
|
||||
this.validateTypes(types);
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
private validateTypes (types: Array<string>): void {
|
||||
const extractTypes = (types: Array<string>): Array<any> => {
|
||||
return types.map((type) => {
|
||||
const decoded = getTypeDef(type);
|
||||
|
||||
switch (decoded.info) {
|
||||
case TypeDefInfo.Plain:
|
||||
return decoded.type;
|
||||
|
||||
case TypeDefInfo.Compact:
|
||||
case TypeDefInfo.Option:
|
||||
case TypeDefInfo.Vector:
|
||||
return extractTypes([(decoded.sub as TypeDef).type]);
|
||||
|
||||
case TypeDefInfo.Tuple:
|
||||
return extractTypes(
|
||||
(decoded.sub as Array<TypeDef>).map((sub) => sub.type)
|
||||
);
|
||||
|
||||
default:
|
||||
throw new Error('Unreachable');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const allTypes = require('../index');
|
||||
const missing = flattenUniq(extractTypes(types)).filter((type) =>
|
||||
isUndefined(allTypes[type])
|
||||
);
|
||||
|
||||
assert(missing.length === 0, `Unknown types found, no types for ${missing}`);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
// 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.
|
||||
|
||||
export interface MetadataInterface {
|
||||
getUniqTypes (): Array<string>;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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.
|
||||
|
||||
// Quick and dirty flatten (.flat() not available)
|
||||
export default function flattenUniq (list: Array<any>): Array<any> {
|
||||
const flat = list.reduce((result, entry) => {
|
||||
return result.concat(
|
||||
Array.isArray(entry)
|
||||
? flattenUniq(entry)
|
||||
: entry
|
||||
);
|
||||
}, []);
|
||||
|
||||
return [...new Set(flat)]
|
||||
.filter((value: any) => value)
|
||||
.sort();
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
export { default as flattenUniq } from './flattenUniq';
|
||||
export { default as validateTypes } from './validateTypes';
|
||||
@@ -0,0 +1,41 @@
|
||||
// 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 { assert, isUndefined } from '@polkadot/util';
|
||||
|
||||
import { getTypeDef, TypeDef, TypeDefInfo } from '../../codec/createType';
|
||||
import flattenUniq from './flattenUniq';
|
||||
|
||||
export default function validateTypes (types: Array<string>): void {
|
||||
const extractTypes = (types: Array<string>): Array<any> => {
|
||||
return types.map((type) => {
|
||||
const decoded = getTypeDef(type);
|
||||
|
||||
switch (decoded.info) {
|
||||
case TypeDefInfo.Plain:
|
||||
return decoded.type;
|
||||
|
||||
case TypeDefInfo.Compact:
|
||||
case TypeDefInfo.Option:
|
||||
case TypeDefInfo.Vector:
|
||||
return extractTypes([(decoded.sub as TypeDef).type]);
|
||||
|
||||
case TypeDefInfo.Tuple:
|
||||
return extractTypes(
|
||||
(decoded.sub as Array<TypeDef>).map((sub) => sub.type)
|
||||
);
|
||||
|
||||
default:
|
||||
throw new Error('Unreachable');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const allTypes = require('../../index');
|
||||
const missing = flattenUniq(extractTypes(types)).filter((type) =>
|
||||
isUndefined(allTypes[type])
|
||||
);
|
||||
|
||||
assert(missing.length === 0, `Unknown types found, no types for ${missing}`);
|
||||
}
|
||||
@@ -2,10 +2,10 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import Struct from '../codec/Struct';
|
||||
import Vector from '../codec/Vector';
|
||||
import Text from '../Text';
|
||||
import U16 from '../U16';
|
||||
import Struct from '../../codec/Struct';
|
||||
import Vector from '../../codec/Vector';
|
||||
import Text from '../../Text';
|
||||
import U16 from '../../U16';
|
||||
|
||||
export class OuterDispatchCall extends Struct {
|
||||
constructor (value?: any) {
|
||||
@@ -2,11 +2,11 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import Struct from '../codec/Struct';
|
||||
import Tuple from '../codec/Tuple';
|
||||
import Vector from '../codec/Vector';
|
||||
import Text from '../Text';
|
||||
import Type from '../Type';
|
||||
import Struct from '../../codec/Struct';
|
||||
import Tuple from '../../codec/Tuple';
|
||||
import Vector from '../../codec/Vector';
|
||||
import Text from '../../Text';
|
||||
import Type from '../../Type';
|
||||
|
||||
export class EventMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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 extrinsicsFromMeta from '@polkadot/extrinsics/fromMetadata';
|
||||
|
||||
import createType from '../../codec/createType';
|
||||
import Method from '../../Method';
|
||||
|
||||
import Metadata from './index';
|
||||
import latestParsed from './latest.substrate.json';
|
||||
import rpcData from './static';
|
||||
|
||||
describe('Metadata', () => {
|
||||
it('decodes latest properly', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
const str = JSON.stringify(metadata.toJSON());
|
||||
|
||||
console.error(str);
|
||||
console.error(metadata.getUniqTypes());
|
||||
|
||||
expect(metadata.events.length).not.toBe(0);
|
||||
expect(str).toEqual(JSON.stringify(latestParsed));
|
||||
});
|
||||
|
||||
describe('storage with default values', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
|
||||
Method.injectMethods(extrinsicsFromMeta(metadata));
|
||||
|
||||
metadata.modules.forEach((mod) => {
|
||||
if (mod.storage.isNone) {
|
||||
return;
|
||||
}
|
||||
|
||||
mod.storage.unwrap().functions.forEach((fn) => {
|
||||
it(`creates default types for ${mod.prefix}.${fn.name}, type ${fn.type}`, () => {
|
||||
expect(
|
||||
() => createType(fn.type.toString(), fn.default)
|
||||
).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+10
-10
@@ -2,17 +2,17 @@
|
||||
// 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 { AnyNumber } from '../../types';
|
||||
|
||||
import Bytes from '../Bytes';
|
||||
import Enum from '../codec/Enum';
|
||||
import EnumType from '../codec/EnumType';
|
||||
import Option from '../codec/Option';
|
||||
import Struct from '../codec/Struct';
|
||||
import Vector from '../codec/Vector';
|
||||
import Text from '../Text';
|
||||
import Type from '../Type';
|
||||
import U16 from '../U16';
|
||||
import Bytes from '../../Bytes';
|
||||
import Enum from '../../codec/Enum';
|
||||
import EnumType from '../../codec/EnumType';
|
||||
import Option from '../../codec/Option';
|
||||
import Struct from '../../codec/Struct';
|
||||
import Vector from '../../codec/Vector';
|
||||
import Text from '../../Text';
|
||||
import Type from '../../Type';
|
||||
import U16 from '../../U16';
|
||||
|
||||
export class FunctionArgumentMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
@@ -0,0 +1,116 @@
|
||||
// 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 { hexToU8a, isHex, isU8a } from '@polkadot/util';
|
||||
|
||||
import Compact from '../../codec/Compact';
|
||||
import Struct from '../../codec/Struct';
|
||||
import Vector from '../../codec/Vector';
|
||||
import { flattenUniq, validateTypes } from '../util';
|
||||
import { OuterDispatchMetadata, OuterDispatchCall } from './Calls';
|
||||
import { OuterEventMetadata, OuterEventMetadataEvent } from './Events';
|
||||
import { RuntimeModuleMetadata } from './Modules';
|
||||
|
||||
// Decodes the runtime metadata as passed through from the `state_getMetadata` call. This
|
||||
// file is probably best understood from the bottom-up, i.e. start reading right at the
|
||||
// end and work up. (Just so we don't use before definition)
|
||||
|
||||
/**
|
||||
* @name MetadataV0
|
||||
* @description
|
||||
* The runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class MetadataV0 extends Struct implements MetadataInterface {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
outerEvent: OuterEventMetadata,
|
||||
modules: Vector.with(RuntimeModuleMetadata),
|
||||
outerDispatch: OuterDispatchMetadata
|
||||
}, MetadataV0.decodeMetadata(value));
|
||||
}
|
||||
|
||||
static decodeMetadata (value: string | Uint8Array | object): object | Uint8Array {
|
||||
if (isHex(value)) {
|
||||
// We receive this as an hex in the JSON output from the Node.
|
||||
// Convert to u8a and use the U8a version to do the actual parsing.
|
||||
return MetadataV0.decodeMetadata(hexToU8a(value));
|
||||
} else if (isU8a(value)) {
|
||||
// HACK 13 Oct 2018 - For current running BBQ nodes, Metadata is not properly
|
||||
// encoded, it does not have a length prefix. For latest substrate master, it
|
||||
// is properly encoded. Here we pull the prefix, check it agianst the length -
|
||||
// if matches, then we have the length, otherwise we assume it is an older node
|
||||
// and use the whole buffer
|
||||
const [offset, length] = Compact.decodeU8a(value);
|
||||
|
||||
return value.length === (offset + length.toNumber())
|
||||
? value.subarray(offset)
|
||||
: value;
|
||||
}
|
||||
|
||||
// Decode as normal struct
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Wrapped [[OuterDispatchCall]]
|
||||
*/
|
||||
get calls (): Vector<OuterDispatchCall> {
|
||||
return (this.get('outerDispatch') as OuterDispatchMetadata).calls;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Wrapped [[OuterEventMetadataEvent]]
|
||||
*/
|
||||
get events (): Vector<OuterEventMetadataEvent> {
|
||||
return (this.get('outerEvent') as OuterEventMetadata).events;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Wrapped [[RuntimeModuleMetadata]]
|
||||
*/
|
||||
get modules (): Vector<RuntimeModuleMetadata> {
|
||||
return this.get('modules') as Vector<RuntimeModuleMetadata>;
|
||||
}
|
||||
|
||||
private get argNames () {
|
||||
return this.modules.map((module) =>
|
||||
module.module.call.functions.map((fn) =>
|
||||
fn.arguments.map((argument) => argument.type.toString())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private get eventNames () {
|
||||
return this.events.map((module) =>
|
||||
module.events.map((event) =>
|
||||
event.arguments.map((argument) => argument.toString())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private get storageNames () {
|
||||
return this.modules.map((module) =>
|
||||
module.storage.isSome
|
||||
? module.storage.unwrap().functions.map((fn) =>
|
||||
fn.type.isMap
|
||||
? [fn.type.asMap.key.toString(), fn.type.asMap.value.toString()]
|
||||
: [fn.type.asType.toString()]
|
||||
)
|
||||
: []
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Helper to retrieve a list of all type that are found, sorted and de-deuplicated
|
||||
*/
|
||||
getUniqTypes (): Array<string> {
|
||||
const types = flattenUniq([this.argNames, this.eventNames, this.storageNames]);
|
||||
|
||||
validateTypes(types);
|
||||
|
||||
return types;
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,129 @@
|
||||
// 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 '../../Text';
|
||||
|
||||
import { flattenUniq, validateTypes } from '../util';
|
||||
import { EventMetadata } from '../v0/Events';
|
||||
import { CallMetadata, StorageMetadata } from '../v0/Modules';
|
||||
import { OuterDispatchCall } from './outerDispatch';
|
||||
|
||||
class RuntimeModuleMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
prefix: Text,
|
||||
storage: Option.with(StorageMetadata),
|
||||
calls: CallMetadata,
|
||||
outerDispatch: Option.with(OuterDispatchCall),
|
||||
events: Vector.with(EventMetadata)
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module call
|
||||
*/
|
||||
get calls (): CallMetadata {
|
||||
return this.get('calls') as CallMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module events
|
||||
*/
|
||||
get events (): Vector<EventMetadata> {
|
||||
return this.get('events') as Vector<EventMetadata>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module name
|
||||
*/
|
||||
get name (): Text {
|
||||
return this.get('name') as Text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the outer dispatch
|
||||
*/
|
||||
get outerDispatch (): Option<OuterDispatchCall> {
|
||||
return this.get('outerDispatch') as Option<OuterDispatchCall>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module name
|
||||
*/
|
||||
get prefix (): Text {
|
||||
return this.get('prefix') as Text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the associated module storage
|
||||
*/
|
||||
get storage (): Option<StorageMetadata> {
|
||||
return this.get('storage') as Option<StorageMetadata>;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name MetadataV1
|
||||
* @description
|
||||
* The runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class MetadataV1 extends Struct implements MetadataInterface {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
modules: Vector.with(RuntimeModuleMetadata)
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The associated modules for this structure
|
||||
*/
|
||||
get modules (): Vector<RuntimeModuleMetadata> {
|
||||
return this.get('modules') as Vector<RuntimeModuleMetadata>;
|
||||
}
|
||||
|
||||
private get callNames () {
|
||||
return this.modules.map((module) =>
|
||||
module.calls.functions.map((fn) =>
|
||||
fn.arguments.map((argument) => argument.type.toString())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private get eventNames () {
|
||||
return this.modules.map((module) =>
|
||||
module.events.map((event) =>
|
||||
event.arguments.map((argument) => argument.toString())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private get storageNames () {
|
||||
return this.modules.map((module) =>
|
||||
module.storage.isSome
|
||||
? module.storage.unwrap().functions.map((fn) =>
|
||||
fn.type.isMap
|
||||
? [fn.type.asMap.key.toString(), fn.type.asMap.value.toString()]
|
||||
: [fn.type.asType.toString()]
|
||||
)
|
||||
: []
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Helper to retrieve a list of all type that are found, sorted and de-deuplicated
|
||||
*/
|
||||
getUniqTypes (): Array<string> {
|
||||
const types = flattenUniq([this.callNames, this.eventNames, this.storageNames]);
|
||||
|
||||
validateTypes(types);
|
||||
|
||||
return types;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
// 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 Struct from '../../codec/Struct';
|
||||
import Text from '../../Text';
|
||||
import U16 from '../../U16';
|
||||
|
||||
export class OuterDispatchCall extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
index: U16
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The [[U16]] index for the call
|
||||
*/
|
||||
get index (): U16 {
|
||||
return this.get('index') as U16;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The name for the call
|
||||
*/
|
||||
get name (): Text {
|
||||
return this.get('name') as Text;
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,63 @@
|
||||
// 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 { OuterDispatchCall, OuterDispatchMetadata } from '../v0/Calls';
|
||||
import { OuterEventMetadata, OuterEventMetadataEvent } from '../v0/Events';
|
||||
import { RuntimeModuleMetadata, ModuleMetadata } from '../v0/Modules';
|
||||
|
||||
import MetadataV0 from '../v0';
|
||||
import MetadataV1 from './index';
|
||||
|
||||
function modulesV0 (v1: MetadataV1): Array<RuntimeModuleMetadata> {
|
||||
return v1.modules.map((mod) => {
|
||||
return new RuntimeModuleMetadata({
|
||||
prefix: mod.prefix,
|
||||
module: new ModuleMetadata({
|
||||
name: 'Module',
|
||||
call: mod.calls
|
||||
}),
|
||||
storage: mod.storage.isNone
|
||||
? null
|
||||
: mod.storage.unwrap()
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function outerDispatchV0 (v1: MetadataV1): OuterDispatchMetadata {
|
||||
return new OuterDispatchMetadata({
|
||||
name: 'Call',
|
||||
calls: v1.modules
|
||||
.filter((mod) => mod.outerDispatch.isSome)
|
||||
.map((mod) => {
|
||||
const dispatch = mod.outerDispatch.unwrap();
|
||||
|
||||
return new OuterDispatchCall({
|
||||
name: dispatch.name,
|
||||
prefix: mod.prefix,
|
||||
index: dispatch.index
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function outerEventV0 (v1: MetadataV1): OuterEventMetadata {
|
||||
return new OuterEventMetadata({
|
||||
name: 'Event',
|
||||
events: v1.modules.map((mod) =>
|
||||
new OuterEventMetadataEvent([mod.prefix, mod.events])
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
export default function toV0 (v1: MetadataV1): MetadataV0 {
|
||||
const outerEvent = outerEventV0(v1);
|
||||
const modules = modulesV0(v1);
|
||||
const outerDispatch = outerDispatchV0(v1);
|
||||
|
||||
return new MetadataV0({
|
||||
outerEvent,
|
||||
modules,
|
||||
outerDispatch
|
||||
});
|
||||
}
|
||||
@@ -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, FunctionArgumentMetadata } from './Metadata/Modules';
|
||||
import { FunctionMetadata, FunctionArgumentMetadata } from './Metadata/v0/Modules';
|
||||
|
||||
interface ArgsDef {
|
||||
[index: string]: Constructor;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { AnyU8a } from './types';
|
||||
import { isFunction } from '@polkadot/util';
|
||||
|
||||
import Bytes from './Bytes';
|
||||
import { StorageFunctionMetadata } from './Metadata/Modules';
|
||||
import { StorageFunctionMetadata } from './Metadata/v0/Modules';
|
||||
|
||||
export interface StorageFunction {
|
||||
(arg?: any): Uint8Array;
|
||||
|
||||
@@ -102,6 +102,13 @@ export default class EnumType<T> extends Base<Codec> implements Codec {
|
||||
return 1 + this.raw.encodedLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The index of the metadata value
|
||||
*/
|
||||
get index (): number {
|
||||
return this._index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the Enum points to a [[Null]] type
|
||||
*/
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
const fs = require('fs');
|
||||
|
||||
import Metadata from '../Metadata';
|
||||
import rpcdata from '../Metadata/static';
|
||||
import rpcdata from '../Metadata/v0/static';
|
||||
|
||||
function metadataStringifyAsJson () {
|
||||
const decoded = new Metadata(rpcdata);
|
||||
const decoded = new Metadata(rpcdata).asV0;
|
||||
|
||||
return JSON.stringify(decoded.toJSON(), null, 2);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ import { stringCamelCase, stringLowerFirst } from '@polkadot/util';
|
||||
|
||||
import interfaces from '../../../type-jsonrpc/src';
|
||||
import Metadata from '../Metadata';
|
||||
import rpcdata from '../Metadata/static';
|
||||
import MetadataV0 from '../Metadata/v0';
|
||||
import rpcdata from '../Metadata/v0/static';
|
||||
import Method from '../Method';
|
||||
|
||||
const ANCHOR_TOP = `<a id='top' style='text-decoration: none;'>`;
|
||||
@@ -22,7 +23,7 @@ function sectionLink (sectionName: string) {
|
||||
return `- **[${stringCamelCase(sectionName)}](#${stringCamelCase(sectionName)})**\n\n`;
|
||||
}
|
||||
|
||||
function generateSectionLinks (sectionName: string, metadata: Metadata) {
|
||||
function generateSectionLinks (sectionName: string, metadata: MetadataV0) {
|
||||
switch (sectionName) {
|
||||
case 'events':
|
||||
return metadata.events.map((i) => i).sort().map((data: any) =>
|
||||
@@ -81,7 +82,7 @@ function sortExtrinsicsSectionMethods (a: any, b: any) {
|
||||
return nameA.localeCompare(nameB);
|
||||
}
|
||||
|
||||
function addEvents (metadata: Metadata) {
|
||||
function addEvents (metadata: MetadataV0) {
|
||||
const renderHeading = `## ${ANCHOR_TOP}Events${DESC_EVENTS}`;
|
||||
const orderedSections = metadata.events.map((i) => i).sort();
|
||||
const renderAnchors = generateSectionLinks('events', metadata);
|
||||
@@ -108,7 +109,7 @@ function addEvents (metadata: Metadata) {
|
||||
}, renderHeading + renderAnchors);
|
||||
}
|
||||
|
||||
function addExtrinsics (metadata: Metadata) {
|
||||
function addExtrinsics (metadata: MetadataV0) {
|
||||
const renderHeading = `## ${ANCHOR_TOP}Extrinsics${DESC_EXTRINSICS}`;
|
||||
const orderedSections = metadata.modules.map((i) => i).sort();
|
||||
const renderAnchors = generateSectionLinks('extrinsics', metadata);
|
||||
@@ -134,7 +135,7 @@ function addExtrinsics (metadata: Metadata) {
|
||||
}, renderHeading + renderAnchors);
|
||||
}
|
||||
|
||||
function addStorage (metadata: Metadata) {
|
||||
function addStorage (metadata: MetadataV0) {
|
||||
const renderHeading = `## ${ANCHOR_TOP}Storage${DESC_STORAGE}`;
|
||||
const orderedSections = metadata.modules.sort();
|
||||
const renderAnchors = generateSectionLinks('storage', metadata) + sectionLink('substrate');
|
||||
@@ -179,22 +180,22 @@ function writeToRpcMd () {
|
||||
writeFile('docs/METHODS_RPC.md', addRpc());
|
||||
}
|
||||
|
||||
function writeToStorageMd (metadata: Metadata) {
|
||||
function writeToStorageMd (metadata: MetadataV0) {
|
||||
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: Metadata) {
|
||||
function writeToExtrinsicsMd (metadata: MetadataV0) {
|
||||
writeFile('docs/METHODS_EXTRINSICS.md', addExtrinsics(metadata));
|
||||
}
|
||||
|
||||
function writeToEventsMd (metadata: Metadata) {
|
||||
function writeToEventsMd (metadata: MetadataV0) {
|
||||
writeFile('docs/METHODS_EVENTS.md', addEvents(metadata));
|
||||
}
|
||||
|
||||
const metadata = new Metadata(rpcdata);
|
||||
const metadata = new Metadata(rpcdata).asV0;
|
||||
|
||||
writeToRpcMd();
|
||||
writeToStorageMd(metadata);
|
||||
|
||||
Reference in New Issue
Block a user