diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c16c3e5ce..4c344c141c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ - Add support for `api.rpc.engine.*` for manual seal support - Expand `.toHuman` on `ExtrinsicEra`, `SubmittableResult` & `Vote` - Remove `GenericDigestItem`, the `DigestItem` is now a type interface via `@polkadot/types/interfaces` -- Move `H160`, `H256` & `H512` to interfaces in `@polkadot/types/interfaces` +- Move `Fixed64`, `H160`, `H256` & `H512` to interfaces in `@polkadot/types/interfaces` - Align construction of unknown types via `registry.get` e.g. in Events, warn on detection, throw on use - Expose static `.with` on `UInt`, `Int` & `U8aFixed` classes with optional type name override - `UInt` & `Int` now does source bitLength checks upon construction diff --git a/packages/typegen/src/generate/tsDef.ts b/packages/typegen/src/generate/tsDef.ts index 8644a1e914..6a8cee04b2 100644 --- a/packages/typegen/src/generate/tsDef.ts +++ b/packages/typegen/src/generate/tsDef.ts @@ -66,6 +66,12 @@ function tsEnum (definitions: object, { name: enumName, sub }: TypeDef, imports: return exportInterface(enumName, 'Enum', keys.join('')); } +function tsInt (definitions: object, def: TypeDef, imports: TypeImports, type: 'Int' | 'UInt' = 'Int'): string { + setImports(definitions, imports, [type]); + + return exportInterface(def.name, type); +} + /** @internal */ function tsResultGetter (definitions: object, resultName = '', getter: 'Ok' | 'Error', def: TypeDef, imports: TypeImports): string { const { info, type } = def; @@ -124,9 +130,7 @@ function tsStruct (definitions: object, { name: structName, sub }: TypeDef, impo /** @internal */ function tsUInt (definitions: object, def: TypeDef, imports: TypeImports): string { - setImports(definitions, imports, ['UInt']); - - return exportInterface(def.name, 'UInt'); + return tsInt(definitions, def, imports, 'UInt'); } /** @internal */ @@ -154,6 +158,7 @@ function generateInterfaces (definitions: object, { types }: { types: Record): string { })`; } -function encodeUInt (typeDef: Pick): string { +function encodeUInt (typeDef: Pick, type: 'Int' | 'UInt'): string { assert(typeDef.ext, 'Unable to encode VecFixed type'); const { length } = typeDef.ext as TypeDefExtUInt; - return `UInt<${length}>`; + return `${type}<${length}>`; } function encodeVecFixed (typeDef: Pick): string { @@ -126,6 +126,7 @@ const encoders: Record string> = { [TypeDefInfo.BTreeSet]: (typeDef: TypeDef): string => encodeWithParams(typeDef, 'BTreeSet'), [TypeDefInfo.Compact]: (typeDef: TypeDef): string => encodeWithParams(typeDef, 'Compact'), [TypeDefInfo.Enum]: (typeDef: TypeDef): string => encodeEnum(typeDef), + [TypeDefInfo.Int]: (typeDef: TypeDef): string => encodeUInt(typeDef, 'Int'), [TypeDefInfo.Linkage]: (typeDef: TypeDef): string => encodeWithParams(typeDef, 'Linkage'), // eslint-disable-next-line @typescript-eslint/no-unused-vars [TypeDefInfo.Null]: (typeDef: TypeDef): string => 'Null', @@ -135,7 +136,7 @@ const encoders: Record string> = { [TypeDefInfo.Set]: (typeDef: TypeDef): string => typeDef.type, [TypeDefInfo.Struct]: (typeDef: TypeDef): string => encodeStruct(typeDef), [TypeDefInfo.Tuple]: (typeDef: TypeDef): string => encodeTuple(typeDef), - [TypeDefInfo.UInt]: (typeDef: TypeDef): string => encodeUInt(typeDef), + [TypeDefInfo.UInt]: (typeDef: TypeDef): string => encodeUInt(typeDef, 'UInt'), [TypeDefInfo.Vec]: (typeDef: TypeDef): string => encodeWithParams(typeDef, 'Vec'), [TypeDefInfo.VecFixed]: (typeDef: TypeDef): string => encodeVecFixed(typeDef) }; diff --git a/packages/types/src/create/createClass.ts b/packages/types/src/create/createClass.ts index 8b8c0a2eb3..ffbd001513 100644 --- a/packages/types/src/create/createClass.ts +++ b/packages/types/src/create/createClass.ts @@ -11,6 +11,7 @@ import BTreeMap from '../codec/BTreeMap'; import BTreeSet from '../codec/BTreeSet'; import Compact from '../codec/Compact'; import Enum from '../codec/Enum'; +import Int from '../codec/Int'; import Option from '../codec/Option'; import Result from '../codec/Result'; import CodecSet from '../codec/Set'; @@ -76,6 +77,14 @@ function getTypeClassArray (value: TypeDef): (InterfaceTypes)[] { ); } +function createInt (value: TypeDef, Clazz: typeof Int | typeof UInt): Constructor { + assert(value.ext, `Expected bitLength information for ${Clazz.constructor.name}`); + + const ext = value.ext as TypeDefExtUInt; + + return Clazz.with(ext.length, ext.typeName); +} + const infoMapping: Record Constructor> = { [TypeDefInfo.BTreeMap]: (registry: Registry, value: TypeDef): Constructor => { const [keyType, valueType] = getTypeClassArray(value); @@ -90,6 +99,8 @@ const infoMapping: Record C [TypeDefInfo.Enum]: (registry: Registry, value: TypeDef): Constructor => Enum.with(getTypeClassMap(value)), + [TypeDefInfo.Int]: (registry: Registry, value: TypeDef): Constructor => createInt(value, Int), + // We have circular deps between Linkage & Struct [TypeDefInfo.Linkage]: (registry: Registry, value: TypeDef): Constructor => { const type = `Option<${getSubType(value)}>`; @@ -133,13 +144,7 @@ const infoMapping: Record C [TypeDefInfo.Tuple]: (registry: Registry, value: TypeDef): Constructor => Tuple.with(getTypeClassArray(value)), - [TypeDefInfo.UInt]: (registry: Registry, value: TypeDef): Constructor => { - assert(value.ext, 'Expected bitLength information for UInt'); - - const ext = value.ext as TypeDefExtUInt; - - return UInt.with(ext.length, ext.typeName); - }, + [TypeDefInfo.UInt]: (registry: Registry, value: TypeDef): Constructor => createInt(value, UInt), [TypeDefInfo.Vec]: (registry: Registry, value: TypeDef): Constructor => { const subType = getSubType(value); diff --git a/packages/types/src/create/createType.spec.ts b/packages/types/src/create/createType.spec.ts index b5e992f013..a20a1dc785 100644 --- a/packages/types/src/create/createType.spec.ts +++ b/packages/types/src/create/createType.spec.ts @@ -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 Int from '../codec/Int'; import CodecSet from '../codec/Set'; import { createClass, createType, createTypeUnsafe, ClassOf, TypeRegistry } from '.'; @@ -10,13 +11,22 @@ describe('createType', (): void => { it('allows creation of a H256 (with proper toRawType)', (): void => { expect( - createTypeUnsafe(registry, 'H256').toRawType() + createType(registry, 'H256').toRawType() ).toEqual('H256'); expect( - createTypeUnsafe(registry, 'Hash').toRawType() + createType(registry, 'Hash').toRawType() ).toEqual('H256'); }); + it('allows creation of a Fixed64 (with proper toRawType & instance)', (): void => { + const f64 = createType(registry, 'Fixed64'); + + expect(f64.toRawType()).toEqual('Fixed64'); + expect(f64.bitLength()).toEqual(64); + expect(f64.isUnsigned).toBe(false); + expect(f64 instanceof Int).toBe(true); + }); + it('allows creation of a Struct', (): void => { const raw = '{"balance":"Balance","index":"u32"}'; const struct = createTypeUnsafe(registry, raw, [{ diff --git a/packages/types/src/create/getTypeDef.ts b/packages/types/src/create/getTypeDef.ts index 5fce6cf5e4..8848b604ee 100644 --- a/packages/types/src/create/getTypeDef.ts +++ b/packages/types/src/create/getTypeDef.ts @@ -90,20 +90,24 @@ function _decodeTuple (value: TypeDef, _: string, subType: string): TypeDef { return value; } -// decode a fixed vector, e.g. [u8;32] +// decode a Int/UInt // eslint-disable-next-line @typescript-eslint/no-unused-vars -function _decodeUInt (value: TypeDef, type: string, _: string): TypeDef { - const _bitLength = type.substr(5, type.length - 6); - const length = parseInt(_bitLength.trim(), 10); +function _decodeInt (value: TypeDef, type: string, _: string, clazz: 'Int' | 'UInt' = 'Int'): TypeDef { + const [strLength, typeName] = type.substr(clazz.length + 1, type.length - clazz.length - 1 - 1).split(','); + const length = parseInt(strLength.trim(), 10); // as a first round, only u8 via u8aFixed, we can add more support - assert(length <= 8192 && (length % 8) === 0, `${type}: Only support for UInt, where length <= 8192 and a power of 8`); + assert(length <= 8192 && (length % 8) === 0, `${type}: Only support for ${clazz}, where length <= 8192 and a power of 8, found ${length}`); - value.ext = { length } as TypeDefExtUInt; + value.ext = { length, typeName } as TypeDefExtUInt; return value; } +function _decodeUInt (value: TypeDef, type: string, subType: string): TypeDef { + return _decodeInt(value, type, subType, 'UInt'); +} + function hasWrapper (type: string, [start, end]: [string, string, TypeDefInfo, any?]): boolean { if (type.substr(0, start.length) !== start) { return false; @@ -120,6 +124,7 @@ const nestedExtraction: [string, string, TypeDefInfo, (value: TypeDef, type: str ['(', ')', TypeDefInfo.Tuple, _decodeTuple], // the inner for these are the same as tuple, multiple values ['BTreeMap<', '>', TypeDefInfo.BTreeMap, _decodeTuple], + ['Int<', '>', TypeDefInfo.Int, _decodeInt], ['Result<', '>', TypeDefInfo.Result, _decodeTuple], ['UInt<', '>', TypeDefInfo.UInt, _decodeUInt] ]; diff --git a/packages/types/src/create/sanitize.ts b/packages/types/src/create/sanitize.ts index 0ee323a780..eda010f2d4 100644 --- a/packages/types/src/create/sanitize.ts +++ b/packages/types/src/create/sanitize.ts @@ -5,7 +5,7 @@ type Mapper = (value: string) => string; -const ALLOWED_BOXES = ['BTreeMap', 'BTreeSet', 'Compact', 'Linkage', 'Result', 'Option', 'UInt', 'Vec']; +const ALLOWED_BOXES = ['BTreeMap', 'BTreeSet', 'Compact', 'Int', 'Linkage', 'Result', 'Option', 'UInt', 'Vec']; const BOX_PRECEDING = ['<', '(', '[', '"', ',', ' ']; // start of vec, tuple, fixed array, part of struct def or in tuple const mappings: Mapper[] = [ diff --git a/packages/types/src/create/types.ts b/packages/types/src/create/types.ts index dc2ac49808..4e3104a4df 100644 --- a/packages/types/src/create/types.ts +++ b/packages/types/src/create/types.ts @@ -26,6 +26,7 @@ export enum TypeDefInfo { Tuple, Vec, VecFixed, + Int, UInt, // anything not fully supported (keep this as the last entry) Null diff --git a/packages/types/src/interfaceRegistry.ts b/packages/types/src/interfaceRegistry.ts index 5f41d56037..7c790cc1a0 100644 --- a/packages/types/src/interfaceRegistry.ts +++ b/packages/types/src/interfaceRegistry.ts @@ -2,8 +2,8 @@ /* eslint-disable @typescript-eslint/no-empty-interface */ import { Compact, Option, Raw, Vec } from '@polkadot/types/codec'; -import { BitVec, Bytes, Data, Fixed64, IdentityFields, Null, StorageData, StorageKey, Text, Type, U256, Unconstructable, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types/primitive'; -import { AccountId, AccountIdOf, AccountIndex, Address, AssetId, Balance, BalanceOf, Block, BlockNumber, Call, ChangesTrieConfiguration, Consensus, ConsensusEngineId, Digest, DigestItem, DispatchClass, DispatchInfo, DispatchInfoTo190, EcdsaSignature, Ed25519Signature, Extrinsic, ExtrinsicEra, ExtrinsicPayload, ExtrinsicPayloadUnknown, ExtrinsicPayloadV1, ExtrinsicPayloadV2, ExtrinsicPayloadV3, ExtrinsicPayloadV4, ExtrinsicSignatureV1, ExtrinsicSignatureV2, ExtrinsicSignatureV3, ExtrinsicSignatureV4, ExtrinsicUnknown, ExtrinsicV1, ExtrinsicV2, ExtrinsicV3, ExtrinsicV4, H160, H256, H512, Hash, Header, ImmortalEra, Index, Justification, KeyTypeId, KeyValue, LockIdentifier, LookupSource, LookupTarget, Moment, MortalEra, MultiSignature, Origin, Perbill, Percent, Permill, Perquintill, Phantom, PhantomData, PreRuntime, Seal, SealV0, Signature, SignedBlock, SignerPayload, Sr25519Signature, ValidatorId, Weight, WeightMultiplier } from '@polkadot/types/interfaces/runtime'; +import { BitVec, Bytes, Data, IdentityFields, Null, StorageData, StorageKey, Text, Type, U256, Unconstructable, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types/primitive'; +import { AccountId, AccountIdOf, AccountIndex, Address, AssetId, Balance, BalanceOf, Block, BlockNumber, Call, ChangesTrieConfiguration, Consensus, ConsensusEngineId, Digest, DigestItem, DispatchClass, DispatchInfo, DispatchInfoTo190, EcdsaSignature, Ed25519Signature, Extrinsic, ExtrinsicEra, ExtrinsicPayload, ExtrinsicPayloadUnknown, ExtrinsicPayloadV1, ExtrinsicPayloadV2, ExtrinsicPayloadV3, ExtrinsicPayloadV4, ExtrinsicSignatureV1, ExtrinsicSignatureV2, ExtrinsicSignatureV3, ExtrinsicSignatureV4, ExtrinsicUnknown, ExtrinsicV1, ExtrinsicV2, ExtrinsicV3, ExtrinsicV4, Fixed64, H160, H256, H512, Hash, Header, ImmortalEra, Index, Justification, KeyTypeId, KeyValue, LockIdentifier, LookupSource, LookupTarget, Moment, MortalEra, MultiSignature, Origin, Perbill, Percent, Permill, Perquintill, Phantom, PhantomData, PreRuntime, Seal, SealV0, Signature, SignedBlock, SignerPayload, Sr25519Signature, ValidatorId, Weight, WeightMultiplier } from '@polkadot/types/interfaces/runtime'; import { InclusionHeight, Uncle, UncleEntryItem } from '@polkadot/types/interfaces/authorship'; import { RawAuraPreDigest } from '@polkadot/types/interfaces/aura'; import { BabeAuthorityWeight, BabeBlockWeight, BabeWeight, MaybeVrf, RawBabePreDigest, RawBabePreDigestCompat, RawBabePreDigestPrimary, RawBabePreDigestPrimaryTo159, RawBabePreDigestSecondary, RawBabePreDigestSecondaryTo159, RawBabePreDigestTo159, SlotNumber, VrfData, VrfProof } from '@polkadot/types/interfaces/babe'; @@ -64,9 +64,6 @@ export interface InterfaceRegistry { i64: i64; 'Option': Option; 'Vec': Vec; - Fixed64: Fixed64; - 'Option': Option; - 'Vec': Vec; i128: i128; 'Option': Option; 'Vec': Vec; @@ -231,6 +228,9 @@ export interface InterfaceRegistry { DispatchInfoTo190: DispatchInfoTo190; 'Option': Option; 'Vec': Vec; + Fixed64: Fixed64; + 'Option': Option; + 'Vec': Vec; H160: H160; 'Option': Option; 'Vec': Vec; diff --git a/packages/types/src/interfaces/runtime/definitions.ts b/packages/types/src/interfaces/runtime/definitions.ts index 839ce89285..cc438c0d22 100644 --- a/packages/types/src/interfaces/runtime/definitions.ts +++ b/packages/types/src/interfaces/runtime/definitions.ts @@ -65,6 +65,7 @@ export default { weight: 'Weight', class: 'DispatchClass' }, + Fixed64: 'Int<64, Fixed64>', H160: '[u8; 20; H160]', H256: '[u8; 32; H256]', H512: '[u8; 64; H512]', diff --git a/packages/types/src/interfaces/runtime/types.ts b/packages/types/src/interfaces/runtime/types.ts index 98cd0911f3..1a8cc26077 100644 --- a/packages/types/src/interfaces/runtime/types.ts +++ b/packages/types/src/interfaces/runtime/types.ts @@ -2,10 +2,10 @@ /* eslint-disable @typescript-eslint/no-empty-interface */ import { ITuple } from '@polkadot/types/types'; -import { Compact, Enum, Struct, U8aFixed, Vec } from '@polkadot/types/codec'; +import { Compact, Enum, Int, Struct, U8aFixed, Vec } from '@polkadot/types/codec'; import { GenericExtrinsic, GenericExtrinsicEra, GenericExtrinsicPayload, GenericExtrinsicPayloadUnknown, GenericExtrinsicPayloadV1, GenericExtrinsicPayloadV2, GenericExtrinsicPayloadV3, GenericExtrinsicPayloadV4, GenericExtrinsicSignatureV1, GenericExtrinsicSignatureV2, GenericExtrinsicSignatureV3, GenericExtrinsicSignatureV4, GenericExtrinsicUnknown, GenericExtrinsicV1, GenericExtrinsicV2, GenericExtrinsicV3, GenericExtrinsicV4, GenericImmortalEra, GenericMortalEra, GenericSignerPayload } from '@polkadot/types/extrinsic'; import { GenericAccountId, GenericAccountIndex, GenericAddress, GenericBlock, GenericCall, GenericConsensusEngineId, GenericDigest, GenericOrigin } from '@polkadot/types/generic'; -import { Bytes, Fixed64, Null, StorageData, StorageKey, bool, u128, u32, u64, u8 } from '@polkadot/types/primitive'; +import { Bytes, Null, StorageData, StorageKey, bool, u128, u32, u64, u8 } from '@polkadot/types/primitive'; import { AuthorityId } from '@polkadot/types/interfaces/consensus'; /** @name AccountId */ @@ -147,6 +147,9 @@ export interface ExtrinsicV3 extends GenericExtrinsicV3 {} /** @name ExtrinsicV4 */ export interface ExtrinsicV4 extends GenericExtrinsicV4 {} +/** @name Fixed64 */ +export interface Fixed64 extends Int {} + /** @name H160 */ export interface H160 extends U8aFixed {} diff --git a/packages/types/src/interfaces/txpayment/types.ts b/packages/types/src/interfaces/txpayment/types.ts index 257d8e0418..4feea636dd 100644 --- a/packages/types/src/interfaces/txpayment/types.ts +++ b/packages/types/src/interfaces/txpayment/types.ts @@ -1,7 +1,7 @@ // Auto-generated via `yarn polkadot-types-from-defs`, do not edit /* eslint-disable @typescript-eslint/no-empty-interface */ -import { Fixed64 } from '@polkadot/types/primitive'; +import { Fixed64 } from '@polkadot/types/interfaces/runtime'; /** @name Multiplier */ export interface Multiplier extends Fixed64 {} diff --git a/packages/types/src/primitive/I64Fixed.ts b/packages/types/src/primitive/I64Fixed.ts deleted file mode 100644 index 078cd83f7d..0000000000 --- a/packages/types/src/primitive/I64Fixed.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017-2020 @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 I64 from './I64'; - -/** - * @name I64Fixed - * @description - * A 64-bit signed integer (Fixed64 in Rust) - */ -export default class I64Fixed extends I64 { -} diff --git a/packages/types/src/primitive/index.ts b/packages/types/src/primitive/index.ts index 254cc3260d..8ab3c73b38 100644 --- a/packages/types/src/primitive/index.ts +++ b/packages/types/src/primitive/index.ts @@ -17,7 +17,6 @@ export { default as i8 } from './I8'; export { default as i16 } from './I16'; export { default as i32 } from './I32'; export { default as i64 } from './I64'; -export { default as Fixed64 } from './I64Fixed'; export { default as i128 } from './I128'; export { default as i256 } from './I256'; export { default as Null } from './Null';