Round out metadata types (#169)
* Fake Origin for compatibility * Add Gas * Add Moment * Cleanups * NewAccountOutcome * Permill & Perbill * PrendingExtrinsics -> PendingExtrinsics * Extrinsics & PendingExtrinsics * Alias String -> Text (as found in jsonrpc, expose it) * MetaDate -> Metadata (compat) * Add StorageData, StorageKey & ChangeSet * Cleanup comments * Comment update * Comment typo * Add ParachainId * Add Tuple type * Tuple tests * Clenaup Tuple generics * Expand comment * Expose keys/values on struct * Array-like at -> get * Cleanup & simplify EnumType * Use setValue internally to fromU8a * Add RuntimeVersion * Expose RuntimeVersion
This commit is contained in:
@@ -36,7 +36,7 @@ describe('BftHashSignature', () => {
|
||||
|
||||
describe('Justification', () => {
|
||||
const just = new Justification({
|
||||
round_number: 32,
|
||||
round: 32,
|
||||
hash: '0xabcd',
|
||||
signatures: [
|
||||
{ authorityId: '0x1234', signature: '0x5678' },
|
||||
@@ -53,7 +53,7 @@ describe('Justification', () => {
|
||||
});
|
||||
|
||||
it('has the correct signatures', () => {
|
||||
const sig = just.signatures.at(1);
|
||||
const sig = just.signatures.get(1);
|
||||
|
||||
expect(sig.authorityId.toHex()).toEqual('0x9876');
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import { AnyNumber, AnyU8a } from './types';
|
||||
|
||||
import Struct from './codec/Struct';
|
||||
import Tuple from './codec/Tuple';
|
||||
import Vector from './codec/Vector';
|
||||
import AuthorityId from './AuthorityId';
|
||||
import Hash from './Hash';
|
||||
@@ -18,8 +19,8 @@ export type BftAuthoritySignatureValue = {
|
||||
|
||||
// Represents a Bft Hash and Signature pairing, typically used in reporting
|
||||
// network behaviour.
|
||||
export class BftAuthoritySignature extends Struct {
|
||||
constructor (value: BftAuthoritySignatureValue = {}) {
|
||||
export class BftAuthoritySignature extends Tuple {
|
||||
constructor (value?: BftAuthoritySignatureValue) {
|
||||
super({
|
||||
authorityId: AuthorityId,
|
||||
signature: Signature
|
||||
@@ -42,8 +43,8 @@ export type BftHashSignatureValue = {
|
||||
|
||||
// Represents a Bft Hash and Signature pairing, typically used in reporting
|
||||
// network behaviour.
|
||||
export class BftHashSignature extends Struct {
|
||||
constructor (value: BftHashSignatureValue = {}) {
|
||||
export class BftHashSignature extends Tuple {
|
||||
constructor (value?: BftHashSignatureValue) {
|
||||
super({
|
||||
hash: Hash,
|
||||
signature: Signature
|
||||
@@ -60,20 +61,20 @@ export class BftHashSignature extends Struct {
|
||||
}
|
||||
|
||||
export type JustificationValue = {
|
||||
round_number?: AnyNumber,
|
||||
round?: AnyNumber,
|
||||
hash?: AnyU8a,
|
||||
signatures?: Array<BftAuthoritySignatureValue>
|
||||
};
|
||||
|
||||
export class Justification extends Struct {
|
||||
constructor (value: JustificationValue = {}) {
|
||||
constructor (value?: JustificationValue) {
|
||||
super({
|
||||
// FIXME Rust returns this as "round_number", we actually want a JSON alias
|
||||
// in the structure to take care of these renames...
|
||||
round_number: U32,
|
||||
round: U32,
|
||||
hash: Hash,
|
||||
signatures: Vector.with(BftAuthoritySignature)
|
||||
}, value);
|
||||
}, value, new Map([['round', 'round_number']]));
|
||||
}
|
||||
|
||||
get hash (): Hash {
|
||||
@@ -81,7 +82,7 @@ export class Justification extends Struct {
|
||||
}
|
||||
|
||||
get round (): U32 {
|
||||
return this.raw.round_number as U32;
|
||||
return this.raw.round as U32;
|
||||
}
|
||||
|
||||
get signatures (): Vector<BftAuthoritySignature> {
|
||||
|
||||
@@ -45,7 +45,7 @@ describe('Block', () => {
|
||||
block.extrinsics.length
|
||||
).toEqual(1); // eslint-disable-line
|
||||
expect(
|
||||
block.extrinsics.at(0).length
|
||||
block.extrinsics.get(0).length
|
||||
).toEqual(111); // eslint-disable-line
|
||||
});
|
||||
|
||||
|
||||
@@ -7,8 +7,7 @@ import { AnyU8a } from './types';
|
||||
import blake2Asu8a from '@polkadot/util-crypto/blake2/asU8a';
|
||||
|
||||
import Struct from './codec/Struct';
|
||||
import Vector from './codec/Vector';
|
||||
import Extrinsic from './Extrinsic';
|
||||
import Extrinsics from './Extrinsics';
|
||||
import Hash from './Hash';
|
||||
import Header, { HeaderValue } from './Header';
|
||||
|
||||
@@ -19,15 +18,15 @@ export type BlockValue = {
|
||||
|
||||
// A block encoded with header and extrinsics
|
||||
export default class Block extends Struct {
|
||||
constructor (value: BlockValue = {}) {
|
||||
constructor (value?: BlockValue) {
|
||||
super({
|
||||
header: Header,
|
||||
extrinsics: Vector.with(Extrinsic)
|
||||
extrinsics: Extrinsics
|
||||
}, value);
|
||||
}
|
||||
|
||||
get extrinsics (): Vector<Extrinsic> {
|
||||
return this.raw.extrinsics as Vector<Extrinsic>;
|
||||
get extrinsics (): Extrinsics {
|
||||
return this.raw.extrinsics as Extrinsics;
|
||||
}
|
||||
|
||||
// convenience, encodes the header and returns the actual hash
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// 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 Vector from './codec/Vector';
|
||||
import Extrinsic from './Extrinsic';
|
||||
|
||||
// A list of extrinsics
|
||||
export default class Extrinsics extends Vector.with(Extrinsic) {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// 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 U64 from './U64';
|
||||
|
||||
// Gas for contracts
|
||||
export default class Gas extends U64 {
|
||||
}
|
||||
@@ -27,7 +27,7 @@ export type HeaderValue = {
|
||||
|
||||
// A block header digest.
|
||||
export class Digest extends Struct {
|
||||
constructor (value: DigestValue = {}) {
|
||||
constructor (value?: DigestValue) {
|
||||
super({
|
||||
logs: Vector.with(Bytes)
|
||||
}, value);
|
||||
@@ -40,7 +40,7 @@ export class Digest extends Struct {
|
||||
|
||||
// A block header.
|
||||
export default class Header extends Struct {
|
||||
constructor (value: HeaderValue = {}) {
|
||||
constructor (value?: HeaderValue) {
|
||||
super({
|
||||
parentHash: Hash,
|
||||
number: BlockNumber,
|
||||
|
||||
@@ -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 KeyValue from './KeyValue';
|
||||
import KeyValue, { KeyValueOption } from './KeyValue';
|
||||
|
||||
describe('KeyValue', () => {
|
||||
it('decodes KeyValue from u8a', () => {
|
||||
@@ -47,3 +47,14 @@ describe('KeyValue', () => {
|
||||
expect(kv.value.toHex()).toEqual('0x998877665544332211');
|
||||
});
|
||||
});
|
||||
|
||||
describe('KeyValueOption', () => {
|
||||
it('exposes the properties for key/value', () => {
|
||||
const kv = new KeyValueOption({
|
||||
key: '0x11223344'
|
||||
});
|
||||
|
||||
expect(kv.key.toHex()).toEqual('0x11223344');
|
||||
expect(kv.value.isEmpty).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
import { AnyU8a } from './types';
|
||||
|
||||
import Option from './codec/Option';
|
||||
import Struct from './codec/Struct';
|
||||
|
||||
import Bytes from './Bytes';
|
||||
import StorageData from './StorageData';
|
||||
import StorageKey from './StorageKey';
|
||||
|
||||
type KeyValueValue = {
|
||||
key?: AnyU8a,
|
||||
@@ -18,18 +19,42 @@ type KeyValueValue = {
|
||||
// for the keys and values. (Not to be confused with the KeyValue in Metadata, that
|
||||
// is actually for Maps, whereas this is a representation of actaul storage values)
|
||||
export default class KeyValue extends Struct {
|
||||
constructor (value: KeyValueValue = {}) {
|
||||
constructor (value?: KeyValueValue) {
|
||||
super({
|
||||
key: Bytes,
|
||||
value: Bytes
|
||||
key: StorageKey,
|
||||
value: StorageData
|
||||
}, value);
|
||||
}
|
||||
|
||||
get key (): Bytes {
|
||||
return this.raw.key as Bytes;
|
||||
get key (): StorageKey {
|
||||
return this.raw.key as StorageKey;
|
||||
}
|
||||
|
||||
get value (): Bytes {
|
||||
return this.raw.value as Bytes;
|
||||
get value (): StorageData {
|
||||
return this.raw.value as StorageData;
|
||||
}
|
||||
}
|
||||
|
||||
export type KeyValueOptionValue = {
|
||||
key?: AnyU8a,
|
||||
value?: AnyU8a
|
||||
};
|
||||
|
||||
// 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 {
|
||||
constructor (value?: KeyValueOptionValue) {
|
||||
super({
|
||||
key: StorageKey,
|
||||
value: Option.with(StorageData)
|
||||
}, value);
|
||||
}
|
||||
|
||||
get key (): StorageKey {
|
||||
return this.raw.key as StorageKey;
|
||||
}
|
||||
|
||||
get value (): Option<StorageData> {
|
||||
return this.raw.value as Option<StorageData>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,14 +174,11 @@ export class StorageFunctionType$Map extends Struct {
|
||||
}
|
||||
|
||||
export class StorageFunctionType extends EnumType<Type | StorageFunctionType$Map> {
|
||||
// NOTE Since this is called dynamically, we may have empty values here
|
||||
constructor (index?: number, value?: any) {
|
||||
super([
|
||||
Type,
|
||||
StorageFunctionType$Map
|
||||
], ['Plain', 'Map']);
|
||||
|
||||
this.setValue(index, value);
|
||||
], index, value);
|
||||
}
|
||||
|
||||
get isMap (): boolean {
|
||||
@@ -271,22 +268,20 @@ export default class RuntimeMetadata extends Struct {
|
||||
}, value);
|
||||
}
|
||||
|
||||
// We receive this a an Array<number> in the JSON output from the Node. Convert
|
||||
// We receive this as an Array<number> in the JSON output from the Node. Convert
|
||||
// to u8a and use the fromU8a to do the actual parsing
|
||||
//
|
||||
// FIXME Currently toJSON creates a struct, so it is not a one-to-one mapping
|
||||
// with what is actually found on the RPC layer. This needs to be adjusted to
|
||||
// match. (However for now, it is useful in debugging)
|
||||
fromJSON (input: Array<number>): RuntimeMetadata {
|
||||
return this.fromU8a(
|
||||
Uint8Array.from(input)
|
||||
) as RuntimeMetadata;
|
||||
}
|
||||
|
||||
// FIXME Really not crazy about having to manually add all the getters. Preferably it should
|
||||
// be done automagically in the actual Struct - however what is really important here
|
||||
// here is that we should nbot lose the autocompletion and checking that TS gives us. So if
|
||||
// we have to choose between the 2, manual defs it would have to be.
|
||||
// FIXME Currently toJSON creates a struct, so it is not a one-to-one mapping
|
||||
// with what is actually found on the RPC layer. This needs to be adjusted to
|
||||
// match fromJSON. (However for now, it is useful in debugging)
|
||||
toJSON (): any {
|
||||
return super.toJSON();
|
||||
}
|
||||
|
||||
get events (): Vector<OuterEventMetadataEvent> {
|
||||
return (this.raw.outerEvent as OuterEventMetadata).events;
|
||||
|
||||
@@ -25,7 +25,7 @@ type BftAtReportValue = {
|
||||
// items in the structure is called, except a & b (one should be expected, the
|
||||
// other actual)
|
||||
export class BftAtReport extends Struct {
|
||||
constructor (value: BftAtReportValue = {}) {
|
||||
constructor (value?: BftAtReportValue) {
|
||||
super({
|
||||
round: U32,
|
||||
a: BftHashSignature,
|
||||
@@ -55,13 +55,11 @@ export class BftDoubleCommit extends BftAtReport {
|
||||
}
|
||||
|
||||
export class MisbehaviorKind extends EnumType<BftDoublePrepare | BftDoubleCommit> {
|
||||
constructor (index: number, value: BftAtReportValue = {}) {
|
||||
super([
|
||||
BftDoublePrepare,
|
||||
BftDoubleCommit
|
||||
], [], [0x11, 0x12]);
|
||||
|
||||
this.setValue(index, value);
|
||||
constructor (index: number = 0x11, value?: BftAtReportValue) {
|
||||
super({
|
||||
0x11: BftDoublePrepare,
|
||||
0x12: BftDoubleCommit
|
||||
}, index, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +70,7 @@ type MisbehaviorReportValue = {
|
||||
|
||||
// A Misbehaviour report against a specific AuthorityId
|
||||
export default class MisbehaviorReport extends Struct {
|
||||
constructor (value: MisbehaviorReportValue = {}) {
|
||||
constructor (value?: MisbehaviorReportValue) {
|
||||
super({
|
||||
parentHash: Hash,
|
||||
parentNumber: BlockNumber,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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 Moment from './Moment';
|
||||
import U64 from './U64';
|
||||
|
||||
describe('Moment', () => {
|
||||
it('constructs via Date', () => {
|
||||
expect(
|
||||
new Moment(
|
||||
new Date(1537968546280)
|
||||
).toString()
|
||||
).toEqual('2018-09-26T13:29:07.000Z');
|
||||
});
|
||||
|
||||
it('wraps from another Moment', () => {
|
||||
expect(
|
||||
new Moment(
|
||||
new Moment(1234)
|
||||
).toJSON()
|
||||
).toEqual(1234);
|
||||
});
|
||||
|
||||
it('reads values from JSON', () => {
|
||||
expect(
|
||||
new Moment().fromJSON(42).toNumber()
|
||||
).toEqual(42);
|
||||
});
|
||||
|
||||
it('reads values from u8a', () => {
|
||||
expect(
|
||||
new Moment().fromU8a(
|
||||
new U64(69).toU8a()
|
||||
).toNumber()
|
||||
).toEqual(69);
|
||||
});
|
||||
|
||||
it('creates valid U64 u8a outputs', () => {
|
||||
expect(
|
||||
new U64().fromU8a(
|
||||
new Moment(421).toU8a()
|
||||
).toNumber()
|
||||
).toEqual(421);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
// 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 BN from 'bn.js';
|
||||
import bnToBn from '@polkadot/util/bn/toBn';
|
||||
import bnToU8a from '@polkadot/util/bn/toU8a';
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
|
||||
import Base from './codec/Base';
|
||||
|
||||
const BITLENGTH = 64;
|
||||
|
||||
// A wrapper around seconds/timestamps. Internally the representation only has
|
||||
// second precicion (aligning with Rust), so any numbers passed an/out are always
|
||||
// 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) {
|
||||
super(
|
||||
value instanceof Date
|
||||
? new Date(Math.ceil(value.getTime() / 1000) * 1000)
|
||||
: Moment.decode(value)
|
||||
);
|
||||
}
|
||||
|
||||
static decode (value: Moment | number | BN): Date {
|
||||
return value instanceof Moment
|
||||
? value.raw
|
||||
: new Date(
|
||||
bnToBn(value).toNumber() * 1000
|
||||
);
|
||||
}
|
||||
|
||||
byteLength (): number {
|
||||
return BITLENGTH / 8;
|
||||
}
|
||||
|
||||
fromJSON (input: any): Moment {
|
||||
this.raw = Moment.decode(input);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): Moment {
|
||||
this.raw = Moment.decode(
|
||||
u8aToBn(input.subarray(0, this.byteLength()), true)
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
toJSON (): any {
|
||||
return this.toNumber();
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
return bnToU8a(this.toNumber(), BITLENGTH, true);
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
return this.raw.toISOString();
|
||||
}
|
||||
|
||||
toNumber (): number {
|
||||
return Math.ceil(this.raw.getTime() / 1000);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// 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 NewAccountOutcome from './NewAccountOutcome';
|
||||
|
||||
describe('NewAccountOutcome', () => {
|
||||
it('allows setting value in constructor', () => {
|
||||
expect(
|
||||
new NewAccountOutcome(2).toNumber()
|
||||
).toEqual(2);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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 Enum from './codec/Enum';
|
||||
|
||||
// Enum to track the outcome for creation of an account
|
||||
export default class NewAccountOutcome extends Enum {
|
||||
constructor (index?: number) {
|
||||
super([
|
||||
'NoHint',
|
||||
'GoodHint',
|
||||
'BadHint'
|
||||
], index);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// 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 Origin from './Origin';
|
||||
|
||||
describe('Origin', () => {
|
||||
it('does not allow construction', () => {
|
||||
expect(
|
||||
() => new Origin()
|
||||
).toThrow(/placeholder/);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
// 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 Base from './codec/Base';
|
||||
|
||||
// Where Origin occurs, it should be ignored, so it should never actually be constructed
|
||||
export default class Origin extends Base {
|
||||
constructor () {
|
||||
super();
|
||||
|
||||
throw new Error('Origin should not be constructed, it is only a placeholder for compatibility');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// 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 U64 from './U64';
|
||||
|
||||
// Identifier for a deployed parachain
|
||||
export default class ParachainId extends U64 {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// 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 Extrinsics from './Extrinsics';
|
||||
|
||||
// A list of pending extrinsics
|
||||
export default class PendingExtrinsics extends Extrinsics {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// 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 U32 from './U32';
|
||||
|
||||
// Parts per billion (see also Permill)
|
||||
//
|
||||
// TODO We need to think about the toNumber() and toString() here, so we
|
||||
// want to multiply by 1_000_000_000 for those purposes?
|
||||
export default class Perbill extends U32 {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// 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 U32 from './U32';
|
||||
|
||||
// Parts per million (See also Perbill)
|
||||
//
|
||||
// TODO We need to think about the toNumber() and toString() here, so we
|
||||
// want to multiply by 1_000_000 for those purposes?
|
||||
export default class Permill extends U32 {
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"jsonrpc":"2.0","result":{"apis":[[[105,110,104,101,114,101,110,116],1],[[118,97,108,105,100,97,116,120],1]],"authoring_version":1,"impl_name":"substrate-node","impl_version":0,"spec_name":"node","spec_version":1},"id":1}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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 rpc from './RuntimeVersion.rpc.json';
|
||||
import RuntimeVersion from './RuntimeVersion';
|
||||
|
||||
describe('RuntimeVersion', () => {
|
||||
const version = new RuntimeVersion().fromJSON(rpc.result);
|
||||
|
||||
it('has the correct authoring', () => {
|
||||
expect(version.authoringVersion.toNumber()).toEqual(1);
|
||||
});
|
||||
|
||||
it('has the apis', () => {
|
||||
const api = version.apis.get(0);
|
||||
|
||||
expect(api.id.toHex()).toEqual('0x696e686572656e74');
|
||||
expect(api.version.toNumber()).toEqual(1);
|
||||
});
|
||||
|
||||
it('has the correct implementation', () => {
|
||||
expect(version.implName.toString()).toEqual('substrate-node');
|
||||
expect(version.implVersion.toNumber()).toEqual(0);
|
||||
});
|
||||
|
||||
it('has the correct spec', () => {
|
||||
expect(version.specName.toString()).toEqual('node');
|
||||
expect(version.specVersion.toNumber()).toEqual(1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,92 @@
|
||||
// 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 { AnyNumber, AnyU8a } from './types';
|
||||
|
||||
import Struct from './codec/Struct';
|
||||
import Tuple from './codec/Tuple';
|
||||
import Vector from './codec/Vector';
|
||||
import Text from './Text';
|
||||
import U32 from './U32';
|
||||
import U8aFixed from '@polkadot/api-codec/codec/U8aFixed';
|
||||
|
||||
class ApiId extends U8aFixed {
|
||||
constructor (value?: AnyU8a) {
|
||||
super(value, 64);
|
||||
}
|
||||
}
|
||||
|
||||
type RuntimeVersionApiValue = {
|
||||
id?: AnyU8a,
|
||||
version?: AnyNumber
|
||||
};
|
||||
|
||||
class RuntimeVersionApi extends Tuple {
|
||||
constructor (value?: RuntimeVersionApiValue) {
|
||||
super({
|
||||
id: ApiId,
|
||||
version: U32
|
||||
}, value);
|
||||
}
|
||||
|
||||
get id (): ApiId {
|
||||
return this.raw.id as ApiId;
|
||||
}
|
||||
|
||||
get version (): U32 {
|
||||
return this.raw.version as U32;
|
||||
}
|
||||
}
|
||||
|
||||
type RuntimeVersionValue = {
|
||||
specName?: string,
|
||||
implName?: string,
|
||||
authoringVersion?: AnyNumber,
|
||||
specVersion?: AnyNumber,
|
||||
implVersion?: AnyNumber,
|
||||
apis?: Array<RuntimeVersionApiValue>
|
||||
};
|
||||
|
||||
export default class RuntimeVersion extends Struct {
|
||||
constructor (value?: RuntimeVersionValue) {
|
||||
super({
|
||||
specName: Text,
|
||||
implName: Text,
|
||||
authoringVersion: U32,
|
||||
specVersion: U32,
|
||||
implVersion: U32,
|
||||
apis: Vector.with(RuntimeVersionApi)
|
||||
}, value, new Map([
|
||||
['authoringVersion', 'authoring_version'],
|
||||
['implName', 'impl_name'],
|
||||
['implVersion', 'impl_version'],
|
||||
['specName', 'spec_name'],
|
||||
['specVersion', 'spec_version']
|
||||
]));
|
||||
}
|
||||
|
||||
get apis (): Vector<RuntimeVersionApi> {
|
||||
return this.raw.apis as Vector<RuntimeVersionApi>;
|
||||
}
|
||||
|
||||
get authoringVersion (): U32 {
|
||||
return this.raw.authoringVersion as U32;
|
||||
}
|
||||
|
||||
get implName (): Text {
|
||||
return this.raw.implName as Text;
|
||||
}
|
||||
|
||||
get implVersion (): U32 {
|
||||
return this.raw.implVersion as U32;
|
||||
}
|
||||
|
||||
get specName (): Text {
|
||||
return this.raw.specName as Text;
|
||||
}
|
||||
|
||||
get specVersion (): U32 {
|
||||
return this.raw.specVersion as U32;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ type SignedBlockValue = {
|
||||
};
|
||||
|
||||
export default class SignedBlock extends Struct {
|
||||
constructor (value: SignedBlockValue = {}) {
|
||||
constructor (value?: SignedBlockValue) {
|
||||
super({
|
||||
block: Block,
|
||||
justification: Justification
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// 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 StorageChangeSet from './StorageChangeSet';
|
||||
|
||||
describe('StorageChangeSet', () => {
|
||||
const set = new StorageChangeSet({
|
||||
hash: '0x1234',
|
||||
changes: [
|
||||
{ key: '0xab', value: '0xcd' }
|
||||
]
|
||||
});
|
||||
|
||||
it('wraps hash', () => {
|
||||
expect(
|
||||
set.hash.toHex()
|
||||
).toEqual('0x1234');
|
||||
});
|
||||
|
||||
it('wraps key/value', () => {
|
||||
expect(
|
||||
set.changes.get(0).value.toString()
|
||||
).toEqual('0xcd');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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 { AnyU8a } from './types';
|
||||
|
||||
import Struct from './codec/Struct';
|
||||
import Vector from './codec/Vector';
|
||||
import Hash from './Hash';
|
||||
import { KeyValueOption, KeyValueOptionValue } from './KeyValue';
|
||||
|
||||
type StorageChangeSetValue = {
|
||||
hash?: AnyU8a,
|
||||
changes?: Array<KeyValueOptionValue>
|
||||
};
|
||||
|
||||
// A set of storage changes. It contains the hash/block and
|
||||
// a list of the actual changes that took place
|
||||
export default class StorageChangeSet extends Struct {
|
||||
constructor (value?: StorageChangeSetValue) {
|
||||
super({
|
||||
hash: Hash,
|
||||
changes: Vector.with(KeyValueOption)
|
||||
}, value);
|
||||
}
|
||||
|
||||
get changes (): Vector<KeyValueOption> {
|
||||
return this.raw.changes as Vector<KeyValueOption>;
|
||||
}
|
||||
|
||||
get hash (): Hash {
|
||||
return this.raw.hash as Hash;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// 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 Bytes from './Bytes';
|
||||
|
||||
export default class StorageData extends Bytes {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// 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 Bytes from './Bytes';
|
||||
|
||||
// A representation of a storage key (typically hashed) in the system
|
||||
export default class StorageKey extends Bytes {
|
||||
}
|
||||
@@ -42,7 +42,7 @@ export default class Text extends Base<string> {
|
||||
}
|
||||
|
||||
fromJSON (input: any): Text {
|
||||
this.raw = `${input}`;
|
||||
this.raw = `${input || ''}`;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import Text from './Text';
|
||||
|
||||
type Mapper = (value: string) => string;
|
||||
|
||||
const ALLOWED_BOXES = ['Vec', 'Option'];
|
||||
|
||||
// This is a extended version of String, specifically to handle types. Here we rely full on
|
||||
// what string provides us, however we also "tweak" the types received from the runtime, i.e.
|
||||
// we remove the `T::` prefixes found in some types for consistency accross implementation.
|
||||
@@ -44,6 +46,8 @@ export default class Type extends Text {
|
||||
this._removeWrap('Box'),
|
||||
// remove generics, `MisbehaviorReport<Hash, BlockNumber>` -> `MisbehaviorReport`
|
||||
this._removeGenerics(),
|
||||
// alias String -> Text (compat with jsonrpc methods)
|
||||
this._alias('String', 'Text'),
|
||||
// alias Vec<u8> -> Bytes
|
||||
this._alias('Vec<u8>', 'Bytes')
|
||||
// TODO Check these for possibly matching -
|
||||
@@ -89,9 +93,16 @@ export default class Type extends Text {
|
||||
return (value: string): string => {
|
||||
for (let index = 0; index < value.length; index++) {
|
||||
if (value[index] === '<') {
|
||||
if (value.substr(index - 3, 3) !== 'Vec') {
|
||||
const start = index + 1;
|
||||
const end = this._findClosing(value, start);
|
||||
// check against the allowed wrappers, be it Vec<..>, Option<...> ...
|
||||
const box = ALLOWED_BOXES.find((box) => {
|
||||
const start = index - box.length;
|
||||
|
||||
return start >= 0 && value.substr(start, box.length) === box;
|
||||
});
|
||||
|
||||
// we have not found anything, unwrap generic innards
|
||||
if (!box) {
|
||||
const end = this._findClosing(value, index + 1);
|
||||
|
||||
value = `${value.substr(0, index)}${value.substr(end + 1)}`;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ type ValidatorPrefsValue = {
|
||||
};
|
||||
|
||||
export default class ValidatorPrefs extends Struct {
|
||||
constructor (value: ValidatorPrefsValue = {}) {
|
||||
constructor (value?: ValidatorPrefsValue) {
|
||||
super({
|
||||
unstakeThreshold: U32,
|
||||
validatorPayment: Balance
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// 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 VoteThreshold from './VoteThreshold';
|
||||
|
||||
describe('VoteThreshold', () => {
|
||||
it('starts with default value', () => {
|
||||
expect(
|
||||
new VoteThreshold().toString()
|
||||
).toEqual('Super majority approval');
|
||||
});
|
||||
|
||||
it('allows setting value in constructor', () => {
|
||||
expect(
|
||||
new VoteThreshold(2).toNumber()
|
||||
).toEqual(2);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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 Enum from './codec/Enum';
|
||||
|
||||
// Voting threshold, used inside proposals to set change the voting tally
|
||||
export default class VoteThreshold extends Enum {
|
||||
constructor (index?: number) {
|
||||
super([
|
||||
'Super majority approval',
|
||||
'Super majority rejection',
|
||||
'Simple majority'
|
||||
], index);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,10 @@
|
||||
|
||||
import Base from './Base';
|
||||
|
||||
type EnumDef = {
|
||||
[index: number]: string
|
||||
} | Array<string>;
|
||||
|
||||
// A codec wrapper for an enum. Enums are encoded as a single byte, where the byte
|
||||
// is a zero-indexed value. This class allows you to retrieve the value either
|
||||
// by `toNumber()` exposing the actual raw index, or `toString()` returning a
|
||||
@@ -12,16 +16,16 @@ import Base from './Base';
|
||||
// TODO:
|
||||
// - It would be great if this could actually wrap actual TS enums
|
||||
export default class Enum extends Base<number> {
|
||||
private _strings: Array<string>;
|
||||
private _enum: EnumDef;
|
||||
|
||||
constructor (strings: Array<string>, value: Enum | number = 0) {
|
||||
constructor (def: EnumDef, value: Enum | number = 0) {
|
||||
super(
|
||||
value instanceof Enum
|
||||
? value.raw
|
||||
: value
|
||||
);
|
||||
|
||||
this._strings = strings;
|
||||
this._enum = def;
|
||||
}
|
||||
|
||||
byteLength (): number {
|
||||
@@ -29,12 +33,14 @@ export default class Enum extends Base<number> {
|
||||
}
|
||||
|
||||
fromJSON (input: any): Enum {
|
||||
// FIXME We potentially want to assert that the value is actually inside this._enum
|
||||
this.raw = input;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): Enum {
|
||||
// FIXME We potentially want to assert that the value is actually inside this._enum
|
||||
this.raw = input[0];
|
||||
|
||||
return this;
|
||||
@@ -53,6 +59,6 @@ export default class Enum extends Base<number> {
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
return this._strings[this.raw] || `${this.raw}`;
|
||||
return this._enum[this.raw] || `${this.raw}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('Struct', () => {
|
||||
it('provides a clean toString() (raw)', () => {
|
||||
expect(
|
||||
new EnumType(
|
||||
[Text, U32], ['Stringy', 'Inty']
|
||||
[Text, U32]
|
||||
).fromU8a(new Uint8Array([0, 2 << 2, 49, 50])).raw.toString()
|
||||
).toEqual('12');
|
||||
});
|
||||
@@ -26,7 +26,7 @@ describe('Struct', () => {
|
||||
it('allows checking against defined indexes', () => {
|
||||
expect(
|
||||
new EnumType(
|
||||
[Text, U32], [], [1, 5]
|
||||
{ 1: Text, 5: U32 }
|
||||
).fromU8a(new Uint8Array([1, 2 << 2, 49, 50])).toString()
|
||||
).toEqual('Text');
|
||||
});
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
import Base from './Base';
|
||||
|
||||
type TypesArray = Array<{ new(value?: any): Base }>;
|
||||
type TypesDef = {
|
||||
[index: number]: { new(value?: any): Base }
|
||||
} | TypesArray;
|
||||
|
||||
// This implements an enum, that based on the value wraps a different type. It is effectively an
|
||||
// extension to enum where the value type is determined by the actual index.
|
||||
//
|
||||
@@ -12,24 +17,24 @@ import Base from './Base';
|
||||
// - It should rather probably extend Enum instead of copying code
|
||||
// - There doesn't actually seem to be a way to get to the actual determined/wrapped value
|
||||
export default class EnumType <T> extends Base<Base<T>> {
|
||||
private _Types: Array<{ new(value?: any): Base }>;
|
||||
private _Types: TypesArray;
|
||||
private _index: number;
|
||||
private _indexes: Array<number>;
|
||||
private _strings: Array<string>;
|
||||
|
||||
constructor (Types: Array<{ new(value?: any): Base }>, strings: Array<string> = [], indexes: Array<number> = []) {
|
||||
constructor (def: TypesDef, index?: number, value?: any) {
|
||||
super(
|
||||
new Types[0]()
|
||||
new (Object.values(def)[0])()
|
||||
);
|
||||
|
||||
this._Types = Types;
|
||||
this._indexes = Types.map((Type, index) =>
|
||||
indexes[index] || index
|
||||
this._Types = Array.isArray(def)
|
||||
? def
|
||||
: Object.values(def);
|
||||
this._indexes = Object.keys(def).map((index) =>
|
||||
parseInt(index, 10)
|
||||
);
|
||||
this._index = this._indexes[0];
|
||||
this._strings = Types.map((Type, index) =>
|
||||
strings[index] || Type.name
|
||||
);
|
||||
|
||||
this.setValue(index, value);
|
||||
}
|
||||
|
||||
get Type (): string {
|
||||
@@ -41,15 +46,19 @@ export default class EnumType <T> extends Base<Base<T>> {
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): EnumType<T> {
|
||||
this._index = this._indexes.indexOf(input[0]);
|
||||
this.raw = new this._Types[this._index]().fromU8a(input.subarray(1));
|
||||
this.setValue(input[0]);
|
||||
this.raw.fromU8a(input.subarray(1));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
setValue (index?: number, value?: any): void {
|
||||
// NOTE If this is called from constructors, we may have empty values...
|
||||
this._index = this._indexes.indexOf(index || 0) || 0;
|
||||
this._index = this._indexes.indexOf(index || 0);
|
||||
|
||||
if (this._index === -1) {
|
||||
this._index = this._indexes[0];
|
||||
}
|
||||
|
||||
this.raw = new this._Types[this._index](value);
|
||||
}
|
||||
|
||||
@@ -62,6 +71,6 @@ export default class EnumType <T> extends Base<Base<T>> {
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
return this._strings[this._index];
|
||||
return this._Types[this._index].name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,4 +31,18 @@ describe('Struct', () => {
|
||||
baz: 'U32'
|
||||
});
|
||||
});
|
||||
|
||||
it('exposes the keys/values', () => {
|
||||
const test = new Struct({
|
||||
foo: Text,
|
||||
bar: U32
|
||||
}, { foo: 'bazzing', bar: 69 });
|
||||
|
||||
expect(test.keys()).toEqual(['foo', 'bar']);
|
||||
expect(
|
||||
test.values().map((v) =>
|
||||
v.toString()
|
||||
)
|
||||
).toEqual(['bazzing', '0x00000045']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,9 +21,10 @@ export default class Struct <
|
||||
// type names, mapped by key, name of Class in S
|
||||
E = { [K in keyof S]: string }
|
||||
> extends Base<T> {
|
||||
private _Types: E;
|
||||
protected _jsonMap: Map<keyof S, string>;
|
||||
protected _Types: E;
|
||||
|
||||
constructor (Types: S, value: V = {} as V) {
|
||||
constructor (Types: S, value: V = {} as V, jsonMap: Map<keyof S, string> = new Map()) {
|
||||
super(
|
||||
Object
|
||||
.keys(Types)
|
||||
@@ -38,6 +39,7 @@ export default class Struct <
|
||||
}, {} as T)
|
||||
);
|
||||
|
||||
this._jsonMap = jsonMap;
|
||||
this._Types = Object
|
||||
.keys(Types)
|
||||
.reduce((result: E, key) => {
|
||||
@@ -52,8 +54,8 @@ export default class Struct <
|
||||
S = { [index: string]: { new(value?: any): Base } }
|
||||
> (Types: S): { new(value?: any): Struct<S> } {
|
||||
return class extends Struct<S> {
|
||||
constructor (value?: any) {
|
||||
super(Types, value);
|
||||
constructor (value?: any, jsonMap?: Map<keyof S, string>) {
|
||||
super(Types, value, jsonMap);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -69,30 +71,21 @@ export default class Struct <
|
||||
}
|
||||
|
||||
fromJSON (input: any): Struct<S, T, V, E> {
|
||||
// NOTE From Rust, anonymous structures are encoded to Arrays, here
|
||||
// we handle that case, taking each value in the array and passing it
|
||||
// (in order) to the actual decoders (See e.g. SignedBlock.spec.json)
|
||||
const isArrayIn = Array.isArray(input);
|
||||
Object.keys(this.raw).forEach((key) => {
|
||||
const jsonKey = this._jsonMap.get(key as any) || key;
|
||||
|
||||
Object.keys(this.raw).forEach((key, index) => {
|
||||
// @ts-ignore as above...
|
||||
this.raw[key].fromJSON(
|
||||
isArrayIn
|
||||
? input[index]
|
||||
: input[key]
|
||||
);
|
||||
this.raw[key].fromJSON(input[jsonKey]);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): Struct<S, T, V, E> {
|
||||
Object.keys(this.raw).reduce((offset, key) => {
|
||||
// @ts-ignore as above...
|
||||
this.raw[key].fromU8a(input.subarray(offset));
|
||||
Object.values(this.raw).reduce((offset, entry) => {
|
||||
entry.fromU8a(input.subarray(offset));
|
||||
|
||||
// @ts-ignore as above...
|
||||
return offset + this.raw[key].byteLength();
|
||||
return offset + entry.byteLength();
|
||||
}, 0);
|
||||
|
||||
return this;
|
||||
@@ -100,18 +93,23 @@ export default class Struct <
|
||||
|
||||
toJSON (): any {
|
||||
return Object.keys(this.raw).reduce((json, key) => {
|
||||
const jsonKey = this._jsonMap.get(key as any) || key;
|
||||
|
||||
// @ts-ignore as above...
|
||||
json[key] = this.raw[key].toJSON();
|
||||
json[jsonKey] = this.raw[key].toJSON();
|
||||
|
||||
return json;
|
||||
}, {} as any);
|
||||
}
|
||||
|
||||
keys (): Array<string> {
|
||||
return Object.keys(this.raw);
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
return u8aConcat(
|
||||
...Object.keys(this.raw).map((key) =>
|
||||
// @ts-ignore as above...
|
||||
this.raw[key].toU8a()
|
||||
...Object.values(this.raw).map((entry) =>
|
||||
entry.toU8a()
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -124,4 +122,8 @@ export default class Struct <
|
||||
|
||||
return `{${data}}`;
|
||||
}
|
||||
|
||||
values (): Array<Base> {
|
||||
return Object.values(this.raw);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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 Text from '../Text';
|
||||
import U32 from '../U32';
|
||||
import Tuple from './Tuple';
|
||||
|
||||
describe('Tuple', () => {
|
||||
let tuple;
|
||||
|
||||
beforeEach(() => {
|
||||
tuple = new Tuple({
|
||||
foo: Text,
|
||||
bar: U32
|
||||
}, { foo: 'foo', bar: 69 });
|
||||
});
|
||||
|
||||
it('returns array with toJSON', () => {
|
||||
expect(
|
||||
tuple.toJSON()
|
||||
).toEqual([
|
||||
'foo',
|
||||
'0x00000045'
|
||||
]);
|
||||
});
|
||||
|
||||
it('initialises via JSON array', () => {
|
||||
const test = new (Tuple.with({
|
||||
a: Text,
|
||||
b: U32,
|
||||
c: Text
|
||||
}))();
|
||||
|
||||
expect(
|
||||
test.fromJSON([
|
||||
'bazzing', 32
|
||||
]).toJSON()
|
||||
).toEqual([
|
||||
'bazzing',
|
||||
'0x00000020',
|
||||
''
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
// 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 Base from './Base';
|
||||
import Struct from './Struct';
|
||||
|
||||
// A Tuple defines an anonymous Object with key/values - where the values are Base<T> values.It
|
||||
// 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 = { [index: string]: { new(value?: any): Base } },
|
||||
T = { [K in keyof S]: Base }
|
||||
> extends Struct<S, T> {
|
||||
static with <
|
||||
S = { [index: string]: { new(value?: any): Base } }
|
||||
> (Types: S): { new(value?: any): Tuple<S> } {
|
||||
return class extends Tuple<S> {
|
||||
constructor (value?: any) {
|
||||
super(Types, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fromJSON (input: any): Tuple<S, T> {
|
||||
Object.values(this.raw).forEach((entry, index) => {
|
||||
entry.fromJSON(input[index]);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
toJSON (): any {
|
||||
return Object.values(this.raw).map((entry) =>
|
||||
entry.toJSON()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import { AnyU8a } from '../types';
|
||||
|
||||
import U8a from './U8a';
|
||||
|
||||
type BitLength = 256 | 512;
|
||||
type BitLength = 64 | 128 | 256 | 512;
|
||||
|
||||
// A U8a that manages a a sequence of bytes up to the specified bitLength. Not meant
|
||||
// to be used directly, rather is should be subclassed with the specific lengths.
|
||||
|
||||
@@ -44,7 +44,7 @@ describe('Vector', () => {
|
||||
describe('array-like functions', () => {
|
||||
it('allows retrieval of a specific item', () => {
|
||||
expect(
|
||||
array.at(2).toString()
|
||||
array.get(2).toString()
|
||||
).toEqual('345');
|
||||
});
|
||||
|
||||
|
||||
@@ -53,10 +53,6 @@ export default class Vector <
|
||||
}, this._length.byteLength());
|
||||
}
|
||||
|
||||
at (index: number): T {
|
||||
return this.raw[index];
|
||||
}
|
||||
|
||||
filter (fn: (entry: T, index?: number) => any): Array<T> {
|
||||
return this.raw.filter(fn);
|
||||
}
|
||||
@@ -90,6 +86,10 @@ export default class Vector <
|
||||
return this;
|
||||
}
|
||||
|
||||
get (index: number): T {
|
||||
return this.raw[index];
|
||||
}
|
||||
|
||||
map <O> (fn: (entry: T, index?: number) => O): Array<O> {
|
||||
return this.raw.map(fn);
|
||||
}
|
||||
|
||||
@@ -9,4 +9,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';
|
||||
|
||||
@@ -19,6 +19,9 @@ export { default as BlockNumber } from './BlockNumber';
|
||||
export { default as Bool } from './Bool';
|
||||
export { default as Bytes } from './Bytes';
|
||||
export { default as Extrinsic } from './Extrinsic';
|
||||
// NOTE Only used internally, exported as PendingExtrinsics
|
||||
// export { default as Extrinsics } from './Extrinsics';
|
||||
export { default as Gas } from './Gas';
|
||||
// NOTE These are currently only used internally, no direct mapping to Rust strings
|
||||
// export { default as H256 } from './H256';
|
||||
// export { default as H512 } from './H512';
|
||||
@@ -27,16 +30,26 @@ export { default as Header } from './Header';
|
||||
export { default as KeyValue } from './KeyValue';
|
||||
export { default as Metadata } from './Metadata';
|
||||
export { default as MisbehaviorReport } from './MisbehaviorReport';
|
||||
export { default as Moment } from './Moment';
|
||||
export { default as NewAccountOutcome } from './NewAccountOutcome';
|
||||
// NOTE Nonce is renamed to Index
|
||||
export { default as Index } from './Nonce';
|
||||
export { default as Origin } from './Origin';
|
||||
export { default as ParachainId } from './ParachainId';
|
||||
export { default as PendingExtrinsics } from './PendingExtrinsics';
|
||||
export { default as Permill } from './Permill';
|
||||
export { default as Perbill } from './Perbill';
|
||||
export { default as PropIndex } from './PropIndex';
|
||||
export { default as ProposalIndex } from './ProposalIndex';
|
||||
export { default as RawAddress } from './RawAddress';
|
||||
export { default as ReferendumIndex } from './ReferendumIndex';
|
||||
export { default as RuntimeVersion } from './RuntimeVersion';
|
||||
export { default as Signature } from './Signature';
|
||||
export { default as SignedBlock } from './SignedBlock';
|
||||
// NOTE Text is currently only used internally, export not needed
|
||||
// export { default as Text } from './Text';
|
||||
export { default as StorageChangeSet } from './StorageChangeSet';
|
||||
export { default as StorageData } from './StorageData';
|
||||
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';
|
||||
@@ -45,5 +58,6 @@ 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 ValidatorPrefx } from './ValidatorPrefs';
|
||||
export { default as UoteIndex } from './VoteIndex';
|
||||
export { default as ValidatorPrefs } from './ValidatorPrefs';
|
||||
export { default as VoteThreshold } from './VoteThreshold';
|
||||
export { default as VoteIndex } from './VoteIndex';
|
||||
|
||||
@@ -43,7 +43,7 @@ const formatters = new Map<Param$Types, FormatterFunction>([
|
||||
['Bytes', bytesDecode],
|
||||
['Hash', hashDecode],
|
||||
['Header', headerDecode],
|
||||
['MetaData', metaDecode],
|
||||
['Metadata', metaDecode],
|
||||
['SignedBlock', blockDecode],
|
||||
['u64', bnDecode]
|
||||
]);
|
||||
|
||||
@@ -13,27 +13,6 @@ describe.skip('e2e basics', () => {
|
||||
api = new Api(new Ws('ws://127.0.0.1:9944'));
|
||||
});
|
||||
|
||||
it('subscribes to chain_newHead', (done) => {
|
||||
let count = 0;
|
||||
|
||||
// tslint:disable-next-line
|
||||
api.chain
|
||||
.newHead((error, data) => {
|
||||
if (error) {
|
||||
return done(error);
|
||||
}
|
||||
|
||||
expect(data).toBeDefined();
|
||||
|
||||
if (++count === 3) {
|
||||
done();
|
||||
}
|
||||
})
|
||||
.then((subscriptionId) => {
|
||||
console.log('newHead: subscriptionId =', subscriptionId);
|
||||
});
|
||||
});
|
||||
|
||||
it('retrieves the pending extrinsics', () => {
|
||||
return api.author
|
||||
.pendingExtrinsics()
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// 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 Api from '../../api/src';
|
||||
import Ws from '../src/ws';
|
||||
|
||||
describe.skip('e2e chain', () => {
|
||||
let api;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.setTimeout(30000);
|
||||
api = new Api(new Ws('ws://127.0.0.1:9944'));
|
||||
});
|
||||
|
||||
it('subscribes to chain_newHead', (done) => {
|
||||
let count = 0;
|
||||
|
||||
// tslint:disable-next-line
|
||||
api.chain
|
||||
.newHead((error, data) => {
|
||||
if (error) {
|
||||
return done(error);
|
||||
}
|
||||
|
||||
expect(data).toBeDefined();
|
||||
|
||||
if (++count === 3) {
|
||||
done();
|
||||
}
|
||||
})
|
||||
.then((subscriptionId) => {
|
||||
console.log('newHead: subscriptionId =', subscriptionId);
|
||||
});
|
||||
});
|
||||
|
||||
it('retrieves the runtime version', () => {
|
||||
return api.chain
|
||||
.getRuntimeVersion()
|
||||
.then((version) => {
|
||||
console.error('version', version);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -11,7 +11,7 @@ import createSection from '@polkadot/params/section';
|
||||
const pendingExtrinsics: CreateItemOptions = {
|
||||
description: 'Returns all pending extrinsics, potentially grouped by sender',
|
||||
params: [],
|
||||
type: 'PrendingExtrinsics'
|
||||
type: 'PendingExtrinsics'
|
||||
};
|
||||
|
||||
const submitExtrinsic: CreateItemOptions = {
|
||||
|
||||
@@ -30,6 +30,20 @@ const getHeader: CreateItemOptions = {
|
||||
type: 'Header'
|
||||
};
|
||||
|
||||
const getRuntimeVersion: CreateItemOptions = {
|
||||
description: ' Get the runtime version',
|
||||
params: [],
|
||||
type: 'RuntimeVersion'
|
||||
};
|
||||
|
||||
const getRuntimeVersionAt: CreateItemOptions = {
|
||||
description: ' Get the runtime version at a specific block',
|
||||
params: [
|
||||
param('hash', 'Hash')
|
||||
],
|
||||
type: 'RuntimeVersion'
|
||||
};
|
||||
|
||||
const newHead: CreateItemOptions = {
|
||||
description: 'Retrieves the best header via subscription',
|
||||
subscribe: [
|
||||
@@ -43,7 +57,7 @@ const newHead: CreateItemOptions = {
|
||||
const privateMethods: CreateItemOptionsMap = {};
|
||||
|
||||
const publicMethods: CreateItemOptionsMap = {
|
||||
getBlock, getHead, getHeader, newHead
|
||||
getBlock, getHead, getHeader, getRuntimeVersion, getRuntimeVersionAt, newHead
|
||||
};
|
||||
|
||||
export type PublicMethods = typeof publicMethods;
|
||||
|
||||
@@ -30,7 +30,7 @@ const callAt: CreateItemOptions = {
|
||||
const getMetadata: CreateItemOptions = {
|
||||
description: 'Returns the runtime metadata',
|
||||
params: [],
|
||||
type: 'MetaData'
|
||||
type: 'Metadata'
|
||||
};
|
||||
|
||||
const getMetadataAt: CreateItemOptions = {
|
||||
@@ -38,7 +38,7 @@ const getMetadataAt: CreateItemOptions = {
|
||||
params: [
|
||||
param('block', 'Hash')
|
||||
],
|
||||
type: 'MetaData'
|
||||
type: 'Metadata'
|
||||
};
|
||||
|
||||
const getStorage: CreateItemOptions = {
|
||||
|
||||
@@ -81,7 +81,7 @@ export default function decodeValue (decode: Decoder, type: Param$Type, _input:
|
||||
return keyValue(input);
|
||||
|
||||
// HACKY, but a stopgap...
|
||||
case 'MetaData':
|
||||
case 'Metadata':
|
||||
return u8a(input, (input as Uint8Array).length * 8, 0);
|
||||
|
||||
case 'MisbehaviorReport':
|
||||
@@ -94,6 +94,9 @@ export default function decodeValue (decode: Decoder, type: Param$Type, _input:
|
||||
case 'VoteIndex':
|
||||
return bn(input, 32);
|
||||
|
||||
case 'RuntimeVersion':
|
||||
return u8a(input, 256, 0);
|
||||
|
||||
case 'Signature':
|
||||
return u8a(input, 512, 0);
|
||||
|
||||
|
||||
Vendored
+3
-3
@@ -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' | 'PrendingExtrinsics' | 'PropIndex' | 'Proposal' | 'ReferendumIndex' | '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' | 'StorageResult' | 'StorageResultSet' | 'String' | 'Timestamp' | 'u32' | 'u64' | 'u128' | 'VoteIndex' | 'VoteThreshold';
|
||||
|
||||
export type Param$Type$Array = Array<Param$Type | Array<Param$Type | Array<Param$Type>>>;
|
||||
|
||||
@@ -48,7 +48,7 @@ export type BlockDecoded = {
|
||||
justification: BlockJustificationDecoded
|
||||
};
|
||||
|
||||
export type MetaData = {
|
||||
export type Metadata = {
|
||||
};
|
||||
|
||||
export type KeyValue = {
|
||||
@@ -56,7 +56,7 @@ export type KeyValue = {
|
||||
value: Uint8Array
|
||||
}
|
||||
|
||||
export type Param$Value = Digest | Header | KeyValue | MetaData | MisbehaviorReport | ExtrinsicDecoded | BN | Date | Uint8Array | boolean | number | string | null;
|
||||
export type Param$Value = Digest | Header | KeyValue | Metadata | MisbehaviorReport | ExtrinsicDecoded | BN | Date | Uint8Array | boolean | number | string | null;
|
||||
|
||||
export type Param$Value$Array = Array<Param$Value | Array<Param$Value | Array<Param$Value>>>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user