Revert "Update extrinsics FromMetadata. Drop storages with doublemap type when converting v3 to v2 (#888)" (#903)

This reverts commit 97032e7e86.
This commit is contained in:
Jaco Greeff
2019-05-14 16:21:32 +02:00
committed by GitHub
parent 5ac7841fd9
commit 57715c50c0
21 changed files with 56 additions and 313 deletions
+2 -2
View File
@@ -398,7 +398,7 @@ export default abstract class ApiBase<CodecResult, SubscriptionResult> implement
this._genesisHash = this._options.source.genesisHash;
}
const extrinsics = extrinsicsFromMeta(this.runtimeMetadata);
const extrinsics = extrinsicsFromMeta(this.runtimeMetadata.asV0);
const storage = storageFromMeta(this.runtimeMetadata);
this._extrinsics = this.decorateExtrinsics(extrinsics, this.onCall);
@@ -413,7 +413,7 @@ export default abstract class ApiBase<CodecResult, SubscriptionResult> implement
// only inject if we are not a clone (global init)
if (!this._options.source) {
Event.injectMetadata(this.runtimeMetadata);
Event.injectMetadata(this.runtimeMetadata.asV0);
Method.injectMethods(extrinsics);
}
@@ -5,11 +5,11 @@
import { Extrinsic, Metadata } from '@polkadot/types';
import json from '@polkadot/types/Metadata/v0/static';
import fromV0 from '.';
import fromMetadata from './fromMetadata';
// Use the pre-generated metadata
const metadata = new Metadata(json).asV0;
const newExtrinsics = fromV0(metadata);
const newExtrinsics = fromMetadata(metadata);
describe('fromMetadata', () => {
it('should throw if an incorrect number of args is supplied', () => {
@@ -2,13 +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 MetadataV0 from '@polkadot/types/Metadata/v0';
import { RuntimeModuleMetadata } from '@polkadot/types/Metadata/v0/Modules';
import { Methods, ModulesWithMethods } from '@polkadot/types/primitive/Method';
import MetadataV0 from '@polkadot/types/Metadata/v0';
import { stringCamelCase } from '@polkadot/util';
import extrinsics from '../../index';
import createUnchecked from './createUnchecked';
import createUnchecked from './utils/createUnchecked';
import extrinsics from '.';
/**
* Extend a storage object with the storage modules & module functions present
@@ -17,7 +18,7 @@ import createUnchecked from './createUnchecked';
* @param extrinsics - An extrinsics object to be extended.
* @param metadata - The metadata to extend the storage object against.
*/
export default function fromV0 (metadata: MetadataV0): ModulesWithMethods {
export default function fromMetadata (metadata: MetadataV0): ModulesWithMethods {
let indexCount = -1;
const findIndex = (prefix: string): number => {
@@ -1,26 +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 { ModulesWithMethods } from '@polkadot/types/primitive/Method';
import Metadata from '@polkadot/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 extrinsics - An extrinsics object to be extended.
* @param metadata - The metadata to extend the storage object against.
*/
export default function fromMetadata (metadata: Metadata): ModulesWithMethods {
if (metadata.version === 4) {
// For v4, we use fromV4 function
return fromV4(metadata.asV4);
}
// For v0-v3 we convert to v0, and use the fromV0 function to parse
return fromV0(metadata.asV0);
}
@@ -1,7 +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 fromMetadata from './fromMetadata';
export default fromMetadata;
@@ -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 { MetadataCall } from '@polkadot/types/Metadata/v1/Calls';
import { MethodFunction } from '@polkadot/types/primitive/Method';
import { Method } from '@polkadot/types';
import { assert } from '@polkadot/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,
indexCount: number,
meta: MetadataCall,
index: number
): MethodFunction {
const callIndex = new Uint8Array([indexCount, index]);
const expectedArgs = Method.filterOrigin(meta);
const 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;
}
@@ -1,39 +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 { Extrinsic, Metadata } from '@polkadot/types';
import json from '@polkadot/types/Metadata/v4/static';
import fromV4 from '.';
// Use the pre-generated metadata
const metadata = new Metadata(json).asV4;
const newExtrinsics = fromV4(metadata);
describe('fromMetadata', () => {
it('should throw if an incorrect number of args is supplied', () => {
expect(() => newExtrinsics.balances.setBalance()).toThrowError(/expects 3 arguments/);
});
it('should return a value if the storage function does not expect an argument', () => {
expect(() => newExtrinsics.balances.setBalance('5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF', 2, 3)).not.toThrow();
});
it('should return properly-encoded transactions', () => {
expect(
new Extrinsic(newExtrinsics.timestamp.set([10101])).toU8a()
).toEqual(
new Uint8Array([
// length (encoded)
4 << 2,
// version, no signature
1,
// index
0, 0,
// values, Compact<Moment>
116
])
);
});
});
@@ -1,40 +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 { MetadataModule } from '@polkadot/types/Metadata/v4/Metadata';
import { Methods, ModulesWithMethods } from '@polkadot/types/primitive/Method';
import MetadataV4 from '@polkadot/types/Metadata/v4';
import { stringCamelCase } from '@polkadot/util';
import extrinsics from '../../index';
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 fromV4 (metadata: MetadataV4): ModulesWithMethods {
let indexCount = -1;
return metadata.modules.reduce((result, module: MetadataModule) => {
if (module.calls.isNone || module.calls.isEmpty) {
return result;
}
indexCount++;
const prefix = stringCamelCase(module.prefix.toString());
result[prefix] = module.calls.unwrap().reduce((newModule, call, index) => {
const funcName = stringCamelCase(call.name.toString());
newModule[funcName] = createUnchecked(prefix, funcName, indexCount, call, index);
return newModule;
}, {} as Methods);
return result;
}, { ...extrinsics });
}
+1 -1
View File
@@ -9,6 +9,6 @@ import { ModulesWithMethods } from '@polkadot/types/primitive/Method';
import fromMetadata from './fromMetadata';
const staticMetadata: ModulesWithMethods = fromMetadata(
new Metadata(metadataRpc)
new Metadata(metadataRpc).asV0
);
export default staticMetadata;
@@ -239,7 +239,7 @@ export default class MetadataVersioned extends Struct implements MetadataInterfa
}
/**
* @description Returns the wrapped values as a V4 object
* @description Returns the wrapped values as a V3 object
*/
get asV4 (): MetadataV4 {
assert(this.metadata.version === 4, `Cannot convert metadata from v${this.metadata.version} to v4`);
@@ -7,14 +7,13 @@ import extrinsicsFromMeta from '@polkadot/extrinsics/fromMetadata';
import createType from '../../codec/createType';
import Method from '../../primitive/Method';
import Metadata from '../Metadata';
import MetadataV0 from './Metadata';
import Metadata from './Metadata';
import latestParsed from './latest.substrate.json';
import rpcData from './static';
describe('Metadata', () => {
it('decodes latest properly', () => {
const metadata = new MetadataV0(rpcData);
const metadata = new Metadata(rpcData);
const str = JSON.stringify(metadata.toJSON());
expect(metadata.events.length).not.toBe(0);
@@ -26,7 +25,7 @@ describe('Metadata', () => {
Method.injectMethods(extrinsicsFromMeta(metadata));
metadata.asV0.modules.forEach((mod) => {
metadata.modules.forEach((mod) => {
if (mod.storage.isNone) {
return;
}
@@ -29,7 +29,7 @@ describe('MetadataV1', () => {
});
describe('storage with default values', () => {
Method.injectMethods(extrinsicsFromMeta(metadata));
Method.injectMethods(extrinsicsFromMeta(metadata.asV0));
metadata.asV1.modules
.filter(({ storage }) => storage.isSome)
@@ -35,7 +35,7 @@ describe('MetadataV2', () => {
});
describe('storage with default values', () => {
Method.injectMethods(extrinsicsFromMeta(metadata));
Method.injectMethods(extrinsicsFromMeta(metadata.asV0));
metadata.asV2.modules
.filter(({ storage }) => storage.isSome)
+2 -30
View File
@@ -2,37 +2,9 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import Option from '../../codec/Option';
import Vector from '../../codec/Vector';
import MetadataV2 from '../v2/Metadata';
import MetadataV3 from '.';
import { MetadataModule } from './Metadata';
import { StorageFunctionMetadata } from './Storage';
function storageV2 (storage: Option<Vector<StorageFunctionMetadata>>): Option<Vector<StorageFunctionMetadata>> {
if (storage.isNone) {
return storage;
}
const storageV2 = storage.unwrap().filter(({ type }) => !type.isDoubleMap);
return new Option<Vector<StorageFunctionMetadata>>(
Vector.with(StorageFunctionMetadata),
new Vector<StorageFunctionMetadata>(StorageFunctionMetadata, storageV2)
);
}
function modulesV2 (v3: MetadataV3): Array<MetadataModule> {
return v3.modules.map((mod) =>
new MetadataModule({
name: mod.name,
prefix: mod.prefix,
storage: storageV2(mod.storage)
}));
}
export default function toV2 (v3: MetadataV3): MetadataV2 {
return new MetadataV2({
modules: modulesV2(v3)
});
export default function toV2 (v2: MetadataV3): MetadataV2 {
return new MetadataV2(v2);
}
@@ -2,11 +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 extrinsicsFromMeta from '@polkadot/extrinsics/fromMetadata';
import createType from '../../codec/createType';
import Method from '../../primitive/Method';
import Metadata from '../Metadata';
import latestParsed from './latest.substrate.v4.json';
import rpcData from './static';
@@ -24,20 +19,4 @@ describe('MetadataV4', () => {
expect(metadata.asV4.modules.length).not.toBe(0);
expect(str).toEqual(JSON.stringify(latestParsed));
});
describe('storage with default values', () => {
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 -20
View File
@@ -9,8 +9,7 @@ import { assert, isHex, isObject, isU8a, hexToU8a } from '@polkadot/util';
import { getTypeDef, getTypeClass } from '../codec/createType';
import Struct from '../codec/Struct';
import U8aFixed from '../codec/U8aFixed';
import { FunctionMetadata as MetaV0, FunctionArgumentMetadata } from '../Metadata/v0/Modules';
import { MetadataCall as MetaV4 } from '../Metadata/v1/Calls';
import { FunctionMetadata, FunctionArgumentMetadata } from '../Metadata/v0/Modules';
interface DecodeMethodInput {
args: any;
@@ -19,13 +18,13 @@ interface DecodeMethodInput {
interface DecodedMethod extends DecodeMethodInput {
argsDef: ArgsDef;
meta: MetaV0 | MetaV4;
meta: FunctionMetadata;
}
export interface MethodFunction {
(...args: any[]): Method;
callIndex: Uint8Array;
meta: MetaV0 | MetaV4;
meta: FunctionMetadata;
method: string;
section: string;
toJSON: () => any;
@@ -64,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: MetaV0 | MetaV4;
protected _meta: FunctionMetadata;
constructor (value: any, meta?: MetaV0 | MetaV4) {
constructor (value: any, meta?: FunctionMetadata) {
const decoded = Method.decodeMethod(value, meta);
super({
@@ -87,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?: MetaV0 | MetaV4): DecodedMethod {
private static decodeMethod (value: DecodedMethod | Uint8Array | string, _meta?: FunctionMetadata): DecodedMethod {
if (isHex(value)) {
return Method.decodeMethod(hexToU8a(value), _meta);
} else if (isU8a(value)) {
@@ -128,21 +127,14 @@ export default class Method extends Struct implements IMethod {
return {
args: new Uint8Array(),
argsDef: {},
meta: new MetaV0(),
meta: new FunctionMetadata(),
callIndex: new Uint8Array([255, 255])
};
}
// If the extrinsic function has an argument of type `Origin`, we ignore it
static filterOrigin (meta?: MetaV0 | MetaV4): Array<FunctionArgumentMetadata> {
static filterOrigin (meta?: FunctionMetadata): Array<FunctionArgumentMetadata> {
// FIXME should be `arg.type !== Origin`, but doesn't work...
if (meta instanceof MetaV4) {
return meta
? meta.args.filter(({ type }) =>
type.toString() !== 'Origin'
)
: [];
}
return meta
? meta.arguments.filter(({ type }) =>
type.toString() !== 'Origin'
@@ -169,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: MetaV0 | MetaV4): ArgsDef {
private static getArgsDef (meta: FunctionMetadata): ArgsDef {
return Method.filterOrigin(meta).reduce((result, { name, type }) => {
const Type = getTypeClass(
getTypeDef(type)
@@ -223,15 +215,15 @@ 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 instanceof MetaV4 ? this.meta.args[0] : this.meta.arguments[0];
const firstArg = this.meta.arguments[0];
return !!firstArg && firstArg.type.toString() === 'Origin';
}
/**
* @description The [[MetaV0]]
* @description The [[FunctionMetadata]]
*/
get meta (): MetaV0 | MetaV4 {
get meta (): FunctionMetadata {
return this._meta;
}
}
+20 -46
View File
@@ -11,9 +11,8 @@ import Tuple from '../codec/Tuple';
import U8aFixed from '../codec/U8aFixed';
import Null from '../primitive/Null';
import { TypeDef, getTypeClass, getTypeDef } from '../codec/createType';
import Metadata from '../Metadata';
import { EventMetadata as MetaV0 } from '../Metadata/v0/Events';
import { MetadataEvent as MetaV1 } from '../Metadata/v1/Events';
import MetadataV0 from '../Metadata/v0';
import { EventMetadata } from '../Metadata/v0/Events';
const EventTypes: { [index: string]: Constructor<EventData> } = {};
@@ -23,12 +22,12 @@ const EventTypes: { [index: string]: Constructor<EventData> } = {};
* Wrapper for the actual data that forms part of an [[Event]]
*/
export class EventData extends Tuple {
private _meta: MetaV0 | MetaV1;
private _meta: EventMetadata;
private _method: string;
private _section: string;
private _typeDef: Array<TypeDef>;
constructor (Types: Array<Constructor>, value: Uint8Array, typeDef: Array<TypeDef>, meta: MetaV0 | MetaV1, section: string, method: string) {
constructor (Types: Array<Constructor>, value: Uint8Array, typeDef: Array<TypeDef>, meta: EventMetadata, section: string, method: string) {
super(Types, value);
this._meta = meta;
@@ -40,7 +39,7 @@ export class EventData extends Tuple {
/**
* @description The wrapped [[EventMetadata]]
*/
get meta (): MetaV0 | MetaV1 {
get meta (): EventMetadata {
return this._meta;
}
@@ -120,48 +119,23 @@ 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 === 0) {
const metadataV0 = metadata.asV0;
metadataV0.events.forEach((section, sectionIndex) => {
const sectionName = stringCamelCase(section.name.toString());
static injectMetadata (metadata: MetadataV0): void {
metadata.events.forEach((section, sectionIndex) => {
const sectionName = stringCamelCase(section.name.toString());
section.events.forEach((meta, methodIndex) => {
const methodName = meta.name.toString();
const eventIndex = new Uint8Array([sectionIndex, methodIndex]);
const typeDef = meta.arguments.map((arg) => getTypeDef(arg));
const Types = typeDef.map(getTypeClass);
section.events.forEach((meta, methodIndex) => {
const methodName = meta.name.toString();
const eventIndex = new Uint8Array([sectionIndex, methodIndex]);
const typeDef = meta.arguments.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);
}
};
});
EventTypes[eventIndex.toString()] = class extends EventData {
constructor (value: Uint8Array) {
super(Types, value, typeDef, meta, sectionName, methodName);
}
};
});
} else {
const metadataV4 = metadata.asV4;
let sectionIndex = 0;
metadataV4.modules.forEach((section) => {
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;
}
});
}
});
}
/**
@@ -181,7 +155,7 @@ export default class Event extends Struct {
/**
* @description The [[EventMetadata]] with the documentation
*/
get meta (): MetaV0 | MetaV1 {
get meta (): EventMetadata {
return this.data.meta;
}
+2 -18
View File
@@ -13,13 +13,12 @@ import EventRecord from './EventRecord';
import Metadata from '../Metadata';
import metadataV0 from '../Metadata/v0/static';
import metadataV1 from '../Metadata/static';
import metadataV4 from '../Metadata/v4/static';
describe('EventRecord', () => {
describe('v0', () => {
beforeEach(() => {
Event.injectMetadata(
new Metadata(metadataV0)
new Metadata(metadataV0).asV0
);
});
@@ -54,22 +53,7 @@ describe('EventRecord', () => {
describe.skip('v1', () => {
beforeEach(() => {
Event.injectMetadata(
new Metadata(metadataV1)
);
});
it('decodes correctly', () => {
const records: Vector<EventRecord> = createType('Vec<EventRecord>', json3.params.result.changes[0][1]) as any;
const er = records[0];
expect(er.phase.type).toEqual('ApplyExtrinsic');
});
});
describe.skip('v4', () => {
beforeEach(() => {
Event.injectMetadata(
new Metadata(metadataV4)
new Metadata(metadataV1).asV0
);
});
+2 -3
View File
@@ -10,8 +10,7 @@ import { blake2AsU8a } from '@polkadot/util-crypto';
import Compact from '../codec/Compact';
import Struct from '../codec/Struct';
import { FunctionMetadata as MetaV0 } from '../Metadata/v0/Modules';
import { MetadataCall as MetaV1 } from '../Metadata/v1/Calls';
import { FunctionMetadata } from '../Metadata/v0/Modules';
import Method from '../primitive/Method';
import Address from './Address';
import ExtrinsicSignature from './ExtrinsicSignature';
@@ -141,7 +140,7 @@ export default class Extrinsic extends Struct implements IExtrinsic {
/**
* @description The [[FunctionMetadata]] that describes the extrinsic
*/
get meta (): MetaV0 | MetaV1 {
get meta (): FunctionMetadata {
return this.method.meta;
}
+2 -3
View File
@@ -7,8 +7,7 @@ import BN from 'bn.js';
import U8a from './codec/U8a';
import Method from './primitive/Method';
import Address from './type/Address';
import { FunctionMetadata as MetaV0 } from './Metadata/v0/Modules';
import { MetadataCall as MetaV4 } from './Metadata/v1/Calls';
import { FunctionMetadata } from './Metadata/v0/Modules';
export type CodecArg = Codec | BN | Boolean | String | Uint8Array | boolean | number | string | undefined | CodecArgArray | CodecArgObject;
@@ -113,7 +112,7 @@ export interface IMethod extends Codec {
readonly callIndex: Uint8Array;
readonly data: Uint8Array;
readonly hasOrigin: boolean;
readonly meta: MetaV0 | MetaV4;
readonly meta: FunctionMetadata;
}
export interface IExtrinsicSignature extends Codec {