Add Types from RPC (and more tests) (#165)
* Tests for Array for proper coverage * Expand tests * Add PropIndex :( * Add RawAddress * Index -> Nonce * Disable test for alias code (commented) * Block & Extrinsic (base) * String -> Text, Array -> Vector * Remove Codec* prefixes * Unsigned -> Long * import renames * Values for structures * Export classes from Metadata * Long -> UInt * Alias vec<u8> -> Bytes
This commit is contained in:
@@ -9,16 +9,16 @@ import isHex from '@polkadot/util/is/hex';
|
||||
import isU8a from '@polkadot/util/is/u8a';
|
||||
import u8aToU8a from '@polkadot/util/u8a/toU8a';
|
||||
|
||||
import CodecU8a from './codec/U8a';
|
||||
import CodecU8aFixed from './codec/U8aFixed';
|
||||
import U8a from './codec/U8a';
|
||||
import U8aFixed from './codec/U8aFixed';
|
||||
|
||||
// A wrapper around an AccountId/PublicKey representation. Since we are dealing with
|
||||
// underlying PublicKeys (32 bytes in length), we extend from CodecU8aFixed which is
|
||||
// underlying PublicKeys (32 bytes in length), we extend from U8aFixed which is
|
||||
// basically just a Uint8Array wrapper with a fixed length.
|
||||
export default class AccountId extends CodecU8aFixed {
|
||||
constructor (value: CodecU8a | string | Uint8Array = new Uint8Array()) {
|
||||
export default class AccountId extends U8aFixed {
|
||||
constructor (value: U8a | string | Uint8Array = new Uint8Array()) {
|
||||
super(
|
||||
value instanceof CodecU8a
|
||||
value instanceof U8a
|
||||
? value.raw
|
||||
: AccountId.decode(value),
|
||||
256
|
||||
|
||||
@@ -2,21 +2,18 @@
|
||||
// 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 isU8a from '@polkadot/util/is/u8a';
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
import u8aToU8a from '@polkadot/util/u8a/toU8a';
|
||||
|
||||
import CodecU8a from './codec/U8a';
|
||||
import U8a from './codec/U8a';
|
||||
|
||||
// A wrapper around an AccountIndex, which is a shortened, variable-length encoding
|
||||
// for an Account. We extends from CodecU8a which is basically
|
||||
// for an Account. We extends from U8a which is basically
|
||||
// just a Uint8Array wrapper.
|
||||
export default class AccountIndex extends CodecU8a {
|
||||
constructor (value: CodecU8a | string | Uint8Array = new Uint8Array()) {
|
||||
export default class AccountIndex extends U8a {
|
||||
constructor (value: U8a | string | Uint8Array = new Uint8Array()) {
|
||||
super(
|
||||
value instanceof CodecU8a
|
||||
value instanceof U8a
|
||||
? value.raw
|
||||
: AccountIndex.decode(value)
|
||||
);
|
||||
@@ -29,13 +26,7 @@ export default class AccountIndex extends CodecU8a {
|
||||
}
|
||||
|
||||
static decode (value: string | Uint8Array | Array<number>): Uint8Array {
|
||||
if (isU8a(value) || Array.isArray(value)) {
|
||||
return u8aToU8a(value);
|
||||
} else if (isHex(value)) {
|
||||
return hexToU8a(value);
|
||||
}
|
||||
|
||||
throw new Error(`Unable to decode AccountIndex for [${value.toString()}]`);
|
||||
return u8aToU8a(value);
|
||||
}
|
||||
|
||||
fromJSON (input: any): AccountIndex {
|
||||
|
||||
@@ -7,7 +7,7 @@ import isU8a from '@polkadot/util/is/u8a';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
import u8aToU8a from '@polkadot/util/u8a/toU8a';
|
||||
|
||||
import CodecBase from './codec/Base';
|
||||
import Base from './codec/Base';
|
||||
import AccountId from './AccountId';
|
||||
import AccountIndex from './AccountIndex';
|
||||
|
||||
@@ -16,7 +16,7 @@ import AccountIndex from './AccountIndex';
|
||||
// we extend from Base with an AccountId/AccountIndex wrapper. Basically the Address
|
||||
// is encoded as
|
||||
// [ <prefix-byte>, ...publicKey/...bytes ]
|
||||
export default class Address extends CodecBase<AccountId | AccountIndex> {
|
||||
export default class Address extends Base<AccountId | AccountIndex> {
|
||||
constructor (value: Address | AccountId | AccountIndex | string | Uint8Array = new Uint8Array()) {
|
||||
super(
|
||||
value instanceof Address
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// 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 hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
|
||||
import Block from './Block';
|
||||
|
||||
describe('Block', () => {
|
||||
it('decodes a block properly', () => {
|
||||
const block = new Block();
|
||||
|
||||
block.fromU8a(hexToU8a(
|
||||
'0x' +
|
||||
// parent_hash
|
||||
'0900000000000000000000000000000000000000000000000000000000000009' +
|
||||
// number
|
||||
'4300000000000000' +
|
||||
// state_root
|
||||
'0800000000000000000000000000000000000000000000000000000000000008' +
|
||||
// transaction_root
|
||||
'0700000000000000000000000000000000000000000000000000000000000007' +
|
||||
// digest
|
||||
'08' + // 2 << 2
|
||||
'0401' +
|
||||
'0402' +
|
||||
// transactions
|
||||
'04' + // 1 << 2
|
||||
// 111 bytes in compact encoding
|
||||
'bd01' +
|
||||
// prefix
|
||||
'ff' +
|
||||
'0000000000000000000000000000000000000000000000000000000000000000' +
|
||||
'00000000' +
|
||||
'0300' +
|
||||
'7527000000000000' +
|
||||
'0000000000000000000000000000000000000000000000000000000000000000' +
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
));
|
||||
|
||||
expect(
|
||||
block.header.blockNumber.toNumber()
|
||||
).toEqual(67);
|
||||
expect(
|
||||
block.extrinsics.length
|
||||
).toEqual(1); // eslint-disable-line
|
||||
expect(
|
||||
block.extrinsics.at(0).length
|
||||
).toEqual(111); // eslint-disable-line
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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 Struct from './codec/Struct';
|
||||
import Vector from './codec/Vector';
|
||||
|
||||
import Extrinsic from './Extrinsic';
|
||||
import Header from './Header';
|
||||
|
||||
// A block encoded with header and extrinsics
|
||||
export default class Block extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
header: Header,
|
||||
extrinsics: Vector.with(Extrinsic)
|
||||
}, value);
|
||||
}
|
||||
|
||||
get extrinsics (): Vector<Extrinsic> {
|
||||
return this.raw.extrinsics as Vector<Extrinsic>;
|
||||
}
|
||||
|
||||
get header (): Header {
|
||||
return this.raw.header as Header;
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import CodecBase from './codec/Base';
|
||||
import Base from './codec/Base';
|
||||
|
||||
export default class Bool extends CodecBase<boolean> {
|
||||
export default class Bool extends Base<boolean> {
|
||||
constructor (value: Bool | boolean = false) {
|
||||
super(
|
||||
value instanceof Bool
|
||||
|
||||
@@ -4,31 +4,30 @@
|
||||
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
import CodecU8a from './U8a';
|
||||
import Length from './Length';
|
||||
import Length from './codec/Length';
|
||||
import U8a from './codec/U8a';
|
||||
|
||||
// A CodecBytes. The significant difference between this and a normal Uint8Array is that
|
||||
// A Bytes. The significant difference between this and a normal Uint8Array is that
|
||||
// this version allows for length-encoding. (i.e. it is a variable-item codec, the same
|
||||
// as what is found in String and Array)
|
||||
export default class CodecBytes extends CodecU8a {
|
||||
export default class Bytes extends U8a {
|
||||
protected _length: Length;
|
||||
|
||||
constructor (value: CodecU8a | Uint8Array = new Uint8Array()) {
|
||||
super(
|
||||
value instanceof CodecU8a
|
||||
? value.raw
|
||||
: value
|
||||
);
|
||||
constructor (value?: U8a | string | Uint8Array) {
|
||||
super(value);
|
||||
|
||||
this._length = new Length(value.length);
|
||||
this._length = new Length(this.raw.length);
|
||||
}
|
||||
|
||||
get length (): number {
|
||||
return this._length.toNumber();
|
||||
}
|
||||
|
||||
byteLength (): number {
|
||||
return this._length.byteLength() +
|
||||
this._length.toNumber();
|
||||
return this._length.byteLength() + this.length;
|
||||
}
|
||||
|
||||
fromJSON (input: any): CodecBytes {
|
||||
fromJSON (input: any): Bytes {
|
||||
super.fromJSON(input);
|
||||
|
||||
this._length.setValue(this.raw.length);
|
||||
@@ -36,7 +35,7 @@ export default class CodecBytes extends CodecU8a {
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecBytes {
|
||||
fromU8a (input: Uint8Array): Bytes {
|
||||
this._length.fromU8a(input);
|
||||
|
||||
const length = this._length.toNumber();
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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 blake2Asu8a from '@polkadot/util-crypto/blake2/asU8a';
|
||||
|
||||
import Bytes from './Bytes';
|
||||
import Hash from './Hash';
|
||||
|
||||
// Representation of an Extrinsic in the system.
|
||||
//
|
||||
// NOTE At this point we are just keeping to a bare-bones Vec<u8> structure,
|
||||
// this should be expanded to do the automatic decoding of an extrinsic
|
||||
export default class Extrinsic extends Bytes {
|
||||
// convernience, encodes the extrinsic and returns the actual hash
|
||||
get hash (): Hash {
|
||||
return new Hash(
|
||||
blake2Asu8a(this.toU8a(), 256)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,13 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import CodecU8a from './codec/U8a';
|
||||
import CodecU8aFixed from './codec/U8aFixed';
|
||||
import U8a from './codec/U8a';
|
||||
import U8aFixed from './codec/U8aFixed';
|
||||
|
||||
// Hash containing 256 bits (32 bytes), typically used in blocks, extrinsics and
|
||||
// as a sane default for fixed-length hash representations.
|
||||
export default class H256 extends CodecU8aFixed {
|
||||
constructor (value?: CodecU8a | Uint8Array) {
|
||||
export default class H256 extends U8aFixed {
|
||||
constructor (value?: U8a | string | Uint8Array) {
|
||||
super(value, 256);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import CodecU8a from './codec/U8a';
|
||||
import CodecU8aFixed from './codec/U8aFixed';
|
||||
import U8a from './codec/U8a';
|
||||
import U8aFixed from './codec/U8aFixed';
|
||||
|
||||
// Hash containing 512 bits (64 bytes), typically used for signatures
|
||||
export default class H512 extends CodecU8aFixed {
|
||||
constructor (value?: CodecU8a | Uint8Array) {
|
||||
export default class H512 extends U8aFixed {
|
||||
constructor (value?: U8a | string | Uint8Array) {
|
||||
super(value, 512);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,29 +2,45 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import CodecArray from './codec/Array';
|
||||
import CodecBytes from './codec/Bytes';
|
||||
import CodecStruct from './codec/Struct';
|
||||
import BN from 'bn.js';
|
||||
import blake2Asu8a from '@polkadot/util-crypto/blake2/asU8a';
|
||||
|
||||
import UInt from './codec/UInt';
|
||||
import Struct from './codec/Struct';
|
||||
import Vector from './codec/Vector';
|
||||
|
||||
import BlockNumber from './BlockNumber';
|
||||
import Bytes from './Bytes';
|
||||
import Hash from './Hash';
|
||||
|
||||
type DigestStruct = {
|
||||
logs?: Array<Uint8Array | string>
|
||||
};
|
||||
|
||||
type HeaderStruct = {
|
||||
digest?: DigestStruct,
|
||||
extrinsicsRoot?: Hash | Uint8Array | string,
|
||||
number?: UInt | BN | number | string,
|
||||
parentHash?: Hash | Uint8Array | string,
|
||||
stateRoot?: Hash | Uint8Array | string
|
||||
};
|
||||
|
||||
// A block header digest.
|
||||
export class Digest extends CodecStruct {
|
||||
constructor (value?: any) {
|
||||
export class Digest extends Struct {
|
||||
constructor (value: DigestStruct = {}) {
|
||||
super({
|
||||
logs: CodecArray.with(CodecBytes)
|
||||
logs: Vector.with(Bytes)
|
||||
}, value);
|
||||
}
|
||||
|
||||
get logs (): CodecArray<CodecBytes> {
|
||||
return this.raw.logs as CodecArray<CodecBytes>;
|
||||
get logs (): Vector<Bytes> {
|
||||
return this.raw.logs as Vector<Bytes>;
|
||||
}
|
||||
}
|
||||
|
||||
// A block header.
|
||||
export default class Header extends CodecStruct {
|
||||
constructor (value?: any) {
|
||||
export default class Header extends Struct {
|
||||
constructor (value: HeaderStruct = {}) {
|
||||
super({
|
||||
parentHash: Hash,
|
||||
number: BlockNumber,
|
||||
@@ -46,6 +62,13 @@ export default class Header extends CodecStruct {
|
||||
return this.raw.extrinsicsRoot as Hash;
|
||||
}
|
||||
|
||||
// convernience, encodes the header and returns the actual hash
|
||||
get hash (): Hash {
|
||||
return new Hash(
|
||||
blake2Asu8a(this.toU8a(), 256)
|
||||
);
|
||||
}
|
||||
|
||||
get parentHash (): Hash {
|
||||
return this.raw.parentHash as Hash;
|
||||
}
|
||||
|
||||
@@ -2,31 +2,32 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import CodecBytes from './codec/Bytes';
|
||||
import CodecStruct from './codec/Struct';
|
||||
import Struct from './codec/Struct';
|
||||
|
||||
import Bytes from './Bytes';
|
||||
|
||||
type KeyValueStruct = {
|
||||
key: Uint8Array,
|
||||
value: Uint8Array
|
||||
key?: Uint8Array | string,
|
||||
value?: Uint8Array | string
|
||||
};
|
||||
|
||||
// KeyValue structure. Since most of the keys and resultant values in Subtrate is
|
||||
// hashed and/or encoded, this does not wrap a CodecString, but rather a CodecBytes
|
||||
// hashed and/or encoded, this does not wrap a Text, but rather a Bytes
|
||||
// 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 CodecStruct {
|
||||
constructor (value: KeyValueStruct = {} as KeyValueStruct) {
|
||||
export default class KeyValue extends Struct {
|
||||
constructor (value: KeyValueStruct = {}) {
|
||||
super({
|
||||
key: CodecBytes,
|
||||
value: CodecBytes
|
||||
key: Bytes,
|
||||
value: Bytes
|
||||
}, value);
|
||||
}
|
||||
|
||||
get key (): CodecBytes {
|
||||
return this.raw.key as CodecBytes;
|
||||
get key (): Bytes {
|
||||
return this.raw.key as Bytes;
|
||||
}
|
||||
|
||||
get value (): CodecBytes {
|
||||
return this.raw.value as CodecBytes;
|
||||
get value (): Bytes {
|
||||
return this.raw.value as Bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import CodecArray from './codec/Array';
|
||||
import CodecBase from './codec/Base';
|
||||
import CodecEnum from './codec/Enum';
|
||||
import CodecEnumType from './codec/EnumType';
|
||||
import CodecOption from './codec/Option';
|
||||
import CodecStruct from './codec/Struct';
|
||||
import String from './String';
|
||||
import Vector from './codec/Vector';
|
||||
import Base from './codec/Base';
|
||||
import Enum from './codec/Enum';
|
||||
import EnumType from './codec/EnumType';
|
||||
import Option from './codec/Option';
|
||||
import Struct from './codec/Struct';
|
||||
import Text from './Text';
|
||||
import Type from './Type';
|
||||
import U16 from './U16';
|
||||
|
||||
@@ -16,72 +16,72 @@ import U16 from './U16';
|
||||
// file is probably best understood from the bottom-up, i.e. start reading right at the
|
||||
// end and work up. (Just so we don't use before definition)
|
||||
|
||||
class EventMetadata extends CodecStruct {
|
||||
export class EventMetadata extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
name: String,
|
||||
arguments: CodecArray.with(Type),
|
||||
documentation: CodecArray.with(String)
|
||||
name: Text,
|
||||
arguments: Vector.with(Type),
|
||||
documentation: Vector.with(Text)
|
||||
});
|
||||
}
|
||||
|
||||
get arguments (): CodecArray<Type> {
|
||||
return this.raw.arguments as CodecArray<Type>;
|
||||
get arguments (): Vector<Type> {
|
||||
return this.raw.arguments as Vector<Type>;
|
||||
}
|
||||
|
||||
get documentation (): CodecArray<String> {
|
||||
return this.raw.documentation as CodecArray<String>;
|
||||
get documentation (): Vector<Text> {
|
||||
return this.raw.documentation as Vector<Text>;
|
||||
}
|
||||
|
||||
get name (): String {
|
||||
return this.raw.name as String;
|
||||
get name (): Text {
|
||||
return this.raw.name as Text;
|
||||
}
|
||||
}
|
||||
|
||||
class OuterEventMetadataEvent extends CodecStruct {
|
||||
export class OuterEventMetadataEvent extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
name: String,
|
||||
events: CodecArray.with(EventMetadata)
|
||||
name: Text,
|
||||
events: Vector.with(EventMetadata)
|
||||
});
|
||||
}
|
||||
|
||||
get events (): CodecArray<EventMetadata> {
|
||||
return this.raw.events as CodecArray<EventMetadata>;
|
||||
get events (): Vector<EventMetadata> {
|
||||
return this.raw.events as Vector<EventMetadata>;
|
||||
}
|
||||
|
||||
get name (): String {
|
||||
return this.raw.name as String;
|
||||
get name (): Text {
|
||||
return this.raw.name as Text;
|
||||
}
|
||||
}
|
||||
|
||||
class OuterEventMetadata extends CodecStruct {
|
||||
export class OuterEventMetadata extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
name: String,
|
||||
events: CodecArray.with(OuterEventMetadataEvent)
|
||||
name: Text,
|
||||
events: Vector.with(OuterEventMetadataEvent)
|
||||
});
|
||||
}
|
||||
|
||||
get events (): CodecArray<OuterEventMetadataEvent> {
|
||||
return this.raw.events as CodecArray<OuterEventMetadataEvent>;
|
||||
get events (): Vector<OuterEventMetadataEvent> {
|
||||
return this.raw.events as Vector<OuterEventMetadataEvent>;
|
||||
}
|
||||
|
||||
get name (): String {
|
||||
return this.raw.name as String;
|
||||
get name (): Text {
|
||||
return this.raw.name as Text;
|
||||
}
|
||||
}
|
||||
|
||||
class FunctionArgumentMetadata extends CodecStruct {
|
||||
export class FunctionArgumentMetadata extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
name: String,
|
||||
name: Text,
|
||||
type: Type
|
||||
});
|
||||
}
|
||||
|
||||
get name (): String {
|
||||
return this.raw.name as String;
|
||||
get name (): Text {
|
||||
return this.raw.name as Text;
|
||||
}
|
||||
|
||||
get type (): Type {
|
||||
@@ -89,54 +89,54 @@ class FunctionArgumentMetadata extends CodecStruct {
|
||||
}
|
||||
}
|
||||
|
||||
class FunctionMetadata extends CodecStruct {
|
||||
export class FunctionMetadata extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
id: U16,
|
||||
name: String,
|
||||
arguments: CodecArray.with(FunctionArgumentMetadata),
|
||||
documentation: CodecArray.with(String)
|
||||
name: Text,
|
||||
arguments: Vector.with(FunctionArgumentMetadata),
|
||||
documentation: Vector.with(Text)
|
||||
});
|
||||
}
|
||||
|
||||
get arguments (): CodecArray<FunctionArgumentMetadata> {
|
||||
return this.raw.arguments as CodecArray<FunctionArgumentMetadata>;
|
||||
get arguments (): Vector<FunctionArgumentMetadata> {
|
||||
return this.raw.arguments as Vector<FunctionArgumentMetadata>;
|
||||
}
|
||||
|
||||
get documentation (): CodecArray<String> {
|
||||
return this.raw.documentation as CodecArray<String>;
|
||||
get documentation (): Vector<Text> {
|
||||
return this.raw.documentation as Vector<Text>;
|
||||
}
|
||||
|
||||
get id (): U16 {
|
||||
return this.raw.id as U16;
|
||||
}
|
||||
|
||||
get name (): String {
|
||||
return this.raw.name as String;
|
||||
get name (): Text {
|
||||
return this.raw.name as Text;
|
||||
}
|
||||
}
|
||||
|
||||
class CallMetadata extends CodecStruct {
|
||||
export class CallMetadata extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
name: String,
|
||||
functions: CodecArray.with(FunctionMetadata)
|
||||
name: Text,
|
||||
functions: Vector.with(FunctionMetadata)
|
||||
});
|
||||
}
|
||||
|
||||
get functions (): CodecArray<FunctionMetadata> {
|
||||
return this.raw.functions as CodecArray<FunctionMetadata>;
|
||||
get functions (): Vector<FunctionMetadata> {
|
||||
return this.raw.functions as Vector<FunctionMetadata>;
|
||||
}
|
||||
|
||||
get name (): String {
|
||||
return this.raw.name as String;
|
||||
get name (): Text {
|
||||
return this.raw.name as Text;
|
||||
}
|
||||
}
|
||||
|
||||
class ModuleMetadata extends CodecStruct {
|
||||
export class ModuleMetadata extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
name: String,
|
||||
name: Text,
|
||||
call: CallMetadata
|
||||
});
|
||||
}
|
||||
@@ -145,18 +145,18 @@ class ModuleMetadata extends CodecStruct {
|
||||
return this.raw.call as CallMetadata;
|
||||
}
|
||||
|
||||
get name (): String {
|
||||
return this.raw.name as String;
|
||||
get name (): Text {
|
||||
return this.raw.name as Text;
|
||||
}
|
||||
}
|
||||
|
||||
class StorageFunctionModifier extends CodecEnum {
|
||||
export class StorageFunctionModifier extends Enum {
|
||||
constructor () {
|
||||
super(['None', 'Default', 'Required']);
|
||||
}
|
||||
}
|
||||
|
||||
class StorageFunctionType$Map extends CodecStruct {
|
||||
export class StorageFunctionType$Map extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
key: Type,
|
||||
@@ -173,7 +173,7 @@ class StorageFunctionType$Map extends CodecStruct {
|
||||
}
|
||||
}
|
||||
|
||||
class StorageFunctionType extends CodecEnumType<Type | StorageFunctionType$Map> {
|
||||
export class StorageFunctionType extends EnumType<Type | StorageFunctionType$Map> {
|
||||
constructor () {
|
||||
super([
|
||||
Type,
|
||||
@@ -186,30 +186,30 @@ class StorageFunctionType extends CodecEnumType<Type | StorageFunctionType$Map>
|
||||
}
|
||||
|
||||
get asMap (): StorageFunctionType$Map {
|
||||
return (this.raw as CodecBase<StorageFunctionType$Map>).raw;
|
||||
return (this.raw as Base<StorageFunctionType$Map>).raw;
|
||||
}
|
||||
|
||||
get asType (): Type {
|
||||
return (this.raw as CodecBase<Type>).raw;
|
||||
return (this.raw as Base<Type>).raw;
|
||||
}
|
||||
}
|
||||
|
||||
class StorageFunctionMetadata extends CodecStruct {
|
||||
export class StorageFunctionMetadata extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
name: String,
|
||||
name: Text,
|
||||
modifier: StorageFunctionModifier,
|
||||
type: StorageFunctionType,
|
||||
documentation: CodecArray.with(String)
|
||||
documentation: Vector.with(Text)
|
||||
});
|
||||
}
|
||||
|
||||
get documentation (): CodecArray<String> {
|
||||
return this.raw.documentation as CodecArray<String>;
|
||||
get documentation (): Vector<Text> {
|
||||
return this.raw.documentation as Vector<Text>;
|
||||
}
|
||||
|
||||
get name (): String {
|
||||
return this.raw.name as String;
|
||||
get name (): Text {
|
||||
return this.raw.name as Text;
|
||||
}
|
||||
|
||||
get modifier (): StorageFunctionModifier {
|
||||
@@ -221,29 +221,29 @@ class StorageFunctionMetadata extends CodecStruct {
|
||||
}
|
||||
}
|
||||
|
||||
class StorageMetadata extends CodecStruct {
|
||||
export class StorageMetadata extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
prefix: String,
|
||||
functions: CodecArray.with(StorageFunctionMetadata)
|
||||
prefix: Text,
|
||||
functions: Vector.with(StorageFunctionMetadata)
|
||||
});
|
||||
}
|
||||
|
||||
get functions (): CodecArray<StorageFunctionMetadata> {
|
||||
return this.raw.functions as CodecArray<StorageFunctionMetadata>;
|
||||
get functions (): Vector<StorageFunctionMetadata> {
|
||||
return this.raw.functions as Vector<StorageFunctionMetadata>;
|
||||
}
|
||||
|
||||
get prefix (): String {
|
||||
return this.raw.prefix as String;
|
||||
get prefix (): Text {
|
||||
return this.raw.prefix as Text;
|
||||
}
|
||||
}
|
||||
|
||||
class RuntimeModuleMetadata extends CodecStruct {
|
||||
export class RuntimeModuleMetadata extends Struct {
|
||||
constructor () {
|
||||
super({
|
||||
prefix: String,
|
||||
prefix: Text,
|
||||
module: ModuleMetadata,
|
||||
storage: CodecOption.with(StorageMetadata)
|
||||
storage: Option.with(StorageMetadata)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -251,20 +251,20 @@ class RuntimeModuleMetadata extends CodecStruct {
|
||||
return this.raw.module as ModuleMetadata;
|
||||
}
|
||||
|
||||
get prefix (): String {
|
||||
return this.raw.prefix as String;
|
||||
get prefix (): Text {
|
||||
return this.raw.prefix as Text;
|
||||
}
|
||||
|
||||
get storage (): StorageMetadata | undefined {
|
||||
return (this.raw.storage as CodecOption<StorageMetadata>).value;
|
||||
return (this.raw.storage as Option<StorageMetadata>).value;
|
||||
}
|
||||
}
|
||||
|
||||
export default class RuntimeMetadata extends CodecStruct {
|
||||
export default class RuntimeMetadata extends Struct {
|
||||
constructor (value?: any) {
|
||||
super({
|
||||
outerEvent: OuterEventMetadata,
|
||||
modules: CodecArray.with(RuntimeModuleMetadata)
|
||||
modules: Vector.with(RuntimeModuleMetadata)
|
||||
}, value);
|
||||
}
|
||||
|
||||
@@ -281,16 +281,16 @@ export default class RuntimeMetadata extends CodecStruct {
|
||||
}
|
||||
|
||||
// FIXME Really not crazy about having to manually add all the getters. Preferably it should
|
||||
// be done automagically in the actual CodecStruct - however what is really important here
|
||||
// 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.
|
||||
|
||||
get events (): CodecArray<OuterEventMetadataEvent> {
|
||||
get events (): Vector<OuterEventMetadataEvent> {
|
||||
return (this.raw.outerEvent as OuterEventMetadata).events;
|
||||
}
|
||||
|
||||
get modules (): CodecArray<RuntimeModuleMetadata> {
|
||||
return this.raw.modules as CodecArray<RuntimeModuleMetadata>;
|
||||
get modules (): Vector<RuntimeModuleMetadata> {
|
||||
return this.raw.modules as Vector<RuntimeModuleMetadata>;
|
||||
}
|
||||
|
||||
// Helper to retrieve a list of all type that are found, sorted and de-deuplicated
|
||||
|
||||
@@ -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 U32 from './U32';
|
||||
|
||||
// An increasing number that represents a specific proposal in the system
|
||||
export default class PropIndex extends U32 {
|
||||
}
|
||||
@@ -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 Address from './Address';
|
||||
|
||||
// Wrapper for a RawAddress.
|
||||
// NOTE Not 100% on the differences between this and Address in the runtime
|
||||
export default class RawAddress extends Address {
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import u8aFromUtf8 from '@polkadot/util/u8a/fromUtf8';
|
||||
import u8aToUtf8 from '@polkadot/util/u8a/toUtf8';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
import CodecBase from './codec/Base';
|
||||
import Base from './codec/Base';
|
||||
import Length from './codec/Length';
|
||||
|
||||
// This is a string wrapper, along with the length. It is used both for strings as well
|
||||
@@ -17,14 +17,14 @@ import Length from './codec/Length';
|
||||
// - Potentially we want a "TypeString" extension to this. Basically something that
|
||||
// wraps the `Balance`, `T::AccountId`, etc. The reasoning - with a "TypeString"
|
||||
// we can nicely strip types down like "T::AcountId" -> "AccountId"
|
||||
export default class String extends CodecBase<string> {
|
||||
export default class Text extends Base<string> {
|
||||
protected _length: Length;
|
||||
|
||||
constructor (value: String | string = '') {
|
||||
constructor (value: Text | string = '') {
|
||||
super(
|
||||
value instanceof String
|
||||
value instanceof Text
|
||||
? value.raw
|
||||
: value
|
||||
: value.trim()
|
||||
);
|
||||
|
||||
this._length = new Length(value.length);
|
||||
@@ -41,13 +41,13 @@ export default class String extends CodecBase<string> {
|
||||
this._length.byteLength();
|
||||
}
|
||||
|
||||
fromJSON (input: any): String {
|
||||
fromJSON (input: any): Text {
|
||||
this.raw = `${input}`;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): String {
|
||||
fromU8a (input: Uint8Array): Text {
|
||||
this._length.fromU8a(input);
|
||||
|
||||
const length = this._length.toNumber();
|
||||
@@ -2,6 +2,7 @@
|
||||
// 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 Type from './Type';
|
||||
|
||||
describe('Type', () => {
|
||||
@@ -19,8 +20,8 @@ describe('Type', () => {
|
||||
|
||||
it('handles aliasses, multiples per line', () => {
|
||||
expect(
|
||||
new Type().fromJSON('(PropIndex, AccountId, PropIndex)').toString()
|
||||
).toEqual('(ProposalIndex, AccountId, ProposalIndex)');
|
||||
new Type().fromJSON('(Vec<u8>, AccountId, Vec<u8>)').toString()
|
||||
).toEqual('(Bytes, AccountId, Bytes)');
|
||||
});
|
||||
|
||||
it('does not allow toU8a', () => {
|
||||
@@ -28,4 +29,12 @@ describe('Type', () => {
|
||||
() => new Type().toU8a()
|
||||
).toThrow(/unimplemented/);
|
||||
});
|
||||
|
||||
it('has a length for the type', () => {
|
||||
expect(
|
||||
new Type(
|
||||
new Text(' Box<Proposal> ')
|
||||
).length
|
||||
).toEqual('Proposal'.length); // eslint-disable-line
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,14 +2,20 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import String from './String';
|
||||
import Text from './Text';
|
||||
|
||||
type Mapper = (value: string) => string;
|
||||
|
||||
// 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.
|
||||
export default class Type extends String {
|
||||
export default class Type extends Text {
|
||||
constructor (value?: Text | string) {
|
||||
super(value);
|
||||
|
||||
this._cleanupTypes();
|
||||
}
|
||||
|
||||
fromJSON (input: any): Type {
|
||||
super.fromJSON(input);
|
||||
|
||||
@@ -39,9 +45,9 @@ export default class Type extends String {
|
||||
// remove generics, `MisbehaviorReport<Hash, BlockNumber>` -> `MisbehaviorReport`
|
||||
this._ungeneric(),
|
||||
// convert `RawAddress` -> `Address`
|
||||
this._unalias('RawAddress', 'Address'),
|
||||
// convert `PropIndex` -> `ProposalIndex`
|
||||
this._unalias('PropIndex', 'ProposalIndex')
|
||||
// alias Vec<u8> -> Bytes
|
||||
this._unalias('Vec<u8>', 'Bytes')
|
||||
];
|
||||
|
||||
this.raw = mappings.reduce((result, fn) => {
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import CodecNumber from './codec/Number';
|
||||
import UInt from './codec/UInt';
|
||||
|
||||
export default class U128 extends CodecNumber {
|
||||
constructor (value?: CodecNumber | BN | string | number) {
|
||||
export default class U128 extends UInt {
|
||||
constructor (value?: UInt | BN | string | number) {
|
||||
super(value, 128);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import CodecNumber from './codec/Number';
|
||||
import UInt from './codec/UInt';
|
||||
|
||||
export default class U16 extends CodecNumber {
|
||||
constructor (value?: CodecNumber | BN | string | number) {
|
||||
export default class U16 extends UInt {
|
||||
constructor (value?: UInt | BN | string | number) {
|
||||
super(value, 16);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import CodecNumber from './codec/Number';
|
||||
import UInt from './codec/UInt';
|
||||
|
||||
export default class U256 extends CodecNumber {
|
||||
constructor (value?: CodecNumber | BN | string | number) {
|
||||
export default class U256 extends UInt {
|
||||
constructor (value?: UInt | BN | string | number) {
|
||||
super(value, 256);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import CodecNumber from './codec/Number';
|
||||
import UInt from './codec/UInt';
|
||||
|
||||
export default class U32 extends CodecNumber {
|
||||
constructor (value?: CodecNumber | BN | string | number) {
|
||||
export default class U32 extends UInt {
|
||||
constructor (value?: UInt | BN | string | number) {
|
||||
super(value, 32);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import CodecNumber from './codec/Number';
|
||||
import UInt from './codec/UInt';
|
||||
|
||||
export default class U64 extends CodecNumber {
|
||||
constructor (value?: CodecNumber | BN | string | number) {
|
||||
export default class U64 extends UInt {
|
||||
constructor (value?: UInt | BN | string | number) {
|
||||
super(value, 64);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import CodecNumber from './codec/Number';
|
||||
import UInt from './codec/UInt';
|
||||
|
||||
export default class U8 extends CodecNumber {
|
||||
constructor (value?: CodecNumber | BN | string | number) {
|
||||
export default class U8 extends UInt {
|
||||
constructor (value?: UInt | BN | string | number) {
|
||||
super(value, 8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// TODO
|
||||
// - This could probably be abstract, as long as we have the functions abstract as well
|
||||
export default class CodecBase <T = any> {
|
||||
export default class Base <T = any> {
|
||||
raw: T;
|
||||
|
||||
constructor (value?: any) {
|
||||
@@ -16,26 +16,26 @@ export default class CodecBase <T = any> {
|
||||
}
|
||||
|
||||
byteLength (): number {
|
||||
throw new Error('CodecBase::byteLength: unimplemented');
|
||||
throw new Error('Base::byteLength: unimplemented');
|
||||
}
|
||||
|
||||
fromJSON (input: any): CodecBase <T> {
|
||||
throw new Error('CodecBase::fromJSON: unimplemented');
|
||||
fromJSON (input: any): Base <T> {
|
||||
throw new Error('Base::fromJSON: unimplemented');
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecBase <T> {
|
||||
throw new Error('CodecBase::fromU8a: unimplemented');
|
||||
fromU8a (input: Uint8Array): Base <T> {
|
||||
throw new Error('Base::fromU8a: unimplemented');
|
||||
}
|
||||
|
||||
toJSON (): any {
|
||||
throw new Error('CodecBase::toJSON: unimplemented');
|
||||
throw new Error('Base::toJSON: unimplemented');
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
throw new Error('CodecBase::toString: unimplemented');
|
||||
throw new Error('Base::toString: unimplemented');
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
throw new Error('CodecBase::toU8a: unimplemented');
|
||||
throw new Error('Base::toU8a: unimplemented');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 CodecBase from './Base';
|
||||
import Base from './Base';
|
||||
|
||||
// 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
|
||||
@@ -11,7 +11,7 @@ import CodecBase from './Base';
|
||||
//
|
||||
// TODO:
|
||||
// - It would be great if this could actually wrap actual TS enums
|
||||
export default class CodecEnum extends CodecBase<number> {
|
||||
export default class Enum extends Base<number> {
|
||||
private _strings: Array<string>;
|
||||
|
||||
constructor (strings: Array<string>, value: number = 0) {
|
||||
@@ -24,13 +24,13 @@ export default class CodecEnum extends CodecBase<number> {
|
||||
return 1;
|
||||
}
|
||||
|
||||
fromJSON (input: any): CodecEnum {
|
||||
fromJSON (input: any): Enum {
|
||||
this.raw = input;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecEnum {
|
||||
fromU8a (input: Uint8Array): Enum {
|
||||
this.raw = input[0];
|
||||
|
||||
return this;
|
||||
|
||||
@@ -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 CodecBase from './Base';
|
||||
import Base from './Base';
|
||||
|
||||
// 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.
|
||||
@@ -11,12 +11,12 @@ import CodecBase from './Base';
|
||||
// - As per Enum, actually use TS enum
|
||||
// - 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 CodecEnumType <T> extends CodecBase<CodecBase<T>> {
|
||||
private _Type: Array<{ new(value?: any): CodecBase }>;
|
||||
export default class EnumType <T> extends Base<Base<T>> {
|
||||
private _Type: Array<{ new(value?: any): Base }>;
|
||||
private _index: number;
|
||||
private _strings: Array<string>;
|
||||
|
||||
constructor (Type: Array<{ new(value?: any): CodecBase }>, strings: Array<string>, index: number = 0) {
|
||||
constructor (Type: Array<{ new(value?: any): Base }>, strings: Array<string>, index: number = 0) {
|
||||
super(
|
||||
new Type[index]()
|
||||
);
|
||||
@@ -30,11 +30,11 @@ export default class CodecEnumType <T> extends CodecBase<CodecBase<T>> {
|
||||
return 1 + this.raw.byteLength();
|
||||
}
|
||||
|
||||
fromJSON (input: any): CodecEnumType<T> {
|
||||
throw new Error('CodecEnumType:fromJSON: unimplemented');
|
||||
fromJSON (input: any): EnumType<T> {
|
||||
throw new Error('EnumType:fromJSON: unimplemented');
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecEnumType<T> {
|
||||
fromU8a (input: Uint8Array): EnumType<T> {
|
||||
this._index = input[0];
|
||||
this.raw = new this._Type[this._index]().fromU8a(input.subarray(1));
|
||||
|
||||
@@ -46,7 +46,7 @@ export default class CodecEnumType <T> extends CodecBase<CodecBase<T>> {
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
throw new Error('CodecEnumType:toU8a: unimplemented');
|
||||
throw new Error('EnumType:toU8a: unimplemented');
|
||||
}
|
||||
|
||||
toNumber (): number {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import Length from './Length';
|
||||
|
||||
describe('Compact', () => {
|
||||
describe('Length', () => {
|
||||
it('encodes short u8', () => {
|
||||
expect(
|
||||
new Length(18).toU8a()
|
||||
@@ -29,14 +29,18 @@ describe('Compact', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('encodes basic ua6 (not at edge)', () => {
|
||||
expect(
|
||||
new Length(111).toHex()
|
||||
).toEqual('0xbd01');
|
||||
});
|
||||
|
||||
it('decodes from same u16 encoded value', () => {
|
||||
expect(
|
||||
new Length()
|
||||
.fromU8a(new Uint8Array([0b11111101, 0b00000111]))
|
||||
.toNumber()
|
||||
).toEqual(
|
||||
511
|
||||
);
|
||||
).toEqual(511);
|
||||
});
|
||||
|
||||
it('encodes basic u32 values (short)', () => {
|
||||
@@ -52,9 +56,7 @@ describe('Compact', () => {
|
||||
new Length()
|
||||
.fromU8a(new Uint8Array([254, 255, 3, 0]))
|
||||
.toNumber()
|
||||
).toEqual(
|
||||
0xffff
|
||||
);
|
||||
).toEqual(0xffff);
|
||||
});
|
||||
|
||||
it('encodes basic u32 values (full)', () => {
|
||||
@@ -70,8 +72,6 @@ describe('Compact', () => {
|
||||
new Length()
|
||||
.fromU8a(new Uint8Array([3, 249, 255, 255, 255]))
|
||||
.toNumber()
|
||||
).toEqual(
|
||||
0xfffffff9
|
||||
);
|
||||
).toEqual(0xfffffff9);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,8 +7,9 @@ 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 CodecBase from './Base';
|
||||
import Base from './Base';
|
||||
|
||||
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);
|
||||
@@ -29,10 +30,10 @@ const MAX_U32 = new BN(2).pow(new BN(32 - 2)).subn(1);
|
||||
// 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 CodecLength extends CodecBase<BN> {
|
||||
constructor (value: CodecLength | BN | number = new BN(0)) {
|
||||
export default class Length extends Base<BN> {
|
||||
constructor (value: Length | BN | number = new BN(0)) {
|
||||
super(
|
||||
value instanceof CodecLength
|
||||
value instanceof Length
|
||||
? value.raw
|
||||
: bnToBn(value)
|
||||
);
|
||||
@@ -69,32 +70,32 @@ export default class CodecLength extends CodecBase<BN> {
|
||||
);
|
||||
}
|
||||
|
||||
get length (): number {
|
||||
return this.raw.toNumber();
|
||||
}
|
||||
|
||||
byteLength (): number {
|
||||
return this.toU8a().length;
|
||||
}
|
||||
|
||||
fromJSON (): CodecLength {
|
||||
throw new Error('CodecLength::fromJSON: unimplemented');
|
||||
fromJSON (): Length {
|
||||
throw new Error('Length::fromJSON: unimplemented');
|
||||
}
|
||||
|
||||
fromNumber (value: BN | number): CodecLength {
|
||||
fromNumber (value: BN | number): Length {
|
||||
this.raw = bnToBn(value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecLength {
|
||||
this.raw = CodecLength.decode(input);
|
||||
fromU8a (input: Uint8Array): Length {
|
||||
this.raw = Length.decode(input);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
toJSON (): any {
|
||||
throw new Error('CodecLength::toJSON: unimplemented');
|
||||
throw new Error('Length::toJSON: unimplemented');
|
||||
}
|
||||
|
||||
toHex (): string {
|
||||
return u8aToHex(this.toU8a());
|
||||
}
|
||||
|
||||
toNumber (): number {
|
||||
@@ -102,11 +103,11 @@ export default class CodecLength extends CodecBase<BN> {
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
throw new Error('CodecLength::toString: unimplemented');
|
||||
throw new Error('Length::toString: unimplemented');
|
||||
}
|
||||
|
||||
toU8a (): Uint8Array {
|
||||
return CodecLength.encode(this.raw);
|
||||
return Length.encode(this.raw);
|
||||
}
|
||||
|
||||
setValue (value: BN | number): void {
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
|
||||
import isUndefined from '@polkadot/util/is/undefined';
|
||||
|
||||
import CodecBase from './Base';
|
||||
import Base from './Base';
|
||||
|
||||
// An Option is an optional field. Basically the first byte indicates that there is
|
||||
// is value to follow. If the byte is `1` there is an actual value. So the CodecOption
|
||||
// is value to follow. If the byte is `1` there is an actual value. So the Option
|
||||
// implements that - decodes, checks for optionality and wraps the required structure
|
||||
// with a value if/as required/found.
|
||||
export default class CodecOption <T> extends CodecBase<CodecBase<T>> {
|
||||
export default class Option <T> extends Base<Base<T>> {
|
||||
private _hasValue: boolean;
|
||||
|
||||
constructor (Value: { new(value?: any): CodecBase<T> }, value?: any) {
|
||||
constructor (Value: { new(value?: any): Base<T> }, value?: any) {
|
||||
super(
|
||||
new Value(value)
|
||||
);
|
||||
@@ -21,8 +21,8 @@ export default class CodecOption <T> extends CodecBase<CodecBase<T>> {
|
||||
this._hasValue = !isUndefined(value);
|
||||
}
|
||||
|
||||
static with <O> (Type: { new(value?: any): CodecBase<O> }): { new(value?: any): CodecOption<O> } {
|
||||
return class extends CodecOption<O> {
|
||||
static with <O> (Type: { new(value?: any): Base<O> }): { new(value?: any): Option<O> } {
|
||||
return class extends Option<O> {
|
||||
constructor (value?: any) {
|
||||
super(Type, value);
|
||||
}
|
||||
@@ -43,7 +43,7 @@ export default class CodecOption <T> extends CodecBase<CodecBase<T>> {
|
||||
return 1 + childLength;
|
||||
}
|
||||
|
||||
fromJSON (input: any): CodecOption<T> {
|
||||
fromJSON (input: any): Option<T> {
|
||||
this._hasValue = !isUndefined(input);
|
||||
|
||||
if (this._hasValue) {
|
||||
@@ -53,7 +53,7 @@ export default class CodecOption <T> extends CodecBase<CodecBase<T>> {
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecOption<T> {
|
||||
fromU8a (input: Uint8Array): Option<T> {
|
||||
this._hasValue = input[0] === 1;
|
||||
|
||||
if (this._hasValue) {
|
||||
|
||||
@@ -4,29 +4,29 @@
|
||||
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
import CodecBase from './Base';
|
||||
import Base from './Base';
|
||||
|
||||
// A Struct defines an Object with key/values - where the values are CodecCodecBase values. It removes
|
||||
// a lot of repetition from the actual coding, define a structure type, pass it the key/CodecBase<T>
|
||||
// A Struct defines an Object with key/values - where the values are CodecBase values. It removes
|
||||
// a lot of repetition from the actual coding, define a structure type, pass it the key/Base<T>
|
||||
// values in the constructor and it manages the decoding. It is important that the constructor
|
||||
// values matches 100% to the order in th Rust code, i.e. don't go crazy and make it alphabetical,
|
||||
// it needs to decoded in the specific defined order.
|
||||
//
|
||||
// TODO:
|
||||
// - Check the constructor, something is really, really wrong with the way the defs are used
|
||||
export default class CodecStruct <
|
||||
S = { [index: string]: { new(value?: any): CodecBase } },
|
||||
T = { [K in keyof S]: CodecBase },
|
||||
export default class Struct <
|
||||
S = { [index: string]: { new(value?: any): Base } },
|
||||
T = { [K in keyof S]: Base },
|
||||
V = { [K in keyof S]: any }
|
||||
> extends CodecBase<T> {
|
||||
constructor (Struct: S, value: V = {} as V) {
|
||||
> extends Base<T> {
|
||||
constructor (Def: S, value: V = {} as V) {
|
||||
super(
|
||||
Object.keys(Struct).reduce((raw: T, key) => {
|
||||
Object.keys(Def).reduce((raw: T, key) => {
|
||||
// @ts-ignore Ok, something weid 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 Struct[key](value[key]);
|
||||
raw[key] = new Def[key](value[key]);
|
||||
|
||||
return raw;
|
||||
}, {} as T)
|
||||
@@ -34,11 +34,11 @@ export default class CodecStruct <
|
||||
}
|
||||
|
||||
static with <
|
||||
S = { [index: string]: { new(value?: any): CodecBase } }
|
||||
> (Struct: S): { new(value?: any): CodecStruct<S> } {
|
||||
return class extends CodecStruct<S> {
|
||||
S = { [index: string]: { new(value?: any): Base } }
|
||||
> (Def: S): { new(value?: any): Struct<S> } {
|
||||
return class extends Struct<S> {
|
||||
constructor (value?: any) {
|
||||
super(Struct, value);
|
||||
super(Def, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -49,7 +49,7 @@ export default class CodecStruct <
|
||||
}, 0);
|
||||
}
|
||||
|
||||
fromJSON (input: any): CodecStruct<S, T, V> {
|
||||
fromJSON (input: any): Struct<S, T, V> {
|
||||
Object.keys(this.raw).forEach((key) => {
|
||||
// @ts-ignore as above...
|
||||
this.raw[key].fromJSON(input[key]);
|
||||
@@ -58,7 +58,7 @@ export default class CodecStruct <
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecStruct<S, T, V> {
|
||||
fromU8a (input: Uint8Array): Struct<S, T, V> {
|
||||
Object.keys(this.raw).reduce((offset, key) => {
|
||||
// @ts-ignore as above...
|
||||
this.raw[key].fromU8a(input.subarray(offset));
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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 U8a from './U8a';
|
||||
|
||||
describe('U8a', () => {
|
||||
let u8a;
|
||||
|
||||
beforeEach(() => {
|
||||
u8a = new U8a([1, 2, 3, 4, 5]);
|
||||
});
|
||||
|
||||
it('contains the length of the elements', () => {
|
||||
expect(u8a.length).toEqual(5); // eslint-disable-line
|
||||
});
|
||||
|
||||
it('allows wrapping of a pre-existing instance', () => {
|
||||
expect(
|
||||
new U8a(u8a).length
|
||||
).toEqual(5); // eslint-disable-line
|
||||
});
|
||||
});
|
||||
@@ -5,16 +5,16 @@
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
import toU8a from '@polkadot/util/u8a/toU8a';
|
||||
|
||||
import CodecBase from './Base';
|
||||
import Base from './Base';
|
||||
|
||||
// A CodecU8a. A basic wrapper around Uint8Array, with no frills and no fuss. It
|
||||
// A U8a. A basic wrapper around Uint8Array, with no frills and no fuss. It
|
||||
// wraps a Uint8Array. It does differ from other implementations wher it will
|
||||
// consume the full u8a as passed to it in fromU8a. As such it is meant to be
|
||||
// subclassed where the wrapper takes care of the actual lengths.
|
||||
export default class CodecU8a extends CodecBase<Uint8Array> {
|
||||
constructor (value: CodecU8a | string | Uint8Array = new Uint8Array()) {
|
||||
export default class U8a extends Base<Uint8Array> {
|
||||
constructor (value: U8a | string | Uint8Array | Array<number> = new Uint8Array()) {
|
||||
super(
|
||||
value instanceof CodecU8a
|
||||
value instanceof U8a
|
||||
? value.raw
|
||||
: toU8a(value)
|
||||
);
|
||||
@@ -28,13 +28,13 @@ export default class CodecU8a extends CodecBase<Uint8Array> {
|
||||
return this.raw.length;
|
||||
}
|
||||
|
||||
fromJSON (input: any): CodecU8a {
|
||||
fromJSON (input: any): U8a {
|
||||
this.raw = toU8a(input);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecU8a {
|
||||
fromU8a (input: Uint8Array): U8a {
|
||||
this.raw = input;
|
||||
|
||||
return this;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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 U8aFixed from './U8aFixed';
|
||||
|
||||
describe('U8aFixed', () => {
|
||||
let u8a;
|
||||
|
||||
beforeEach(() => {
|
||||
u8a = new U8aFixed([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 32);
|
||||
});
|
||||
|
||||
it('limits the length', () => {
|
||||
expect(u8a.length).toEqual(4); // eslint-disable-line
|
||||
});
|
||||
|
||||
it('allows wrapping of a pre-existing instance', () => {
|
||||
expect(
|
||||
u8a.toU8a()
|
||||
).toEqual(new Uint8Array([1, 2, 3, 4]));
|
||||
});
|
||||
|
||||
it('allows empty values', () => {
|
||||
expect(
|
||||
new U8aFixed().toHex()
|
||||
).toEqual('0x');
|
||||
});
|
||||
});
|
||||
@@ -2,26 +2,40 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import CodecU8a from './U8a';
|
||||
import U8a from './U8a';
|
||||
|
||||
type BitLength = 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.
|
||||
export default class CodecU8aFixed extends CodecU8a {
|
||||
export default class U8aFixed extends U8a {
|
||||
protected _bitLength: number;
|
||||
|
||||
constructor (value: CodecU8a | string | Uint8Array = new Uint8Array(), bitLength: BitLength = 256) {
|
||||
constructor (value: U8a | string | Uint8Array = new Uint8Array(), bitLength: BitLength = 256) {
|
||||
super(value);
|
||||
|
||||
this._bitLength = bitLength;
|
||||
|
||||
this._trimLength();
|
||||
}
|
||||
|
||||
private _trimLength (): void {
|
||||
this.raw = this.raw.subarray(0, this.byteLength());
|
||||
}
|
||||
|
||||
byteLength (): number {
|
||||
return this._bitLength / 8;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecU8aFixed {
|
||||
fromJSON (input: any): U8aFixed {
|
||||
super.fromJSON(input);
|
||||
|
||||
this._trimLength();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): U8aFixed {
|
||||
super.fromU8a(input.subarray(0, this.byteLength()));
|
||||
|
||||
return this;
|
||||
|
||||
@@ -11,7 +11,7 @@ import bnToU8a from '@polkadot/util/bn/toU8a';
|
||||
import hexToBn from '@polkadot/util/hex/toBn';
|
||||
import u8aToBn from '@polkadot/util/u8a/toBn';
|
||||
|
||||
import CodecBase from './Base';
|
||||
import Base from './Base';
|
||||
|
||||
type BitLength = 8 | 16 | 32 | 64 | 128 | 256;
|
||||
|
||||
@@ -21,19 +21,19 @@ type BitLength = 8 | 16 | 32 | 64 | 128 | 256;
|
||||
//
|
||||
// TODO:
|
||||
// - Apart from encoding/decoding we don't actuall keep check on the sizes, is this good enough?
|
||||
export default class CodecNumber extends CodecBase<BN> {
|
||||
export default class UInt extends Base<BN> {
|
||||
private _bitLength: BitLength;
|
||||
|
||||
constructor (value: CodecNumber | BN | string | number = 0, bitLength: BitLength = 64) {
|
||||
constructor (value: UInt | BN | string | number = 0, bitLength: BitLength = 64) {
|
||||
super(
|
||||
CodecNumber.decode(value)
|
||||
UInt.decode(value)
|
||||
);
|
||||
|
||||
this._bitLength = bitLength;
|
||||
}
|
||||
|
||||
static decode (value: CodecNumber | BN | string | number): BN {
|
||||
if (value instanceof CodecNumber) {
|
||||
static decode (value: UInt | BN | string | number): BN {
|
||||
if (value instanceof UInt) {
|
||||
return value.raw;
|
||||
} else if (isHex(value)) {
|
||||
return hexToBn(value as string);
|
||||
@@ -48,13 +48,13 @@ export default class CodecNumber extends CodecBase<BN> {
|
||||
return this._bitLength / 8;
|
||||
}
|
||||
|
||||
fromJSON (input: any): CodecNumber {
|
||||
this.raw = CodecNumber.decode(input);
|
||||
fromJSON (input: any): UInt {
|
||||
this.raw = UInt.decode(input);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecNumber {
|
||||
fromU8a (input: Uint8Array): UInt {
|
||||
this.raw = u8aToBn(input.subarray(0, this.byteLength()), true);
|
||||
|
||||
return this;
|
||||
@@ -0,0 +1,81 @@
|
||||
// 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 Vector from './Vector';
|
||||
|
||||
describe('Vector', () => {
|
||||
let array;
|
||||
|
||||
beforeEach(() => {
|
||||
array = new Vector(Text, [ '1', '23', '345', '4567', new Text('56789') ]);
|
||||
});
|
||||
|
||||
it('wraps a sequence of values', () => {
|
||||
expect(array.length).toEqual(5); // eslint-disable-line
|
||||
});
|
||||
|
||||
it('has a sane representation for toString', () => {
|
||||
expect(array.toString()).toEqual('[1, 23, 345, 4567, 56789]');
|
||||
});
|
||||
|
||||
it('encodes with length prefix', () => {
|
||||
expect(array.toU8a()).toEqual(new Uint8Array([
|
||||
5 << 2,
|
||||
1 << 2, 49,
|
||||
2 << 2, 50, 51,
|
||||
3 << 2, 51, 52, 53,
|
||||
4 << 2, 52, 53, 54, 55,
|
||||
5 << 2, 53, 54, 55, 56, 57
|
||||
]));
|
||||
});
|
||||
|
||||
it('allows contruction via JSON', () => {
|
||||
expect(
|
||||
new Vector(Text).fromJSON(['6', '7']).toString()
|
||||
).toEqual('[6, 7]');
|
||||
});
|
||||
|
||||
describe('array-like functions', () => {
|
||||
it('allows retrieval of a specific item', () => {
|
||||
expect(
|
||||
array.at(2).toString()
|
||||
).toEqual('345');
|
||||
});
|
||||
|
||||
it('exposes a working forEach', () => {
|
||||
const result = {};
|
||||
|
||||
array.forEach((e, i) => {
|
||||
result[i] = e.toString();
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
0: '1',
|
||||
1: '23',
|
||||
2: '345',
|
||||
3: '4567',
|
||||
4: '56789'
|
||||
});
|
||||
});
|
||||
|
||||
it('exposes a working filter', () => {
|
||||
expect(
|
||||
array.filter((e, i) => i >= 3).toString()
|
||||
).toEqual('4567,56789');
|
||||
});
|
||||
|
||||
it('exposes a working map', () => {
|
||||
expect(
|
||||
array.map((e) => e.toString().substr(0, 1))
|
||||
).toEqual(['1', '2', '3', '4', '5']);
|
||||
});
|
||||
|
||||
it('exposes a working reduce', () => {
|
||||
expect(
|
||||
array.reduce((r, e) => `${r}${e}`, '')
|
||||
).toEqual('123345456756789');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
import CodecBase from './Base';
|
||||
import Base from './Base';
|
||||
import Length from './Length';
|
||||
|
||||
// This manages codec arrays. Intrernally it keeps track of the length (as decoded) and allows
|
||||
@@ -12,16 +12,18 @@ import Length from './Length';
|
||||
// i.e. while it wraps an array, it provides a `length` property to get the actual length, `at(index)`
|
||||
// to retrieve a specific item. Additionally the helper functions `map`, `filter`, `forEach` and
|
||||
// `reduce` is exposed on the interface.
|
||||
export default class CodecArray <
|
||||
T extends CodecBase
|
||||
> extends CodecBase<Array<T>> {
|
||||
export default class Vector <
|
||||
T extends Base
|
||||
> extends Base<Array<T>> {
|
||||
private _length: Length;
|
||||
private _Type: { new(value?: any): T };
|
||||
|
||||
constructor (Type: { new(value?: any): T }, value: Array<any> = [] as Array<any>) {
|
||||
super(
|
||||
value.map((entry) =>
|
||||
new Type(entry)
|
||||
entry instanceof Type
|
||||
? entry
|
||||
: new Type(entry)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -29,8 +31,8 @@ export default class CodecArray <
|
||||
this._Type = Type;
|
||||
}
|
||||
|
||||
static with <O extends CodecBase> (Type: { new(value?: any): O }): { new(value?: any): CodecArray<O> } {
|
||||
return class extends CodecArray<O> {
|
||||
static with <O extends Base> (Type: { new(value?: any): O }): { new(value?: any): Vector<O> } {
|
||||
return class extends Vector<O> {
|
||||
constructor (value?: Array<any>) {
|
||||
super(Type, value);
|
||||
}
|
||||
@@ -59,7 +61,7 @@ export default class CodecArray <
|
||||
return this.raw.forEach(fn);
|
||||
}
|
||||
|
||||
fromJSON (input: any): CodecArray<T> {
|
||||
fromJSON (input: any): Vector<T> {
|
||||
this.raw = input.map((input: any) =>
|
||||
new this._Type().fromJSON(input)
|
||||
);
|
||||
@@ -67,7 +69,7 @@ export default class CodecArray <
|
||||
return this;
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): CodecArray<T> {
|
||||
fromU8a (input: Uint8Array): Vector<T> {
|
||||
this._length.fromU8a(input);
|
||||
|
||||
const length = this._length.toNumber();
|
||||
@@ -110,8 +112,8 @@ export default class CodecArray <
|
||||
toString (): string {
|
||||
const data = this.raw.map((entry) =>
|
||||
entry.toString()
|
||||
).join(', ');
|
||||
);
|
||||
|
||||
return `[${data}]`;
|
||||
return `[${data.join(', ')}]`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user