Pass registry to all codec types (#1592)

* Pass registry to all codec types

* Pass through registry inside API (where the rubber meets the road)

* Small additions

* Derive w/ registry

* Types are more-or-less covered

* Some test adjustments (guided by linting)

* Rid the world of some ../injector

* Additional cleanups, merge injector into registry

* Cleanup extrinsics (always passing registry)

* Remove injector imports (not all replaced)

* Typ spec cleanups

* Phase 1 - types seem lint-free

* rpc-{core,provider} lint free

* Start working through metadata

* Small metadata additions

* Some e2e tests (out-of-order)

* Down to a handful

* Fixup tests for packages/types/src/codec/*.spec.ts

* packages/types/src/codec passes all tests

* packages/types ok (Convert storage with registry fn)

* progress (sort out injection, dreaded find-before msg)

* Down to 1 lint issue...

* Linting done... along with on-demand import

* Exposed ordering

* Remove global injects

* Cleanup comments

* Add CHANGELOG & UPGRADING

* Apply suggestions from code review

Co-Authored-By: Amaury Martiny <amaury.martiny@protonmail.com>

* Update Metadata description
This commit is contained in:
Jaco Greeff
2019-11-21 16:32:39 +01:00
committed by GitHub
co-authored by Amaury Martiny
parent 099992627b
commit 011e24bd49
269 changed files with 2495 additions and 2126 deletions
+10 -2
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyJson, AnyJsonArray, Codec, IHash } from '../types';
import { AnyJson, AnyJsonArray, Codec, IHash, Registry } from '../types';
import { u8aConcat, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -19,6 +19,14 @@ import { compareArray } from './utils';
* @noInheritDoc
*/
export default abstract class AbstractArray<T extends Codec> extends Array<T> implements Codec {
public readonly registry: Registry;
protected constructor (registry: Registry, ...values: T[]) {
super(...values);
this.registry = registry;
}
/**
* @description The length of the value when encoded as a Uint8Array
*/
@@ -32,7 +40,7 @@ export default abstract class AbstractArray<T extends Codec> extends Array<T> im
* @description returns a hash of the contents
*/
public get hash (): IHash {
return new U8a(blake2AsU8a(this.toU8a(), 256));
return new U8a(this.registry, blake2AsU8a(this.toU8a(), 256));
}
/**
+7 -9
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyNumber, Codec, IHash } from '../types';
import { AnyNumber, Codec, IHash, Registry } from '../types';
import BN from 'bn.js';
import { bnToBn, hexToBn, isHex, isString, isU8a, u8aToBn } from '@polkadot/util';
@@ -22,20 +22,18 @@ export const DEFAULT_UINT_BITS = 64;
// TODO:
// - Apart from encoding/decoding we don't actually keep check on the sizes, is this good enough?
export default abstract class AbstractInt extends BN implements Codec {
public readonly registry: Registry;
protected _bitLength: UIntBitLength;
private _isHexJson: boolean;
private _isNegative: boolean;
constructor (
isNegative: boolean,
value: AnyNumber = 0,
bitLength: UIntBitLength = DEFAULT_UINT_BITS, isHexJson = true) {
super(
AbstractInt.decodeAbstracInt(value, bitLength, isNegative)
);
protected constructor (registry: Registry, isNegative: boolean, value: AnyNumber = 0, bitLength: UIntBitLength = DEFAULT_UINT_BITS, isHexJson = true) {
super(AbstractInt.decodeAbstracInt(value, bitLength, isNegative));
this.registry = registry;
this._bitLength = bitLength;
this._isHexJson = isHexJson;
this._isNegative = isNegative;
@@ -80,7 +78,7 @@ export default abstract class AbstractInt extends BN implements Codec {
* @description returns a hash of the contents
*/
public get hash (): IHash {
return new U8a(blake2AsU8a(this.toU8a(), 256));
return new U8a(this.registry, blake2AsU8a(this.toU8a(), 256));
}
/**
+18 -17
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../injector';
import { TypeRegistry } from '../codec';
import Text from '../primitive/Text';
import U32 from '../primitive/U32';
import Struct from './Struct';
@@ -10,18 +10,19 @@ import { CodecTo } from '../types';
import BTreeMap from './BTreeMap';
const registry = new TypeRegistry();
const mockU32TextMap = new Map<Text, U32>();
mockU32TextMap.set(new Text('bazzing'), new U32(69));
mockU32TextMap.set(new Text(registry, 'bazzing'), new U32(registry, 69));
const mockU32TextMapString = '{"bazzing":69}';
const mockU32TextMapObject = { bazzing: 69 };
const mockU32TextMapHexString = '0x041c62617a7a696e6745000000';
const mockU32TextMapUint8Array = Uint8Array.from([4, 28, 98, 97, 122, 122, 105, 110, 103, 69, 0, 0, 0]);
const mockU32U32Map = new Map<U32, U32>();
mockU32U32Map.set(new U32(1), new U32(2));
mockU32U32Map.set(new U32(23), new U32(24));
mockU32U32Map.set(new U32(28), new U32(30));
mockU32U32Map.set(new U32(45), new U32(80));
mockU32U32Map.set(new U32(registry, 1), new U32(registry, 2));
mockU32U32Map.set(new U32(registry, 23), new U32(registry, 24));
mockU32U32Map.set(new U32(registry, 28), new U32(registry, 30));
mockU32U32Map.set(new U32(registry, 45), new U32(registry, 80));
const mockU32U32MapString = '{"1":2,"23":24,"28":30,"45":80}';
const mockU32U32MapObject = { 1: 2, 23: 24, 28: 30, 45: 80 };
const mockU32U32MapHexString = '0x10043102000000083233180000000832381e00000008343550000000';
@@ -31,7 +32,7 @@ describe('BTreeMap', (): void => {
describe('decoding', (): void => {
const testDecode = (type: string, input: any, output: string): void =>
it(`can decode from ${type}`, (): void => {
const s = new BTreeMap(Text, U32, input);
const s = new BTreeMap(registry, Text, U32, input);
expect(s.toString()).toBe(output);
});
@@ -48,7 +49,7 @@ describe('BTreeMap', (): void => {
describe('encoding', (): void => {
const testEncode = (to: CodecTo, expected: any): void =>
it(`can encode ${to}`, (): void => {
const s = new BTreeMap(Text, U32, mockU32TextMap);
const s = new BTreeMap(registry, Text, U32, mockU32TextMap);
expect(s[to]()).toEqual(expected);
});
@@ -61,7 +62,7 @@ describe('BTreeMap', (): void => {
describe('encoding muple values', (): void => {
const testEncode = (to: CodecTo, expected: any): void =>
it(`can encode ${to}`, (): void => {
const s = new BTreeMap(Text, U32, mockU32U32Map);
const s = new BTreeMap(registry, Text, U32, mockU32U32Map);
expect(s[to]()).toEqual(expected);
});
@@ -75,16 +76,16 @@ describe('BTreeMap', (): void => {
expect(
new (
BTreeMap.with(Text, U32)
)(null).toString()
)(registry, null).toString()
).toEqual('{}');
});
it('decodes within more complicated types', (): void => {
const s = new Struct({
const s = new Struct(registry, {
placeholder: U32,
value: BTreeMap.with(Text, U32)
});
s.set('value', new BTreeMap(Text, U32, mockU32TextMap));
s.set('value', new BTreeMap(registry, Text, U32, mockU32TextMap));
expect(s.toString()).toBe('{"placeholder":0,"value":{"bazzing":69}}');
});
@@ -92,21 +93,21 @@ describe('BTreeMap', (): void => {
expect(
(): BTreeMap<Text, U32> => new (
BTreeMap.with(Text, U32)
)('ABC')
)(registry, 'ABC')
).toThrowError(/BTreeMap: cannot decode type/);
});
it('correctly encodes length', (): void => {
expect(
new (
BTreeMap.with(Text, U32))(mockU32TextMap).encodedLength
BTreeMap.with(Text, U32))(registry, mockU32TextMap).encodedLength
).toEqual(13);
});
it('generates sane toRawTypes', (): void => {
expect(new (BTreeMap.with(Text, U32))().toRawType()).toBe('BTreeMap<Text,u32>');
expect(new (BTreeMap.with(Text, Text))().toRawType()).toBe('BTreeMap<Text,Text>');
expect(new (BTreeMap.with(Text, Struct.with({ a: U32, b: Text })))().toRawType())
expect(new (BTreeMap.with(Text, U32))(registry).toRawType()).toBe('BTreeMap<Text,u32>');
expect(new (BTreeMap.with(Text, Text))(registry).toRawType()).toBe('BTreeMap<Text,Text>');
expect(new (BTreeMap.with(Text, Struct.with({ a: U32, b: Text })))(registry).toRawType())
.toBe('BTreeMap<Text,{"a":"u32","b":"Text"}>');
});
});
+21 -18
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyJson, Constructor, Codec, IHash, InterfaceTypes } from '../types';
import { AnyJson, Constructor, Codec, IHash, InterfaceTypes, Registry } from '../types';
import { isHex, hexToU8a, isU8a, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -12,16 +12,19 @@ import U8a from './U8a';
import { compareMap, decodeU8a, typeToConstructor } from './utils';
export default class BTreeMap<K extends Codec = Codec, V extends Codec = Codec> extends Map<K, V> implements Codec {
public readonly registry: Registry;
protected _KeyClass: Constructor<K>;
protected _ValClass: Constructor<V>;
constructor (keyType: Constructor<K> | InterfaceTypes, valType: Constructor<V> | InterfaceTypes, rawValue: any) {
const KeyClass = typeToConstructor(keyType);
const ValClass = typeToConstructor(valType);
constructor (registry: Registry, keyType: Constructor<K> | InterfaceTypes, valType: Constructor<V> | InterfaceTypes, rawValue: any) {
const KeyClass = typeToConstructor(registry, keyType);
const ValClass = typeToConstructor(registry, valType);
super(BTreeMap.decodeBTreeMap(KeyClass, ValClass, rawValue));
super(BTreeMap.decodeBTreeMap(registry, KeyClass, ValClass, rawValue));
this.registry = registry;
this._KeyClass = KeyClass;
this._ValClass = ValClass;
}
@@ -40,21 +43,21 @@ export default class BTreeMap<K extends Codec = Codec, V extends Codec = Codec>
* constructors or decodeable values for their types.
* @param jsonMap
*/
private static decodeBTreeMap<K extends Codec = Codec, V extends Codec = Codec> (KeyClass: Constructor<K>, ValClass: Constructor<V>, value: Uint8Array | string | Map<any, any>): Map<K, V> {
private static decodeBTreeMap<K extends Codec = Codec, V extends Codec = Codec> (registry: Registry, KeyClass: Constructor<K>, ValClass: Constructor<V>, value: Uint8Array | string | Map<any, any>): Map<K, V> {
if (!value) {
return new Map<K, V>();
} else if (isHex(value)) {
return BTreeMap.decodeBTreeMap(KeyClass, ValClass, hexToU8a(value));
return BTreeMap.decodeBTreeMap(registry, KeyClass, ValClass, hexToU8a(value));
} else if (isU8a(value)) {
return BTreeMap.decodeBTreeMapFromU8a<K, V>(KeyClass, ValClass, u8aToU8a(value));
return BTreeMap.decodeBTreeMapFromU8a<K, V>(registry, KeyClass, ValClass, u8aToU8a(value));
} else if (value instanceof Map) {
return BTreeMap.decodeBTreeMapFromMap<K, V>(KeyClass, ValClass, value);
return BTreeMap.decodeBTreeMapFromMap<K, V>(registry, KeyClass, ValClass, value);
}
throw new Error('BTreeMap: cannot decode type');
}
private static decodeBTreeMapFromU8a<K extends Codec = Codec, V extends Codec = Codec> (KeyClass: Constructor<K>, ValClass: Constructor<V>, u8a: Uint8Array): Map<K, V> {
private static decodeBTreeMapFromU8a<K extends Codec = Codec, V extends Codec = Codec> (registry: Registry, KeyClass: Constructor<K>, ValClass: Constructor<V>, u8a: Uint8Array): Map<K, V> {
const output = new Map<K, V>();
const [offset, length] = Compact.decodeU8a(u8a);
const types = [];
@@ -63,7 +66,7 @@ export default class BTreeMap<K extends Codec = Codec, V extends Codec = Codec>
types.push(KeyClass, ValClass);
}
const values = decodeU8a(u8a.subarray(offset), types);
const values = decodeU8a(registry, u8a.subarray(offset), types);
for (let i = 0; i < values.length; i += 2) {
output.set(values[i] as K, values[i + 1] as V);
@@ -72,14 +75,14 @@ export default class BTreeMap<K extends Codec = Codec, V extends Codec = Codec>
return output;
}
private static decodeBTreeMapFromMap<K extends Codec = Codec, V extends Codec = Codec> (KeyClass: Constructor<K>, ValClass: Constructor<V>, value: Map<any, any>): Map<K, V> {
private static decodeBTreeMapFromMap<K extends Codec = Codec, V extends Codec = Codec> (registry: Registry, KeyClass: Constructor<K>, ValClass: Constructor<V>, value: Map<any, any>): Map<K, V> {
const output = new Map<K, V>();
value.forEach((v: any, k: any) => {
let key, val;
try {
key = (k instanceof KeyClass) ? k : new KeyClass(k);
val = (v instanceof ValClass) ? v : new ValClass(v);
key = (k instanceof KeyClass) ? k : new KeyClass(registry, k);
val = (v instanceof ValClass) ? v : new ValClass(registry, v);
} catch (error) {
console.error('Failed to decode BTreeMap key or value:', error.message);
throw error;
@@ -93,8 +96,8 @@ export default class BTreeMap<K extends Codec = Codec, V extends Codec = Codec>
public static with<K extends Codec, V extends Codec> (keyType: Constructor<K> | InterfaceTypes, valType: Constructor<V> | InterfaceTypes): Constructor<BTreeMap<K, V>> {
return class extends BTreeMap<K, V> {
constructor (value?: any) {
super(keyType, valType, value);
constructor (registry: Registry, value?: any) {
super(registry, keyType, valType, value);
}
};
}
@@ -116,7 +119,7 @@ export default class BTreeMap<K extends Codec = Codec, V extends Codec = Codec>
* @description Returns a hash of the value
*/
public get hash (): IHash {
return new U8a(blake2AsU8a(this.toU8a(), 256));
return new U8a(this.registry, blake2AsU8a(this.toU8a(), 256));
}
/**
@@ -157,7 +160,7 @@ export default class BTreeMap<K extends Codec = Codec, V extends Codec = Codec>
* @description Returns the base runtime type name for this instance
*/
public toRawType (): string {
return `BTreeMap<${new this._KeyClass().toRawType()},${new this._ValClass().toRawType()}>`;
return `BTreeMap<${new this._KeyClass(this.registry).toRawType()},${new this._ValClass(this.registry).toRawType()}>`;
}
/**
+6 -3
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyJson, Codec, IHash } from '../types';
import { AnyJson, Codec, IHash, Registry } from '../types';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -13,9 +13,12 @@ import U8a from './U8a';
* @description A type extends the Base class, when it holds a value
*/
export default abstract class Base<T extends Codec> implements Codec {
public readonly registry: Registry;
protected raw: T;
constructor (value?: any) {
protected constructor (registry: Registry, value?: any) {
this.registry = registry;
this.raw = value;
}
@@ -30,7 +33,7 @@ export default abstract class Base<T extends Codec> implements Codec {
* @description returns a hash of the contents
*/
public get hash (): IHash {
return new U8a(blake2AsU8a(this.toU8a(), 256));
return new U8a(this.registry, blake2AsU8a(this.toU8a(), 256));
}
/**
+14 -14
View File
@@ -2,17 +2,17 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../injector';
import BN from 'bn.js';
import { createType, ClassOf } from './create';
import { createType, ClassOf, TypeRegistry } from './create';
import Moment from './Date';
import U32 from '../primitive/U32';
import Compact from './Compact';
import UInt from './UInt';
describe('Compact', (): void => {
const registry = new TypeRegistry();
describe('encodeU8a', (): void => {
it('encodes short u8', (): void => {
expect(
@@ -24,7 +24,7 @@ describe('Compact', (): void => {
it('encodes max u8 values', (): void => {
expect(
Compact.encodeU8a(new UInt(63))
Compact.encodeU8a(new (UInt.with())(registry, 63))
).toEqual(
new Uint8Array([0b11111100])
);
@@ -64,7 +64,7 @@ describe('Compact', (): void => {
it('encondes a large balance', (): void => {
expect(
Compact.encodeU8a(createType('Balance', '0x5af3107a4000'))
Compact.encodeU8a(createType(registry, 'Balance', '0x5af3107a4000'))
).toEqual(
new Uint8Array([
3 + ((6 - 4) << 2),
@@ -109,52 +109,52 @@ describe('Compact', (): void => {
describe('constructor', (): void => {
it('has the correct bitLength for constructor values (BlockNumber)', (): void => {
expect(
new Compact(ClassOf('BlockNumber'), 0xfffffff9).bitLength()
new (Compact.with(ClassOf(registry, 'BlockNumber')))(registry, 0xfffffff9).bitLength()
).toEqual(32);
});
it('has the correct encodedLength for constructor values (string BlockNumber)', (): void => {
expect(
new Compact('BlockNumber', 0xfffffff9).encodedLength
new (Compact.with('BlockNumber'))(registry, 0xfffffff9).encodedLength
).toEqual(5);
});
it('has the correct encodedLength for constructor values (class BlockNumber)', (): void => {
expect(
new Compact(ClassOf('BlockNumber'), 0xfffffff9).encodedLength
new (Compact.with(ClassOf(registry, 'BlockNumber')))(registry, 0xfffffff9).encodedLength
).toEqual(5);
});
it('has the correct encodedLength for constructor values (u32)', (): void => {
expect(
new Compact(U32, 0xffff9).encodedLength
new (Compact.with(U32))(registry, 0xffff9).encodedLength
).toEqual(4);
});
it('constructs properly via U8a as U32', (): void => {
expect(
new Compact(U32, new Uint8Array([254, 255, 3, 0])).toNumber()
new (Compact.with(U32))(registry, new Uint8Array([254, 255, 3, 0])).toNumber()
).toEqual(new BN(0xffff).toNumber());
});
it('constructs properly via number as Moment', (): void => {
expect(
new Compact(Moment, 1537968546).toString().startsWith('Wed Sep 26 2018') // The time depends on the timezone this test is run in
new (Compact.with(Moment))(registry, 1537968546).toString().startsWith('Wed Sep 26 2018') // The time depends on the timezone this test is run in
).toBe(true);
});
});
describe('utils', (): void => {
it('compares against another Compact', (): void => {
expect(new Compact(U32, 12345).eq(new Compact(U32, 12345))).toBe(true);
expect(new (Compact.with(U32))(registry, 12345).eq(new (Compact.with(U32))(registry, 12345))).toBe(true);
});
it('compares against a primitive', (): void => {
expect(new Compact(U32, 12345).eq(12345)).toBe(true);
expect(new (Compact.with(U32))(registry, 12345).eq(12345)).toBe(true);
});
it('unwraps to the wrapped value', (): void => {
expect(new Compact(U32, 12345).unwrap() instanceof U32).toBe(true);
expect(new (Compact.with(U32))(registry, 12345).unwrap() instanceof U32).toBe(true);
});
});
+10 -10
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyNumber, Codec, Constructor, InterfaceTypes } from '../types';
import { AnyNumber, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import BN from 'bn.js';
import { compactAddLength, compactFromU8a, compactStripLength, compactToU8a, isBn, isNumber, isString } from '@polkadot/util';
@@ -27,14 +27,14 @@ export interface CompactEncodable extends Codec {
* a number and making the compact representation thereof
*/
export default class Compact<T extends CompactEncodable> extends Base<T> {
constructor (Type: Constructor<T> | InterfaceTypes, value: Compact<T> | AnyNumber = 0) {
super(Compact.decodeCompact<T>(typeToConstructor(Type), value));
constructor (registry: Registry, Type: Constructor<T> | InterfaceTypes, value: Compact<T> | AnyNumber = 0) {
super(registry, Compact.decodeCompact<T>(registry, typeToConstructor(registry, Type), value));
}
public static with<T extends CompactEncodable> (Type: Constructor<T> | InterfaceTypes): Constructor<Compact<T>> {
return class extends Compact<T> {
constructor (value?: any) {
super(Type, value);
constructor (registry: Registry, value?: any) {
super(registry, Type, value);
}
};
}
@@ -56,16 +56,16 @@ export default class Compact<T extends CompactEncodable> extends Base<T> {
return value;
}
public static decodeCompact<T extends CompactEncodable> (Type: Constructor<T>, value: Compact<T> | AnyNumber): CompactEncodable {
public static decodeCompact<T extends CompactEncodable> (registry: Registry, Type: Constructor<T>, value: Compact<T> | AnyNumber): CompactEncodable {
if (value instanceof Compact) {
return new Type(value.raw);
return new Type(registry, value.raw);
} else if (isString(value) || isNumber(value) || isBn(value)) {
return new Type(value);
return new Type(registry, value);
}
const [, _value] = Compact.decodeU8a(value, new Type(0).bitLength());
const [, _value] = Compact.decodeU8a(value, new Type(registry, 0).bitLength());
return new Type(_value);
return new Type(registry, _value);
}
/**
+15 -11
View File
@@ -2,29 +2,33 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { CodecTo } from '../types';
import BN from 'bn.js';
import { CodecTo } from '../types';
import CodecDate from './Date';
import { TypeRegistry } from './create';
import U64 from '../primitive/U64';
import CodecDate from './Date';
describe('Date', (): void => {
const registry = new TypeRegistry();
describe('decode', (): void => {
const testDecode = (type: string, input: Date | CodecDate | U64 | number, expected: string | number, toJSON = false): void =>
it(`can decode from ${type}`, (): void => {
expect(new CodecDate(input)[toJSON ? 'toJSON' : 'toISOString']()).toBe(expected);
expect(new CodecDate(registry, input)[toJSON ? 'toJSON' : 'toISOString']()).toBe(expected);
});
testDecode('Date', new Date(1537968546280), '2018-09-26T13:29:06.280Z');
testDecode('CodecDate', new CodecDate(1234), 1234, true);
testDecode('CodecDate', new CodecDate(registry, 1234), 1234, true);
testDecode('number', 1234, 1234, true);
testDecode('U64', new U64(69), 69, true);
testDecode('U64', new U64(registry, 69), 69, true);
});
describe('encode', (): void => {
const testEncode = (to: 'toBn' | 'toISOString' | 'toNumber' | CodecTo, expected: BN | number | string | Uint8Array): void =>
it(`can encode ${to}`, (): void => {
expect(new CodecDate(421)[to]()).toEqual(expected);
expect(new CodecDate(registry, 421)[to]()).toEqual(expected);
});
testEncode('toBn', new BN(421));
@@ -36,7 +40,7 @@ describe('Date', (): void => {
it('can encode toString', (): void => {
expect(
new CodecDate(421)
new CodecDate(registry, 421)
.toString()
.startsWith('Thu Jan 01 1970') // The time depends on the timezone this test is run in
).toBe(true);
@@ -44,24 +48,24 @@ describe('Date', (): void => {
it('encodes default BE hex', (): void => {
expect(
new CodecDate(3).toHex()
new CodecDate(registry, 3).toHex()
).toEqual('0x0000000000000003');
});
it('encodes options LE hex', (): void => {
expect(
new CodecDate(3).toHex(true)
new CodecDate(registry, 3).toHex(true)
).toEqual('0x0300000000000000');
});
});
describe('utils', (): void => {
it('compares values', (): void => {
expect(new CodecDate(123).eq(123)).toBe(true);
expect(new CodecDate(registry, 123).eq(123)).toBe(true);
});
it('compares values (non-match)', (): void => {
expect(new CodecDate(123).eq(456)).toBe(false);
expect(new CodecDate(registry, 123).eq(456)).toBe(false);
});
});
});
+7 -6
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyNumber, Codec, IHash } from '../types';
import { AnyNumber, Codec, IHash, Registry } from '../types';
import BN from 'bn.js';
import { bnToBn, bnToHex, bnToU8a, isString, isU8a, u8aToBn } from '@polkadot/util';
@@ -24,13 +24,14 @@ const BITLENGTH: UIntBitLength = 64;
* @noInheritDoc
*/
export default class CodecDate extends Date implements Codec {
public readonly registry: Registry;
protected raw: Date; // FIXME Remove this once we convert all types out of Base
constructor (value: CodecDate | Date | AnyNumber = 0) {
super(
CodecDate.decodeDate(value)
);
constructor (registry: Registry, value: CodecDate | Date | AnyNumber = 0) {
super(CodecDate.decodeDate(value));
this.registry = registry;
this.raw = this;
}
@@ -59,7 +60,7 @@ export default class CodecDate extends Date implements Codec {
* @description returns a hash of the contents
*/
public get hash (): IHash {
return createType('Hash', blake2AsU8a(this.toU8a(), 256));
return createType(this.registry, 'Hash', blake2AsU8a(this.toU8a(), 256));
}
/**
+46 -35
View File
@@ -2,20 +2,24 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../injector';
import { Registry } from '../types';
import { u8aToHex } from '@polkadot/util';
import Enum from './Enum';
import { TypeRegistry } from './create';
import Null from '../primitive/Null';
import Text from '../primitive/Text';
import U32 from '../primitive/U32';
import Enum from './Enum';
describe('Enum', (): void => {
const registry = new TypeRegistry();
describe('typed enum (previously EnumType)', (): void => {
it('provides a clean toString() (value)', (): void => {
expect(
new Enum(
registry,
{ Text, U32 },
new Uint8Array([0, 2 << 2, 49, 50])
).value.toString()
@@ -25,6 +29,7 @@ describe('Enum', (): void => {
it('provides a clean toString() (enum)', (): void => {
expect(
new Enum(
registry,
{ Text, U32 },
new Uint8Array([1, 2 << 2, 49, 50])
).toString()
@@ -34,6 +39,7 @@ describe('Enum', (): void => {
it('decodes from a JSON input (lowercase)', (): void => {
expect(
new Enum(
registry,
{ Text, U32 },
{ text: 'some text value' }
).value.toString()
@@ -43,6 +49,7 @@ describe('Enum', (): void => {
it('decodes from hex', (): void => {
expect(
new Enum(
registry,
{ Text, U32 },
'0x0134120000'
).value.toString()
@@ -52,6 +59,7 @@ describe('Enum', (): void => {
it('decodes from hex (string types)', (): void => {
expect(
new Enum(
registry,
{ foo: 'Text', bar: 'u32' },
'0x0134120000'
).value.toString()
@@ -61,6 +69,7 @@ describe('Enum', (): void => {
it('decodes from a JSON input (mixed case)', (): void => {
expect(
new Enum(
registry,
{ Text, U32 },
{ U32: 42 }
).value.toString()
@@ -70,6 +79,7 @@ describe('Enum', (): void => {
it('decodes from JSON string', (): void => {
expect(
new Enum(
registry,
{ Null, U32 },
'null'
).type
@@ -77,7 +87,7 @@ describe('Enum', (): void => {
});
it('has correct isXyz/asXyz (Enum.with)', (): void => {
const test = new (Enum.with({ First: Text, Second: U32, Third: U32 }))({ Second: 42 }) as any as { isSecond: boolean; asSecond: U32; asThird: never };
const test = new (Enum.with({ First: Text, Second: U32, Third: U32 }))(registry, { Second: 42 }) as any as { isSecond: boolean; asSecond: U32; asThird: never };
expect(test.isSecond).toEqual(true);
expect(test.asSecond.toNumber()).toEqual(42);
@@ -89,8 +99,8 @@ describe('Enum', (): void => {
class B extends Null { }
class C extends Null { }
class Test extends Enum {
constructor (value?: string, index?: number) {
super({
constructor (registry: Registry, value?: string, index?: number) {
super(registry, {
a: A,
b: B,
c: C
@@ -98,7 +108,7 @@ describe('Enum', (): void => {
}
}
expect(new Test().toJSON()).toEqual({ a: null });
expect(new Test(registry).toJSON()).toEqual({ a: null });
});
it('creates via with', (): void => {
@@ -107,13 +117,14 @@ describe('Enum', (): void => {
class C extends Null { }
const Test = Enum.with({ A, B, C });
expect(new Test().toJSON()).toEqual({ A: null });
expect(new Test(1234, 1).toJSON()).toEqual({ B: 1234 });
expect(new Test(registry).toJSON()).toEqual({ A: null });
expect(new Test(registry, 1234, 1).toJSON()).toEqual({ B: 1234 });
});
it('allows accessing the type and value', (): void => {
const text = new Text('foo');
const text = new Text(registry, 'foo');
const enumType = new Enum(
registry,
{ Text, U32 },
{ Text: text }
);
@@ -125,7 +136,7 @@ describe('Enum', (): void => {
describe('utils', (): void => {
const DEF = { num: U32, str: Text };
const u8a = new Uint8Array([1, 3 << 2, 88, 89, 90]);
const test = new Enum(DEF, u8a);
const test = new Enum(registry, DEF, u8a);
it('compares against index', (): void => {
expect(test.eq(1)).toBe(true);
@@ -140,7 +151,7 @@ describe('Enum', (): void => {
});
it('compares against another enum', (): void => {
expect(test.eq(new Enum(DEF, u8a))).toBe(true);
expect(test.eq(new Enum(registry, DEF, u8a))).toBe(true);
});
it('compares against another object', (): void => {
@@ -152,7 +163,7 @@ describe('Enum', (): void => {
});
it('compares basic enum on string', (): void => {
expect(new Enum(['A', 'B', 'C'], 1).eq('B')).toBe(true);
expect(new Enum(registry, ['A', 'B', 'C'], 1).eq('B')).toBe(true);
});
});
});
@@ -160,20 +171,20 @@ describe('Enum', (): void => {
describe('string-only construction (old Enum)', (): void => {
const testDecode = (type: string, input: any, expected: any): void =>
it(`can decode from ${type}`, (): void => {
const e = new Enum(['foo', 'bar'], input);
const e = new Enum(registry, ['foo', 'bar'], input);
expect(e.toString()).toBe(expected);
});
const testEncode = (to: 'toJSON' | 'toNumber' | 'toString' | 'toU8a', expected: any): void =>
it(`can encode ${to}`, (): void => {
const e = new Enum(['foo', 'bar'], 1);
const e = new Enum(registry, ['foo', 'bar'], 1);
expect(e[to]()).toEqual(expected);
});
testDecode('Enum', undefined, 'foo');
testDecode('Enum', new Enum(['foo', 'bar'], 1), 'bar');
testDecode('Enum', new Enum(registry, ['foo', 'bar'], 1), 'bar');
testDecode('number', 0, 'foo');
testDecode('number', 1, 'bar');
testDecode('string', 'bar', 'bar');
@@ -187,61 +198,61 @@ describe('Enum', (): void => {
it('provides a clean toString()', (): void => {
expect(
new Enum(['foo', 'bar']).toString()
new Enum(registry, ['foo', 'bar']).toString()
).toEqual('foo');
});
it('provides a clean toString() (enum)', (): void => {
expect(
new Enum(['foo', 'bar'], new Enum(['foo', 'bar'], 1)).toNumber()
new Enum(registry, ['foo', 'bar'], new Enum(registry, ['foo', 'bar'], 1)).toNumber()
).toEqual(1);
});
it('converts to and from U8a', (): void => {
expect(
new Enum(['foo', 'bar'], new Uint8Array([1])).toU8a()
new Enum(registry, ['foo', 'bar'], new Uint8Array([1])).toU8a()
).toEqual(new Uint8Array([1]));
});
it('converts from JSON', (): void => {
expect(
new Enum(['foo', 'bar', 'baz', 'gaz', 'jaz'], 4).toNumber()
new Enum(registry, ['foo', 'bar', 'baz', 'gaz', 'jaz'], 4).toNumber()
).toEqual(4);
});
it('has correct isXyz getters (Enum.with)', (): void => {
const test = new (Enum.with(['First', 'Second', 'Third']))('Second') as any as { isSecond: boolean; asSecond: never };
const test = new (Enum.with(['First', 'Second', 'Third']))(registry, 'Second') as any as { isSecond: boolean; asSecond: never };
expect(test.isSecond).toEqual(true);
});
describe('utils', (): void => {
it('compares agains the index value', (): void => {
it('compares against the index value', (): void => {
expect(
new Enum(['foo', 'bar'], 1).eq(1)
new Enum(registry, ['foo', 'bar'], 1).eq(1)
).toBe(true);
});
it('compares agains the index value (false)', (): void => {
it('compares against the index value (false)', (): void => {
expect(
new Enum(['foo', 'bar'], 1).eq(0)
new Enum(registry, ['foo', 'bar'], 1).eq(0)
).toBe(false);
});
it('compares agains the string value', (): void => {
it('compares against the string value', (): void => {
expect(
new Enum(['foo', 'bar'], 1).eq('bar')
new Enum(registry, ['foo', 'bar'], 1).eq('bar')
).toBe(true);
});
it('compares agains the string value (false)', (): void => {
it('compares against the string value (false)', (): void => {
expect(
new Enum(['foo', 'bar'], 1).eq('foo')
new Enum(registry, ['foo', 'bar'], 1).eq('foo')
).toBe(false);
});
it('has isNone set, with correct index (i.e. no values are used)', (): void => {
const test = new Enum(['foo', 'bar'], 1);
const test = new Enum(registry, ['foo', 'bar'], 1);
expect(test.isNone).toBe(true);
expect(test.index).toEqual(1);
@@ -255,7 +266,7 @@ describe('Enum', (): void => {
A: U32,
B: U32
});
const test = new Test(new U32(123), 1);
const test = new Test(registry, new U32(registry, 123), 1);
expect(test.type).toEqual('B');
expect((test.value as U32).toNumber()).toEqual(123);
@@ -266,7 +277,7 @@ describe('Enum', (): void => {
A: U32,
B: U32
});
const test = new Test(new Test(123, 1));
const test = new Test(registry, new Test(registry, 123, 1));
expect(test.type).toEqual('B');
expect((test.value as U32).toNumber()).toEqual(123);
@@ -281,7 +292,7 @@ describe('Enum', (): void => {
A: U32,
B: Nest
});
const test = new Test(new Nest(123, 1), 1);
const test = new Test(registry, new Nest(registry, 123, 1), 1);
expect(test.type).toEqual('B');
expect((test.value as Enum).type).toEqual('D');
@@ -293,13 +304,13 @@ describe('Enum', (): void => {
describe('toRawType', (): void => {
it('has a sane output for basic enums', (): void => {
expect(
new Enum(['foo', 'bar']).toRawType()
new Enum(registry, ['foo', 'bar']).toRawType()
).toEqual(JSON.stringify({ _enum: ['foo', 'bar'] }));
});
it('has a sane output for typed enums', (): void => {
expect(
new Enum({ foo: Text, bar: U32 }).toRawType()
new Enum(registry, { foo: Text, bar: U32 }).toRawType()
).toEqual(JSON.stringify({ _enum: { foo: 'Text', bar: 'u32' } }));
});
});
@@ -310,7 +321,7 @@ describe('Enum', (): void => {
A: Text,
B: U32
});
const test = new Test(123, 1);
const test = new Test(registry, 123, 1);
expect(test.toHex()).toEqual('0x017b000000');
expect(test.encodedLength).toEqual(1 + 4);
+28 -28
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyJson, Codec, Constructor, InterfaceTypes } from '../types';
import { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { assert, hexToU8a, isHex, isNumber, isObject, isString, isU8a, isUndefined, stringCamelCase, stringUpperFirst, u8aConcat, u8aToHex } from '@polkadot/util';
@@ -13,7 +13,7 @@ import Struct from './Struct';
// export interface, this is used in Enum.with, so required as public by TS
export interface EnumConstructor<T = Codec> {
new(value?: any, index?: number): T;
new(registry: Registry, value?: any, index?: number): T;
}
type TypesDef = Record<string, Constructor>;
@@ -23,9 +23,9 @@ interface Decoded {
value: Codec;
}
function extractDef (_def: Record<string, InterfaceTypes | Constructor> | string[]): { def: TypesDef; isBasic: boolean } {
function extractDef (registry: Registry, _def: Record<string, InterfaceTypes | Constructor> | string[]): { def: TypesDef; isBasic: boolean } {
if (!Array.isArray(_def)) {
const def = mapToTypeMap(_def);
const def = mapToTypeMap(registry, _def);
const isBasic = !Object.values(def).some((type): boolean => type !== Null);
return {
@@ -44,18 +44,18 @@ function extractDef (_def: Record<string, InterfaceTypes | Constructor> | string
};
}
function createFromValue (def: TypesDef, index = 0, value?: any): Decoded {
function createFromValue (registry: Registry, def: TypesDef, index = 0, value?: any): Decoded {
const Clazz = Object.values(def)[index];
assert(!isUndefined(Clazz), `Unable to create Enum via index ${index}, in ${Object.keys(def).join(', ')}`);
return {
index,
value: new Clazz(value)
value: new Clazz(registry, value)
};
}
function decodeFromJSON (def: TypesDef, key: string, value?: any): Decoded {
function decodeFromJSON (registry: Registry, def: TypesDef, key: string, value?: any): Decoded {
// JSON comes in the form of { "<type (lowercased)>": "<value for type>" }, here we
// additionally force to lower to ensure forward compat
const keys = Object.keys(def).map((k): string => k.toLowerCase());
@@ -64,31 +64,31 @@ function decodeFromJSON (def: TypesDef, key: string, value?: any): Decoded {
assert(index !== -1, `Cannot map Enum JSON, unable to find '${key}' in ${keys.join(', ')}`);
return createFromValue(def, index, value);
return createFromValue(registry, def, index, value);
}
function decodeFromString (def: TypesDef, value: string): Decoded {
function decodeFromString (registry: Registry, def: TypesDef, value: string): Decoded {
return isHex(value)
// eslint-disable-next-line @typescript-eslint/no-use-before-define
? decodeFromValue(def, hexToU8a(value))
: decodeFromJSON(def, value);
? decodeFromValue(registry, def, hexToU8a(value))
: decodeFromJSON(registry, def, value);
}
function decodeFromValue (def: TypesDef, value?: any): Decoded {
function decodeFromValue (registry: Registry, def: TypesDef, value?: any): Decoded {
if (isU8a(value)) {
return createFromValue(def, value[0], value.subarray(1));
return createFromValue(registry, def, value[0], value.subarray(1));
} else if (isNumber(value)) {
return createFromValue(def, value);
return createFromValue(registry, def, value);
} else if (isString(value)) {
return decodeFromString(def, value.toString());
return decodeFromString(registry, def, value.toString());
} else if (isObject(value)) {
const key = Object.keys(value)[0];
return decodeFromJSON(def, key, value[key]);
return decodeFromJSON(registry, def, key, value[key]);
}
// Worst-case scenario, return the first with default
return createFromValue(def, 0);
return createFromValue(registry, def, 0);
}
/**
@@ -109,11 +109,11 @@ export default class Enum extends Base<Codec> {
private _isBasic: boolean;
constructor (def: Record<string, InterfaceTypes | Constructor> | string[], value?: any, index?: number) {
const defInfo = extractDef(def);
const decoded = Enum.decodeEnum(defInfo.def, value, index);
constructor (registry: Registry, def: Record<string, InterfaceTypes | Constructor> | string[], value?: any, index?: number) {
const defInfo = extractDef(registry, def);
const decoded = Enum.decodeEnum(registry, defInfo.def, value, index);
super(decoded.value);
super(registry, decoded.value);
this._def = defInfo.def;
this._isBasic = defInfo.isBasic;
@@ -121,23 +121,23 @@ export default class Enum extends Base<Codec> {
this._index = this._indexes.indexOf(decoded.index) || 0;
}
private static decodeEnum (def: TypesDef, value?: any, index?: number): Decoded {
private static decodeEnum (registry: Registry, def: TypesDef, value?: any, index?: number): Decoded {
// NOTE We check the index path first, before looking at values - this allows treating
// the optional indexes before anything else, more-specific > less-specific
if (isNumber(index)) {
return createFromValue(def, index, value);
return createFromValue(registry, def, index, value);
} else if (value instanceof Enum) {
return createFromValue(def, value._index, value.raw);
return createFromValue(registry, def, value._index, value.raw);
}
// Or else, we just look at `value`
return decodeFromValue(def, value);
return decodeFromValue(registry, def, value);
}
public static with (Types: Record<string, InterfaceTypes | Constructor> | string[]): EnumConstructor<Enum> {
return class extends Enum {
constructor (value?: any, index?: number) {
super(Types, value, index);
constructor (registry: Registry, value?: any, index?: number) {
super(registry, Types, value, index);
Object.keys(this._def).forEach((_key): void => {
const name = stringUpperFirst(stringCamelCase(_key.replace(' ', '_')));
@@ -261,7 +261,7 @@ export default class Enum extends Base<Codec> {
protected toRawStruct (): string[] | Record<string, string> {
return this._isBasic
? Object.keys(this._def)
: Struct.typesToMap(this._def);
: Struct.typesToMap(this.registry, this._def);
}
/**
+12 -9
View File
@@ -2,50 +2,53 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { TypeRegistry } from './create';
import Int from './Int';
describe('Int', (): void => {
const registry = new TypeRegistry();
it('provides a toBn interface', (): void => {
expect(
new Int(-1234).toBn().toNumber()
new Int(registry, -1234).toBn().toNumber()
).toEqual(-1234);
});
it('provides a toNumber interface', (): void => {
expect(
new Int(-1234).toNumber()
new Int(registry, -1234).toNumber()
).toEqual(-1234);
});
it('converts to Little Endian from the provided value', (): void => {
expect(
new Int(-1234).toU8a()
new Int(registry, -1234).toU8a()
).toEqual(new Uint8Array([46, 251, 255, 255, 255, 255, 255, 255]));
});
it('converts to Little Endian from the provided value (bitLength)', (): void => {
expect(
new Int(-1234, 32).toU8a()
new Int(registry, -1234, 32).toU8a()
).toEqual(new Uint8Array([46, 251, 255, 255]));
});
it('converts to hex/string', (): void => {
const i = new Int('0x12', 16);
const i = new Int(registry, '0x12', 16);
expect(i.toHex()).toEqual('0x0012');
expect(i.toString()).toEqual('18');
});
it('converts to equivalents', (): void => {
const a = new Int('-123');
const a = new Int(registry, '-123');
expect(
new Int(a).toNumber()
new Int(registry, a).toNumber()
).toEqual(-123);
});
it('converts to JSON depending on flags', (): void => {
expect(new Int(0x12, 16).toJSON()).toEqual('0x0012');
expect(new Int(0x12, 16, false).toJSON()).toEqual(0x12);
expect(new Int(registry, 0x12, 16).toJSON()).toEqual('0x0012');
expect(new Int(registry, 0x12, 16, false).toJSON()).toEqual(0x12);
});
});
+3 -10
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyNumber } from '../types';
import { AnyNumber, Registry } from '../types';
import { bnToHex, bnToU8a } from '@polkadot/util';
@@ -19,15 +19,8 @@ import AbstractInt, { DEFAULT_UINT_BITS, UIntBitLength } from './AbstractInt';
* @noInheritDoc
*/
export default class Int extends AbstractInt {
constructor (
value: AnyNumber = 0,
bitLength: UIntBitLength = DEFAULT_UINT_BITS, isHexJson = true) {
super(
true,
value,
bitLength,
isHexJson
);
constructor (registry: Registry, value: AnyNumber = 0, bitLength: UIntBitLength = DEFAULT_UINT_BITS, isHexJson = true) {
super(registry, true, value, bitLength, isHexJson);
}
/**
+7 -7
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Constructor, Codec, InterfaceTypes } from '../types';
import { Constructor, Codec, InterfaceTypes, Registry } from '../types';
import Option from './Option';
import Struct from './Struct';
@@ -18,8 +18,8 @@ const EMPTY = new Uint8Array();
* @description The wrapper for the result from a LinkedMap
*/
export default class Linkage<T extends Codec> extends Struct {
constructor (Type: Constructor | InterfaceTypes, value?: any) {
super({
constructor (registry: Registry, Type: Constructor | InterfaceTypes, value?: any) {
super(registry, {
previous: Option.with(Type),
next: Option.with(Type)
}, value);
@@ -27,8 +27,8 @@ export default class Linkage<T extends Codec> extends Struct {
public static withKey<O extends Codec> (Type: Constructor | InterfaceTypes): Constructor<Linkage<O>> {
return class extends Linkage<O> {
constructor (value?: any) {
super(Type, value);
constructor (registry: Registry, value?: any) {
super(registry, Type, value);
}
};
}
@@ -65,8 +65,8 @@ export default class Linkage<T extends Codec> extends Struct {
* @description A Linkage keys/Values tuple
*/
export class LinkageResult extends Tuple {
constructor ([TypeKey, keys]: TypeWithValues, [TypeValue, values]: TypeWithValues) {
super({
constructor (registry: Registry, [TypeKey, keys]: TypeWithValues, [TypeValue, values]: TypeWithValues) {
super(registry, {
Keys: Vec.with(TypeKey),
Values: Vec.with(TypeValue)
}, [keys, values]);
+21 -20
View File
@@ -2,16 +2,17 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../injector';
import Option from './Option';
import { TypeRegistry } from './create';
import Bytes from '../primitive/Bytes';
import U32 from '../primitive/U32';
import Text from '../primitive/Text';
import Option from './Option';
const registry = new TypeRegistry();
const testDecode = (type: string, input: any, expected: any): void =>
it(`can decode from ${type}`, (): void => {
const o = new Option(Text, input);
const o = new Option(registry, Text, input);
expect(o.toString()).toBe(expected);
expect(o.isNone).toBe(!expected.length);
@@ -19,27 +20,27 @@ const testDecode = (type: string, input: any, expected: any): void =>
const testEncode = (to: string, expected: any): void =>
it(`can encode ${to}`, (): void => {
const e = new Option(Text, 'foo');
const e = new Option(registry, Text, 'foo');
expect((e as any)[to]()).toEqual(expected);
});
describe('Option', (): void => {
it('converts undefined/null to empty', (): void => {
expect(new Option(Text, undefined).isNone).toBe(true);
expect(new Option(Text, null).isNone).toBe(true);
expect(new Option(Text, 'test').isNone).toBe(false);
expect(new Option(registry, Text, undefined).isNone).toBe(true);
expect(new Option(registry, Text, null).isNone).toBe(true);
expect(new Option(registry, Text, 'test').isNone).toBe(false);
});
it('converts an option to an option', (): void => {
expect(
new Option(Text, new Option(Text, 'hello')).toString()
new Option(registry, Text, new Option(registry, Text, 'hello')).toString()
).toEqual('hello');
});
it('converts an option to an option (strings)', (): void => {
expect(
new Option('Text', new Option('Text', 'hello')).toString()
new Option(registry, 'Text', new Option(registry, 'Text', 'hello')).toString()
).toEqual('hello');
});
@@ -50,7 +51,7 @@ describe('Option', (): void => {
// whatc the hex prefix and length
expect(
new Option(Bytes, HEX).toHex().substr(6)
new Option(registry, Bytes, HEX).toHex().substr(6)
).toEqual(HEX.substr(2));
});
@@ -58,7 +59,7 @@ describe('Option', (): void => {
const HEX = '0x12345678';
expect(
(new Option(U32, HEX).unwrap() as U32).toNumber()
(new Option(registry, U32, HEX).unwrap() as U32).toNumber()
).toEqual(0x12345678);
});
@@ -73,33 +74,33 @@ describe('Option', (): void => {
it('has empty toString() (undefined)', (): void => {
expect(
new Option(Text).toString()
new Option(registry, Text).toString()
).toEqual('');
});
it('has value toString() (provided)', (): void => {
expect(
new Option(Text, new Uint8Array([1, 4 << 2, 49, 50, 51, 52])).toString()
new Option(registry, Text, new Uint8Array([1, 4 << 2, 49, 50, 51, 52])).toString()
).toEqual('1234');
});
it('converts toU8a() with', (): void => {
expect(
new Option(Text, '1234').toU8a()
new Option(registry, Text, '1234').toU8a()
).toEqual(new Uint8Array([1, 4 << 2, 49, 50, 51, 52]));
});
it('converts toU8a() without', (): void => {
expect(
new Option(Text).toU8a()
new Option(registry, Text).toU8a()
).toEqual(new Uint8Array([0]));
});
describe('utils', (): void => {
const testeq = new Option(Text, '1234');
const testeq = new Option(registry, Text, '1234');
it('compares against other option', (): void => {
expect(testeq.eq(new Option(Text, '1234'))).toBe(true);
expect(testeq.eq(new Option(registry, Text, '1234'))).toBe(true);
});
it('compares against raw value', (): void => {
@@ -107,11 +108,11 @@ describe('Option', (): void => {
});
it('unwraps to default if empty', (): void => {
expect(new Option(Text).unwrapOr('6789')).toBe('6789');
expect(new Option(registry, Text).unwrapOr('6789')).toBe('6789');
});
it('unwraps to value if non-empty', (): void => {
expect((new Option(Text, '1234').unwrapOr(null) as Text).toString()).toBe('1234');
expect((new Option(registry, Text, '1234').unwrapOr(null) as Text).toString()).toBe('1234');
});
});
});
+15 -15
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor, InterfaceTypes } from '../types';
import { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { isNull, isU8a, isUndefined, u8aToHex } from '@polkadot/util';
@@ -21,41 +21,41 @@ import Base from './Base';
export default class Option<T extends Codec> extends Base<T> {
private _Type: Constructor;
constructor (Type: Constructor | InterfaceTypes, value?: any) {
const Clazz = typeToConstructor(Type);
constructor (registry: Registry, Type: Constructor | InterfaceTypes, value?: any) {
const Clazz = typeToConstructor(registry, Type);
super(Option.decodeOption(Clazz, value));
super(registry, Option.decodeOption(registry, Clazz, value));
this._Type = Clazz;
}
public static decodeOption (Type: Constructor, value?: any): Codec {
public static decodeOption (registry: Registry, Type: Constructor, value?: any): Codec {
if (isNull(value) || isUndefined(value) || value instanceof Null) {
return new Null();
return new Null(registry);
} else if (value instanceof Option) {
return Option.decodeOption(Type, value.value);
return Option.decodeOption(registry, Type, value.value);
} else if (value instanceof Type) {
// don't re-create, use as it (which also caters for derived types)
return value;
} else if (isU8a(value)) {
// the isU8a check happens last in the if-tree - since the wrapped value
// may be an instance of it, so Type and Option checks go in first
return Option.decodeOptionU8a(Type, value);
return Option.decodeOptionU8a(registry, Type, value);
}
return new Type(value);
return new Type(registry, value);
}
private static decodeOptionU8a (Type: Constructor, value: Uint8Array): Codec {
private static decodeOptionU8a (registry: Registry, Type: Constructor, value: Uint8Array): Codec {
return !value.length || value[0] === 0
? new Null()
: new Type(value.subarray(1));
? new Null(registry)
: new Type(registry, value.subarray(1));
}
public static with<O extends Codec> (Type: Constructor | InterfaceTypes): Constructor<Option<O>> {
return class extends Option<O> {
constructor (value?: any) {
super(Type, value);
constructor (registry: Registry, value?: any) {
super(registry, Type, value);
}
};
}
@@ -122,7 +122,7 @@ export default class Option<T extends Codec> extends Base<T> {
* @description Returns the base runtime type name for this instance
*/
public toRawType (isBare?: boolean): string {
const wrapped = new this._Type().toRawType();
const wrapped = new this._Type(this.registry).toRawType();
return isBare
? wrapped
+7 -8
View File
@@ -2,23 +2,22 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../injector';
import { hexToString } from '@polkadot/util';
import { u32, Text } from '../primitive';
import { createType } from './create';
import { createType, TypeRegistry } from './create';
import Result from './Result';
describe('Result', (): void => {
const registry = new TypeRegistry();
const Type = Result.with({ Ok: u32, Error: Text });
it('has a sane toRawType representation', (): void => {
expect(new Type().toRawType()).toEqual('Result<u32,Text>');
expect(new Type(registry).toRawType()).toEqual('Result<u32,Text>');
});
it('decodes from a u8a (success)', (): void => {
const result = new Type(new Uint8Array([0, 1, 2, 3, 4]));
const result = new Type(registry, new Uint8Array([0, 1, 2, 3, 4]));
expect(result.isOk);
expect(result.asOk.toU8a()).toEqual(new Uint8Array([1, 2, 3, 4]));
@@ -29,7 +28,7 @@ describe('Result', (): void => {
});
it('decodes from a u8a (error)', (): void => {
const result = new Type(new Uint8Array([1, 4 << 2, 100, 101, 102, 103]));
const result = new Type(registry, new Uint8Array([1, 4 << 2, 100, 101, 102, 103]));
expect(result.isError);
expect(result.asError.toU8a()).toEqual(new Uint8Array([4 << 2, 100, 101, 102, 103]));
@@ -40,12 +39,12 @@ describe('Result', (): void => {
});
it('decodes from a JSON representation', (): void => {
const result = new Type({ Error: 'error' });
const result = new Type(registry, { Error: 'error' });
expect(result.toHex()).toEqual('0x01146572726f72');
});
it('returns a proper raw typedef rom a built-in', (): void => {
expect(createType('DispatchResult').toRawType()).toEqual('Result<Null,Text>');
expect(createType(registry, 'DispatchResult').toRawType()).toEqual('Result<Null,Text>');
});
});
+5 -5
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor, InterfaceTypes } from '../types';
import { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { assert } from '@polkadot/util';
@@ -14,15 +14,15 @@ import Enum from './Enum';
* A Result maps to the Rust Result type, that can either wrap a success or error value
*/
export default class Result<O extends Codec, E extends Codec> extends Enum {
constructor (Ok: Constructor<O> | InterfaceTypes, Error: Constructor<E> | InterfaceTypes, value?: any) {
constructor (registry: Registry, Ok: Constructor<O> | InterfaceTypes, Error: Constructor<E> | InterfaceTypes, value?: any) {
// NOTE This is order-dependent, Ok (with index 0) needs to be first
super({ Ok, Error }, value);
super(registry, { Ok, Error }, value);
}
public static with<O extends Codec, E extends Codec> (Types: { Ok: Constructor<O> | InterfaceTypes; Error: Constructor<E> | InterfaceTypes }): Constructor<Result<O, E>> {
return class extends Result<O, E> {
constructor (value?: any) {
super(Types.Ok, Types.Error, value);
constructor (registry: Registry, value?: any) {
super(registry, Types.Ok, Types.Error, value);
}
};
}
+12 -9
View File
@@ -2,6 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { TypeRegistry } from './create';
import Set from './Set';
const SET_FIELDS = {
@@ -25,8 +26,10 @@ const SET_WITHDRAW = {
};
describe('Set', (): void => {
const registry = new TypeRegistry();
it('constructs via an string[]', (): void => {
const set = new Set(SET_ROLES, ['full', 'authority']);
const set = new Set(registry, SET_ROLES, ['full', 'authority']);
expect(set.isEmpty).toEqual(false);
expect(set.toString()).toEqual(
@@ -36,36 +39,36 @@ describe('Set', (): void => {
it('throws with invalid values', (): void => {
expect(
(): Set => new Set(SET_ROLES, ['full', 'authority', 'invalid'])
(): Set => new Set(registry, SET_ROLES, ['full', 'authority', 'invalid'])
).toThrow(/Invalid key 'invalid'/);
});
it('throws with add on invalid', (): void => {
expect(
(): Set => (new Set(SET_ROLES, [])).add('invalid')
(): Set => (new Set(registry, SET_ROLES, [])).add('invalid')
).toThrow(/Invalid key 'invalid'/);
});
it('allows construction via number', (): void => {
expect(
(new Set(SET_WITHDRAW, 15)).eq(['TransactionPayment', 'Transfer', 'Reserve', 'Fee'])
(new Set(registry, SET_WITHDRAW, 15)).eq(['TransactionPayment', 'Transfer', 'Reserve', 'Fee'])
).toBe(true);
});
it('does not allow invalid number', (): void => {
expect(
(): Set => new Set(SET_WITHDRAW, 31)
(): Set => new Set(registry, SET_WITHDRAW, 31)
).toThrow(/Mismatch decoding '31', computed as '15'/);
});
it('hash a valid encoding', (): void => {
const set = new Set(SET_FIELDS, ['header', 'body', 'justification']);
const set = new Set(registry, SET_FIELDS, ['header', 'body', 'justification']);
expect(set.toU8a()).toEqual(new Uint8Array([19]));
});
describe('utils', (): void => {
const set = new Set(SET_ROLES, ['full', 'authority']);
const set = new Set(registry, SET_ROLES, ['full', 'authority']);
it('compares against string array', (): void => {
expect(
@@ -81,7 +84,7 @@ describe('Set', (): void => {
it('compares against other sets', (): void => {
expect(
set.eq(new Set(SET_ROLES, ['authority', 'full']))
set.eq(new Set(registry, SET_ROLES, ['authority', 'full']))
).toBe(true);
});
@@ -94,7 +97,7 @@ describe('Set', (): void => {
it('has a sane toRawType representation', (): void => {
expect(
new Set({ a: 1, b: 2, c: 345 }).toRawType()
new Set(registry, { a: 1, b: 2, c: 345 }).toRawType()
).toEqual(JSON.stringify({
_set: { a: 1, b: 2, c: 345 }
}));
+8 -5
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor, IHash } from '../types';
import { Codec, Constructor, IHash, Registry } from '../types';
import { assert, isU8a, isNumber, isUndefined, stringCamelCase, stringUpperFirst, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -20,11 +20,14 @@ type SetValues = Record<string, number>;
*/
// FIXME This is a prime candidate to extend the JavaScript built-in Set
export default class CodecSet extends Set<string> implements Codec {
public readonly registry: Registry;
private _setValues: SetValues;
constructor (setValues: SetValues, value?: string[] | Set<string> | Uint8Array | number) {
constructor (registry: Registry, setValues: SetValues, value?: string[] | Set<string> | Uint8Array | number) {
super(CodecSet.decodeSet(setValues, value));
this.registry = registry;
this._setValues = setValues;
}
@@ -76,8 +79,8 @@ export default class CodecSet extends Set<string> implements Codec {
public static with (values: SetValues): Constructor<CodecSet> {
return class extends CodecSet {
constructor (value?: any) {
super(values, value);
constructor (registry: Registry, value?: any) {
super(registry, values, value);
Object.keys(values).forEach((_key): void => {
const name = stringUpperFirst(stringCamelCase(_key));
@@ -106,7 +109,7 @@ export default class CodecSet extends Set<string> implements Codec {
* @description returns a hash of the contents
*/
public get hash (): IHash {
return new U8a(blake2AsU8a(this.toU8a(), 256));
return new U8a(this.registry, blake2AsU8a(this.toU8a(), 256));
}
/**
+26 -26
View File
@@ -2,9 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../injector';
import { ClassOf } from './create';
import { ClassOf, TypeRegistry } from './create';
import AccountId from '../primitive/Generic/AccountId';
import Text from '../primitive/Text';
import U32 from '../primitive/U32';
@@ -13,10 +11,12 @@ import Struct from './Struct';
import Vec from './Vec';
describe('Struct', (): void => {
const registry = new TypeRegistry();
describe('decoding', (): void => {
const testDecode = (type: string, input: any): void =>
it(`can decode from ${type}`, (): void => {
const s = new Struct({
const s = new Struct(registry, {
foo: Text,
bar: U32
}, input);
@@ -37,7 +37,7 @@ describe('Struct', (): void => {
describe('encoding', (): void => {
const testEncode = (to: CodecTo, expected: any): void =>
it(`can encode ${to}`, (): void => {
const s = new Struct({
const s = new Struct(registry, {
foo: Text,
bar: U32
}, { foo: 'bazzing', bar: 69 });
@@ -57,12 +57,12 @@ describe('Struct', (): void => {
txt: Text,
u32: U32
})
)(null).toString()
)(registry, null).toString()
).toEqual('{}');
});
it('decodes a more complicated type', (): void => {
const s = new Struct({
const s = new Struct(registry, {
foo: Vec.with(Struct.with({
bar: Text
}))
@@ -71,11 +71,11 @@ describe('Struct', (): void => {
});
it('decodes from a Map input', (): void => {
const input = new Struct({
const input = new Struct(registry, {
a: U32,
txt: Text
}, { a: 42, txt: 'fubar' });
const s = new Struct({
const s = new Struct(registry, {
txt: Text,
foo: U32,
bar: U32
@@ -90,7 +90,7 @@ describe('Struct', (): void => {
txt: Text,
u32: U32
})
)('ABC')
)(registry, 'ABC')
).toThrowError(/Struct: cannot decode type/);
});
@@ -101,7 +101,7 @@ describe('Struct', (): void => {
txt: Text,
u32: U32
})
)({ txt: 'foo', u32: 0x123456 }).toString()
)(registry, { txt: 'foo', u32: 0x123456 }).toString()
).toEqual('{"txt":"foo","u32":1193046}');
});
@@ -113,7 +113,7 @@ describe('Struct', (): void => {
num: 'u32',
cls: U32
})
)({ txt: 'foo', num: 0x123456, cls: 123 }).toString()
)(registry, { txt: 'foo', num: 0x123456, cls: 123 }).toString()
).toEqual('{"txt":"foo","num":1193046,"cls":123}');
});
@@ -123,7 +123,7 @@ describe('Struct', (): void => {
txt: Text,
u32: U32
})
)({ txt: 'foo', u32: 0x123456 });
)(registry, { txt: 'foo', u32: 0x123456 });
expect((struct as any).txt.toString()).toEqual('foo');
expect((struct as any).u32.toNumber()).toEqual(0x123456);
@@ -136,13 +136,13 @@ describe('Struct', (): void => {
txt: Text,
u32: U32
})
)({ foo: 'bazzing', bar: 69 }).encodedLength
)(registry, { foo: 'bazzing', bar: 69 }).encodedLength
).toEqual(5);
});
it('exposes the types', (): void => {
expect(
new Struct({
new Struct(registry, {
foo: Text,
bar: Text,
baz: U32
@@ -165,7 +165,7 @@ describe('Struct', (): void => {
txt: Text,
u32: U32
})
)({ txt: 'foo', u32: 1234 })
)(registry, { txt: 'foo', u32: 1234 })
.getAtIndex(1)
.toString()
).toEqual('1234');
@@ -180,7 +180,7 @@ describe('Struct', (): void => {
};
expect(
new Struct({
new Struct(registry, {
foo: Text,
bar: Text,
baz: U32
@@ -192,20 +192,20 @@ describe('Struct', (): void => {
it('allows toString with large numbers', (): void => {
// replicate https://github.com/polkadot-js/api/issues/640
expect(
new Struct({
blockNumber: ClassOf('Option<BlockNumber>')
new Struct(registry, {
blockNumber: ClassOf(registry, 'Option<BlockNumber>')
}, { blockNumber: '0x0000000010abcdef' }).toString()
).toEqual('{"blockNumber":279694831}');
});
it('generates sane toRawType', (): void => {
expect(
new Struct({
new Struct(registry, {
accountId: AccountId,
balanceCompact: ClassOf('Compact<Balance>'),
blockNumber: ClassOf('BlockNumber'),
compactNumber: ClassOf('Compact<BlockNumber>'),
optionNumber: ClassOf('Option<BlockNumber>'),
balanceCompact: ClassOf(registry, 'Compact<Balance>'),
blockNumber: ClassOf(registry, 'BlockNumber'),
compactNumber: ClassOf(registry, 'Compact<BlockNumber>'),
optionNumber: ClassOf(registry, 'Option<BlockNumber>'),
counter: U32,
vector: Vec.with(AccountId)
}).toRawType()
@@ -223,11 +223,11 @@ describe('Struct', (): void => {
it('generates sane toRawType (via with)', (): void => {
const Type = Struct.with({
accountId: AccountId,
balance: ClassOf('Balance')
balance: ClassOf(registry, 'Balance')
});
expect(
new Type().toRawType()
new Type(registry).toRawType()
).toEqual(JSON.stringify({
accountId: 'AccountId',
balance: 'Balance' // Override in Uint
+22 -19
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyJsonObject, Codec, Constructor, ConstructorDef, IHash, InterfaceTypes } from '../types';
import { AnyJsonObject, Codec, Constructor, ConstructorDef, IHash, InterfaceTypes, Registry } from '../types';
import { hexToU8a, isHex, isObject, isU8a, isUndefined, u8aConcat, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -31,16 +31,19 @@ export default class Struct<
V extends { [K in keyof S]: any } = { [K in keyof S]: any },
// type names, mapped by key, name of Class in S
E extends { [K in keyof S]: string } = { [K in keyof S]: string }> extends Map<keyof S, Codec> implements Codec {
public readonly registry: Registry;
protected _jsonMap: Map<keyof S, string>;
protected _Types: ConstructorDef;
constructor (Types: S, value: V | Map<any, any> | any[] | string = {} as unknown as V, jsonMap: Map<keyof S, string> = new Map()) {
const Clazzes = mapToTypeMap(Types);
const decoded: T = Struct.decodeStruct(Clazzes, value, jsonMap);
constructor (registry: Registry, Types: S, value: V | Map<any, any> | any[] | string = {} as unknown as V, jsonMap: Map<keyof S, string> = new Map()) {
const Clazzes = mapToTypeMap(registry, Types);
const decoded: T = Struct.decodeStruct(registry, Clazzes, value, jsonMap);
super(Object.entries(decoded));
this.registry = registry;
this._jsonMap = jsonMap;
this._Types = Clazzes;
}
@@ -60,11 +63,11 @@ export default class Struct<
* `Object.keys(Types)`
* @param jsonMap
*/
private static decodeStruct <T> (Types: ConstructorDef, value: any, jsonMap: Map<any, string>): T {
private static decodeStruct <T> (registry: Registry, Types: ConstructorDef, value: any, jsonMap: Map<any, string>): T {
if (isHex(value)) {
return Struct.decodeStruct(Types, hexToU8a(value as string), jsonMap);
return Struct.decodeStruct(registry, Types, hexToU8a(value as string), jsonMap);
} else if (isU8a(value)) {
const values = decodeU8a(value, Object.values(Types));
const values = decodeU8a(registry, value, Object.values(Types));
// Transform array of values to {key: value} mapping
return Object.keys(Types).reduce((raw, key, index): T => {
@@ -78,10 +81,10 @@ export default class Struct<
}
// We assume from here that value is a JS object (Array, Map, Object)
return Struct.decodeStructFromObject(Types, value, jsonMap);
return Struct.decodeStructFromObject(registry, Types, value, jsonMap);
}
private static decodeStructFromObject <T> (Types: ConstructorDef, value: any, jsonMap: Map<any, string>): T {
private static decodeStructFromObject <T> (registry: Registry, Types: ConstructorDef, value: any, jsonMap: Map<any, string>): T {
return Object.keys(Types).reduce((raw, key, index): T => {
// The key in the JSON can be snake_case (or other cases), but in our
// Types, result or any other maps, it's camelCase
@@ -92,17 +95,17 @@ export default class Struct<
// TS2322: Type 'Codec' is not assignable to type 'T[keyof S]'.
(raw as any)[key] = value[index] instanceof Types[key]
? value[index]
: new Types[key](value[index]);
: new Types[key](registry, value[index]);
} else if (value instanceof Map) {
const mapped = value.get(jsonKey);
(raw as any)[key] = mapped instanceof Types[key]
? mapped
: new Types[key](mapped);
: new Types[key](registry, mapped);
} else if (isObject(value)) {
(raw as any)[key] = value[jsonKey as string] instanceof Types[key]
? value[jsonKey as string]
: new Types[key](value[jsonKey as string]);
: new Types[key](registry, value[jsonKey as string]);
} else {
throw new Error(`Struct: cannot decode type ${Types[key].name} with value ${JSON.stringify(value)}`);
}
@@ -116,8 +119,8 @@ export default class Struct<
public static with<S extends TypesDef> (Types: S): Constructor<Struct<S>> {
return class extends Struct<S> {
constructor (value?: any, jsonMap?: Map<keyof S, string>) {
super(Types, value, jsonMap);
constructor (registry: Registry, value?: any, jsonMap?: Map<keyof S, string>) {
super(registry, Types, value, jsonMap);
(Object.keys(Types) as (keyof S)[]).forEach((key): void => {
// do not clobber existing properties on the object
@@ -156,7 +159,7 @@ export default class Struct<
return (Object
.entries(this._Types) as [keyof S, Constructor][])
.reduce((result: E, [key, Type]): E => {
(result as any)[key] = new Type().toRawType();
(result as any)[key] = new Type(this.registry).toRawType();
return result;
}, {} as unknown as E);
@@ -177,7 +180,7 @@ export default class Struct<
* @description returns a hash of the contents
*/
public get hash (): IHash {
return new U8a(blake2AsU8a(this.toU8a(), 256));
return new U8a(this.registry, blake2AsU8a(this.toU8a(), 256));
}
/**
@@ -232,9 +235,9 @@ export default class Struct<
}, {} as any);
}
public static typesToMap (Types: Record<string, Constructor>): Record<string, string> {
public static typesToMap (registry: Registry, Types: Record<string, Constructor>): Record<string, string> {
return Object.entries(Types).reduce((result, [key, Type]): Record<string, string> => {
result[key] = new Type().toRawType();
result[key] = new Type(registry).toRawType();
return result;
}, {} as unknown as Record<string, string>);
@@ -245,7 +248,7 @@ export default class Struct<
*/
public toRawType (): string {
return JSON.stringify(
Struct.typesToMap(this._Types)
Struct.typesToMap(this.registry, this._Types)
);
}
+7 -3
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyJsonObject, Codec, IHash } from '../types';
import { AnyJsonObject, Codec, IHash, Registry } from '../types';
import { isUndefined } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -20,11 +20,15 @@ import { compareMap } from './utils';
* @noInheritDoc
*/
export default class StructAny extends Map<string, any> implements Codec {
constructor (value?: { [index: string]: any } | null) {
public readonly registry: Registry;
constructor (registry: Registry, value?: { [index: string]: any } | null) {
const decoded = StructAny.decodeJson(value);
super(decoded);
this.registry = registry;
// like we are doing with structs, add the keys as getters
decoded.forEach(([key]): void => {
// do not clobber existing properties on the object
@@ -54,7 +58,7 @@ export default class StructAny extends Map<string, any> implements Codec {
* @description returns a hash of the contents
*/
public get hash (): IHash {
return new U8a(blake2AsU8a(this.toU8a(), 256));
return new U8a(this.registry, blake2AsU8a(this.toU8a(), 256));
}
/**
+15 -14
View File
@@ -2,8 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../injector';
import { VoteThreshold } from '../interfaces/elections';
import { BlockNumber } from '../interfaces/runtime';
import { CodecTo } from '../types';
@@ -11,18 +9,19 @@ import { CodecTo } from '../types';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import { ClassOf } from './create';
import Call from '../primitive/Generic/Call';
import { ClassOf, TypeRegistry } from './create';
import Text from '../primitive/Text';
import U32 from '../primitive/U32';
import U128 from '../primitive/U128';
import Tuple from './Tuple';
describe('Tuple', (): void => {
const registry = new TypeRegistry();
let tuple: Tuple;
beforeEach((): void => {
tuple = new Tuple(
registry,
[Text, U32],
['bazzing', 69]
);
@@ -31,7 +30,7 @@ describe('Tuple', (): void => {
describe('decoding', (): void => {
const testDecode = (type: string, input: any): void =>
it(`can decode from ${type}`, (): void => {
const t = new Tuple([
const t = new Tuple(registry, [
Text,
U32
], input);
@@ -60,6 +59,7 @@ describe('Tuple', (): void => {
it('creates from string types', (): void => {
expect(
new Tuple(
registry,
['Text', 'u32', U32],
['foo', 69, 42]
).toString()
@@ -67,12 +67,13 @@ describe('Tuple', (): void => {
});
it('creates properly via actual hex string', (): void => {
Call.injectMetadata(new Metadata(rpcMetadata));
// eslint-disable-next-line no-new
new Metadata(registry, rpcMetadata);
const test = new (Tuple.with([
ClassOf('BlockNumber'), ClassOf('VoteThreshold')
ClassOf(registry, 'BlockNumber'), ClassOf(registry, 'VoteThreshold')
]
))('0x6219000001');
))(registry, '0x6219000001');
expect((test[0] as BlockNumber).toNumber()).toEqual(6498);
expect((test[1] as VoteThreshold).toNumber()).toEqual(1);
@@ -83,16 +84,16 @@ describe('Tuple', (): void => {
});
it('exposes the Types (object creation)', (): void => {
const test = new Tuple({
BlockNumber: ClassOf('BlockNumber'),
VoteThreshold: ClassOf('VoteThreshold')
const test = new Tuple(registry, {
BlockNumber: ClassOf(registry, 'BlockNumber'),
VoteThreshold: ClassOf(registry, 'VoteThreshold')
}, []);
expect(test.Types).toEqual(['BlockNumber', 'VoteThreshold']);
});
it('exposes filter', (): void => {
expect(tuple.filter((v): boolean => v.toJSON() === 69)).toEqual([new U32(69)]);
expect(tuple.filter((v): boolean => v.toJSON() === 69)).toEqual([new U32(registry, 69)]);
});
it('exposes map', (): void => {
@@ -112,13 +113,13 @@ describe('Tuple', (): void => {
describe('toRawType', (): void => {
it('generates sane value with array types', (): void => {
expect(
new Tuple([U128, ClassOf('BlockNumber')]).toRawType()
new Tuple(registry, [U128, ClassOf(registry, 'BlockNumber')]).toRawType()
).toEqual('(u128,u32)');
});
it('generates sane value with object types', (): void => {
expect(
new Tuple({ number: U128, blockNumber: ClassOf('BlockNumber') }).toRawType()
new Tuple(registry, { number: U128, blockNumber: ClassOf(registry, 'BlockNumber') }).toRawType()
).toEqual('(u128,u32)');
});
});
+13 -13
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyNumber, AnyU8a, AnyString, Codec, Constructor, InterfaceTypes } from '../types';
import { AnyNumber, AnyU8a, AnyString, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { isU8a, u8aConcat, isHex, hexToU8a } from '@polkadot/util';
@@ -26,21 +26,21 @@ type TupleTypes = (Constructor | InterfaceTypes)[] | {
export default class Tuple extends AbstractArray<Codec> {
private _Types: TupleConstructors;
constructor (Types: TupleTypes, value?: any) {
constructor (registry: Registry, Types: TupleTypes, value?: any) {
const Clazzes = Array.isArray(Types)
? Types.map((type): Constructor => typeToConstructor(type))
: mapToTypeMap(Types);
? Types.map((type): Constructor => typeToConstructor(registry, type))
: mapToTypeMap(registry, Types);
super(...Tuple.decodeTuple(Clazzes, value));
super(registry, ...Tuple.decodeTuple(registry, Clazzes, value));
this._Types = Clazzes;
}
private static decodeTuple (_Types: TupleConstructors, value: AnyU8a | string | (AnyU8a | AnyNumber | AnyString | undefined | null)[]): Codec[] {
private static decodeTuple (registry: Registry, _Types: TupleConstructors, value: AnyU8a | string | (AnyU8a | AnyNumber | AnyString | undefined | null)[]): Codec[] {
if (isU8a(value)) {
return decodeU8a(value, _Types);
return decodeU8a(registry, value, _Types);
} else if (isHex(value)) {
return Tuple.decodeTuple(_Types, hexToU8a(value));
return Tuple.decodeTuple(registry, _Types, hexToU8a(value));
}
const Types: Constructor[] = Array.isArray(_Types)
@@ -49,7 +49,7 @@ export default class Tuple extends AbstractArray<Codec> {
return Types.map((Type, index): Codec => {
try {
return new Type(value && value[index]);
return new Type(registry, value && value[index]);
} catch (error) {
throw new Error(`Tuple: failed on ${index}:: ${error.message}`);
}
@@ -58,8 +58,8 @@ export default class Tuple extends AbstractArray<Codec> {
public static with (Types: TupleTypes): Constructor<Tuple> {
return class extends Tuple {
constructor (value?: any) {
super(Types, value);
constructor (registry: Registry, value?: any) {
super(registry, Types, value);
}
};
}
@@ -80,7 +80,7 @@ export default class Tuple extends AbstractArray<Codec> {
*/
public get Types (): string[] {
return Array.isArray(this._Types)
? this._Types.map((Type): string => new Type().toRawType())
? this._Types.map((Type): string => new Type(this.registry).toRawType())
: Object.keys(this._Types);
}
@@ -92,7 +92,7 @@ export default class Tuple extends AbstractArray<Codec> {
Array.isArray(this._Types)
? this._Types
: Object.values(this._Types)
).map((Type): string => new Type().toRawType());
).map((Type): string => new Type(this.registry).toRawType());
return `(${types.join(',')})`;
}
+8 -4
View File
@@ -3,18 +3,22 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { CodecTo } from '../types';
import { TypeRegistry } from './create';
import U8a from './U8a';
const registry = new TypeRegistry();
const testDecode = (type: string, input: any, expected: string): void =>
it(`can decode from ${type}`, (): void => {
const e = new U8a(input);
const e = new U8a(registry, input);
expect(e.toString()).toBe(expected);
});
const testEncode = (to: CodecTo, expected: any): void =>
it(`can encode ${to}`, (): void => {
const e = new U8a([1, 2, 3, 4, 5]);
const e = new U8a(registry, [1, 2, 3, 4, 5]);
expect(e[to]()).toEqual(expected);
});
@@ -23,7 +27,7 @@ describe('U8a', (): void => {
let u8a: U8a;
beforeEach((): void => {
u8a = new U8a([1, 2, 3, 4, 5]);
u8a = new U8a(registry, [1, 2, 3, 4, 5]);
});
testDecode('Array', [1, 2, 3, 4, 5], '0x0102030405');
@@ -46,7 +50,7 @@ describe('U8a', (): void => {
it('allows wrapping of a pre-existing instance', (): void => {
expect(
new U8a(u8a).length
new U8a(registry, u8a).length
).toEqual(5);
});
+8 -6
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyU8a, Codec, IHash } from '../types';
import { AnyU8a, Codec, IHash, Registry } from '../types';
import { isU8a, isUndefined, u8aToHex, u8aToU8a } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -17,10 +17,12 @@ import { blake2AsU8a } from '@polkadot/util-crypto';
* @noInheritDoc
*/
export default class U8a extends Uint8Array implements Codec {
constructor (value?: AnyU8a) {
super(
U8a.decodeU8a(value)
);
public readonly registry: Registry;
constructor (registry: Registry, value?: AnyU8a) {
super(U8a.decodeU8a(value));
this.registry = registry;
}
private static decodeU8a (value?: any): Uint8Array {
@@ -42,7 +44,7 @@ export default class U8a extends Uint8Array implements Codec {
* @description returns a hash of the contents
*/
public get hash (): IHash {
return new U8a(blake2AsU8a(this.toU8a(), 256));
return new U8a(this.registry, blake2AsU8a(this.toU8a(), 256));
}
/**
+8 -5
View File
@@ -2,25 +2,28 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { TypeRegistry } from './create';
import U8aFixed from './U8aFixed';
describe('U8aFixed', (): void => {
const registry = new TypeRegistry();
describe('construction', (): void => {
it('allows empty values', (): void => {
expect(
new U8aFixed().toHex()
new U8aFixed(registry).toHex()
).toEqual('0x0000000000000000000000000000000000000000000000000000000000000000');
});
it('allows construction via with', (): void => {
expect(
new (U8aFixed.with(64))().bitLength()
new (U8aFixed.with(64))(registry).bitLength()
).toEqual(64);
});
it('constructs from hex', (): void => {
expect(
new (U8aFixed.with(32))('0x01020304').toU8a()
new (U8aFixed.with(32))(registry, '0x01020304').toU8a()
).toEqual(
new Uint8Array([0x01, 0x02, 0x03, 0x04])
);
@@ -28,7 +31,7 @@ describe('U8aFixed', (): void => {
it('constructs from number[]', (): void => {
expect(
new (U8aFixed.with(32))([0x02, 0x03]).toU8a()
new (U8aFixed.with(32))(registry, [0x02, 0x03]).toU8a()
).toEqual(
new Uint8Array([0x02, 0x03, 0x00, 0x00])
);
@@ -39,7 +42,7 @@ describe('U8aFixed', (): void => {
let u8a: U8aFixed;
beforeEach((): void => {
u8a = new U8aFixed([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 32);
u8a = new U8aFixed(registry, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 32);
});
it('limits the length', (): void => {
+5 -7
View File
@@ -4,7 +4,7 @@
import { isString, u8aToU8a } from '@polkadot/util';
import { AnyU8a, Constructor } from '../types';
import { AnyU8a, Constructor, Registry } from '../types';
import U8a from './U8a';
@@ -20,10 +20,8 @@ export type BitLength = 8 | 16 | 32 | 64 | 128 | 160 | 256 | 512 | 520 | 1024 |
* to be used directly, rather is should be subclassed with the specific lengths.
*/
export default class U8aFixed extends U8a {
constructor (value: AnyU8a = new Uint8Array(), bitLength: BitLength = 256) {
super(
U8aFixed.decodeU8aFixed(value, bitLength)
);
constructor (registry: Registry, value: AnyU8a = new Uint8Array(), bitLength: BitLength = 256) {
super(registry, U8aFixed.decodeU8aFixed(value, bitLength));
}
private static decodeU8aFixed (value: AnyU8a, bitLength: BitLength): AnyU8a {
@@ -49,8 +47,8 @@ export default class U8aFixed extends U8a {
public static with (bitLength: BitLength): Constructor<U8aFixed> {
return class extends U8aFixed {
constructor (value?: any) {
super(value, bitLength);
constructor (registry: Registry, value?: any) {
super(registry, value, bitLength);
}
};
}
+14 -11
View File
@@ -4,56 +4,59 @@
import BN from 'bn.js';
import { TypeRegistry } from './create';
import UInt from './UInt';
describe('UInt', (): void => {
const registry = new TypeRegistry();
it('provides a toBn interface', (): void => {
expect(
new UInt(987).toBn().toNumber()
new UInt(registry, 987).toBn().toNumber()
).toEqual(987);
});
it('provides a toNumber interface', (): void => {
expect(
new UInt(4567).toNumber()
new UInt(registry, 4567).toNumber()
).toEqual(4567);
});
it('converts to Little Endian from the provided value', (): void => {
expect(
new UInt(1234567).toU8a()
new UInt(registry, 1234567).toU8a()
).toEqual(new Uint8Array([135, 214, 18, 0, 0, 0, 0, 0]));
});
it('converts to Little Endian from the provided value (bitLength)', (): void => {
expect(
new UInt(1234567, 32).toU8a()
new UInt(registry, 1234567, 32).toU8a()
).toEqual(new Uint8Array([135, 214, 18, 0]));
});
it('converts to hex/string', (): void => {
const u = new UInt('0x12', 16);
const u = new UInt(registry, '0x12', 16);
expect(u.toHex()).toEqual('0x0012');
expect(u.toString()).toEqual('18');
});
it('converts to equivalents', (): void => {
const a = new UInt('123');
const a = new UInt(registry, '123');
expect(
new UInt(a).toNumber()
new UInt(registry, a).toNumber()
).toEqual(123);
});
it('converts to JSON representation based on flags/size', (): void => {
expect(new UInt('0x12345678', 64, true).toJSON()).toEqual('0x0000000012345678');
expect(new UInt('0x1234567890', 64, false).toJSON()).toEqual(0x1234567890);
expect(new UInt('0x1234567890abcdef', 64, false).toJSON()).toEqual('0x1234567890abcdef');
expect(new UInt(registry, '0x12345678', 64, true).toJSON()).toEqual('0x0000000012345678');
expect(new UInt(registry, '0x1234567890', 64, false).toJSON()).toEqual(0x1234567890);
expect(new UInt(registry, '0x1234567890abcdef', 64, false).toJSON()).toEqual('0x1234567890abcdef');
});
describe('eq', (): void => {
const test = new UInt(12345);
const test = new UInt(registry, 12345);
it('compares against other BN values', (): void => {
expect(test.eq(new BN(12345))).toBe(true);
+13 -12
View File
@@ -2,11 +2,11 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyNumber } from '../types';
import { AnyNumber, Constructor, Registry } from '../types';
import { bnToHex, bnToU8a } from '@polkadot/util';
import { ClassOf } from './create';
import { ClassOf } from './create/createClass';
import AbstractInt, { DEFAULT_UINT_BITS, UIntBitLength } from './AbstractInt';
/**
@@ -20,15 +20,16 @@ import AbstractInt, { DEFAULT_UINT_BITS, UIntBitLength } from './AbstractInt';
* @noInheritDoc
*/
export default class UInt extends AbstractInt {
constructor (
value: AnyNumber = 0,
bitLength: UIntBitLength = DEFAULT_UINT_BITS, isHexJson = false) {
super(
false,
value,
bitLength,
isHexJson
);
constructor (registry: Registry, value: AnyNumber = 0, bitLength: UIntBitLength = DEFAULT_UINT_BITS, isHexJson = false) {
super(registry, false, value, bitLength, isHexJson);
}
public static with (bitLength?: UIntBitLength): Constructor<UInt> {
return class extends UInt {
constructor (registry: Registry, value?: any) {
super(registry, value, bitLength);
}
};
}
/**
@@ -50,7 +51,7 @@ export default class UInt extends AbstractInt {
// NOTE In the case of balances, which have a special meaning on the UI
// and can be interpreted differently, return a specific value for it so
// underlying it always matches (no matter which length it actually is)
return this instanceof ClassOf('Balance')
return this instanceof ClassOf(this.registry, 'Balance')
? 'Balance'
: `u${this._bitLength}`;
}
+17 -17
View File
@@ -2,8 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../injector';
import { PropIndex } from '../interfaces/democracy';
import { Codec, CodecTo } from '../types';
@@ -11,19 +9,21 @@ import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import AccountId from '../primitive/Generic/AccountId';
import Call from '../primitive/Generic/Call';
import Text from '../primitive/Text';
import { createTypeUnsafe } from './create';
import { createTypeUnsafe, TypeRegistry } from './create';
import Vec from './Vec';
import Tuple from './Tuple';
const registry = new TypeRegistry();
// eslint-disable-next-line no-new
new Metadata(registry, rpcMetadata);
describe('Vec', (): void => {
let vector: Vec<Codec>;
beforeEach((): void => {
vector = new Vec(Text, ['1', '23', '345', '4567', new Text('56789')]);
Call.injectMetadata(new Metadata(rpcMetadata));
vector = new Vec(registry, Text, ['1', '23', '345', '4567', new Text(registry, '56789')]);
});
it('wraps a sequence of values', (): void => {
@@ -45,15 +45,15 @@ describe('Vec', (): void => {
]));
});
it('allows contruction via JSON', (): void => {
it('allows construction via JSON', (): void => {
expect(
new Vec(Text, ['6', '7']).toJSON()
new Vec(registry, Text, ['6', '7']).toJSON()
).toEqual(['6', '7']);
});
it('allows contruction via JSON (string type)', (): void => {
it('allows construction via JSON (string type)', (): void => {
expect(
new Vec('u32', ['6', '7']).toJSON()
new Vec(registry, 'u32', ['6', '7']).toJSON()
).toEqual([6, 7]);
});
@@ -62,7 +62,7 @@ describe('Vec', (): void => {
});
it('decodes a complex type via construction', (): void => {
const test = createTypeUnsafe('Vec<(PropIndex, AccountId)>', [new Uint8Array([
const test = createTypeUnsafe(registry, 'Vec<(PropIndex, AccountId)>', [new Uint8Array([
4, 10, 0, 0, 0, 209, 114, 167, 76, 218, 76, 134, 89, 18, 195, 43, 160, 168, 10, 87, 174, 105, 171, 174, 65, 14, 92, 203, 89, 222, 232, 78, 47, 68, 50, 219, 79
])]);
const first = (test as Vec<Codec>)[0] as Tuple;
@@ -114,7 +114,7 @@ describe('Vec', (): void => {
it('exposes a working indexOf', (): void => {
expect(vector.indexOf('1')).toEqual(0);
expect(vector.indexOf(new Text('23'))).toEqual(1);
expect(vector.indexOf(new Text(registry, '23'))).toEqual(1);
expect(vector.indexOf('0')).toEqual(-1);
});
});
@@ -132,19 +132,19 @@ describe('Vec', (): void => {
});
describe('utils', (): void => {
const vec = new Vec(Text, ['123', '456']);
const vec = new Vec(registry, Text, ['123', '456']);
it('compares against codec types', (): void => {
expect(vec.eq([new Text('123'), new Text('456')])).toBe(true);
expect(vec.eq([new Text(registry, '123'), new Text(registry, '456')])).toBe(true);
});
it('compares against codec + primitive types', (): void => {
expect(vec.eq(['123', new Text('456')])).toBe(true);
expect(vec.eq(['123', new Text(registry, '456')])).toBe(true);
});
it('finds the index of an value', (): void => {
const myId = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY';
const vec = new Vec(AccountId, [
const vec = new Vec(registry, AccountId, [
'5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw', '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty', '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'
]);
+11 -11
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor, InterfaceTypes } from '../types';
import { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { u8aToU8a, assert } from '@polkadot/util';
@@ -22,21 +22,21 @@ const MAX_LENGTH = 32768;
export default class Vec<T extends Codec> extends AbstractArray<T> {
private _Type: Constructor<T>;
constructor (Type: Constructor<T> | InterfaceTypes, value: Vec<any> | Uint8Array | string | any[] = [] as any[]) {
const Clazz = typeToConstructor<T>(Type);
constructor (registry: Registry, Type: Constructor<T> | InterfaceTypes, value: Vec<any> | Uint8Array | string | any[] = [] as any[]) {
const Clazz = typeToConstructor<T>(registry, Type);
super(...Vec.decodeVec(Clazz, value));
super(registry, ...Vec.decodeVec(registry, Clazz, value));
this._Type = Clazz;
}
public static decodeVec<T extends Codec> (Type: Constructor<T>, value: Vec<any> | Uint8Array | string | any[]): T[] {
public static decodeVec<T extends Codec> (registry: Registry, Type: Constructor<T>, value: Vec<any> | Uint8Array | string | any[]): T[] {
if (Array.isArray(value)) {
return value.map((entry, index): T => {
try {
return entry instanceof Type
? entry
: new Type(entry);
: new Type(registry, entry);
} catch (error) {
console.error(`Unable to decode Vec on index ${index}`, error.message);
@@ -50,13 +50,13 @@ export default class Vec<T extends Codec> extends AbstractArray<T> {
assert(length.lten(MAX_LENGTH), `Vec length ${length.toString()} exceeds ${MAX_LENGTH}`);
return decodeU8a(u8a.subarray(offset), new Array(length.toNumber()).fill(Type)) as T[];
return decodeU8a(registry, u8a.subarray(offset), new Array(length.toNumber()).fill(Type)) as T[];
}
public static with<O extends Codec> (Type: Constructor<O> | InterfaceTypes): Constructor<Vec<O>> {
return class extends Vec<O> {
constructor (value?: any[]) {
super(Type, value);
constructor (registry: Registry, value?: any[]) {
super(registry, Type, value);
}
};
}
@@ -75,7 +75,7 @@ export default class Vec<T extends Codec> extends AbstractArray<T> {
// convert type first, this removes overhead from the eq
const other = _other instanceof this._Type
? _other
: new this._Type(_other);
: new this._Type(this.registry, _other);
for (let i = 0; i < this.length; i++) {
if (other.eq(this[i])) {
@@ -90,6 +90,6 @@ export default class Vec<T extends Codec> extends AbstractArray<T> {
* @description Returns the base runtime type name for this instance
*/
public toRawType (): string {
return `Vec<${new this._Type().toRawType()}>`;
return `Vec<${new this._Type(this.registry).toRawType()}>`;
}
}
+6 -3
View File
@@ -2,17 +2,20 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { TypeRegistry } from '../codec';
import Text from '../primitive/Text';
import VecFixed from './VecFixed';
describe('VecFixed', (): void => {
const registry = new TypeRegistry();
describe('construction', (): void => {
it('constructs via empty', (): void => {
expect(new VecFixed(Text, 2).toHex()).toEqual('0x0000');
expect(new VecFixed(registry, Text, 2).toHex()).toEqual('0x0000');
});
it('constructs via Uint8Array', (): void => {
expect(new VecFixed(Text, 2, new Uint8Array([0x00, 0x04, 0x31])).toHex()).toEqual('0x000431');
expect(new VecFixed(registry, Text, 2, new Uint8Array([0x00, 0x04, 0x31])).toHex()).toEqual('0x000431');
});
});
@@ -20,7 +23,7 @@ describe('VecFixed', (): void => {
let test: VecFixed<Text>;
beforeEach((): void => {
test = new (VecFixed.with(Text, 5))(['1', '2', '3', undefined, '5']);
test = new (VecFixed.with(Text, 5))(registry, ['1', '2', '3', undefined, '5']);
});
it('has a sane string types', (): void => {
+10 -9
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor, InterfaceTypes } from '../types';
import { Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { assert, isU8a, u8aConcat, compactToU8a } from '@polkadot/util';
import AbstractArray from './AbstractArray';
@@ -17,16 +17,17 @@ import Vec from './Vec';
export default class VecFixed<T extends Codec> extends AbstractArray<T> {
private _Type: Constructor<T>;
constructor (Type: Constructor<T> | InterfaceTypes, length: number, value: VecFixed<any> | Uint8Array | string | any[] = [] as any[]) {
const Clazz = typeToConstructor<T>(Type);
constructor (registry: Registry, Type: Constructor<T> | InterfaceTypes, length: number, value: VecFixed<any> | Uint8Array | string | any[] = [] as any[]) {
const Clazz = typeToConstructor<T>(registry, Type);
super(...VecFixed.decodeVecFixed(Clazz, length, value));
super(registry, ...VecFixed.decodeVecFixed(registry, Clazz, length, value));
this._Type = Clazz;
}
public static decodeVecFixed<T extends Codec> (Type: Constructor<T>, allocLength: number, value: VecFixed<any> | Uint8Array | string | any[]): T[] {
public static decodeVecFixed<T extends Codec> (registry: Registry, Type: Constructor<T>, allocLength: number, value: VecFixed<any> | Uint8Array | string | any[]): T[] {
const values = Vec.decodeVec(
registry,
Type,
isU8a(value)
? u8aConcat(compactToU8a(allocLength), value)
@@ -34,7 +35,7 @@ export default class VecFixed<T extends Codec> extends AbstractArray<T> {
);
while (values.length < allocLength) {
values.push(new Type());
values.push(new Type(registry));
}
assert(values.length === allocLength, `Expected a length of exactly ${allocLength} entries`);
@@ -44,8 +45,8 @@ export default class VecFixed<T extends Codec> extends AbstractArray<T> {
public static with<O extends Codec> (Type: Constructor<O> | InterfaceTypes, length: number): Constructor<VecFixed<O>> {
return class extends VecFixed<O> {
constructor (value?: any[]) {
super(Type, length, value);
constructor (registry: Registry, value?: any[]) {
super(registry, Type, length, value);
}
};
}
@@ -54,7 +55,7 @@ export default class VecFixed<T extends Codec> extends AbstractArray<T> {
* @description The type for the items
*/
public get Type (): string {
return new this._Type().toRawType();
return new this._Type(this.registry).toRawType();
}
public toU8a (): Uint8Array {
@@ -2,22 +2,22 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { createClass } from '.';
import { createClass, TypeRegistry } from '.';
describe('createClass', (): void => {
const registry = new TypeRegistry();
it('should memoize from strings', (): void => {
const a = createClass('BabeWeight');
const b = createClass('BabeWeight');
const a = createClass(registry, 'BabeWeight');
const b = createClass(registry, 'BabeWeight');
expect(a).toBe(b);
});
it('should return equivalents for Bytes & Vec<u8>', (): void => {
const A = createClass('Vec<u8>');
const B = createClass('Bytes');
const A = createClass(registry, 'Vec<u8>');
const B = createClass(registry, 'Bytes');
expect(new A() instanceof B).toBe(true);
expect(new A(registry) instanceof B).toBe(true);
});
});
+9 -11
View File
@@ -2,29 +2,27 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor, InterfaceTypes } from '../../types';
import { Codec, Constructor, InterfaceTypes, Registry } from '../../types';
import { FromReg } from './types';
import { InterfaceRegistry } from '../../interfaceRegistry';
import { getTypeClass } from './getTypeClass';
import { getTypeDef } from './getTypeDef';
export function createClass<T extends Codec = Codec, K extends string = string> (
type: K
): Constructor<FromReg<T, K>> {
return getTypeClass<FromReg<T, K>>(getTypeDef(type));
export function createClass<T extends Codec = Codec, K extends string = string> (registry: Registry, type: K): Constructor<FromReg<T, K>> {
return getTypeClass<FromReg<T, K>>(registry, getTypeDef(type));
}
// An unsafe version of the `createType` below. It's unsafe because the `type`
// argument here can be any string, which, if not parseable, will yield a
// runtime error.
export function ClassOfUnsafe<T extends Codec = Codec, K extends string = string> (name: K): Constructor<FromReg<T, K>> {
return createClass<T, K>(name);
// argument here can be any string, which, if it cannot be parsed, it will yield
// a runtime error.
export function ClassOfUnsafe<T extends Codec = Codec, K extends string = string> (registry: Registry, name: K): Constructor<FromReg<T, K>> {
return createClass<T, K>(registry, name);
}
// alias for createClass
export function ClassOf<K extends InterfaceTypes> (name: K): Constructor<InterfaceRegistry[K]> {
export function ClassOf<K extends InterfaceTypes> (registry: Registry, name: K): Constructor<InterfaceRegistry[K]> {
// TS2589: Type instantiation is excessively deep and possibly infinite.
// The above happens with as Constructor<InterfaceRegistry[K]>;
return ClassOfUnsafe<Codec, K>(name) as any;
return ClassOfUnsafe<Codec, K>(registry, name) as any;
}
@@ -2,15 +2,15 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { createClass, createType, createTypeUnsafe, getTypeRegistry, ClassOf } from '.';
import { createClass, createType, createTypeUnsafe, ClassOf, TypeRegistry } from '.';
import CodecSet from '../Set';
describe('createType', (): void => {
const registry = new TypeRegistry();
it('allows creation of a Struct', (): void => {
expect(
createTypeUnsafe('{"balance":"Balance","index":"u32"}', [{
createTypeUnsafe(registry, '{"balance":"Balance","index":"u32"}', [{
balance: 1234,
index: '0x10'
}]).toJSON()
@@ -22,68 +22,68 @@ describe('createType', (): void => {
it('allows creation of a BTreeMap', (): void => {
expect(
createTypeUnsafe('BTreeMap<Text,u32>', ['0x041c62617a7a696e6745000000']).toString()
createTypeUnsafe(registry, 'BTreeMap<Text,u32>', ['0x041c62617a7a696e6745000000']).toString()
).toEqual('{"bazzing":69}');
});
it('allows creation of a Result', (): void => {
expect(
createTypeUnsafe('Result<u32,Text>', ['0x011064656667']).toJSON()
createTypeUnsafe(registry, 'Result<u32,Text>', ['0x011064656667']).toJSON()
).toEqual({ Error: 'defg' });
});
it('allows creation of a Tuple', (): void => {
expect(
createTypeUnsafe('(Balance,u32)', [[1234, 5678]]).toJSON()
createTypeUnsafe(registry, '(Balance,u32)', [[1234, 5678]]).toJSON()
).toEqual([1234, 5678]);
});
it('allows creation of a Enum (simple)', (): void => {
expect(
createTypeUnsafe('{"_enum": ["A", "B", "C"]}', [1]).toJSON()
createTypeUnsafe(registry, '{"_enum": ["A", "B", "C"]}', [1]).toJSON()
).toEqual(1);
});
it('allows creation of a Enum (parametrised)', (): void => {
expect(
createTypeUnsafe('{"_enum": {"A": null, "B": "u32", "C": null} }', [1]).toJSON()
createTypeUnsafe(registry, '{"_enum": {"A": null, "B": "u32", "C": null} }', [1]).toJSON()
).toEqual({ B: 0 });
});
it('allows creation of a Set', (): void => {
expect(
createTypeUnsafe<CodecSet>('{"_set": { "A": 1, "B": 2, "C": 4, "D": 8, "E": 16, "G": 32, "H": 64, "I": 128 } }', [1 + 4 + 16 + 64]).strings
createTypeUnsafe<CodecSet>(registry, '{"_set": { "A": 1, "B": 2, "C": 4, "D": 8, "E": 16, "G": 32, "H": 64, "I": 128 } }', [1 + 4 + 16 + 64]).strings
).toEqual(['A', 'C', 'E', 'H']);
});
it('allows creation of a [u8; 8]', (): void => {
expect(
createTypeUnsafe('[u8; 8]', [[0x12, 0x00, 0x23, 0x00, 0x45, 0x00, 0x67, 0x00]]).toHex()
createTypeUnsafe(registry, '[u8; 8]', [[0x12, 0x00, 0x23, 0x00, 0x45, 0x00, 0x67, 0x00]]).toHex()
).toEqual('0x1200230045006700');
});
it('allows creation of a [u16; 4]', (): void => {
expect(
createTypeUnsafe('[u16; 4]', [[0x1200, 0x2300, 0x4500, 0x6700]]).toU8a()
createTypeUnsafe(registry, '[u16; 4]', [[0x1200, 0x2300, 0x4500, 0x6700]]).toU8a()
).toEqual(new Uint8Array([0x00, 0x12, 0x00, 0x23, 0x00, 0x45, 0x00, 0x67]));
});
describe('instanceof', (): void => {
it('instanceof should work (primitive type)', (): void => {
const value = createType('Balance', 1234);
const value = createType(registry, 'Balance', 1234);
expect(value instanceof ClassOf('Balance')).toBe(true);
expect(value instanceof ClassOf(registry, 'Balance')).toBe(true);
});
it('instanceof should work (srml type)', (): void => {
const value = createType('Gas', 1234);
const Gas = ClassOf('Gas');
const value = createType(registry, 'Gas', 1234);
const Gas = ClassOf(registry, 'Gas');
expect(value instanceof Gas).toBe(true);
});
it('instanceof should work (complex type)', (): void => {
getTypeRegistry().register({
registry.register({
TestComplex: {
balance: 'Balance',
accountId: 'AccountId',
@@ -92,32 +92,32 @@ describe('createType', (): void => {
}
});
const value = createTypeUnsafe('TestComplex', [{
const value = createTypeUnsafe(registry, 'TestComplex', [{
balance: 123,
accountId: '0x1234567812345678123456781234567812345678123456781234567812345678',
log: [456, 789],
fromSrml: 0
}]);
expect(value instanceof createClass('TestComplex')).toBe(true);
expect(value instanceof createClass(registry, 'TestComplex')).toBe(true);
});
it('allows for re-registration of a type', (): void => {
const balDef = createType('Balance');
const balDef = createType(registry, 'Balance');
expect(balDef instanceof ClassOf('Balance'));
expect(balDef instanceof ClassOf(registry, 'Balance'));
expect(balDef.bitLength()).toEqual(128);
getTypeRegistry().register({ Balance: 'u32' });
registry.register({ Balance: 'u32' });
const balu32 = createType('Balance');
const balu32 = createType(registry, 'Balance');
expect(balu32 instanceof ClassOf('Balance'));
expect(balu32 instanceof ClassOf(registry, 'Balance'));
expect(balu32.bitLength()).toEqual(32);
});
it('allows for re-registration of a type (affecting derives)', (): void => {
getTypeRegistry().register({
registry.register({
Balance: 'u128',
TestComplex: {
balance: 'Balance',
@@ -127,13 +127,13 @@ describe('createType', (): void => {
}
});
const cmpDef: any = createTypeUnsafe('TestComplex');
const cmpDef: any = createTypeUnsafe(registry, 'TestComplex');
expect(cmpDef.balance.bitLength()).toEqual(128);
getTypeRegistry().register({ Balance: 'u32' });
registry.register({ Balance: 'u32' });
const cmpu32: any = createTypeUnsafe('TestComplex');
const cmpu32: any = createTypeUnsafe(registry, 'TestComplex');
expect(cmpu32.balance.bitLength()).toEqual(32);
});
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor, InterfaceTypes } from '../../types';
import { Codec, Constructor, InterfaceTypes, Registry } from '../../types';
import { FromReg } from './types';
import { isU8a, u8aToHex } from '@polkadot/util';
@@ -43,8 +43,8 @@ function checkInstance<T extends Codec = Codec, K extends string = string> (valu
// Initializes a type with a value. This also checks for fallbacks and in the cases
// where isPedantic is specified (storage decoding), also check the format/structure
function initType<T extends Codec = Codec, K extends string = string> (Type: Constructor<FromReg<T, K>>, params: any[] = [], isPedantic?: boolean): FromReg<T, K> {
const created = new Type(...params);
function initType<T extends Codec = Codec, K extends string = string> (registry: Registry, Type: Constructor<FromReg<T, K>>, params: any[] = [], isPedantic?: boolean): FromReg<T, K> {
const created = new Type(registry, ...params);
const [value] = params;
if (isPedantic && isU8a(value)) {
@@ -57,9 +57,9 @@ function initType<T extends Codec = Codec, K extends string = string> (Type: Con
// An unsafe version of the `createType` below. It's unsafe because the `type`
// argument here can be any string, which, if not parseable, will yield a
// runtime error.
export function createTypeUnsafe<T extends Codec = Codec, K extends string = string> (type: K, params: any[] = [], isPedantic?: boolean): FromReg<T, K> {
export function createTypeUnsafe<T extends Codec = Codec, K extends string = string> (registry: Registry, type: K, params: any[] = [], isPedantic?: boolean): FromReg<T, K> {
try {
return initType(createClass<T, K>(type), params, isPedantic);
return initType(registry, createClass<T, K>(registry, type), params, isPedantic);
} catch (error) {
throw new Error(`createType(${type}):: ${error.message}`);
}
@@ -71,8 +71,8 @@ export function createTypeUnsafe<T extends Codec = Codec, K extends string = str
* instance from
* @param params - The value to instantiate the type with
*/
export function createType<K extends InterfaceTypes> (type: K, ...params: any[]): InterfaceRegistry[K] {
export function createType<K extends InterfaceTypes> (registry: Registry, type: K, ...params: any[]): InterfaceRegistry[K] {
// error TS2589: Type instantiation is excessively deep and possibly infinite.
// The above happens with as Constructor<InterfaceRegistry[K]>;
return createTypeUnsafe<Codec, K>(type, params) as any;
return createTypeUnsafe<Codec, K>(registry, type, params) as any;
}
@@ -2,16 +2,16 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { Codec, Constructor } from '../../types';
import { getTypeClass } from '.';
import { getTypeClass, TypeRegistry } from '.';
describe('getTypeClass', (): void => {
const registry = new TypeRegistry();
it('does not allow invalid types', (): void => {
expect(
(): Constructor<Codec> => getTypeClass('SomethingInvalid' as any)
(): Constructor<Codec> => getTypeClass(registry, 'SomethingInvalid' as any)
).toThrow(/determine type/);
});
});
+21 -22
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor, InterfaceTypes } from '../../types';
import { Codec, Constructor, InterfaceTypes, Registry } from '../../types';
import { TypeDef, TypeDefExtVecFixed, TypeDefInfo } from './types';
import { assert } from '@polkadot/util';
@@ -20,7 +20,6 @@ import U8aFixed, { BitLength as U8aFixedBitLength } from '../U8aFixed';
import Vec from '../Vec';
import VecFixed from '../VecFixed';
import { ClassOf } from './createClass';
import { getTypeRegistry } from './registry';
function getSubDefArray (value: TypeDef): TypeDef[] {
assert(value.sub && Array.isArray(value.sub), `Expected subtype as TypeDef[] in ${JSON.stringify(value)}`);
@@ -56,39 +55,39 @@ function getTypeClassArray (value: TypeDef): (InterfaceTypes)[] {
);
}
const infoMapping: Record<TypeDefInfo, (value: TypeDef) => Constructor> = {
[TypeDefInfo.BTreeMap]: (value: TypeDef): Constructor => {
const infoMapping: Record<TypeDefInfo, (registry: Registry, value: TypeDef) => Constructor> = {
[TypeDefInfo.BTreeMap]: (registry: Registry, value: TypeDef): Constructor => {
const [keyType, valueType] = getTypeClassArray(value);
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return BTreeMap.with(keyType, valueType);
},
[TypeDefInfo.Compact]: (value: TypeDef): Constructor => Compact.with(getSubType(value)),
[TypeDefInfo.Compact]: (registry: Registry, value: TypeDef): Constructor => Compact.with(getSubType(value)),
// eslint-disable-next-line @typescript-eslint/no-use-before-define
[TypeDefInfo.DoubleMap]: (value: TypeDef): Constructor => getTypeClass(getSubDef(value)),
[TypeDefInfo.DoubleMap]: (registry: Registry, value: TypeDef): Constructor => getTypeClass(registry, getSubDef(value)),
[TypeDefInfo.Enum]: (value: TypeDef): Constructor => Enum.with(getTypeClassMap(value)),
[TypeDefInfo.Enum]: (registry: Registry, value: TypeDef): Constructor => Enum.with(getTypeClassMap(value)),
[TypeDefInfo.Linkage]: (value: TypeDef): Constructor => Linkage.withKey(getSubType(value)),
[TypeDefInfo.Linkage]: (registry: Registry, value: TypeDef): Constructor => Linkage.withKey(getSubType(value)),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[TypeDefInfo.Null]: (_: TypeDef): Constructor => ClassOf('Null'),
[TypeDefInfo.Null]: (registry: Registry, _: TypeDef): Constructor => ClassOf(registry, 'Null'),
[TypeDefInfo.Option]: (value: TypeDef): Constructor => Option.with(getSubType(value)),
[TypeDefInfo.Option]: (registry: Registry, value: TypeDef): Constructor => Option.with(getSubType(value)),
[TypeDefInfo.Plain]: (value: TypeDef): Constructor =>
getTypeRegistry().getOrThrow(value.type, `Unable to find plain type for ${JSON.stringify(value)}`),
[TypeDefInfo.Plain]: (registry: Registry, value: TypeDef): Constructor =>
registry.getOrThrow(value.type, `Unable to find plain type for ${JSON.stringify(value)}`),
[TypeDefInfo.Result]: (value: TypeDef): Constructor => {
[TypeDefInfo.Result]: (registry: Registry, value: TypeDef): Constructor => {
const [Ok, Error] = getTypeClassArray(value);
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return Result.with({ Ok, Error });
},
[TypeDefInfo.Set]: (value: TypeDef): Constructor => {
[TypeDefInfo.Set]: (registry: Registry, value: TypeDef): Constructor => {
const result: Record<string, number> = {};
return CodecSet.with(
@@ -100,21 +99,21 @@ const infoMapping: Record<TypeDefInfo, (value: TypeDef) => Constructor> = {
);
},
[TypeDefInfo.Struct]: (value: TypeDef): Constructor => Struct.with(getTypeClassMap(value)),
[TypeDefInfo.Struct]: (registry: Registry, value: TypeDef): Constructor => Struct.with(getTypeClassMap(value)),
[TypeDefInfo.Tuple]: (value: TypeDef): Constructor => Tuple.with(getTypeClassArray(value)),
[TypeDefInfo.Tuple]: (registry: Registry, value: TypeDef): Constructor => Tuple.with(getTypeClassArray(value)),
[TypeDefInfo.Vec]: (value: TypeDef): Constructor => {
[TypeDefInfo.Vec]: (registry: Registry, value: TypeDef): Constructor => {
const subType = getSubType(value);
return (
subType === 'u8'
? ClassOf('Bytes')
? ClassOf(registry, 'Bytes')
: Vec.with(subType)
);
},
[TypeDefInfo.VecFixed]: (value: TypeDef): Constructor => {
[TypeDefInfo.VecFixed]: (registry: Registry, value: TypeDef): Constructor => {
assert(value.ext, 'Expected length & type information for fixed vector');
const ext = value.ext as TypeDefExtVecFixed;
@@ -128,8 +127,8 @@ const infoMapping: Record<TypeDefInfo, (value: TypeDef) => Constructor> = {
};
// Returns the type Class for construction
export function getTypeClass<T extends Codec = Codec> (value: TypeDef): Constructor<T> {
const Type = getTypeRegistry().get<T>(value.type);
export function getTypeClass<T extends Codec = Codec> (registry: Registry, value: TypeDef): Constructor<T> {
const Type = registry.get<T>(value.type);
if (Type) {
return Type;
@@ -141,5 +140,5 @@ export function getTypeClass<T extends Codec = Codec> (value: TypeDef): Construc
throw new Error(`Unable to determine type from ${JSON.stringify(value)}`);
}
return getFn(value) as Constructor<T>;
return getFn(registry, value) as Constructor<T>;
}
@@ -2,8 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { TypeDef, TypeDefInfo } from '../types';
import { getTypeDef } from '.';
@@ -2,11 +2,9 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { Constructor } from '../../types';
import { TypeRegistry, getTypeRegistry } from './registry';
import { TypeRegistry } from './registry';
import Struct from '../Struct';
import Text from '../../primitive/Text';
import U32 from '../../primitive/U32';
@@ -20,11 +18,7 @@ function isChildClass (Parent: Constructor<any>, Child?: Constructor<any>): bool
}
describe('TypeRegistry', (): void => {
let registry: TypeRegistry;
beforeEach((): void => {
registry = getTypeRegistry();
});
const registry = new TypeRegistry();
it('handles non exist type', (): void => {
expect(registry.get('non-exist')).toBeUndefined();
@@ -64,8 +58,8 @@ describe('TypeRegistry', (): void => {
expect(registry.hasClass('Recursive')).toBe(true);
const last = new Recursive({ next: null });
const first = new Recursive({ next: last });
const last = new Recursive(registry, { next: null });
const first = new Recursive(registry, { next: last });
expect((first as any).next.isSome).toBe(true);
expect((first as any).next.unwrap().next.isSome).toBe(false);
@@ -89,8 +83,8 @@ describe('TypeRegistry', (): void => {
expect(registry.hasClass('Recursive')).toBe(true);
const last = new B({ End: null });
const first = new B({ Other: new A({ next: last }) });
const last = new B(registry, { End: null });
const first = new B(registry, { Other: new A(registry, { next: last }) });
expect((first as any).isOther).toBe(true);
});
@@ -102,7 +96,7 @@ describe('TypeRegistry', (): void => {
const Type = registry.getOrThrow('U32Renamed');
expect(new Type() instanceof U32).toBe(true);
expect(new Type(registry) instanceof U32).toBe(true);
});
it('can create structs via definition', (): void => {
@@ -113,8 +107,8 @@ describe('TypeRegistry', (): void => {
}
});
const SomeStruct: any = registry.get('SomeStruct');
const struct: any = new SomeStruct({
const SomeStruct = registry.getOrThrow('SomeStruct');
const struct: any = new SomeStruct(registry, {
foo: 42,
bar: 'testing'
});
+108 -40
View File
@@ -1,60 +1,60 @@
/* eslint-disable @typescript-eslint/no-var-requires */
// Copyright 2017-2019 @polkadot/types authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor, RegistryTypes } from '../../types';
import { CallFunction, Codec, Constructor, RegistryTypes, Registry, RegistryMetadata, TypeDef } from '../../types';
import { isFunction, isString, isUndefined } from '@polkadot/util';
import extrinsicsFromMeta from '@polkadot/metadata/Decorated/extrinsics/fromMetadata';
import { assert, isFunction, isString, isUndefined, stringCamelCase, u8aToHex } from '@polkadot/util';
import { EventData } from '../../primitive/Generic/Event';
import { createClass } from './createClass';
import { getTypeClass } from './getTypeClass';
import { getTypeDef } from './getTypeDef';
export class TypeRegistry {
public static readonly defaultRegistry: TypeRegistry = new TypeRegistry();
const FN_UNKNOWN: Partial<CallFunction> = {
method: 'unknown',
section: 'unknown'
};
export class TypeRegistry implements Registry {
private _classes: Map<string, Constructor> = new Map();
private _definitions: Map<string, string> = new Map();
public register (type: Constructor | RegistryTypes): void;
private _metadataCalls: Record<string, CallFunction> = {};
// eslint-disable-next-line no-dupe-class-members
public register (name: string, type: Constructor): void;
private _metadataEvents: Record<string, Constructor<EventData>> = {};
// eslint-disable-next-line no-dupe-class-members
public register (arg1: string | Constructor | RegistryTypes, arg2?: Constructor): void {
if (isString(arg1)) {
const name = arg1;
const type = arg2!;
constructor () {
// we only want to import these on creation, i.e. we want to avoid types
// weird side-effects from circular references. (Since registry is injected
// into types, this can be a real concern now)
const baseTypes: RegistryTypes = require('../../index.types');
const definitions: Record<string, { types: RegistryTypes }> = require('../../interfaces/definitions');
this._classes.set(name, type);
} else if (isFunction(arg1)) {
const name = arg1.name;
const type = arg1;
// since these are classes, they are injected first
this.register({ ...baseTypes });
this._classes.set(name, type);
} else {
this.registerObject(arg1);
}
// since these are definitions, they would only get created when needed
Object.values(definitions).forEach(({ types }): void =>
this.register(types)
);
}
private registerObject (obj: RegistryTypes): void {
Object.entries(obj).forEach(([name, type]): void => {
if (isFunction(type)) {
// This _looks_ a bit funny, but `typeof Clazz === 'function'
this._classes.set(name, type);
} else {
const def = isString(type)
? type
: JSON.stringify(type);
public findMetaCall (callIndex: Uint8Array): CallFunction {
assert(Object.keys(this._metadataCalls).length > 0, 'Calling registry.findMetaCall before metadata has been attached.');
// we already have this type, remove the classes registered for it
if (this._classes.has(name)) {
this._classes.delete(name);
}
return this._metadataCalls[callIndex.toString()] || FN_UNKNOWN;
}
this._definitions.set(name, def);
}
});
public findMetaEvent (eventIndex: Uint8Array): Constructor<EventData> {
const Event = this._metadataEvents[eventIndex.toString()];
assert(!isUndefined(Event), `Unable to find Event with index ${u8aToHex(eventIndex)}`);
return Event;
}
public get <T extends Codec = Codec> (name: string): Constructor<T> | undefined {
@@ -66,10 +66,11 @@ export class TypeRegistry {
// we have a definition, so create the class now (lazily)
if (definition) {
const BaseType = createClass(definition);
const BaseType = createClass(this, definition);
// NOTE If we didn't extend here, we would have strange artifacts. An example is
// Balance, with this, new Balance() instanceof u128 is true, but Balance !== u128
// Additionally, we now pass through the registry, which is a link to ourselves
Type = class extends BaseType {};
this._classes.set(name, Type);
@@ -104,8 +105,75 @@ export class TypeRegistry {
public hasType (name: string): boolean {
return this.hasClass(name) || this.hasDef(name);
}
}
export function getTypeRegistry (): TypeRegistry {
return TypeRegistry.defaultRegistry;
public register (type: Constructor | RegistryTypes): void;
// eslint-disable-next-line no-dupe-class-members
public register (name: string, type: Constructor): void;
// eslint-disable-next-line no-dupe-class-members
public register (arg1: string | Constructor | RegistryTypes, arg2?: Constructor): void {
// NOTE Constructors appear as functions here
if (isFunction(arg1)) {
this._classes.set(arg1.name, arg1);
} else if (isString(arg1)) {
assert(isFunction(arg2), `Expected class definition passed to '${arg1}' registration`);
this._classes.set(arg1, arg2);
} else {
this.registerObject(arg1);
}
}
private registerObject (obj: RegistryTypes): void {
Object.entries(obj).forEach(([name, type]): void => {
if (isFunction(type)) {
// This _looks_ a bit funny, but `typeof Clazz === 'function'
this._classes.set(name, type);
} else {
const def = isString(type)
? type
: JSON.stringify(type);
// we already have this type, remove the classes registered for it
if (this._classes.has(name)) {
this._classes.delete(name);
}
this._definitions.set(name, def);
}
});
}
// sets the metadata
public setMetadata (metadata: RegistryMetadata): void {
const extrinsics = extrinsicsFromMeta(this, metadata);
// decorate the extrinsics
Object.values(extrinsics).forEach((methods): void =>
Object.values(methods).forEach((method): void => {
this._metadataCalls[method.callIndex.toString()] = method;
})
);
// decorate the events
metadata.asLatest.modules
.filter(({ events }): boolean => events.isSome)
.forEach((section, sectionIndex): void => {
const sectionName = stringCamelCase(section.name.toString());
section.events.unwrap().forEach((meta, methodIndex): void => {
const methodName = meta.name.toString();
const eventIndex = new Uint8Array([sectionIndex, methodIndex]);
const typeDef = meta.args.map((arg): TypeDef => getTypeDef(arg.toString()));
const Types = typeDef.map((typeDef): Constructor<Codec> => getTypeClass(this, typeDef));
this._metadataEvents[eventIndex.toString()] = class extends EventData {
constructor (registry: Registry, value: Uint8Array) {
super(registry, Types, value, typeDef, meta, sectionName, methodName);
}
};
});
});
}
}
@@ -2,8 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { typeSplit } from '.';
describe('typeSplit', (): void => {
@@ -2,11 +2,13 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { TypeRegistry } from '../create';
import U32 from '../../primitive/U32';
import compareArray from './compareArray';
describe('compareArray', (): void => {
const a = [new U32(123), new U32(456), new U32(789)];
const registry = new TypeRegistry();
const a = [new U32(registry, 123), new U32(registry, 456), new U32(registry, 789)];
it('returns false when second param is a non-array', (): void => {
expect(
@@ -22,7 +24,7 @@ describe('compareArray', (): void => {
it('compares array of codec agains codec', (): void => {
expect(
compareArray(a, [new U32(123), new U32(456), new U32(789)])
compareArray(a, [new U32(registry, 123), new U32(registry, 456), new U32(registry, 789)])
).toBe(true);
});
@@ -3,14 +3,16 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec } from '../../types';
import { TypeRegistry } from '../create';
import U32 from '../../primitive/U32';
import compareMap from './compareMap';
describe('compareMap', (): void => {
const registry = new TypeRegistry();
const a = new Map<string, Codec>([
['decimals', new U32(15)],
['missing', new U32(10)],
['foobar', new U32(5)]
['decimals', new U32(registry, 15)],
['missing', new U32(registry, 10)],
['foobar', new U32(registry, 5)]
]);
const b = new Map<string, any>([
['decimals', 15],
@@ -18,9 +20,9 @@ describe('compareMap', (): void => {
['foobar', 5]
]);
const c = new Map<string, Codec>([
['decimals', new U32(15)],
['missing', new U32(10)],
['foobar', new U32(5)]
['decimals', new U32(registry, 15)],
['missing', new U32(registry, 10)],
['foobar', new U32(registry, 5)]
]);
it('compares Map<string, Codec> against Object', (): void => {
+4 -4
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor } from '../../types';
import { Codec, Constructor, Registry } from '../../types';
/**
* Given an u8a, and an array of Type constructors, decode the u8a against the
@@ -11,7 +11,7 @@ import { Codec, Constructor } from '../../types';
* @param u8a - The u8a to decode.
* @param types - The array of Constructor to decode the U8a against.
*/
export default function decodeU8a (u8a: Uint8Array, _types: Constructor[] | { [index: string]: Constructor }): Codec[] {
export default function decodeU8a (registry: Registry, u8a: Uint8Array, _types: Constructor[] | { [index: string]: Constructor }): Codec[] {
const types = Array.isArray(_types)
? _types
: Object.values(_types);
@@ -21,7 +21,7 @@ export default function decodeU8a (u8a: Uint8Array, _types: Constructor[] | { [i
}
const Type = types[0];
const value = new Type(u8a);
const value = new Type(registry, u8a);
return [value].concat(decodeU8a(u8a.subarray(value.encodedLength), types.slice(1)));
return [value].concat(decodeU8a(registry, u8a.subarray(value.encodedLength), types.slice(1)));
}
+11 -11
View File
@@ -2,29 +2,29 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Constructor, InterfaceTypes } from '../../types';
import { Codec, Constructor, InterfaceTypes, Registry } from '../../types';
import { isString } from '@polkadot/util';
import { ClassOf } from '../create';
export function typeToConstructor <T = Codec> (type: InterfaceTypes | Constructor<T>): Constructor<T> {
export function typeToConstructor <T = Codec> (registry: Registry, type: InterfaceTypes | Constructor<T>): Constructor<T> {
return (
isString(type)
? ClassOf(type)
? ClassOf(registry, type)
: type
) as Constructor<T>;
}
/**
* @description takes an input map of the form `{ [string]: string | Constructor }` and returns a map of `{ [string]: Conbstructor }`
* @description takes an input map of the form `{ [string]: string | Constructor }` and returns a map of `{ [string]: Constructor }`
*/
export function mapToTypeMap (input: Record<string, InterfaceTypes | Constructor>): Record<string, Constructor> {
const output: Record<string, Constructor> = {};
export function mapToTypeMap (registry: Registry, input: Record<string, InterfaceTypes | Constructor>): Record<string, Constructor> {
return Object
.entries(input)
.reduce((output: Record<string, Constructor>, [key, type]): Record<string, Constructor> => {
output[key] = typeToConstructor(registry, type);
Object.entries(input).forEach(([key, type]): void => {
output[key] = typeToConstructor(type);
});
return output;
return output;
}, {});
}
+7 -7
View File
@@ -2,13 +2,10 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import './injector';
import Metadata from '@polkadot/metadata/Metadata';
import metadataStatic from '@polkadot/metadata/Metadata/static';
import { createTypeUnsafe } from './codec/create';
import GenericCall from './primitive/Generic/Call';
import { createTypeUnsafe, TypeRegistry } from './codec/create';
import { Codec } from './types';
import * as exported from './index.types';
import * as definitions from './interfaces/definitions';
@@ -24,13 +21,15 @@ const UNCONSTRUCTABLE = [
'usize'
].map((v): string => v.toLowerCase());
const registry = new TypeRegistry();
function testTypes (type: string, typeNames: string[]): void {
describe(type, (): void => {
describe(`${type}:: default creation`, (): void => {
typeNames.forEach((name): void => {
it(`creates an empty ${name}`, (): void => {
const constructFn = (): Codec =>
createTypeUnsafe(name);
createTypeUnsafe(registry, name);
if (UNCONSTRUCTABLE.includes(name.toLowerCase())) {
expect(constructFn).toThrow();
@@ -42,12 +41,13 @@ function testTypes (type: string, typeNames: string[]): void {
});
describe(`${type}:: default creation (empty bytes)`, (): void => {
GenericCall.injectMetadata(new Metadata(metadataStatic));
// eslint-disable-next-line no-new
new Metadata(registry, metadataStatic);
typeNames.forEach((name): void => {
it(`creates an empty ${name} (from empty bytes)`, (): void => {
const constructFn = (): Codec =>
createTypeUnsafe(name, [createTypeUnsafe('Bytes')]);
createTypeUnsafe(registry, name, [createTypeUnsafe(registry, 'Bytes')]);
if (UNCONSTRUCTABLE.includes(name.toLowerCase())) {
expect(constructFn).toThrow();
-12
View File
@@ -7,18 +7,6 @@
import { assertSingletonPackage } from '@polkadot/util';
// HACK Register our types before anything else - if just means that any use of
// createType (either here, like in derive) or in users of this app, will have
// the type available without resorting to juggling imports themselves.
//
// This was found here in api-derive (see ReferendumInfoExtended) as well in apps,
// where `createType` was used on constant definitions, but before the actual API
// has been injected (which registers the srml types).
//
// It needs resolution, but atm, no worse than having classes that are statically
// defined, so really, eating the elephant one bite at a time...
import './injector';
assertSingletonPackage('@polkadot/types');
export * from './codec';
-24
View File
@@ -1,24 +0,0 @@
// Copyright 2017-2019 @polkadot/types authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { getTypeRegistry } from './codec/create';
import * as definitions from './interfaces/definitions';
import * as baseTypes from './index.types';
/**
* @description A utility method that injects all the srml definitions into the type registry
*/
export function injectTypes (): void {
const registry = getTypeRegistry();
// since these are classes, the are active immediately
registry.register({ ...baseTypes });
// since these are definitions, they would only get created when needed
Object.values(definitions).forEach(({ types }): void =>
registry.register(types)
);
}
injectTypes();
@@ -2,19 +2,19 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { createType } from '../../codec/create';
import { createType, TypeRegistry } from '../../codec/create';
describe('ChainProperties', (): void => {
const registry = new TypeRegistry();
it('decodes from a null value', (): void => {
expect(
[...createType('ChainProperties', null).entries()]
[...createType(registry, 'ChainProperties', null).entries()]
).toEqual([]);
});
it('decodes from an actual object', (): void => {
const { ss58Format, tokenDecimals, tokenSymbol } = createType('ChainProperties', {
const { ss58Format, tokenDecimals, tokenSymbol } = createType(registry, 'ChainProperties', {
ss58Format: 2,
tokenDecimals: 15,
tokenSymbol: 'KSM'
@@ -26,7 +26,7 @@ describe('ChainProperties', (): void => {
});
it('decodes from an object, flagged for non-existent ss58Format', (): void => {
const { ss58Format, tokenDecimals, tokenSymbol } = createType('ChainProperties', { tokenSymbol: 'DEV' });
const { ss58Format, tokenDecimals, tokenSymbol } = createType(registry, 'ChainProperties', { tokenSymbol: 'DEV' });
expect(ss58Format.isNone).toBe(true);
expect(tokenDecimals.isNone).toBe(true);
@@ -2,18 +2,17 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { ExtrinsicStatus } from './types';
import { createType } from '../../codec/create';
import { createType, TypeRegistry } from '../../codec/create';
import rpc from '../../json/ExtrinsicStatus.001.json';
describe('ExtrinsicStatus', (): void => {
const registry = new TypeRegistry();
let status: ExtrinsicStatus;
beforeEach((): void => {
status = createType('ExtrinsicStatus', rpc.params.result);
status = createType(registry, 'ExtrinsicStatus', rpc.params.result);
});
it('has the correct type', (): void => {
@@ -2,13 +2,13 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { createType } from '../../codec/create';
import { createType, TypeRegistry } from '../../codec/create';
describe('KeyValueOption', (): void => {
const registry = new TypeRegistry();
it('exposes the properties for key/value', (): void => {
const [key, value] = createType('KeyValueOption', [
const [key, value] = createType(registry, 'KeyValueOption', [
'0x11223344'
]);
@@ -2,18 +2,17 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { RuntimeVersion } from './types';
import { createType } from '../../codec/create';
import { createType, TypeRegistry } from '../../codec/create';
import rpc from '../../json/RuntimeVersion.002.json';
describe('RuntimeVersion', (): void => {
const registry = new TypeRegistry();
let version: RuntimeVersion;
beforeEach((): void => {
version = createType('RuntimeVersion', rpc.result);
version = createType(registry, 'RuntimeVersion', rpc.result);
});
it('has the correct authoring', (): void => {
@@ -2,15 +2,15 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { createType } from '@polkadot/types';
import { createType, TypeRegistry } from '@polkadot/types';
import json from '../../json/StorageChangeSet.001.json';
describe('StorageChangeSet', (): void => {
const registry = new TypeRegistry();
describe('construction', (): void => {
const set = createType('StorageChangeSet', {
const set = createType(registry, 'StorageChangeSet', {
block: '0x1234',
changes: [
['0xab', '0xcd']
@@ -31,7 +31,7 @@ describe('StorageChangeSet', (): void => {
});
describe('json', (): void => {
const set = createType('StorageChangeSet', json.params.result);
const set = createType(registry, 'StorageChangeSet', json.params.result);
it('has the correct hash', (): void => {
expect(
@@ -2,35 +2,33 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { hexToU8a } from '@polkadot/util';
import { createType } from '../../codec/create';
import { createType, TypeRegistry } from '../../codec/create';
const TESTS = [
// jaco's claims sig
'0x55bd020bdbbdc02de34e915effc9b18a99002f4c29f64e22e8dcbb69e722ea6c28e1bb53b9484063fbbfd205e49dcc1f620929f520c9c4c3695150f05a28f52a01',
// keith's claim sig
'0x98adffe14b1882ba5a861d6aaa10805d52aed56f480e1ece01505a77470f29f15cb4b0a1dc33177761de8270199282baf160f255e1ca0e4c8354b54b0059e40a1c'
];
describe('EdcsaSignature', (): void => {
const registry = new TypeRegistry();
it('constructs and has a valid representation (toHex)', (): void => {
expect(
createType('EcdsaSignature', TESTS[0]).toHex()
createType(registry, 'EcdsaSignature', TESTS[0]).toHex()
).toEqual(TESTS[0]);
});
it('constructs and has a valid representation (toJSON)', (): void => {
expect(
createType('EcdsaSignature', TESTS[0]).toJSON()
createType(registry, 'EcdsaSignature', TESTS[0]).toJSON()
).toEqual(TESTS[0]);
});
it('constructs and has a valid representation (toU8a)', (): void => {
expect(
createType('EcdsaSignature', TESTS[1]).toU8a()
createType(registry, 'EcdsaSignature', TESTS[1]).toU8a()
).toEqual(hexToU8a(TESTS[1]));
});
});
@@ -2,11 +2,9 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import BN from 'bn.js';
import { createType } from '../../codec/create';
import { createType, TypeRegistry } from '../../codec/create';
import json1 from '../../json/Header.001.json';
import json2 from '../../json/Header.002.json';
import json3 from '../../json/Header.003.json';
@@ -14,8 +12,10 @@ import block00300 from '../../json/SignedBlock.003.00.json';
import block00301 from '../../json/SignedBlock.003.01.json';
describe('Header', (): void => {
const registry = new TypeRegistry();
it('decodes an actual JSON response', (): void => {
const header = createType('Header', json1.result);
const header = createType(registry, 'Header', json1.result);
expect(
header.number.toNumber()
@@ -35,7 +35,7 @@ describe('Header', (): void => {
});
it('parses old-style JSON headers (deprecated)', (): void => {
const header = createType('Header', json2.result);
const header = createType(registry, 'Header', json2.result);
expect(
header.digest.logs
@@ -43,7 +43,7 @@ describe('Header', (): void => {
});
it('creates a valid hash (incl. digest & compact)', (): void => {
const header = createType('Header', json3.result);
const header = createType(registry, 'Header', json3.result);
expect(
header.hash.toHex()
@@ -54,7 +54,7 @@ describe('Header', (): void => {
});
it('calculates correct hash, matching with parentHash', (): void => {
const blockHash = createType('Header', block00300.result.block.header).hash.toHex();
const blockHash = createType(registry, 'Header', block00300.result.block.header).hash.toHex();
expect(blockHash).toEqual(block00301.result.block.header.parentHash);
});
@@ -2,14 +2,14 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { createType } from '../../codec/create';
import { createType, TypeRegistry } from '../../codec/create';
describe('KeyValue', (): void => {
const registry = new TypeRegistry();
it('decodes KeyValue from u8a', (): void => {
expect(
createType('KeyValue', Uint8Array.from([
createType(registry, 'KeyValue', Uint8Array.from([
4 << 2,
0x11, 0x22, 0x33, 0x44,
9 << 2,
@@ -20,7 +20,7 @@ describe('KeyValue', (): void => {
it('encodes KeyValue from JSON', (): void => {
expect(
createType('KeyValue', ['0x11223344', '0x998877665544332211']).toU8a()
createType(registry, 'KeyValue', ['0x11223344', '0x998877665544332211']).toU8a()
).toEqual(
new Uint8Array([
4 << 2,
@@ -32,7 +32,7 @@ describe('KeyValue', (): void => {
});
it('exposes the properties for key/value', (): void => {
const [key, value] = createType('KeyValue', ['0x11223344', '0x998877665544332211']);
const [key, value] = createType(registry, 'KeyValue', ['0x11223344', '0x998877665544332211']);
expect(key.toHex()).toEqual('0x11223344');
expect(value.toHex()).toEqual('0x998877665544332211');
@@ -2,25 +2,23 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import Metadata from '@polkadot/metadata/Metadata';
import metadataStatic from '@polkadot/metadata/Metadata/static';
import { createType } from '../../codec/create';
import Call from '../../primitive/Generic/Call';
import { createType, TypeRegistry } from '../../codec/create';
import events from '../../json/SignedBlock.002.json';
import immortalTxs from '../../json/SignedBlock.004.immortal.json';
import mortalTxs from '../../json/SignedBlock.004.mortal.json';
import knownMehods from '../../json/SignedBlock.005.json';
describe('SignedBlock', (): void => {
beforeEach((): void => {
Call.injectMetadata(new Metadata(metadataStatic));
});
const registry = new TypeRegistry();
// eslint-disable-next-line no-new
new Metadata(registry, metadataStatic);
describe('SignedBlock', (): void => {
it('decodes a full block', (): void => {
const s = createType('SignedBlock', events.result);
const s = createType(registry, 'SignedBlock', events.result);
expect(
s.block.header.stateRoot.toString()
@@ -40,7 +38,7 @@ describe('SignedBlock', (): void => {
// Test to replicate https://github.com/polkadot-js/api/issues/1212
it('decodes to known extrinsics', (): void => {
const s = createType('SignedBlock', knownMehods.result);
const s = createType(registry, 'SignedBlock', knownMehods.result);
const indexes = s.block.extrinsics.map(({ method: { callIndex } }): Uint8Array => callIndex);
expect(indexes).toEqual([
@@ -51,7 +49,7 @@ describe('SignedBlock', (): void => {
describe('eras', (): void => {
it('can decode immortals', (): void => {
const s = createType('SignedBlock', immortalTxs.result);
const s = createType(registry, 'SignedBlock', immortalTxs.result);
const immortalTx = s.block.extrinsics[0];
expect(immortalTx.method.methodName).toEqual('transfer');
@@ -59,7 +57,7 @@ describe('SignedBlock', (): void => {
});
it('can decode mortals', (): void => {
const s = createType('SignedBlock', mortalTxs.result);
const s = createType(registry, 'SignedBlock', mortalTxs.result);
const mortalTx = s.block.extrinsics[0];
expect(mortalTx.method.methodName).toEqual('transfer');
@@ -2,30 +2,25 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { EventRecord } from './types';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadataV0 from '@polkadot/metadata/Metadata/v0/static';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import { createType } from '../../codec/create';
import Vec from '../../codec/Vec';
import { createType, TypeRegistry } from '../../codec/create';
import json1 from '../../json/EventRecord.001.json';
import json3 from '../../json/EventRecord.003.json';
import GenericEvent from '../../primitive/Generic/Event';
describe('EventRecord', (): void => {
const registry = new TypeRegistry();
describe('EventRecord_0_76', (): void => {
beforeEach((): void => {
GenericEvent.injectMetadata(
new Metadata(rpcMetadataV0)
);
// eslint-disable-next-line no-new
new Metadata(registry, rpcMetadataV0);
});
it('decodes correctly', (): void => {
const records: Vec<EventRecord> = createType('Vec<EventRecord>', json1.params.result.changes[0][1]) as any;
const records = createType(registry, 'Vec<EventRecord>', json1.params.result.changes[0][1]) as any;
const er = records[0];
expect(er.phase.type).toEqual('ApplyExtrinsic');
@@ -34,13 +29,12 @@ describe('EventRecord', (): void => {
describe('EventRecord (current)', (): void => {
beforeEach((): void => {
GenericEvent.injectMetadata(
new Metadata(rpcMetadata)
);
// eslint-disable-next-line no-new
new Metadata(registry, rpcMetadata);
});
it('decodes older eventrecord correctly', (): void => {
const records: Vec<EventRecord> = createType('Vec<EventRecord>', json1.params.result.changes[0][1], true) as any;
const records = createType(registry, 'Vec<EventRecord>', json1.params.result.changes[0][1], true) as any;
const er = records[0];
expect(er.phase.type).toEqual('ApplyExtrinsic');
@@ -48,7 +42,7 @@ describe('EventRecord', (): void => {
it('decodes eventrecord with topics correctly', (): void => {
const hex = json3.params.result.changes[0][1];
const records: Vec<EventRecord> = createType('Vec<EventRecord>', hex, true) as any;
const records = createType(registry, 'Vec<EventRecord>', hex, true) as any;
const er = records[0];
expect(er.phase.type).toEqual('ApplyExtrinsic');
+13 -9
View File
@@ -2,18 +2,22 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import Bool from './Bool';
import { CodecTo } from '../types';
import { TypeRegistry } from '../codec';
import Bool from './Bool';
describe('Bool', (): void => {
const registry = new TypeRegistry();
describe('decode', (): void => {
// eslint-disable-next-line @typescript-eslint/ban-types
const testDecode = (type: string, input: Uint8Array | boolean | Boolean | Bool | number, expected: boolean): void =>
it(`can decode from ${type}`, (): void => {
expect(new Bool(input).toJSON()).toBe(expected);
expect(new Bool(registry, input).toJSON()).toBe(expected);
});
testDecode('Bool', new Bool(true), true);
testDecode('Bool', new Bool(registry, true), true);
testDecode('Boolean', Boolean(true), true);
testDecode('boolean', true, true);
testDecode('number', 1, true);
@@ -23,7 +27,7 @@ describe('Bool', (): void => {
describe('encode', (): void => {
const testEncode = (to: CodecTo, expected: string | Uint8Array | boolean, value: boolean): void =>
it(`can encode ${to}`, (): void => {
expect(new Bool(value)[to]()).toEqual(expected);
expect(new Bool(registry, value)[to]()).toEqual(expected);
});
testEncode('toJSON', true, true);
@@ -34,24 +38,24 @@ describe('Bool', (): void => {
});
it('correctly encodes length', (): void => {
expect(new Bool(true).encodedLength).toEqual(1);
expect(new Bool(registry, true).encodedLength).toEqual(1);
});
describe('utils', (): void => {
it('compares agains a boolean', (): void => {
expect(new Bool(true).eq(true)).toBe(true);
expect(new Bool(registry, true).eq(true)).toBe(true);
});
it('compares agains a Bool', (): void => {
expect(new Bool(false).eq(new Bool(false))).toBe(true);
expect(new Bool(registry, false).eq(new Bool(registry, false))).toBe(true);
});
it('has isTrue', (): void => {
expect(new Bool(true).isTrue).toBe(true);
expect(new Bool(registry, true).isTrue).toBe(true);
});
it('has isFalse', (): void => {
expect(new Bool(true).isFalse).toBe(false);
expect(new Bool(registry, true).isFalse).toBe(false);
});
});
});
+8 -6
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, IHash } from '../types';
import { Codec, IHash, Registry } from '../types';
import { isU8a, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -16,11 +16,13 @@ import { createType } from '../codec/create';
* @noInheritDoc
*/
export default class Bool extends Boolean implements Codec {
public readonly registry: Registry;
// eslint-disable-next-line @typescript-eslint/ban-types
constructor (value: Bool | Boolean | Uint8Array | boolean | number = false) {
super(
Bool.decodeBool(value)
);
constructor (registry: Registry, value: Bool | Boolean | Uint8Array | boolean | number = false) {
super(Bool.decodeBool(value));
this.registry = registry;
}
private static decodeBool (value: any): boolean {
@@ -44,7 +46,7 @@ export default class Bool extends Boolean implements Codec {
* @description returns a hash of the contents
*/
public get hash (): IHash {
return createType('Hash', blake2AsU8a(this.toU8a(), 256));
return createType(this.registry, 'Hash', blake2AsU8a(this.toU8a(), 256));
}
/**
+7 -7
View File
@@ -2,37 +2,37 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../injector';
import { createType } from '../codec/create';
import { createType, TypeRegistry } from '../codec/create';
import Bytes from './Bytes';
describe('Bytes', (): void => {
const registry = new TypeRegistry();
const CODE = new Uint8Array([0x14, 0x3a, 0x63, 0x6f, 0x64, 0x65]);
describe('construction', (): void => {
it('decodes when input is string', (): void => {
expect(
new Bytes(':code').toU8a()
new Bytes(registry, ':code').toU8a()
).toEqual(CODE);
});
it('decodes when hex is not length prefixed', (): void => {
expect(
new Bytes('0x3a636f6465').toU8a()
new Bytes(registry, '0x3a636f6465').toU8a()
).toEqual(CODE);
});
it('decodes from number[]', (): void => {
expect(
new Bytes([0x3a, 0x63, 0x6f, 0x64, 0x65]).toU8a()
new Bytes(registry, [0x3a, 0x63, 0x6f, 0x64, 0x65]).toU8a()
).toEqual(CODE);
});
it('creates via storagedata (no prefix)', (): void => {
expect(
new Bytes(
createType('StorageData', '0x3a636f6465')
registry,
createType(registry, 'StorageData', '0x3a636f6465')
).toU8a()
).toEqual(CODE);
});
+3 -3
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyU8a } from '../types';
import { AnyU8a, Registry } from '../types';
import { assert, isString, isU8a, u8aToU8a } from '@polkadot/util';
@@ -17,8 +17,8 @@ import U8a from '../codec/U8a';
* as what is found in [[Text]] and [[Vec]])
*/
export default class Bytes extends U8a {
constructor (value?: AnyU8a) {
super(Bytes.decodeBytes(value));
constructor (registry: Registry, value?: AnyU8a) {
super(registry, Bytes.decodeBytes(value));
}
private static decodeBytes (value?: AnyU8a): Uint8Array | undefined {
@@ -2,23 +2,23 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import { hexToU8a } from '@polkadot/util';
import Call from '../Generic/Call';
import { TypeRegistry } from '../../codec';
import Extrinsic from './Extrinsic';
describe('Extrinsic', (): void => {
beforeAll((): void => {
Call.injectMetadata(new Metadata(rpcMetadata));
});
const registry = new TypeRegistry();
// eslint-disable-next-line no-new
new Metadata(registry, rpcMetadata);
describe('Extrinsic', (): void => {
describe('V1', (): void => {
it('decodes an actual transaction (length prefix)', (): void => {
const extrinsic = new Extrinsic(
registry,
'0x' +
'2502' +
'81' +
@@ -46,6 +46,7 @@ describe('Extrinsic', (): void => {
it('decodes an actual transaction (no length prefix, old version)', (): void => {
const extrinsic = new Extrinsic(
registry,
'0x' +
'81' +
'ff' +
@@ -74,6 +75,7 @@ describe('Extrinsic', (): void => {
describe('V2', (): void => {
it('decodes an actual transaction (length prefix)', (): void => {
const extrinsic = new Extrinsic(
registry,
'0x' +
'2902' + // yes, longer than in v1, 1 byte for the tip
'82' +
@@ -118,7 +120,7 @@ describe('Extrinsic', (): void => {
'e5c0';
expect(
new Extrinsic(new Extrinsic(input)).toU8a()
new Extrinsic(registry, new Extrinsic(registry, input)).toU8a()
).toEqual(hexToU8a(input));
});
});
@@ -4,7 +4,7 @@
import { FunctionMetadataLatest } from '../../interfaces/metadata/types';
import { Address, Balance, Call, EcdsaSignature, Ed25519Signature, ExtrinsicUnknown, ExtrinsicV1, ExtrinsicV2, ExtrinsicV3, ExtrinsicV4, Index, Sr25519Signature } from '../../interfaces/runtime';
import { AnyU8a, ArgsDef, Codec, ExtrinsicPayloadValue, IExtrinsic, IKeyringPair, InterfaceTypes, SignatureOptions } from '../../types';
import { AnyU8a, ArgsDef, Codec, ExtrinsicPayloadValue, IExtrinsic, IKeyringPair, InterfaceTypes, Registry, SignatureOptions } from '../../types';
import { assert, isHex, isU8a, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
@@ -51,11 +51,11 @@ export { TRANSACTION_VERSION as LATEST_EXTRINSIC_VERSION } from './v4/Extrinsic'
* - left as is, to create an inherent
*/
export default class Extrinsic extends Base<ExtrinsicVx | ExtrinsicUnknown> implements IExtrinsic {
constructor (value: Extrinsic | ExtrinsicValue | AnyU8a | Call | undefined, { version }: CreateOptions = {}) {
super(Extrinsic.decodeExtrinsic(value, version));
constructor (registry: Registry, value: Extrinsic | ExtrinsicValue | AnyU8a | Call | undefined, { version }: CreateOptions = {}) {
super(registry, Extrinsic.decodeExtrinsic(registry, value, version));
}
private static newFromValue (value: any, version: number): ExtrinsicVx | ExtrinsicUnknown {
private static newFromValue (registry: Registry, value: any, version: number): ExtrinsicVx | ExtrinsicUnknown {
if (value instanceof Extrinsic) {
return value.raw;
}
@@ -65,22 +65,22 @@ export default class Extrinsic extends Base<ExtrinsicVx | ExtrinsicUnknown> impl
// we cast here since the VERSION definition is incredibly broad - we don't have a
// slice for "only add extrinsic types", and more string definitions become unwieldy
return createType(type, value, { isSigned, version }) as ExtrinsicVx;
return createType(registry, type, value, { isSigned, version }) as ExtrinsicVx;
}
public static decodeExtrinsic (value: Extrinsic | ExtrinsicValue | AnyU8a | Call | undefined, version: number = DEFAULT_VERSION): ExtrinsicVx | ExtrinsicUnknown {
public static decodeExtrinsic (registry: Registry, value: Extrinsic | ExtrinsicValue | AnyU8a | Call | undefined, version: number = DEFAULT_VERSION): ExtrinsicVx | ExtrinsicUnknown {
if (Array.isArray(value) || isHex(value)) {
return Extrinsic.decodeU8aLike(value, version);
return Extrinsic.decodeU8aLike(registry, value, version);
} else if (isU8a(value)) {
return Extrinsic.decodeU8a(value, version);
} else if (value instanceof ClassOf('Call')) {
return Extrinsic.newFromValue({ method: value }, version);
return Extrinsic.decodeU8a(registry, value, version);
} else if (value instanceof ClassOf(registry, 'Call')) {
return Extrinsic.newFromValue(registry, { method: value }, version);
}
return Extrinsic.newFromValue(value, version);
return Extrinsic.newFromValue(registry, value, version);
}
private static decodeU8aLike (value: string | number[], version: number): ExtrinsicVx | ExtrinsicUnknown {
private static decodeU8aLike (registry: Registry, value: string | number[], version: number): ExtrinsicVx | ExtrinsicUnknown {
// Instead of the block below, it should simply be:
// return Extrinsic.decodeExtrinsic(hexToU8a(value as string));
const u8a = u8aToU8a(value);
@@ -92,6 +92,7 @@ export default class Extrinsic extends Base<ExtrinsicVx | ExtrinsicUnknown> impl
const withPrefix = u8a.length === (offset + length.toNumber());
return Extrinsic.decodeU8a(
registry,
withPrefix
? u8a
: Compact.addLengthPrefix(u8a),
@@ -99,9 +100,9 @@ export default class Extrinsic extends Base<ExtrinsicVx | ExtrinsicUnknown> impl
);
}
private static decodeU8a (value: Uint8Array, version: number): ExtrinsicVx | ExtrinsicUnknown {
private static decodeU8a (registry: Registry, value: Uint8Array, version: number): ExtrinsicVx | ExtrinsicUnknown {
if (!value.length) {
return Extrinsic.newFromValue(new Uint8Array(), version);
return Extrinsic.newFromValue(registry, new Uint8Array(), version);
}
const [offset, length] = Compact.decodeU8a(value);
@@ -111,7 +112,7 @@ export default class Extrinsic extends Base<ExtrinsicVx | ExtrinsicUnknown> impl
const data = value.subarray(offset, total);
return Extrinsic.newFromValue(data.subarray(1), data[0]);
return Extrinsic.newFromValue(registry, data.subarray(1), data[0]);
}
/**
@@ -2,46 +2,47 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { TypeRegistry } from '../../codec';
import ExtrinsicEra from './ExtrinsicEra';
describe('ExtrinsicEra', (): void => {
const registry = new TypeRegistry();
it('decodes an Extrinsic Era with immortal', (): void => {
const extrinsicEra = new ExtrinsicEra(new Uint8Array([0]));
const extrinsicEra = new ExtrinsicEra(registry, new Uint8Array([0]));
expect(extrinsicEra.asImmortalEra).toBeDefined();
expect(extrinsicEra.toJSON()).toEqual({ ImmortalEra: '0x00' });
});
it('decodes an Extrinsic Era from u8 as mortal', (): void => {
const extrinsicEra = new ExtrinsicEra(new Uint8Array([78, 156]));
const extrinsicEra = new ExtrinsicEra(registry, new Uint8Array([78, 156]));
expect(extrinsicEra.asMortalEra.period.toNumber()).toEqual(32768);
expect(extrinsicEra.asMortalEra.phase.toNumber()).toEqual(20000);
});
it('decoded from an existing ExtrinsicEra', (): void => {
const extrinsicEra = new ExtrinsicEra(new ExtrinsicEra(new Uint8Array([78, 156])));
const extrinsicEra = new ExtrinsicEra(registry, new ExtrinsicEra(registry, new Uint8Array([78, 156])));
expect(extrinsicEra.asMortalEra.period.toNumber()).toEqual(32768);
expect(extrinsicEra.asMortalEra.phase.toNumber()).toEqual(20000);
});
it('encode an Extrinsic Era from Object with blocknumber & period as mortal instance', (): void => {
const extrinsicEra = new ExtrinsicEra({ current: 1400, period: 200 });
const extrinsicEra = new ExtrinsicEra(registry, { current: 1400, period: 200 });
expect(extrinsicEra.asMortalEra.period.toNumber()).toEqual(256);
expect(extrinsicEra.asMortalEra.phase.toNumber()).toEqual(120);
});
it('serializes and de-serializes from JSON', (): void => {
const extrinsicEra = new ExtrinsicEra(new Uint8Array([78, 156]));
const extrinsicEra = new ExtrinsicEra(registry, new Uint8Array([78, 156]));
const u8a = extrinsicEra.toU8a();
const json = extrinsicEra.toJSON();
expect(u8a).toEqual(new Uint8Array([78, 156]));
expect(json).toEqual({ MortalEra: '0x4e9c' });
expect(new ExtrinsicEra(json).toU8a()).toEqual(u8a);
expect(new ExtrinsicEra(registry, json).toU8a()).toEqual(u8a);
});
});
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyU8a, IExtrinsicEra } from '../../types';
import { AnyU8a, IExtrinsicEra, Registry } from '../../types';
import BN from 'bn.js';
import { assert, bnToBn, hexToU8a, isHex, isU8a, isObject, u8aToBn } from '@polkadot/util';
@@ -35,10 +35,10 @@ interface ImmortalEnumDef {
*/
export class ImmortalEra extends U8a {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
constructor (value?: AnyU8a) {
constructor (registry: Registry, value?: AnyU8a) {
// For immortals, we always provide the known value (i.e. treated as a
// constant no matter how it is constructed - it is a fixed structure)
super(IMMORTAL_ERA);
super(registry, IMMORTAL_ERA);
}
}
@@ -48,30 +48,30 @@ export class ImmortalEra extends U8a {
* The MortalEra for an extrinsic, indicating period and phase
*/
export class MortalEra extends Tuple {
constructor (value?: MortalMethod | Uint8Array | number[] | string) {
super({
constructor (registry: Registry, value?: MortalMethod | Uint8Array | number[] | string) {
super(registry, {
period: U64,
phase: U64
}, MortalEra.decodeMortalEra(value));
}, MortalEra.decodeMortalEra(registry, value));
}
private static decodeMortalEra (value?: MortalMethod | Uint8Array | number[] | string): MortalEraValue {
private static decodeMortalEra (registry: Registry, value?: MortalMethod | Uint8Array | number[] | string): MortalEraValue {
if (isHex(value)) {
return MortalEra.decodeMortalU8a(hexToU8a(value));
return MortalEra.decodeMortalU8a(registry, hexToU8a(value));
} else if (Array.isArray(value)) {
return MortalEra.decodeMortalU8a(new Uint8Array(value));
return MortalEra.decodeMortalU8a(registry, new Uint8Array(value));
} else if (isU8a(value)) {
return MortalEra.decodeMortalU8a(value);
return MortalEra.decodeMortalU8a(registry, value);
} else if (isObject(value)) {
return MortalEra.decodeMortalObject(value);
return MortalEra.decodeMortalObject(registry, value);
} else if (!value) {
return [new U64(), new U64()];
return [new U64(registry), new U64(registry)];
}
throw new Error('Invalid data passed to Mortal era');
}
private static decodeMortalObject (value: MortalMethod): MortalEraValue {
private static decodeMortalObject (registry: Registry, value: MortalMethod): MortalEraValue {
const { current, period } = value;
let calPeriod = Math.pow(2, Math.ceil(Math.log2(period)));
calPeriod = Math.min(Math.max(calPeriod, 4), 1 << 16);
@@ -79,12 +79,12 @@ export class MortalEra extends Tuple {
const quantizeFactor = Math.max(calPeriod >> 12, 1);
const quantizedPhase = phase / quantizeFactor * quantizeFactor;
return [new U64(calPeriod), new U64(quantizedPhase)];
return [new U64(registry, calPeriod), new U64(registry, quantizedPhase)];
}
private static decodeMortalU8a (value: Uint8Array): MortalEraValue {
private static decodeMortalU8a (registry: Registry, value: Uint8Array): MortalEraValue {
if (value.length === 0) {
return [new U64(), new U64()];
return [new U64(registry), new U64(registry)];
}
const first = u8aToBn(value.subarray(0, 1)).toNumber();
@@ -96,7 +96,7 @@ export class MortalEra extends Tuple {
assert(period >= 4 && phase < period, 'Invalid data passed to Mortal era');
return [new U64(period), new U64(phase)];
return [new U64(registry, period), new U64(registry, phase)];
}
/**
@@ -191,8 +191,8 @@ export class MortalEra extends Tuple {
* The era for an extrinsic, indicating either a mortal or immortal extrinsic
*/
export default class ExtrinsicEra extends Enum implements IExtrinsicEra {
constructor (value?: any) {
super({
constructor (registry: Registry, value?: any) {
super(registry, {
ImmortalEra,
MortalEra
}, ExtrinsicEra.decodeExtrinsicEra(value));
@@ -2,11 +2,11 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { TypeRegistry } from '../../codec';
import ExtrinsicPayload from './ExtrinsicPayload';
describe('ExtrinsicPayload', (): void => {
const registry = new TypeRegistry();
const TEST = {
address: '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE',
blockHash: '0xde8f69eeb5e065e18c6950ff708d7e551f68dc9bf59a07c52367c0280f805ec7',
@@ -19,15 +19,15 @@ describe('ExtrinsicPayload', (): void => {
};
it('creates and can re-create from itself (U8a)', (): void => {
const a = new ExtrinsicPayload(TEST, { version: 3 });
const b = new ExtrinsicPayload(a.toU8a(), { version: 3 });
const a = new ExtrinsicPayload(registry, TEST, { version: 3 });
const b = new ExtrinsicPayload(registry, a.toU8a(), { version: 3 });
expect(a).toEqual(b);
});
it('creates and can re-create from itself (hex)', (): void => {
const a = new ExtrinsicPayload(TEST, { version: 3 });
const b = new ExtrinsicPayload(a.toHex(), { version: 3 });
const a = new ExtrinsicPayload(registry, TEST, { version: 3 });
const b = new ExtrinsicPayload(registry, a.toHex(), { version: 3 });
expect(a).toEqual(b);
});
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Balance, ExtrinsicPayloadV1, ExtrinsicPayloadV2, ExtrinsicPayloadV3, ExtrinsicPayloadV4, Hash, Index } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IKeyringPair, InterfaceTypes } from '../../types';
import { ExtrinsicPayloadValue, IKeyringPair, InterfaceTypes, Registry } from '../../types';
import { u8aToHex } from '@polkadot/util';
@@ -37,18 +37,16 @@ const VERSIONS: InterfaceTypes[] = [
* on the contents included
*/
export default class ExtrinsicPayload extends Base<ExtrinsicPayloadVx> {
constructor (value: Partial<ExtrinsicPayloadValue> | Uint8Array | string | undefined, { version }: ExtrinsicPayloadOptions = {}) {
super(
ExtrinsicPayload.decodeExtrinsicPayload(value as ExtrinsicPayloadValue, version)
);
constructor (registry: Registry, value: Partial<ExtrinsicPayloadValue> | Uint8Array | string | undefined, { version }: ExtrinsicPayloadOptions = {}) {
super(registry, ExtrinsicPayload.decodeExtrinsicPayload(registry, value as ExtrinsicPayloadValue, version));
}
public static decodeExtrinsicPayload (value: ExtrinsicPayload | ExtrinsicPayloadValue | Uint8Array | string | undefined, version: number = DEFAULT_VERSION): ExtrinsicPayloadVx {
public static decodeExtrinsicPayload (registry: Registry, value: ExtrinsicPayload | ExtrinsicPayloadValue | Uint8Array | string | undefined, version: number = DEFAULT_VERSION): ExtrinsicPayloadVx {
if (value instanceof ExtrinsicPayload) {
return value.raw;
}
return createType(VERSIONS[version] || VERSIONS[0], value, { version }) as ExtrinsicPayloadVx;
return createType(registry, VERSIONS[version] || VERSIONS[0], value, { version }) as ExtrinsicPayloadVx;
}
/**
@@ -70,7 +68,7 @@ export default class ExtrinsicPayload extends Base<ExtrinsicPayloadVx> {
*/
public get genesisHash (): Hash {
// NOTE only v3+
return (this.raw as ExtrinsicPayloadV3).genesisHash || createType('Hash');
return (this.raw as ExtrinsicPayloadV3).genesisHash || createType(this.registry, 'Hash');
}
/**
@@ -92,7 +90,7 @@ export default class ExtrinsicPayload extends Base<ExtrinsicPayloadVx> {
*/
public get specVersion (): u32 {
// NOTE only v3+
return (this.raw as ExtrinsicPayloadV3).specVersion || createType('u32');
return (this.raw as ExtrinsicPayloadV3).specVersion || createType(this.registry, 'u32');
}
/**
@@ -100,7 +98,7 @@ export default class ExtrinsicPayload extends Base<ExtrinsicPayloadVx> {
*/
public get tip (): Compact<Balance> {
// NOTE from v2+
return (this.raw as ExtrinsicPayloadV2).tip || createType('Compact<Balance>');
return (this.raw as ExtrinsicPayloadV2).tip || createType(this.registry, 'Compact<Balance>');
}
/**
@@ -2,6 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Registry } from '../../types';
import { ExtrinsicPayloadOptions } from './types';
import Struct from '../../codec/Struct';
@@ -12,8 +13,8 @@ import Struct from '../../codec/Struct';
* A default handler for payloads where the version is not known (default throw)
*/
export default class ExtrinsicPayloadUnknown extends Struct {
constructor (value?: any, { version = 0 }: Partial<ExtrinsicPayloadOptions> = {}) {
super({});
constructor (registry: Registry, value?: any, { version = 0 }: Partial<ExtrinsicPayloadOptions> = {}) {
super(registry, {});
throw new Error(`Unsupported extrinsic payload version ${version}`);
}
@@ -2,6 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Registry } from '../../types';
import { ExtrinsicOptions } from './types';
import Struct from '../../codec/Struct';
@@ -13,8 +14,8 @@ import { UNMASK_VERSION } from './constants';
* A default handler for extrinsics where the version is not known (default throw)
*/
export default class ExtrinsicUnknown extends Struct {
constructor (value?: any, { isSigned = false, version = 0 }: Partial<ExtrinsicOptions> = {}) {
super({});
constructor (registry: Registry, value?: any, { isSigned = false, version = 0 }: Partial<ExtrinsicOptions> = {}) {
super(registry, {});
throw new Error(`Unsupported ${isSigned ? '' : 'un'}signed extrinsic version ${version & UNMASK_VERSION}`);
}
@@ -2,12 +2,19 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { createType, GenericCall } from '@polkadot/types';
import { createType } from '@polkadot/types';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import { TypeRegistry } from '../../codec';
import SignerPayload from './SignerPayload';
const registry = new TypeRegistry();
// eslint-disable-next-line no-new
new Metadata(registry, rpcMetadata);
describe('SignerPayload', (): void => {
const TEST = {
address: '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE',
@@ -22,19 +29,15 @@ describe('SignerPayload', (): void => {
version: 3
};
beforeEach((): void => {
GenericCall.injectMetadata(new Metadata(rpcMetadata));
});
it('creates a valid JSON output', (): void => {
expect(
new SignerPayload({
new SignerPayload(registry, {
address: '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE',
blockHash: '0xde8f69eeb5e065e18c6950ff708d7e551f68dc9bf59a07c52367c0280f805ec7',
blockNumber: '0x231d30',
era: createType('ExtrinsicEra', { current: 2301232, period: 200 }),
era: createType(registry, 'ExtrinsicEra', { current: 2301232, period: 200 }),
genesisHash: '0xdcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b',
method: createType('Call', '0x0600ffd7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9e56c'),
method: createType(registry, 'Call', '0x0600ffd7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9e56c'),
nonce: 0x1234,
tip: 0x5678,
version: 3
@@ -55,21 +58,22 @@ describe('SignerPayload', (): void => {
it('re-constructs from JSON', (): void => {
expect(
new SignerPayload(TEST).toPayload()
new SignerPayload(registry, TEST).toPayload()
).toEqual(TEST);
});
it('re-constructs from itself', (): void => {
expect(
new SignerPayload(
new SignerPayload(TEST)
registry,
new SignerPayload(registry, TEST)
).toPayload()
).toEqual(TEST);
});
it('can be used as a feed to ExtrinsicPayload', (): void => {
const signer = new SignerPayload(TEST).toPayload();
const payload = createType('ExtrinsicPayload', signer, { version: signer.version });
const signer = new SignerPayload(registry, TEST).toPayload();
const payload = createType(registry, 'ExtrinsicPayload', signer, { version: signer.version });
expect(payload.era.toHex()).toEqual(TEST.era);
expect(payload.method.toHex()).toEqual(TEST.method);
@@ -65,7 +65,7 @@ export default class SignerPayload extends _Payload implements ISignerPayload {
public toRaw (): SignerPayloadRaw {
const payload = this.toPayload();
// NOTE Explicitly pass the bare flag so the method is encoded un-prefixed (non-decodable, for signing only)
const data = u8aToHex(createType('ExtrinsicPayload', payload, { version: payload.version }).toU8a(true));
const data = u8aToHex(createType(this.registry, 'ExtrinsicPayload', payload, { version: payload.version }).toU8a(true));
return {
address: payload.address,
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Address, Call } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, SignatureOptions } from '../../../types';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, Registry, SignatureOptions } from '../../../types';
import { ExtrinsicOptions } from '../types';
import { isU8a } from '@polkadot/util';
@@ -25,22 +25,22 @@ const TRANSACTION_VERSION = 1;
* The first generation of compact extrinsics
*/
export default class ExtrinsicV1 extends Struct implements IExtrinsicImpl {
constructor (value?: Uint8Array | ExtrinsicValueV1, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super({
constructor (registry: Registry, value?: Uint8Array | ExtrinsicValueV1, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super(registry, {
signature: ExtrinsicSignatureV1,
method: 'Call'
}, ExtrinsicV1.decodeExtrinsic(value, isSigned));
}, ExtrinsicV1.decodeExtrinsic(registry, value, isSigned));
}
public static decodeExtrinsic (value?: Uint8Array | ExtrinsicValueV1, isSigned = false): ExtrinsicValueV1 {
public static decodeExtrinsic (registry: Registry, value?: Uint8Array | ExtrinsicValueV1, isSigned = false): ExtrinsicValueV1 {
if (!value) {
return {};
} else if (value instanceof ExtrinsicV1) {
return value;
} else if (isU8a(value)) {
// here we decode manually since we need to pull through the version information
const signature = new ExtrinsicSignatureV1(value, { isSigned });
const method = createType('Call', value.subarray(signature.encodedLength));
const signature = new ExtrinsicSignatureV1(registry, value, { isSigned });
const method = createType(registry, 'Call', value.subarray(signature.encodedLength));
return {
method,
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Hash, ExtrinsicEra, Index } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IKeyringPair } from '../../../types';
import { ExtrinsicPayloadValue, IKeyringPair, Registry } from '../../../types';
import Compact from '../../../codec/Compact';
import Struct from '../../../codec/Struct';
@@ -22,8 +22,8 @@ import { sign } from '../util';
* 32 bytes: The hash of the authoring block implied by the Transaction Era and the current block.
*/
export default class ExtrinsicPayloadV1 extends Struct {
constructor (value?: ExtrinsicPayloadValue | Uint8Array | string) {
super({
constructor (registry: Registry, value?: ExtrinsicPayloadValue | Uint8Array | string) {
super(registry, {
nonce: 'Compact<Index>',
method: 'Bytes',
era: 'ExtrinsicEra',
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Address, Balance, Call, ExtrinsicEra, Index, Signature } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, SignatureOptions } from '../../../types';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../../types';
import { ExtrinsicSignatureOptions } from '../types';
import { createType } from '../../../codec/create';
@@ -23,8 +23,8 @@ export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSi
// 64 bytes: The sr25519/ed25519 signature of the Signing Payload
// 1-8 bytes: The Compact<Nonce> of the signing account
// 1/2 bytes: The Transaction Era
constructor (value?: ExtrinsicSignatureV1 | Uint8Array, { isSigned }: ExtrinsicSignatureOptions = {}) {
super({
constructor (registry: Registry, value?: ExtrinsicSignatureV1 | Uint8Array, { isSigned }: ExtrinsicSignatureOptions = {}) {
super(registry, {
signer: 'Address',
signature: 'Signature',
nonce: 'Compact<Index>',
@@ -92,7 +92,7 @@ export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSi
* @description Forwards compat
*/
public get tip (): Compact<Balance> {
return createType('Compact<Balance>', 0);
return createType(this.registry, 'Compact<Balance>', 0);
}
private injectSignature (signer: Address, signature: Signature, { era, nonce }: ExtrinsicPayloadV1): IExtrinsicSignature {
@@ -109,9 +109,9 @@ export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSi
*/
public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): IExtrinsicSignature {
return this.injectSignature(
createType('Address', signer),
createType('Signature', signature),
new ExtrinsicPayloadV1(payload)
createType(this.registry, 'Address', signer),
createType(this.registry, 'Signature', signature),
new ExtrinsicPayloadV1(this.registry, payload)
);
}
@@ -119,8 +119,8 @@ export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSi
* @description Generate a payload and applies the signature from a keypair
*/
public sign (method: Call, account: IKeyringPair, { blockHash, era, genesisHash, nonce }: SignatureOptions): IExtrinsicSignature {
const signer = createType('Address', account.publicKey);
const payload = new ExtrinsicPayloadV1({
const signer = createType(this.registry, 'Address', account.publicKey);
const payload = new ExtrinsicPayloadV1(this.registry, {
blockHash,
era: era || IMMORTAL_ERA,
genesisHash,
@@ -129,7 +129,7 @@ export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSi
specVersion: 0, // unused for v1, added for compat
tip: 0
});
const signature = createType('Signature', payload.sign(account));
const signature = createType(this.registry, 'Signature', payload.sign(account));
return this.injectSignature(signer, signature, payload);
}
@@ -2,34 +2,33 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../../injector';
import BN from 'bn.js';
import Decorated from '@polkadot/metadata/Decorated';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import testingPairs from '@polkadot/keyring/testingPairs';
import Call from '../../Generic/Call';
import { TypeRegistry } from '../../../codec';
import Extrinsic from './Extrinsic';
const decorated = new Decorated(rpcMetadata);
const registry = new TypeRegistry();
const decorated = new Decorated(registry, rpcMetadata);
const keyring = testingPairs({ type: 'ed25519' }, false);
describe('ExtrinsicV2', (): void => {
beforeEach((): void => {
Call.injectMetadata(new Metadata(rpcMetadata));
});
// eslint-disable-next-line no-new
new Metadata(registry, rpcMetadata);
describe('ExtrinsicV2', (): void => {
it('constructs a sane Uint8Array (default)', (): void => {
expect(
new Extrinsic().toU8a()
new Extrinsic(registry).toU8a()
).toEqual(new Uint8Array([0, 0]));
});
it('creates a unsigned extrinsic', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969)
).toHex()
).toEqual(
@@ -44,6 +43,7 @@ describe('ExtrinsicV2', (): void => {
it('creates a signed extrinsic', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969)
).sign(keyring.alice, {
blockHash: '0xec7afaf1cca720ce88c1d1b689d81f0583cc15a97d621cf046dd9abf605ef22f',
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Address, Call } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, SignatureOptions } from '../../../types';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, Registry, SignatureOptions } from '../../../types';
import { ExtrinsicOptions } from '../types';
import { isU8a } from '@polkadot/util';
@@ -25,24 +25,24 @@ export interface ExtrinsicValueV2 {
* The second generation of compact extrinsics
*/
export default class ExtrinsicV2 extends Struct implements IExtrinsicImpl {
constructor (value?: Uint8Array | ExtrinsicValueV2 | Call, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super({
constructor (registry: Registry, value?: Uint8Array | ExtrinsicValueV2 | Call, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super(registry, {
signature: ExtrinsicSignatureV2,
method: 'Call'
}, ExtrinsicV2.decodeExtrinsic(value, isSigned));
}, ExtrinsicV2.decodeExtrinsic(registry, value, isSigned));
}
public static decodeExtrinsic (value?: Call | Uint8Array | ExtrinsicValueV2, isSigned = false): ExtrinsicValueV2 {
public static decodeExtrinsic (registry: Registry, value?: Call | Uint8Array | ExtrinsicValueV2, isSigned = false): ExtrinsicValueV2 {
if (!value) {
return {};
} else if (value instanceof ExtrinsicV2) {
return value;
} else if (value instanceof ClassOf('Call')) {
} else if (value instanceof ClassOf(registry, 'Call')) {
return { method: value };
} else if (isU8a(value)) {
// here we decode manually since we need to pull through the version information
const signature = new ExtrinsicSignatureV2(value, { isSigned });
const method = createType('Call', value.subarray(signature.encodedLength));
const signature = new ExtrinsicSignatureV2(registry, value, { isSigned });
const method = createType(registry, 'Call', value.subarray(signature.encodedLength));
return {
method,
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Balance, ExtrinsicEra, Hash, Index } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IKeyringPair, InterfaceTypes } from '../../../types';
import { ExtrinsicPayloadValue, IKeyringPair, InterfaceTypes, Registry } from '../../../types';
import Compact from '../../../codec/Compact';
import Struct from '../../../codec/Struct';
@@ -40,8 +40,8 @@ const SignedPayloadDefV2: Record<string, InterfaceTypes> = {
* on the contents included
*/
export default class ExtrinsicPayloadV2 extends Struct {
constructor (value?: ExtrinsicPayloadValue | Uint8Array | string) {
super(SignedPayloadDefV2, value);
constructor (registry: Registry, value?: ExtrinsicPayloadValue | Uint8Array | string) {
super(registry, SignedPayloadDefV2, value);
}
/**
@@ -2,11 +2,12 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../../injector';
import { TypeRegistry } from '../../../codec';
import ExtrinsicSignature from './ExtrinsicSignature';
describe('ExtrinsicSignatureV2', (): void => {
const registry = new TypeRegistry();
it('encodes to a sane Uint8Array', (): void => {
const u8a = new Uint8Array([
// signer as an AccountIndex
@@ -23,7 +24,7 @@ describe('ExtrinsicSignatureV2', (): void => {
]);
expect(
new ExtrinsicSignature(u8a, { isSigned: true }).toU8a()
new ExtrinsicSignature(registry, u8a, { isSigned: true }).toU8a()
).toEqual(u8a);
});
});
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Address, Balance, Call, ExtrinsicEra, Index, Signature } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, SignatureOptions } from '../../../types';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../../types';
import { ExtrinsicSignatureOptions } from '../types';
import { createType } from '../../../codec/create';
@@ -18,8 +18,8 @@ import ExtrinsicPayloadV2 from './ExtrinsicPayload';
* A container for the [[Signature]] associated with a specific [[Extrinsic]]
*/
export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSignature {
constructor (value: ExtrinsicSignatureV2 | Uint8Array | undefined, { isSigned }: ExtrinsicSignatureOptions = {}) {
super({
constructor (registry: Registry, value: ExtrinsicSignatureV2 | Uint8Array | undefined, { isSigned }: ExtrinsicSignatureOptions = {}) {
super(registry, {
signer: 'Address',
signature: 'Signature',
era: 'ExtrinsicEra',
@@ -106,9 +106,9 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi
*/
public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): IExtrinsicSignature {
return this.injectSignature(
createType('Address', signer),
createType('Signature', signature),
new ExtrinsicPayloadV2(payload)
createType(this.registry, 'Address', signer),
createType(this.registry, 'Signature', signature),
new ExtrinsicPayloadV2(this.registry, payload)
);
}
@@ -116,8 +116,8 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi
* @description Generate a payload and applies the signature from a keypair
*/
public sign (method: Call, account: IKeyringPair, { blockHash, era, genesisHash, nonce, tip }: SignatureOptions): IExtrinsicSignature {
const signer = createType('Address', account.publicKey);
const payload = new ExtrinsicPayloadV2({
const signer = createType(this.registry, 'Address', account.publicKey);
const payload = new ExtrinsicPayloadV2(this.registry, {
blockHash,
era: era || IMMORTAL_ERA,
genesisHash,
@@ -126,7 +126,7 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi
specVersion: 0, // unused for v2
tip: tip || 0
});
const signature = createType('Signature', payload.sign(account));
const signature = createType(this.registry, 'Signature', payload.sign(account));
return this.injectSignature(signer, signature, payload);
}
@@ -2,34 +2,33 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../../injector';
import BN from 'bn.js';
import Decorated from '@polkadot/metadata/Decorated';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import testingPairs from '@polkadot/keyring/testingPairs';
import Call from '../../Generic/Call';
import { TypeRegistry } from '../../../codec';
import Extrinsic from './Extrinsic';
const decorated = new Decorated(rpcMetadata);
const registry = new TypeRegistry();
const decorated = new Decorated(registry, rpcMetadata);
const keyring = testingPairs({ type: 'ed25519' }, false);
describe('ExtrinsicV3', (): void => {
beforeEach((): void => {
Call.injectMetadata(new Metadata(rpcMetadata));
});
// eslint-disable-next-line no-new
new Metadata(registry, rpcMetadata);
describe('ExtrinsicV3', (): void => {
it('constructs a sane Uint8Array (default)', (): void => {
expect(
new Extrinsic().toU8a()
new Extrinsic(registry).toU8a()
).toEqual(new Uint8Array([0, 0]));
});
it('creates a unsigned extrinsic', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969)
).toHex()
).toEqual(
@@ -44,6 +43,7 @@ describe('ExtrinsicV3', (): void => {
it('creates a signed extrinsic', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969)
).sign(keyring.alice, {
blockHash: '0xec7afaf1cca720ce88c1d1b689d81f0583cc15a97d621cf046dd9abf605ef22f',
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Address, Call } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, SignatureOptions } from '../../../types';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, Registry, SignatureOptions } from '../../../types';
import { ExtrinsicOptions } from '../types';
import { isU8a } from '@polkadot/util';
@@ -25,24 +25,24 @@ export interface ExtrinsicValueV3 {
* The third generation of compact extrinsics
*/
export default class ExtrinsicV3 extends Struct implements IExtrinsicImpl {
constructor (value?: Uint8Array | ExtrinsicValueV3 | Call, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super({
constructor (registry: Registry, value?: Uint8Array | ExtrinsicValueV3 | Call, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super(registry, {
signature: ExtrinsicSignatureV3,
method: 'Call'
}, ExtrinsicV3.decodeExtrinsic(value, isSigned));
}, ExtrinsicV3.decodeExtrinsic(registry, value, isSigned));
}
public static decodeExtrinsic (value?: Call | Uint8Array | ExtrinsicValueV3, isSigned = false): ExtrinsicValueV3 {
public static decodeExtrinsic (registry: Registry, value?: Call | Uint8Array | ExtrinsicValueV3, isSigned = false): ExtrinsicValueV3 {
if (!value) {
return {};
} else if (value instanceof ExtrinsicV3) {
return value;
} else if (value instanceof ClassOf('Call')) {
} else if (value instanceof ClassOf(registry, 'Call')) {
return { method: value };
} else if (isU8a(value)) {
// here we decode manually since we need to pull through the version information
const signature = new ExtrinsicSignatureV3(value, { isSigned });
const method = createType('Call', value.subarray(signature.encodedLength));
const signature = new ExtrinsicSignatureV3(registry, value, { isSigned });
const method = createType(registry, 'Call', value.subarray(signature.encodedLength));
return {
method,
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Balance, ExtrinsicEra, Hash, Index } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IKeyringPair, InterfaceTypes } from '../../../types';
import { ExtrinsicPayloadValue, IKeyringPair, InterfaceTypes, Registry } from '../../../types';
import Compact from '../../../codec/Compact';
import Struct from '../../../codec/Struct';
@@ -38,8 +38,8 @@ export const SignedPayloadDefV3: Record<string, InterfaceTypes> = {
* on the contents included
*/
export default class ExtrinsicPayloadV3 extends Struct {
constructor (value?: ExtrinsicPayloadValue | Uint8Array | string) {
super(SignedPayloadDefV3, value);
constructor (registry: Registry, value?: ExtrinsicPayloadValue | Uint8Array | string) {
super(registry, SignedPayloadDefV3, value);
}
/**
@@ -2,11 +2,12 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../../injector';
import { TypeRegistry } from '../../../codec';
import ExtrinsicSignature from './ExtrinsicSignature';
describe('ExtrinsicSignatureV3', (): void => {
const registry = new TypeRegistry();
it('encodes to a sane Uint8Array', (): void => {
const u8a = new Uint8Array([
// signer as an AccountIndex
@@ -23,7 +24,7 @@ describe('ExtrinsicSignatureV3', (): void => {
]);
expect(
new ExtrinsicSignature(u8a, { isSigned: true }).toU8a()
new ExtrinsicSignature(registry, u8a, { isSigned: true }).toU8a()
).toEqual(u8a);
});
});
@@ -21,9 +21,9 @@ export default class ExtrinsicSignatureV3 extends ExtrinsicSignatureV2 {
*/
public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): IExtrinsicSignature {
return this.injectSignature(
createType('Address', signer),
createType('Signature', signature),
new ExtrinsicPayloadV3(payload)
createType(this.registry, 'Address', signer),
createType(this.registry, 'Signature', signature),
new ExtrinsicPayloadV3(this.registry, payload)
);
}
@@ -31,8 +31,8 @@ export default class ExtrinsicSignatureV3 extends ExtrinsicSignatureV2 {
* @description Generate a payload and pplies the signature from a keypair
*/
public sign (method: Call, account: IKeyringPair, { blockHash, era, genesisHash, nonce, runtimeVersion: { specVersion }, tip }: SignatureOptions): IExtrinsicSignature {
const signer = createType('Address', account.publicKey);
const payload = new ExtrinsicPayloadV3({
const signer = createType(this.registry, 'Address', account.publicKey);
const payload = new ExtrinsicPayloadV3(this.registry, {
blockHash,
era: era || IMMORTAL_ERA,
genesisHash,
@@ -41,7 +41,7 @@ export default class ExtrinsicSignatureV3 extends ExtrinsicSignatureV2 {
specVersion,
tip: tip || 0
});
const signature = createType('Signature', payload.sign(account));
const signature = createType(this.registry, 'Signature', payload.sign(account));
return this.injectSignature(signer, signature, payload);
}
@@ -2,34 +2,33 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../../injector';
import BN from 'bn.js';
import testingPairs from '@polkadot/keyring/testingPairs';
import Decorated from '@polkadot/metadata';
import Metadata from '@polkadot/metadata/Metadata';
import metadataStatic from '@polkadot/metadata/Metadata/static';
import Call from '../../Generic/Call';
import { TypeRegistry } from '../../../codec/create';
import Extrinsic from './Extrinsic';
const decorated = new Decorated(metadataStatic);
const registry = new TypeRegistry();
const decorated = new Decorated(registry, metadataStatic);
const keyring = testingPairs({ type: 'ed25519' }, false);
describe('ExtrinsicV4', (): void => {
beforeEach((): void => {
Call.injectMetadata(new Metadata(metadataStatic));
});
// eslint-disable-next-line no-new
new Metadata(registry, metadataStatic);
describe('ExtrinsicV4', (): void => {
it('constructs a sane Uint8Array (default)', (): void => {
expect(
new Extrinsic().toU8a()
new Extrinsic(registry).toU8a()
).toEqual(new Uint8Array([0, 0]));
});
it('creates a unsigned extrinsic', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969)
).toHex()
).toEqual(
@@ -44,6 +43,7 @@ describe('ExtrinsicV4', (): void => {
it('creates a signed extrinsic', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969)
).sign(keyring.alice, {
blockHash: '0xec7afaf1cca720ce88c1d1b689d81f0583cc15a97d621cf046dd9abf605ef22f',
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Address, Call } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, SignatureOptions } from '../../../types';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, Registry, SignatureOptions } from '../../../types';
import { ExtrinsicOptions } from '../types';
import { isU8a } from '@polkadot/util';
@@ -25,24 +25,24 @@ export interface ExtrinsicValueV4 {
* The third generation of compact extrinsics
*/
export default class ExtrinsicV4 extends Struct implements IExtrinsicImpl {
constructor (value?: Uint8Array | ExtrinsicValueV4 | Call, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super({
constructor (registry: Registry, value?: Uint8Array | ExtrinsicValueV4 | Call, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super(registry, {
signature: ExtrinsicSignatureV4,
method: 'Call'
}, ExtrinsicV4.decodeExtrinsic(value, isSigned));
}, ExtrinsicV4.decodeExtrinsic(registry, value, isSigned));
}
public static decodeExtrinsic (value?: Call | Uint8Array | ExtrinsicValueV4, isSigned = false): ExtrinsicValueV4 {
public static decodeExtrinsic (registry: Registry, value?: Call | Uint8Array | ExtrinsicValueV4, isSigned = false): ExtrinsicValueV4 {
if (!value) {
return {};
} else if (value instanceof ExtrinsicV4) {
return value;
} else if (value instanceof ClassOf('Call')) {
} else if (value instanceof ClassOf(registry, 'Call')) {
return { method: value };
} else if (isU8a(value)) {
// here we decode manually since we need to pull through the version information
const signature = new ExtrinsicSignatureV4(value, { isSigned });
const method = createType('Call', value.subarray(signature.encodedLength));
const signature = new ExtrinsicSignatureV4(registry, value, { isSigned });
const method = createType(registry, 'Call', value.subarray(signature.encodedLength));
return {
method,
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Balance, ExtrinsicEra, Hash, Index } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IKeyringPair } from '../../../types';
import { ExtrinsicPayloadValue, IKeyringPair, Registry } from '../../../types';
import Compact from '../../../codec/Compact';
import Struct from '../../../codec/Struct';
@@ -19,8 +19,8 @@ import { SignedPayloadDefV3 as SignedPayloadDefV4 } from '../v3/ExtrinsicPayload
* on the contents included
*/
export default class ExtrinsicPayloadV4 extends Struct {
constructor (value?: ExtrinsicPayloadValue | Uint8Array | string) {
super(SignedPayloadDefV4, value);
constructor (registry: Registry, value?: ExtrinsicPayloadValue | Uint8Array | string) {
super(registry, SignedPayloadDefV4, value);
}
/**
@@ -2,11 +2,12 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../../injector';
import { TypeRegistry } from '../../../codec';
import ExtrinsicSignature from './ExtrinsicSignature';
describe('ExtrinsicSignatureV4', (): void => {
const registry = new TypeRegistry();
it('encodes to a sane Uint8Array', (): void => {
const u8a = new Uint8Array([
// signer as an AccountIndex
@@ -25,7 +26,7 @@ describe('ExtrinsicSignatureV4', (): void => {
]);
expect(
new ExtrinsicSignature(u8a, { isSigned: true }).toU8a()
new ExtrinsicSignature(registry, u8a, { isSigned: true }).toU8a()
).toEqual(u8a);
});
});
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Address, Balance, Call, EcdsaSignature, Ed25519Signature, ExtrinsicEra, Index, MultiSignature, Sr25519Signature } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, SignatureOptions } from '../../../types';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../../types';
import { ExtrinsicSignatureOptions } from '../types';
import { createType } from '../../../codec/create';
@@ -18,8 +18,8 @@ import ExtrinsicPayloadV4 from './ExtrinsicPayload';
* A container for the [[Signature]] associated with a specific [[Extrinsic]]
*/
export default class ExtrinsicSignatureV4 extends Struct implements IExtrinsicSignature {
constructor (value: ExtrinsicSignatureV4 | Uint8Array | undefined, { isSigned }: ExtrinsicSignatureOptions = {}) {
super({
constructor (registry: Registry, value: ExtrinsicSignatureV4 | Uint8Array | undefined, { isSigned }: ExtrinsicSignatureOptions = {}) {
super(registry, {
signer: 'Address',
signature: 'MultiSignature',
era: 'ExtrinsicEra',
@@ -113,9 +113,9 @@ export default class ExtrinsicSignatureV4 extends Struct implements IExtrinsicSi
*/
public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): IExtrinsicSignature {
return this.injectSignature(
createType('Address', signer),
createType('MultiSignature', signature),
new ExtrinsicPayloadV4(payload)
createType(this.registry, 'Address', signer),
createType(this.registry, 'MultiSignature', signature),
new ExtrinsicPayloadV4(this.registry, payload)
);
}
@@ -123,8 +123,8 @@ export default class ExtrinsicSignatureV4 extends Struct implements IExtrinsicSi
* @description Generate a payload and applies the signature from a keypair
*/
public sign (method: Call, account: IKeyringPair, { blockHash, era, genesisHash, nonce, runtimeVersion: { specVersion }, tip }: SignatureOptions): IExtrinsicSignature {
const signer = createType('Address', account.publicKey);
const payload = new ExtrinsicPayloadV4({
const signer = createType(this.registry, 'Address', account.publicKey);
const payload = new ExtrinsicPayloadV4(this.registry, {
blockHash,
era: era || IMMORTAL_ERA,
genesisHash,
@@ -133,7 +133,7 @@ export default class ExtrinsicSignatureV4 extends Struct implements IExtrinsicSi
specVersion,
tip: tip || 0
});
const signature = createType('MultiSignature', payload.sign(account));
const signature = createType(this.registry, 'MultiSignature', payload.sign(account));
return this.injectSignature(signer, signature, payload);
}
@@ -2,18 +2,18 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { setSS58Format } from '@polkadot/util-crypto';
import { createType } from '../../codec/create';
import { createType, TypeRegistry } from '../../codec/create';
import U8a from '../../codec/U8a';
import jsonVec from '../../json/AccountIdVec.001.json';
import AccountId from './AccountId';
describe('AccountId', (): void => {
const registry = new TypeRegistry();
describe('defaults', (): void => {
const id = createType('AccountId');
const id = createType(registry, 'AccountId');
it('has a 32-byte length', (): void => {
expect(id).toHaveLength(32);
@@ -31,20 +31,20 @@ describe('AccountId', (): void => {
describe('decoding', (): void => {
const testDecode = (type: string, input: Uint8Array | string | AccountId, expected: string): void =>
it(`can decode from ${type}`, (): void => {
const a = createType('AccountId', input);
const a = createType(registry, 'AccountId', input);
expect(a.toString()).toBe(expected);
});
testDecode(
'AccountId',
createType('AccountId', '0x0102030405060708010203040506070801020304050607080102030405060708'),
createType(registry, 'AccountId', '0x0102030405060708010203040506070801020304050607080102030405060708'),
'5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF'
);
testDecode('hex', '0x0102030405060708010203040506070801020304050607080102030405060708', '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF');
testDecode('string', '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF', '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF');
testDecode(
'U8a',
new U8a([
new U8a(registry, [
1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8,
1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8
]),
@@ -63,7 +63,7 @@ describe('AccountId', (): void => {
describe('encoding', (): void => {
const testEncode = (to: 'toHex' | 'toJSON' | 'toString' | 'toU8a', expected: Uint8Array | string, input = '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF'): void =>
it(`can encode ${to}`, (): void => {
const a = createType('AccountId', input);
const a = createType(registry, 'AccountId', input);
expect(a[to]()).toEqual(expected);
});
@@ -78,7 +78,7 @@ describe('AccountId', (): void => {
]));
it('decodes to a non-empty value', (): void => {
expect(createType('AccountId', '7qT1BvpawNbqb3BZaBTMFMMAKrpJKLPf1LmEHR1JyarWJdMX').isEmpty).toBe(false);
expect(createType(registry, 'AccountId', '7qT1BvpawNbqb3BZaBTMFMMAKrpJKLPf1LmEHR1JyarWJdMX').isEmpty).toBe(false);
});
});
@@ -86,8 +86,8 @@ describe('AccountId', (): void => {
it('has the correct entries', (): void => {
setSS58Format(68);
const data = createType('StorageData', jsonVec.params.result.changes[0][1]);
const list = createType('Vec<AccountId>', data).map((accountId): string => accountId.toString());
const data = createType(registry, 'StorageData', jsonVec.params.result.changes[0][1]);
const list = createType(registry, 'Vec<AccountId>', data).map((accountId): string => accountId.toString());
expect(list).toEqual([
'7qVJujLF3EDbZt5WfQXWvueFedMS4Vfk2Hb4GyR8jwksTLup',
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyString, AnyU8a } from '../../types';
import { AnyString, AnyU8a, Registry } from '../../types';
import { hexToU8a, isHex, isString, isU8a, u8aToU8a } from '@polkadot/util';
import { decodeAddress, encodeAddress } from '@polkadot/util-crypto';
@@ -17,11 +17,8 @@ import U8aFixed from '../../codec/U8aFixed';
* just a Uint8Array wrapper with a fixed length.
*/
export default class AccountId extends U8aFixed {
constructor (value: AnyU8a = new Uint8Array()) {
super(
AccountId.decodeAccountId(value),
256
);
constructor (registry: Registry, value: AnyU8a = new Uint8Array()) {
super(registry, AccountId.decodeAccountId(value), 256);
}
public static encode (value: Uint8Array): string {
@@ -2,44 +2,44 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import BN from 'bn.js';
import { createType } from '../../codec/create';
import { createType, TypeRegistry } from '../../codec/create';
import AccountIndex from './AccountIndex';
describe('AccountIndex', (): void => {
const registry = new TypeRegistry();
it('creates a BN representation', (): void => {
expect(
createType('AccountIndex', new Uint8Array([17, 18, 19, 20])).toNumber()
createType(registry, 'AccountIndex', new Uint8Array([17, 18, 19, 20])).toNumber()
).toEqual(336794129);
});
it('creates a BN representation (from ss-58)', (): void => {
expect(
createType('AccountIndex', 'Mwz15xP2').toNumber()
createType(registry, 'AccountIndex', 'Mwz15xP2').toNumber()
).toEqual(336794129);
});
it('constructs 2-byte from number', (): void => {
expect(
createType('AccountIndex', 256 * 1).toString()
createType(registry, 'AccountIndex', 256 * 1).toString()
).toEqual('25GUyv');
});
it('constructs from number', (): void => {
expect(
createType('AccountIndex', new BN(336794129)).toString()
createType(registry, 'AccountIndex', new BN(336794129)).toString()
).toEqual('Mwz15xP2');
});
it('compares ss-58 values', (): void => {
expect(createType('AccountIndex', 256 * 1).eq('25GUyv')).toBe(true);
expect(createType(registry, 'AccountIndex', 256 * 1).eq('25GUyv')).toBe(true);
});
it('compares numbers', (): void => {
expect(createType('AccountIndex', '2jpAFn').eq(256 * 1)).toBe(true);
expect(createType(registry, 'AccountIndex', '2jpAFn').eq(256 * 1)).toBe(true);
});
describe('calcLength', (): void => {
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyNumber } from '../../types';
import { AnyNumber, Registry } from '../../types';
import BN from 'bn.js';
import { bnToBn, isBn, isNumber, isU8a, isHex } from '@polkadot/util';
@@ -28,10 +28,8 @@ const MAX_4BYTE = new BN(1).shln(32);
* for an Account. We extends from [[U32]] to provide the number-like properties.
*/
export default class AccountIndex extends U32 {
constructor (value: AnyNumber = new BN(0)) {
super(
AccountIndex.decodeAccountIndex(value)
);
constructor (registry: Registry, value: AnyNumber = new BN(0)) {
super(registry, AccountIndex.decodeAccountIndex(value));
}
public static decodeAccountIndex (value: AnyNumber): BN | Uint8Array | number | string {
@@ -93,7 +91,7 @@ export default class AccountIndex extends U32 {
}
// convert and compare
return super.eq(createType('AccountIndex', other));
return super.eq(createType(this.registry, 'AccountIndex', other));
}
/**
@@ -2,17 +2,17 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import '../../injector';
import { createType } from '../../codec/create';
import { createType, TypeRegistry } from '../../codec/create';
import AccountId from './AccountId';
import AccountIndex from './AccountIndex';
import Address from './Address';
describe('Address', (): void => {
const registry = new TypeRegistry();
const testDecode = (type: string, input: Address | AccountId | AccountIndex | number[] | Uint8Array, expected: string): void =>
it(`can decode from ${type}`, (): void => {
const a = createType('Address', input);
const a = createType(registry, 'Address', input);
expect(a.toString()).toBe(expected);
});
@@ -20,35 +20,35 @@ describe('Address', (): void => {
it('equals on AccountId', (): void => {
const addr = '5DkQbYAExs3M2sZgT1Ec3mKfZnAQCL4Dt9beTCknkCUn5jzo';
expect(createType('Address', addr).eq(addr)).toBe(true);
expect(createType(registry, 'Address', addr).eq(addr)).toBe(true);
});
it('equals on AccountIndex', (): void => {
// see the test below - these are equivalent (with different prefix encoding)
expect(createType('Address', '2jpAFn').eq('25GUyv')).toBe(true);
expect(createType(registry, 'Address', '2jpAFn').eq('25GUyv')).toBe(true);
});
});
describe('decoding', (): void => {
testDecode(
'Address',
createType('Address', '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF'),
createType(registry, 'Address', '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF'),
'5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF'
);
testDecode(
'AccountId',
createType('AccountId', '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF'),
createType(registry, 'AccountId', '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF'),
'5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF'
);
testDecode(
'AccountIndex (mixed prefixes)',
createType('Address', '2jpAFn'),
createType(registry, 'Address', '2jpAFn'),
// NOTE Expected adress here is encoded with prefix 42, input above with 68
'25GUyv'
);
testDecode(
'AccountIndex (hex)',
createType('AccountIndex', '0x0100'),
createType(registry, 'AccountIndex', '0x0100'),
'25GUyv'
);
testDecode(
@@ -97,7 +97,7 @@ describe('Address', (): void => {
describe('encoding', (): void => {
const testEncode = (to: 'toHex' | 'toString' | 'toU8a', expected: string | Uint8Array): void =>
it(`can encode ${to}`, (): void => {
const a = createType('Address', '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF');
const a = createType(registry, 'Address', '5C62W7ELLAAfix9LYrcx5smtcffbhvThkM5x7xfMeYXCtGwF');
expect(a[to]()).toEqual(expected);
});
+15 -15
View File
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Registry } from '../../types';
import BN from 'bn.js';
import { isBn, isHex, isNumber, isU8a, u8aConcat, u8aToHex, u8aToU8a, u8aToBn } from '@polkadot/util';
import { decodeAddress } from '@polkadot/util-crypto';
@@ -24,46 +26,44 @@ export const ACCOUNT_ID_PREFIX = new Uint8Array([0xff]);
* is encoded as `[ <prefix-byte>, ...publicKey/...bytes ]` as per spec
*/
export default class Address extends Base<AccountId | AccountIndex> {
constructor (value: AnyAddress = new Uint8Array()) {
super(
Address.decodeAddress(value)
);
constructor (registry: Registry, value: AnyAddress = new Uint8Array()) {
super(registry, Address.decodeAddress(registry, value));
}
public static decodeAddress (value: AnyAddress): AccountId | AccountIndex {
public static decodeAddress (registry: Registry, value: AnyAddress): AccountId | AccountIndex {
if (value instanceof AccountId || value instanceof AccountIndex) {
return value;
} else if (value instanceof Address) {
return value.raw;
} else if (isBn(value) || isNumber(value)) {
return createType('AccountIndex', value);
return createType(registry, 'AccountIndex', value);
} else if (Array.isArray(value) || isHex(value) || isU8a(value)) {
return Address.decodeU8a(u8aToU8a(value));
return Address.decodeU8a(registry, u8aToU8a(value));
}
return Address.decodeString(value);
return Address.decodeString(registry, value);
}
private static decodeString (value: string): AccountId | AccountIndex {
private static decodeString (registry: Registry, value: string): AccountId | AccountIndex {
const decoded = decodeAddress(value);
return decoded.length === 32
? createType('AccountId', decoded)
: createType('AccountIndex', u8aToBn(decoded, true));
? createType(registry, 'AccountId', decoded)
: createType(registry, 'AccountIndex', u8aToBn(decoded, true));
}
private static decodeU8a (value: Uint8Array): AccountId | AccountIndex {
private static decodeU8a (registry: Registry, value: Uint8Array): AccountId | AccountIndex {
// This allows us to instantiate an address with a raw publicKey. Do this first before
// we checking the first byte, otherwise we may split an already-existent valid address
if (value.length === 32) {
return createType('AccountId', value);
return createType(registry, 'AccountId', value);
} else if (value[0] === 0xff) {
return createType('AccountId', value.subarray(1));
return createType(registry, 'AccountId', value.subarray(1));
}
const [offset, length] = AccountIndex.readLength(value);
return createType('AccountIndex', u8aToBn(value.subarray(offset, offset + length), true));
return createType(registry, 'AccountIndex', u8aToBn(value.subarray(offset, offset + length), true));
}
/**

Some files were not shown because too many files have changed in this diff Show More