Pull in observable API from UI (#175)
* Pull in observable api... * Progress changing stuff... * votingBalance * Update resul types * Expose toBn on Moment * Rework... WIP * ... More type cleanups * Linting passes * BN helpers for UInt * Update api-observable * Add api-observable package.json * Allow Struct/Tuple to create from hex string * Future-proof Length with bitLength (u64/u128 compant encoding PR out) * Make Compact number encoding shareable * Split Api into functional sections * Cleanup types * Additional per-use comments * Remove params/primitives from README * api-format -> api-codec * Whitespace.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -4,6 +4,8 @@
|
||||
|
||||
import { AnyNumber } from './types';
|
||||
|
||||
import toU8a from '@polkadot/util/u8a/toU8a';
|
||||
|
||||
import Vector from './codec/Vector';
|
||||
import Base from './codec/Base';
|
||||
import Enum from './codec/Enum';
|
||||
@@ -285,9 +287,9 @@ export default class RuntimeMetadata extends Struct {
|
||||
|
||||
// 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
|
||||
fromJSON (input: Array<number>): RuntimeMetadata {
|
||||
fromJSON (input: Uint8Array | string | Array<number>): RuntimeMetadata {
|
||||
return this.fromU8a(
|
||||
Uint8Array.from(input)
|
||||
toU8a(input)
|
||||
) as RuntimeMetadata;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +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> {
|
||||
constructor (value: Uint8Array | Moment | Date | number = 0) {
|
||||
constructor (value: Uint8Array | Moment | Date | BN | number = 0) {
|
||||
super(
|
||||
value instanceof Date
|
||||
? new Date(Math.ceil(value.getTime() / 1000) * 1000)
|
||||
@@ -55,6 +55,10 @@ export default class Moment extends Base<Date> {
|
||||
return this;
|
||||
}
|
||||
|
||||
getTime (): number {
|
||||
return this.raw.getTime();
|
||||
}
|
||||
|
||||
toJSON (): any {
|
||||
return this.toNumber();
|
||||
}
|
||||
@@ -67,6 +71,10 @@ export default class Moment extends Base<Date> {
|
||||
return this.raw.toISOString();
|
||||
}
|
||||
|
||||
toBn (): BN {
|
||||
return new BN(this.toNumber());
|
||||
}
|
||||
|
||||
toNumber (): number {
|
||||
return Math.ceil(this.raw.getTime() / 1000);
|
||||
}
|
||||
|
||||
@@ -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 Extrinsic from './Extrinsic';
|
||||
|
||||
// The Nonce or number of transactiosn sent by a specific account. Generally used
|
||||
// with extrinsics to determine the order of execution.
|
||||
export default class Proposal extends Extrinsic {
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// 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 bnToU8a from '@polkadot/util/bn/toU8a';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
|
||||
const MAX_U8 = new BN(2).pow(new BN(8 - 2)).subn(1);
|
||||
const MAX_U16 = new BN(2).pow(new BN(16 - 2)).subn(1);
|
||||
const MAX_U32 = new BN(2).pow(new BN(32 - 2)).subn(1);
|
||||
|
||||
type BitLength = 32;
|
||||
|
||||
// A new compact length-encoding algorithm. It performs the same function as Length, however
|
||||
// differs in that it uses a variable number of bytes to do the actual encoding. From the Rust
|
||||
// implementation for compact encoding
|
||||
//
|
||||
// 0b00 00 00 00 / 00 00 00 00 / 00 00 00 00 / 00 00 00 00
|
||||
// (0 ... 2**6 - 1) (u8)
|
||||
// xx xx xx 00
|
||||
// (2**6 ... 2**14 - 1) (u8, u16) low LH high
|
||||
// yL yL yL 01 / yH yH yH yL
|
||||
// (2**14 ... 2**30 - 1) (u16, u32) low LMMH high
|
||||
// zL zL zL 10 / zM zM zM zL / zM zM zM zM / zH zH zH zM
|
||||
// (2**30 ... 2**536 - 1) (u32, u64, u128, U256, U512, U520) straight LE-encoded
|
||||
// nn nn nn 11 [ / zz zz zz zz ]{4 + n}
|
||||
//
|
||||
// Note: we use *LOW BITS* of the LSB in LE encoding to encode the 2 bit key.
|
||||
export default class Compact {
|
||||
static decode (input: Uint8Array, bitLength: BitLength): BN {
|
||||
const flag = input[0] & 0b11;
|
||||
|
||||
if (flag === 0b00) {
|
||||
return new BN(input[0]).shrn(2);
|
||||
} else if (flag === 0b01) {
|
||||
return u8aToBn(input.slice(0, 2), true).shrn(2);
|
||||
} else if (flag === 0b10) {
|
||||
return u8aToBn(input.slice(0, 4), true).shrn(2);
|
||||
}
|
||||
|
||||
const byteLength = bitLength / 8;
|
||||
|
||||
return u8aToBn(input.subarray(1, 1 + byteLength), true);
|
||||
}
|
||||
|
||||
static encode (length: BN, bitLength: BitLength): Uint8Array {
|
||||
if (length.lte(MAX_U8)) {
|
||||
return new Uint8Array([length.toNumber() << 2]);
|
||||
} else if (length.lte(MAX_U16)) {
|
||||
return bnToU8a(length.shln(2).addn(0b01), 16, true);
|
||||
} else if (length.lte(MAX_U32)) {
|
||||
return bnToU8a(length.shln(2).addn(0b10), 32, true);
|
||||
}
|
||||
|
||||
return u8aConcat(
|
||||
new Uint8Array([
|
||||
0b11
|
||||
]),
|
||||
bnToU8a(length, bitLength, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,33 +6,16 @@ import { AnyNumber } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import bnToBn from '@polkadot/util/bn/toBn';
|
||||
import bnToU8a from '@polkadot/util/bn/toU8a';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
|
||||
import Base from './Base';
|
||||
import Compact from './Compact';
|
||||
import UInt from './UInt';
|
||||
|
||||
const MAX_U8 = new BN(2).pow(new BN(8 - 2)).subn(1);
|
||||
const MAX_U16 = new BN(2).pow(new BN(16 - 2)).subn(1);
|
||||
const MAX_U32 = new BN(2).pow(new BN(32 - 2)).subn(1);
|
||||
type BitLength = 32;
|
||||
|
||||
// A new compact length-encoding algorithm. It performs the same function as Length, however
|
||||
// differs in that it uses a variable number of bytes to do the actual encoding. From the Rust
|
||||
// implementation for compact encoding
|
||||
//
|
||||
// 0b00 00 00 00 / 00 00 00 00 / 00 00 00 00 / 00 00 00 00
|
||||
// (0 ... 2**6 - 1) (u8)
|
||||
// xx xx xx 00
|
||||
// (2**6 ... 2**14 - 1) (u8, u16) low LH high
|
||||
// yL yL yL 01 / yH yH yH yL
|
||||
// (2**14 ... 2**30 - 1) (u16, u32) low LMMH high
|
||||
// zL zL zL 10 / zM zM zM zL / zM zM zM zM / zH zH zH zM
|
||||
// (2**30 ... 2**536 - 1) (u32, u64, u128, U256, U512, U520) straight LE-encoded
|
||||
// nn nn nn 11 [ / zz zz zz zz ]{4 + n}
|
||||
//
|
||||
// Note: we use *LOW BITS* of the LSB in LE encoding to encode the 2 bit key.
|
||||
// A Length-prefix that can be added to any variable length stream of bytes, e.g. String,
|
||||
// Vectors and Bytes
|
||||
//
|
||||
// FIXME Not crazy about the use of Length. If we look at Vector, Bytes & String,
|
||||
// the implementations are basically the same. Vector is slightly different since
|
||||
@@ -40,41 +23,14 @@ const MAX_U32 = new BN(2).pow(new BN(32 - 2)).subn(1);
|
||||
// code and a more generic implementation around the use of Length. Looking at
|
||||
// Array or Struct, the same type of wrapper would be useful here.
|
||||
export default class Length extends Base<BN> {
|
||||
constructor (value: AnyNumber = new BN(0)) {
|
||||
private _bitLength: BitLength;
|
||||
|
||||
constructor (value: AnyNumber = new BN(0), bitLength: BitLength = 32) {
|
||||
super(
|
||||
UInt.decode(value)
|
||||
);
|
||||
}
|
||||
|
||||
static decode (input: Uint8Array): BN {
|
||||
const flag = input[0] & 0b11;
|
||||
|
||||
if (flag === 0b00) {
|
||||
return new BN(input[0]).shrn(2);
|
||||
} else if (flag === 0b01) {
|
||||
return u8aToBn(input.slice(0, 2), true).shrn(2);
|
||||
} else if (flag === 0b10) {
|
||||
return u8aToBn(input.slice(0, 4), true).shrn(2);
|
||||
}
|
||||
|
||||
return u8aToBn(input.subarray(1, 5), true);
|
||||
}
|
||||
|
||||
static encode (length: BN): Uint8Array {
|
||||
if (length.lte(MAX_U8)) {
|
||||
return new Uint8Array([length.toNumber() << 2]);
|
||||
} else if (length.lte(MAX_U16)) {
|
||||
return bnToU8a(length.shln(2).addn(0b01), 16, true);
|
||||
} else if (length.lte(MAX_U32)) {
|
||||
return bnToU8a(length.shln(2).addn(0b10), 32, true);
|
||||
}
|
||||
|
||||
return u8aConcat(
|
||||
new Uint8Array([
|
||||
0b11
|
||||
]),
|
||||
bnToU8a(length, 32, true)
|
||||
);
|
||||
this._bitLength = bitLength;
|
||||
}
|
||||
|
||||
byteLength (): number {
|
||||
@@ -82,7 +38,7 @@ export default class Length extends Base<BN> {
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): Length {
|
||||
this.raw = Length.decode(input);
|
||||
this.raw = Compact.decode(input, this._bitLength);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -98,7 +54,7 @@ export default class Length extends Base<BN> {
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return isBare
|
||||
? new Uint8Array()
|
||||
: Length.encode(this.raw);
|
||||
: Compact.encode(this.raw, this._bitLength);
|
||||
}
|
||||
|
||||
setValue (value: BN | number): void {
|
||||
|
||||
@@ -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 hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
import isHex from '@polkadot/util/is/hex';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
import Base, { l } from './Base';
|
||||
@@ -82,6 +84,10 @@ export default class Struct <
|
||||
}
|
||||
|
||||
fromJSON (input: any): Struct<S, T, V, E> {
|
||||
if (isHex(input)) {
|
||||
return this.fromU8a(hexToU8a(input));
|
||||
}
|
||||
|
||||
Object.keys(this.raw).forEach((key) => {
|
||||
const jsonKey = this._jsonMap.get(key as any) || key;
|
||||
|
||||
@@ -102,6 +108,10 @@ export default class Struct <
|
||||
return this;
|
||||
}
|
||||
|
||||
get (index: number): Base {
|
||||
return this.values()[index];
|
||||
}
|
||||
|
||||
toJSON (): any {
|
||||
return Object.keys(this.raw).reduce((json, key) => {
|
||||
const jsonKey = this._jsonMap.get(key as any) || key;
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
// 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 isHex from '@polkadot/util/is/hex';
|
||||
|
||||
import Base from './Base';
|
||||
import Struct from './Struct';
|
||||
|
||||
@@ -29,6 +32,10 @@ export default class Tuple <
|
||||
}
|
||||
|
||||
fromJSON (input: any): Tuple<S, T, V> {
|
||||
if (isHex(input)) {
|
||||
return this.fromU8a(hexToU8a(input));
|
||||
}
|
||||
|
||||
Object.values(this.raw).forEach((entry, index) => {
|
||||
entry.fromJSON(input[index]);
|
||||
});
|
||||
|
||||
@@ -89,4 +89,54 @@ export default class UInt extends Base<BN> {
|
||||
toNumber (): number {
|
||||
return this.raw.toNumber();
|
||||
}
|
||||
|
||||
// helpers from BN, this would be great as a "don't do this", i.e. extending properly
|
||||
// from BN. Underlying these will always return BN (unless it is compare checks)
|
||||
add (other: UInt | BN | number): BN {
|
||||
return other instanceof UInt
|
||||
? this.raw.add(other.raw)
|
||||
: this.raw.add(bnToBn(other));
|
||||
}
|
||||
|
||||
div (other: UInt | BN | number): BN {
|
||||
return other instanceof UInt
|
||||
? this.raw.div(other.raw)
|
||||
: this.raw.div(bnToBn(other));
|
||||
}
|
||||
|
||||
lt (test: UInt | BN | number): boolean {
|
||||
return test instanceof UInt
|
||||
? this.raw.lt(test.raw)
|
||||
: this.raw.lt(bnToBn(test));
|
||||
}
|
||||
|
||||
lte (test: UInt | BN | number): boolean {
|
||||
return test instanceof UInt
|
||||
? this.raw.lte(test.raw)
|
||||
: this.raw.lte(bnToBn(test));
|
||||
}
|
||||
|
||||
gt (test: UInt | BN | number): boolean {
|
||||
return test instanceof UInt
|
||||
? this.raw.gt(test.raw)
|
||||
: this.raw.gt(bnToBn(test));
|
||||
}
|
||||
|
||||
gte (test: UInt | BN | number): boolean {
|
||||
return test instanceof UInt
|
||||
? this.raw.gte(test.raw)
|
||||
: this.raw.gte(bnToBn(test));
|
||||
}
|
||||
|
||||
mul (other: UInt | BN | number): BN {
|
||||
return other instanceof UInt
|
||||
? this.raw.mul(other.raw)
|
||||
: this.raw.mul(bnToBn(other));
|
||||
}
|
||||
|
||||
sub (other: UInt | BN | number): BN {
|
||||
return other instanceof UInt
|
||||
? this.raw.sub(other.raw)
|
||||
: this.raw.sub(bnToBn(other));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ 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 Proposal } from './Proposal';
|
||||
export { default as ProposalIndex } from './ProposalIndex';
|
||||
export { default as RawAddress } from './RawAddress';
|
||||
export { default as ReferendumIndex } from './ReferendumIndex';
|
||||
|
||||
Reference in New Issue
Block a user