refactor: Metadata overhaul (#913)
* Replace part1 * Replace part2 * Replace part3 * Replace part5 * Replace part6 * Fix small bugs * Fix double map toString * Small fixes * Update to v4 * Fix docs script * Grumbles * Alphabetical * Reads better * comment * module to modul
This commit is contained in:
@@ -424,7 +424,7 @@ export default abstract class ApiBase<CodecResult, SubscriptionResult> implement
|
||||
|
||||
injectNodeCompat(this._runtimeVersion as RuntimeVersion);
|
||||
|
||||
const extrinsics = extrinsicsFromMeta(this.runtimeMetadata.asV0);
|
||||
const extrinsics = extrinsicsFromMeta(this.runtimeMetadata);
|
||||
const storage = storageFromMeta(this.runtimeMetadata);
|
||||
|
||||
this._extrinsics = this.decorateExtrinsics(extrinsics, this.onCall);
|
||||
|
||||
@@ -3,78 +3,94 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
import storage from '@plugnet/storage/static';
|
||||
import fromMetadata from '@plugnet/storage/fromMetadata';
|
||||
import { Storage } from '@plugnet/storage/types';
|
||||
import Metadata from '@plugnet/types/Metadata';
|
||||
import rpcMetadataV3 from '@plugnet/types/Metadata/v3/static';
|
||||
import rpcMetadataV4 from '@plugnet/types/Metadata/v4/static';
|
||||
|
||||
import Api from '.';
|
||||
|
||||
const ADDR_ONE = '5DkQbYAExs3M2sZgT1Ec3mKfZnAQCL4Dt9beTCknkCUn5jzo';
|
||||
const ADDR_TWO = '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF';
|
||||
|
||||
const ENC_ONE = '0x4af2c53fce3ec33c6ccccf22e926f1a7';
|
||||
const ENC_TWO = '0x3e62f7ed6e788e1337bce2a97b68a12a';
|
||||
function formattingTests (version: string, storage: Storage, encodedValues: [String, String]) {
|
||||
const [ENC_ONE, ENC_TWO] = encodedValues;
|
||||
|
||||
describe('formatting', () => {
|
||||
let api: Api;
|
||||
let provider: any;
|
||||
describe(`formatting with Metadata ${version}`, () => {
|
||||
let api: Api;
|
||||
let provider: any;
|
||||
|
||||
beforeEach(() => {
|
||||
provider = {
|
||||
send: jest.fn((method, params) =>
|
||||
Promise.resolve('0x0102')
|
||||
),
|
||||
subscribe: jest.fn((type, method, params, subscription) =>
|
||||
subscription(null, {
|
||||
block: '0x1234',
|
||||
changes: [
|
||||
[ENC_ONE, '0x0102'],
|
||||
[ENC_TWO, '0x0201']
|
||||
]
|
||||
})
|
||||
)
|
||||
};
|
||||
api = new Api(provider);
|
||||
beforeEach(() => {
|
||||
provider = {
|
||||
send: jest.fn((method, params) =>
|
||||
Promise.resolve('0x0102')
|
||||
),
|
||||
subscribe: jest.fn((type, method, params, subscription) =>
|
||||
subscription(null, {
|
||||
block: '0x1234',
|
||||
changes: [
|
||||
[ENC_ONE, '0x0102'],
|
||||
[ENC_TWO, '0x0201']
|
||||
]
|
||||
})
|
||||
)
|
||||
};
|
||||
api = new Api(provider);
|
||||
});
|
||||
|
||||
it('encodes key (with params), decoding response', () => {
|
||||
return api.state
|
||||
.getStorage(
|
||||
[storage.balances.freeBalance, ADDR_ONE]
|
||||
)
|
||||
.then((value) => {
|
||||
expect(
|
||||
provider.send
|
||||
).toHaveBeenCalledWith(
|
||||
'state_getStorage',
|
||||
[ENC_ONE]
|
||||
);
|
||||
expect(value.toNumber()).toEqual(513);
|
||||
});
|
||||
});
|
||||
|
||||
it('encodes multiple keys, decoding multiple results', (done) => {
|
||||
return api.state.subscribeStorage(
|
||||
[
|
||||
[storage.balances.freeBalance, ADDR_ONE],
|
||||
[storage.balances.freeBalance, ADDR_TWO]
|
||||
],
|
||||
(value: any) => {
|
||||
console.error(value);
|
||||
|
||||
expect(
|
||||
provider.subscribe
|
||||
).toHaveBeenCalledWith(
|
||||
'state_storage',
|
||||
'state_subscribeStorage',
|
||||
[[ENC_ONE, ENC_TWO]],
|
||||
expect.anything()
|
||||
);
|
||||
expect(
|
||||
value.map((balance: BN) =>
|
||||
balance.toNumber()
|
||||
)
|
||||
).toEqual([513, 258]);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('encodes key (with params), decoding response', () => {
|
||||
return api.state
|
||||
.getStorage(
|
||||
[storage.balances.freeBalance, ADDR_ONE]
|
||||
)
|
||||
.then((value) => {
|
||||
expect(
|
||||
provider.send
|
||||
).toHaveBeenCalledWith(
|
||||
'state_getStorage',
|
||||
[ENC_ONE]
|
||||
);
|
||||
expect(value.toNumber()).toEqual(513);
|
||||
});
|
||||
});
|
||||
|
||||
it('encodes multiple keys, decoding multiple results', (done) => {
|
||||
return api.state.subscribeStorage(
|
||||
[
|
||||
[storage.balances.freeBalance, ADDR_ONE],
|
||||
[storage.balances.freeBalance, ADDR_TWO]
|
||||
],
|
||||
(value: any) => {
|
||||
console.error(value);
|
||||
|
||||
expect(
|
||||
provider.subscribe
|
||||
).toHaveBeenCalledWith(
|
||||
'state_storage',
|
||||
'state_subscribeStorage',
|
||||
[[ENC_ONE, ENC_TWO]],
|
||||
expect.anything()
|
||||
);
|
||||
expect(
|
||||
value.map((balance: BN) =>
|
||||
balance.toNumber()
|
||||
)
|
||||
).toEqual([513, 258]);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
formattingTests(
|
||||
'v3',
|
||||
fromMetadata(new Metadata(rpcMetadataV3)),
|
||||
['0x4af2c53fce3ec33c6ccccf22e926f1a7', '0x3e62f7ed6e788e1337bce2a97b68a12a']
|
||||
);
|
||||
formattingTests(
|
||||
'v4',
|
||||
fromMetadata(new Metadata(rpcMetadataV4)),
|
||||
['0xec8f96437274a883afcac82d01a9defeb68209cd4f2c084632813692aa5e65ad', '0x1dbb0224910f42a14e7f1406b24c6fe8157296691b02a78756e01946038fffab']
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ import interfaces from '@plugnet/jsonrpc';
|
||||
import testKeyring from '@plugnet/keyring/testing';
|
||||
import storage from '@plugnet/storage/static';
|
||||
import { Codec } from '@plugnet/types/types';
|
||||
import metadata from '@plugnet/types/Metadata/v0/static';
|
||||
import rpcMetadataV4 from '@plugnet/types/Metadata/v4/static';
|
||||
import { Header, RuntimeVersion } from '@plugnet/types';
|
||||
import { bnToU8a, logger, u8aToHex } from '@plugnet/util';
|
||||
import { randomAsU8a } from '@plugnet/util-crypto';
|
||||
@@ -50,7 +50,7 @@ export default class Mock implements ProviderInterface {
|
||||
);
|
||||
},
|
||||
'system_chain': (): string => 'mockChain',
|
||||
'state_getMetadata': (): string => metadata,
|
||||
'state_getMetadata': (): string => rpcMetadataV4,
|
||||
'system_name': (): string => 'mockClient',
|
||||
'system_version': (): string => '9.8.7'
|
||||
};
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/extrinsics 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 { RuntimeModuleMetadata } from '@plugnet/types/Metadata/v0/Modules';
|
||||
import { Methods, ModulesWithMethods } from '@plugnet/types/primitive/Method';
|
||||
import MetadataV0 from '@plugnet/types/Metadata/v0';
|
||||
|
||||
import { stringCamelCase } from '@plugnet/util';
|
||||
|
||||
import createUnchecked from './utils/createUnchecked';
|
||||
import extrinsics from '.';
|
||||
|
||||
/**
|
||||
* Extend a storage object with the storage modules & module functions present
|
||||
* in the metadata.
|
||||
*
|
||||
* @param extrinsics - An extrinsics object to be extended.
|
||||
* @param metadata - The metadata to extend the storage object against.
|
||||
*/
|
||||
export default function fromMetadata (metadata: MetadataV0): ModulesWithMethods {
|
||||
let indexCount = -1;
|
||||
|
||||
const findIndex = (prefix: string): number => {
|
||||
indexCount++;
|
||||
|
||||
const mod = metadata.calls.find((item) => item.prefix.toString() === prefix);
|
||||
|
||||
if (!mod) {
|
||||
console.error(`Unable to find module index for '${prefix}'`);
|
||||
|
||||
// compatible with old versions
|
||||
return indexCount;
|
||||
}
|
||||
|
||||
return mod.index.toNumber();
|
||||
};
|
||||
|
||||
return metadata.modules.reduce((result, meta: RuntimeModuleMetadata) => {
|
||||
if (!meta.module.call || !meta.module.call.functions.length) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const prefix = stringCamelCase(meta.prefix.toString());
|
||||
const index = findIndex(meta.prefix.toString());
|
||||
|
||||
result[prefix] = meta.module.call.functions.reduce((newModule, funcMeta) => {
|
||||
// extrinsics.balances.set_balance -> extrinsics.balances.setBalance
|
||||
const funcName = stringCamelCase(funcMeta.name.toString());
|
||||
|
||||
newModule[funcName] = createUnchecked(prefix, funcName, index, funcMeta);
|
||||
|
||||
return newModule;
|
||||
}, {} as Methods);
|
||||
|
||||
return result;
|
||||
}, { ...extrinsics });
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2017-2019 @polkadot/extrinsics 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 { FunctionMetadata } from '@polkadot/types/Metadata/v4/Calls';
|
||||
import { MethodFunction } from '@polkadot/types/primitive/Method';
|
||||
import { Method } from '@polkadot/types';
|
||||
import { assert, stringCamelCase } from '@polkadot/util';
|
||||
|
||||
/**
|
||||
* From the metadata of a function in the module's storage, generate the function
|
||||
* that will return the an [[MethodFunction]].
|
||||
*
|
||||
* @param section - Name of the module section.
|
||||
* @param sectionIndex - Index of the module section in the modules array.
|
||||
* @param methodIndex - Index of the method inside the section.
|
||||
* @param callMetadata - Metadata of the call function.
|
||||
*/
|
||||
export default function createDescriptor (
|
||||
section: string,
|
||||
sectionIndex: number,
|
||||
methodIndex: number,
|
||||
callMetadata: FunctionMetadata
|
||||
): MethodFunction {
|
||||
const callIndex = new Uint8Array([sectionIndex, methodIndex]);
|
||||
const expectedArgs = callMetadata.args;
|
||||
const funcName = stringCamelCase(callMetadata.name.toString());
|
||||
const extrinsicFn = (...args: any[]): Method => {
|
||||
assert(
|
||||
expectedArgs.length.valueOf() === args.length,
|
||||
`Extrinsic ${section}.${funcName} expects ${expectedArgs.length.valueOf()} arguments, got ${args.length}.`
|
||||
);
|
||||
|
||||
return new Method({
|
||||
args,
|
||||
callIndex
|
||||
}, callMetadata);
|
||||
};
|
||||
|
||||
extrinsicFn.callIndex = callIndex;
|
||||
extrinsicFn.meta = callMetadata;
|
||||
extrinsicFn.method = funcName;
|
||||
extrinsicFn.section = section;
|
||||
extrinsicFn.toJSON = (): any =>
|
||||
callMetadata.toJSON();
|
||||
|
||||
return extrinsicFn as MethodFunction;
|
||||
}
|
||||
+4
-4
@@ -3,13 +3,13 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { Extrinsic, Metadata } from '@plugnet/types';
|
||||
import json from '@plugnet/types/Metadata/v0/static';
|
||||
import json from '@plugnet/types/Metadata/v4/static';
|
||||
|
||||
import fromMetadata from './fromMetadata';
|
||||
import fromV4 from '.';
|
||||
|
||||
// Use the pre-generated metadata
|
||||
const metadata = new Metadata(json).asV0;
|
||||
const newExtrinsics = fromMetadata(metadata);
|
||||
const metadata = new Metadata(json);
|
||||
const newExtrinsics = fromV4(metadata);
|
||||
|
||||
describe('fromMetadata', () => {
|
||||
it('should throw if an incorrect number of args is supplied', () => {
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2017-2019 @polkadot/extrinsics 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 { ModuleMetadata } from '@polkadot/types/Metadata/v4/Metadata';
|
||||
import { Methods, ModulesWithMethods } from '@polkadot/types/primitive/Method';
|
||||
import Metadata from '@polkadot/types/Metadata';
|
||||
import { stringCamelCase } from '@polkadot/util';
|
||||
|
||||
import extrinsics from '../';
|
||||
import createUnchecked from './createUnchecked';
|
||||
|
||||
/**
|
||||
* Extend a storage object with the storage modules & module functions present
|
||||
* in the metadata.
|
||||
*
|
||||
* @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 {
|
||||
return metadata.asV4.modules
|
||||
.filter((modul) => modul.calls.isSome)
|
||||
.reduce((result, modul: ModuleMetadata, sectionIndex) => {
|
||||
const prefix = stringCamelCase(modul.prefix.toString());
|
||||
|
||||
result[prefix] = modul.calls.unwrap().reduce((newModule, callMetadata, methodIndex) => {
|
||||
const funcName = stringCamelCase(callMetadata.name.toString());
|
||||
|
||||
newModule[funcName] = createUnchecked(prefix, sectionIndex, methodIndex, callMetadata);
|
||||
|
||||
return newModule;
|
||||
}, {} as Methods);
|
||||
|
||||
return result;
|
||||
}, { ...extrinsics });
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { Metadata } from '@plugnet/types';
|
||||
import metadataRpc from '@plugnet/types/Metadata/v0/static';
|
||||
import metadataRpc from '@plugnet/types/Metadata/v4/static';
|
||||
import { ModulesWithMethods } from '@plugnet/types/primitive/Method';
|
||||
|
||||
import fromMetadata from './fromMetadata';
|
||||
|
||||
const staticMetadata: ModulesWithMethods = fromMetadata(
|
||||
new Metadata(metadataRpc).asV0
|
||||
new Metadata(metadataRpc)
|
||||
);
|
||||
export default staticMetadata;
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/extrinsics 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 { FunctionMetadata } from '@plugnet/types/Metadata/v0/Modules';
|
||||
import { MethodFunction } from '@plugnet/types/primitive/Method';
|
||||
import { Method } from '@plugnet/types';
|
||||
import { assert } from '@plugnet/util';
|
||||
|
||||
/**
|
||||
* From the metadata of a function in the module's storage, generate the function
|
||||
* that will return the an UncheckExtrinsic.
|
||||
*
|
||||
* @param index - Index of the module section in the modules array.
|
||||
*/
|
||||
export default function createDescriptor (
|
||||
section: string,
|
||||
method: string,
|
||||
index: number,
|
||||
meta: FunctionMetadata
|
||||
): MethodFunction {
|
||||
const callIndex = new Uint8Array([index, meta.id.toNumber()]);
|
||||
let extrinsicFn: any;
|
||||
|
||||
const expectedArgs = Method.filterOrigin(meta);
|
||||
|
||||
extrinsicFn = (...args: any[]): Method => {
|
||||
assert(expectedArgs.length.valueOf() === args.length, `Extrinsic ${section}.${method} expects ${expectedArgs.length.valueOf()} arguments, got ${args.length}.`);
|
||||
|
||||
return new Method({
|
||||
args,
|
||||
callIndex
|
||||
}, meta);
|
||||
};
|
||||
|
||||
extrinsicFn.callIndex = callIndex;
|
||||
extrinsicFn.meta = meta;
|
||||
extrinsicFn.method = method;
|
||||
extrinsicFn.section = section;
|
||||
extrinsicFn.toJSON = (): any =>
|
||||
meta.toJSON();
|
||||
|
||||
return extrinsicFn as MethodFunction;
|
||||
}
|
||||
+4
-4
@@ -26,8 +26,8 @@ describe('createFunction', () => {
|
||||
'authorityCount',
|
||||
{ type: {} } as any,
|
||||
{
|
||||
isUnhashed: true,
|
||||
key: ':auth:len'
|
||||
key: ':auth:len',
|
||||
skipHashing: true
|
||||
}
|
||||
).method
|
||||
).toEqual('authorityCount');
|
||||
@@ -42,8 +42,8 @@ describe('createFunction', () => {
|
||||
'authorityCount',
|
||||
{ type: {} } as any,
|
||||
{
|
||||
isUnhashed: true,
|
||||
key
|
||||
key,
|
||||
skipHashing: true
|
||||
}
|
||||
)()
|
||||
).toEqual(
|
||||
+2
-3
@@ -10,8 +10,8 @@ import { assert, isNull, isUndefined, stringLowerFirst, stringToU8a, u8aConcat }
|
||||
import getHasher from './getHasher';
|
||||
|
||||
export interface CreateItemOptions {
|
||||
isUnhashed?: boolean;
|
||||
key?: string;
|
||||
skipHashing?: boolean; // We don't hash the keys defined in ./substrate.ts
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,14 +52,13 @@ export default function createFunction (section: Text | string, method: Text | s
|
||||
|
||||
// StorageKey is a Bytes, so is length-prefixed
|
||||
return Compact.addLengthPrefix(
|
||||
options.isUnhashed
|
||||
options.skipHashing
|
||||
? key
|
||||
: hasher(key)
|
||||
);
|
||||
};
|
||||
|
||||
if (meta.type.isMap && meta.type.asMap.isLinked) {
|
||||
// TODO: there needs some better way to do this
|
||||
const keyHash = new U8a(hasher(`head of ${stringKey}`));
|
||||
const keyFn: any = () => keyHash;
|
||||
keyFn.meta = new StorageFunctionMetadata({
|
||||
+7
-7
@@ -7,26 +7,26 @@ import { Metadata } from '@plugnet/types';
|
||||
import json from '@plugnet/types/Metadata/v4/static';
|
||||
import { u8aToHex } from '@plugnet/util';
|
||||
|
||||
import fromv4 from '.';
|
||||
import fromMetadata from '.';
|
||||
|
||||
const keyring = testingPairs({ type: 'ed25519' });
|
||||
// Use the pre-generated metadata
|
||||
const metadata = new Metadata(json).asV4;
|
||||
const newStorage = fromv4(metadata);
|
||||
const metadata = new Metadata(json);
|
||||
const storage = fromMetadata(metadata);
|
||||
|
||||
describe('fromv4', () => {
|
||||
describe('fromMetadata', () => {
|
||||
it('should throw if the storage function expects an argument', () => {
|
||||
expect(() => newStorage.balances.freeBalance()).toThrowError(/expects one argument/);
|
||||
expect(() => storage.balances.freeBalance()).toThrowError(/expects one argument/);
|
||||
});
|
||||
|
||||
it('should return a value if the storage function does not expect an argument', () => {
|
||||
expect(() => newStorage.timestamp.now()).not.toThrow();
|
||||
expect(() => storage.timestamp.now()).not.toThrow();
|
||||
});
|
||||
|
||||
it('should return the correct length-prefixed storage key', () => {
|
||||
expect(
|
||||
u8aToHex(
|
||||
newStorage.balances.freeBalance(keyring.alice.address())
|
||||
storage.balances.freeBalance(keyring.alice.address())
|
||||
)
|
||||
).toEqual(
|
||||
'0x807f864e18e3dd8b58386310d2fe0919eef27c6e558564b7f67f22d99d20f587bb'
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/storage 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 { Storage } from '../types';
|
||||
|
||||
import Metadata from '@plugnet/types/Metadata';
|
||||
|
||||
import fromV0 from './v0';
|
||||
import fromV4 from './v4';
|
||||
|
||||
/**
|
||||
* Extend a storage object with the storage modules & module functions present
|
||||
* in the metadata.
|
||||
*
|
||||
* @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 {
|
||||
// For v0-v3 we convert to v0, and use the fromV0 function to parse
|
||||
if ([0, 1, 2, 3].includes(metadata.version)) {
|
||||
return fromV0(metadata.asV0);
|
||||
}
|
||||
|
||||
// For v4, we use fromV4 function
|
||||
return fromV4(metadata.asV4);
|
||||
}
|
||||
@@ -2,6 +2,36 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import fromMetadata from './fromMetadata';
|
||||
import { ModuleStorage, Storage } from '../types';
|
||||
|
||||
export default fromMetadata;
|
||||
import Metadata from '@polkadot/types/Metadata';
|
||||
import { stringLowerFirst } from '@polkadot/util';
|
||||
|
||||
import createFunction from './createFunction';
|
||||
import { storage } from './storage';
|
||||
|
||||
/**
|
||||
* Extend a storage object with the storage modules & module functions present
|
||||
* in the metadata.
|
||||
*
|
||||
* @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 {
|
||||
return metadata.asV4.modules.reduce((result, moduleMetadata) => {
|
||||
if (moduleMetadata.storage.isNone) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const prefix = moduleMetadata.prefix;
|
||||
|
||||
// For access, we change the index names, i.e. Balances.FreeBalance -> balances.freeBalance
|
||||
result[stringLowerFirst(prefix.toString())] = moduleMetadata.storage.unwrap().reduce((newModule, storageFnMeta) => {
|
||||
newModule[stringLowerFirst(storageFnMeta.name.toString())] = createFunction(prefix, storageFnMeta.name, storageFnMeta);
|
||||
|
||||
return newModule;
|
||||
}, {} as ModuleStorage);
|
||||
|
||||
return result;
|
||||
}, { ...storage });
|
||||
}
|
||||
|
||||
+1
-1
@@ -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 { Storage } from '../../types';
|
||||
import { Storage } from '../types';
|
||||
import * as substrate from './substrate';
|
||||
|
||||
export const storage: Storage = {
|
||||
+2
-2
@@ -25,8 +25,8 @@ const createRuntimeFunction = (method: string, key: string, { documentation, typ
|
||||
toJSON: (): any => key
|
||||
} as StorageFunctionMetadata,
|
||||
{
|
||||
isUnhashed: true,
|
||||
key
|
||||
key,
|
||||
skipHashing: true
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/storage 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 { PlainType, StorageFunctionMetadata, StorageFunctionModifier, StorageFunctionType } from '@plugnet/types/Metadata/v0/Storage';
|
||||
import { StorageFunction } from '@plugnet/types/primitive/StorageKey';
|
||||
import { Compact, Text, createType, StorageKey, Bytes, U8a } from '@plugnet/types';
|
||||
import { assert, isNull, isUndefined, stringLowerFirst, stringToU8a, u8aConcat } from '@plugnet/util';
|
||||
import { xxhashAsU8a } from '@plugnet/util-crypto';
|
||||
|
||||
export interface CreateItemOptions {
|
||||
isUnhashed?: boolean;
|
||||
key?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* From the schema of a function in the module's storage, generate the function
|
||||
* that will return the correct storage key.
|
||||
*
|
||||
* @param schema - The function's definition schema to create the function from.
|
||||
* The schema is taken from state_getMetadata.
|
||||
* @param options - Additional options when creating the function. These options
|
||||
* are not known at runtime (from state_getMetadata), they need to be supplied
|
||||
* by us manually at compile time.
|
||||
*/
|
||||
export default function createFunction (section: Text | string, method: Text | string, meta: StorageFunctionMetadata, options: CreateItemOptions = {}): StorageFunction {
|
||||
const stringKey = options.key
|
||||
? options.key
|
||||
: `${section.toString()} ${method.toString()}`;
|
||||
const rawKey = stringToU8a(stringKey);
|
||||
|
||||
// Can only have zero or one argument:
|
||||
// - storage.balances.freeBalance(address)
|
||||
// - storage.timestamp.blockPeriod()
|
||||
const storageFn = (arg?: any): Uint8Array => {
|
||||
let key = rawKey;
|
||||
if (meta.type.isMap) {
|
||||
assert(!isUndefined(arg) && !isNull(arg), `${meta.name} expects one argument`);
|
||||
|
||||
const type = meta.type.asMap.key.toString();
|
||||
const param = createType(type, arg).toU8a(false);
|
||||
|
||||
key = u8aConcat(key, param);
|
||||
}
|
||||
|
||||
// StorageKey is a Bytes, so is length-prefixed
|
||||
return Compact.addLengthPrefix(
|
||||
options.isUnhashed
|
||||
? key
|
||||
: xxhashAsU8a(key, 128)
|
||||
);
|
||||
};
|
||||
|
||||
if (meta.type.isMap && meta.type.asMap.isLinked) {
|
||||
// TODO: there needs some better way to do this
|
||||
const keyHash = new U8a(xxhashAsU8a(`head of ${stringKey}`, 128));
|
||||
const keyFn: any = () => keyHash;
|
||||
keyFn.meta = new StorageFunctionMetadata({
|
||||
name: meta.name,
|
||||
modifier: new StorageFunctionModifier('Required'),
|
||||
type: new StorageFunctionType(new PlainType(meta.type.asMap.key), 0),
|
||||
fallback: new Bytes(),
|
||||
documentation: meta.documentation
|
||||
});
|
||||
storageFn.headKey = new StorageKey(keyFn);
|
||||
}
|
||||
|
||||
storageFn.meta = meta;
|
||||
storageFn.method = stringLowerFirst(method.toString());
|
||||
storageFn.section = stringLowerFirst(section.toString());
|
||||
storageFn.toJSON = (): any => meta.toJSON();
|
||||
|
||||
return storageFn as StorageFunction;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/storage 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 { ModuleStorage, Storage } from '../../types';
|
||||
|
||||
import MetadataV0 from '@plugnet/types/Metadata/v0';
|
||||
import { stringLowerFirst } from '@plugnet/util';
|
||||
|
||||
import createFunction from './createFunction';
|
||||
import { storage } from './storage';
|
||||
|
||||
/**
|
||||
* Extend a storage object with the storage modules & module functions present
|
||||
* in the metadata.
|
||||
*
|
||||
* @param storage - A storage object to be extended.
|
||||
* @param metadata - The metadata to extend the storage object against.
|
||||
*/
|
||||
export default function fromV0 (metadata: MetadataV0): Storage {
|
||||
return metadata.modules.reduce((result, moduleMetadata) => {
|
||||
if (moduleMetadata.storage.isNone) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const prefix = moduleMetadata.storage.unwrap().prefix;
|
||||
|
||||
// For access, we change the index names, i.e. Balances.FreeBalance -> balances.freeBalance
|
||||
result[stringLowerFirst(prefix.toString())] = moduleMetadata.storage.unwrap().functions.reduce((newModule, func) => {
|
||||
newModule[stringLowerFirst(func.name.toString())] = createFunction(prefix, func.name, func);
|
||||
|
||||
return newModule;
|
||||
}, {} as ModuleStorage);
|
||||
|
||||
return result;
|
||||
}, { ...storage });
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/storage 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 { StorageFunctionMetadata, StorageFunctionModifier, StorageFunctionType } from '@plugnet/types/Metadata/v0/Storage';
|
||||
import { StorageFunction } from '@plugnet/types/primitive/StorageKey';
|
||||
import { Text, Vector } from '@plugnet/types';
|
||||
|
||||
import createFunction from './createFunction';
|
||||
|
||||
interface SubstrateMetadata {
|
||||
documentation: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
// Small helper function to factorize code on this page.
|
||||
const createRuntimeFunction = (method: string, key: string, { documentation, type }: SubstrateMetadata): StorageFunction =>
|
||||
createFunction(
|
||||
new Text('Substrate'),
|
||||
new Text(method),
|
||||
{
|
||||
documentation: new Vector(Text, [documentation]),
|
||||
modifier: new StorageFunctionModifier(1), // default
|
||||
type: new StorageFunctionType(type, 0),
|
||||
toJSON: (): any => key
|
||||
} as StorageFunctionMetadata,
|
||||
{
|
||||
isUnhashed: true,
|
||||
key
|
||||
}
|
||||
);
|
||||
|
||||
export const code = createRuntimeFunction('code', ':code', {
|
||||
documentation: 'Wasm code of the runtime.',
|
||||
type: 'Bytes'
|
||||
});
|
||||
|
||||
export const heapPages = createRuntimeFunction('heapPages', ':heappages', {
|
||||
documentation: 'Number of wasm linear memory pages required for execution of the runtime.',
|
||||
type: 'u64'
|
||||
});
|
||||
|
||||
export const authorityCount = createRuntimeFunction('authorityCount', ':auth:len', {
|
||||
documentation: 'Number of authorities.',
|
||||
type: 'u32'
|
||||
});
|
||||
|
||||
export const authorityPrefix = createRuntimeFunction('authorityPrefix', ':auth:', {
|
||||
documentation: 'Prefix under which authorities are stored.',
|
||||
type: 'u32'
|
||||
});
|
||||
|
||||
export const extrinsicIndex = createRuntimeFunction('extrinsicIndex', ':extrinsic_index', {
|
||||
documentation: 'Current extrinsic index (u32) is stored under this key.',
|
||||
type: 'u32'
|
||||
});
|
||||
|
||||
export const changesTrieConfig = createRuntimeFunction('changesTrieConfig', ':changes_trie', {
|
||||
documentation: 'Changes trie configuration is stored under this key.',
|
||||
type: 'u32'
|
||||
});
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/storage 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 { u8aToHex } from '@plugnet/util';
|
||||
import { Metadata } from '@plugnet/types';
|
||||
import json from '@plugnet/types/Metadata/v0/static';
|
||||
|
||||
import fromv0 from '.';
|
||||
|
||||
// Use the pre-generated metadata
|
||||
const metadata = new Metadata(json).asV0;
|
||||
const newStorage = fromv0(metadata);
|
||||
|
||||
describe('fromv0', () => {
|
||||
it('should throw if the storage function expects an argument', () => {
|
||||
expect(() => newStorage.balances.freeBalance()).toThrowError(/expects one argument/);
|
||||
});
|
||||
|
||||
it('should return a value if the storage function does not expect an argument', () => {
|
||||
expect(() => newStorage.timestamp.now()).not.toThrow();
|
||||
});
|
||||
|
||||
it('should return the correct length-prefixed storage key', () => {
|
||||
expect(
|
||||
u8aToHex(
|
||||
newStorage.balances.freeBalance('5DkQbYAExs3M2sZgT1Ec3mKfZnAQCL4Dt9beTCknkCUn5jzo')
|
||||
)
|
||||
).toEqual(
|
||||
'0x404af2c53fce3ec33c6ccccf22e926f1a7'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/storage 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 { stringToU8a, u8aConcat } from '@plugnet/util';
|
||||
|
||||
import createFunction from './createFunction';
|
||||
|
||||
describe('createFunction', () => {
|
||||
it('should create timestamp.now correctly', () => {
|
||||
expect(
|
||||
createFunction(
|
||||
'Timestamp',
|
||||
'Now',
|
||||
{ type: {} } as any
|
||||
)()
|
||||
).toEqual(
|
||||
Uint8Array.from([64, 14, 73, 68, 207, 217, 141, 111, 76, 195, 116, 209, 111, 90, 78, 63, 156]) // Length-prefixed
|
||||
);
|
||||
});
|
||||
|
||||
it('allows overrides on key (keeping name)', () => {
|
||||
expect(
|
||||
createFunction(
|
||||
'Substrate',
|
||||
'authorityCount',
|
||||
{ type: {} } as any,
|
||||
{
|
||||
isUnhashed: true,
|
||||
key: ':auth:len'
|
||||
}
|
||||
).method
|
||||
).toEqual('authorityCount');
|
||||
});
|
||||
|
||||
it('allows overrides on key (unhashed)', () => {
|
||||
const key = ':auth:len';
|
||||
|
||||
expect(
|
||||
createFunction(
|
||||
'Substrate',
|
||||
'authorityCount',
|
||||
{ type: {} } as any,
|
||||
{
|
||||
isUnhashed: true,
|
||||
key
|
||||
}
|
||||
)()
|
||||
).toEqual(
|
||||
u8aConcat(
|
||||
Uint8Array.from([key.length << 2]),
|
||||
stringToU8a(':auth:len')
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,37 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/storage 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 { ModuleStorage, Storage } from '../../types';
|
||||
|
||||
import MetadataV4 from '@plugnet/types/Metadata/v4';
|
||||
import { stringLowerFirst } from '@plugnet/util';
|
||||
|
||||
import createFunction from './createFunction';
|
||||
import { storage } from './storage';
|
||||
|
||||
/**
|
||||
* Extend a storage object with the storage modules & module functions present
|
||||
* in the metadata.
|
||||
*
|
||||
* @param storage - A storage object to be extended.
|
||||
* @param metadata - The metadata to extend the storage object against.
|
||||
*/
|
||||
export default function fromV4 (metadata: MetadataV4): Storage {
|
||||
return metadata.modules.reduce((result, moduleMetadata) => {
|
||||
if (moduleMetadata.storage.isNone) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const prefix = moduleMetadata.prefix;
|
||||
|
||||
// For access, we change the index names, i.e. Balances.FreeBalance -> balances.freeBalance
|
||||
result[stringLowerFirst(prefix.toString())] = moduleMetadata.storage.unwrap().reduce((newModule, storageFnMeta) => {
|
||||
newModule[stringLowerFirst(storageFnMeta.name.toString())] = createFunction(prefix, storageFnMeta.name, storageFnMeta);
|
||||
|
||||
return newModule;
|
||||
}, {} as ModuleStorage);
|
||||
|
||||
return result;
|
||||
}, { ...storage });
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/storage 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 { storage } from './storage';
|
||||
|
||||
describe('storage', () => {
|
||||
it('should return well known keys', () => {
|
||||
expect(typeof storage.substrate).toBe('object');
|
||||
expect(storage.substrate.authorityCount).toBeTruthy();
|
||||
expect(storage.substrate.authorityPrefix).toBeTruthy();
|
||||
expect(storage.substrate.changesTrieConfig).toBeTruthy();
|
||||
expect(storage.substrate.code).toBeTruthy();
|
||||
expect(storage.substrate.extrinsicIndex).toBeTruthy();
|
||||
expect(storage.substrate.heapPages).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/storage 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 { Storage } from '../../types';
|
||||
import * as substrate from './substrate';
|
||||
|
||||
export const storage: Storage = {
|
||||
substrate // Prefill storage with well known keys, as not returned by state_getMetadata
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/storage 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 { authorityCount, authorityPrefix, changesTrieConfig, code, extrinsicIndex, heapPages } from './substrate';
|
||||
|
||||
describe('substrate', () => {
|
||||
it('authorityCount should return the correct storage key', () => {
|
||||
expect(authorityCount()).toEqual(Uint8Array.from([36, 58, 97, 117, 116, 104, 58, 108, 101, 110])); // Length-prefixed
|
||||
});
|
||||
|
||||
it('authorityPrefix should return the correct storage key', () => {
|
||||
expect(authorityPrefix()).toEqual(Uint8Array.from([24, 58, 97, 117, 116, 104, 58])); // Length-prefixed
|
||||
});
|
||||
|
||||
it('changesTrieConfig should return the correct storage key', () => {
|
||||
expect(changesTrieConfig()).toEqual(Uint8Array.from([52, 58, 99, 104, 97, 110, 103, 101, 115, 95, 116, 114, 105, 101])); // Length-prefixed
|
||||
});
|
||||
|
||||
it('code should return the correct storage key', () => {
|
||||
expect(code()).toEqual(Uint8Array.from([20, 58, 99, 111, 100, 101])); // Length-prefixed
|
||||
});
|
||||
|
||||
it('extrinsicIndex should return the correct storage key', () => {
|
||||
expect(extrinsicIndex()).toEqual(
|
||||
Uint8Array.from([64, 58, 101, 120, 116, 114, 105, 110, 115, 105, 99, 95, 105, 110, 100, 101, 120]) // Length-prefixed
|
||||
);
|
||||
});
|
||||
|
||||
it('heapPages should return the correct storage key', () => {
|
||||
expect(heapPages()).toEqual(Uint8Array.from([40, 58, 104, 101, 97, 112, 112, 97, 103, 101, 115])); // Length-prefixed
|
||||
});
|
||||
});
|
||||
@@ -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 { storage } from './fromMetadata/v0/storage';
|
||||
import { storage } from './fromMetadata/storage';
|
||||
|
||||
export default storage;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { Metadata } from '@plugnet/types';
|
||||
import metadataRpc from '@plugnet/types/Metadata/v0/static';
|
||||
import metadataRpc from '@plugnet/types/Metadata/v4/static';
|
||||
|
||||
import fromMetadata from './fromMetadata';
|
||||
|
||||
|
||||
@@ -2,8 +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 { MetadataInterface } from './types';
|
||||
|
||||
import { assert, isUndefined } from '@plugnet/util';
|
||||
|
||||
import EnumType from '../codec/EnumType';
|
||||
@@ -15,10 +13,10 @@ import MetadataV1 from './v1';
|
||||
import MetadataV2 from './v2';
|
||||
import MetadataV3 from './v3';
|
||||
import MetadataV4 from './v4';
|
||||
import v1ToV0 from './v1/toV0';
|
||||
import v2ToV1 from './v2/toV1';
|
||||
import v3ToV2 from './v3/toV2';
|
||||
import v4ToV3 from './v4/toV3';
|
||||
import v0ToV1 from './v0/toV1';
|
||||
import v1ToV2 from './v1/toV2';
|
||||
import v2ToV3 from './v2/toV3';
|
||||
import v3ToV4 from './v3/toV4';
|
||||
|
||||
class MetadataDeprecated extends Null {
|
||||
}
|
||||
@@ -134,11 +132,11 @@ class MetadataEnum extends EnumType<MetadataDeprecated | MetadataV0 | MetadataV1
|
||||
* @description
|
||||
* The versioned runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class MetadataVersioned extends Struct implements MetadataInterface {
|
||||
private _convertedV0?: MetadataV0;
|
||||
export default class MetadataVersioned extends Struct {
|
||||
private _convertedV1?: MetadataV1;
|
||||
private _convertedV2?: MetadataV2;
|
||||
private _convertedV3?: MetadataV3;
|
||||
private _convertedV4?: MetadataV4;
|
||||
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
@@ -172,29 +170,23 @@ export default class MetadataVersioned extends Struct implements MetadataInterfa
|
||||
* @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 === 0, `Cannot convert metadata from v${this.metadata.version} to v0`);
|
||||
|
||||
if (isUndefined(this._convertedV0)) {
|
||||
this._convertedV0 = v1ToV0(this.asV1);
|
||||
}
|
||||
|
||||
return this._convertedV0;
|
||||
return this.metadata.asV0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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`);
|
||||
|
||||
if (this.metadata.version === 1) {
|
||||
return this.metadata.asV1;
|
||||
}
|
||||
|
||||
assert([2, 3, 4].includes(this.metadata.version), `Cannot convert metadata from v${this.metadata.version} to v1`);
|
||||
|
||||
if (isUndefined(this._convertedV1)) {
|
||||
this._convertedV1 = v2ToV1(this.asV2);
|
||||
this._convertedV1 = v0ToV1(this.asV0);
|
||||
}
|
||||
|
||||
return this._convertedV1;
|
||||
@@ -204,14 +196,14 @@ export default class MetadataVersioned extends Struct implements MetadataInterfa
|
||||
* @description Returns the wrapped values as a V2 object
|
||||
*/
|
||||
get asV2 (): MetadataV2 {
|
||||
assert(this.metadata.version <= 2, `Cannot convert metadata from v${this.metadata.version} to v2`);
|
||||
|
||||
if (this.metadata.version === 2) {
|
||||
return this.metadata.asV2;
|
||||
}
|
||||
|
||||
assert([3, 4].includes(this.metadata.version), `Cannot convert metadata from v${this.metadata.version} to v2`);
|
||||
|
||||
if (isUndefined(this._convertedV2)) {
|
||||
this._convertedV2 = v3ToV2(this.asV3);
|
||||
this._convertedV2 = v1ToV2(this.asV1);
|
||||
}
|
||||
|
||||
return this._convertedV2;
|
||||
@@ -221,29 +213,37 @@ export default class MetadataVersioned extends Struct implements MetadataInterfa
|
||||
* @description Returns the wrapped values as a V3 object
|
||||
*/
|
||||
get asV3 (): MetadataV3 {
|
||||
assert(this.metadata.version <= 3, `Cannot convert metadata from v${this.metadata.version} to v3`);
|
||||
|
||||
if (this.metadata.version === 3) {
|
||||
return this.metadata.asV3;
|
||||
}
|
||||
|
||||
assert([4].includes(this.metadata.version), `Cannot convert metadata from v${this.metadata.version} to v3`);
|
||||
|
||||
if (isUndefined(this._convertedV3)) {
|
||||
this._convertedV3 = v4ToV3(this.asV4);
|
||||
this._convertedV3 = v2ToV3(this.asV2);
|
||||
}
|
||||
|
||||
return this._convertedV3;
|
||||
}
|
||||
|
||||
getUniqTypes (throwError: boolean): Array<string> {
|
||||
return (this.metadata.value as any as MetadataInterface).getUniqTypes(throwError);
|
||||
return this.asV4.getUniqTypes(throwError);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the wrapped values as a V3 object
|
||||
* @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 v4`);
|
||||
assert(this.metadata.version <= 4, `Cannot convert metadata from v${this.metadata.version} to v3`);
|
||||
|
||||
return this.metadata.asV4;
|
||||
if (this.metadata.version === 4) {
|
||||
return this.metadata.asV4;
|
||||
}
|
||||
|
||||
if (isUndefined(this._convertedV4)) {
|
||||
this._convertedV4 = v3ToV4(this.asV3);
|
||||
}
|
||||
|
||||
return this._convertedV4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 './v3/static';
|
||||
import metadata from './v4/static';
|
||||
|
||||
export default metadata;
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
// 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 {
|
||||
import { Vector } from '../codec';
|
||||
import { Codec } from '../types';
|
||||
|
||||
export interface MetadataInterface<Modules extends Codec> extends Codec {
|
||||
modules: Vector<Modules>;
|
||||
getUniqTypes (throwError: boolean): Array<string>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 Metadata from '../Metadata';
|
||||
import Method from '../../primitive/Method';
|
||||
import { MetadataInterface } from '../types';
|
||||
import { Codec } from '../../types';
|
||||
|
||||
/**
|
||||
* Given the static `rpcData` and the `latestSubstrate` JSON file, Metadata
|
||||
* should decode `rpcData` and output `latestSubstrate`.
|
||||
*/
|
||||
export function decodeLatestSubstrate<Modules extends Codec> (
|
||||
version: number,
|
||||
rpcData: string,
|
||||
latestSubstrate: object
|
||||
) {
|
||||
it('decodes latest substrate properly', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
|
||||
console.error(JSON.stringify(metadata.toJSON()));
|
||||
|
||||
expect(metadata.version).toBe(version);
|
||||
expect((metadata[`asV${version}` as keyof Metadata] as unknown as MetadataInterface<Modules>).modules.length).not.toBe(0);
|
||||
expect(metadata.toJSON()).toEqual(latestSubstrate);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a `version`, MetadataV4 and MetadataV{version} should output the same
|
||||
* unique types.
|
||||
*/
|
||||
export function toV4<Modules extends Codec> (version: number, rpcData: string) {
|
||||
it('converts to V4', () => {
|
||||
const metadata = new Metadata(rpcData)[`asV${version}` as keyof Metadata];
|
||||
const metadataV4 = new Metadata(rpcData).asV4;
|
||||
|
||||
expect(
|
||||
(metadata as unknown as MetadataInterface<Modules>).getUniqTypes(true)
|
||||
).toEqual(metadataV4.getUniqTypes(true));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a Metadata, no type should throw when given its fallback value.
|
||||
*/
|
||||
export function defaultValues (rpcData: string) {
|
||||
describe('storage with default values', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
Method.injectMethods(extrinsicsFromMeta(metadata));
|
||||
|
||||
metadata.asV4.modules
|
||||
.filter(({ storage }) => storage.isSome)
|
||||
.map((mod) =>
|
||||
mod.storage.unwrap().forEach(({ fallback, name, type }) => {
|
||||
it(`creates default types for ${mod.prefix}.${name}, type ${type}`, () => {
|
||||
expect(
|
||||
() => createType(type.toString(), fallback)
|
||||
).not.toThrow();
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -12,7 +12,7 @@ export class EventMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
arguments: Vector.with(Type),
|
||||
args: Vector.with(Type),
|
||||
documentation: Vector.with(Text)
|
||||
}, value);
|
||||
}
|
||||
@@ -20,8 +20,16 @@ export class EventMetadata extends Struct {
|
||||
/**
|
||||
* @description The arguments of [[Type]]
|
||||
*/
|
||||
get args (): Vector<Type> {
|
||||
return this.get('args') as Vector<Type>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The arguments of [[Type]]
|
||||
* @deprecated Use `.args` instead
|
||||
*/
|
||||
get arguments (): Vector<Type> {
|
||||
return this.get('arguments') as Vector<Type>;
|
||||
return this.args;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,7 +55,7 @@ export class EventMetadata extends Struct {
|
||||
}
|
||||
}
|
||||
|
||||
export class OuterEventMetadataEvent extends Tuple {
|
||||
export class OuterEventEventMetadata extends Tuple {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
Text,
|
||||
@@ -74,15 +82,15 @@ export class OuterEventMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
events: Vector.with(OuterEventMetadataEvent)
|
||||
events: Vector.with(OuterEventEventMetadata)
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The [[OuterEventMetadataEvent]]
|
||||
* @description The [[OuterEventEventMetadata]]
|
||||
*/
|
||||
get events (): Vector<OuterEventMetadataEvent> {
|
||||
return this.get('events') as Vector<OuterEventMetadataEvent>;
|
||||
get events (): Vector<OuterEventEventMetadata> {
|
||||
return this.get('events') as Vector<OuterEventEventMetadata>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,41 +2,32 @@
|
||||
// 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 '@plugnet/extrinsics/fromMetadata';
|
||||
|
||||
import createType from '../../codec/createType';
|
||||
import Method from '../../primitive/Method';
|
||||
|
||||
import Metadata from './Metadata';
|
||||
import latestParsed from './latest.substrate.json';
|
||||
import MetadataV0 from './';
|
||||
import Metadata from '../';
|
||||
import latestSubstrateV0 from './latest.substrate.v0.json';
|
||||
import rpcData from './static';
|
||||
import { defaultValues, toV4 } from '../util/testUtil';
|
||||
|
||||
describe('Metadata', () => {
|
||||
it('decodes latest properly', () => {
|
||||
it('works with fallback', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
const str = JSON.stringify(metadata.toJSON());
|
||||
const metadataV0 = new MetadataV0(rpcData);
|
||||
|
||||
expect(metadata.events.length).not.toBe(0);
|
||||
expect(str).toEqual(JSON.stringify(latestParsed));
|
||||
expect(metadata.asV0.toString()).toEqual(metadataV0.toString());
|
||||
});
|
||||
|
||||
describe('storage with default values', () => {
|
||||
it('decodes latest substrate properly', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
const json = metadata.asV0.toJSON();
|
||||
|
||||
Method.injectMethods(extrinsicsFromMeta(metadata));
|
||||
console.error(JSON.stringify(json));
|
||||
|
||||
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.fallback)
|
||||
).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(metadata.version).toBe(0);
|
||||
expect(metadata.asV0.modules.length).not.toBe(0);
|
||||
expect(json).toEqual(latestSubstrateV0);
|
||||
});
|
||||
|
||||
toV4(0, rpcData);
|
||||
|
||||
defaultValues(rpcData);
|
||||
});
|
||||
|
||||
@@ -11,19 +11,17 @@ 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 { OuterEventMetadata, OuterEventEventMetadata } 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)
|
||||
// Decodes the runtime metadata as passed through from the `state_getMetadata` call.
|
||||
|
||||
/**
|
||||
* @name MetadataV0
|
||||
* @description
|
||||
* The runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class MetadataV0 extends Struct implements MetadataInterface {
|
||||
export default class MetadataV0 extends Struct implements MetadataInterface<RuntimeModuleMetadata> {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
outerEvent: OuterEventMetadata,
|
||||
@@ -62,9 +60,9 @@ export default class MetadataV0 extends Struct implements MetadataInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Wrapped [[OuterEventMetadataEvent]]
|
||||
* @description Wrapped [[OuterEventEventMetadata]]
|
||||
*/
|
||||
get events (): Vector<OuterEventMetadataEvent> {
|
||||
get events (): Vector<OuterEventEventMetadata> {
|
||||
return (this.get('outerEvent') as OuterEventMetadata).events;
|
||||
}
|
||||
|
||||
@@ -76,25 +74,25 @@ export default class MetadataV0 extends Struct implements MetadataInterface {
|
||||
}
|
||||
|
||||
private get argNames () {
|
||||
return this.modules.map((module) =>
|
||||
module.module.call.functions.map((fn) =>
|
||||
fn.arguments.map((argument) => argument.type.toString())
|
||||
return this.modules.map((modul) =>
|
||||
modul.module.call.functions.map((fn) =>
|
||||
fn.args.map((argument) => argument.type.toString())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private get eventNames () {
|
||||
return this.events.map((module) =>
|
||||
module.events.map((event) =>
|
||||
event.arguments.map((argument) => argument.toString())
|
||||
return this.events.map((modul) =>
|
||||
modul.events.map((event) =>
|
||||
event.args.map((argument) => argument.toString())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private get storageNames () {
|
||||
return this.modules.map((module) =>
|
||||
module.storage.isSome
|
||||
? module.storage.unwrap().functions.map((fn) =>
|
||||
return this.modules.map((modul) =>
|
||||
modul.storage.isSome
|
||||
? modul.storage.unwrap().functions.map((fn) =>
|
||||
fn.type.isMap
|
||||
? [fn.type.asMap.key.toString(), fn.type.asMap.value.toString()]
|
||||
: [fn.type.asType.toString()]
|
||||
|
||||
@@ -39,13 +39,21 @@ export class FunctionMetadata extends Struct {
|
||||
super({
|
||||
id: U16,
|
||||
name: Text,
|
||||
arguments: Vector.with(FunctionArgumentMetadata),
|
||||
args: Vector.with(FunctionArgumentMetadata),
|
||||
documentation: Vector.with(Text)
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The arguments of [[Type]]
|
||||
*/
|
||||
get args (): Vector<FunctionArgumentMetadata> {
|
||||
return this.get('args') as Vector<FunctionArgumentMetadata>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The [[FunctionArgumentMetadata]] for arguments
|
||||
* @deprecated Use `.args` instead
|
||||
*/
|
||||
get arguments (): Vector<FunctionArgumentMetadata> {
|
||||
return this.get('arguments') as Vector<FunctionArgumentMetadata>;
|
||||
@@ -103,7 +111,6 @@ export class CallMetadata extends Struct {
|
||||
return this.get('name') as Text;
|
||||
}
|
||||
}
|
||||
|
||||
export class ModuleMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
@@ -113,7 +120,7 @@ export class ModuleMetadata extends Struct {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The calls as [[CallMetadata]]
|
||||
* @description The calls as [[FunctionMetadata]]
|
||||
*/
|
||||
get call (): CallMetadata {
|
||||
return this.get('call') as CallMetadata;
|
||||
|
||||
@@ -11,7 +11,6 @@ import EnumType from '../../codec/EnumType';
|
||||
import Struct from '../../codec/Struct';
|
||||
import Vector from '../../codec/Vector';
|
||||
import Bytes from '../../primitive/Bytes';
|
||||
import Null from '../../primitive/Null';
|
||||
import Text from '../../primitive/Text';
|
||||
import Type from '../../primitive/Type';
|
||||
|
||||
@@ -33,8 +32,6 @@ export class StorageFunctionModifier extends Enum {
|
||||
}
|
||||
}
|
||||
|
||||
export class DoubleMapType extends Null {}
|
||||
|
||||
export class MapType extends Struct {
|
||||
private _isLinked = false;
|
||||
|
||||
@@ -78,20 +75,10 @@ export class StorageFunctionType extends EnumType<PlainType | MapType> {
|
||||
constructor (value?: any, index?: number) {
|
||||
super({
|
||||
PlainType,
|
||||
MapType,
|
||||
DoubleMapType
|
||||
MapType
|
||||
}, 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
|
||||
*/
|
||||
@@ -110,13 +97,6 @@ export class StorageFunctionType extends EnumType<PlainType | MapType> {
|
||||
return this.value as PlainType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description `true` if the storage entry is a double map
|
||||
*/
|
||||
get isDoubleMap (): boolean {
|
||||
return this.toNumber() === 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description `true` if the storage entry is a map
|
||||
*/
|
||||
@@ -135,9 +115,7 @@ export class StorageFunctionType extends EnumType<PlainType | MapType> {
|
||||
* @description Returns the string representation of the value
|
||||
*/
|
||||
toString (): string {
|
||||
if (this.isDoubleMap) {
|
||||
return `DoubleMap<${this.asDoubleMap.toString()}>`;
|
||||
} else if (this.isMap) {
|
||||
if (this.isMap) {
|
||||
if (this.asMap.isLinked) {
|
||||
return `(${this.asMap.value.toString()}, Linkage<${this.asMap.key.toString()}>)`;
|
||||
}
|
||||
|
||||
+85
-85
@@ -7,14 +7,14 @@
|
||||
[
|
||||
{
|
||||
"name": "ExtrinsicSuccess",
|
||||
"arguments": [],
|
||||
"args": [],
|
||||
"documentation": [
|
||||
" An extrinsic completed successfully."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ExtrinsicFailed",
|
||||
"arguments": [],
|
||||
"args": [],
|
||||
"documentation": [
|
||||
" An extrinsic failed."
|
||||
]
|
||||
@@ -26,7 +26,7 @@
|
||||
[
|
||||
{
|
||||
"name": "NewAccount",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"AccountId",
|
||||
"AccountIndex",
|
||||
"NewAccountOutcome"
|
||||
@@ -37,7 +37,7 @@
|
||||
},
|
||||
{
|
||||
"name": "ReapedAccount",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"AccountId"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -46,7 +46,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Transfer",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"AccountId",
|
||||
"AccountId",
|
||||
"Balance",
|
||||
@@ -63,7 +63,7 @@
|
||||
[
|
||||
{
|
||||
"name": "NewSession",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"BlockNumber"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -78,7 +78,7 @@
|
||||
[
|
||||
{
|
||||
"name": "Reward",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Balance"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -87,7 +87,7 @@
|
||||
},
|
||||
{
|
||||
"name": "OfflineWarning",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"AccountId",
|
||||
"u32"
|
||||
],
|
||||
@@ -98,7 +98,7 @@
|
||||
},
|
||||
{
|
||||
"name": "OfflineSlash",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"AccountId",
|
||||
"Balance"
|
||||
],
|
||||
@@ -113,7 +113,7 @@
|
||||
[
|
||||
{
|
||||
"name": "Tabled",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"PropIndex",
|
||||
"Balance",
|
||||
"Vec<AccountId>"
|
||||
@@ -122,7 +122,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Started",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"ReferendumIndex",
|
||||
"VoteThreshold"
|
||||
],
|
||||
@@ -130,28 +130,28 @@
|
||||
},
|
||||
{
|
||||
"name": "Passed",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"ReferendumIndex"
|
||||
],
|
||||
"documentation": []
|
||||
},
|
||||
{
|
||||
"name": "NotPassed",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"ReferendumIndex"
|
||||
],
|
||||
"documentation": []
|
||||
},
|
||||
{
|
||||
"name": "Cancelled",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"ReferendumIndex"
|
||||
],
|
||||
"documentation": []
|
||||
},
|
||||
{
|
||||
"name": "Executed",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"ReferendumIndex",
|
||||
"bool"
|
||||
],
|
||||
@@ -164,7 +164,7 @@
|
||||
[
|
||||
{
|
||||
"name": "NewAuthorities",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Vec<(SessionKey,u64)>"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -178,7 +178,7 @@
|
||||
[
|
||||
{
|
||||
"name": "VoterReaped",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"AccountId",
|
||||
"AccountId"
|
||||
],
|
||||
@@ -188,7 +188,7 @@
|
||||
},
|
||||
{
|
||||
"name": "BadReaperSlashed",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"AccountId"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -197,7 +197,7 @@
|
||||
},
|
||||
{
|
||||
"name": "TallyStarted",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"u32"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -206,7 +206,7 @@
|
||||
},
|
||||
{
|
||||
"name": "TallyFinalised",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Vec<AccountId>",
|
||||
"Vec<AccountId>"
|
||||
],
|
||||
@@ -221,7 +221,7 @@
|
||||
[
|
||||
{
|
||||
"name": "TallyCancelation",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Hash",
|
||||
"u32",
|
||||
"u32",
|
||||
@@ -234,7 +234,7 @@
|
||||
},
|
||||
{
|
||||
"name": "TallyReferendum",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Hash",
|
||||
"u32",
|
||||
"u32",
|
||||
@@ -252,7 +252,7 @@
|
||||
[
|
||||
{
|
||||
"name": "Proposed",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"AccountId",
|
||||
"ProposalIndex",
|
||||
"Hash",
|
||||
@@ -264,7 +264,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Voted",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"AccountId",
|
||||
"Hash",
|
||||
"bool",
|
||||
@@ -278,7 +278,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Approved",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Hash"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -287,7 +287,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Disapproved",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Hash"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -296,7 +296,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Executed",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Hash",
|
||||
"bool"
|
||||
],
|
||||
@@ -311,7 +311,7 @@
|
||||
[
|
||||
{
|
||||
"name": "Proposed",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"ProposalIndex"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -320,7 +320,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Spending",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Balance"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -329,7 +329,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Awarded",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"ProposalIndex",
|
||||
"Balance",
|
||||
"AccountId"
|
||||
@@ -340,7 +340,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Burnt",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Balance"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -349,7 +349,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Rollover",
|
||||
"arguments": [
|
||||
"args": [
|
||||
"Balance"
|
||||
],
|
||||
"documentation": [
|
||||
@@ -468,7 +468,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "set",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "now",
|
||||
"type": "Compact<Moment>"
|
||||
@@ -528,7 +528,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "report_misbehavior",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "_report",
|
||||
"type": "Bytes"
|
||||
@@ -541,7 +541,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "note_offline",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "offline",
|
||||
"type": "InherentOfflineReport"
|
||||
@@ -554,7 +554,7 @@
|
||||
{
|
||||
"id": 2,
|
||||
"name": "remark",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "_remark",
|
||||
"type": "Bytes"
|
||||
@@ -567,7 +567,7 @@
|
||||
{
|
||||
"id": 3,
|
||||
"name": "set_heap_pages",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "pages",
|
||||
"type": "u64"
|
||||
@@ -580,7 +580,7 @@
|
||||
{
|
||||
"id": 4,
|
||||
"name": "set_code",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "new",
|
||||
"type": "Bytes"
|
||||
@@ -593,7 +593,7 @@
|
||||
{
|
||||
"id": 5,
|
||||
"name": "set_storage",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "items",
|
||||
"type": "Vec<KeyValue>"
|
||||
@@ -628,7 +628,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "transfer",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "dest",
|
||||
"type": "Address"
|
||||
@@ -645,7 +645,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "set_balance",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "who",
|
||||
"type": "Address"
|
||||
@@ -800,7 +800,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "set_key",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "key",
|
||||
"type": "SessionKey"
|
||||
@@ -814,7 +814,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "set_length",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "new",
|
||||
"type": "Compact<BlockNumber>"
|
||||
@@ -827,7 +827,7 @@
|
||||
{
|
||||
"id": 2,
|
||||
"name": "force_new_session",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "apply_rewards",
|
||||
"type": "bool"
|
||||
@@ -924,7 +924,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "stake",
|
||||
"arguments": [],
|
||||
"args": [],
|
||||
"documentation": [
|
||||
" Declare the desire to stake for the transactor.",
|
||||
"",
|
||||
@@ -934,7 +934,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "unstake",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "intentions_index",
|
||||
"type": "Compact<u32>"
|
||||
@@ -949,7 +949,7 @@
|
||||
{
|
||||
"id": 2,
|
||||
"name": "nominate",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "Address"
|
||||
@@ -960,7 +960,7 @@
|
||||
{
|
||||
"id": 3,
|
||||
"name": "unnominate",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "target_index",
|
||||
"type": "Compact<u32>"
|
||||
@@ -974,7 +974,7 @@
|
||||
{
|
||||
"id": 4,
|
||||
"name": "register_preferences",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "intentions_index",
|
||||
"type": "Compact<u32>"
|
||||
@@ -993,7 +993,7 @@
|
||||
{
|
||||
"id": 5,
|
||||
"name": "set_sessions_per_era",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "new",
|
||||
"type": "Compact<BlockNumber>"
|
||||
@@ -1006,7 +1006,7 @@
|
||||
{
|
||||
"id": 6,
|
||||
"name": "set_bonding_duration",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "new",
|
||||
"type": "Compact<BlockNumber>"
|
||||
@@ -1019,7 +1019,7 @@
|
||||
{
|
||||
"id": 7,
|
||||
"name": "set_validator_count",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "new",
|
||||
"type": "Compact<u32>"
|
||||
@@ -1032,7 +1032,7 @@
|
||||
{
|
||||
"id": 8,
|
||||
"name": "force_new_era",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "apply_rewards",
|
||||
"type": "bool"
|
||||
@@ -1046,7 +1046,7 @@
|
||||
{
|
||||
"id": 9,
|
||||
"name": "set_offline_slash_grace",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "new",
|
||||
"type": "Compact<u32>"
|
||||
@@ -1261,7 +1261,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "propose",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "proposal",
|
||||
"type": "Proposal"
|
||||
@@ -1278,7 +1278,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "second",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "proposal",
|
||||
"type": "Compact<PropIndex>"
|
||||
@@ -1291,7 +1291,7 @@
|
||||
{
|
||||
"id": 2,
|
||||
"name": "vote",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "ref_index",
|
||||
"type": "Compact<ReferendumIndex>"
|
||||
@@ -1309,7 +1309,7 @@
|
||||
{
|
||||
"id": 3,
|
||||
"name": "start_referendum",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "proposal",
|
||||
"type": "Proposal"
|
||||
@@ -1330,7 +1330,7 @@
|
||||
{
|
||||
"id": 4,
|
||||
"name": "cancel_referendum",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "ref_index",
|
||||
"type": "Compact<ReferendumIndex>"
|
||||
@@ -1343,7 +1343,7 @@
|
||||
{
|
||||
"id": 5,
|
||||
"name": "cancel_queued",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "when",
|
||||
"type": "BlockNumber"
|
||||
@@ -1506,7 +1506,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "report_misbehavior",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "_report",
|
||||
"type": "Bytes"
|
||||
@@ -1541,7 +1541,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "set_approvals",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "votes",
|
||||
"type": "Vec<bool>"
|
||||
@@ -1559,7 +1559,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "reap_inactive_voter",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "reporter_index",
|
||||
"type": "Compact<u32>"
|
||||
@@ -1588,7 +1588,7 @@
|
||||
{
|
||||
"id": 2,
|
||||
"name": "retract_voter",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "index",
|
||||
"type": "Compact<u32>"
|
||||
@@ -1601,7 +1601,7 @@
|
||||
{
|
||||
"id": 3,
|
||||
"name": "submit_candidacy",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "slot",
|
||||
"type": "Compact<u32>"
|
||||
@@ -1616,7 +1616,7 @@
|
||||
{
|
||||
"id": 4,
|
||||
"name": "present_winner",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "candidate",
|
||||
"type": "Address"
|
||||
@@ -1639,7 +1639,7 @@
|
||||
{
|
||||
"id": 5,
|
||||
"name": "set_desired_seats",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "count",
|
||||
"type": "Compact<u32>"
|
||||
@@ -1654,7 +1654,7 @@
|
||||
{
|
||||
"id": 6,
|
||||
"name": "remove_member",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "who",
|
||||
"type": "Address"
|
||||
@@ -1669,7 +1669,7 @@
|
||||
{
|
||||
"id": 7,
|
||||
"name": "set_presentation_duration",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "count",
|
||||
"type": "Compact<BlockNumber>"
|
||||
@@ -1683,7 +1683,7 @@
|
||||
{
|
||||
"id": 8,
|
||||
"name": "set_term_duration",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "count",
|
||||
"type": "Compact<BlockNumber>"
|
||||
@@ -1883,7 +1883,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "propose",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "proposal",
|
||||
"type": "Proposal"
|
||||
@@ -1894,7 +1894,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "vote",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "proposal",
|
||||
"type": "Hash"
|
||||
@@ -1909,7 +1909,7 @@
|
||||
{
|
||||
"id": 2,
|
||||
"name": "veto",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "proposal_hash",
|
||||
"type": "Hash"
|
||||
@@ -1920,7 +1920,7 @@
|
||||
{
|
||||
"id": 3,
|
||||
"name": "set_cooloff_period",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "blocks",
|
||||
"type": "Compact<BlockNumber>"
|
||||
@@ -1931,7 +1931,7 @@
|
||||
{
|
||||
"id": 4,
|
||||
"name": "set_voting_period",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "blocks",
|
||||
"type": "Compact<BlockNumber>"
|
||||
@@ -2020,7 +2020,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "propose",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "threshold",
|
||||
"type": "Compact<u32>"
|
||||
@@ -2035,7 +2035,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "vote",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "proposal",
|
||||
"type": "Hash"
|
||||
@@ -2108,7 +2108,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "propose_spend",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "Compact<Balance>"
|
||||
@@ -2127,7 +2127,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "set_pot",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "new_pot",
|
||||
"type": "Compact<Balance>"
|
||||
@@ -2140,7 +2140,7 @@
|
||||
{
|
||||
"id": 2,
|
||||
"name": "configure",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "proposal_bond",
|
||||
"type": "Permill"
|
||||
@@ -2165,7 +2165,7 @@
|
||||
{
|
||||
"id": 3,
|
||||
"name": "reject_proposal",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "proposal_id",
|
||||
"type": "Compact<ProposalIndex>"
|
||||
@@ -2178,7 +2178,7 @@
|
||||
{
|
||||
"id": 4,
|
||||
"name": "approve_proposal",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "proposal_id",
|
||||
"type": "Compact<ProposalIndex>"
|
||||
@@ -2276,7 +2276,7 @@
|
||||
{
|
||||
"id": 0,
|
||||
"name": "set_heads",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "heads",
|
||||
"type": "Vec<AttestedCandidate>"
|
||||
@@ -2289,7 +2289,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "register_parachain",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "Id"
|
||||
@@ -2311,7 +2311,7 @@
|
||||
{
|
||||
"id": 2,
|
||||
"name": "deregister_parachain",
|
||||
"arguments": [
|
||||
"args": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "Id"
|
||||
File diff suppressed because it is too large
Load Diff
+324
-384
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,60 @@
|
||||
|
||||
// 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 { stringUpperFirst } from '@polkadot/util';
|
||||
|
||||
import { Option, Vector } from '../../codec';
|
||||
import MetadataV0 from './Metadata';
|
||||
import { RuntimeModuleMetadata } from './Modules';
|
||||
import { Text } from '../../primitive';
|
||||
import { FunctionMetadata } from '../v1/Calls';
|
||||
import { EventMetadata } from '../v1/Events';
|
||||
import MetadataV1, { ModuleMetadata } from '../v1/Metadata';
|
||||
import { StorageFunctionMetadata } from '../v1/Storage';
|
||||
|
||||
function toV1Calls (modul: RuntimeModuleMetadata) {
|
||||
return modul.module.call.functions.length === 0
|
||||
? new Option(Vector.with(FunctionMetadata))
|
||||
: new Option(Vector.with(FunctionMetadata), modul.module.call.functions);
|
||||
}
|
||||
|
||||
function toV1Events (metadataV0: MetadataV0, prefix: Text) {
|
||||
const events = metadataV0.events.find((event) => event.name.eq(prefix));
|
||||
|
||||
return events
|
||||
? new Option(Vector.with(EventMetadata), events.events)
|
||||
: new Option(Vector.with(EventMetadata));
|
||||
}
|
||||
|
||||
function toV1Storage (modul: RuntimeModuleMetadata) {
|
||||
return modul.storage.isNone
|
||||
? new Option(Vector.with(StorageFunctionMetadata))
|
||||
: new Option(
|
||||
Vector.with(StorageFunctionMetadata),
|
||||
modul.storage.unwrap().functions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that converts MetadataV0 to MetadataV1
|
||||
*/
|
||||
export default function toV1 (metadataV0: MetadataV0): MetadataV1 {
|
||||
return new MetadataV1({
|
||||
modules: metadataV0.modules.map((modul) => {
|
||||
// The prefix of this module (capitalized)
|
||||
const prefix = modul.storage.isSome
|
||||
? modul.storage.unwrap().prefix.toString()
|
||||
: stringUpperFirst(modul.prefix.toString()); // If this module doesn't have storage, we just assume the prefix is the name capitalized
|
||||
|
||||
return new ModuleMetadata({
|
||||
name: modul.prefix, // Not capitalized
|
||||
prefix, // Capitalized
|
||||
storage: toV1Storage(modul),
|
||||
calls: toV1Calls(modul),
|
||||
events: toV1Events(metadataV0, modul.prefix)
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import Vector from '../../codec/Vector';
|
||||
import Text from '../../primitive/Text';
|
||||
import Type from '../../primitive/Type';
|
||||
|
||||
export class MetadataCallArg extends Struct {
|
||||
export class FunctionArgumentMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
@@ -31,27 +31,24 @@ export class MetadataCallArg extends Struct {
|
||||
}
|
||||
|
||||
/**
|
||||
* @name MetadataCall
|
||||
* @name FunctionMetadata
|
||||
* @description
|
||||
* The definition of a call
|
||||
*/
|
||||
export class MetadataCall extends Struct {
|
||||
export class FunctionMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
// NOTE Just commented out, it is not available in current, but an open question
|
||||
// around the usefulness of supplying this remains (could be re-added)
|
||||
// id: u16,
|
||||
name: Text,
|
||||
args: Vector.with(MetadataCallArg),
|
||||
args: Vector.with(FunctionArgumentMetadata),
|
||||
documentation: Vector.with(Text)
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The [[MetadataCallArg]] for arguments
|
||||
* @description The [[FunctionArgumentMetadata]] for arguments
|
||||
*/
|
||||
get args (): Vector<MetadataCallArg> {
|
||||
return this.get('args') as Vector<MetadataCallArg>;
|
||||
get args (): Vector<FunctionArgumentMetadata> {
|
||||
return this.get('args') as Vector<FunctionArgumentMetadata>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,13 +66,6 @@ export class MetadataCall extends Struct {
|
||||
return this.documentation;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @description The call function id
|
||||
// */
|
||||
// get id (): u16 {
|
||||
// return this.get('id') as u16;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @description The call name
|
||||
*/
|
||||
|
||||
@@ -2,51 +2,5 @@
|
||||
// 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 '../../primitive/Text';
|
||||
import Type from '../../primitive/Type';
|
||||
|
||||
/**
|
||||
* @name MetadataEvent
|
||||
* @description
|
||||
* The definition of an event
|
||||
*/
|
||||
export class MetadataEvent extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
args: Vector.with(Type),
|
||||
documentation: Vector.with(Text)
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The [[Type]] for args
|
||||
*/
|
||||
get args (): Vector<Type> {
|
||||
return this.get('args') as Vector<Type>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 call name
|
||||
*/
|
||||
get name (): Text {
|
||||
return this.get('name') as Text;
|
||||
}
|
||||
}
|
||||
// Re-export classes that haven't changed between V0 and V1
|
||||
export { EventMetadata } from '../v0/Events';
|
||||
|
||||
@@ -2,45 +2,14 @@
|
||||
// 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 '@plugnet/extrinsics/fromMetadata';
|
||||
|
||||
import createType from '../../codec/createType';
|
||||
import Method from '../../primitive/Method';
|
||||
|
||||
import Metadata from '../Metadata';
|
||||
import latestParsed from './latest.substrate.v1.json';
|
||||
import latestSubstrate from './latest.substrate.v1.json';
|
||||
import rpcData from './static';
|
||||
import { decodeLatestSubstrate, defaultValues, toV4 } from '../util/testUtil';
|
||||
|
||||
describe('MetadataV1', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
decodeLatestSubstrate(1, rpcData, latestSubstrate);
|
||||
|
||||
it('decodes latest properly', () => {
|
||||
const str = JSON.stringify(metadata.toJSON());
|
||||
toV4(1, rpcData);
|
||||
|
||||
expect(metadata.version).toBe(1);
|
||||
expect(metadata.asV1.modules.length).not.toBe(0);
|
||||
expect(str).toEqual(JSON.stringify(latestParsed));
|
||||
});
|
||||
|
||||
it('converts v1 to V0', () => {
|
||||
const v0 = metadata.asV0;
|
||||
|
||||
expect(metadata.getUniqTypes(true)).toEqual(v0.getUniqTypes(true));
|
||||
});
|
||||
|
||||
describe('storage with default values', () => {
|
||||
Method.injectMethods(extrinsicsFromMeta(metadata.asV0));
|
||||
|
||||
metadata.asV1.modules
|
||||
.filter(({ storage }) => storage.isSome)
|
||||
.map((mod) =>
|
||||
mod.storage.unwrap().forEach(({ fallback, name, type }) => {
|
||||
it(`creates default types for ${mod.prefix}.${name}, type ${type}`, () => {
|
||||
expect(
|
||||
() => createType(type.toString(), fallback)
|
||||
).not.toThrow();
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
defaultValues(rpcData);
|
||||
});
|
||||
|
||||
@@ -10,38 +10,38 @@ import Vector from '../../codec/Vector';
|
||||
import Text from '../../primitive/Text';
|
||||
import { flattenUniq, validateTypes } from '../util';
|
||||
|
||||
import { MetadataCall } from './Calls';
|
||||
import { MetadataEvent } from './Events';
|
||||
import { FunctionMetadata } from './Calls';
|
||||
import { EventMetadata } from './Events';
|
||||
import { StorageFunctionMetadata } from './Storage';
|
||||
|
||||
/**
|
||||
* @name MetadataModule
|
||||
* @name ModuleMetadata
|
||||
* @description
|
||||
* The definition of a module in the system
|
||||
*/
|
||||
export class MetadataModule extends Struct {
|
||||
export class ModuleMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
prefix: Text,
|
||||
storage: Option.with(Vector.with(StorageFunctionMetadata)),
|
||||
calls: Option.with(Vector.with(MetadataCall)),
|
||||
events: Option.with(Vector.with(MetadataEvent))
|
||||
calls: Option.with(Vector.with(FunctionMetadata)),
|
||||
events: Option.with(Vector.with(EventMetadata))
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module calls
|
||||
*/
|
||||
get calls (): Option<Vector<MetadataCall>> {
|
||||
return this.get('calls') as Option<Vector<MetadataCall>>;
|
||||
get calls (): Option<Vector<FunctionMetadata>> {
|
||||
return this.get('calls') as Option<Vector<FunctionMetadata>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module events
|
||||
*/
|
||||
get events (): Option<Vector<MetadataEvent>> {
|
||||
return this.get('events') as Option<Vector<MetadataEvent>>;
|
||||
get events (): Option<Vector<EventMetadata>> {
|
||||
return this.get('events') as Option<Vector<EventMetadata>>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,18 +71,18 @@ export class MetadataModule extends Struct {
|
||||
* @description
|
||||
* The runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class MetadataV1 extends Struct implements MetadataInterface {
|
||||
export default class MetadataV1 extends Struct implements MetadataInterface<ModuleMetadata> {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
modules: Vector.with(MetadataModule)
|
||||
modules: Vector.with(ModuleMetadata)
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The associated modules for this structure
|
||||
*/
|
||||
get modules (): Vector<MetadataModule> {
|
||||
return this.get('modules') as Vector<MetadataModule>;
|
||||
get modules (): Vector<ModuleMetadata> {
|
||||
return this.get('modules') as Vector<ModuleMetadata>;
|
||||
}
|
||||
|
||||
private get callNames () {
|
||||
|
||||
@@ -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 { default as MetadataV1, MetadataModule as MetadataModuleV1 } from './Metadata';
|
||||
import { default as MetadataV1, ModuleMetadata as ModuleMetadataV1 } from './Metadata';
|
||||
|
||||
export default MetadataV1;
|
||||
|
||||
export {
|
||||
MetadataModuleV1
|
||||
ModuleMetadataV1
|
||||
};
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
// 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 { EventMetadata, OuterEventMetadata, OuterEventMetadataEvent } from '../v0/Events';
|
||||
import { CallMetadata, FunctionMetadata, RuntimeModuleMetadata, ModuleMetadata } from '../v0/Modules';
|
||||
import { StorageFunctionMetadata, StorageMetadata, StorageFunctionType } from '../v0/Storage';
|
||||
|
||||
import MetadataV0 from '../v0/Metadata';
|
||||
import MetadataV1, { MetadataModuleV1 } from '.';
|
||||
|
||||
function storageV0 (mod: MetadataModuleV1): StorageMetadata | null {
|
||||
if (mod.storage.isNone) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new StorageMetadata({
|
||||
prefix: mod.prefix,
|
||||
functions: mod.storage.unwrap().map(({ documentation, fallback, modifier, name, type }) =>
|
||||
new StorageFunctionMetadata({
|
||||
name,
|
||||
modifier: modifier.toNumber(),
|
||||
type: new StorageFunctionType(type),
|
||||
fallback,
|
||||
documentation
|
||||
})
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
function moduleV0 (mod: MetadataModuleV1): ModuleMetadata {
|
||||
return new ModuleMetadata({
|
||||
name: 'Module',
|
||||
call: new CallMetadata({
|
||||
name: 'Call',
|
||||
functions: mod.calls.isNone
|
||||
? []
|
||||
: mod.calls.unwrap().map(({ args, documentation, name }, id) =>
|
||||
new FunctionMetadata({
|
||||
id,
|
||||
name,
|
||||
arguments: args,
|
||||
documentation
|
||||
})
|
||||
)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function modulesV0 (v1: MetadataV1): Array<RuntimeModuleMetadata> {
|
||||
return v1.modules.map((mod) =>
|
||||
new RuntimeModuleMetadata({
|
||||
prefix: mod.name, // passed from name, compact with casing
|
||||
module: moduleV0(mod),
|
||||
storage: storageV0(mod)
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function outerDispatchV0 (v1: MetadataV1): OuterDispatchMetadata {
|
||||
return new OuterDispatchMetadata({
|
||||
name: 'Call',
|
||||
calls: v1.modules
|
||||
.filter(({ calls }) => calls.isSome)
|
||||
.map((mod, index) =>
|
||||
new OuterDispatchCall({
|
||||
// name and prefix are swapped in the actual V0 data, i.e. name is UpperCase
|
||||
name: mod.prefix,
|
||||
prefix: mod.name,
|
||||
index
|
||||
})
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
function outerEventV0 (v1: MetadataV1): OuterEventMetadata {
|
||||
return new OuterEventMetadata({
|
||||
name: 'Event',
|
||||
events: v1.modules
|
||||
.filter(({ events }) => events.isSome)
|
||||
.map((mod) =>
|
||||
new OuterEventMetadataEvent([
|
||||
mod.name,
|
||||
mod.events.unwrap().map(({ args, documentation, name }) =>
|
||||
new EventMetadata({
|
||||
name,
|
||||
arguments: args,
|
||||
documentation
|
||||
})
|
||||
)
|
||||
])
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
export default function toV0 (v1: MetadataV1): MetadataV0 {
|
||||
return new MetadataV0({
|
||||
outerEvent: outerEventV0(v1),
|
||||
modules: modulesV0(v1),
|
||||
outerDispatch: outerDispatchV0(v1)
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// 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 MetadataV1 from './Metadata';
|
||||
import MetadataV2 from '../v2';
|
||||
|
||||
export default function toV2 (metadataV1: MetadataV1): MetadataV2 {
|
||||
return new MetadataV2(metadataV1);
|
||||
}
|
||||
@@ -2,9 +2,8 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import MetadataV3 from '../v3/Metadata';
|
||||
import MetadataV4 from '.';
|
||||
|
||||
export default function toV3 (v4: MetadataV4): MetadataV3 {
|
||||
return new MetadataV3(v4);
|
||||
}
|
||||
// Re-export classes that haven't changed between V1 and V2
|
||||
export {
|
||||
FunctionArgumentMetadata,
|
||||
FunctionMetadata
|
||||
} from '../v1/Calls';
|
||||
@@ -2,9 +2,5 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import MetadataV1 from '../v1/Metadata';
|
||||
import MetadataV2 from '.';
|
||||
|
||||
export default function toV1 (v2: MetadataV2): MetadataV1 {
|
||||
return new MetadataV1(v2);
|
||||
}
|
||||
// Re-export classes that haven't changed between V1 and V2
|
||||
export { EventMetadata } from '../v1/Events';
|
||||
@@ -2,51 +2,14 @@
|
||||
// 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 '@plugnet/extrinsics/fromMetadata';
|
||||
|
||||
import createType from '../../codec/createType';
|
||||
import Method from '../../primitive/Method';
|
||||
|
||||
import Metadata from '../Metadata';
|
||||
import latestParsed from './latest.substrate.v2.json';
|
||||
import latestSubstrate from './latest.substrate.v2.json';
|
||||
import rpcData from './static';
|
||||
import { decodeLatestSubstrate, defaultValues, toV4 } from '../util/testUtil';
|
||||
|
||||
describe('MetadataV2', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
decodeLatestSubstrate(2, rpcData, latestSubstrate);
|
||||
|
||||
it('decodes latest properly', () => {
|
||||
const str = JSON.stringify(metadata.toJSON());
|
||||
toV4(2, rpcData);
|
||||
|
||||
expect(metadata.version).toBe(2);
|
||||
expect(metadata.asV2.modules.length).not.toBe(0);
|
||||
expect(str).toEqual(JSON.stringify(latestParsed));
|
||||
});
|
||||
|
||||
it('converts v2 to V1', () => {
|
||||
const v1 = metadata.asV1;
|
||||
|
||||
expect(metadata.getUniqTypes(true)).toEqual(v1.getUniqTypes(true));
|
||||
});
|
||||
|
||||
it('converts v2 to V0', () => {
|
||||
const v1 = metadata.asV0;
|
||||
|
||||
expect(metadata.getUniqTypes(true)).toEqual(v1.getUniqTypes(true));
|
||||
});
|
||||
|
||||
describe('storage with default values', () => {
|
||||
Method.injectMethods(extrinsicsFromMeta(metadata.asV0));
|
||||
|
||||
metadata.asV2.modules
|
||||
.filter(({ storage }) => storage.isSome)
|
||||
.map((mod) =>
|
||||
mod.storage.unwrap().forEach(({ fallback, name, type }) => {
|
||||
it(`creates default types for ${mod.prefix}.${name}, type ${type}`, () => {
|
||||
expect(
|
||||
() => createType(type.toString(), fallback)
|
||||
).not.toThrow();
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
defaultValues(rpcData);
|
||||
});
|
||||
|
||||
@@ -10,38 +10,38 @@ import Vector from '../../codec/Vector';
|
||||
import Text from '../../primitive/Text';
|
||||
import { flattenUniq, validateTypes } from '../util';
|
||||
|
||||
import { MetadataCall } from '../v1/Calls';
|
||||
import { MetadataEvent } from '../v1/Events';
|
||||
import { FunctionMetadata } from './Calls';
|
||||
import { EventMetadata } from './Events';
|
||||
import { StorageFunctionMetadata } from './Storage';
|
||||
|
||||
/**
|
||||
* @name MetadataModule
|
||||
* @name ModuleMetadata
|
||||
* @description
|
||||
* The definition of a module in the system
|
||||
*/
|
||||
export class MetadataModule extends Struct {
|
||||
export class ModuleMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
prefix: Text,
|
||||
storage: Option.with(Vector.with(StorageFunctionMetadata)),
|
||||
calls: Option.with(Vector.with(MetadataCall)),
|
||||
events: Option.with(Vector.with(MetadataEvent))
|
||||
calls: Option.with(Vector.with(FunctionMetadata)),
|
||||
events: Option.with(Vector.with(EventMetadata))
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module calls
|
||||
*/
|
||||
get calls (): Option<Vector<MetadataCall>> {
|
||||
return this.get('calls') as Option<Vector<MetadataCall>>;
|
||||
get calls (): Option<Vector<FunctionMetadata>> {
|
||||
return this.get('calls') as Option<Vector<FunctionMetadata>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module events
|
||||
*/
|
||||
get events (): Option<Vector<MetadataEvent>> {
|
||||
return this.get('events') as Option<Vector<MetadataEvent>>;
|
||||
get events (): Option<Vector<EventMetadata>> {
|
||||
return this.get('events') as Option<Vector<EventMetadata>>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,18 +71,18 @@ export class MetadataModule extends Struct {
|
||||
* @description
|
||||
* The runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class MetadataV2 extends Struct implements MetadataInterface {
|
||||
export default class MetadataV2 extends Struct implements MetadataInterface<ModuleMetadata> {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
modules: Vector.with(MetadataModule)
|
||||
modules: Vector.with(ModuleMetadata)
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The associated modules for this structure
|
||||
*/
|
||||
get modules (): Vector<MetadataModule> {
|
||||
return this.get('modules') as Vector<MetadataModule>;
|
||||
get modules (): Vector<ModuleMetadata> {
|
||||
return this.get('modules') as Vector<ModuleMetadata>;
|
||||
}
|
||||
|
||||
private get callNames () {
|
||||
|
||||
@@ -11,7 +11,6 @@ import Struct from '../../codec/Struct';
|
||||
import Vector from '../../codec/Vector';
|
||||
import Bool from '../../primitive/Bool';
|
||||
import Bytes from '../../primitive/Bytes';
|
||||
import Null from '../../primitive/Null';
|
||||
import Text from '../../primitive/Text';
|
||||
import Type from '../../primitive/Type';
|
||||
import { PlainType, StorageFunctionModifier } from '../v1/Storage';
|
||||
@@ -22,8 +21,6 @@ export {
|
||||
StorageFunctionModifier
|
||||
};
|
||||
|
||||
export class DoubleMapType extends Null {}
|
||||
|
||||
export class MapType extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
@@ -59,20 +56,10 @@ export class StorageFunctionType extends EnumType<PlainType | MapType> {
|
||||
constructor (value?: any, index?: number) {
|
||||
super({
|
||||
PlainType,
|
||||
MapType,
|
||||
DoubleMapType
|
||||
MapType
|
||||
}, 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
|
||||
*/
|
||||
@@ -91,13 +78,6 @@ export class StorageFunctionType extends EnumType<PlainType | MapType> {
|
||||
return this.value as PlainType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description `true` if the storage entry is a double map
|
||||
*/
|
||||
get isDoubleMap (): boolean {
|
||||
return this.toNumber() === 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description `true` if the storage entry is a map
|
||||
*/
|
||||
@@ -116,9 +96,7 @@ export class StorageFunctionType extends EnumType<PlainType | MapType> {
|
||||
* @description Returns the string representation of the value
|
||||
*/
|
||||
toString (): string {
|
||||
if (this.isDoubleMap) {
|
||||
return `DoubleMap<${this.asDoubleMap.toString()}>`;
|
||||
} else if (this.isMap) {
|
||||
if (this.isMap) {
|
||||
if (this.asMap.isLinked) {
|
||||
return `(${this.asMap.value.toString()}, Linkage<${this.asMap.key.toString()}>)`;
|
||||
}
|
||||
@@ -139,7 +117,7 @@ export type StorageFunctionMetadataValue = {
|
||||
};
|
||||
|
||||
/**
|
||||
* @name MetadataModule
|
||||
* @name ModuleMetadata
|
||||
* @description
|
||||
* The definition of a storage function
|
||||
*/
|
||||
|
||||
@@ -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 { default as MetadataV2, MetadataModule as MetadataModuleV2 } from './Metadata';
|
||||
import { default as MetadataV2, ModuleMetadata as ModuleMetadataV2 } from './Metadata';
|
||||
|
||||
export default MetadataV2;
|
||||
|
||||
export {
|
||||
MetadataModuleV2
|
||||
ModuleMetadataV2
|
||||
};
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// 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 MetadataV2 from './Metadata';
|
||||
import MetadataV3 from '../v3';
|
||||
|
||||
export default function toV3 (metadataV2: MetadataV2): MetadataV3 {
|
||||
return new MetadataV3(metadataV2);
|
||||
}
|
||||
@@ -2,9 +2,8 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import MetadataV2 from '../v2/Metadata';
|
||||
import MetadataV3 from '.';
|
||||
|
||||
export default function toV2 (v2: MetadataV3): MetadataV2 {
|
||||
return new MetadataV2(v2);
|
||||
}
|
||||
// Re-export classes that haven't changed between V2 and V3
|
||||
export {
|
||||
FunctionArgumentMetadata,
|
||||
FunctionMetadata
|
||||
} from '../v2/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 V2 and V3
|
||||
export { EventMetadata } from '../v2/Events';
|
||||
@@ -2,21 +2,14 @@
|
||||
// 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 '../Metadata';
|
||||
import latestParsed from './latest.substrate.v3.json';
|
||||
import latestSubstrate from './latest.substrate.v3.json';
|
||||
import rpcData from './static';
|
||||
import { decodeLatestSubstrate, defaultValues, toV4 } from '../util/testUtil';
|
||||
|
||||
describe('MetadataV3', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
decodeLatestSubstrate(3, rpcData, latestSubstrate);
|
||||
|
||||
it('decodes latest properly', () => {
|
||||
const str = JSON.stringify(metadata.toJSON());
|
||||
toV4(3, rpcData);
|
||||
|
||||
console.error(str);
|
||||
console.error(metadata.getUniqTypes(true));
|
||||
|
||||
expect(metadata.version).toBe(3);
|
||||
expect(metadata.asV3.modules.length).not.toBe(0);
|
||||
expect(str).toEqual(JSON.stringify(latestParsed));
|
||||
});
|
||||
defaultValues(rpcData);
|
||||
});
|
||||
|
||||
@@ -10,38 +10,38 @@ import Vector from '../../codec/Vector';
|
||||
import Text from '../../primitive/Text';
|
||||
import { flattenUniq, validateTypes } from '../util';
|
||||
|
||||
import { MetadataCall } from '../v1/Calls';
|
||||
import { MetadataEvent } from '../v1/Events';
|
||||
import { FunctionMetadata } from './Calls';
|
||||
import { EventMetadata } from './Events';
|
||||
import { StorageFunctionMetadata } from './Storage';
|
||||
|
||||
/**
|
||||
* @name MetadataModule
|
||||
* @name ModuleMetadata
|
||||
* @description
|
||||
* The definition of a module in the system
|
||||
*/
|
||||
export class MetadataModule extends Struct {
|
||||
export class ModuleMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
prefix: Text,
|
||||
storage: Option.with(Vector.with(StorageFunctionMetadata)),
|
||||
calls: Option.with(Vector.with(MetadataCall)),
|
||||
events: Option.with(Vector.with(MetadataEvent))
|
||||
calls: Option.with(Vector.with(FunctionMetadata)),
|
||||
events: Option.with(Vector.with(EventMetadata))
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module calls
|
||||
*/
|
||||
get calls (): Option<Vector<MetadataCall>> {
|
||||
return this.get('calls') as Option<Vector<MetadataCall>>;
|
||||
get calls (): Option<Vector<FunctionMetadata>> {
|
||||
return this.get('calls') as Option<Vector<FunctionMetadata>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module events
|
||||
*/
|
||||
get events (): Option<Vector<MetadataEvent>> {
|
||||
return this.get('events') as Option<Vector<MetadataEvent>>;
|
||||
get events (): Option<Vector<EventMetadata>> {
|
||||
return this.get('events') as Option<Vector<EventMetadata>>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,18 +71,18 @@ export class MetadataModule extends Struct {
|
||||
* @description
|
||||
* The runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class MetadataV3 extends Struct implements MetadataInterface {
|
||||
export default class MetadataV3 extends Struct implements MetadataInterface<ModuleMetadata> {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
modules: Vector.with(MetadataModule)
|
||||
modules: Vector.with(ModuleMetadata)
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The associated modules for this structure
|
||||
*/
|
||||
get modules (): Vector<MetadataModule> {
|
||||
return this.get('modules') as Vector<MetadataModule>;
|
||||
get modules (): Vector<ModuleMetadata> {
|
||||
return this.get('modules') as Vector<ModuleMetadata>;
|
||||
}
|
||||
|
||||
private get callNames () {
|
||||
|
||||
@@ -127,7 +127,9 @@ export class StorageFunctionType extends EnumType<PlainType | MapType | DoubleMa
|
||||
toString (): string {
|
||||
if (this.isDoubleMap) {
|
||||
return `DoubleMap<${this.asDoubleMap.toString()}>`;
|
||||
} else if (this.isMap) {
|
||||
}
|
||||
|
||||
if (this.isMap) {
|
||||
if (this.asMap.isLinked) {
|
||||
return `(${this.asMap.value.toString()}, Linkage<${this.asMap.key.toString()}>)`;
|
||||
}
|
||||
|
||||
@@ -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 { default as MetadataV3, MetadataModule as MetadataModuleV3 } from './Metadata';
|
||||
import { default as MetadataV3, ModuleMetadata as ModuleMetadataV3 } from './Metadata';
|
||||
|
||||
export default MetadataV3;
|
||||
|
||||
export {
|
||||
MetadataModuleV3
|
||||
ModuleMetadataV3
|
||||
};
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 MetadataV3 from './Metadata';
|
||||
import StorageHasher from '../../primitive/StorageHasher';
|
||||
import MetadataV4 from '../v4';
|
||||
import { StorageFunctionMetadata as StorageFunctionMetadataV3 } from '../v3/Storage';
|
||||
import { DoubleMapType, MapType, StorageFunctionMetadata, StorageFunctionType } from '../v4/Storage';
|
||||
|
||||
/**
|
||||
* Convert V3 StorageFunction to V4 StorageFunction
|
||||
*/
|
||||
function toV4StorageFunction (storageFn: StorageFunctionMetadataV3): StorageFunctionMetadata {
|
||||
const { documentation, fallback, modifier, name, type } = storageFn;
|
||||
|
||||
// Convert the old type to the new type: there is one new field
|
||||
// called `hasher`, which we initialize to xxHash (the default in
|
||||
// v3).
|
||||
const [newType, index] = type.isPlainType
|
||||
? [type, 0]
|
||||
: type.isMap
|
||||
? [new MapType({
|
||||
hasher: new StorageHasher('Twox128'),
|
||||
key: type.asMap.key,
|
||||
value: type.asMap.value,
|
||||
isLinked: type.asMap.isLinked
|
||||
}), 1]
|
||||
: [new DoubleMapType({
|
||||
hasher: new StorageHasher('Twox128'),
|
||||
key1: type.asDoubleMap.key1,
|
||||
key2: type.asDoubleMap.key2,
|
||||
value: type.asDoubleMap.value,
|
||||
key2Hasher: type.asDoubleMap.key2Hasher
|
||||
}), 2];
|
||||
|
||||
return new StorageFunctionMetadata({
|
||||
name: name,
|
||||
modifier: modifier,
|
||||
type: new StorageFunctionType(newType, index),
|
||||
fallback: fallback,
|
||||
documentation: documentation
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from MetadataV3 to MetadataV4
|
||||
* See https://github.com/paritytech/substrate/pull/2268 for details
|
||||
*/
|
||||
export default function toV4 (metadataV3: MetadataV3): MetadataV4 {
|
||||
return new MetadataV4({
|
||||
modules: metadataV3.modules.map((modul) => {
|
||||
return {
|
||||
name: modul.name,
|
||||
prefix: modul.prefix,
|
||||
storage: modul.storage.isSome
|
||||
? new Option(
|
||||
Vector.with(StorageFunctionMetadata),
|
||||
modul.storage.unwrap().map(toV4StorageFunction)
|
||||
)
|
||||
: 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 V3 and V4
|
||||
export {
|
||||
FunctionArgumentMetadata,
|
||||
FunctionMetadata
|
||||
} from '../v3/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 V3 and V4
|
||||
export { EventMetadata } from '../v3/Events';
|
||||
@@ -2,29 +2,14 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
<<<<<<< HEAD
|
||||
import extrinsicsFromMeta from '@plugnet/extrinsics/fromMetadata';
|
||||
|
||||
import createType from '../../codec/createType';
|
||||
import Method from '../../primitive/Method';
|
||||
|
||||
=======
|
||||
>>>>>>> 57715c50c0... Revert "Update extrinsics FromMetadata. Drop storages with doublemap type when converting v3 to v2 (#888)" (#903)
|
||||
import Metadata from '../Metadata';
|
||||
import latestParsed from './latest.substrate.v4.json';
|
||||
import latestSubstrate from './latest.substrate.v4.json';
|
||||
import rpcData from './static';
|
||||
import { decodeLatestSubstrate, defaultValues, toV4 } from '../util/testUtil';
|
||||
|
||||
describe('MetadataV4', () => {
|
||||
const metadata = new Metadata(rpcData);
|
||||
decodeLatestSubstrate(4, rpcData, latestSubstrate);
|
||||
|
||||
it('decodes latest properly', () => {
|
||||
const str = JSON.stringify(metadata.toJSON());
|
||||
toV4(4, rpcData);
|
||||
|
||||
console.error(str);
|
||||
console.error(metadata.getUniqTypes(true));
|
||||
|
||||
expect(metadata.version).toBe(4);
|
||||
expect(metadata.asV4.modules.length).not.toBe(0);
|
||||
expect(str).toEqual(JSON.stringify(latestParsed));
|
||||
});
|
||||
defaultValues(rpcData);
|
||||
});
|
||||
|
||||
@@ -10,42 +10,38 @@ import Vector from '../../codec/Vector';
|
||||
import Text from '../../primitive/Text';
|
||||
import { flattenUniq, validateTypes } from '../util';
|
||||
|
||||
import { MetadataCall } from '../v1/Calls';
|
||||
import { MetadataEvent } from '../v1/Events';
|
||||
import { FunctionMetadata } from './Calls';
|
||||
import { EventMetadata } from './Events';
|
||||
import { StorageFunctionMetadata } from './Storage';
|
||||
|
||||
export {
|
||||
MetadataEvent
|
||||
};
|
||||
|
||||
/**
|
||||
* @name MetadataModule
|
||||
* @name ModuleMetadata
|
||||
* @description
|
||||
* The definition of a module in the system
|
||||
*/
|
||||
export class MetadataModule extends Struct {
|
||||
export class ModuleMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
prefix: Text,
|
||||
storage: Option.with(Vector.with(StorageFunctionMetadata)),
|
||||
calls: Option.with(Vector.with(MetadataCall)),
|
||||
events: Option.with(Vector.with(MetadataEvent))
|
||||
calls: Option.with(Vector.with(FunctionMetadata)),
|
||||
events: Option.with(Vector.with(EventMetadata))
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module calls
|
||||
*/
|
||||
get calls (): Option<Vector<MetadataCall>> {
|
||||
return this.get('calls') as Option<Vector<MetadataCall>>;
|
||||
get calls (): Option<Vector<FunctionMetadata>> {
|
||||
return this.get('calls') as Option<Vector<FunctionMetadata>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description the module events
|
||||
*/
|
||||
get events (): Option<Vector<MetadataEvent>> {
|
||||
return this.get('events') as Option<Vector<MetadataEvent>>;
|
||||
get events (): Option<Vector<EventMetadata>> {
|
||||
return this.get('events') as Option<Vector<EventMetadata>>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,18 +71,18 @@ export class MetadataModule extends Struct {
|
||||
* @description
|
||||
* The runtime metadata as a decoded structure
|
||||
*/
|
||||
export default class MetadataV4 extends Struct implements MetadataInterface {
|
||||
export default class MetadataV4 extends Struct implements MetadataInterface<ModuleMetadata> {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
modules: Vector.with(MetadataModule)
|
||||
modules: Vector.with(ModuleMetadata)
|
||||
}, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The associated modules for this structure
|
||||
*/
|
||||
get modules (): Vector<MetadataModule> {
|
||||
return this.get('modules') as Vector<MetadataModule>;
|
||||
get modules (): Vector<ModuleMetadata> {
|
||||
return this.get('modules') as Vector<ModuleMetadata>;
|
||||
}
|
||||
|
||||
private get callNames () {
|
||||
|
||||
@@ -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 { default as MetadataV4, MetadataModule as MetadataModuleV4 } from './Metadata';
|
||||
import { default as MetadataV4, ModuleMetadata as ModuleMetadataV4 } from './Metadata';
|
||||
|
||||
export default MetadataV4;
|
||||
|
||||
export {
|
||||
MetadataModuleV4
|
||||
ModuleMetadataV4
|
||||
};
|
||||
|
||||
@@ -11,8 +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 EventMetadataV0 } from '../Metadata/v0/Events';
|
||||
import { MetadataEvent as EventMetadataV4 } from '../Metadata/v1/Events';
|
||||
import { EventMetadata as EventMetadataV4 } from '../Metadata/v4/Events';
|
||||
import Null from './Null';
|
||||
import U32 from './U32';
|
||||
|
||||
@@ -32,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: EventMetadataV0 | EventMetadataV4;
|
||||
private _meta: EventMetadataV4;
|
||||
private _method: string;
|
||||
private _section: string;
|
||||
private _typeDef: Array<TypeDef>;
|
||||
|
||||
constructor (Types: Array<Constructor>, value: Uint8Array, typeDef: Array<TypeDef>, meta: EventMetadataV0 | EventMetadataV4, section: string, method: string) {
|
||||
constructor (Types: Array<Constructor>, value: Uint8Array, typeDef: Array<TypeDef>, meta: EventMetadataV4, section: string, method: string) {
|
||||
super(Types, value);
|
||||
|
||||
this._meta = meta;
|
||||
@@ -49,7 +48,7 @@ export class EventData extends Tuple {
|
||||
/**
|
||||
* @description The wrapped [[EventMetadata]]
|
||||
*/
|
||||
get meta (): EventMetadataV0 | EventMetadataV4 {
|
||||
get meta (): EventMetadataV4 {
|
||||
return this._meta;
|
||||
}
|
||||
|
||||
@@ -129,37 +128,15 @@ 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 {
|
||||
if (metadata.version === 4) {
|
||||
let sectionIndex = 0;
|
||||
|
||||
metadata.asV4.modules.forEach((section) => {
|
||||
metadata.asV4.modules
|
||||
.filter((section) => section.events.isSome)
|
||||
.forEach((section, sectionIndex) => {
|
||||
const sectionName = stringCamelCase(section.name.toString());
|
||||
|
||||
if (!section.events.isNone && !section.events.isEmpty) {
|
||||
section.events.unwrap().forEach((meta, methodIndex) => {
|
||||
const methodName = meta.name.toString();
|
||||
const eventIndex = new Uint8Array([sectionIndex, methodIndex]);
|
||||
const typeDef = meta.args.map((arg) => getTypeDef(arg));
|
||||
const Types = typeDef.map(getTypeClass);
|
||||
|
||||
EventTypes[eventIndex.toString()] = class extends EventData {
|
||||
constructor (value: Uint8Array) {
|
||||
super(Types, value, typeDef, meta, sectionName, methodName);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
sectionIndex += 1;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
metadata.asV0.events.forEach((section, sectionIndex) => {
|
||||
const sectionName = stringCamelCase(section.name.toString());
|
||||
|
||||
section.events.forEach((meta, methodIndex) => {
|
||||
section.events.unwrap().forEach((meta, methodIndex) => {
|
||||
const methodName = meta.name.toString();
|
||||
const eventIndex = new Uint8Array([sectionIndex, methodIndex]);
|
||||
const typeDef = meta.arguments.map((arg) => getTypeDef(arg));
|
||||
const typeDef = meta.args.map((arg) => getTypeDef(arg));
|
||||
const Types = typeDef.map(getTypeClass);
|
||||
|
||||
EventTypes[eventIndex.toString()] = class extends EventData {
|
||||
@@ -169,7 +146,6 @@ export default class Event extends Struct {
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +165,7 @@ export default class Event extends Struct {
|
||||
/**
|
||||
* @description The [[EventMetadata]] with the documentation
|
||||
*/
|
||||
get meta (): EventMetadataV0 | EventMetadataV4 {
|
||||
get meta (): EventMetadataV4 {
|
||||
return this.data.meta;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,19 +34,19 @@ describe('Method', () => {
|
||||
|
||||
it('is false with no arguments', () => {
|
||||
expect(
|
||||
new Method(test, { arguments: [] } as any).hasOrigin
|
||||
new Method(test, { args: [] } as any).hasOrigin
|
||||
).toEqual(false);
|
||||
});
|
||||
|
||||
it('is false with first argument as non-Origin', () => {
|
||||
expect(
|
||||
new Method(test, { arguments: [{ name: 'a', type: 'u32' }] } as any).hasOrigin
|
||||
new Method(test, { args: [{ name: 'a', type: 'u32' }] } as any).hasOrigin
|
||||
).toEqual(false);
|
||||
});
|
||||
|
||||
it('is false with first argument as non-Origin', () => {
|
||||
expect(
|
||||
new Method(test, { arguments: [{ name: 'a', type: 'Origin' }] } as any).hasOrigin
|
||||
new Method(test, { args: [{ name: 'a', type: 'Origin' }] } as any).hasOrigin
|
||||
).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ import { assert, isHex, isObject, isU8a, hexToU8a } from '@plugnet/util';
|
||||
import { getTypeDef, getTypeClass } from '../codec/createType';
|
||||
import Struct from '../codec/Struct';
|
||||
import U8aFixed from '../codec/U8aFixed';
|
||||
import { FunctionMetadata, FunctionArgumentMetadata } from '../Metadata/v0/Modules';
|
||||
import { FunctionMetadata as FunctionMetadataV4, FunctionArgumentMetadata } from '../Metadata/v4/Calls';
|
||||
|
||||
interface DecodeMethodInput {
|
||||
args: any;
|
||||
@@ -18,13 +18,13 @@ interface DecodeMethodInput {
|
||||
|
||||
interface DecodedMethod extends DecodeMethodInput {
|
||||
argsDef: ArgsDef;
|
||||
meta: FunctionMetadata;
|
||||
meta: FunctionMetadataV4;
|
||||
}
|
||||
|
||||
export interface MethodFunction {
|
||||
(...args: any[]): Method;
|
||||
callIndex: Uint8Array;
|
||||
meta: FunctionMetadata;
|
||||
meta: FunctionMetadataV4;
|
||||
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: FunctionMetadata;
|
||||
protected _meta: FunctionMetadataV4;
|
||||
|
||||
constructor (value: any, meta?: FunctionMetadata) {
|
||||
constructor (value: any, meta?: FunctionMetadataV4) {
|
||||
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, _meta?: FunctionMetadata): DecodedMethod {
|
||||
private static decodeMethod (value: DecodedMethod | Uint8Array | string, _meta?: FunctionMetadataV4): DecodedMethod {
|
||||
if (isHex(value)) {
|
||||
return Method.decodeMethod(hexToU8a(value), _meta);
|
||||
} else if (isU8a(value)) {
|
||||
@@ -127,16 +127,16 @@ export default class Method extends Struct implements IMethod {
|
||||
return {
|
||||
args: new Uint8Array(),
|
||||
argsDef: {},
|
||||
meta: new FunctionMetadata(),
|
||||
meta: new FunctionMetadataV4(),
|
||||
callIndex: new Uint8Array([255, 255])
|
||||
};
|
||||
}
|
||||
|
||||
// If the extrinsic function has an argument of type `Origin`, we ignore it
|
||||
static filterOrigin (meta?: FunctionMetadata): Array<FunctionArgumentMetadata> {
|
||||
static filterOrigin (meta?: FunctionMetadataV4): Array<FunctionArgumentMetadata> {
|
||||
// FIXME should be `arg.type !== Origin`, but doesn't work...
|
||||
return meta
|
||||
? meta.arguments.filter(({ type }) =>
|
||||
? meta.args.filter(({ type }) =>
|
||||
type.toString() !== 'Origin'
|
||||
)
|
||||
: [];
|
||||
@@ -161,7 +161,7 @@ export default class Method extends Struct implements IMethod {
|
||||
*
|
||||
* @param meta - The function metadata used to get the definition.
|
||||
*/
|
||||
private static getArgsDef (meta: FunctionMetadata): ArgsDef {
|
||||
private static getArgsDef (meta: FunctionMetadataV4): ArgsDef {
|
||||
return Method.filterOrigin(meta).reduce((result, { name, type }) => {
|
||||
const Type = getTypeClass(
|
||||
getTypeDef(type)
|
||||
@@ -215,7 +215,7 @@ export default class Method extends Struct implements IMethod {
|
||||
* @description `true` if the `Origin` type is on the method (extrinsic method)
|
||||
*/
|
||||
get hasOrigin (): boolean {
|
||||
const firstArg = this.meta.arguments[0];
|
||||
const firstArg = this.meta.args[0];
|
||||
|
||||
return !!firstArg && firstArg.type.toString() === 'Origin';
|
||||
}
|
||||
@@ -223,7 +223,7 @@ export default class Method extends Struct implements IMethod {
|
||||
/**
|
||||
* @description The [[FunctionMetadata]]
|
||||
*/
|
||||
get meta (): FunctionMetadata {
|
||||
get meta (): FunctionMetadataV4 {
|
||||
return this._meta;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,33 +3,71 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { hexToU8a } from '@plugnet/util';
|
||||
import storage from '@plugnet/storage/static';
|
||||
import fromMetadata from '@plugnet/storage/fromMetadata';
|
||||
import rpcDataV3 from '@plugnet/types/Metadata/v3/static';
|
||||
import rpcDataV4 from '@plugnet/types/Metadata/v4/static';
|
||||
|
||||
import Metadata from '../Metadata';
|
||||
import StorageKey from './StorageKey';
|
||||
|
||||
describe('StorageKey', () => {
|
||||
it(`should correctly get Alice's freeBalance storage key (hex)`, () => {
|
||||
expect(
|
||||
new StorageKey(
|
||||
storage
|
||||
.balances
|
||||
.freeBalance('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY')
|
||||
)
|
||||
.toHex()
|
||||
).toBe('0xc99f5446efa57788f39ab529311f4550'); // FIXME OK this should be length-prefixed in reality
|
||||
describe('with MetadataV3 (uses xxHash by default)', () => {
|
||||
const storage = fromMetadata(new Metadata(rpcDataV3));
|
||||
|
||||
it(`should correctly get Alice's freeBalance storage key (hex)`, () => {
|
||||
expect(
|
||||
new StorageKey(
|
||||
storage
|
||||
.balances
|
||||
.freeBalance('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY')
|
||||
)
|
||||
.toHex()
|
||||
).toBe('0xc99f5446efa57788f39ab529311f4550'); // FIXME OK this should be length-prefixed in reality
|
||||
});
|
||||
|
||||
it(`should correctly get Alice's freeBalance storage key (u8a)`, () => {
|
||||
expect(
|
||||
new StorageKey(
|
||||
storage
|
||||
.balances
|
||||
.freeBalance('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY')
|
||||
)
|
||||
.toU8a()
|
||||
).toEqual(
|
||||
// length prefix attached
|
||||
hexToU8a('0x40c99f5446efa57788f39ab529311f4550')
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should correctly get Alice's freeBalance storage key (u8a)`, () => {
|
||||
expect(
|
||||
new StorageKey(
|
||||
storage
|
||||
.balances
|
||||
.freeBalance('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY')
|
||||
)
|
||||
.toU8a()
|
||||
).toEqual(
|
||||
// length prefix attached
|
||||
hexToU8a('0x40c99f5446efa57788f39ab529311f4550')
|
||||
);
|
||||
describe('with MetadataV4 (uses xxHash by default)', () => {
|
||||
const storage = fromMetadata(new Metadata(rpcDataV4));
|
||||
|
||||
it(`should correctly get Alice's freeBalance storage key (hex)`, () => {
|
||||
expect(
|
||||
new StorageKey(
|
||||
storage
|
||||
.balances
|
||||
.freeBalance('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY')
|
||||
)
|
||||
.toHex()
|
||||
).toBe('0x7f864e18e3dd8b58386310d2fe0919eef27c6e558564b7f67f22d99d20f587bb');
|
||||
});
|
||||
|
||||
it(`should correctly get Alice's freeBalance storage key (u8a)`, () => {
|
||||
expect(
|
||||
new StorageKey(
|
||||
storage
|
||||
.balances
|
||||
.freeBalance('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY')
|
||||
)
|
||||
.toU8a()
|
||||
).toEqual(
|
||||
// length prefix attached
|
||||
Uint8Array.from([
|
||||
128, 127, 134, 78, 24, 227, 221, 139, 88, 56, 99, 16, 210, 254, 9, 25, 238, 242, 124, 110, 85, 133, 100, 183, 246, 127, 34, 217, 157, 32, 245, 135, 187
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,12 +7,11 @@ import { AnyU8a } from '../types';
|
||||
import { assert, isFunction, isString, isU8a } from '@plugnet/util';
|
||||
|
||||
import Bytes from './Bytes';
|
||||
import { StorageFunctionMetadata as MetaV0 } from '../Metadata/v0/Storage';
|
||||
import { StorageFunctionMetadata as MetaV4 } from '../Metadata/v4/Storage';
|
||||
|
||||
export interface StorageFunction {
|
||||
(arg?: any): Uint8Array;
|
||||
meta: MetaV0 | MetaV4;
|
||||
meta: MetaV4;
|
||||
method: string;
|
||||
section: string;
|
||||
toJSON: () => any;
|
||||
@@ -26,8 +25,8 @@ export interface StorageFunction {
|
||||
* constructed by passing in a raw key or a StorageFunction with (optional) arguments.
|
||||
*/
|
||||
export default class StorageKey extends Bytes {
|
||||
private _meta: MetaV0 | MetaV4 | null;
|
||||
private _outputType: string | null;
|
||||
private _meta?: MetaV4;
|
||||
private _outputType?: string;
|
||||
|
||||
constructor (value?: AnyU8a | StorageKey | StorageFunction | [StorageFunction, any]) {
|
||||
super(StorageKey.decodeStorageKey(value));
|
||||
@@ -53,7 +52,7 @@ export default class StorageKey extends Bytes {
|
||||
throw new Error(`Unable to convert input ${value} to StorageKey`);
|
||||
}
|
||||
|
||||
static getMeta (value: StorageKey | StorageFunction | [StorageFunction, any]): MetaV0 | MetaV4 | null {
|
||||
static getMeta (value: StorageKey | StorageFunction | [StorageFunction, any]): MetaV4 | undefined {
|
||||
if (value instanceof StorageKey) {
|
||||
return value.meta;
|
||||
} else if (isFunction(value)) {
|
||||
@@ -64,10 +63,10 @@ export default class StorageKey extends Bytes {
|
||||
return fn.meta;
|
||||
}
|
||||
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static getType (value: StorageKey | StorageFunction | [StorageFunction, any]): string | null {
|
||||
static getType (value: StorageKey | StorageFunction | [StorageFunction, any]): string | undefined {
|
||||
if (value instanceof StorageKey) {
|
||||
return value.outputType;
|
||||
} else if (isFunction(value)) {
|
||||
@@ -78,20 +77,20 @@ export default class StorageKey extends Bytes {
|
||||
return fn.meta.type.toString();
|
||||
}
|
||||
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The metadata or `null` when not available
|
||||
*/
|
||||
get meta (): MetaV0 | MetaV4 | null {
|
||||
get meta (): MetaV4 | undefined {
|
||||
return this._meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The output type, `null` when not available
|
||||
*/
|
||||
get outputType (): string | null {
|
||||
get outputType (): string | undefined {
|
||||
return this._outputType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 MetadataV0 from '../Metadata/v0';
|
||||
import MetadataV4 from '../Metadata/v4';
|
||||
|
||||
const ANCHOR_TOP = '';
|
||||
const LINK_BACK_TO_TOP = '';
|
||||
@@ -56,7 +56,10 @@ function addRpc () {
|
||||
}, renderHeading + renderAnchors);
|
||||
}
|
||||
|
||||
function sortExtrinsicsSectionMethods (a: any, b: any) {
|
||||
/**
|
||||
* Sort object by their `.name`
|
||||
*/
|
||||
function sortByName<T extends { name: any }> (a: T, b: T): number {
|
||||
// ignore upper and lowercase
|
||||
const nameA = a.name.toString().toUpperCase();
|
||||
const nameB = b.name.toString().toUpperCase();
|
||||
@@ -64,26 +67,28 @@ function sortExtrinsicsSectionMethods (a: any, b: any) {
|
||||
return nameA.localeCompare(nameB);
|
||||
}
|
||||
|
||||
function addEvents (metadata: MetadataV0) {
|
||||
function addEvents (metadata: MetadataV4) {
|
||||
const renderHeading = `## ${ANCHOR_TOP}Events${DESC_EVENTS}`;
|
||||
const orderedSections = metadata.events.map((i) => i).sort();
|
||||
const orderedSections = metadata.modules.sort(sortByName);
|
||||
let renderAnchors = '';
|
||||
const sections = orderedSections.reduce((md, meta) => {
|
||||
if (!meta.events || !meta.events.length) {
|
||||
if (meta.events.isNone || !meta.events.unwrap().length) {
|
||||
return md;
|
||||
}
|
||||
|
||||
const events = meta.events.unwrap();
|
||||
|
||||
const sectionName = stringCamelCase(meta.name.toString());
|
||||
|
||||
renderAnchors += sectionLink(sectionName);
|
||||
|
||||
const renderSection = generateSectionHeader(md, sectionName);
|
||||
|
||||
const orderedMethods = meta.events.sort(sortExtrinsicsSectionMethods);
|
||||
const orderedMethods = events.sort(sortByName);
|
||||
|
||||
return orderedMethods.reduce((md, func) => {
|
||||
const methodName = func.name.toString();
|
||||
const args = func.arguments.map((type) => '`' + type + '`').join(', ');
|
||||
const args = func.args.map((type) => '`' + type + '`').join(', ');
|
||||
const doc = func.documentation.reduce((md, doc) => `${md} ${doc}`, '');
|
||||
const renderSignature = `${md}\n▸ **${methodName}**(${args})`;
|
||||
const renderSummary = `${doc ? `\n- **summary**: ${doc}\n` : '\n'}`;
|
||||
@@ -95,21 +100,23 @@ function addEvents (metadata: MetadataV0) {
|
||||
return renderHeading + renderAnchors + sections;
|
||||
}
|
||||
|
||||
function addExtrinsics (metadata: MetadataV0) {
|
||||
function addExtrinsics (metadata: MetadataV4) {
|
||||
const renderHeading = `## ${ANCHOR_TOP}Extrinsics${DESC_EXTRINSICS}`;
|
||||
const orderedSections = metadata.modules.map((i) => i).sort();
|
||||
const orderedSections = metadata.modules.map((i) => i).sort(sortByName);
|
||||
let renderAnchors = '';
|
||||
const sections = orderedSections.reduce((md, meta) => {
|
||||
if (!meta.module.call || !meta.module.call.functions.length) {
|
||||
if (meta.calls.isNone || !meta.calls.unwrap().length) {
|
||||
return md;
|
||||
}
|
||||
|
||||
const calls = meta.calls.unwrap();
|
||||
|
||||
const sectionName = stringCamelCase(meta.prefix.toString());
|
||||
|
||||
renderAnchors += sectionLink(sectionName);
|
||||
|
||||
const renderSection = generateSectionHeader(md, sectionName);
|
||||
const orderedMethods = meta.module.call.functions.sort(sortExtrinsicsSectionMethods);
|
||||
const orderedMethods = calls.sort(sortByName);
|
||||
|
||||
return orderedMethods.reduce((md, func) => {
|
||||
const methodName = stringCamelCase(func.name.toString());
|
||||
@@ -125,21 +132,21 @@ function addExtrinsics (metadata: MetadataV0) {
|
||||
return renderHeading + renderAnchors + sections;
|
||||
}
|
||||
|
||||
function addStorage (metadata: MetadataV0) {
|
||||
function addStorage (metadata: MetadataV4) {
|
||||
const renderHeading = `## ${ANCHOR_TOP}Storage${DESC_STORAGE}`;
|
||||
const orderedSections = metadata.modules.sort();
|
||||
const orderedSections = metadata.modules.sort(sortByName);
|
||||
let renderAnchors = '';
|
||||
const sections = orderedSections.reduce((md, moduleMetadata) => {
|
||||
if (moduleMetadata.storage.isNone) {
|
||||
return md;
|
||||
}
|
||||
|
||||
const sectionName = stringLowerFirst(moduleMetadata.storage.unwrap().prefix.toString());
|
||||
const sectionName = stringLowerFirst(moduleMetadata.prefix.toString());
|
||||
|
||||
renderAnchors += sectionLink(sectionName);
|
||||
|
||||
const renderSection = generateSectionHeader(md, sectionName);
|
||||
const orderedMethods = moduleMetadata.storage.unwrap().functions.sort();
|
||||
const orderedMethods = moduleMetadata.storage.unwrap().sort(sortByName);
|
||||
|
||||
return orderedMethods.reduce((md, func) => {
|
||||
const methodName = stringLowerFirst(func.name.toString());
|
||||
@@ -177,22 +184,22 @@ function writeToRpcMd () {
|
||||
writeFile('docs/METHODS_RPC.md', addRpc());
|
||||
}
|
||||
|
||||
function writeToStorageMd (metadata: MetadataV0) {
|
||||
function writeToStorageMd (metadata: MetadataV4) {
|
||||
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: MetadataV0) {
|
||||
function writeToExtrinsicsMd (metadata: MetadataV4) {
|
||||
writeFile('docs/METHODS_EXTRINSICS.md', addExtrinsics(metadata));
|
||||
}
|
||||
|
||||
function writeToEventsMd (metadata: MetadataV0) {
|
||||
function writeToEventsMd (metadata: MetadataV4) {
|
||||
writeFile('docs/METHODS_EVENTS.md', addEvents(metadata));
|
||||
}
|
||||
|
||||
const metadata = new Metadata(rpcdata).asV0;
|
||||
const metadata = new Metadata(rpcdata).asV4;
|
||||
|
||||
writeToRpcMd();
|
||||
writeToStorageMd(metadata);
|
||||
|
||||
@@ -10,7 +10,7 @@ import { blake2AsU8a } from '@plugnet/util-crypto';
|
||||
|
||||
import Compact from '../codec/Compact';
|
||||
import Struct from '../codec/Struct';
|
||||
import { FunctionMetadata } from '../Metadata/v0/Modules';
|
||||
import { FunctionMetadata } from '../Metadata/v4/Calls';
|
||||
import Method from '../primitive/Method';
|
||||
import Address from '../primitive/Address';
|
||||
import Hash from '../primitive/Hash';
|
||||
|
||||
@@ -7,13 +7,13 @@ import { KeyringPair } from '@plugnet/keyring/types';
|
||||
import BN from 'bn.js';
|
||||
|
||||
import U8a from './codec/U8a';
|
||||
import { FunctionMetadata } from './Metadata/v4/Calls';
|
||||
import Method from './primitive/Method';
|
||||
import Address from './primitive/Address';
|
||||
import { FunctionMetadata } from './Metadata/v0/Modules';
|
||||
|
||||
export type CodecArg = Codec | BN | Boolean | String | Uint8Array | boolean | number | string | undefined | CodecArgArray | CodecArgObject;
|
||||
|
||||
export type CodecCallback <T extends Codec = any> = (result: T) => any;
|
||||
export type CodecCallback<T extends Codec = any> = (result: T) => any;
|
||||
|
||||
interface CodecArgObject {
|
||||
[index: string]: CodecArg;
|
||||
@@ -106,7 +106,7 @@ export interface ArgsDef {
|
||||
[index: string]: Constructor;
|
||||
}
|
||||
|
||||
export interface IHash extends U8a {}
|
||||
export interface IHash extends U8a { }
|
||||
|
||||
export interface IMethod extends Codec {
|
||||
readonly args: Array<Codec>;
|
||||
|
||||
Reference in New Issue
Block a user