API formatting for inputs & outputs (#171)
* API formatting for inputs & outputs * Shorten naming * getStorage (signle key) operational * Remove api-format (not used in api anymore) * Cleanup creation logic * Cleanup linting * Cleanup storage creation * e2e state test * Add code test * Add isBare flag to toU8a * Uppercase... wtill wrong though * Update metadata json * We are creating keys properly * Cleanup tslint * Type splitting,m handling Tuple & Vector * StorageChangeSet results in-place * Update deps * Allow Tuples to have array constructors * Test for uncloded vec/tuple * Update deps
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@ const config = require('@polkadot/dev/config/jest');
|
||||
|
||||
module.exports = Object.assign({}, config, {
|
||||
moduleNameMapper: {
|
||||
'@polkadot/api-(codec|format|jsonrpc|provider|rx)(.*)$': '<rootDir>/packages/api-$1/src/$2',
|
||||
'@polkadot/api-(codec|jsonrpc|provider|rx)(.*)$': '<rootDir>/packages/api-$1/src/$2',
|
||||
'@polkadot/api(.*)$': '<rootDir>/packages/api/src/$1',
|
||||
'@polkadot/extrinsics(.*)$': '<rootDir>/packages/type-extrinsics/src/$1',
|
||||
'@polkadot/jsonrpc(.*)$': '<rootDir>/packages/type-jsonrpc/src/$1',
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-codec#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@polkadot/util": "^0.30.4",
|
||||
"@polkadot/util-keyring": "^0.30.4"
|
||||
"@polkadot/util": "^0.30.7",
|
||||
"@polkadot/util-keyring": "^0.30.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,10 +114,12 @@ export default class Address extends Base<AccountId | AccountIndex> {
|
||||
return this.raw.toString();
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
return u8aConcat(
|
||||
Address.writeLength(this.raw.byteLength()),
|
||||
this.raw.toU8a()
|
||||
);
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return isBare
|
||||
? this.raw.toU8a(true)
|
||||
: u8aConcat(
|
||||
Address.writeLength(this.raw.byteLength()),
|
||||
this.raw.toU8a(isBare)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export default class Bool extends Base<boolean> {
|
||||
return this.raw;
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return new Uint8Array([this.raw ? 1 : 0]);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,9 +48,9 @@ export default class Bytes extends U8a {
|
||||
return this;
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return u8aConcat(
|
||||
this._length.toU8a(),
|
||||
this._length.toU8a(isBare),
|
||||
this.raw
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { AnyU8a } from './types';
|
||||
|
||||
import Option from './codec/Option';
|
||||
import Struct from './codec/Struct';
|
||||
import Tuple from './codec/Tuple';
|
||||
import StorageData from './StorageData';
|
||||
import StorageKey from './StorageKey';
|
||||
|
||||
@@ -41,8 +42,9 @@ export type KeyValueOptionValue = {
|
||||
};
|
||||
|
||||
// A key/value change. This is similar to the KeyValue structure,
|
||||
// however in this case the value could be optional.
|
||||
export class KeyValueOption extends Struct {
|
||||
// however in this case the value could be optional. Here it extends
|
||||
// from a Tuple, indicating the use inside areas such as StorageChangeSet
|
||||
export class KeyValueOption extends Tuple {
|
||||
constructor (value?: KeyValueOptionValue) {
|
||||
super({
|
||||
key: StorageKey,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2,6 +2,8 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { AnyNumber } from './types';
|
||||
|
||||
import Vector from './codec/Vector';
|
||||
import Base from './codec/Base';
|
||||
import Enum from './codec/Enum';
|
||||
@@ -17,12 +19,12 @@ import U16 from './U16';
|
||||
// end and work up. (Just so we don't use before definition)
|
||||
|
||||
export class EventMetadata extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
arguments: Vector.with(Type),
|
||||
documentation: Vector.with(Text)
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get arguments (): Vector<Type> {
|
||||
@@ -39,11 +41,11 @@ export class EventMetadata extends Struct {
|
||||
}
|
||||
|
||||
export class OuterEventMetadataEvent extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
events: Vector.with(EventMetadata)
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get events (): Vector<EventMetadata> {
|
||||
@@ -56,11 +58,11 @@ export class OuterEventMetadataEvent extends Struct {
|
||||
}
|
||||
|
||||
export class OuterEventMetadata extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
events: Vector.with(OuterEventMetadataEvent)
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get events (): Vector<OuterEventMetadataEvent> {
|
||||
@@ -73,11 +75,11 @@ export class OuterEventMetadata extends Struct {
|
||||
}
|
||||
|
||||
export class FunctionArgumentMetadata extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
type: Type
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get name (): Text {
|
||||
@@ -90,13 +92,13 @@ export class FunctionArgumentMetadata extends Struct {
|
||||
}
|
||||
|
||||
export class FunctionMetadata extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
id: U16,
|
||||
name: Text,
|
||||
arguments: Vector.with(FunctionArgumentMetadata),
|
||||
documentation: Vector.with(Text)
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get arguments (): Vector<FunctionArgumentMetadata> {
|
||||
@@ -117,11 +119,11 @@ export class FunctionMetadata extends Struct {
|
||||
}
|
||||
|
||||
export class CallMetadata extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
functions: Vector.with(FunctionMetadata)
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get functions (): Vector<FunctionMetadata> {
|
||||
@@ -134,11 +136,11 @@ export class CallMetadata extends Struct {
|
||||
}
|
||||
|
||||
export class ModuleMetadata extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
name: Text,
|
||||
call: CallMetadata
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get call (): CallMetadata {
|
||||
@@ -151,17 +153,17 @@ export class ModuleMetadata extends Struct {
|
||||
}
|
||||
|
||||
export class StorageFunctionModifier extends Enum {
|
||||
constructor () {
|
||||
super(['None', 'Default', 'Required']);
|
||||
constructor (value?: any) {
|
||||
super(['None', 'Default', 'Required'], value);
|
||||
}
|
||||
}
|
||||
|
||||
export class StorageFunctionType$Map extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
key: Type,
|
||||
value: Type
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get key (): Type {
|
||||
@@ -192,16 +194,29 @@ export class StorageFunctionType extends EnumType<Type | StorageFunctionType$Map
|
||||
get asType (): Type {
|
||||
return (this.raw as Base<Type>).raw;
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
return this.isMap
|
||||
? this.asMap.value.toString()
|
||||
: this.asType.toString();
|
||||
}
|
||||
}
|
||||
|
||||
type StorageFunctionMetadataValue = {
|
||||
name?: string | Text,
|
||||
modifier?: StorageFunctionModifier | AnyNumber,
|
||||
type?: StorageFunctionType,
|
||||
documentation?: Vector<Text> | Array<string>
|
||||
};
|
||||
|
||||
export class StorageFunctionMetadata extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: StorageFunctionMetadataValue) {
|
||||
super({
|
||||
name: Text,
|
||||
modifier: StorageFunctionModifier,
|
||||
type: StorageFunctionType,
|
||||
documentation: Vector.with(Text)
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get documentation (): Vector<Text> {
|
||||
@@ -222,11 +237,11 @@ export class StorageFunctionMetadata extends Struct {
|
||||
}
|
||||
|
||||
export class StorageMetadata extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
prefix: Text,
|
||||
functions: Vector.with(StorageFunctionMetadata)
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get functions (): Vector<StorageFunctionMetadata> {
|
||||
@@ -239,12 +254,12 @@ export class StorageMetadata extends Struct {
|
||||
}
|
||||
|
||||
export class RuntimeModuleMetadata extends Struct {
|
||||
constructor () {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
prefix: Text,
|
||||
module: ModuleMetadata,
|
||||
storage: Option.with(StorageMetadata)
|
||||
});
|
||||
}, value);
|
||||
}
|
||||
|
||||
get module (): ModuleMetadata {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import BN from 'bn.js';
|
||||
import bnToBn from '@polkadot/util/bn/toBn';
|
||||
import bnToU8a from '@polkadot/util/bn/toU8a';
|
||||
import isU8a from '@polkadot/util/is/u8a';
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
|
||||
import Base from './codec/Base';
|
||||
@@ -16,8 +17,7 @@ const BITLENGTH = 64;
|
||||
// per-second. For any encoding/decoding the 1000 multiplier would be applied to
|
||||
// get it in line with JavaScript formats
|
||||
export default class Moment extends Base<Date> {
|
||||
// NOTE
|
||||
constructor (value: Moment | Date | number = 0) {
|
||||
constructor (value: Uint8Array | Moment | Date | number = 0) {
|
||||
super(
|
||||
value instanceof Date
|
||||
? new Date(Math.ceil(value.getTime() / 1000) * 1000)
|
||||
@@ -25,12 +25,16 @@ export default class Moment extends Base<Date> {
|
||||
);
|
||||
}
|
||||
|
||||
static decode (value: Moment | number | BN): Date {
|
||||
return value instanceof Moment
|
||||
? value.raw
|
||||
: new Date(
|
||||
bnToBn(value).toNumber() * 1000
|
||||
);
|
||||
static decode (value: Uint8Array | Moment | number | BN): Date {
|
||||
if (value instanceof Moment) {
|
||||
return value.raw;
|
||||
} if (isU8a(value)) {
|
||||
value = u8aToBn(value, true);
|
||||
}
|
||||
|
||||
return new Date(
|
||||
bnToBn(value).toNumber() * 1000
|
||||
);
|
||||
}
|
||||
|
||||
byteLength (): number {
|
||||
@@ -55,7 +59,7 @@ export default class Moment extends Base<Date> {
|
||||
return this.toNumber();
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return bnToU8a(this.toNumber(), BITLENGTH, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,62 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import Bytes from './Bytes';
|
||||
import { AnyU8a } from './types';
|
||||
|
||||
// A representation of a storage key (typically hashed) in the system
|
||||
export default class StorageKey extends Bytes {
|
||||
import isFunction from '@polkadot/util/is/function';
|
||||
import toU8a from '@polkadot/util/u8a/toU8a';
|
||||
|
||||
import U8a from './codec/U8a';
|
||||
import Bytes from './Bytes';
|
||||
import { StorageFunctionMetadata } from './Metadata';
|
||||
|
||||
export interface StorageFunction {
|
||||
(arg?: any): Uint8Array;
|
||||
meta: StorageFunctionMetadata;
|
||||
}
|
||||
|
||||
// A representation of a storage key (typically hashed) in the system. It can be constructed
|
||||
// by passing in a raw key or a StorageFunction with (optional) arguments.
|
||||
export default class StorageKey extends Bytes {
|
||||
private _outputType: string | null;
|
||||
|
||||
constructor (value: AnyU8a | StorageKey | StorageFunction | [StorageFunction, any]) {
|
||||
super(StorageKey.encode(value));
|
||||
|
||||
this._outputType = StorageKey.getType(value as StorageKey);
|
||||
}
|
||||
|
||||
static encode (value: AnyU8a | StorageKey | StorageFunction | [StorageFunction, any]): Uint8Array {
|
||||
if (value instanceof StorageKey || value instanceof U8a) {
|
||||
return value.raw;
|
||||
} else if (isFunction(value)) {
|
||||
return value();
|
||||
} else if (Array.isArray(value)) {
|
||||
const [fn, arg] = value;
|
||||
|
||||
if (isFunction(fn)) {
|
||||
return fn(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return toU8a(value);
|
||||
}
|
||||
|
||||
static getType (value: StorageKey | StorageFunction | [StorageFunction, any]): string | null {
|
||||
if (value instanceof StorageKey) {
|
||||
return value.outputType;
|
||||
} else if (isFunction(value)) {
|
||||
return value.meta.type.toString();
|
||||
} else if (Array.isArray(value)) {
|
||||
const [fn] = value;
|
||||
|
||||
return fn.meta.type.toString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
get outputType (): string | null {
|
||||
return this._outputType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,14 +66,14 @@ export default class Text extends Base<string> {
|
||||
return this.raw;
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
// NOTE Since we trim in the fromU8a, here we re-calculate the actual length
|
||||
const encoded = u8aFromUtf8(this.raw);
|
||||
|
||||
this._length.setValue(encoded.length);
|
||||
|
||||
return u8aConcat(
|
||||
this._length.toU8a(),
|
||||
this._length.toU8a(isBare),
|
||||
encoded
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export default class Type extends Text {
|
||||
// Note Since we are mangling what we get in beyond recognition, we really should
|
||||
// not allow the re-encoding. Additionally, this is probably more of a decoder-only
|
||||
// helper, so treat it as such.
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
throw new Error('Type::toU8a: unimplemented');
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import logger from '@polkadot/util/logger';
|
||||
|
||||
export const l = logger('codec');
|
||||
|
||||
// The actual base class for any type. As it stands, this should not be used on it's own,
|
||||
// so we expose the interface, but throw on anything. This allows subclasses to actaully
|
||||
// only implement part (things that are unused/unexpected should just error-out)
|
||||
@@ -38,7 +42,7 @@ export default class Base <T = any> {
|
||||
throw new Error('Base::toString: unimplemented');
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
throw new Error('Base::toU8a: unimplemented');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ export default class Enum extends Base<number> {
|
||||
return this.raw;
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return new Uint8Array([this.raw]);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ export default class EnumType <T> extends Base<Base<T>> {
|
||||
private _index: number;
|
||||
private _indexes: Array<number>;
|
||||
|
||||
constructor (def: TypesDef, index?: number, value?: any) {
|
||||
constructor (def: TypesDef, index?: number | EnumType<T>, value?: any) {
|
||||
super(
|
||||
new (Object.values(def)[0])()
|
||||
);
|
||||
@@ -52,7 +52,14 @@ export default class EnumType <T> extends Base<Base<T>> {
|
||||
return this;
|
||||
}
|
||||
|
||||
setValue (index?: number, value?: any): void {
|
||||
setValue (index?: | EnumType<T> | number, value?: any): void {
|
||||
if (index instanceof EnumType) {
|
||||
this._index = index._index;
|
||||
this.raw = new this._Types[this._index](index.raw);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._index = this._indexes.indexOf(index || 0);
|
||||
|
||||
if (this._index === -1) {
|
||||
|
||||
@@ -95,8 +95,10 @@ export default class Length extends Base<BN> {
|
||||
return this.raw.toNumber();
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
return Length.encode(this.raw);
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return isBare
|
||||
? new Uint8Array()
|
||||
: Length.encode(this.raw);
|
||||
}
|
||||
|
||||
setValue (value: BN | number): void {
|
||||
|
||||
@@ -73,7 +73,11 @@ export default class Option <T> extends Base<Base<T>> {
|
||||
: this.raw.toJSON();
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
if (isBare) {
|
||||
return this.raw.toU8a(true);
|
||||
}
|
||||
|
||||
const u8a = new Uint8Array(this.byteLength());
|
||||
|
||||
if (!this._isEmpty) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
import Base from './Base';
|
||||
import Base, { l } from './Base';
|
||||
|
||||
// A Struct defines an Object with key/values - where the values are Base<T> values. It removes
|
||||
// a lot of repetition from the actual coding, define a structure type, pass it the key/Base<T>
|
||||
@@ -24,19 +24,9 @@ export default class Struct <
|
||||
protected _jsonMap: Map<keyof S, string>;
|
||||
protected _Types: E;
|
||||
|
||||
constructor (Types: S, value: V = {} as V, jsonMap: Map<keyof S, string> = new Map()) {
|
||||
constructor (Types: S, value: V | Array<any> = {} as V, jsonMap: Map<keyof S, string> = new Map(), isTuple: boolean = false) {
|
||||
super(
|
||||
Object
|
||||
.keys(Types)
|
||||
.reduce((raw: T, key) => {
|
||||
// @ts-ignore FIXME Ok, something weird is going on here or I just don't get it...
|
||||
// it works, so ignore the checker, although it drives me batty. (It started when
|
||||
// the [key in keyof T] was added, the idea is to provide better checks, which
|
||||
// does backfire here, but works externally.)
|
||||
raw[key] = new Types[key](value[key]);
|
||||
|
||||
return raw;
|
||||
}, {} as T)
|
||||
Struct.decode(Types, value, isTuple)
|
||||
);
|
||||
|
||||
this._jsonMap = jsonMap;
|
||||
@@ -50,6 +40,27 @@ export default class Struct <
|
||||
}, {} as E);
|
||||
}
|
||||
|
||||
static decode <S, V, T> (Types: S, value: V | Array<any>, isTuple: boolean): T {
|
||||
l.debug(() => ['Struct.decode', { Types, value }]);
|
||||
|
||||
return Object
|
||||
.keys(Types)
|
||||
.reduce((raw: T, key, index) => {
|
||||
// @ts-ignore FIXME Ok, something weird is going on here or I just don't get it...
|
||||
// it works, so ignore the checker, although it drives me batty. (It started when
|
||||
// the [key in keyof T] was added, the idea is to provide better checks, which
|
||||
// does backfire here, but works externally.)
|
||||
raw[key] = new Types[key](
|
||||
isTuple && Array.isArray(value)
|
||||
? value[index]
|
||||
// @ts-ignore as above
|
||||
: value[key]
|
||||
);
|
||||
|
||||
return raw;
|
||||
}, {} as T);
|
||||
}
|
||||
|
||||
static with <
|
||||
S = { [index: string]: { new(value?: any): Base } }
|
||||
> (Types: S): { new(value?: any): Struct<S> } {
|
||||
@@ -106,10 +117,10 @@ export default class Struct <
|
||||
return Object.keys(this.raw);
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return u8aConcat(
|
||||
...Object.values(this.raw).map((entry) =>
|
||||
entry.toU8a()
|
||||
entry.toU8a(isBare)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,10 +9,15 @@ import Struct from './Struct';
|
||||
// is a specialization of the Struct type where the toJSON/fromJSON operates on Array structures,
|
||||
// while the U8a encoding is handled in the same way as a Struct
|
||||
export default class Tuple <
|
||||
// S & T definitions maps to what we have in Struct (naming expanded there)
|
||||
// S & T definitions maps to what we have in Struct (naming documented there)
|
||||
S = { [index: string]: { new(value?: any): Base } },
|
||||
T = { [K in keyof S]: Base }
|
||||
> extends Struct<S, T> {
|
||||
T = { [K in keyof S]: Base },
|
||||
V = { [K in keyof S]: any }
|
||||
> extends Struct<S, T, V> {
|
||||
constructor (Types: S, value?: V | Array<any>, jsonMap?: Map<keyof S, string>) {
|
||||
super(Types, value, jsonMap, true);
|
||||
}
|
||||
|
||||
static with <
|
||||
S = { [index: string]: { new(value?: any): Base } }
|
||||
> (Types: S): { new(value?: any): Tuple<S> } {
|
||||
@@ -23,7 +28,7 @@ export default class Tuple <
|
||||
};
|
||||
}
|
||||
|
||||
fromJSON (input: any): Tuple<S, T> {
|
||||
fromJSON (input: any): Tuple<S, T, V> {
|
||||
Object.values(this.raw).forEach((entry, index) => {
|
||||
entry.fromJSON(input[index]);
|
||||
});
|
||||
|
||||
@@ -50,7 +50,7 @@ export default class U8a extends Base<Uint8Array> {
|
||||
return this.toHex();
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return this.raw;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import { AnyNumber } from '../types';
|
||||
import BN from 'bn.js';
|
||||
import isHex from '@polkadot/util/is/hex';
|
||||
import isString from '@polkadot/util/is/string';
|
||||
import isU8a from '@polkadot/util/is/u8a';
|
||||
import bnToBn from '@polkadot/util/bn/toBn';
|
||||
import bnToHex from '@polkadot/util/bn/toHex';
|
||||
import bnToU8a from '@polkadot/util/bn/toU8a';
|
||||
@@ -39,6 +40,9 @@ export default class UInt extends Base<BN> {
|
||||
return value.raw;
|
||||
} else if (isHex(value)) {
|
||||
return hexToBn(value as string);
|
||||
} else if (isU8a(value)) {
|
||||
// NOTE When passing u8a in (typically from decoded data), it is always u8a
|
||||
return u8aToBn(value, true);
|
||||
} else if (isString(value)) {
|
||||
return new BN(value, 10);
|
||||
}
|
||||
@@ -70,7 +74,7 @@ export default class UInt extends Base<BN> {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return bnToU8a(this.raw, this._bitLength, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,11 +53,15 @@ export default class Vector <
|
||||
}, this._length.byteLength());
|
||||
}
|
||||
|
||||
filter (fn: (entry: T, index?: number) => any): Array<T> {
|
||||
filter (fn: (item: T, index?: number) => any): Array<T> {
|
||||
return this.raw.filter(fn);
|
||||
}
|
||||
|
||||
forEach (fn: (entry: T, index?: number) => any): any {
|
||||
find (fn: (item: T, index?: number) => any): T | undefined {
|
||||
return this.raw.find(fn);
|
||||
}
|
||||
|
||||
forEach (fn: (item: T, index?: number) => any): any {
|
||||
return this.raw.forEach(fn);
|
||||
}
|
||||
|
||||
@@ -90,11 +94,16 @@ export default class Vector <
|
||||
return this.raw[index];
|
||||
}
|
||||
|
||||
map <O> (fn: (entry: T, index?: number) => O): Array<O> {
|
||||
map <O> (fn: (item: T, index?: number) => O): Array<O> {
|
||||
return this.raw.map(fn);
|
||||
}
|
||||
|
||||
reduce <O> (fn: (result: O, entry: T, index?: number) => O, initial: O): O {
|
||||
push (item: T): void {
|
||||
this.raw.push(item);
|
||||
this._length.setValue(this.raw.length);
|
||||
}
|
||||
|
||||
reduce <O> (fn: (result: O, item: T, index?: number) => O, initial: O): O {
|
||||
return this.raw.reduce(fn, initial);
|
||||
}
|
||||
|
||||
@@ -104,11 +113,11 @@ export default class Vector <
|
||||
);
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return u8aConcat(
|
||||
this._length.toU8a(),
|
||||
this._length.toU8a(isBare),
|
||||
...this.raw.map((entry) =>
|
||||
entry.toU8a()
|
||||
entry.toU8a(isBare)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright 2017-2018 @polkadot/api-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { typeSplit, getType, getTupleType, getVectorType } from './createType';
|
||||
|
||||
describe('typeSplit', () => {
|
||||
it('splits simple types into an array', () => {
|
||||
expect(
|
||||
typeSplit('Text, u32, u64')
|
||||
).toEqual(['Text', 'u32', 'u64']);
|
||||
});
|
||||
|
||||
it('splits nested combinations', () => {
|
||||
expect(
|
||||
typeSplit('Text, (u32), Vec<u64>')
|
||||
).toEqual(['Text', '(u32)', 'Vec<u64>']);
|
||||
});
|
||||
|
||||
it('keeps nested tuples together', () => {
|
||||
expect(
|
||||
typeSplit('Text, (u32, u128), Vec<u64>')
|
||||
).toEqual(['Text', '(u32, u128)', 'Vec<u64>']);
|
||||
});
|
||||
|
||||
it('keeps nested vector tuples together', () => {
|
||||
expect(
|
||||
typeSplit('Text, (u32, u128), Vec<(u64, u32)>')
|
||||
).toEqual(['Text', '(u32, u128)', 'Vec<(u64, u32)>']);
|
||||
});
|
||||
|
||||
it('allows for deep nesting', () => {
|
||||
expect(
|
||||
typeSplit('Text, (u32, (u128, u8)), Vec<(u64, (u32, u32))>')
|
||||
).toEqual(['Text', '(u32, (u128, u8))', 'Vec<(u64, (u32, u32))>']);
|
||||
});
|
||||
|
||||
it('checks for unclosed vec', () => {
|
||||
expect(
|
||||
() => typeSplit('Text, Vec<u64')
|
||||
).toThrow(/Invalid Vector/);
|
||||
});
|
||||
|
||||
it('checks for unclosed tuple', () => {
|
||||
expect(
|
||||
() => typeSplit('Text, (u64, u32')
|
||||
).toThrow(/Invalid Tuple/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTupleType', () => {
|
||||
it('does not allow invalid tuples, end )', () => {
|
||||
expect(
|
||||
() => getTupleType('(u64, u32')
|
||||
).toThrow(/tuple wrapped/);
|
||||
});
|
||||
|
||||
it('does not allow invalid tuples, start (', () => {
|
||||
expect(
|
||||
() => getTupleType('u64, u32)')
|
||||
).toThrow(/tuple wrapped/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getVectorType', () => {
|
||||
it('does not allow invalid vectors, end >', () => {
|
||||
expect(
|
||||
() => getVectorType('Vec<u64')
|
||||
).toThrow(/Vec wrapped/);
|
||||
});
|
||||
|
||||
it('does not allow invalid vectors, start Vec<', () => {
|
||||
expect(
|
||||
() => getVectorType('u64>')
|
||||
).toThrow(/Vec wrapped/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getType', () => {
|
||||
it('does not allow invalid types', () => {
|
||||
expect(
|
||||
() => getType('SomethingInvalid')
|
||||
).toThrow(/determine type/);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,123 @@
|
||||
// Copyright 2017-2018 @polkadot/api-codec authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import assert from '@polkadot/util/assert';
|
||||
|
||||
import * as Types from '../index';
|
||||
import Base, { l } from './Base';
|
||||
import Tuple from './Tuple';
|
||||
import Vector from './Vector';
|
||||
|
||||
type Constructor = { new (value?: any): Base };
|
||||
|
||||
// safely split a string on ', ' while taking care of any nested occurences
|
||||
export function typeSplit (type: string): Array<string> {
|
||||
let tDepth = 0;
|
||||
let vDepth = 0;
|
||||
let start = 0;
|
||||
const result = [];
|
||||
|
||||
for (let index = 0; index < type.length; index++) {
|
||||
switch (type[index]) {
|
||||
case ',':
|
||||
// we are not nested, add the type
|
||||
if (tDepth === 0 && vDepth === 0) {
|
||||
result.push(type.substr(start, index - start).trim());
|
||||
start = index + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '(':
|
||||
// inc tuple depth
|
||||
tDepth++;
|
||||
break;
|
||||
|
||||
case ')':
|
||||
// dec tuple depth
|
||||
tDepth--;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
// inc vec depth
|
||||
vDepth++;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
// dec tuple depth
|
||||
vDepth--;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(tDepth === 0, `Invalid Tuple in ${type}`);
|
||||
assert(vDepth === 0, `Invalid Vector in ${type}`);
|
||||
|
||||
// the final leg of the journey
|
||||
result.push(type.substr(start, type.length - start).trim());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Handle Vector types, i.e Vec<AccountId> or Vec<(AccountId, Balance)>
|
||||
export function getVectorType (type: string): Constructor {
|
||||
l.debug(() => ['getVectorType', { type }]);
|
||||
|
||||
assert(type.substr(0, 4) === 'Vec<' && type[type.length - 1] === '>', `Expected Vec wrapped with <>`);
|
||||
|
||||
// strip wrapping Vec<>
|
||||
const subType = type.substr(4, type.length - 5);
|
||||
|
||||
return Vector.with(
|
||||
getType(subType)
|
||||
);
|
||||
}
|
||||
|
||||
// Handle tuple types, (u32, String, AccountId). It could be nested and wrapped in other
|
||||
// types, i.e. (u32, Vec<(AccountId, Balance)>)
|
||||
export function getTupleType (type: string): Constructor {
|
||||
l.debug(() => ['getTupleType', { type }]);
|
||||
|
||||
assert(type[0] === '(' && type[type.length - 1] === ')', `Expected tuple wrapped with ()`);
|
||||
|
||||
// strip wrapping ()'s
|
||||
const innerTypes = typeSplit(type.substr(1, type.length - 2));
|
||||
|
||||
return Tuple.with(
|
||||
innerTypes.reduce((result, type, index) => {
|
||||
result[`entry${index}`] = getType(type);
|
||||
|
||||
return result;
|
||||
}, {} as { [index: string]: Constructor })
|
||||
);
|
||||
}
|
||||
|
||||
// Returns the type Class for construction
|
||||
export function getType (_type: string): Constructor {
|
||||
const type = _type.trim();
|
||||
|
||||
l.debug(() => ['getType', { type }]);
|
||||
|
||||
if (type[0] === '(') {
|
||||
return getTupleType(type);
|
||||
} else if (type.substr(0, 4) === 'Vec<') {
|
||||
return getVectorType(type);
|
||||
}
|
||||
|
||||
const Type = (Types as any)[type];
|
||||
|
||||
assert(Type, `Unable to determine type from '${type}'`);
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
export default function createType (type: string, value?: any): Base {
|
||||
l.debug(() => ['createType', { type, value }]);
|
||||
|
||||
const Type = getType(type);
|
||||
|
||||
return new Type(value);
|
||||
}
|
||||
@@ -11,3 +11,5 @@ export { default as Base } from './Base';
|
||||
export { default as Struct } from './Struct';
|
||||
export { default as Tuple } from './Tuple';
|
||||
export { default as Vector } from './Vector';
|
||||
|
||||
export { default as createType } from './createType';
|
||||
|
||||
@@ -52,12 +52,13 @@ export { default as StorageKey } from './StorageKey';
|
||||
export { default as Text } from './Text';
|
||||
// NOTE Type is currently only used internally (possibly in codec-related work)
|
||||
// export { default as Type } from './Type';
|
||||
export { default as U8 } from './U8';
|
||||
export { default as U16 } from './U16';
|
||||
export { default as U32 } from './U32';
|
||||
export { default as U64 } from './U64';
|
||||
export { default as U128 } from './U128';
|
||||
export { default as U256 } from './U256';
|
||||
// NOTE We are exporting the U* classes as lowercase, matching with Rust
|
||||
export { default as u8 } from './U8';
|
||||
export { default as u16 } from './U16';
|
||||
export { default as u32 } from './U32';
|
||||
export { default as u64 } from './U64';
|
||||
export { default as u128 } from './U128';
|
||||
export { default as u256 } from './U256';
|
||||
export { default as ValidatorPrefs } from './ValidatorPrefs';
|
||||
export { default as VoteThreshold } from './VoteThreshold';
|
||||
export { default as VoteIndex } from './VoteIndex';
|
||||
|
||||
Vendored
+1
-1
@@ -7,6 +7,6 @@ import BN from 'bn.js';
|
||||
import U8a from './codec/U8a';
|
||||
import UInt from './codec/UInt';
|
||||
|
||||
export type AnyNumber = UInt | BN | number | string;
|
||||
export type AnyNumber = UInt | BN | Uint8Array | number | string;
|
||||
|
||||
export type AnyU8a = U8a | Uint8Array | Array<number> | string;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
ISC License (ISC)
|
||||
|
||||
Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
@@ -1,21 +0,0 @@
|
||||
[](https://polkadot.js.org)
|
||||

|
||||
[](https://github.com/Flet/semistandard)
|
||||
[](https://www.npmjs.com/package/@polkadot/api-format)
|
||||
[](https://travis-ci.org/polkadot-js/api)
|
||||
[](https://codeclimate.com/github/polkadot-js/api/maintainability)
|
||||
[](https://coveralls.io/github/polkadot-js/api?branch=master)
|
||||
[](https://david-dm.org/polkadot-js/api?path=packages/api-format)
|
||||
[](https://david-dm.org/polkadot-js/api?path=packages/api-format#info=devDependencies)
|
||||
|
||||
# @polkadot/api-format
|
||||
|
||||
Formatters that are used by the application API interface, taking care of transparently formatting parameters (inputs) and the results (output) for requests made over the client RPC interfaces.
|
||||
|
||||
## Usage
|
||||
|
||||
Installation -
|
||||
|
||||
```
|
||||
npm install --save @polkadot/api-format
|
||||
```
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"name": "@polkadot/api-format",
|
||||
"version": "0.30.1",
|
||||
"description": "Input/Output formatters for JsonRPC exchange",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
"Polkadot",
|
||||
"JsonRPC"
|
||||
],
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
],
|
||||
"contributors": [],
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=6.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/polkadot-js/api.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/polkadot-js/api/issues"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-format#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@polkadot/api-codec": "^0.30.1",
|
||||
"@polkadot/jsonrpc": "^0.30.1",
|
||||
"@polkadot/primitives": "^0.30.1",
|
||||
"@polkadot/util": "^0.30.4",
|
||||
"@polkadot/util-keyring": "^0.30.4"
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import echo from './echo';
|
||||
|
||||
describe('echo', () => {
|
||||
it('returns input value as output value', () => {
|
||||
const input = { 'some': 'object' };
|
||||
|
||||
expect(
|
||||
echo(input)
|
||||
).toEqual(input);
|
||||
});
|
||||
});
|
||||
@@ -1,12 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
/**
|
||||
* A function returning any value passed to it
|
||||
* @param {any} value The input value
|
||||
* @return {any} The value passed as input
|
||||
*/
|
||||
export default function echo (value: any): any {
|
||||
return value;
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import format from './format';
|
||||
import echo from './echo';
|
||||
|
||||
describe('format', () => {
|
||||
let formatters;
|
||||
let echoSpy;
|
||||
let warnSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
echoSpy = jest.fn(echo);
|
||||
warnSpy = jest.spyOn(console, 'log');
|
||||
|
||||
formatters = new Map([
|
||||
['Address', echoSpy],
|
||||
['Exception', () => {
|
||||
throw new Error('something went wrong');
|
||||
}]
|
||||
]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
echoSpy.mockRestore();
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('formats unknown types with a fallback', () => {
|
||||
expect(
|
||||
format(formatters, ['Unknown'], ['test'])
|
||||
).toEqual(['test']);
|
||||
});
|
||||
|
||||
it('logs a warning with unknown types', () => {
|
||||
format(formatters, ['Unknown'], ['test']);
|
||||
expect(warnSpy).toHaveBeenCalledWith(
|
||||
expect.anything(), expect.anything(), "Unable to find default formatter for 'Unknown', falling back to echo"
|
||||
);
|
||||
});
|
||||
|
||||
it('wraps exceptions with the type', () => {
|
||||
expect(
|
||||
() => format(formatters, ['Exception'], ['test'])
|
||||
).toThrow(/Error formatting 'test' as 'Exception'/);
|
||||
});
|
||||
|
||||
describe('primitives', () => {
|
||||
it('formats known types using the supplied formatter', () => {
|
||||
format(formatters, ['Address'], ['0xaddress']);
|
||||
|
||||
expect(echoSpy).toHaveBeenCalledWith('0xaddress');
|
||||
});
|
||||
});
|
||||
|
||||
describe('primitive[]', () => {
|
||||
it('formats using the primitive type', () => {
|
||||
format(formatters, [['Address']], [['0x123', '0x234']]);
|
||||
|
||||
expect(echoSpy).toHaveBeenCalledWith('0x123');
|
||||
expect(echoSpy).toHaveBeenCalledWith('0x234');
|
||||
});
|
||||
|
||||
it('returns formatted values as arrays', () => {
|
||||
expect(
|
||||
format(formatters, [['Address']], [['0x123', '0x234']])
|
||||
).toEqual([['0x123', '0x234']]);
|
||||
});
|
||||
});
|
||||
|
||||
it('formats each value in an array', () => {
|
||||
expect(
|
||||
format(formatters, ['Unknown', 'Unknown'], ['test', 'blah'])
|
||||
).toEqual(['test', 'blah']);
|
||||
});
|
||||
});
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Storages } from '@polkadot/storage/types';
|
||||
import { SectionItem, Param$Types, Param$Type$Array } from '@polkadot/params/types';
|
||||
import { FormattersFunctionMap } from './types';
|
||||
|
||||
import typeToString from '@polkadot/params/typeToString';
|
||||
import isUndefined from '@polkadot/util/is/undefined';
|
||||
import logger from '@polkadot/util/logger';
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
import createStorageKey from '@polkadot/storage/key';
|
||||
|
||||
import echo from './echo';
|
||||
|
||||
const l = logger('api-format');
|
||||
|
||||
function formatSingleType (formatters: FormattersFunctionMap, type: Param$Types, value: any): any {
|
||||
if (type === 'StorageKey') {
|
||||
const [key, ...params]: [SectionItem<Storages>, Array<any>] = value;
|
||||
|
||||
return u8aToHex(
|
||||
createStorageKey(key).apply(null, params)
|
||||
);
|
||||
}
|
||||
|
||||
const formatter = formatters.get(type);
|
||||
|
||||
if (isUndefined(formatter)) {
|
||||
l.debug(() => `Unable to find default formatter for '${typeToString(type)}', falling back to echo`);
|
||||
|
||||
return echo(value);
|
||||
}
|
||||
|
||||
try {
|
||||
return formatter(value);
|
||||
} catch (error) {
|
||||
throw new Error(`Error formatting '${value.toString()}' as '${typeToString(type)}': ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function formatArrayType (formatters: FormattersFunctionMap, [ type ]: Param$Type$Array, value: Array<any>): any {
|
||||
return value.map((value) => {
|
||||
return formatSingleType(formatters, type, value);
|
||||
});
|
||||
}
|
||||
|
||||
export default function format (formatters: FormattersFunctionMap, types: Array<Param$Types>, values: Array<any>): Array<any> {
|
||||
return values.map((value, index): any => {
|
||||
const type = types[index];
|
||||
|
||||
if (Array.isArray(type)) {
|
||||
// FIXME we are currently not catering for tuples
|
||||
return formatArrayType(formatters, type, value);
|
||||
}
|
||||
|
||||
return formatSingleType(formatters, type, value);
|
||||
});
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import formatInputs from './input';
|
||||
import formatOutput from './output';
|
||||
|
||||
export {
|
||||
formatInputs,
|
||||
formatOutput
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { formatInputs } from './index';
|
||||
|
||||
describe('formatInputs', () => {
|
||||
it('formats each value in an array', () => {
|
||||
expect(
|
||||
formatInputs(
|
||||
[
|
||||
{ name: 'foo', type: 'Bytes' },
|
||||
{ name: 'bar', type: 'Hash' }
|
||||
],
|
||||
[
|
||||
new Uint8Array([0x12, 0x34]),
|
||||
new Uint8Array([0xab, 0xcd])
|
||||
]
|
||||
)
|
||||
).toEqual([
|
||||
'0x1234',
|
||||
'0xabcd'
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Params, Param$Types } from '@polkadot/params/types';
|
||||
import { FormatterFunction } from './types';
|
||||
|
||||
import assert from '@polkadot/util/assert';
|
||||
import addressDecode from '@polkadot/util-keyring/address/decode';
|
||||
import bytesEncode from '@polkadot/primitives/json/bytes/encode';
|
||||
import hashEncode from '@polkadot/primitives/json/hash/encode';
|
||||
|
||||
import format from './format';
|
||||
|
||||
const formatters = new Map<Param$Types, FormatterFunction>([
|
||||
// funnily named, goes from address -> u8a
|
||||
['AccountId', addressDecode],
|
||||
['Bytes', bytesEncode],
|
||||
['Hash', hashEncode]
|
||||
]);
|
||||
|
||||
export default function formatInputs (params: Params, values: Array<any>): Array<any> {
|
||||
const required = params.filter(({ isOptional }) => !isOptional);
|
||||
const optionalText = params.length
|
||||
? ` (${(params.length - required.length) || 'none'} optional)`
|
||||
: '';
|
||||
|
||||
assert(values.length >= required.length && values.length <= params.length, `${params.length || 'no'} params expected${optionalText}, found ${values.length} instead`);
|
||||
|
||||
const types = params.map(({ type }) => type);
|
||||
|
||||
return format(formatters, types, values);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import { formatOutput } from './index';
|
||||
|
||||
describe('formatOutput', () => {
|
||||
it('formats the value', () => {
|
||||
expect(
|
||||
JSON.stringify(
|
||||
formatOutput(
|
||||
'Header',
|
||||
{
|
||||
digest: {
|
||||
logs: ['0x5678', '0x789a']
|
||||
},
|
||||
extrinsicsRoot: '0xabcd',
|
||||
number: '0x1234',
|
||||
parentHash: '0x1234',
|
||||
stateRoot: '0x5678'
|
||||
}
|
||||
)
|
||||
)
|
||||
).toEqual(
|
||||
JSON.stringify({
|
||||
digest: {
|
||||
logs: [
|
||||
new Uint8Array([0x56, 0x78]),
|
||||
new Uint8Array([0x78, 0x9a])
|
||||
]
|
||||
},
|
||||
extrinsicsRoot: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xab, 0xcd]),
|
||||
number: new BN(0x1234),
|
||||
parentHash: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0x34]),
|
||||
stateRoot: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x56, 0x78])
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Param$Types } from '@polkadot/params/types';
|
||||
import { FormatterFunction } from './types';
|
||||
|
||||
import Metadata from '@polkadot/api-codec/Metadata';
|
||||
import addressEncode from '@polkadot/util-keyring/address/encode';
|
||||
import bnDecode from '@polkadot/primitives/json/bn/decode';
|
||||
import bytesDecode from '@polkadot/primitives/json/bytes/decode';
|
||||
import hashDecode from '@polkadot/primitives/json/hash/decode';
|
||||
import headerDecode from '@polkadot/primitives/json/header/decode';
|
||||
import blockDecode from '@polkadot/primitives/json/block/decode';
|
||||
import isNull from '@polkadot/util/is/null';
|
||||
import isUndefined from '@polkadot/util/is/undefined';
|
||||
|
||||
import format from './format';
|
||||
|
||||
// NOTE Here we are trying to do things a bit differently, i.e. more in line with where we think things
|
||||
// could go with the primitive classes. (Good testbed anyway for the decoding, although maybe a bit messy
|
||||
// with duplication). Overall, bit hackly since it shoehorns in a potential new implementation into an
|
||||
// original way of doing things
|
||||
|
||||
const metaDecode = (input: Array<number>) => {
|
||||
const metadata = new Metadata();
|
||||
|
||||
try {
|
||||
metadata.fromJSON(input);
|
||||
} catch (error) {
|
||||
console.error('current', JSON.stringify(metadata.toJSON()), error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
return metadata;
|
||||
};
|
||||
|
||||
const formatters = new Map<Param$Types, FormatterFunction>([
|
||||
// publicKey -> address
|
||||
['AccountId', addressEncode],
|
||||
['BlockNumber', bnDecode],
|
||||
['Bytes', bytesDecode],
|
||||
['Hash', hashDecode],
|
||||
['Header', headerDecode],
|
||||
['Metadata', metaDecode],
|
||||
['SignedBlock', blockDecode],
|
||||
['u64', bnDecode]
|
||||
]);
|
||||
|
||||
export default function formatOutput (type: Param$Types, value?: any): any | null {
|
||||
if (isUndefined(value) || isNull(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return format(formatters, [type], [value])[0];
|
||||
}
|
||||
Vendored
-9
@@ -1,9 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-format authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { Param$Types } from '@polkadot/params/types';
|
||||
|
||||
export type FormatterFunction = (value: any) => any;
|
||||
|
||||
type FormattersFunctionMap = Map<Param$Types, FormatterFunction>;
|
||||
@@ -35,9 +35,9 @@
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@polkadot/storage": "^0.30.1",
|
||||
"@polkadot/util": "^0.30.4",
|
||||
"@polkadot/util-crypto": "^0.30.4",
|
||||
"@polkadot/util-keyring": "^0.30.4",
|
||||
"@polkadot/util": "^0.30.7",
|
||||
"@polkadot/util-crypto": "^0.30.7",
|
||||
"@polkadot/util-keyring": "^0.30.7",
|
||||
"@types/nock": "^9.1.3",
|
||||
"eventemitter3": "^3.1.0",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
|
||||
@@ -19,15 +19,14 @@ const ERROR_SUBSCRIBE = 'HTTP Provider does not have subscriptions, use WebSocke
|
||||
* The HTTP Provider allows sending requests using HTTP. it does not support subscriptions
|
||||
* so you won´t be able to listen to events such as new blocks or balance changes.
|
||||
* It is usually preferrable using the [[WsProvider]].
|
||||
* @example
|
||||
* ```javascript
|
||||
*
|
||||
* @example
|
||||
* import createApi from '@polkadot/api';
|
||||
* import WsProvider from '@polkadot/api-provider/ws';
|
||||
*
|
||||
* const provider = new WsProvider('http://127.0.0.1:9933');
|
||||
* const api = createApi(provider);
|
||||
* ```
|
||||
*
|
||||
* @see [[WsProvider]]
|
||||
*/
|
||||
export default class HttpProvider implements ProviderInterface {
|
||||
|
||||
@@ -40,15 +40,13 @@ interface WSProviderInterface extends ProviderInterface {
|
||||
/**
|
||||
* The WebSocket Provider allows sending requests using WebSocket. Unlike the [[HttpProvider]],
|
||||
* it does support subscriptions and allows listening to events such as new blocks or balance changes.
|
||||
* [[include:create_api.adoc]].
|
||||
* @example
|
||||
* ```javascript
|
||||
*
|
||||
* @example
|
||||
* import createApi from '@polkadot/api';
|
||||
* import WsProvider from '@polkadot/api-provider/ws';
|
||||
* const provider = new WsProvider('ws://127.0.0.1:9944');
|
||||
* const api = createApi(provider);
|
||||
* ```
|
||||
*
|
||||
* @see [[HttpProvider]]
|
||||
*/
|
||||
export default class WsProvider extends E3.EventEmitter implements WSProviderInterface {
|
||||
@@ -167,18 +165,16 @@ export default class WsProvider extends E3.EventEmitter implements WSProviderInt
|
||||
* @param {Array<any>} params Parameters
|
||||
* @param {ProviderInterface$Callback} callback Callback
|
||||
* @return {Promise<number>} Promise resolving to the dd of the subscription you can use with [[unsubscribe]].
|
||||
* @example
|
||||
* ```javascript
|
||||
*
|
||||
* @example
|
||||
* const provider = new WsProvider('ws://127.0.0.1:9944');
|
||||
* const api = createApi(provider);
|
||||
*
|
||||
* api.state.storage([[storage.staking.public.freeBalanceOf, <Address>]], (_, values) => {
|
||||
* api.state.storage([[storage.balances.freeBalance, <Address>]], (_, values) => {
|
||||
* console.log(values)
|
||||
* }).then((subscriptionId) => {
|
||||
* console.log('balance changes subscription id: ', subscriptionId)
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
async subscribe (type: string, method: string, params: Array<any>, callback: ProviderInterface$Callback): Promise<number> {
|
||||
const id = await this.send(method, params, { callback, type });
|
||||
|
||||
@@ -25,17 +25,4 @@ describe.skip('e2e basics', () => {
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
|
||||
it('retrieves the wasm metadata', () => {
|
||||
return api.state
|
||||
.getMetadata()
|
||||
.then((meta) => {
|
||||
console.error(JSON.stringify(meta.toJSON()));
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,8 +19,8 @@ describe.skip('e2e krumme lanke', () => {
|
||||
api.state
|
||||
.subscribeStorage(
|
||||
[
|
||||
[storage.system.public.accountIndexOf, '5Ejbye9R8ygByQPrDSasaUid1munedPZUmg4f118HGmtodGp'],
|
||||
[storage.staking.public.freeBalanceOf, '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFacT7']
|
||||
[storage.system.accountNonce, '5Ejbye9R8ygByQPrDSasaUid1munedPZUmg4f118HGmtodGp'],
|
||||
[storage.balances.freeBalance, '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFacT7']
|
||||
],
|
||||
(error, data) => {
|
||||
if (error) {
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright 2017-2018 @polkadot/api-provider authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import storage from '@polkadot/storage/testing';
|
||||
|
||||
import Api from '../../api/src';
|
||||
import Ws from '../src/ws';
|
||||
|
||||
const ALICE = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ';
|
||||
|
||||
describe.skip('e2e state', () => {
|
||||
let api;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.setTimeout(30000);
|
||||
api = new Api(new Ws('ws://127.0.0.1:9944'));
|
||||
});
|
||||
|
||||
it('retrieves code', () => {
|
||||
return api.state
|
||||
.getStorage([
|
||||
storage.substrate.code
|
||||
])
|
||||
.then((code) => {
|
||||
console.error(code.toHex().substr(0, 256), '...');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
|
||||
it('retrieves the wasm metadata', () => {
|
||||
return api.state
|
||||
.getMetadata()
|
||||
.then((meta) => {
|
||||
console.error(JSON.stringify(meta.toJSON()));
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
|
||||
it('retrieves balances', () => {
|
||||
return api.state
|
||||
.getStorage([
|
||||
storage.balances.freeBalance, ALICE
|
||||
])
|
||||
.then((balance) => {
|
||||
console.error(balance);
|
||||
|
||||
expect(balance.toBn().isZero()).not.toEqual(true);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
|
||||
it('retrieves timestamp', () => {
|
||||
return api.state
|
||||
.getStorage([
|
||||
storage.timestamp.now
|
||||
])
|
||||
.then((moment) => {
|
||||
console.error(moment);
|
||||
|
||||
expect(moment.toNumber()).not.toEqual(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -23,15 +23,13 @@ type CachedMap = {
|
||||
|
||||
/**
|
||||
* An RxJs wrapper around the [[api]].
|
||||
* @example
|
||||
* ```javascript
|
||||
*
|
||||
* @example
|
||||
* import RxApi from '@polkadot/api';
|
||||
* import WsProvider from '@polkadot/api-provider/ws';
|
||||
*
|
||||
* const provider = new WsProvider('http://127.0.0.1:9944');
|
||||
* const rxapi = new RxApi(provider);
|
||||
* ```
|
||||
*/
|
||||
export default class RxApi implements RxApiInterface {
|
||||
private _api: ApiInterface;
|
||||
|
||||
@@ -30,10 +30,9 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@polkadot/api-format": "^0.30.1",
|
||||
"@polkadot/api-provider": "^0.30.1",
|
||||
"@polkadot/jsonrpc": "^0.30.1",
|
||||
"@polkadot/params": "^0.30.1",
|
||||
"@polkadot/util": "^0.30.4"
|
||||
"@polkadot/util": "^0.30.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import storage from '@polkadot/storage';
|
||||
import storage from '@polkadot/storage/testing';
|
||||
|
||||
import Api from './index';
|
||||
|
||||
const ADDR_ONE = '5EhmTa7fL6SdjgKXo9g6hetR6nHnRAmrtisoGFWEESjzECtY';
|
||||
const ADDR_TWO = '5FjbQAHSptRU4Q7Py6zDsRnE7UkpZikJVg5nm1tmu3WuZXKd';
|
||||
|
||||
const ENC_ONE = '0x11cf1094db4db43356b7787c3e59c39f';
|
||||
const ENC_TWO = '0x924776c687da8e30afdd2ac87d2c67da';
|
||||
const ENC_ONE = '0x24988a82b3bbaae58680bc9de5dea5aa';
|
||||
const ENC_TWO = '0xdb190750267d8849c35316ec9d342111';
|
||||
|
||||
describe('formatResult', () => {
|
||||
describe('formatting', () => {
|
||||
let api;
|
||||
let provider;
|
||||
|
||||
@@ -25,8 +25,8 @@ describe('formatResult', () => {
|
||||
subscription(null, {
|
||||
block: '0x1234',
|
||||
changes: [
|
||||
['0x11cf1094db4db43356b7787c3e59c39f', '0x0102'],
|
||||
['0x924776c687da8e30afdd2ac87d2c67da', '0x0201']
|
||||
[ENC_ONE, '0x0102'],
|
||||
[ENC_TWO, '0x0201']
|
||||
]
|
||||
})
|
||||
)
|
||||
@@ -34,12 +34,11 @@ describe('formatResult', () => {
|
||||
api = new Api(provider);
|
||||
});
|
||||
|
||||
it.skip('encodes key (with params), decoding response', () => {
|
||||
it('encodes key (with params), decoding response', () => {
|
||||
return api.state
|
||||
.getStorage([
|
||||
// FIXME changed storage api
|
||||
storage.staking.public.freeBalanceOf, ADDR_ONE
|
||||
])
|
||||
.getStorage(
|
||||
[storage.balances.freeBalance, ADDR_ONE]
|
||||
)
|
||||
.then((value) => {
|
||||
expect(
|
||||
provider.send
|
||||
@@ -51,15 +50,16 @@ describe('formatResult', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('encodes multiple keys, decoding multiple results', (done) => {
|
||||
it('encodes multiple keys, decoding multiple results', (done) => {
|
||||
api.state
|
||||
.storage(
|
||||
[
|
||||
// FIXME changed storage api
|
||||
[storage.staking.public.freeBalanceOf, ADDR_ONE],
|
||||
[storage.staking.public.freeBalanceOf, ADDR_TWO]
|
||||
[storage.balances.freeBalance, ADDR_ONE],
|
||||
[storage.balances.freeBalance, ADDR_TWO]
|
||||
],
|
||||
(error, value) => {
|
||||
console.error(value);
|
||||
|
||||
expect(
|
||||
provider.subscribe
|
||||
).toHaveBeenCalledWith(
|
||||
@@ -69,7 +69,9 @@ describe('formatResult', () => {
|
||||
expect.anything()
|
||||
);
|
||||
expect(
|
||||
value.map((bn) => bn.toNumber())
|
||||
value.map((balance) =>
|
||||
balance.toNumber()
|
||||
)
|
||||
).toEqual([513, 258]);
|
||||
|
||||
done(error);
|
||||
+56
-33
@@ -5,13 +5,11 @@
|
||||
import { ProviderInterface, ProviderInterface$Callback } from '@polkadot/api-provider/types';
|
||||
import { Interfaces, Interface$Sections } from '@polkadot/jsonrpc/types';
|
||||
import { SectionItem } from '@polkadot/params/types';
|
||||
import { Storages } from '@polkadot/storage/types';
|
||||
import { ApiInterface, ApiInterface$Section, ApiInterface$Section$Method } from './types';
|
||||
|
||||
import formatInputs from '@polkadot/api-format/input';
|
||||
import formatOutput from '@polkadot/api-format/output';
|
||||
import { Base, Vector, createType } from '@polkadot/api-codec/codec';
|
||||
import { StorageChangeSet, StorageKey } from '@polkadot/api-codec/index';
|
||||
import interfaces from '@polkadot/jsonrpc/index';
|
||||
import decodeParams from '@polkadot/params/decode';
|
||||
import signature from '@polkadot/params/signature';
|
||||
import assert from '@polkadot/util/assert';
|
||||
import ExtError from '@polkadot/util/ext/error';
|
||||
@@ -20,14 +18,11 @@ import isUndefined from '@polkadot/util/is/undefined';
|
||||
|
||||
/**
|
||||
* @example
|
||||
* ```javascript
|
||||
*
|
||||
* import Api from '@polkadot/api';
|
||||
* import WsProvider from '@polkadot/api-provider/ws';
|
||||
*
|
||||
* const provider = new WsProvider('http://127.0.0.1:9944');
|
||||
* const api = new Api(provider);
|
||||
* ```
|
||||
*/
|
||||
export default class Api implements ApiInterface {
|
||||
private _provider: ProviderInterface;
|
||||
@@ -78,12 +73,17 @@ export default class Api implements ApiInterface {
|
||||
const call = async (...values: Array<any>): Promise<any> => {
|
||||
// TODO Warn on deprecated methods
|
||||
try {
|
||||
const params = formatInputs(method.params, values);
|
||||
const result = await this._provider.send(rpcName, params);
|
||||
const params = this.formatInputs(method, values);
|
||||
const paramsJson = params.map((param) => param.toJSON());
|
||||
const result = await this._provider.send(rpcName, paramsJson);
|
||||
|
||||
return this.formatResult(method, params, values, result);
|
||||
return this.formatOutput(method, params, result);
|
||||
} catch (error) {
|
||||
throw new ExtError(`${signature(method)}:: ${error.message}`, (error as ExtError).code, undefined);
|
||||
const message = `${signature(method)}:: ${error.message}`;
|
||||
|
||||
console.error(message, error);
|
||||
|
||||
throw new ExtError(message, (error as ExtError).code, undefined);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -99,14 +99,19 @@ export default class Api implements ApiInterface {
|
||||
|
||||
assert(isFunction(cb), `Expected callback in last position of params`);
|
||||
|
||||
const params = formatInputs(method.params, values);
|
||||
const params = this.formatInputs(method, values);
|
||||
const paramsJson = params.map((param) => param.toJSON());
|
||||
const update = (error: Error | null, result?: any) => {
|
||||
cb(error, this.formatResult(method, params, values, result));
|
||||
cb(error, this.formatOutput(method, params, result));
|
||||
};
|
||||
|
||||
return this._provider.subscribe(rpcName, method.subscribe[0], params, update);
|
||||
return this._provider.subscribe(rpcName, method.subscribe[0], paramsJson, update);
|
||||
} catch (error) {
|
||||
throw new ExtError(`${signature(method)}:: ${error.message}`, (error as ExtError).code, undefined);
|
||||
const message = `${signature(method)}:: ${error.message}`;
|
||||
|
||||
console.error(message, error);
|
||||
|
||||
throw new ExtError(message, (error as ExtError).code, undefined);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -117,29 +122,47 @@ export default class Api implements ApiInterface {
|
||||
return call;
|
||||
}
|
||||
|
||||
private formatResult (method: SectionItem<Interfaces>, params: Array<any>, inputs: Array<any>, result?: any): any {
|
||||
if (method.type === 'StorageResult') {
|
||||
return this.formatStorageOutput(inputs[0][0], result);
|
||||
}
|
||||
private formatInputs (method: SectionItem<Interfaces>, inputs: Array<any>): Array<Base> {
|
||||
assert(method.params.length === inputs.length, `Expected ${method.params.length} parameters, ${inputs.length} found instead`);
|
||||
|
||||
if (method.type === 'StorageResultSet') {
|
||||
return params[0].map((key: string, index: number) => {
|
||||
const input = inputs[0][index][0];
|
||||
const { changes = [] }: { block: string, changes: Array<[string, string]> } = result || {};
|
||||
const value = changes.find(([_key]) => key === _key);
|
||||
return method.params.map(({ type }, index) =>
|
||||
createType(type as string, inputs[index])
|
||||
);
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
return undefined;
|
||||
private formatOutput (method: SectionItem<Interfaces>, params: Array<Base>, result?: any): Base {
|
||||
const base = createType(method.type as string, result);
|
||||
|
||||
if (method.type === 'StorageData') {
|
||||
const type = (params[0] as StorageKey).outputType;
|
||||
|
||||
if (type) {
|
||||
return createType(type, base.raw);
|
||||
}
|
||||
} else if (method.type === 'StorageChangeSet') {
|
||||
return (params[0] as Vector<StorageKey>).reduce((vector, _key: StorageKey) => {
|
||||
const type = _key.outputType;
|
||||
|
||||
if (!type) {
|
||||
throw new Error('Cannot format StorageChangeSet, output type missing for key');
|
||||
}
|
||||
|
||||
return this.formatStorageOutput(input, value[1]);
|
||||
});
|
||||
const key = _key.toHex();
|
||||
|
||||
const item = (base as StorageChangeSet).changes.find((item) =>
|
||||
item.key.toHex() === key
|
||||
);
|
||||
|
||||
if (!item) {
|
||||
throw new Error('No result found for key in StorageChangeSet');
|
||||
}
|
||||
|
||||
vector.push(createType(type, item.value.value));
|
||||
|
||||
return vector;
|
||||
}, new (Vector.with(Base))());
|
||||
}
|
||||
|
||||
return formatOutput(method.type, result);
|
||||
}
|
||||
|
||||
private formatStorageOutput (key: SectionItem<Storages>, result?: any): any {
|
||||
return decodeParams(key.type, result, 'latest', true).value;
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ describe('methodSend', () => {
|
||||
const method = api.createMethodSend('test_bleh', methods.bleh);
|
||||
|
||||
return method(1).catch((error) => {
|
||||
expect(error.message).toMatch(/no params expected, found 1 instead/);
|
||||
expect(error.message).toMatch(/parameters, 1 found instead/);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@polkadot/params": "^0.30.1",
|
||||
"@polkadot/primitives": "^0.30.1",
|
||||
"@polkadot/util": "^0.30.4"
|
||||
"@polkadot/util": "^0.30.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ const getStorage: CreateItemOptions = {
|
||||
params: [
|
||||
param('key', 'StorageKey')
|
||||
],
|
||||
type: 'StorageResult'
|
||||
type: 'StorageData'
|
||||
};
|
||||
|
||||
const getStorageAt: CreateItemOptions = {
|
||||
@@ -99,9 +99,9 @@ const storage: CreateItemOptions = {
|
||||
'state_unsubscribeStorage'
|
||||
],
|
||||
params: [
|
||||
param('keys', ['StorageKey'])
|
||||
param('keys', 'Vec<StorageKey>')
|
||||
],
|
||||
type: 'StorageResultSet'
|
||||
type: 'StorageChangeSet'
|
||||
};
|
||||
|
||||
const privateMethods: CreateItemOptionsMap = {};
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"@polkadot/extrinsics": "^0.30.1",
|
||||
"@polkadot/params": "^0.30.1",
|
||||
"@polkadot/primitives": "^0.30.1",
|
||||
"@polkadot/util": "^0.30.4",
|
||||
"@polkadot/util-keyring": "^0.30.4"
|
||||
"@polkadot/util": "^0.30.7",
|
||||
"@polkadot/util-keyring": "^0.30.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,8 +112,8 @@ export default function decodeValue (decode: Decoder, type: Param$Type, _input:
|
||||
case 'VoteThreshold':
|
||||
return byte(input);
|
||||
|
||||
case 'StorageResult':
|
||||
case 'StorageResultSet':
|
||||
case 'StorageData':
|
||||
case 'StorageChangeSet':
|
||||
default:
|
||||
// tslint:disable-next-line
|
||||
(type as never);
|
||||
|
||||
@@ -7,11 +7,11 @@ import toU8a from '@polkadot/util/u8a/toU8a';
|
||||
|
||||
import encode from './index';
|
||||
|
||||
describe('storageKey', () => {
|
||||
it.skip('encodes storageKey -> Uint8Array properly', () => {
|
||||
describe.skip('storageKey', () => {
|
||||
it('encodes storageKey -> Uint8Array properly', () => {
|
||||
expect(
|
||||
encode('StorageKey', [
|
||||
storage.staking.public.freeBalanceOf,
|
||||
storage.balances.freeBalance,
|
||||
'5EhmTa7fL6SdjgKXo9g6hetR6nHnRAmrtisoGFWEESjzECtY'
|
||||
])
|
||||
).toEqual(
|
||||
|
||||
Vendored
+1
-1
@@ -14,7 +14,7 @@ export type EncodingVersions = 'poc-1' | 'latest';
|
||||
// - @polkadot/storage/key/params.ts
|
||||
// - decode/value/index.js
|
||||
// - encode/type/index.js
|
||||
export type Param$Type = 'AccountId' | 'AccountIndex' | 'Balance' | 'BlockNumber' | 'bool' | 'Bytes' | 'Call' | 'CandidateReceipt' | 'Code' | 'Digest' | 'Gas' | 'Hash' | 'Header' | 'KeyValue' | 'Metadata' | 'MisbehaviorReport' | 'ParachainId' | 'PendingExtrinsics' | 'PropIndex' | 'Proposal' | 'ReferendumIndex' | 'RuntimeVersion' | 'SessionKey' | 'Signature' | 'SignedBlock' | 'StorageKey' | 'StorageKeyValue' | 'StorageResult' | 'StorageResultSet' | 'String' | 'Timestamp' | 'u32' | 'u64' | 'u128' | 'VoteIndex' | 'VoteThreshold';
|
||||
export type Param$Type = 'AccountId' | 'AccountIndex' | 'Balance' | 'BlockNumber' | 'bool' | 'Bytes' | 'Call' | 'CandidateReceipt' | 'Code' | 'Digest' | 'Gas' | 'Hash' | 'Header' | 'KeyValue' | 'Metadata' | 'MisbehaviorReport' | 'ParachainId' | 'PendingExtrinsics' | 'PropIndex' | 'Proposal' | 'ReferendumIndex' | 'RuntimeVersion' | 'SessionKey' | 'Signature' | 'SignedBlock' | 'StorageKey' | 'StorageKeyValue' | 'StorageData' | 'StorageChangeSet' | 'String' | 'Timestamp' | 'u32' | 'u64' | 'u128' | 'VoteIndex' | 'VoteThreshold' | 'Vec<StorageKey>';
|
||||
|
||||
export type Param$Type$Array = Array<Param$Type | Array<Param$Type | Array<Param$Type>>>;
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/type-primitives#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@polkadot/trie-hash": "^0.30.4",
|
||||
"@polkadot/util": "^0.30.4"
|
||||
"@polkadot/trie-hash": "^0.30.7",
|
||||
"@polkadot/util": "^0.30.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bn.js": "^4.11.8"
|
||||
|
||||
@@ -30,10 +30,11 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/type-storage#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@polkadot/api-codec": "^0.30.1",
|
||||
"@polkadot/params": "^0.30.1",
|
||||
"@polkadot/primitives": "^0.30.1",
|
||||
"@polkadot/util": "^0.30.4",
|
||||
"@polkadot/util-crypto": "^0.30.4",
|
||||
"@polkadot/util-keyring": "^0.30.4"
|
||||
"@polkadot/util": "^0.30.7",
|
||||
"@polkadot/util-crypto": "^0.30.7",
|
||||
"@polkadot/util-keyring": "^0.30.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import Metadata from '@polkadot/api-codec/Metadata';
|
||||
import json from '@polkadot/api-codec/Metadata.rpc.json';
|
||||
|
||||
import { fromMetadata } from './fromMetadata';
|
||||
import fromMetadata from './fromMetadata';
|
||||
|
||||
// Use the pre-generated metadata
|
||||
const metadata = new Metadata().fromJSON(json.result);
|
||||
@@ -23,7 +23,7 @@ describe('fromMetadata', () => {
|
||||
// FIXME check again when we have a valid chain/UI
|
||||
it('should return the correct storage key', () => {
|
||||
expect(newStorage.balances.freeBalance('5GwPuAgYgP6q58uWTXp4uSg6FwfzQv9HfFZwAFEREUrQjCvy')).toEqual(
|
||||
Uint8Array.from([237, 14, 33, 216, 167, 215, 237, 69, 175, 111, 52, 40, 57, 42, 106, 40])
|
||||
Uint8Array.from([52, 103, 23, 10, 157, 95, 244, 9, 70, 215, 120, 149, 1, 238, 109, 69])
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,20 +2,12 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import Metadata, { RuntimeModuleMetadata } from '@polkadot/api-codec/Metadata';
|
||||
|
||||
import { createFunction } from './utils/createFunction';
|
||||
import { ModuleStorage, Storage } from './types';
|
||||
|
||||
/**
|
||||
* Sets the 1st letter of a string to lowercase.
|
||||
*
|
||||
* @param s - The string to lower first letter.
|
||||
* TODO Move to @polkadot/util
|
||||
*/
|
||||
function lowerFirstLetter (s: string) {
|
||||
return s.charAt(0).toLowerCase() + s.slice(1);
|
||||
}
|
||||
import Metadata from '@polkadot/api-codec/Metadata';
|
||||
import { stringLowerFirst } from '@polkadot/util/string';
|
||||
|
||||
import createFunction from './utils/createFunction';
|
||||
|
||||
/**
|
||||
* Extend a storage object with the storage modules & module functions present
|
||||
@@ -24,20 +16,27 @@ function lowerFirstLetter (s: string) {
|
||||
* @param storage - A storage object to be extended.
|
||||
* @param metadata - The metadata to extend the storage object against.
|
||||
*/
|
||||
export const fromMetadata = (storage: Storage, metadata: Metadata) => {
|
||||
metadata.modules.forEach((moduleMetadata: RuntimeModuleMetadata) => {
|
||||
export default function fromMetadata (storage: Storage, metadata: Metadata) {
|
||||
const result = Object.keys(storage).reduce((result, key) => {
|
||||
result[key] = storage[key];
|
||||
|
||||
return result;
|
||||
}, {} as Storage);
|
||||
|
||||
return metadata.modules.reduce((result, moduleMetadata) => {
|
||||
if (!moduleMetadata.storage) {
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
const newModule: ModuleStorage = {
|
||||
};
|
||||
const prefix = moduleMetadata.storage.prefix.toString();
|
||||
|
||||
moduleMetadata.storage.functions.forEach(func => {
|
||||
result[stringLowerFirst(prefix)] = moduleMetadata.storage.functions.reduce((newModule, func) => {
|
||||
// Lowercase the 'f' in storage.balances.freeBalance
|
||||
newModule[lowerFirstLetter(func.name.toString())] = createFunction(moduleMetadata.prefix, func);
|
||||
});
|
||||
storage[moduleMetadata.prefix.toString()] = newModule;
|
||||
});
|
||||
return storage;
|
||||
};
|
||||
newModule[stringLowerFirst(func.name.toString())] = createFunction(prefix, func.name, func);
|
||||
|
||||
return newModule;
|
||||
}, {} as ModuleStorage);
|
||||
|
||||
return result;
|
||||
}, result);
|
||||
}
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
|
||||
import { StorageFunctionModifier, StorageFunctionType } from '@polkadot/api-codec/Metadata';
|
||||
import Text from '@polkadot/api-codec/Text';
|
||||
import U8a from '@polkadot/api-codec/codec/U8a';
|
||||
import Vector from '@polkadot/api-codec/codec/Vector';
|
||||
|
||||
import { createFunction } from './utils/createFunction';
|
||||
import createFunction from './utils/createFunction';
|
||||
|
||||
interface SubstrateMetadata {
|
||||
documentation: string;
|
||||
@@ -15,13 +14,13 @@ interface SubstrateMetadata {
|
||||
}
|
||||
|
||||
// Small helper function to factorize code on this page.
|
||||
const createRuntimeFunction = (prefix: string, functionMetadata: SubstrateMetadata) =>
|
||||
const createRuntimeFunction = (name: string, functionMetadata: SubstrateMetadata) =>
|
||||
// TODO The expected 2nd argument is a StorageFunctionMetadata, but we
|
||||
// actually only need the fields `documentation` and `type` of it, so in
|
||||
// order to not input other fields (byteLength, fromJSON...) we lazily cast
|
||||
// as any.
|
||||
createFunction(
|
||||
new U8a(prefix),
|
||||
'', name,
|
||||
{
|
||||
documentation: new Vector(Text, [functionMetadata.documentation]),
|
||||
modifier: new StorageFunctionModifier().fromJSON(0),
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2017-2018 @polkadot/storage authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import metadataJson from '@polkadot/api-codec/Metadata.rpc.json';
|
||||
import Metadata from '@polkadot/api-codec/Metadata';
|
||||
|
||||
import storage from './index';
|
||||
import fromMetadata from './fromMetadata';
|
||||
|
||||
export default fromMetadata(
|
||||
storage,
|
||||
new Metadata().fromJSON(metadataJson.result)
|
||||
);
|
||||
Vendored
+1
-6
@@ -2,7 +2,7 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { StorageFunctionMetadata } from '@polkadot/api-codec/Metadata';
|
||||
import { StorageFunction } from '@polkadot/api-codec/StorageKey';
|
||||
import BN from 'bn.js';
|
||||
import { Section } from '@polkadot/params/types';
|
||||
|
||||
@@ -10,10 +10,6 @@ import * as substrate from './substrate';
|
||||
|
||||
type Substrate = keyof typeof substrate;
|
||||
|
||||
export interface StorageFunction extends StorageFunctionMetadata {
|
||||
(arg: any): Uint8Array;
|
||||
}
|
||||
|
||||
export interface ModuleStorage {
|
||||
[key: string]: StorageFunction;
|
||||
}
|
||||
@@ -25,7 +21,6 @@ export interface Storage {
|
||||
|
||||
// TODO Below is legacy code, used in:
|
||||
// - api-provider
|
||||
// - api-format
|
||||
export type Storage$Key$Value = number | BN | Uint8Array | string;
|
||||
export type Storages = {
|
||||
consensus: Section<Storages, any, any>;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2017-2018 @polkadot/storage authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
|
||||
import createFunction from './createFunction';
|
||||
|
||||
describe('createFunction', () => {
|
||||
it('should create timestamp.now correctly', () => {
|
||||
expect(
|
||||
createFunction(
|
||||
'Timestamp',
|
||||
'Now',
|
||||
{ type: {} }
|
||||
)()
|
||||
).toEqual(
|
||||
hexToU8a('0x0e4944cfd98d6f4cc374d16f5a4e3f9c')
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -2,15 +2,14 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import * as CodecTypes from '@polkadot/api-codec/index';
|
||||
import { createType } from '@polkadot/api-codec/codec';
|
||||
import { StorageFunctionMetadata } from '@polkadot/api-codec/Metadata';
|
||||
import Text from '@polkadot/api-codec/Text';
|
||||
import U8a from '@polkadot/api-codec/codec/U8a';
|
||||
import { StorageFunction } from '@polkadot/api-codec/StorageKey';
|
||||
import { Text } from '@polkadot/api-codec/index';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
import u8aFromUtf8 from '@polkadot/util/u8a/fromUtf8';
|
||||
import xxhash from '@polkadot/util-crypto/xxhash/asU8a';
|
||||
|
||||
import { StorageFunction } from '../types';
|
||||
|
||||
export interface CreateItemOptions {
|
||||
isUnhashed?: boolean;
|
||||
}
|
||||
@@ -25,40 +24,47 @@ export interface CreateItemOptions {
|
||||
* are not known at runtime (from state_getMetadata), they need to be supplied
|
||||
* by us manually at compile time.
|
||||
*/
|
||||
export function createFunction (
|
||||
prefix: Text | U8a,
|
||||
functionMetadata: StorageFunctionMetadata,
|
||||
export default function createFunction (
|
||||
prefix: string | Text,
|
||||
name: string | Text,
|
||||
meta: StorageFunctionMetadata,
|
||||
options: CreateItemOptions = {}
|
||||
) {
|
||||
let func: any; // The return value, it's a function that has metadata.
|
||||
): StorageFunction {
|
||||
let storageFn: any;
|
||||
|
||||
if (options.isUnhashed) {
|
||||
func = () => prefix.toU8a();
|
||||
storageFn = (): Uint8Array =>
|
||||
u8aFromUtf8(name.toString());
|
||||
} else {
|
||||
// TODO Find better type than any
|
||||
// Can only have zero or one argument:
|
||||
// - storage.balances.freeBalance(address)
|
||||
// - storage.timestamp.blockPeriod()
|
||||
func = (arg?: any) => {
|
||||
if (functionMetadata.type.isMap) {
|
||||
if (!arg) {
|
||||
throw new Error(`${functionMetadata.name} expects one argument.`);
|
||||
}
|
||||
|
||||
const argType = functionMetadata.type.asMap.key.toString(); // Argument type, as string
|
||||
const ArgType = (CodecTypes as any)[argType]; // Argument type, as Class
|
||||
return xxhash(u8aConcat(prefix.toU8a(), new ArgType(arg).toU8a()), 128);
|
||||
storageFn = (arg?: any): Uint8Array => {
|
||||
if (!meta.type.isMap) {
|
||||
return xxhash(
|
||||
u8aFromUtf8(`${prefix.toString()} ${name.toString()}`),
|
||||
128
|
||||
);
|
||||
}
|
||||
|
||||
return xxhash(prefix.toU8a(), 128);
|
||||
if (!arg) {
|
||||
throw new Error(`${meta.name} expects one argument`);
|
||||
}
|
||||
|
||||
const type = meta.type.asMap.key.toString(); // Argument type, as string
|
||||
|
||||
return xxhash(
|
||||
u8aConcat(
|
||||
u8aFromUtf8(`${prefix.toString()} ${name.toString()}`),
|
||||
createType(type, arg).toU8a(true)
|
||||
),
|
||||
128
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
// Add metadata to the storage function
|
||||
Object.assign(func as StorageFunction, {
|
||||
documentation: functionMetadata.documentation,
|
||||
type: functionMetadata.type
|
||||
});
|
||||
storageFn.meta = meta;
|
||||
|
||||
return func as StorageFunction;
|
||||
return storageFn as StorageFunction;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
"paths":
|
||||
{
|
||||
"@polkadot/api-codec/*": ["packages/api-codec/src/*"],
|
||||
"@polkadot/api-format/*": ["packages/api-format/src/*"],
|
||||
"@polkadot/api-provider/*": ["packages/api-provider/src/*"],
|
||||
"@polkadot/api-rx/*": ["packages/api-rx/src/*"],
|
||||
"@polkadot/api/*": ["packages/api/src/*"],
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"extends": "@polkadot/dev/config/tslint",
|
||||
"linterOptions": {
|
||||
"exclude": "packages/**/src/**/*.json"
|
||||
},
|
||||
"rules": {
|
||||
"completed-docs": false
|
||||
}
|
||||
|
||||
@@ -1219,57 +1219,59 @@
|
||||
typedoc-plugin-markdown "^1.1.15"
|
||||
typescript "^3.0.1"
|
||||
|
||||
"@polkadot/trie-hash@^0.30.4":
|
||||
version "0.30.4"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/trie-hash/-/trie-hash-0.30.4.tgz#eb2520b45cbb634000319e8420623a992c4fd56a"
|
||||
"@polkadot/trie-hash@^0.30.7":
|
||||
version "0.30.7"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/trie-hash/-/trie-hash-0.30.7.tgz#b68102736d03a2a4cd673f113a90a7cd2b21bc69"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
"@polkadot/util" "^0.30.4"
|
||||
"@polkadot/util-crypto" "^0.30.4"
|
||||
"@polkadot/util-rlp" "^0.30.4"
|
||||
"@polkadot/util" "^0.30.7"
|
||||
"@polkadot/util-crypto" "^0.30.7"
|
||||
"@polkadot/util-rlp" "^0.30.7"
|
||||
|
||||
"@polkadot/ts@^0.1.30":
|
||||
version "0.1.30"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/ts/-/ts-0.1.30.tgz#d6d1498a5597e09de88f6117663bcf842040c801"
|
||||
|
||||
"@polkadot/util-crypto@^0.30.4":
|
||||
version "0.30.4"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-0.30.4.tgz#d2e23fd1f661200771c10381f4b8ef20d337c1a8"
|
||||
"@polkadot/util-crypto@^0.30.7":
|
||||
version "0.30.7"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-0.30.7.tgz#7af110c286164cd4870ba8b499c2601b7181ed4d"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
"@polkadot/util" "^0.30.4"
|
||||
"@polkadot/util" "^0.30.7"
|
||||
blakejs "^1.1.0"
|
||||
js-sha3 "^0.8.0"
|
||||
tweetnacl "^1.0.0"
|
||||
xxhashjs "^0.2.2"
|
||||
|
||||
"@polkadot/util-keyring@^0.30.4":
|
||||
version "0.30.4"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/util-keyring/-/util-keyring-0.30.4.tgz#97aa4e442f38ce0afe7f54b2f0c537b184031b7c"
|
||||
"@polkadot/util-keyring@^0.30.7":
|
||||
version "0.30.7"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/util-keyring/-/util-keyring-0.30.7.tgz#b98df3430937a441422e1ea788e0115d0e2a9c88"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
"@polkadot/util" "^0.30.4"
|
||||
"@polkadot/util-crypto" "^0.30.4"
|
||||
"@polkadot/util" "^0.30.7"
|
||||
"@polkadot/util-crypto" "^0.30.7"
|
||||
"@types/bs58" "^3.0.30"
|
||||
bs58 "^4.0.1"
|
||||
|
||||
"@polkadot/util-rlp@^0.30.4":
|
||||
version "0.30.4"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/util-rlp/-/util-rlp-0.30.4.tgz#3f08ad08e0f47febeacf9225c4615f18f6e450b7"
|
||||
"@polkadot/util-rlp@^0.30.7":
|
||||
version "0.30.7"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/util-rlp/-/util-rlp-0.30.7.tgz#bb314ebdbf44803a0575e067ef316f60099c274a"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
"@polkadot/util" "^0.30.4"
|
||||
"@polkadot/util" "^0.30.7"
|
||||
|
||||
"@polkadot/util@^0.30.4":
|
||||
version "0.30.4"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-0.30.4.tgz#f3033b5e7e8a2af5a69b4b9f2ea33287da76d045"
|
||||
"@polkadot/util@^0.30.7":
|
||||
version "0.30.7"
|
||||
resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-0.30.7.tgz#989e21e5b32f2a505ad0a787ce8b56da94702d32"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
"@types/bn.js" "^4.11.1"
|
||||
"@types/camelcase" "^4.1.0"
|
||||
"@types/deasync" "^0.1.0"
|
||||
"@types/ip-regex" "^2.0.0"
|
||||
"@types/xxhashjs" "^0.1.1"
|
||||
bn.js "^4.11.8"
|
||||
camelcase "^5.0.0"
|
||||
chalk "^2.4.1"
|
||||
deasync "^0.1.13"
|
||||
ip-regex "^3.0.0"
|
||||
@@ -1291,6 +1293,10 @@
|
||||
dependencies:
|
||||
"@types/base-x" "*"
|
||||
|
||||
"@types/camelcase@^4.1.0":
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/camelcase/-/camelcase-4.1.0.tgz#e054f7986f31658d49936261b5cd4588ef29d1ee"
|
||||
|
||||
"@types/deasync@^0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/deasync/-/deasync-0.1.0.tgz#b2bd6c3fcde3cf67b8be4c2f70136ba8f157b45a"
|
||||
@@ -2225,6 +2231,10 @@ camelcase@^4.0.0, camelcase@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
||||
|
||||
camelcase@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42"
|
||||
|
||||
caniuse-lite@^1.0.30000884:
|
||||
version "1.0.30000885"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000885.tgz#e889e9f8e7e50e769f2a49634c932b8aee622984"
|
||||
|
||||
Reference in New Issue
Block a user