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:
co-authored by
Amaury Martiny
parent
099992627b
commit
011e24bd49
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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"}>');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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()}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
}));
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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(',')})`;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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}`;
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
]);
|
||||
|
||||
|
||||
@@ -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()}>`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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'
|
||||
});
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}, {});
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user