diff --git a/packages/types-known/src/bundle.ts b/packages/types-known/src/bundle.ts index c84db6cf6f..77c870f209 100644 --- a/packages/types-known/src/bundle.ts +++ b/packages/types-known/src/bundle.ts @@ -7,7 +7,7 @@ import type { Hash } from '@polkadot/types/interfaces'; import type { ChainUpgradeVersion, CodecHasher, DefinitionRpc, DefinitionRpcSub, OverrideModuleType, OverrideVersionedType, Registry, RegistryTypes } from '@polkadot/types/types'; import type { BN } from '@polkadot/util'; -import { bnToBn, isNull, isUndefined } from '@polkadot/util'; +import { bnToBn, isNull, isUndefined, objectSpread } from '@polkadot/util'; import typesChain from './chain'; import typesModules from './modules'; @@ -26,20 +26,16 @@ function filterVersions (versions: OverrideVersionedType[] = [], specVersion: nu (isUndefined(min) || isNull(min) || specVersion >= min) && (isUndefined(max) || isNull(max) || specVersion <= max) ) - .reduce((result: RegistryTypes, { types }): RegistryTypes => ({ - ...result, - ...types - }), {}); + .reduce((result: RegistryTypes, { types }): RegistryTypes => + objectSpread(result, types), {} + ); } /** * @description Get types for specific modules (metadata override) */ export function getModuleTypes ({ knownTypes }: Registry, section: string): OverrideModuleType { - return { - ...(typesModules[section] || {}), - ...(knownTypes.typesAlias?.[section] || {}) - }; + return objectSpread({}, typesModules[section], knownTypes.typesAlias?.[section]); } /** @@ -49,10 +45,10 @@ export function getSpecExtensions ({ knownTypes }: Registry, chainName: Text | s const _chainName = chainName.toString(); const _specName = specName.toString(); - return { - ...(knownTypes.typesBundle?.spec?.[_specName]?.signedExtensions || {}), - ...(knownTypes.typesBundle?.chain?.[_chainName]?.signedExtensions || {}) - }; + return objectSpread({}, + knownTypes.typesBundle?.spec?.[_specName]?.signedExtensions, + knownTypes.typesBundle?.chain?.[_chainName]?.signedExtensions + ); } /** @@ -67,15 +63,15 @@ export function getSpecTypes ({ knownTypes }: Registry, chainName: Text | string // - spec then chain // - typesBundle takes higher precedence // - types is the final catch-all override - return { - ...filterVersions(typesSpec[_specName], _specVersion), - ...filterVersions(typesChain[_chainName], _specVersion), - ...filterVersions(knownTypes.typesBundle?.spec?.[_specName]?.types, _specVersion), - ...filterVersions(knownTypes.typesBundle?.chain?.[_chainName]?.types, _specVersion), - ...(knownTypes.typesSpec?.[_specName] || {}), - ...(knownTypes.typesChain?.[_chainName] || {}), - ...(knownTypes.types || {}) - }; + return objectSpread({}, + filterVersions(typesSpec[_specName], _specVersion), + filterVersions(typesChain[_chainName], _specVersion), + filterVersions(knownTypes.typesBundle?.spec?.[_specName]?.types, _specVersion), + filterVersions(knownTypes.typesBundle?.chain?.[_chainName]?.types, _specVersion), + knownTypes.typesSpec?.[_specName], + knownTypes.typesChain?.[_chainName], + knownTypes.types + ); } export function getSpecHasher ({ knownTypes }: Registry, chainName: Text | string, specName: Text | string): CodecHasher | null { @@ -92,10 +88,10 @@ export function getSpecRpc ({ knownTypes }: Registry, chainName: Text | string, const _chainName = chainName.toString(); const _specName = specName.toString(); - return { - ...(knownTypes.typesBundle?.spec?.[_specName]?.rpc || {}), - ...(knownTypes.typesBundle?.chain?.[_chainName]?.rpc || {}) - }; + return objectSpread({}, + knownTypes.typesBundle?.spec?.[_specName]?.rpc, + knownTypes.typesBundle?.chain?.[_chainName]?.rpc + ); } /** @@ -106,11 +102,11 @@ export function getSpecAlias ({ knownTypes }: Registry, chainName: Text | string const _specName = specName.toString(); // as per versions, first spec, then chain then finally non-versioned - return { - ...(knownTypes.typesBundle?.spec?.[_specName]?.alias || {}), - ...(knownTypes.typesBundle?.chain?.[_chainName]?.alias || {}), - ...(knownTypes.typesAlias || {}) - }; + return objectSpread({}, + knownTypes.typesBundle?.spec?.[_specName]?.alias, + knownTypes.typesBundle?.chain?.[_chainName]?.alias, + knownTypes.typesAlias + ); } /** diff --git a/packages/types-known/src/spec/centrifuge-chain.ts b/packages/types-known/src/spec/centrifuge-chain.ts index b21f944cb8..21b17e2a28 100644 --- a/packages/types-known/src/spec/centrifuge-chain.ts +++ b/packages/types-known/src/spec/centrifuge-chain.ts @@ -5,6 +5,8 @@ import type { OverrideVersionedType } from '@polkadot/types/types'; +import { objectSpread } from '@polkadot/util'; + const sharedTypes = { // Anchor AnchorData: { @@ -79,20 +81,18 @@ const sharedTypes = { } }; -const standaloneTypes = { - ...sharedTypes, +const standaloneTypes = objectSpread({}, sharedTypes, { AccountInfo: 'AccountInfoWithRefCount', Address: 'LookupSource', LookupSource: 'IndicesLookupSource', Multiplier: 'Fixed64', RefCount: 'RefCountTo259' -}; +}); const versioned: OverrideVersionedType[] = [ { minmax: [240, 243], - types: { - ...standaloneTypes, + types: objectSpread({}, standaloneTypes, { ProxyType: { _enum: [ 'Any', @@ -102,19 +102,15 @@ const versioned: OverrideVersionedType[] = [ 'Vesting' ] } - } + }) }, { minmax: [244, 999], - types: { - ...standaloneTypes - } + types: objectSpread({}, standaloneTypes) }, { minmax: [1000, undefined], - types: { - ...sharedTypes - } + types: objectSpread({}, sharedTypes) } ]; diff --git a/packages/types-known/src/spec/kusama.ts b/packages/types-known/src/spec/kusama.ts index 593e9064ce..5c420ed4f8 100644 --- a/packages/types-known/src/spec/kusama.ts +++ b/packages/types-known/src/spec/kusama.ts @@ -5,6 +5,8 @@ import type { OverrideVersionedType } from '@polkadot/types/types'; +import { objectSpread } from '@polkadot/util'; + import { mapXcmTypes } from '../xcm'; const sharedTypes = { @@ -40,8 +42,7 @@ const versioned: OverrideVersionedType[] = [ { // 1020 is first CC3 minmax: [1019, 1031], - types: { - ...addrIndicesTypes, + types: objectSpread({}, addrIndicesTypes, { BalanceLock: 'BalanceLockTo212', CompactAssignments: 'CompactAssignmentsTo257', DispatchError: 'DispatchErrorTo198', @@ -57,12 +58,11 @@ const versioned: OverrideVersionedType[] = [ StakingLedger: 'StakingLedgerTo223', Votes: 'VotesTo230', Weight: 'u32' - } + }) }, { minmax: [1032, 1042], - types: { - ...addrIndicesTypes, + types: objectSpread({}, addrIndicesTypes, { BalanceLock: 'BalanceLockTo212', CompactAssignments: 'CompactAssignmentsTo257', DispatchInfo: 'DispatchInfoTo244', @@ -76,13 +76,12 @@ const versioned: OverrideVersionedType[] = [ StakingLedger: 'StakingLedgerTo223', Votes: 'VotesTo230', Weight: 'u32' - } + }) }, { // actual at 1045 (1043-1044 is dev) minmax: [1043, 1045], - types: { - ...addrIndicesTypes, + types: objectSpread({}, addrIndicesTypes, { BalanceLock: 'BalanceLockTo212', CompactAssignments: 'CompactAssignmentsTo257', DispatchInfo: 'DispatchInfoTo244', @@ -95,14 +94,11 @@ const versioned: OverrideVersionedType[] = [ StakingLedger: 'StakingLedgerTo223', Votes: 'VotesTo230', Weight: 'u32' - } + }) }, { minmax: [1046, 1054], - types: { - // Indices optional, not in transaction - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { CompactAssignments: 'CompactAssignmentsTo257', DispatchInfo: 'DispatchInfoTo244', Heartbeat: 'HeartbeatTo244', @@ -112,13 +108,11 @@ const versioned: OverrideVersionedType[] = [ ReferendumInfo: 'ReferendumInfoTo239', StakingLedger: 'StakingLedgerTo240', Weight: 'u32' - } + }) }, { minmax: [1055, 1056], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { CompactAssignments: 'CompactAssignmentsTo257', DispatchInfo: 'DispatchInfoTo244', Heartbeat: 'HeartbeatTo244', @@ -127,92 +121,71 @@ const versioned: OverrideVersionedType[] = [ RefCount: 'RefCountTo259', StakingLedger: 'StakingLedgerTo240', Weight: 'u32' - } + }) }, { minmax: [1057, 1061], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { CompactAssignments: 'CompactAssignmentsTo257', DispatchInfo: 'DispatchInfoTo244', Heartbeat: 'HeartbeatTo244', OpenTip: 'OpenTipTo225', RefCount: 'RefCountTo259' - } + }) }, { minmax: [1062, 2012], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { CompactAssignments: 'CompactAssignmentsTo257', OpenTip: 'OpenTipTo225', RefCount: 'RefCountTo259' - } + }) }, { minmax: [2013, 2022], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { CompactAssignments: 'CompactAssignmentsTo257', RefCount: 'RefCountTo259' - } + }) }, { minmax: [2023, 2024], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { RefCount: 'RefCountTo259' - } + }) }, { minmax: [2025, 2027], - types: { - ...sharedTypes, - ...addrAccountIdTypes - } + types: objectSpread({}, sharedTypes, addrAccountIdTypes) }, { minmax: [2028, 2029], - types: { - ...sharedTypes, + types: objectSpread({}, sharedTypes, { AccountInfo: 'AccountInfoWithDualRefCount', CompactAssignments: 'CompactAssignmentsWith16', RawSolution: 'RawSolutionWith16' - } + }) }, { minmax: [2030, 9000], - types: { - ...sharedTypes, + types: objectSpread({}, sharedTypes, { CompactAssignments: 'CompactAssignmentsWith16', RawSolution: 'RawSolutionWith16' - } + }) }, { minmax: [9010, 9099], - types: { - ...sharedTypes, - ...mapXcmTypes('V0') - } + types: objectSpread({}, sharedTypes, mapXcmTypes('V0')) }, { // jump from 9100 to 9110, however align with Rococo minmax: [9100, 9105], - types: { - ...sharedTypes, - ...mapXcmTypes('V1') - } + types: objectSpread({}, sharedTypes, mapXcmTypes('V1')) }, { // metadata v14 minmax: [9106, undefined], - types: { - ...sharedTypes - } + types: objectSpread({}, sharedTypes) } ]; diff --git a/packages/types-known/src/spec/polkadot.ts b/packages/types-known/src/spec/polkadot.ts index 2da85c328b..d0eaca7fde 100644 --- a/packages/types-known/src/spec/polkadot.ts +++ b/packages/types-known/src/spec/polkadot.ts @@ -5,6 +5,8 @@ import type { OverrideVersionedType } from '@polkadot/types/types'; +import { objectSpread } from '@polkadot/util'; + const sharedTypes = { CompactAssignments: 'CompactAssignmentsWith16', RawSolution: 'RawSolutionWith16', @@ -35,57 +37,43 @@ const addrAccountIdTypes = { const versioned: OverrideVersionedType[] = [ { minmax: [0, 12], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { CompactAssignments: 'CompactAssignmentsTo257', OpenTip: 'OpenTipTo225', RefCount: 'RefCountTo259' - } + }) }, { minmax: [13, 22], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { CompactAssignments: 'CompactAssignmentsTo257', RefCount: 'RefCountTo259' - } + }) }, { minmax: [23, 24], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { RefCount: 'RefCountTo259' - } + }) }, { minmax: [25, 27], - types: { - ...sharedTypes, - ...addrAccountIdTypes - } + types: objectSpread({}, sharedTypes, addrAccountIdTypes) }, { minmax: [28, 29], - types: { - ...sharedTypes, + types: objectSpread({}, sharedTypes, { AccountInfo: 'AccountInfoWithDualRefCount' - } + }) }, { minmax: [30, 9109], - types: { - ...sharedTypes - } + types: objectSpread({}, sharedTypes) }, { // metadata v14 minmax: [9110, undefined], - types: { - ...sharedTypes - } + types: objectSpread({}, sharedTypes) } ]; diff --git a/packages/types-known/src/spec/rococo.ts b/packages/types-known/src/spec/rococo.ts index 92f619e4dd..f98aa6bfc5 100644 --- a/packages/types-known/src/spec/rococo.ts +++ b/packages/types-known/src/spec/rococo.ts @@ -5,6 +5,8 @@ import type { OverrideVersionedType } from '@polkadot/types/types'; +import { objectSpread } from '@polkadot/util'; + import { mapXcmTypes } from '../xcm'; // structs need to be in order @@ -18,47 +20,36 @@ const sharedTypes = { const versioned: OverrideVersionedType[] = [ { minmax: [0, 200], - types: { - ...sharedTypes, + types: objectSpread({}, sharedTypes, { AccountInfo: 'AccountInfoWithDualRefCount', Address: 'AccountId', LookupSource: 'AccountId' - } + }) }, { minmax: [201, 214], - types: { - ...sharedTypes, + types: objectSpread({}, sharedTypes, { AccountInfo: 'AccountInfoWithDualRefCount' - } + }) }, { minmax: [215, 228], - types: { - ...sharedTypes, + types: objectSpread({}, sharedTypes, { Keys: 'SessionKeys6' - } + }) }, { minmax: [229, 9099], - types: { - ...sharedTypes, - ...mapXcmTypes('V0') - } + types: objectSpread({}, sharedTypes, mapXcmTypes('V0')) }, { minmax: [9100, 9105], - types: { - ...sharedTypes, - ...mapXcmTypes('V1') - } + types: objectSpread({}, sharedTypes, mapXcmTypes('V1')) }, { // metadata v14 minmax: [9106, undefined], - types: { - ...sharedTypes - } + types: objectSpread({}, sharedTypes) } ]; diff --git a/packages/types-known/src/spec/statemint.ts b/packages/types-known/src/spec/statemint.ts index 4aa1303f62..8f417b3f11 100644 --- a/packages/types-known/src/spec/statemint.ts +++ b/packages/types-known/src/spec/statemint.ts @@ -5,6 +5,8 @@ import type { OverrideVersionedType } from '@polkadot/types/types'; +import { objectSpread } from '@polkadot/util'; + import { mapXcmTypes } from '../xcm'; const sharedTypes = { @@ -26,24 +28,16 @@ const sharedTypes = { const versioned: OverrideVersionedType[] = [ { minmax: [0, 3], - types: { - ...sharedTypes, - ...mapXcmTypes('V0') - } + types: objectSpread({}, sharedTypes, mapXcmTypes('V0')) }, { minmax: [4, 5], - types: { - ...sharedTypes, - ...mapXcmTypes('V1') - } + types: objectSpread({}, sharedTypes, mapXcmTypes('V1')) }, { // metadata V14 minmax: [500, undefined], - types: { - ...sharedTypes - } + types: objectSpread({}, sharedTypes) } ]; diff --git a/packages/types-known/src/spec/westend.ts b/packages/types-known/src/spec/westend.ts index d2ff324e95..b2512764d9 100644 --- a/packages/types-known/src/spec/westend.ts +++ b/packages/types-known/src/spec/westend.ts @@ -5,6 +5,8 @@ import type { OverrideVersionedType } from '@polkadot/types/types'; +import { objectSpread } from '@polkadot/util'; + import { mapXcmTypes } from '../xcm'; const sharedTypes = { @@ -31,9 +33,7 @@ const addrAccountIdTypes = { const versioned: OverrideVersionedType[] = [ { minmax: [1, 2], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { CompactAssignments: 'CompactAssignmentsTo257', DispatchInfo: 'DispatchInfoTo244', Heartbeat: 'HeartbeatTo244', @@ -41,75 +41,57 @@ const versioned: OverrideVersionedType[] = [ OpenTip: 'OpenTipTo225', RefCount: 'RefCountTo259', Weight: 'u32' - } + }) }, { minmax: [3, 22], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { CompactAssignments: 'CompactAssignmentsTo257', DispatchInfo: 'DispatchInfoTo244', Heartbeat: 'HeartbeatTo244', OpenTip: 'OpenTipTo225', RefCount: 'RefCountTo259' - } + }) }, { minmax: [23, 42], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { CompactAssignments: 'CompactAssignmentsTo257', DispatchInfo: 'DispatchInfoTo244', Heartbeat: 'HeartbeatTo244', RefCount: 'RefCountTo259' - } + }) }, { minmax: [43, 44], - types: { - ...sharedTypes, - ...addrAccountIdTypes, + types: objectSpread({}, sharedTypes, addrAccountIdTypes, { DispatchInfo: 'DispatchInfoTo244', Heartbeat: 'HeartbeatTo244', RefCount: 'RefCountTo259' - } + }) }, { minmax: [45, 47], - types: { - ...sharedTypes, - ...addrAccountIdTypes - } + types: objectSpread({}, sharedTypes, addrAccountIdTypes) }, { minmax: [48, 49], - types: { - ...sharedTypes, + types: objectSpread({}, sharedTypes, { AccountInfo: 'AccountInfoWithDualRefCount' - } + }) }, { minmax: [50, 9099], - types: { - ...sharedTypes, - ...mapXcmTypes('V0') - } + types: objectSpread({}, sharedTypes, mapXcmTypes('V0')) }, { minmax: [9100, 9105], - types: { - ...sharedTypes, - ...mapXcmTypes('V1') - } + types: objectSpread({}, sharedTypes, mapXcmTypes('V1')) }, { // metadata v14 minmax: [9106, undefined], - types: { - ...sharedTypes - } + types: objectSpread({}, sharedTypes) } ]; diff --git a/packages/types-known/src/xcm.ts b/packages/types-known/src/xcm.ts index 692b357471..c9e690bd71 100644 --- a/packages/types-known/src/xcm.ts +++ b/packages/types-known/src/xcm.ts @@ -1,11 +1,12 @@ // Copyright 2017-2021 @polkadot/types-known authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { objectSpread } from '@polkadot/util'; + export const XCM_MAPPINGS = ['AssetInstance', 'Fungibility', 'Junction', 'Junctions', 'MultiAsset', 'MultiAssetFilter', 'MultiLocation', 'Response', 'WildFungibility', 'WildMultiAsset', 'Xcm', 'XcmError', 'XcmOrder']; export function mapXcmTypes (version: 'V0' | 'V1' | 'V2'): Record { - return XCM_MAPPINGS.reduce>((all, key) => ({ - ...all, - [key]: `${key}${version}` - }), {}); + return XCM_MAPPINGS.reduce>((all, key) => + objectSpread(all, { [key]: `${key}${version}` }), {} + ); } diff --git a/packages/types/src/augment/lookup/definitions.ts b/packages/types/src/augment/lookup/definitions.ts index 7490f98215..8fc4d97141 100644 --- a/packages/types/src/augment/lookup/definitions.ts +++ b/packages/types/src/augment/lookup/definitions.ts @@ -3,17 +3,15 @@ import type { Definitions } from '../../types'; +import { objectSpread } from '@polkadot/util'; + import kusama from './kusama'; import polkadot from './polkadot'; import substrate from './substrate'; export default { rpc: {}, - types: { - // Not 100% sure it is relevant, however the order here is the same - // as exposed in the typegen lookup order - ...substrate, - ...polkadot, - ...kusama - } + // Not 100% sure it is relevant, however the order here is the same + // as exposed in the typegen lookup order + types: objectSpread({}, substrate, polkadot, kusama) } as Definitions; diff --git a/packages/types/src/codec/AbstractArray.ts b/packages/types/src/codec/AbstractArray.ts index cac1e5fbfc..c2bd1173dd 100644 --- a/packages/types/src/codec/AbstractArray.ts +++ b/packages/types/src/codec/AbstractArray.ts @@ -21,7 +21,7 @@ export abstract class AbstractArray extends Array implements public createdAtHash?: Hash; - readonly #initialU8aLength?: number; + readonly initialU8aLength?: number; protected constructor (registry: Registry, values: T[], initialU8aLength?: number) { super(values.length); @@ -32,7 +32,7 @@ export abstract class AbstractArray extends Array implements } this.registry = registry; - this.#initialU8aLength = initialU8aLength; + this.initialU8aLength = initialU8aLength; } /** @@ -50,13 +50,6 @@ export abstract class AbstractArray extends Array implements return total; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public get initialU8aLength (): number | undefined { - return this.#initialU8aLength; - } - /** * @description returns a hash of the contents */ diff --git a/packages/types/src/codec/AbstractInt.ts b/packages/types/src/codec/AbstractInt.ts index 5a9af9858d..b5be1ab47a 100644 --- a/packages/types/src/codec/AbstractInt.ts +++ b/packages/types/src/codec/AbstractInt.ts @@ -6,7 +6,7 @@ import type { CodecHash, Hash } from '../interfaces/runtime'; import type { AnyNumber, INumber, Registry } from '../types'; import type { UIntBitLength } from './types'; -import { assert, BN, BN_BILLION, BN_HUNDRED, BN_MILLION, BN_QUINTILL, BN_ZERO, bnToBn, bnToHex, bnToU8a, formatBalance, formatNumber, hexToBn, isHex, isString, isU8a, stringify, u8aToBn } from '@polkadot/util'; +import { assert, BN, BN_BILLION, BN_HUNDRED, BN_MILLION, BN_QUINTILL, BN_ZERO, bnToBn, bnToHex, bnToU8a, formatBalance, formatNumber, hexToBn, isBn, isHex, isU8a, stringify, u8aToBn } from '@polkadot/util'; export const DEFAULT_UINT_BITS = 64; @@ -26,31 +26,26 @@ function toPercentage (value: BN, divisor: BN): string { return `${(value.mul(MUL_P).div(divisor).toNumber() / 100).toFixed(2)}%`; } -/** @internal */ -function decodeAbstracIntU8a (value: Uint8Array, bitLength: UIntBitLength, isNegative: boolean): string { - if (!value.length) { - return '0'; - } - - try { - // NOTE When passing u8a in (typically from decoded data), it is always Little Endian - return u8aToBn(value.subarray(0, bitLength / 8), { isLe: true, isNegative }).toString(); - } catch (error) { - throw new Error(`AbstractInt: failed on ${stringify(value)}:: ${(error as Error).message}`); - } -} - /** @internal */ function decodeAbstractInt (value: AnyNumber, bitLength: UIntBitLength, isNegative: boolean): string { // This function returns a string, which will be passed in the BN // constructor. It would be ideal to actually return a BN, but there's a // bug: https://github.com/indutny/bn.js/issues/206. - if (isHex(value, -1, true)) { + if (isU8a(value)) { + if (!value.length) { + return '0'; + } + + try { + // NOTE When passing u8a in (typically from decoded data), it is always Little Endian + return u8aToBn(value.subarray(0, bitLength / 8), { isLe: true, isNegative }).toString(); + } catch (error) { + throw new Error(`AbstractInt: failed on ${stringify(value)}:: ${(error as Error).message}`); + } + } else if (isBn(value)) { + return value.toString(); + } else if (isHex(value, -1, true)) { return hexToBn(value, { isLe: false, isNegative }).toString(); - } else if (isU8a(value)) { - return decodeAbstracIntU8a(value, bitLength, isNegative); - } else if (isString(value)) { - return new BN(value.toString(), 10).toString(); } return bnToBn(value).toString(); @@ -66,9 +61,9 @@ export abstract class AbstractInt extends BN implements INumber { public createdAtHash?: Hash; - readonly #bitLength: UIntBitLength; + readonly encodedLength: number; - readonly #byteLength: number; + readonly #bitLength: UIntBitLength; readonly #isSigned: boolean; @@ -77,7 +72,7 @@ export abstract class AbstractInt extends BN implements INumber { this.registry = registry; this.#bitLength = bitLength; - this.#byteLength = this.#bitLength / 8; + this.encodedLength = this.#bitLength / 8; this.#isSigned = isSigned; const isPositive = this.gte(BN_ZERO); @@ -87,13 +82,6 @@ export abstract class AbstractInt extends BN implements INumber { assert(super.bitLength() <= maxBits, () => `${this.toRawType()}: Input too large. Found input with ${super.bitLength()} bits, expected ${maxBits}`); } - /** - * @description The length of the value when encoded as a Uint8Array - */ - public get encodedLength (): number { - return this.#byteLength; - } - /** * @description returns a hash of the contents */ diff --git a/packages/types/src/codec/BTreeSet.ts b/packages/types/src/codec/BTreeSet.ts index 608173535c..2ea3b2bf60 100644 --- a/packages/types/src/codec/BTreeSet.ts +++ b/packages/types/src/codec/BTreeSet.ts @@ -62,7 +62,7 @@ function decodeSet (registry: Registry, valType: Constructor const ValClass = typeToConstructor(registry, valType); - if (isHex(value) || isU8a(value)) { + if (isU8a(value) || isHex(value)) { return decodeSetFromU8a(registry, ValClass, u8aToU8a(value)); } else if (Array.isArray(value) || value instanceof Set) { return decodeSetFromSet(registry, ValClass, value); @@ -76,7 +76,7 @@ export class BTreeSet extends Set implements ISet public createdAtHash?: Hash; - readonly #initialU8aLength?: number; + readonly initialU8aLength?: number; readonly #ValClass: Constructor; @@ -86,7 +86,7 @@ export class BTreeSet extends Set implements ISet super(sortSet(values)); this.registry = registry; - this.#initialU8aLength = decodedLength; + this.initialU8aLength = decodedLength; this.#ValClass = typeToConstructor(registry, valType); } @@ -104,20 +104,13 @@ export class BTreeSet extends Set implements ISet public get encodedLength (): number { let len = compactToU8a(this.size).length; - this.forEach((v: V) => { + for (const v of this.values()) { len += v.encodedLength; - }); + } return len; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public get initialU8aLength (): number | undefined { - return this.#initialU8aLength; - } - /** * @description Returns a hash of the value */ @@ -159,9 +152,9 @@ export class BTreeSet extends Set implements ISet public toHuman (isExtended?: boolean): AnyJson { const json: AnyJson = []; - this.forEach((v: V) => { + for (const v of this.values()) { json.push(v.toHuman(isExtended)); - }); + } return json; } @@ -172,9 +165,9 @@ export class BTreeSet extends Set implements ISet public toJSON (): AnyJson { const json: AnyJson = []; - this.forEach((v: V) => { + for (const v of this.values()) { json.push(v.toJSON()); - }); + } return json; } @@ -204,9 +197,9 @@ export class BTreeSet extends Set implements ISet encoded.push(compactToU8a(this.size)); } - this.forEach((v: V) => { + for (const v of this.values()) { encoded.push(v.toU8a(isBare)); - }); + } return u8aConcat(...encoded); } diff --git a/packages/types/src/codec/Base.ts b/packages/types/src/codec/Base.ts index 43c47c79c7..13d7abba64 100644 --- a/packages/types/src/codec/Base.ts +++ b/packages/types/src/codec/Base.ts @@ -14,14 +14,14 @@ export abstract class Base implements Codec { public createdAtHash?: Hash; - readonly #initialU8aLength?: number; + readonly initialU8aLength?: number; protected readonly _raw: T; protected constructor (registry: Registry, value: T, initialU8aLength?: number) { this.registry = registry; this._raw = value; - this.#initialU8aLength = initialU8aLength; + this.initialU8aLength = initialU8aLength; } /** @@ -31,13 +31,6 @@ export abstract class Base implements Codec { return this.toU8a().length; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public get initialU8aLength (): number | undefined { - return this.#initialU8aLength; - } - /** * @description returns a hash of the contents */ diff --git a/packages/types/src/codec/Compact.ts b/packages/types/src/codec/Compact.ts index dc77b0b2f4..ceb8f0d5be 100644 --- a/packages/types/src/codec/Compact.ts +++ b/packages/types/src/codec/Compact.ts @@ -23,9 +23,9 @@ export class Compact implements ICompact { public createdAtHash?: Hash; - readonly #Type: Constructor; + readonly initialU8aLength?: number; - readonly #initialU8aLength?: number; + readonly #Type: Constructor; readonly #raw: T; @@ -35,7 +35,7 @@ export class Compact implements ICompact { const [raw, decodedLength] = Compact.decodeCompact(registry, this.#Type, value); - this.#initialU8aLength = decodedLength; + this.initialU8aLength = decodedLength; this.#raw = raw; } @@ -51,6 +51,8 @@ export class Compact implements ICompact { public static decodeCompact (registry: Registry, Type: Constructor, value: Compact | AnyNumber): [T, number] { if (value instanceof Compact) { return [new Type(registry, value.#raw), 0]; + } else if (value instanceof Type) { + return [value, 0]; } else if (isString(value) || isNumber(value) || isBn(value) || isBigInt(value)) { return [new Type(registry, value), 0]; } @@ -67,13 +69,6 @@ export class Compact implements ICompact { return this.toU8a().length; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public get initialU8aLength (): number | undefined { - return this.#initialU8aLength; - } - /** * @description returns a hash of the contents */ diff --git a/packages/types/src/codec/Date.ts b/packages/types/src/codec/Date.ts index 09758119ca..0182d359bb 100644 --- a/packages/types/src/codec/Date.ts +++ b/packages/types/src/codec/Date.ts @@ -11,10 +11,10 @@ import { BN, bnToBn, bnToHex, bnToU8a, isString, isU8a, u8aToBn } from '@polkado const BITLENGTH: UIntBitLength = 64; function decodeDate (value: CodecDate | Date | AnyNumber): Date { - if (value instanceof Date) { - return value; - } else if (isU8a(value)) { + if (isU8a(value)) { value = u8aToBn(value.subarray(0, BITLENGTH / 8), true); + } else if (value instanceof Date) { + return value; } else if (isString(value)) { value = new BN(value.toString(), 10, 'le'); } diff --git a/packages/types/src/codec/Enum.spec.ts b/packages/types/src/codec/Enum.spec.ts index 1c69e25917..b96df209b9 100644 --- a/packages/types/src/codec/Enum.spec.ts +++ b/packages/types/src/codec/Enum.spec.ts @@ -423,7 +423,7 @@ describe('Enum', (): void => { }); it('encodes a single entry correctly (with embedded encoding)', (): void => { - const Test = Enum.with({ A: 'Address' }); + const Test = Enum.with({ A: 'MultiAddress' }); const test = new Test(registry, registry.createType('AccountId', '0x0001020304050607080910111213141516171819202122232425262728293031'), 0); expect(test.toHex()).toEqual( diff --git a/packages/types/src/codec/Enum.ts b/packages/types/src/codec/Enum.ts index 3a8c754e36..3ded1661d5 100644 --- a/packages/types/src/codec/Enum.ts +++ b/packages/types/src/codec/Enum.ts @@ -170,7 +170,7 @@ export class Enum implements IEnum { readonly #entryIndex: number; - readonly #initialU8aLength?: number; + readonly initialU8aLength?: number; readonly #indexes: number[]; @@ -193,7 +193,7 @@ export class Enum implements IEnum { this.#raw = decoded.value; if (this.#raw.initialU8aLength) { - this.#initialU8aLength = 1 + this.#raw.initialU8aLength; + this.initialU8aLength = 1 + this.#raw.initialU8aLength; } } @@ -228,13 +228,6 @@ export class Enum implements IEnum { return 1 + this.#raw.encodedLength; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public get initialU8aLength (): number | undefined { - return this.#initialU8aLength; - } - /** * @description returns a hash of the contents */ @@ -311,12 +304,12 @@ export class Enum implements IEnum { */ public eq (other?: unknown): boolean { // cater for the case where we only pass the enum index - if (isNumber(other)) { + if (isU8a(other)) { + return !this.toU8a().some((entry, index) => entry !== other[index]); + } else if (isNumber(other)) { return this.toNumber() === other; } else if (this.#isBasic && isString(other)) { return this.type === other; - } else if (isU8a(other)) { - return !this.toU8a().some((entry, index) => entry !== other[index]); } else if (isHex(other)) { return this.toHex() === other; } else if (other instanceof Enum) { diff --git a/packages/types/src/codec/Map.ts b/packages/types/src/codec/Map.ts index 6d6d27b670..25304162b3 100644 --- a/packages/types/src/codec/Map.ts +++ b/packages/types/src/codec/Map.ts @@ -38,7 +38,7 @@ function decodeMapFromU8a (registry: Registry, function decodeMapFromMap (registry: Registry, KeyClass: Constructor, ValClass: Constructor, value: Map): [Map, number] { const output = new Map(); - value.forEach((val: unknown, key: unknown) => { + for (const [key, val] of value.entries()) { const isComplex = KeyClass.prototype instanceof AbstractArray || KeyClass.prototype instanceof Struct || KeyClass.prototype instanceof Enum; @@ -57,7 +57,7 @@ function decodeMapFromMap (registry: Registry, throw error; } - }); + } return [output, 0]; } @@ -103,7 +103,7 @@ export class CodecMap extends readonly #ValClass: Constructor; - readonly #initialU8aLength?: number; + readonly initialU8aLength?: number; readonly #type: string; @@ -113,9 +113,9 @@ export class CodecMap extends super(type === 'BTreeMap' ? sortMap(decoded) : decoded); this.registry = registry; + this.initialU8aLength = decodedLength; this.#KeyClass = typeToConstructor(registry, keyType); this.#ValClass = typeToConstructor(registry, valType); - this.#initialU8aLength = decodedLength; this.#type = type; } @@ -125,20 +125,13 @@ export class CodecMap extends public get encodedLength (): number { let len = compactToU8a(this.size).length; - this.forEach((v: V, k: K) => { + for (const [k, v] of this.entries()) { len += v.encodedLength + k.encodedLength; - }); + } return len; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public get initialU8aLength (): number | undefined { - return this.#initialU8aLength; - } - /** * @description Returns a hash of the value */ @@ -173,9 +166,9 @@ export class CodecMap extends public toHuman (isExtended?: boolean): Record { const json: Record = {}; - this.forEach((v: V, k: K) => { + for (const [k, v] of this.entries()) { json[k.toString()] = v.toHuman(isExtended); - }); + } return json; } @@ -186,9 +179,9 @@ export class CodecMap extends public toJSON (): Record { const json: Record = {}; - this.forEach((v: V, k: K) => { + for (const [k, v] of this.entries()) { json[k.toString()] = v.toJSON(); - }); + } return json; } @@ -218,9 +211,9 @@ export class CodecMap extends encoded.push(compactToU8a(this.size)); } - this.forEach((v: V, k: K) => { + for (const [k, v] of this.entries()) { encoded.push(k.toU8a(isBare), v.toU8a(isBare)); - }); + } return u8aConcat(...encoded); } diff --git a/packages/types/src/codec/Option.ts b/packages/types/src/codec/Option.ts index cd4706fd1d..b2f0a80c52 100644 --- a/packages/types/src/codec/Option.ts +++ b/packages/types/src/codec/Option.ts @@ -10,13 +10,6 @@ import { assert, isNull, isU8a, isUndefined, u8aToHex } from '@polkadot/util'; import { Null } from '../primitive/Null'; import { typeToConstructor } from './utils'; -/** @internal */ -function decodeOptionU8a (registry: Registry, Type: Constructor, value: Uint8Array): Codec { - return !value.length || value[0] === 0 - ? new Null(registry) - : new Type(registry, value.subarray(1)); -} - /** @internal */ function decodeOption (registry: Registry, typeName: Constructor | string, value?: unknown): Codec { if (isNull(value) || isUndefined(value) || value instanceof Null || value === '0x') { @@ -34,7 +27,9 @@ function decodeOption (registry: Registry, typeName: Constructor | string, 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 decodeOptionU8a(registry, Type, value); + return !value.length || value[0] === 0 + ? new Null(registry) + : new Type(registry, value.subarray(1)); } return new Type(registry, value); diff --git a/packages/types/src/codec/Raw.ts b/packages/types/src/codec/Raw.ts index a1ba6037cc..0141ee089a 100644 --- a/packages/types/src/codec/Raw.ts +++ b/packages/types/src/codec/Raw.ts @@ -21,13 +21,13 @@ export class Raw extends Uint8Array implements IU8a { public createdAtHash?: Hash; - readonly #initialU8aLength?: number; + readonly initialU8aLength?: number; constructor (registry: Registry, value?: AnyU8a, initialU8aLength?: number) { super(u8aToU8a(value)); this.registry = registry; - this.#initialU8aLength = initialU8aLength; + this.initialU8aLength = initialU8aLength; } /** @@ -37,13 +37,6 @@ export class Raw extends Uint8Array implements IU8a { return this.length; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public get initialU8aLength (): number | undefined { - return this.#initialU8aLength; - } - /** * @description returns a hash of the contents */ diff --git a/packages/types/src/codec/Set.ts b/packages/types/src/codec/Set.ts index 4da4e37f2a..d6ee093254 100644 --- a/packages/types/src/codec/Set.ts +++ b/packages/types/src/codec/Set.ts @@ -63,12 +63,12 @@ function decodeSet (setValues: SetValues, value: string[] | Set | Uint8A const byteLength = bitLength / 8; - if (isString(value)) { - return decodeSet(setValues, u8aToU8a(value), byteLength); - } else if (isU8a(value)) { + if (isU8a(value)) { return value.length === 0 ? [] : decodeSetNumber(setValues, u8aToBn(value.subarray(0, byteLength), { isLe: true })); + } else if (isString(value)) { + return decodeSet(setValues, u8aToU8a(value), byteLength); } else if (value instanceof Set || Array.isArray(value)) { const input = Array.isArray(value) ? value diff --git a/packages/types/src/codec/Struct.ts b/packages/types/src/codec/Struct.ts index 535c605cc5..b4f48a3509 100644 --- a/packages/types/src/codec/Struct.ts +++ b/packages/types/src/codec/Struct.ts @@ -74,6 +74,10 @@ function decodeStructFromObject (registry: Registry, Types: ConstructorDef, valu return raw; } +function decodeZip (k: string, v: Codec): [string, Codec] { + return [k, v]; +} + /** * Decode input to pass into constructor. * @@ -91,12 +95,12 @@ function decodeStructFromObject (registry: Registry, Types: ConstructorDef, valu * @internal */ function decodeStruct (registry: Registry, Types: ConstructorDef, value: unknown, jsonMap: Map): [Iterable<[string, Codec]>, number] { - if (isHex(value)) { - return decodeStruct(registry, Types, hexToU8a(value), jsonMap); - } else if (isU8a(value)) { - return decodeU8a(registry, value, Types, 0, (k, v) => [k, v]); + if (isU8a(value)) { + return decodeU8a(registry, value, Types, decodeZip); } else if (value instanceof Struct) { return [value as Iterable<[string, Codec]>, 0]; + } else if (isHex(value)) { + return decodeStruct(registry, Types, hexToU8a(value), jsonMap); } // We assume from here that value is a JS object (Array, Map, Object) @@ -124,7 +128,7 @@ export class Struct< public createdAtHash?: Hash; - readonly #initialU8aLength?: number; + readonly initialU8aLength?: number; readonly #jsonMap: Map; @@ -137,7 +141,7 @@ export class Struct< super(decoded); this.registry = registry; - this.#initialU8aLength = decodedLength; + this.initialU8aLength = decodedLength; this.#jsonMap = jsonMap; this.#Types = mapToTypeMap(registry, Types); } @@ -220,13 +224,6 @@ export class Struct< return total; } - /** - * @description The length of the initial encoded value (Only available when constructed from a Uint8Array) - */ - public get initialU8aLength (): number | undefined { - return this.#initialU8aLength; - } - /** * @description returns a hash of the contents */ diff --git a/packages/types/src/codec/U8aFixed.ts b/packages/types/src/codec/U8aFixed.ts index 4a4a6b442c..0281c1e8df 100644 --- a/packages/types/src/codec/U8aFixed.ts +++ b/packages/types/src/codec/U8aFixed.ts @@ -4,26 +4,25 @@ import type { AnyU8a, Constructor, Registry } from '../types'; import type { U8aBitLength } from './types'; -import { assert, isString, u8aToU8a } from '@polkadot/util'; +import { assert, isU8a, u8aToU8a } from '@polkadot/util'; import { Raw } from './Raw'; /** @internal */ function decodeU8aFixed (value: AnyU8a, bitLength: U8aBitLength): [AnyU8a, number] { - if (Array.isArray(value) || isString(value)) { - return decodeU8aFixed(u8aToU8a(value), bitLength); + if (isU8a(value)) { + const byteLength = bitLength / 8; + + if (!value || !value.length) { + return [new Uint8Array(byteLength), 0]; + } + + assert(value.length >= byteLength, () => `Expected at least ${byteLength} bytes (${bitLength} bits), found ${value.length} bytes`); + + return [value.subarray(0, byteLength), byteLength]; } - const byteLength = bitLength / 8; - const u8a = new Uint8Array(byteLength); - - if (!value || !value.length) { - return [u8a, 0]; - } - - assert(value.length >= byteLength, () => `Expected at least ${byteLength} bytes (${bitLength} bits), found ${value.length} bytes`); - - return [value.subarray(0, byteLength), byteLength]; + return decodeU8aFixed(u8aToU8a(value), bitLength); } /** diff --git a/packages/types/src/codec/Vec.ts b/packages/types/src/codec/Vec.ts index 0920a2740d..337f73d0ca 100644 --- a/packages/types/src/codec/Vec.ts +++ b/packages/types/src/codec/Vec.ts @@ -7,12 +7,48 @@ import type { Codec, Constructor, Registry } from '../types'; import { assert, compactFromU8a, logger, u8aToU8a } from '@polkadot/util'; import { AbstractArray } from './AbstractArray'; -import { decodeU8a, typeToConstructor } from './utils'; +import { decodeU8aVec, typeToConstructor } from './utils'; const MAX_LENGTH = 64 * 1024; const l = logger('Vec'); +export function decodeVec (registry: Registry, Type: Constructor, value: Uint8Array | HexString | unknown[], length = -1): [T[], number, number] { + if (Array.isArray(value)) { + const result = new Array(value.length); + + for (let i = 0; i < value.length; i++) { + const entry = value[i]; + + try { + result[i] = entry instanceof Type + ? entry + : new Type(registry, entry); + } catch (error) { + l.error(`Unable to decode on index ${i}`, (error as Error).message); + + throw error; + } + } + + return [result, 0, 0]; + } + + const u8a = u8aToU8a(value); + let offset = 0; + + if (length === -1) { + const [_offset, _length] = compactFromU8a(u8a); + + assert(_length.lten(MAX_LENGTH), () => `Vec length ${_length.toString()} exceeds ${MAX_LENGTH}`); + + length = _length.toNumber(); + offset = _offset; + } + + return decodeU8aVec(registry, u8a, offset, Type, length); +} + /** * @name Vec * @description @@ -25,49 +61,13 @@ export class Vec extends AbstractArray { constructor (registry: Registry, Type: Constructor | string, value: Uint8Array | HexString | unknown[] = []) { const Clazz = typeToConstructor(registry, Type); - const [values, decodedLength] = Vec.decodeVec(registry, Clazz, value); + const [values, decodedLength] = decodeVec(registry, Clazz, value); super(registry, values, decodedLength); this.#Type = Clazz; } - /** @internal */ - public static decodeVec (registry: Registry, Type: Constructor, value: Uint8Array | HexString | unknown[], length = -1): [T[], number, number] { - if (Array.isArray(value)) { - return [ - value.map((entry: unknown, index: number): T => { - try { - return entry instanceof Type - ? entry - : new Type(registry, entry); - } catch (error) { - l.error(`Unable to decode on index ${index}`, (error as Error).message); - - throw error; - } - }), - 0, 0 - ]; - } - - const u8a = u8aToU8a(value); - let offset = 0; - - if (length === -1) { - const [_offset, _length] = compactFromU8a(u8a); - - assert(_length.lten(MAX_LENGTH), () => `Vec length ${_length.toString()} exceeds ${MAX_LENGTH}`); - - length = _length.toNumber(); - offset = _offset; - } - - const [decoded, decodedLength] = decodeU8a(registry, u8a.subarray(offset), Type, length); - - return [decoded as T[], decodedLength + offset, decodedLength]; - } - public static with (Type: Constructor | string): Constructor> { return class extends Vec { constructor (registry: Registry, value?: any[]) { diff --git a/packages/types/src/codec/VecFixed.ts b/packages/types/src/codec/VecFixed.ts index 123610e94a..d9a778d8e1 100644 --- a/packages/types/src/codec/VecFixed.ts +++ b/packages/types/src/codec/VecFixed.ts @@ -8,11 +8,11 @@ import { assert, u8aConcat } from '@polkadot/util'; import { AbstractArray } from './AbstractArray'; import { typeToConstructor } from './utils'; -import { Vec } from './Vec'; +import { decodeVec } from './Vec'; /** @internal */ function decodeVecFixed (registry: Registry, Type: Constructor, length: number, value: Uint8Array | HexString | unknown[]): [T[], number] { - const [values,, decodedLengthNoOffset] = Vec.decodeVec(registry, Type, value, length); + const [values,, decodedLengthNoOffset] = decodeVec(registry, Type, value, length); while (values.length < length) { values.push(new Type(registry)); diff --git a/packages/types/src/codec/utils/decodeU8a.ts b/packages/types/src/codec/utils/decodeU8a.ts index 11113f8f83..1d2e671136 100644 --- a/packages/types/src/codec/utils/decodeU8a.ts +++ b/packages/types/src/codec/utils/decodeU8a.ts @@ -3,9 +3,9 @@ import type { Codec, Constructor, Registry } from '../../types'; -import { isFunction, u8aToHex } from '@polkadot/util'; +import { u8aToHex } from '@polkadot/util'; -function formatFailure (error: Error, key: string, type: string, u8a: Uint8Array): string { +function formatFailure (error: Error, type: string, u8a: Uint8Array, key?: string): string { return `decodeU8a: failed at ${u8aToHex(u8a)}…${key ? ` on ${key}` : ''}${type ? `: ${type}` : ''}:: ${error.message}`; } @@ -25,21 +25,17 @@ function getRawType (registry: Registry, Type: Constructor): string { * @param result - The result array (will be returned with values pushed) * @param types - The array of Constructor to decode the U8a against. */ -export function decodeU8a (registry: Registry, u8a: Uint8Array, types: Constructor | Constructor[] | { [index: string]: Constructor }, count?: number, zip?: (key: string, value: T) => E): [E[], number] { - const [Type, Types, keys]: [Constructor | null, Constructor[], string[]] = isFunction(types) - ? [types, [], []] - : Array.isArray(types) - ? [null, types, []] - : [null, Object.values(types), Object.keys(types)]; +export function decodeU8a (registry: Registry, u8a: Uint8Array, types: Constructor[] | { [index: string]: Constructor }, zip?: (key: string, value: T) => E): [E[], number] { + const [Types, keys]: [Constructor[], string[]] = Array.isArray(types) + ? [types, []] + : [Object.values(types), Object.keys(types)]; - count = count || Types.length; - - const result = new Array(count); + const result = new Array(Types.length); let offset = 0; - for (let i = 0; i < count; i++) { + for (let i = 0; i < Types.length; i++) { try { - const value = new (Type || Types[i])(registry, u8a.subarray(offset)); + const value = new Types[i](registry, u8a.subarray(offset)); offset += value.initialU8aLength || value.encodedLength; result[i] = zip @@ -48,12 +44,36 @@ export function decodeU8a (registry: Registry, } catch (error) { throw new Error(formatFailure( error as Error, - keys[i], - getRawType(registry, Type || Types[i]), - u8a.subarray(offset, offset + 8) + getRawType(registry, Types[i]), + u8a.subarray(offset, offset + 8), + keys[i] )); } } return [result, offset]; } + +// Split from decodeU8a since this is specialized to 1 instance ... yes duplication, but +// since we have to do less checks (and these are intensive anyway), much faster +export function decodeU8aVec (registry: Registry, u8a: Uint8Array, start: number, Type: Constructor, count: number): [T[], number, number] { + const result = new Array(count); + let offset = start; + + for (let i = 0; i < count; i++) { + try { + const value = new Type(registry, u8a.subarray(offset)); + + offset += value.initialU8aLength || value.encodedLength; + result[i] = value; + } catch (error) { + throw new Error(formatFailure( + error as Error, + getRawType(registry, Type), + u8a.subarray(offset, offset + 8) + )); + } + } + + return [result, offset, offset - start]; +} diff --git a/packages/types/src/codec/utils/index.ts b/packages/types/src/codec/utils/index.ts index cd003ba209..97ad9d5740 100644 --- a/packages/types/src/codec/utils/index.ts +++ b/packages/types/src/codec/utils/index.ts @@ -4,7 +4,7 @@ export { compareArray } from './compareArray'; export { compareMap } from './compareMap'; export { compareSet } from './compareSet'; -export { decodeU8a } from './decodeU8a'; +export { decodeU8a, decodeU8aVec } from './decodeU8a'; export { defineProperty } from './defineProperty'; export { mapToTypeMap } from './mapToTypeMap'; export { typeToConstructor } from './typeToConstructor'; diff --git a/packages/types/src/create/encodeTypes.ts b/packages/types/src/create/encodeTypes.ts index 7b25418505..50a69f9c7a 100644 --- a/packages/types/src/create/encodeTypes.ts +++ b/packages/types/src/create/encodeTypes.ts @@ -4,7 +4,7 @@ import type { Registry } from '../types/registry'; import type { TypeDef } from './types'; -import { assert, isNumber, isUndefined, stringify } from '@polkadot/util'; +import { assert, isNumber, isUndefined, objectSpread, stringify } from '@polkadot/util'; import { TypeDefInfo } from './types'; @@ -44,7 +44,7 @@ function encodeSubTypes (registry: Registry, sub: TypeDef[], asEnum?: boolean, e assert(names.every((n) => !!n), () => `Subtypes does not have consistent names, ${names.join(', ')}`); - const inner: Record = { ...(extra as Record) }; + const inner: Record = objectSpread({}, extra); for (let i = 0; i < sub.length; i++) { const def = sub[i]; @@ -102,10 +102,9 @@ const encoders: Record st assert(sub && Array.isArray(sub), 'Unable to encode Set type'); return stringify({ - _set: sub.reduce((all, { index, name }, count): Record => ({ - ...all, - [`${name || `Unknown${index || count}`}`]: index || count - }), { _bitLength: length || 8 } as Record) + _set: sub.reduce((all, { index, name }, count) => + objectSpread(all, { [`${name || `Unknown${index || count}`}`]: index || count }), + { _bitLength: length || 8 }) }); }, // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -114,16 +113,15 @@ const encoders: Record st [TypeDefInfo.Struct]: (registry: Registry, { alias, sub }: TypeDef): string => { assert(sub && Array.isArray(sub), 'Unable to encode Struct type'); - return encodeSubTypes(registry, sub, false, { - ...( - alias - ? { _alias: [...alias.entries()].reduce>((all, [k, v]) => ({ - ...all, - [k]: v - }), {}) } - : {} - ) - }); + return encodeSubTypes(registry, sub, false, + alias + ? { + _alias: [...alias.entries()].reduce>((all, [k, v]) => + objectSpread(all, { [k]: v }), {} + ) + } + : {} + ); }, [TypeDefInfo.Tuple]: (registry: Registry, { sub }: TypeDef): string => { assert(sub && Array.isArray(sub), 'Unable to encode Tuple type'); @@ -159,8 +157,5 @@ export function encodeTypeDef (registry: Registry, typeDef: TypeDef): string { } export function withTypeString (registry: Registry, typeDef: Omit): TypeDef { - return { - ...typeDef, - type: encodeType(registry, typeDef as TypeDef, false) - }; + return objectSpread({}, typeDef, { type: encodeType(registry, typeDef as TypeDef, false) }); } diff --git a/packages/types/src/create/getTypeDef.ts b/packages/types/src/create/getTypeDef.ts index d602b6cd9b..059828b4be 100644 --- a/packages/types/src/create/getTypeDef.ts +++ b/packages/types/src/create/getTypeDef.ts @@ -3,7 +3,7 @@ import type { TypeDef } from './types'; -import { assert, isNumber, isString } from '@polkadot/util'; +import { assert, isNumber, isString, objectSpread } from '@polkadot/util'; import { sanitize } from './sanitize'; import { TypeDefInfo } from './types'; @@ -51,10 +51,9 @@ function _decodeEnum (value: TypeDef, details: string[] | Record type: 'Null' })); } else if (isRustEnum(details)) { - value.sub = Object.entries(details).map(([name, typeOrObj], index): TypeDef => ({ - ...getTypeDef(getTypeString(typeOrObj || 'Null'), { name }, count), - index - })); + value.sub = Object.entries(details).map(([name, typeOrObj], index): TypeDef => + objectSpread({}, getTypeDef(getTypeString(typeOrObj || 'Null'), { name }, count), { index }) + ); } else { value.sub = Object.entries(details).map(([name, index]): TypeDef => ({ index, diff --git a/packages/types/src/create/registry.ts b/packages/types/src/create/registry.ts index 6baa885697..38f3b1fbd2 100644 --- a/packages/types/src/create/registry.ts +++ b/packages/types/src/create/registry.ts @@ -6,7 +6,7 @@ import type { ChainProperties, CodecHash, DispatchErrorModule, Hash, MetadataLat import type { CallFunction, Codec, CodecHasher, Constructor, DetectCodec, DetectConstructor, RegisteredTypes, Registry, RegistryError, RegistryTypes } from '../types'; import type { CreateOptions } from './types'; -import { assert, assertReturn, BN_ZERO, formatBalance, isFunction, isString, isU8a, lazyMethod, logger, stringCamelCase, stringify } from '@polkadot/util'; +import { assert, assertReturn, BN_ZERO, formatBalance, isFunction, isString, isU8a, lazyMethod, logger, objectSpread, stringCamelCase, stringify } from '@polkadot/util'; import { blake2AsU8a } from '@polkadot/util-crypto'; import { DoNotConstruct } from '../codec/DoNotConstruct'; @@ -87,10 +87,7 @@ function injectEvents (registry: Registry, { lookup, pallets }: MetadataLatest, lazyMethod(result, version >= 12 ? index.toNumber() : i, () => lazyVariants(lookup, events.unwrap(), getVariantStringIdx, (variant: SiVariant): Constructor => { - const meta = registry.createType('EventMetadataLatest', { - ...variant, - args: getFieldArgs(lookup, variant.fields) - }); + const meta = registry.createType('EventMetadataLatest', objectSpread({}, variant, { args: getFieldArgs(lookup, variant.fields) })); return class extends GenericEventData { constructor (registry: Registry, value: Uint8Array) { @@ -171,7 +168,7 @@ export class TypeRegistry implements Registry { public createdAtHash?: Hash; constructor (createdAtHash?: Hash | Uint8Array | string) { - this.#knownDefaults = { Json, Metadata, Raw, ...baseTypes }; + this.#knownDefaults = objectSpread({ Json, Metadata, Raw }, baseTypes); this.#knownDefinitions = definitions as unknown as Record; this.init(); diff --git a/packages/types/src/ethereum/LookupSource.ts b/packages/types/src/ethereum/LookupSource.ts index a45ea793fd..c88ca01626 100644 --- a/packages/types/src/ethereum/LookupSource.ts +++ b/packages/types/src/ethereum/LookupSource.ts @@ -60,10 +60,10 @@ export class GenericEthereumLookupSource extends Base [k.toLowerCase(), v]); const mortal = entries.find(([k]) => k.toLowerCase() === 'mortalera'); diff --git a/packages/types/src/extrinsic/ExtrinsicPayload.spec.ts b/packages/types/src/extrinsic/ExtrinsicPayload.spec.ts index d02d79720a..a29225ad82 100644 --- a/packages/types/src/extrinsic/ExtrinsicPayload.spec.ts +++ b/packages/types/src/extrinsic/ExtrinsicPayload.spec.ts @@ -23,14 +23,14 @@ describe('ExtrinsicPayload', (): void => { const a = new ExtrinsicPayload(registry, TEST, { version: 4 }); const b = new ExtrinsicPayload(registry, a.toU8a(), { version: 4 }); - expect(a).toEqual(b); + expect(a.toJSON()).toEqual(b.toJSON()); }); it('creates and can re-create from itself (hex)', (): void => { const a = new ExtrinsicPayload(registry, TEST, { version: 4 }); const b = new ExtrinsicPayload(registry, a.toHex(), { version: 4 }); - expect(a).toEqual(b); + expect(a.toJSON()).toEqual(b.toJSON()); }); it('handles toU8a(true) correctly', (): void => { diff --git a/packages/types/src/extrinsic/SignerPayload.ts b/packages/types/src/extrinsic/SignerPayload.ts index e939db4c4a..d5a0108c89 100644 --- a/packages/types/src/extrinsic/SignerPayload.ts +++ b/packages/types/src/extrinsic/SignerPayload.ts @@ -5,7 +5,7 @@ import type { HexString } from '@polkadot/util/types'; import type { Address, Balance, BlockNumber, Call, ExtrinsicEra, Hash, Index, RuntimeVersion } from '../interfaces'; import type { Codec, ISignerPayload, Registry, SignerPayloadJSON, SignerPayloadRaw } from '../types'; -import { u8aToHex } from '@polkadot/util'; +import { objectSpread, u8aToHex } from '@polkadot/util'; import { Compact } from '../codec/Compact'; import { Option } from '../codec/Option'; @@ -51,24 +51,18 @@ export class GenericSignerPayload extends Struct implements ISignerPayload, Sign private readonly _extraTypes: Record; constructor (registry: Registry, value?: HexString | { [x: string]: unknown; } | Map | unknown[]) { - const extensionTypes = { - ...registry.getSignedExtensionTypes(), - ...registry.getSignedExtensionExtra() - }; + const extensionTypes = objectSpread>({}, registry.getSignedExtensionTypes(), registry.getSignedExtensionExtra()); - super(registry, { - ...extensionTypes, - ...knownTypes - }, value); + super(registry, objectSpread>({}, extensionTypes, knownTypes), value); + + this._extraTypes = {}; // add all extras that are not in the base types - this._extraTypes = Object.entries(extensionTypes).reduce>((map, [key, type]) => { + for (const [key, type] of Object.entries(extensionTypes)) { if (!knownTypes[key]) { - map[key] = type; + this._extraTypes[key] = type; } - - return map; - }, {}); + } } get address (): Address { @@ -119,19 +113,22 @@ export class GenericSignerPayload extends Struct implements ISignerPayload, Sign * @description Creates an representation of the structure as an ISignerPayload JSON */ public toPayload (): SignerPayloadJSON { - return { - // add any explicit overrides we may have - ...(Object.keys(this._extraTypes).reduce>((map, key) => { - const value = this.get(key) as Codec; - const isOption = value instanceof Option; + const result: Record = {}; + const keys = Object.keys(this._extraTypes); - // Don't include Option.isNone - if (!isOption || value.isSome) { - map[key] = value.toHex(); - } + // add any explicit overrides we may have + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const value = this.get(key) as Codec; + const isOption = value instanceof Option; - return map; - }, {})), + // Don't include Option.isNone + if (!isOption || value.isSome) { + result[key] = value.toHex(); + } + } + + return objectSpread(result, { // the known defaults as managed explicitly and has different // formatting in cases, e.g. we mostly expose a hex format here address: this.address.toString(), @@ -146,7 +143,7 @@ export class GenericSignerPayload extends Struct implements ISignerPayload, Sign tip: this.tip.toHex(), transactionVersion: this.runtimeVersion.transactionVersion.toHex(), version: this.version.toNumber() - }; + }); } /** diff --git a/packages/types/src/extrinsic/signedExtensions/index.ts b/packages/types/src/extrinsic/signedExtensions/index.ts index 5b5a54ea51..86ccfdf46f 100644 --- a/packages/types/src/extrinsic/signedExtensions/index.ts +++ b/packages/types/src/extrinsic/signedExtensions/index.ts @@ -3,6 +3,8 @@ import type { ExtDef, ExtInfo, ExtTypes } from './types'; +import { objectSpread } from '@polkadot/util'; + import { polkadot } from './polkadot'; import { shell } from './shell'; import { statemint } from './statemint'; @@ -12,12 +14,7 @@ import { substrate } from './substrate'; // we define the extra fields not as a Tuple, but rather as a struct so they can be named. These will be expanded // into the various fields when added to the payload (we only support V4 onwards with these, V3 and earlier are // deemed fixed and non-changeable) -export const allExtensions: ExtDef = { - ...substrate, - ...polkadot, - ...shell, - ...statemint -}; +export const allExtensions: ExtDef = objectSpread({}, substrate, polkadot, shell, statemint); // the v4 signed extensions prior to the point of exposing these to the metadata. // This may not match 100% with the current defaults and are used when not specified @@ -36,7 +33,7 @@ export const fallbackExtensions = [ export function findUnknownExtensions (extensions: string[], userExtensions: ExtDef = {}): string[] { const names = [...Object.keys(allExtensions), ...Object.keys(userExtensions)]; - return extensions.filter((key) => !names.includes(key)); + return extensions.filter((k) => !names.includes(k)); } export function expandExtensionTypes (extensions: string[], type: keyof ExtInfo, userExtensions: ExtDef = {}): ExtTypes { @@ -44,5 +41,5 @@ export function expandExtensionTypes (extensions: string[], type: keyof ExtInfo, // Always allow user extensions first - these should provide overrides .map((key) => userExtensions[key] || allExtensions[key]) .filter((info): info is ExtInfo => !!info) - .reduce((result, info): ExtTypes => ({ ...result, ...info[type] }), {}); + .reduce((result, info): ExtTypes => objectSpread(result, info[type]), {}); } diff --git a/packages/types/src/extrinsic/v4/ExtrinsicPayload.ts b/packages/types/src/extrinsic/v4/ExtrinsicPayload.ts index 33904d7ed4..a4816f9dc2 100644 --- a/packages/types/src/extrinsic/v4/ExtrinsicPayload.ts +++ b/packages/types/src/extrinsic/v4/ExtrinsicPayload.ts @@ -7,6 +7,8 @@ import type { ExtrinsicEra } from '../../interfaces/extrinsics'; import type { AssetId, Balance, Hash, Index } from '../../interfaces/runtime'; import type { ExtrinsicPayloadValue, IKeyringPair, Registry } from '../../types'; +import { objectSpread } from '@polkadot/util'; + import { Compact } from '../../codec/Compact'; import { Enum } from '../../codec/Enum'; import { Option } from '../../codec/Option'; @@ -25,11 +27,11 @@ export class GenericExtrinsicPayloadV4 extends Struct { #signOptions: SignOptions; constructor (registry: Registry, value?: ExtrinsicPayloadValue | Uint8Array | HexString) { - super(registry, { - method: 'Bytes', - ...registry.getSignedExtensionTypes(), - ...registry.getSignedExtensionExtra() - }, value); + super(registry, objectSpread( + { method: 'Bytes' }, + registry.getSignedExtensionTypes(), + registry.getSignedExtensionExtra() + ), value); // Do detection for the type of extrinsic, in the case of MultiSignature this is an // enum, in the case of AnySignature, this is a Hash only (may be 64 or 65 bytes) diff --git a/packages/types/src/extrinsic/v4/ExtrinsicSignature.ts b/packages/types/src/extrinsic/v4/ExtrinsicSignature.ts index 38d8bb0e1f..56aaf60b94 100644 --- a/packages/types/src/extrinsic/v4/ExtrinsicSignature.ts +++ b/packages/types/src/extrinsic/v4/ExtrinsicSignature.ts @@ -7,7 +7,7 @@ import type { Address, AssetId, Balance, Call, Index } from '../../interfaces/ru import type { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../types'; import type { ExtrinsicSignatureOptions } from '../types'; -import { assert, isU8a, stringify, u8aConcat, u8aToHex } from '@polkadot/util'; +import { assert, isU8a, objectSpread, stringify, u8aConcat, u8aToHex } from '@polkadot/util'; import { Compact } from '../../codec/Compact'; import { Enum } from '../../codec/Enum'; @@ -32,12 +32,15 @@ export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSig #fakePrefix: Uint8Array; constructor (registry: Registry, value?: GenericExtrinsicSignatureV4 | Uint8Array, { isSigned }: ExtrinsicSignatureOptions = {}) { - super(registry, { - signer: 'Address', - // eslint-disable-next-line sort-keys - signature: 'ExtrinsicSignature', - ...registry.getSignedExtensionTypes() - }, GenericExtrinsicSignatureV4.decodeExtrinsicSignature(value, isSigned)); + super( + registry, + objectSpread( + // eslint-disable-next-line sort-keys + { signer: 'Address', signature: 'ExtrinsicSignature' }, + registry.getSignedExtensionTypes() + ), + GenericExtrinsicSignatureV4.decodeExtrinsicSignature(value, isSigned) + ); this.#fakePrefix = registry.createType('ExtrinsicSignature') instanceof Enum ? FAKE_SOME diff --git a/packages/types/src/generic/AccountId.ts b/packages/types/src/generic/AccountId.ts index efe82f71b1..e0729b3e35 100644 --- a/packages/types/src/generic/AccountId.ts +++ b/packages/types/src/generic/AccountId.ts @@ -10,10 +10,10 @@ import { U8aFixed } from '../codec/U8aFixed'; /** @internal */ function decodeAccountId (value?: AnyU8a | AnyString): Uint8Array { - if (!value) { - return new Uint8Array(); - } else if (isU8a(value) || Array.isArray(value)) { + if (isU8a(value) || Array.isArray(value)) { return u8aToU8a(value); + } else if (!value) { + return new Uint8Array(); } else if (isHex(value)) { return hexToU8a(value); } else if (isString(value)) { diff --git a/packages/types/src/generic/Call.ts b/packages/types/src/generic/Call.ts index be329c07fb..839e8defeb 100644 --- a/packages/types/src/generic/Call.ts +++ b/packages/types/src/generic/Call.ts @@ -4,7 +4,7 @@ import type { FunctionMetadataLatest } from '../interfaces/metadata'; import type { AnyJson, AnyTuple, AnyU8a, ArgsDef, CallBase, CallFunction, Codec, IMethod, InterfaceTypes, Registry } from '../types'; -import { isHex, isObject, isU8a, u8aToU8a } from '@polkadot/util'; +import { isHex, isObject, isU8a, objectSpread, u8aToU8a } from '@polkadot/util'; import { Struct } from '../codec/Struct'; import { U8aFixed } from '../codec/U8aFixed'; @@ -87,7 +87,7 @@ function decodeCallViaU8a (registry: Registry, value: Uint8Array, _meta?: Functi * @internal */ function decodeCall (registry: Registry, value: unknown | DecodedMethod | Uint8Array | string = new Uint8Array(), _meta?: FunctionMetadataLatest): DecodedMethod { - if (isHex(value) || isU8a(value)) { + if (isU8a(value) || isHex(value)) { return decodeCallViaU8a(registry, u8aToU8a(value), _meta); } else if (isObject(value) && value.callIndex && value.args) { return decodeCallViaObject(registry, value as DecodedMethod, _meta); @@ -216,18 +216,17 @@ export class GenericCall extends Struct implement // swallow } - return { - args: this.argsEntries.reduce>((args, [n, a]) => ({ - ...args, - [n]: a.toHuman(isExpanded) - }), {}), - method: call?.method, - section: call?.section, - ...(isExpanded && call + return objectSpread( + { + args: this.argsEntries.reduce>((args, [n, a]) => + objectSpread(args, { [n]: a.toHuman(isExpanded) }), {}), + method: call?.method, + section: call?.section + }, + isExpanded && call ? { docs: call.meta.docs.map((d) => d.toString()) } - : {} - ) - }; + : null + ); } /** diff --git a/packages/types/src/generic/Event.ts b/packages/types/src/generic/Event.ts index bad97689ff..b54f42e889 100644 --- a/packages/types/src/generic/Event.ts +++ b/packages/types/src/generic/Event.ts @@ -6,6 +6,8 @@ import type { EventMetadataLatest } from '../interfaces/metadata'; import type { EventId } from '../interfaces/system'; import type { AnyJson, Codec, Constructor, IEvent, IEventData, InterfaceTypes, Registry } from '../types'; +import { objectSpread } from '@polkadot/util'; + import { Struct } from '../codec/Struct'; import { Tuple } from '../codec/Tuple'; import { Null } from '../primitive/Null'; @@ -154,14 +156,15 @@ export class GenericEvent extends Struct implements IEvent { * @description Converts the Object to to a human-friendly JSON, with additional fields, expansion and formatting of information */ public override toHuman (isExpanded?: boolean): Record { - return { - method: this.method, - section: this.section, - ...(isExpanded + return objectSpread( + { + method: this.method, + section: this.section + }, + isExpanded ? { docs: this.meta.docs.map((d) => d.toString()) } - : {} - ), - ...super.toHuman(isExpanded) - }; + : null, + super.toHuman(isExpanded) + ); } } diff --git a/packages/types/src/generic/MultiAddress.ts b/packages/types/src/generic/MultiAddress.ts index 25690aaef9..842fd5a8e6 100644 --- a/packages/types/src/generic/MultiAddress.ts +++ b/packages/types/src/generic/MultiAddress.ts @@ -23,16 +23,17 @@ function decodeU8a (registry: Registry, u8a: Uint8Array): unknown { } function decodeMultiAny (registry: Registry, value?: unknown): unknown { - if (value instanceof GenericMultiAddress) { - return value; - } else if (value instanceof GenericAccountId) { + if (value instanceof GenericAccountId) { return { Id: value }; + } else if (isU8a(value)) { + // NOTE This is after the AccountId check (which is U8a) + return decodeU8a(registry, value); + } else if (value instanceof GenericMultiAddress) { + return value; } else if (value instanceof GenericAccountIndex || isBn(value) || isNumber(value)) { return { Index: isNumber(value) ? value : value.toNumber() }; } else if (isString(value)) { return decodeU8a(registry, decodeAddress(value.toString())); - } else if (isU8a(value)) { - return decodeU8a(registry, value); } return value; diff --git a/packages/types/src/generic/PortableRegistry/PortableRegistry.ts b/packages/types/src/generic/PortableRegistry/PortableRegistry.ts index 07f15a8bba..a268ac29b9 100644 --- a/packages/types/src/generic/PortableRegistry/PortableRegistry.ts +++ b/packages/types/src/generic/PortableRegistry/PortableRegistry.ts @@ -7,7 +7,7 @@ import type { SiField, SiLookupTypeId, SiPath, SiType, SiTypeDefArray, SiTypeDef import type { Text, Type } from '../../primitive'; import type { Registry, TypeDef } from '../../types'; -import { assert, isNumber, isString, stringCamelCase, stringify, stringUpperFirst } from '@polkadot/util'; +import { assert, isNumber, isString, objectSpread, stringCamelCase, stringify, stringUpperFirst } from '@polkadot/util'; import { Struct } from '../../codec/Struct'; import { withTypeString } from '../../create/encodeTypes'; @@ -259,12 +259,16 @@ export class GenericPortableRegistry extends Struct { #types: Record; constructor (registry: Registry, value?: Uint8Array) { + // console.time('PortableRegistry') + super(registry, { types: 'Vec' }, value); this.#names = extractNames(this, this.types); this.#types = extractTypeMap(this.types); + + // console.timeEnd('PortableRegistry') } public get names (): string[] { @@ -403,11 +407,7 @@ export class GenericPortableRegistry extends Struct { throw new Error(`PortableRegistry: ${lookupIndex}${namespace ? ` (${namespace})` : ''}: Error extracting ${stringify(type)}: ${(error as Error).message}`); } - return { - docs: sanitizeDocs(type.docs), - namespace, - ...typeDef - }; + return objectSpread({ docs: sanitizeDocs(type.docs), namespace }, typeDef); } #extractArray (_: number, { len: length, type }: SiTypeDefArray): TypeDef { @@ -454,16 +454,18 @@ export class GenericPortableRegistry extends Struct { } else if (['Range', 'RangeInclusive'].includes(specialVariant)) { return withTypeString(this.registry, { info: TypeDefInfo.Range, - sub: fields.map(({ name, type, typeName }, index) => ({ - name: name.isSome - ? name.unwrap().toString() - : ['start', 'end'][index], - ...this.#createSiDef(type), - ...(typeName.isSome - ? { typeName: sanitize(typeName.unwrap()) } - : {} - ) - })) + sub: fields.map(({ name, type, typeName }, index) => + objectSpread( + { + name: name.isSome + ? name.unwrap().toString() + : ['start', 'end'][index] + }, + this.#createSiDef(type), + typeName.isSome + ? { typeName: sanitize(typeName.unwrap()) } + : null + )) }); } else if (path.length) { if (path[path.length - 1].toString() === 'WrapperOpaque') { @@ -521,44 +523,41 @@ export class GenericPortableRegistry extends Struct { } else if (isTuple && fields.length === 1) { const typeDef = this.#createSiDef(fields[0].type); - return { - ...typeDef, - ...(lookupIndex === -1 + return objectSpread( + {}, + typeDef, + lookupIndex === -1 ? {} : { lookupIndex, lookupName: this.#names[lookupIndex], lookupNameRoot: typeDef.lookupName - } - ), - ...(fields[0].typeName.isSome + }, + fields[0].typeName.isSome ? { typeName: sanitize(fields[0].typeName.unwrap()) } - : {} - ) - }; + : null + ); } const [sub, alias] = this.#extractFieldsAlias(fields); - return withTypeString(this.registry, { - info: isTuple // Tuple check first - ? TypeDefInfo.Tuple - : TypeDefInfo.Struct, - ...( - alias.size - ? { alias } - : {} - ), - ...( - lookupIndex === -1 - ? {} - : { - lookupIndex, - lookupName: this.#names[lookupIndex] - } - ), - sub - }); + return withTypeString(this.registry, objectSpread( + { + info: isTuple // Tuple check first + ? TypeDefInfo.Tuple + : TypeDefInfo.Struct + }, + alias.size + ? { alias } + : null, + lookupIndex === -1 + ? {} + : { + lookupIndex, + lookupName: this.#names[lookupIndex] + }, + { sub } + )); } #extractFieldsAlias (fields: SiField[]): [TypeDef[], Map] { @@ -587,15 +586,17 @@ export class GenericPortableRegistry extends Struct { alias.set(nameField, nameOrig); } - sub[i] = { - ...typeDef, - docs: sanitizeDocs(docs), - name: nameField, - ...(typeName.isSome + sub[i] = objectSpread( + {}, + typeDef, + { + docs: sanitizeDocs(docs), + name: nameField + }, + typeName.isSome ? { typeName: sanitize(typeName.unwrap()) } - : {} - ) - }; + : null + ); } } @@ -603,11 +604,14 @@ export class GenericPortableRegistry extends Struct { } #extractHistoric (_: number, type: Type): TypeDef { - return { - ...getTypeDef(type), - displayName: type.toString(), - isFromSi: true - }; + return objectSpread( + {}, + getTypeDef(type), + { + displayName: type.toString(), + isFromSi: true + } + ); } #extractPrimitive (_: number, type: SiType): TypeDef { @@ -675,10 +679,9 @@ export class GenericPortableRegistry extends Struct { } else if (specialVariant === 'Result') { return withTypeString(this.registry, { info: TypeDefInfo.Result, - sub: params.map(({ type }, index) => ({ - name: ['Ok', 'Error'][index], - ...this.#createSiDef(type.unwrap()) - })) + sub: params.map(({ type }, index) => + objectSpread({ name: ['Ok', 'Error'][index] }, this.#createSiDef(type.unwrap())) + ) }); } else if (variants.length === 0) { return { @@ -709,11 +712,15 @@ export class GenericPortableRegistry extends Struct { }); } - sub.push({ - ...this.#extractFields(-1, fields), - index: index.toNumber(), - name: name.toString() - }); + sub.push( + objectSpread( + this.#extractFields(-1, fields), + { + index: index.toNumber(), + name: name.toString() + } + ) + ); }); return withTypeString(this.registry, { diff --git a/packages/types/src/generic/Vote.ts b/packages/types/src/generic/Vote.ts index b9451d7a6f..4285ce8eab 100644 --- a/packages/types/src/generic/Vote.ts +++ b/packages/types/src/generic/Vote.ts @@ -48,12 +48,12 @@ function decodeVoteType (registry: Registry, value: VoteType): Uint8Array { /** @internal */ function decodeVote (registry: Registry, value?: InputTypes): Uint8Array { - if (isUndefined(value) || value instanceof Boolean || isBoolean(value)) { + if (isU8a(value)) { + return decodeVoteU8a(value); + } else if (isUndefined(value) || value instanceof Boolean || isBoolean(value)) { return decodeVoteBool(new Bool(registry, value).isTrue); } else if (isNumber(value)) { return decodeVoteBool(value < 0); - } else if (isU8a(value)) { - return decodeVoteU8a(value); } return decodeVoteType(registry, value); diff --git a/packages/types/src/interfaces/contractsAbi/definitions.ts b/packages/types/src/interfaces/contractsAbi/definitions.ts index d15b26e248..b9dfa22832 100644 --- a/packages/types/src/interfaces/contractsAbi/definitions.ts +++ b/packages/types/src/interfaces/contractsAbi/definitions.ts @@ -3,6 +3,8 @@ import type { Definitions } from '../../types'; +import { objectSpread } from '@polkadot/util'; + // order important in structs... :) /* eslint-disable sort-keys */ @@ -116,9 +118,7 @@ const ContractProjectInfo = { export default { rpc: {}, - types: { - ...layout, - ...spec, + types: objectSpread({}, layout, spec, { ContractProjectInfo, ContractMetadataV0, ContractMetadataV1, @@ -129,11 +129,7 @@ export default { } }, ContractMetadataLatest: 'ContractMetadataV1', - ContractProjectV0: { - metadataVersion: 'Text', - ...ContractProjectInfo, - ...ContractMetadataV0 - }, + ContractProjectV0: objectSpread({ metadataVersion: 'Text' }, ContractProjectInfo, ContractMetadataV0), ContractProject: '(ContractProjectInfo, ContractMetadata)', ContractProjectContract: { _alias: { @@ -157,5 +153,5 @@ export default { compiler: 'Text', wasm: 'Raw' } - } + }) } as Definitions; diff --git a/packages/types/src/interfaces/cumulus/definitions.ts b/packages/types/src/interfaces/cumulus/definitions.ts index 1c7ec8c35e..e142b5590b 100644 --- a/packages/types/src/interfaces/cumulus/definitions.ts +++ b/packages/types/src/interfaces/cumulus/definitions.ts @@ -22,7 +22,5 @@ const dmpQueue = { export default { rpc: {}, - types: { - ...dmpQueue - } + types: dmpQueue } as Definitions; diff --git a/packages/types/src/interfaces/eth/definitions.ts b/packages/types/src/interfaces/eth/definitions.ts index 082a680fdd..ec1ef4ec7a 100644 --- a/packages/types/src/interfaces/eth/definitions.ts +++ b/packages/types/src/interfaces/eth/definitions.ts @@ -8,6 +8,8 @@ import type { DefinitionsTypes } from '../../types'; +import { objectSpread } from '@polkadot/util'; + import { rpc } from './rpc'; const V0: DefinitionsTypes = { @@ -84,10 +86,7 @@ const V2: DefinitionsTypes = { } }; -const types: DefinitionsTypes = { - ...V0, - ...V1, - ...V2, +const types: DefinitionsTypes = objectSpread({}, V0, V1, V2, { EthereumAccountId: 'GenericEthereumAccountId', EthereumAddress: 'GenericEthereumAccountId', EthereumLookupSource: 'GenericEthereumLookupSource', @@ -328,6 +327,6 @@ const types: DefinitionsTypes = { target: 'H256', number: 'Option' } -}; +}); export default { rpc, types }; diff --git a/packages/types/src/interfaces/eth/rpc.ts b/packages/types/src/interfaces/eth/rpc.ts index 90986833db..a958842021 100644 --- a/packages/types/src/interfaces/eth/rpc.ts +++ b/packages/types/src/interfaces/eth/rpc.ts @@ -5,6 +5,8 @@ import type { DefinitionsRpc } from '../../types'; +import { objectSpread } from '@polkadot/util'; + // We use aliasSection here to override since these are in another namespace const netRpc: DefinitionsRpc = { listening: { @@ -41,9 +43,7 @@ const web3Rpc: DefinitionsRpc = { } }; -export const rpc: DefinitionsRpc = { - ...netRpc, - ...web3Rpc, +export const rpc: DefinitionsRpc = objectSpread({}, netRpc, web3Rpc, { accounts: { description: 'Returns accounts list.', params: [], @@ -476,4 +476,4 @@ export const rpc: DefinitionsRpc = { ], type: 'bool' } -}; +}); diff --git a/packages/types/src/interfaces/jsonrpc.ts b/packages/types/src/interfaces/jsonrpc.ts index 325f5219eb..241ad367a5 100644 --- a/packages/types/src/interfaces/jsonrpc.ts +++ b/packages/types/src/interfaces/jsonrpc.ts @@ -3,6 +3,8 @@ import type { DefinitionRpcExt, DefinitionRpcSub } from '../types'; +import { objectSpread } from '@polkadot/util'; + import * as definitions from './definitions'; const jsonrpc: Record> = {}; @@ -24,7 +26,7 @@ Object jsonrpc[section] = {}; } - jsonrpc[section][method] = ({ ...def, isSubscription, jsonrpc: `${section}_${method}`, method, section }); + jsonrpc[section][method] = objectSpread({}, def, { isSubscription, jsonrpc: `${section}_${method}`, method, section }); }); }); diff --git a/packages/types/src/interfaces/metadata/definitions.ts b/packages/types/src/interfaces/metadata/definitions.ts index f610dd303a..98b5c124b6 100644 --- a/packages/types/src/interfaces/metadata/definitions.ts +++ b/packages/types/src/interfaces/metadata/definitions.ts @@ -6,6 +6,8 @@ import type { Definitions } from '../../types'; +import { objectSpread } from '@polkadot/util'; + import { AllHashers } from './hashers'; import { v9 } from './v9'; import { v10 } from './v10'; @@ -18,14 +20,7 @@ export { AllHashers }; export default { rpc: {}, - types: { - ...v9, - ...v10, - ...v11, - ...v12, - ...v13, - ...v14, - + types: objectSpread({}, v9, v10, v11, v12, v13, v14, { // registry mapping to latest PortableRegistry: 'PortableRegistryV14', PortableType: 'PortableTypeV14', @@ -70,5 +65,5 @@ export default { V14: 'MetadataV14' } } - } + }) } as Definitions; diff --git a/packages/types/src/interfaces/metadata/v14.ts b/packages/types/src/interfaces/metadata/v14.ts index c7f255d951..b5e4853269 100644 --- a/packages/types/src/interfaces/metadata/v14.ts +++ b/packages/types/src/interfaces/metadata/v14.ts @@ -4,7 +4,9 @@ // order important in structs... :) /* eslint-disable sort-keys */ -import type { DefinitionsTypes } from '../../types'; +import type { DefinitionsTypes, DefinitionTypeStruct } from '../../types'; + +import { objectSpread } from '@polkadot/util'; import { Si1Variant } from '../scaleInfo/v1'; @@ -17,23 +19,14 @@ export const v14: DefinitionsTypes = { }, // compatibility with earlier layouts, i.e. don't break previous users - ErrorMetadataV14: { - ...Si1Variant, - args: 'Vec' - }, - EventMetadataV14: { - ...Si1Variant, - args: 'Vec' - }, + ErrorMetadataV14: objectSpread({}, Si1Variant, { args: 'Vec' }), + EventMetadataV14: objectSpread({}, Si1Variant, { args: 'Vec' }), FunctionArgumentMetadataV14: { name: 'Text', type: 'Type', typeName: 'Option' }, - FunctionMetadataV14: { - ...Si1Variant, - args: 'Vec' - }, + FunctionMetadataV14: objectSpread({}, Si1Variant, { args: 'Vec' }), // V14 ExtrinsicMetadataV14: { diff --git a/packages/types/src/interfaces/parachains/definitions.ts b/packages/types/src/interfaces/parachains/definitions.ts index e6a9d12b26..8980180e66 100644 --- a/packages/types/src/interfaces/parachains/definitions.ts +++ b/packages/types/src/interfaces/parachains/definitions.ts @@ -6,6 +6,8 @@ import type { Definitions } from '../../types'; +import { objectSpread } from '@polkadot/util'; + import hrmpTypes from './hrmp'; import slotTypes from './slots'; @@ -75,12 +77,7 @@ const disputeTypes = { export default { rpc: {}, - types: { - ...cumulusTypes, - ...disputeTypes, - ...hrmpTypes, - ...proposeTypes, - ...slotTypes, + types: objectSpread({}, cumulusTypes, disputeTypes, hrmpTypes, proposeTypes, slotTypes, { AbridgedCandidateReceipt: { parachainIndex: 'ParaId', relayParent: 'Hash', @@ -429,5 +426,5 @@ export default { MessagingStateSnapshotEgressEntry: '(ParaId, AbridgedHrmpChannel)', SystemInherentData: 'ParachainInherentData', VecInboundHrmpMessage: 'Vec' - } + }) } as Definitions; diff --git a/packages/types/src/interfaces/parachains/slots.ts b/packages/types/src/interfaces/parachains/slots.ts index 7444cd28ee..79c50fa917 100644 --- a/packages/types/src/interfaces/parachains/slots.ts +++ b/packages/types/src/interfaces/parachains/slots.ts @@ -1,6 +1,8 @@ // Copyright 2017-2021 @polkadot/types authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { objectSpread } from '@polkadot/util'; + // order important in structs... :) /* eslint-disable sort-keys */ @@ -36,8 +38,7 @@ const oldTypes = { SubId: 'u32' }; -export default { - ...oldTypes, +export default objectSpread({}, oldTypes, { AuctionIndex: 'u32', LeasePeriod: 'BlockNumber', LeasePeriodOf: 'BlockNumber', @@ -48,4 +49,4 @@ export default { WinningDataEntry: 'Option<(AccountId, ParaId, BalanceOf)>', WinnersData: 'Vec', WinnersDataTuple: '(AccountId, ParaId, BalanceOf, SlotRange)' -}; +}); diff --git a/packages/types/src/interfaces/runtime/definitions.ts b/packages/types/src/interfaces/runtime/definitions.ts index 7b6f091208..3e2ab778ed 100644 --- a/packages/types/src/interfaces/runtime/definitions.ts +++ b/packages/types/src/interfaces/runtime/definitions.ts @@ -6,6 +6,8 @@ import type { Definitions } from '../../types'; +import { objectSpread } from '@polkadot/util'; + const numberTypes = { Fixed64: 'Int<64, Fixed64>', FixedI64: 'Int<64, FixedI64>', @@ -24,8 +26,7 @@ const numberTypes = { export default { rpc: {}, - types: { - ...numberTypes, + types: objectSpread({}, numberTypes, { AccountId: 'AccountId32', AccountId20: 'GenericEthereumAccountId', AccountId32: 'GenericAccountId', @@ -184,5 +185,5 @@ export default { SealV0: '(u64, Signature)', Seal: '(ConsensusEngineId, Bytes)', Consensus: '(ConsensusEngineId, Bytes)' - } + }) } as Definitions; diff --git a/packages/types/src/interfaces/scaleInfo/definitions.ts b/packages/types/src/interfaces/scaleInfo/definitions.ts index 9a87b15b58..5a005512db 100644 --- a/packages/types/src/interfaces/scaleInfo/definitions.ts +++ b/packages/types/src/interfaces/scaleInfo/definitions.ts @@ -3,6 +3,8 @@ import type { Definitions } from '../../types'; +import { objectSpread } from '@polkadot/util'; + import { v0 } from './v0'; import { v1 } from './v1'; @@ -11,10 +13,7 @@ import { v1 } from './v1'; export default { rpc: {}, - types: { - ...v0, - ...v1, - + types: objectSpread({}, v0, v1, { // latest mappings SiField: 'Si1Field', SiLookupTypeId: 'Si1LookupTypeId', @@ -31,5 +30,5 @@ export default { SiTypeParameter: 'Si1TypeParameter', SiTypeDefVariant: 'Si1TypeDefVariant', SiVariant: 'Si1Variant' - } + }) } as Definitions; diff --git a/packages/types/src/interfaces/session/definitions.ts b/packages/types/src/interfaces/session/definitions.ts index 03cdd9f83f..5afc75f80e 100644 --- a/packages/types/src/interfaces/session/definitions.ts +++ b/packages/types/src/interfaces/session/definitions.ts @@ -6,6 +6,8 @@ import type { Definitions } from '../../types'; +import { objectSpread } from '@polkadot/util'; + // The runtime definition of SessionKeys are passed as a Trait to session // Defined in `node/runtime/src/lib.rs` as follow // impl_opaque_keys! { @@ -37,8 +39,7 @@ const keyTypes = { export default { rpc: {}, - types: { - ...keyTypes, + types: objectSpread({}, keyTypes, { FullIdentification: 'Exposure', IdentificationTuple: '(ValidatorId, FullIdentification)', MembershipProof: { @@ -48,5 +49,5 @@ export default { }, SessionIndex: 'u32', ValidatorCount: 'u32' - } + }) } as Definitions; diff --git a/packages/types/src/interfaces/staking/definitions.ts b/packages/types/src/interfaces/staking/definitions.ts index 5112d06c27..d4ebfab3c0 100644 --- a/packages/types/src/interfaces/staking/definitions.ts +++ b/packages/types/src/interfaces/staking/definitions.ts @@ -6,6 +6,8 @@ import type { Definitions } from '../../types'; +import { objectSpread } from '@polkadot/util'; + const deprecated = { Points: 'u32', EraPoints: { @@ -172,9 +174,7 @@ const phragmen = { export default { rpc: {}, - types: { - ...deprecated, - ...phragmen, + types: objectSpread({}, deprecated, phragmen, { ActiveEraInfo: { index: 'EraIndex', start: 'Option' @@ -298,5 +298,5 @@ export default { unstakeThreshold: 'Compact', validatorPayment: 'Compact' } - } + }) } as Definitions; diff --git a/packages/types/src/interfaces/xcm/definitions.ts b/packages/types/src/interfaces/xcm/definitions.ts index 56387941e8..ae0597abea 100644 --- a/packages/types/src/interfaces/xcm/definitions.ts +++ b/packages/types/src/interfaces/xcm/definitions.ts @@ -7,6 +7,7 @@ import type { Definitions } from '../../types'; import { mapXcmTypes } from '@polkadot/types-known'; +import { objectSpread } from '@polkadot/util'; import { v0 } from './v0'; import { v1 } from './v1'; @@ -81,13 +82,7 @@ const location = { export default { rpc: {}, - types: { - ...location, - ...xcm, - ...v0, - ...v1, - ...v2, - ...mapXcmTypes(XCM_LATEST), + types: objectSpread({}, location, xcm, v0, v1, v2, mapXcmTypes(XCM_LATEST), { DoubleEncodedCall: { encoded: 'Vec' }, @@ -164,5 +159,5 @@ export default { } }, XcmVersion: 'u32' - } + }) } as Definitions; diff --git a/packages/types/src/metadata/Metadata.ts b/packages/types/src/metadata/Metadata.ts index c5c75df0aa..4453f06153 100644 --- a/packages/types/src/metadata/Metadata.ts +++ b/packages/types/src/metadata/Metadata.ts @@ -27,7 +27,7 @@ function toU8a (value: Uint8Array | string = EMPTY_U8A): Uint8Array { } function decodeMetadata (registry: Registry, _value?: Uint8Array | string | Map | Record): MetadataVersioned { - if (!_value || isU8a(_value) || isHex(_value)) { + if (isU8a(_value) || !_value || isHex(_value)) { const value = toU8a(_value); const version = value[VERSION_IDX]; diff --git a/packages/types/src/metadata/decorate/errors/index.ts b/packages/types/src/metadata/decorate/errors/index.ts index 7ba63d3698..56e4dff9a7 100644 --- a/packages/types/src/metadata/decorate/errors/index.ts +++ b/packages/types/src/metadata/decorate/errors/index.ts @@ -6,7 +6,7 @@ import type { Text, u8 } from '../../../primitive'; import type { Registry } from '../../../types'; import type { Errors, IsError } from '../types'; -import { lazyMethod, stringCamelCase } from '@polkadot/util'; +import { lazyMethod, objectSpread, stringCamelCase } from '@polkadot/util'; import { lazyVariants } from '../../../create/lazy'; import { objectNameToString } from '../util'; @@ -20,12 +20,10 @@ interface ItemMeta { } export function variantToMeta (lookup: PortableRegistry, variant: SiVariant): ItemMeta { - return { - ...variant, - args: variant.fields.map(({ type }) => - lookup.getTypeDef(type).type - ) - }; + return objectSpread( + { args: variant.fields.map(({ type }) => lookup.getTypeDef(type).type) }, + variant + ); } /** @internal */ diff --git a/packages/types/src/metadata/decorate/extrinsics/createUnchecked.ts b/packages/types/src/metadata/decorate/extrinsics/createUnchecked.ts index 04696fa8ee..d934f88079 100644 --- a/packages/types/src/metadata/decorate/extrinsics/createUnchecked.ts +++ b/packages/types/src/metadata/decorate/extrinsics/createUnchecked.ts @@ -18,10 +18,7 @@ export function createUnchecked (registry: Registry, section: string, callIndex: const extrinsicFn = (...args: any[]): Call => { assert(expectedArgs.length === args.length, () => `Extrinsic ${section}.${funcName} expects ${expectedArgs.length} arguments, got ${args.length}.`); - return registry.createType('Call', { - args, - callIndex - }, callMetadata); + return registry.createType('Call', { args, callIndex }, callMetadata); }; extrinsicFn.is = (tx: IMethod): tx is IMethod => diff --git a/packages/types/src/metadata/decorate/extrinsics/index.ts b/packages/types/src/metadata/decorate/extrinsics/index.ts index 14fe1f660a..77d4d86eb0 100644 --- a/packages/types/src/metadata/decorate/extrinsics/index.ts +++ b/packages/types/src/metadata/decorate/extrinsics/index.ts @@ -5,7 +5,7 @@ import type { MetadataLatest, PalletMetadataLatest, PortableRegistry, SiVariant import type { CallFunction, Registry } from '../../../types'; import type { Extrinsics } from '../types'; -import { lazyMethod, stringCamelCase } from '@polkadot/util'; +import { lazyMethod, objectSpread, stringCamelCase } from '@polkadot/util'; import { lazyVariants } from '../../../create/lazy'; import { getSiName } from '../../util'; @@ -23,21 +23,22 @@ export function createCallFunction (registry: Registry, lookup: PortableRegistry for (let a = 0; a < fields.length; a++) { const { name, type, typeName } = fields[a]; - args[a] = { - name: stringCamelCase(name.unwrapOr(`param${a}`)), - type: getSiName(lookup, type), - ...(typeName.isSome + args[a] = objectSpread( + { + name: stringCamelCase(name.unwrapOr(`param${a}`)), + type: getSiName(lookup, type) + }, + typeName.isSome ? { typeName: typeName.unwrap() } - : {} - ) - }; + : null + ); } return createUnchecked( registry, sectionName, new Uint8Array([sectionIndex, index.toNumber()]), - registry.createType('FunctionMetadataLatest', { ...variant, args }) + registry.createType('FunctionMetadataLatest', objectSpread({ args }, variant)) ); } diff --git a/packages/types/src/metadata/decorate/storage/createFunction.ts b/packages/types/src/metadata/decorate/storage/createFunction.ts index 880efd2231..04ba3a1e24 100644 --- a/packages/types/src/metadata/decorate/storage/createFunction.ts +++ b/packages/types/src/metadata/decorate/storage/createFunction.ts @@ -6,7 +6,7 @@ import type { SiLookupTypeId } from '../../../interfaces/scaleInfo'; import type { StorageEntry } from '../../../primitive/types'; import type { Registry } from '../../../types'; -import { assert, compactAddLength, compactStripLength, isUndefined, stringCamelCase, stringLowerFirst, u8aConcat, u8aToU8a } from '@polkadot/util'; +import { assert, compactAddLength, compactStripLength, isUndefined, objectSpread, stringCamelCase, stringLowerFirst, u8aConcat, u8aToU8a } from '@polkadot/util'; import { xxhashAsU8a } from '@polkadot/util-crypto'; import { Raw } from '../../../codec'; @@ -79,10 +79,7 @@ function expandWithMeta ({ meta, method, prefix, section }: CreateItemFn, _stora // explicitly add the actual method in the toJSON, this gets used to determine caching and without it // instances (e.g. collective) will not work since it is only matched on param meta - storageFn.toJSON = (): any => ({ - ...(meta.toJSON() as Record), - storage: { method, prefix, section } - }); + storageFn.toJSON = (): any => objectSpread({ storage: { method, prefix, section } }, meta.toJSON()); return storageFn; } diff --git a/packages/types/src/primitive/Bool.ts b/packages/types/src/primitive/Bool.ts index 38a0f93af0..aab5a53a6d 100644 --- a/packages/types/src/primitive/Bool.ts +++ b/packages/types/src/primitive/Bool.ts @@ -9,10 +9,10 @@ import { isU8a, u8aToHex } from '@polkadot/util'; /** @internal */ function decodeBool (value: any): boolean { - if (value instanceof Boolean) { - return value.valueOf(); - } else if (isU8a(value)) { + if (isU8a(value)) { return value[0] === 1; + } else if (value instanceof Boolean) { + return value.valueOf(); } return !!value; diff --git a/packages/types/src/primitive/Data.ts b/packages/types/src/primitive/Data.ts index 68148ca9d1..3c75dd7eb9 100644 --- a/packages/types/src/primitive/Data.ts +++ b/packages/types/src/primitive/Data.ts @@ -30,10 +30,10 @@ function decodeDataU8a (registry: Registry, value: Uint8Array): [undefined | Uin /** @internal */ function decodeData (registry: Registry, value?: Record | Uint8Array | Enum | string): [any, number | undefined] { - if (!value) { - return [undefined, undefined]; - } else if (isU8a(value) || isString(value)) { + if (isU8a(value) || isString(value)) { return decodeDataU8a(registry, u8aToU8a(value)); + } else if (!value) { + return [undefined, undefined]; } // assume we have an Enum or an object input, handle this via the normal Enum decoding diff --git a/packages/types/src/primitive/StorageKey.ts b/packages/types/src/primitive/StorageKey.ts index f91015a98f..f4a7be9f01 100644 --- a/packages/types/src/primitive/StorageKey.ts +++ b/packages/types/src/primitive/StorageKey.ts @@ -52,16 +52,15 @@ export function unwrapStorageType (registry: Registry, type: StorageEntryTypeLat /** @internal */ function decodeStorageKey (value?: string | Uint8Array | StorageKey | StorageEntry | [StorageEntry, unknown[]?]): Decoded { - // eslint-disable-next-line @typescript-eslint/no-use-before-define - if (value instanceof StorageKey) { + if (isU8a(value) || !value || isString(value)) { + // let Bytes handle these inputs + return { key: value }; + } else if (value instanceof StorageKey) { return { key: value, method: value.method, section: value.section }; - } else if (!value || isString(value) || isU8a(value)) { - // let Bytes handle these inputs - return { key: value }; } else if (isFunction(value)) { return { key: value(), diff --git a/packages/types/src/primitive/Text.ts b/packages/types/src/primitive/Text.ts index cf531a44c7..d81a8b76d1 100644 --- a/packages/types/src/primitive/Text.ts +++ b/packages/types/src/primitive/Text.ts @@ -5,7 +5,7 @@ import type { HexString } from '@polkadot/util/types'; import type { CodecHash, Hash } from '../interfaces/runtime'; import type { AnyU8a, Codec, Registry } from '../types'; -import { assert, compactAddLength, compactFromU8a, hexToU8a, isHex, isString, stringToU8a, u8aToHex, u8aToString } from '@polkadot/util'; +import { assert, compactAddLength, compactFromU8a, hexToU8a, isHex, isString, isU8a, stringToU8a, u8aToHex, u8aToString } from '@polkadot/util'; import { Raw } from '../codec/Raw'; @@ -13,9 +13,7 @@ const MAX_LENGTH = 128 * 1024; /** @internal */ function decodeText (value?: null | Text | string | AnyU8a | { toString: () => string }): [string, number] { - if (isHex(value)) { - return [u8aToString(hexToU8a(value)), 0]; - } else if (value instanceof Uint8Array) { + if (isU8a(value)) { if (!value.length) { return ['', 0]; } @@ -33,6 +31,8 @@ function decodeText (value?: null | Text | string | AnyU8a | { toString: () => s assert(total <= value.length, () => `Text: required length less than remainder, expected at least ${total}, found ${value.length}`); return [u8aToString(value.subarray(offset, total)), total]; + } else if (isHex(value)) { + return [u8aToString(hexToU8a(value)), 0]; } return [value ? value.toString() : '', 0];