diff --git a/packages/types/README.md b/packages/types/README.md index a309eb4c92..4927d76777 100644 --- a/packages/types/README.md +++ b/packages/types/README.md @@ -14,7 +14,6 @@ These are the base types of the codec. They are typically not used directly, but | [[Base]] | A type extends the Base class, when it holds a value | | [[Compact]] | A compact length-encoding codec wrapper. Mostly used by other types to add length-prefixed encoding | | [[Enum]] | A codec wrapper for an enum. Enums are encoded as a single byte, where the byte is a zero-indexed value | -| [[EnumType]] | Implements an enum, which wraps a different type based on the value| | [[Int]] | A generic signed integer codec | | [[Option]] | An Option is an optional field. The first byte indicates that there is is value to follow | | [[Set]] | An Set is an array of string values, represented an an encoded type by a bitwise representation of the values | diff --git a/packages/types/src/Metadata/MetadataVersioned.ts b/packages/types/src/Metadata/MetadataVersioned.ts index fb6364c628..2b7b95f70a 100644 --- a/packages/types/src/Metadata/MetadataVersioned.ts +++ b/packages/types/src/Metadata/MetadataVersioned.ts @@ -4,9 +4,8 @@ import { assert, isUndefined } from '@polkadot/util'; -import EnumType from '../codec/EnumType'; +import Enum from '../codec/Enum'; import Struct from '../codec/Struct'; -import Null from '../primitive/Null'; import MagicNumber from './MagicNumber'; import MetadataV0 from './v0'; import MetadataV1 from './v1'; @@ -18,10 +17,7 @@ import v1ToV2 from './v1/toV2'; import v2ToV3 from './v2/toV3'; import v3ToV4 from './v3/toV4'; -class MetadataDeprecated extends Null { -} - -class MetadataEnum extends EnumType { +class MetadataEnum extends Enum { constructor (value?: any) { super({ MetadataV0, // once rolled-out, can replace this with MetadataDeprecated diff --git a/packages/types/src/Metadata/v0/Storage.ts b/packages/types/src/Metadata/v0/Storage.ts index cb8fc86ae8..0a87cf41ef 100644 --- a/packages/types/src/Metadata/v0/Storage.ts +++ b/packages/types/src/Metadata/v0/Storage.ts @@ -7,7 +7,6 @@ import { AnyNumber } from '../../types'; import { assert } from '@polkadot/util'; import Enum from '../../codec/Enum'; -import EnumType from '../../codec/EnumType'; import Struct from '../../codec/Struct'; import Vector from '../../codec/Vector'; import Bytes from '../../primitive/Bytes'; @@ -71,7 +70,7 @@ export class MapType extends Struct { export class PlainType extends Type { } -export class StorageFunctionType extends EnumType { +export class StorageFunctionType extends Enum { constructor (value?: any, index?: number) { super({ PlainType, diff --git a/packages/types/src/Metadata/v2/Storage.ts b/packages/types/src/Metadata/v2/Storage.ts index 67a4b37b8a..26dbece198 100644 --- a/packages/types/src/Metadata/v2/Storage.ts +++ b/packages/types/src/Metadata/v2/Storage.ts @@ -6,7 +6,7 @@ import { AnyNumber } from '../../types'; import { assert } from '@polkadot/util'; -import EnumType from '../../codec/EnumType'; +import Enum from '../../codec/Enum'; import Struct from '../../codec/Struct'; import Vector from '../../codec/Vector'; import Bool from '../../primitive/Bool'; @@ -52,7 +52,7 @@ export class MapType extends Struct { } } -export class StorageFunctionType extends EnumType { +export class StorageFunctionType extends Enum { constructor (value?: any, index?: number) { super({ PlainType, diff --git a/packages/types/src/Metadata/v3/Storage.ts b/packages/types/src/Metadata/v3/Storage.ts index 722788e048..f78379252d 100644 --- a/packages/types/src/Metadata/v3/Storage.ts +++ b/packages/types/src/Metadata/v3/Storage.ts @@ -6,7 +6,7 @@ import { AnyNumber } from '../../types'; import { assert } from '@polkadot/util'; -import EnumType from '../../codec/EnumType'; +import Enum from '../../codec/Enum'; import Struct from '../../codec/Struct'; import Vector from '../../codec/Vector'; import Bytes from '../../primitive/Bytes'; @@ -64,7 +64,7 @@ export class DoubleMapType extends Struct { } } -export class StorageFunctionType extends EnumType { +export class StorageFunctionType extends Enum { constructor (value?: any, index?: number) { super({ PlainType, diff --git a/packages/types/src/Metadata/v4/Storage.ts b/packages/types/src/Metadata/v4/Storage.ts index 568ca50889..581e58a1fa 100644 --- a/packages/types/src/Metadata/v4/Storage.ts +++ b/packages/types/src/Metadata/v4/Storage.ts @@ -6,7 +6,7 @@ import { AnyNumber } from '../../types'; import { assert } from '@polkadot/util'; -import EnumType from '../../codec/EnumType'; +import Enum from '../../codec/Enum'; import Struct from '../../codec/Struct'; import Vector from '../../codec/Vector'; import Bool from '../../primitive/Bool'; @@ -108,7 +108,7 @@ export class DoubleMapType extends Struct { } } -export class StorageFunctionType extends EnumType { +export class StorageFunctionType extends Enum { constructor (value?: any, index?: number) { super({ PlainType, diff --git a/packages/types/src/codec/Enum.spec.ts b/packages/types/src/codec/Enum.spec.ts deleted file mode 100644 index d5a251ad4d..0000000000 --- a/packages/types/src/codec/Enum.spec.ts +++ /dev/null @@ -1,83 +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 Enum from './Enum'; - -const testDecode = (type: string, input: any, expected: any) => - it(`can decode from ${type}`, () => { - const e = new Enum(['foo', 'bar'], input); - expect(e.toString()).toBe(expected); - }); - -const testEncode = (to: 'toJSON' | 'toNumber' | 'toString' | 'toU8a', expected: any) => - it(`can encode ${to}`, () => { - const e = new Enum(['foo', 'bar'], 1); - - expect(e[to]()).toEqual(expected); - }); - -describe('Enum', () => { - testDecode('Enum', undefined, 'foo'); - testDecode('Enum', new Enum([], 1), 'bar'); - testDecode('number', 0, 'foo'); - testDecode('number', 1, 'bar'); - testDecode('string', 'bar', 'bar'); - testDecode('Uint8Array', Uint8Array.from([0]), 'foo'); - testDecode('Uint8Array', Uint8Array.from([1]), 'bar'); - - testEncode('toJSON', 1); - testEncode('toNumber', 1); - testEncode('toString', 'bar'); - testEncode('toU8a', Uint8Array.from([1])); - - it('provides a clean toString()', () => { - expect( - new Enum(['foo', 'bar']).toString() - ).toEqual('foo'); - }); - - it('provides a clean toString() (enum)', () => { - expect( - new Enum(['foo', 'bar'], new Enum([], 1)).toNumber() - ).toEqual(1); - }); - - it('converts to and from U8a', () => { - expect( - new Enum(['foo', 'bar'], new Uint8Array([1])).toU8a() - ).toEqual(new Uint8Array([1])); - }); - - it('converts from JSON', () => { - expect( - new Enum(['foo', 'bar'], 5).toString() - ).toEqual('5'); - }); - - describe('utils', () => { - it('compares agains the index value', () => { - expect( - new Enum(['foo', 'bar'], 1).eq(1) - ).toBe(true); - }); - - it('compares agains the index value (false)', () => { - expect( - new Enum(['foo', 'bar'], 1).eq(0) - ).toBe(false); - }); - - it('compares agains the string value', () => { - expect( - new Enum(['foo', 'bar'], 1).eq('bar') - ).toBe(true); - }); - - it('compares agains the string value (false)', () => { - expect( - new Enum(['foo', 'bar'], 1).eq('foo') - ).toBe(false); - }); - }); -}); diff --git a/packages/types/src/codec/Enum.ts b/packages/types/src/codec/Enum.ts index d6823c3b6c..d53d8ca1c7 100644 --- a/packages/types/src/codec/Enum.ts +++ b/packages/types/src/codec/Enum.ts @@ -2,129 +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 { isString, isU8a, u8aToHex, assert } from '@polkadot/util'; +import Enum from './EnumType'; -import { Codec } from '../types'; -import Base from './Base'; - -type EnumMap = { - [index: number]: string -}; - -type EnumDef = { - [index: string]: number -} | Array; - -/** - * @name Enum - * @description - * A codec wrapper for an enum. Enums are encoded as a single byte, where the byte - * is a zero-indexed value. This class allows you to retrieve the value either - * by `toNumber()` exposing the actual raw index, or `toString()` returning a - * string representation (as provided as part of the constructor) - */ -// TODO: -// - It would be great if this could actually wrap actual TS enums -export default class Enum extends Base implements Codec { - private _enum: EnumMap | Array; - - constructor (def: EnumDef, value: Enum | Uint8Array | string | number = 0) { - const decoded = Enum.decodeEnum(def, value); - - assert(decoded !== -1, `Unable to initialise Enum with value ${value}`); - - super(decoded); - - this._enum = Array.isArray(def) - ? def - : Object.keys(def).reduce((result, key) => { - result[def[key]] = key; - - return result; - }, {} as EnumMap); - } - - static decodeEnum (def: EnumDef, value: Enum | Uint8Array | string | number): number | undefined { - if (value instanceof Enum) { - return value.raw; - } else if (isU8a(value)) { - return value[0]; - } else if (isString(value)) { - return Array.isArray(def) - ? def.indexOf(value) - : def[value] || -1; - } - - return value; - } - - /** - * @description The length of the value when encoded as a Uint8Array - */ - get encodedLength (): number { - return 1; - } - - /** - * @description Returns the index for this value (equivalent to toNumber) - */ - get index (): number { - return this.raw; - } - - /** - * @description Checks if the value is an empty value (always false) - */ - get isEmpty (): boolean { - return false; - } - - /** - * @description Compares the value of the input to see if there is a match - */ - eq (other?: any): boolean { - if (other instanceof Enum) { - return this.raw === other.raw; - } - - return isString(other) - ? this.toString() === other - : this.raw === other; - } - - /** - * @description Returns a hex string representation of the value - */ - toHex (): string { - return u8aToHex(this.toU8a()); - } - - /** - * @description Converts the Object to JSON, typically used for RPC transfers - */ - toJSON (): any { - return this.raw; - } - - /** - * @description Returns the number representation for the value - */ - toNumber (): number { - return this.raw; - } - - /** - * @description Returns the string representation of the value - */ - toString (): string { - return this._enum[this.raw] || `${this.raw}`; - } - - /** - * @description Encodes the value as a Uint8Array as per the parity-codec specifications - * @param isBare true when the value has none of the type-specific prefixes (internal) - */ - toU8a (isBare?: boolean): Uint8Array { - return new Uint8Array([this.raw]); - } -} +export default Enum; diff --git a/packages/types/src/codec/EnumType.spec.ts b/packages/types/src/codec/EnumType.spec.ts index 7330fc32e8..2f5796abc9 100644 --- a/packages/types/src/codec/EnumType.spec.ts +++ b/packages/types/src/codec/EnumType.spec.ts @@ -2,132 +2,213 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import EnumType from './EnumType'; +import Enum from './Enum'; import Null from '../primitive/Null'; import Text from '../primitive/Text'; import U32 from '../primitive/U32'; -describe('Struct', () => { - it('provides a clean toString() (value)', () => { - expect( - new EnumType( - { Text, U32 }, - new Uint8Array([0, 2 << 2, 49, 50]) - ).value.toString() - ).toEqual('12'); - }); - - it('provides a clean toString() (enum)', () => { - expect( - new EnumType( - { Text, U32 }, - new Uint8Array([1, 2 << 2, 49, 50]) - ).toString() - ).toEqual('{"U32":3289352}'); - }); - - it('decodes from a JSON input (lowercase)', () => { - expect( - new EnumType( - { Text, U32 }, - { 'text': 'some text value' } - ).value.toString() - ).toEqual('some text value'); - }); - - it('decodes from hex', () => { - expect( - new EnumType( - { Text, U32 }, - '0x0134120000' - ).value.toString() - ).toEqual('4660'); // 0x1234 in decimal - }); - - it('decodes from a JSON input (mixed case)', () => { - expect( - new EnumType( - { Text, U32 }, - { 'U32': 42 } - ).value.toString() - ).toEqual('42'); - }); - - it('decodes from JSON string', () => { - expect( - new EnumType( - { Null, U32 }, - 'null' - ).type - ).toEqual('Null'); - }); - - it('stringifies with custom types', () => { - class A extends Null { } - class B extends Null { } - class C extends Null { } - class Test extends EnumType { - constructor (value?: string, index?: number) { - super({ - a: A, - b: B, - c: C - }, value, index); - } - } - - expect(new Test().toJSON()).toEqual({ a: null }); - }); - - it('creates via with', () => { - class A extends Null { } - class B extends U32 { } - class C extends Null { } - const Test = EnumType.with({ A, B, C }); - - expect(new Test().toJSON()).toEqual({ A: null }); - expect(new Test(1234, 1).toJSON()).toEqual({ B: 1234 }); - }); - - // We are currently not using this approach, none of the types in Substrate currently - // have any overrides. Insteda of trying to support it (just-in-case), rather have it - // removed to simplyfy the code - it can be pulled-back if needed - it.skip('allows checking against defined indexes', () => { - expect( - new EnumType( - { 1: Text, 5: U32 }, - new Uint8Array([1, 2 << 2, 49, 50]) - ).toString() - ).toEqual('Text'); - }); - - it('allows accessing the type and value', () => { - const text = new Text('foo'); - const enumType = new EnumType( - { Text, U32 }, - { Text: text } - ); - - expect(enumType.type).toBe('Text'); - expect(enumType.value).toEqual(text); - }); - - describe('utils', () => { - const eqtest = new EnumType( - { U32, Text }, - new Uint8Array([1, 3 << 2, 88, 89, 90]) - ); - - it('compares against index', () => { +describe('Enum', () => { + describe('typed enum (previously EnumType)', () => { + it('provides a clean toString() (value)', () => { expect( - eqtest.eq(1) - ).toBe(true); + new Enum( + { Text, U32 }, + new Uint8Array([0, 2 << 2, 49, 50]) + ).value.toString() + ).toEqual('12'); }); - it('compares against values', () => { + it('provides a clean toString() (enum)', () => { expect( - eqtest.eq('XYZ') - ).toBe(true); + new Enum( + { Text, U32 }, + new Uint8Array([1, 2 << 2, 49, 50]) + ).toString() + ).toEqual('{"U32":3289352}'); + }); + + it('decodes from a JSON input (lowercase)', () => { + expect( + new Enum( + { Text, U32 }, + { 'text': 'some text value' } + ).value.toString() + ).toEqual('some text value'); + }); + + it('decodes from hex', () => { + expect( + new Enum( + { Text, U32 }, + '0x0134120000' + ).value.toString() + ).toEqual('4660'); // 0x1234 in decimal + }); + + it('decodes from a JSON input (mixed case)', () => { + expect( + new Enum( + { Text, U32 }, + { 'U32': 42 } + ).value.toString() + ).toEqual('42'); + }); + + it('decodes from JSON string', () => { + expect( + new Enum( + { Null, U32 }, + 'null' + ).type + ).toEqual('Null'); + }); + + it('stringifies with custom types', () => { + class A extends Null { } + class B extends Null { } + class C extends Null { } + class Test extends Enum { + constructor (value?: string, index?: number) { + super({ + a: A, + b: B, + c: C + }, value, index); + } + } + + expect(new Test().toJSON()).toEqual({ a: null }); + }); + + it('creates via with', () => { + class A extends Null { } + class B extends U32 { } + 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 }); + }); + + // We are currently not using this approach, none of the types in Substrate currently + // have any overrides. Instead of trying to support it (just-in-case), rather have it + // removed to simplify the code - it can be pulled-back if needed + it.skip('allows checking against defined indexes', () => { + expect( + new Enum( + { 1: Text, 5: U32 }, + new Uint8Array([1, 2 << 2, 49, 50]) + ).toString() + ).toEqual('Text'); + }); + + it('allows accessing the type and value', () => { + const text = new Text('foo'); + const enumType = new Enum( + { Text, U32 }, + { Text: text } + ); + + expect(enumType.type).toBe('Text'); + expect(enumType.value).toEqual(text); + }); + + describe('utils', () => { + const eqtest = new Enum( + { U32, Text }, + new Uint8Array([1, 3 << 2, 88, 89, 90]) + ); + + it('compares against index', () => { + expect( + eqtest.eq(1) + ).toBe(true); + }); + + it('compares against values', () => { + expect( + eqtest.eq('XYZ') + ).toBe(true); + }); + }); + }); + + describe('string-only construction (old Enum)', () => { + const testDecode = (type: string, input: any, expected: any) => + it(`can decode from ${type}`, () => { + const e = new Enum(['foo', 'bar'], input); + + expect(e.toString()).toBe(expected); + }); + + const testEncode = (to: 'toJSON' | 'toNumber' | 'toString' | 'toU8a', expected: any) => + it(`can encode ${to}`, () => { + const e = new Enum(['foo', 'bar'], 1); + + expect(e[to]()).toEqual(expected); + }); + + testDecode('Enum', undefined, 'foo'); + testDecode('Enum', new Enum(['foo', 'bar'], 1), 'bar'); + testDecode('number', 0, 'foo'); + testDecode('number', 1, 'bar'); + testDecode('string', 'bar', 'bar'); + testDecode('Uint8Array', Uint8Array.from([0]), 'foo'); + testDecode('Uint8Array', Uint8Array.from([1]), 'bar'); + + testEncode('toJSON', 1); + testEncode('toNumber', 1); + testEncode('toString', 'bar'); + testEncode('toU8a', Uint8Array.from([1])); + + it('provides a clean toString()', () => { + expect( + new Enum(['foo', 'bar']).toString() + ).toEqual('foo'); + }); + + it('provides a clean toString() (enum)', () => { + expect( + new Enum(['foo', 'bar'], new Enum(['foo', 'bar'], 1)).toNumber() + ).toEqual(1); + }); + + it('converts to and from U8a', () => { + expect( + new Enum(['foo', 'bar'], new Uint8Array([1])).toU8a() + ).toEqual(new Uint8Array([1])); + }); + + it('converts from JSON', () => { + expect( + new Enum(['foo', 'bar', 'baz', 'gaz', 'jaz'], 4).toNumber() + ).toEqual(4); + }); + + describe('utils', () => { + it('compares agains the index value', () => { + expect( + new Enum(['foo', 'bar'], 1).eq(1) + ).toBe(true); + }); + + it('compares agains the index value (false)', () => { + expect( + new Enum(['foo', 'bar'], 1).eq(0) + ).toBe(false); + }); + + it('compares agains the string value', () => { + expect( + new Enum(['foo', 'bar'], 1).eq('bar') + ).toBe(true); + }); + + it('compares agains the string value (false)', () => { + expect( + new Enum(['foo', 'bar'], 1).eq('foo') + ).toBe(false); + }); }); }); }); diff --git a/packages/types/src/codec/EnumType.ts b/packages/types/src/codec/EnumType.ts index 25515b213e..59e121b223 100644 --- a/packages/types/src/codec/EnumType.ts +++ b/packages/types/src/codec/EnumType.ts @@ -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, ConstructorDef } from '../types'; +import { Codec, Constructor } from '../types'; import { assert, hexToU8a, isHex, isNumber, isObject, isString, isU8a, isUndefined, u8aConcat, u8aToHex } from '@polkadot/util'; @@ -20,12 +20,8 @@ type Decoded = { value: Codec }; -type Aliasses = { - [index: string]: string -}; - /** - * @name EnumType + * @name Enum * @description * This implements an enum, that based on the value wraps a different type. It is effectively * an extension to enum where the value type is determined by the actual index. @@ -33,80 +29,93 @@ type Aliasses = { // TODO: // - As per Enum, actually use TS enum // - It should rather probably extend Enum instead of copying code -export default class EnumType extends Base implements Codec { +export default class Enum extends Base implements Codec { private _def: TypesDef; private _index: number; private _indexes: Array; + private _isBasic: boolean; - constructor (def: TypesDef, value?: any, index?: number | EnumType, aliasses?: Aliasses) { - const decoded = EnumType.decodeEnumType(def, aliasses || {}, value, index); + constructor (def: TypesDef | Array, value?: any, index?: number | Enum) { + const defInfo = Enum.extractDef(def); + const decoded = Enum.decodeEnum(defInfo.def, value, index); super(decoded.value); - this._def = def; - this._indexes = Object.keys(def).map((_, index) => index); + this._def = defInfo.def; + this._isBasic = defInfo.isBasic; + this._indexes = Object.keys(defInfo.def).map((_, index) => index); this._index = this._indexes.indexOf(decoded.index) || 0; } - private static decodeEnumType (def: TypesDef, aliasses: Aliasses, value?: any, index?: number | EnumType): Decoded { + private static extractDef (def: TypesDef | Array): { def: TypesDef, isBasic: boolean } { + if (!Array.isArray(def)) { + return { + def, + isBasic: false + }; + } + + return { + def: def.reduce((def, key) => { + def[key] = Null; + + return def; + }, {} as TypesDef), + isBasic: true + }; + } + + private static decodeEnum (def: TypesDef, value?: any, index?: number | Enum): Decoded { // If `index` is set, we parse it. - if (index instanceof EnumType) { - return EnumType.createValue(def, index._index, index.raw); + if (index instanceof Enum) { + return Enum.createValue(def, index._index, index.raw); } else if (isNumber(index)) { - return EnumType.createValue(def, index, value); + return Enum.createValue(def, index, value); } // Or else, we just look at `value` - return EnumType.decodeViaValue(def, aliasses, value); + return Enum.decodeViaValue(def, value); } - private static decodeViaValue (def: TypesDef, aliasses: Aliasses, value?: any): Decoded { - if (value instanceof EnumType) { - return EnumType.createValue(def, value._index, value.raw); + private static decodeViaValue (def: TypesDef, value?: any): Decoded { + if (value instanceof Enum) { + return Enum.createValue(def, value._index, value.raw); } else if (isU8a(value)) { - return EnumType.createValue(def, value[0], value.subarray(1)); + return Enum.createValue(def, value[0], value.subarray(1)); } else if (isNumber(value)) { - return EnumType.createValue(def, value); + return Enum.createValue(def, value); } else if (isString(value)) { const _str = value.toString(); return isHex(_str) - ? EnumType.decodeViaValue(def, aliasses, hexToU8a(_str)) - : EnumType.createViaJSON(def, aliasses, _str); + ? Enum.decodeViaValue(def, hexToU8a(_str)) + : Enum.createViaJSON(def, _str); } else if (isObject(value)) { const key = Object.keys(value)[0]; - return EnumType.createViaJSON(def, aliasses, key, value[key]); + return Enum.createViaJSON(def, key, value[key]); } // Worst-case scenario, return the first with default - return EnumType.createValue(def, 0); + return Enum.createValue(def, 0); } - private static createViaJSON (def: TypesDef, _aliasses: Aliasses, key: string, value?: any) { + private static createViaJSON (def: TypesDef, key: string, value?: any) { // JSON comes in the form of { "": "" }, here we // additionally force to lower to ensure forward compat const keys = Object.keys(def).map((k) => k.toLowerCase()); - - // FIXME This whole lookup process is not vey efficient const keyLower = key.toLowerCase(); - const aliasses = Object.keys(_aliasses).reduce((aliasses, a) => { - aliasses[a.toLowerCase()] = _aliasses[a].toLowerCase(); + const index = keys.indexOf(keyLower); - return aliasses; - }, {} as Aliasses); - const aliasKey = aliasses[keyLower] || keyLower; - const index = keys.indexOf(aliasKey); + assert(index !== -1, `Cannot map Enum JSON, unable to find '${key}' in ${keys.join(', ')}`); - assert(index !== -1, `Cannot map EnumType JSON, unable to find '${key}' in ${keys.join(', ')}`); - - return EnumType.createValue(def, index, value); + return Enum.createValue(def, index, value); } private static createValue (def: TypesDef, index: number = 0, value?: any): Decoded { const Clazz = Object.values(def)[index]; - assert(!isUndefined(Clazz), `Unable to create EnumType via index ${index}, in ${Object.keys(def).join(', ')}`); + assert(!isUndefined(Clazz), `Unable to create Enum via index ${index}, in ${Object.keys(def).join(', ')}`); return { index, @@ -114,10 +123,8 @@ export default class EnumType extends Base implements Codec { }; } - static with< - S extends ConstructorDef - > (Types: S): EnumConstructor> { - return class extends EnumType { + static with (Types: TypesDef | Array): EnumConstructor { + return class extends Enum { constructor (value?: any, index?: number) { super(Types, value, index); } @@ -180,6 +187,8 @@ export default class EnumType extends Base implements Codec { // cater for the case where we only pass the enum index if (isNumber(other)) { return this.toNumber() === other; + } else if (this._isBasic && isString(other)) { + return this.type === other; } // compare the actual wrapper value @@ -197,9 +206,9 @@ export default class EnumType extends Base implements Codec { * @description Converts the Object to JSON, typically used for RPC transfers */ toJSON (): any { - return { - [this.type]: this.raw.toJSON() - }; + return this._isBasic + ? this._index + : { [this.type]: this.raw.toJSON() }; } /** diff --git a/packages/types/src/codec/createType.ts b/packages/types/src/codec/createType.ts index 7d84ecad4f..580c6e0fad 100644 --- a/packages/types/src/codec/createType.ts +++ b/packages/types/src/codec/createType.ts @@ -8,7 +8,7 @@ import { Codec, Constructor } from '../types'; import Null from '../primitive/Null'; import Text from '../primitive/Text'; import Compact from './Compact'; -import EnumType from './EnumType'; +import Enum from './Enum'; import Linkage from './Linkage'; import Option from './Option'; import Struct from './Struct'; @@ -172,7 +172,7 @@ export function getTypeClass (value: TypeDef): Constructor { case TypeDefInfo.Enum: assert(value.sub && Array.isArray(value.sub), 'Expected subtype for Enum'); - return EnumType.with( + return Enum.with( (value.sub as Array).reduce((result, sub, index) => { result[sub.name as string] = getTypeClass(sub); diff --git a/packages/types/src/json/ExtrinsicStatus.001.json b/packages/types/src/json/ExtrinsicStatus.001.json index 59e486bc00..bcf9f069d6 100644 --- a/packages/types/src/json/ExtrinsicStatus.001.json +++ b/packages/types/src/json/ExtrinsicStatus.001.json @@ -3,8 +3,8 @@ "method": "author_extrinsicUpdate", "params": { "result": { - "finalised": "0xc465b92a72b1d20918d64cd4effa70c2bb58b53a3f8c24c3ac8fd8f465f059b4" + "finalized": "0xc465b92a72b1d20918d64cd4effa70c2bb58b53a3f8c24c3ac8fd8f465f059b4" }, "subscription": 9 } -} \ No newline at end of file +} diff --git a/packages/types/src/primitive/EventRecord.ts b/packages/types/src/primitive/EventRecord.ts index 11f2e948fc..be352190eb 100644 --- a/packages/types/src/primitive/EventRecord.ts +++ b/packages/types/src/primitive/EventRecord.ts @@ -4,7 +4,7 @@ import { assert } from '@polkadot/util'; -import EnumType from '../codec/EnumType'; +import Enum from '../codec/Enum'; import Struct from '../codec/Struct'; import Vector from '../codec/Vector'; import Hash from './Hash'; @@ -31,9 +31,9 @@ export class Finalization extends Null { /** * @name Phase * @description - * An [[EnumType]] that indicates the specific phase where the [[EventRecord]] was generated + * An [[Enum]] that indicates the specific phase where the [[EventRecord]] was generated */ -export class Phase extends EnumType { +export class Phase extends Enum { constructor (value: any, index?: number) { super({ ApplyExtrinsic, diff --git a/packages/types/src/primitive/StorageHasher.ts b/packages/types/src/primitive/StorageHasher.ts index b210168eaf..308ebe7bdc 100644 --- a/packages/types/src/primitive/StorageHasher.ts +++ b/packages/types/src/primitive/StorageHasher.ts @@ -6,7 +6,13 @@ import Enum from '../codec/Enum'; export default class StorageHasher extends Enum { constructor (value?: any) { - super(['Blake2_128', 'Blake2_256', 'Twox128', 'Twox256', 'Twox128Concat'], value); + super([ + 'Blake2_128', + 'Blake2_256', + 'Twox128', + 'Twox256', + 'Twox128Concat' + ], value); } /** diff --git a/packages/types/src/rpc/Digest.ts b/packages/types/src/rpc/Digest.ts index 128a77d4c7..7d21e236c7 100644 --- a/packages/types/src/rpc/Digest.ts +++ b/packages/types/src/rpc/Digest.ts @@ -4,7 +4,7 @@ import { assert } from '@polkadot/util'; -import EnumType from '../codec/EnumType'; +import Enum from '../codec/Enum'; import Struct from '../codec/Struct'; import Tuple from '../codec/Tuple'; import Vector from '../codec/Vector'; @@ -119,10 +119,9 @@ export class Consensus extends Tuple { /** * @name DigestItem * @description - * A [[EnumType]] the specifies the specific item in the logs of a [[Digest]] + * A [[Enum]] the specifies the specific item in the logs of a [[Digest]] */ -export class DigestItem extends EnumType { +export class DigestItem extends Enum { constructor (value: any) { super({ Other, // Position 0, as per Rust (encoding control) diff --git a/packages/types/src/rpc/ExtrinsicStatus.ts b/packages/types/src/rpc/ExtrinsicStatus.ts index 2496bd506a..57ced139ac 100644 --- a/packages/types/src/rpc/ExtrinsicStatus.ts +++ b/packages/types/src/rpc/ExtrinsicStatus.ts @@ -4,7 +4,7 @@ import { assert } from '@polkadot/util'; -import EnumType from '../codec/EnumType'; +import Enum from '../codec/Enum'; import Vector from '../codec/Vector'; import Hash from '../primitive/Hash'; import Null from '../primitive/Null'; @@ -69,9 +69,9 @@ export class Usurped extends Hash { /** * @name ExtrinsicStatus * @description - * An [[EnumType]] that indicates the status of the [[Extrinsic]] as been submitted + * An [[Enum]] that indicates the status of the [[Extrinsic]] as been submitted */ -export default class ExtrinsicStatus extends EnumType { +export default class ExtrinsicStatus extends Enum { constructor (value: any, index?: number) { super({ Future, @@ -81,9 +81,7 @@ export default class ExtrinsicStatus extends EnumType { +export class ValidityAttestation extends Enum { constructor (value?: any) { super({ // This Null is not in the original, however indexes start at 1, so add a diff --git a/packages/types/src/type/ContractInfo.ts b/packages/types/src/type/ContractInfo.ts index 34ee16e5bd..9313ef2939 100644 --- a/packages/types/src/type/ContractInfo.ts +++ b/packages/types/src/type/ContractInfo.ts @@ -5,7 +5,7 @@ import { assert } from '@polkadot/util'; import Bytes from '../primitive/Bytes'; -import EnumType from '../codec/EnumType'; +import Enum from '../codec/Enum'; import Struct from '../codec/Struct'; import Hash from '../primitive/Hash'; import U64 from '../primitive/U64'; @@ -62,7 +62,7 @@ export class Tombstone extends TombstoneContractInfo { * @description * The contract information for a given contract */ -export default class ContractInfo extends EnumType { +export default class ContractInfo extends Enum { constructor (value?: any) { super({ Alive, diff --git a/packages/types/src/type/MisbehaviorReport.ts b/packages/types/src/type/MisbehaviorReport.ts index b635f3131a..10d041e4b7 100644 --- a/packages/types/src/type/MisbehaviorReport.ts +++ b/packages/types/src/type/MisbehaviorReport.ts @@ -6,7 +6,7 @@ import { AnyNumber } from '../types'; import { assert } from '@polkadot/util'; -import EnumType from '../codec/EnumType'; +import Enum from '../codec/Enum'; import Struct from '../codec/Struct'; import Hash from '../primitive/Hash'; import U32 from '../primitive/U32'; @@ -118,9 +118,9 @@ export class BftDoubleCommit extends BftAtReport { /** * @name MisbehaviorKind * @description - * An [[EnumType]] containing a Bft misbehaviour + * An [[Enum]] containing a Bft misbehaviour */ -export class MisbehaviorKind extends EnumType { +export class MisbehaviorKind extends Enum { constructor (value?: BftAtReportValue | Uint8Array, index?: number) { super({ BftProposeOutOfTurn,