Parsing for metadata v14 (#3759)

* Adjust

* Better, need a BoundedVec solution...

* Composites

* Storage optional types

* Better... not perfect

* v14 tests passing

* Always perform asLatest

* Keep portable registry seperate

* Cleanup derived types

* Cleanups

* Adjust

* Cleanups

* Pass wraps

* Rename types (PortableRegistry) -> lookup

* Back on-track...

* SiLookup strings

* Allow building

* unsafe create on registry

* createTypeUnsafe typing

* Adjust

* Fix bool check

* Remove WrappedConstructor

* Additional

* Additional cleanups

* On-demand even type creation

* Rework

* Adjust

* Revert createClass to master (with adjustments)

* Running through v14

* Registry from master

* Run against v14

* Adjust

* Adjust

* Adjust generation (non-complete)

* Adjust

* Definition from metadata (round 1)

* Some linting fixes

* v13

* Adjust

* Dedupe

* Some linting

* Additional linting (md generation, not all)

* md additional

* calls update

* Additional linting

* Cleanups

* Remove extra arg

* Remove unneeded assert

* Revert < 12 index adjustments

* Cleanups

* v13 compat types

* Some tests

* Registry revert

* Additional test fixes

* Adjust sorting

* Adjust tests with lookups

* CodeClimate cleanups

* Additional tests

* Compat with prev-generation args

* Error & events compat args

* Fix Error/Event metadata creation

* Fix lookup circular

* Registry types

* Adjust

* Adjust lookup generation

* Short-circuit full type (with lookupIndex)

* Defaults for type expansion

* Tuple with extra spaces removed

* Fill in generated types

* Checks

* Adjust generation

* Adjust tests

* Adjust

* Adjust type encoding

* Adjust

* Use registry for name generation

* Update v13 lookup generation

* Adjust looup with typeDef (optional)

* Format lookup definitions

* Start with TS interface generation

* Adjust

* Adjust

* Adjust

* Don't short-cisrcuit type evaluation

* Adjust

* Correct plain imports

* Adjust

* Don't remove already-set lookupName

* Bytes

* Cleanups

* Adjust with unused

* Embed non-named structs

* Enum without name throws error

* Case-sensitivity on path duplication

* s/lookupNameOrig/lookupNameRoot/

* Don't export Lookup* type interfaces

* Shortcut lookup

* Adjust

* Revert api/Decorate

* Adjust import name generation

* Don't clobber root lookups

* Root exports

* Remove duplicated fields creation

* Adjust less-important name parts

* Cleanups & imports

* Adjust with correct imports

* Storage optionality

* Rebuild, fix (some) tests

* Extract identity BitFlags

* Additional cleanups

* Adjust

* No IdentityFields override

* v13 for extrinsic test

* Dedupe getUniqTypes

* Simplify?

* Adjust

* Update sorting

* Adjust expansion

* Dedupe

* Strip generics, sub-part * matching

* Name matching

* Align

* Adjust set matching

* hex/json split

* naming

* v13 for extrinsic injection test

* Adjust test signature

* Dedupe tests

* Adjust

* Update import

* augment @polkadot/types/lookup

* Sort import names

* Handle BitSequence in PortableRegistry

* Use Kusama-dev v14 metadata

* Merge bitSequence support

* Polkadot/Substrate split

* Template formatting

* Hobbling along

* Adjust

* Recode subs

* Fix circular in dual fashion

* Adjust

* Also generate Substrate

* Exclude Substrate types from Polkadot

* Remove duplicate phantoms

* Cleanup lookup typegen

* Additional

* Extract names with params (as applicable)

* Ensure path is always available

* renames

* Metadata v14 only has combined Map

* v14 Map conversion de-duped

* Substrate Map conversion

* v13 tests

* Apply suggestions from code review

* Housekeeping

* v14 bump

* NMap -> Map (& others removed)

* Adjust generation

* Decorate linting

* Tuple & non-tuple types

* hashers check

* Condense

* Additional asTuple check

* Consistent pre-v14 Map handling

* Fix metadata tests

* Fix (some) tests

* Fix test expectations

* Fail create early

* Additional fixes

* Additional

* Movement

* Remove CodecArg

* Dump it

* Apply param expansion

* Remove only

* Allow no-args to StorageKey

* linting

* multi fixes

* Map adjustments

* Rebuild

* Rebuild

* Rebuild

* Latest

* Bump metadata

* Rewrite

* Fix lookup formatting

* Rebuild after merge

* Latest substrate v14

* Rebuild

* Rebuild (+ no enum trailing ,)

* trigger

* Fix JSON checks

* Remove unneeded check

* Bump Kusama/Polkadot

* Dedupe testUtil

* Metadata v14
This commit is contained in:
Jaco
2021-09-15 19:46:48 +03:00
committed by GitHub
parent 88e5b26532
commit 22aafbdd4c
120 changed files with 21171 additions and 10491 deletions
@@ -0,0 +1,17 @@
// Copyright 2017-2021 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Definitions } from '../../types';
import kusama from './kusama';
import polkadot from './polkadot';
import substrate from './substrate';
export default {
rpc: {},
types: {
...polkadot,
...kusama,
...substrate
}
} as Definitions;
@@ -0,0 +1,4 @@
// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
/* eslint-disable */
export * from './types';
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,101 @@
// Auto-generated via `yarn polkadot-types-from-`, do not edit
/* eslint-disable */
/* eslint-disable sort-keys */
import type { DefinitionsTypes } from '../../types';
export default {
/**
* Lookup66: polkadot_runtime_common::claims::EthereumAddress
**/
PolkadotRuntimeCommonClaimsEthereumAddress: '[u8;20]',
/**
* Lookup72: polkadot_runtime::ProxyType
**/
PolkadotRuntimeProxyType: {
_enum: ['Any', 'NonTransfer', 'Governance', 'Staking', 'Unused4', 'IdentityJudgement', 'CancelProxy']
},
/**
* Lookup139: polkadot_runtime::SessionKeys
**/
PolkadotRuntimeSessionKeys: {
grandpa: 'SpFinalityGrandpaAppPublic',
babe: 'SpConsensusBabeAppPublic',
imOnline: 'PalletImOnlineSr25519AppSr25519Public',
paraValidator: 'PolkadotPrimitivesV0ValidatorAppPublic',
paraAssignment: 'PolkadotPrimitivesV1AssignmentAppPublic',
authorityDiscovery: 'SpAuthorityDiscoveryAppPublic'
},
/**
* Lookup140: polkadot_primitives::v0::validator_app::Public
**/
PolkadotPrimitivesV0ValidatorAppPublic: 'SpCoreSr25519Public',
/**
* Lookup141: polkadot_primitives::v1::assignment_app::Public
**/
PolkadotPrimitivesV1AssignmentAppPublic: 'SpCoreSr25519Public',
/**
* Lookup175: polkadot_runtime_common::claims::EcdsaSignature
**/
PolkadotRuntimeCommonClaimsEcdsaSignature: '[u8;65]',
/**
* Lookup180: polkadot_runtime_common::claims::StatementKind
**/
PolkadotRuntimeCommonClaimsStatementKind: {
_enum: ['Regular', 'Saft']
},
/**
* Lookup233: polkadot_runtime::NposCompactSolution16
**/
PolkadotRuntimeNposCompactSolution16: {
votes1: 'Vec<(Compact<u32>,Compact<u16>)>',
votes2: 'Vec<(Compact<u32>,(Compact<u16>,Compact<PerU16>),Compact<u16>)>',
votes3: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);2],Compact<u16>)>',
votes4: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);3],Compact<u16>)>',
votes5: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);4],Compact<u16>)>',
votes6: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);5],Compact<u16>)>',
votes7: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);6],Compact<u16>)>',
votes8: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);7],Compact<u16>)>',
votes9: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);8],Compact<u16>)>',
votes10: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);9],Compact<u16>)>',
votes11: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);10],Compact<u16>)>',
votes12: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);11],Compact<u16>)>',
votes13: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);12],Compact<u16>)>',
votes14: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);13],Compact<u16>)>',
votes15: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);14],Compact<u16>)>',
votes16: 'Vec<(Compact<u32>,[(Compact<u16>,Compact<PerU16>);15],Compact<u16>)>'
},
/**
* Lookup290: polkadot_runtime::OriginCaller
**/
PolkadotRuntimeOriginCaller: {
_enum: {
system: 'FrameSystemRawOrigin',
Unused1: 'Null',
Unused2: 'Null',
Void: 'SpCoreVoid',
Unused4: 'Null',
Unused5: 'Null',
Unused6: 'Null',
Unused7: 'Null',
Unused8: 'Null',
Unused9: 'Null',
Unused10: 'Null',
Unused11: 'Null',
Unused12: 'Null',
Unused13: 'Null',
Unused14: 'Null',
Council: 'PalletCollectiveRawOrigin',
TechnicalCommittee: 'PalletCollectiveRawOrigin'
}
},
/**
* Lookup441: polkadot_runtime_common::claims::PrevalidateAttests<T>
**/
PolkadotRuntimeCommonClaimsPrevalidateAttests: 'Null',
/**
* Lookup442: polkadot_runtime::Runtime
**/
PolkadotRuntimeRuntime: 'Null'
} as DefinitionsTypes;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,99 @@
// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
/* eslint-disable */
import type { Compact, Enum, Null, Struct, U8aFixed, Vec, u16, u32 } from '@polkadot/types';
import type { PerU16 } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
declare module '@polkadot/types/lookup' {
/** @name PolkadotRuntimeCommonClaimsEthereumAddress (66) */
export interface PolkadotRuntimeCommonClaimsEthereumAddress extends U8aFixed {}
/** @name PolkadotRuntimeProxyType (72) */
export interface PolkadotRuntimeProxyType extends Enum {
readonly isAny: boolean;
readonly isNonTransfer: boolean;
readonly isGovernance: boolean;
readonly isStaking: boolean;
readonly isUnused4: boolean;
readonly isIdentityJudgement: boolean;
readonly isCancelProxy: boolean;
}
/** @name PolkadotRuntimeSessionKeys (139) */
export interface PolkadotRuntimeSessionKeys extends Struct {
readonly grandpa: SpFinalityGrandpaAppPublic;
readonly babe: SpConsensusBabeAppPublic;
readonly imOnline: PalletImOnlineSr25519AppSr25519Public;
readonly paraValidator: PolkadotPrimitivesV0ValidatorAppPublic;
readonly paraAssignment: PolkadotPrimitivesV1AssignmentAppPublic;
readonly authorityDiscovery: SpAuthorityDiscoveryAppPublic;
}
/** @name PolkadotPrimitivesV0ValidatorAppPublic (140) */
export interface PolkadotPrimitivesV0ValidatorAppPublic extends SpCoreSr25519Public {}
/** @name PolkadotPrimitivesV1AssignmentAppPublic (141) */
export interface PolkadotPrimitivesV1AssignmentAppPublic extends SpCoreSr25519Public {}
/** @name PolkadotRuntimeCommonClaimsEcdsaSignature (175) */
export interface PolkadotRuntimeCommonClaimsEcdsaSignature extends U8aFixed {}
/** @name PolkadotRuntimeCommonClaimsStatementKind (180) */
export interface PolkadotRuntimeCommonClaimsStatementKind extends Enum {
readonly isRegular: boolean;
readonly isSaft: boolean;
}
/** @name PolkadotRuntimeNposCompactSolution16 (233) */
export interface PolkadotRuntimeNposCompactSolution16 extends Struct {
readonly votes1: Vec<ITuple<[Compact<u32>, Compact<u16>]>>;
readonly votes2: Vec<ITuple<[Compact<u32>, ITuple<[Compact<u16>, Compact<PerU16>]>, Compact<u16>]>>;
readonly votes3: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes4: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes5: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes6: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes7: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes8: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes9: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes10: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes11: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes12: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes13: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes14: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes15: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
readonly votes16: Vec<ITuple<[Compact<u32>, Vec<ITuple<[Compact<u16>, Compact<PerU16>]>>, Compact<u16>]>>;
}
/** @name PolkadotRuntimeOriginCaller (290) */
export interface PolkadotRuntimeOriginCaller extends Enum {
readonly isSystem: boolean;
readonly asSystem: FrameSystemRawOrigin;
readonly isUnused1: boolean;
readonly isUnused2: boolean;
readonly isVoid: boolean;
readonly isUnused4: boolean;
readonly isUnused5: boolean;
readonly isUnused6: boolean;
readonly isUnused7: boolean;
readonly isUnused8: boolean;
readonly isUnused9: boolean;
readonly isUnused10: boolean;
readonly isUnused11: boolean;
readonly isUnused12: boolean;
readonly isUnused13: boolean;
readonly isUnused14: boolean;
readonly isCouncil: boolean;
readonly asCouncil: PalletCollectiveRawOrigin;
readonly isTechnicalCommittee: boolean;
readonly asTechnicalCommittee: PalletCollectiveRawOrigin;
}
/** @name PolkadotRuntimeCommonClaimsPrevalidateAttests (441) */
export type PolkadotRuntimeCommonClaimsPrevalidateAttests = Null;
/** @name PolkadotRuntimeRuntime (442) */
export type PolkadotRuntimeRuntime = Null;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,6 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import './types-substrate';
import './types-polkadot';
import './types-kusama';
+1 -4
View File
@@ -32,7 +32,7 @@ import type { AuthorityIndex, AuthorityList, AuthoritySet, AuthoritySetChange, A
import type { IdentityFields, IdentityInfo, IdentityInfoAdditional, IdentityInfoTo198, IdentityJudgement, RegistrarIndex, RegistrarInfo, Registration, RegistrationJudgement, RegistrationTo198 } from '@polkadot/types/interfaces/identity';
import type { AuthIndex, AuthoritySignature, Heartbeat, HeartbeatTo244, OpaqueMultiaddr, OpaqueNetworkState, OpaquePeerId } from '@polkadot/types/interfaces/imOnline';
import type { CallIndex, LotteryConfig } from '@polkadot/types/interfaces/lottery';
import type { ErrorMetadataLatest, ErrorMetadataV10, ErrorMetadataV11, ErrorMetadataV12, ErrorMetadataV13, ErrorMetadataV14, ErrorMetadataV9, EventMetadataLatest, EventMetadataV10, EventMetadataV11, EventMetadataV12, EventMetadataV13, EventMetadataV14, EventMetadataV9, ExtrinsicMetadataLatest, ExtrinsicMetadataV11, ExtrinsicMetadataV12, ExtrinsicMetadataV13, ExtrinsicMetadataV14, FunctionArgumentMetadataLatest, FunctionArgumentMetadataV10, FunctionArgumentMetadataV11, FunctionArgumentMetadataV12, FunctionArgumentMetadataV13, FunctionArgumentMetadataV14, FunctionArgumentMetadataV9, FunctionMetadataLatest, FunctionMetadataV10, FunctionMetadataV11, FunctionMetadataV12, FunctionMetadataV13, FunctionMetadataV14, FunctionMetadataV9, MetadataAll, MetadataLatest, MetadataV10, MetadataV11, MetadataV12, MetadataV13, MetadataV14, MetadataV9, ModuleConstantMetadataLatest, ModuleConstantMetadataV10, ModuleConstantMetadataV11, ModuleConstantMetadataV12, ModuleConstantMetadataV13, ModuleConstantMetadataV9, ModuleMetadataLatest, ModuleMetadataV10, ModuleMetadataV11, ModuleMetadataV12, ModuleMetadataV13, ModuleMetadataV9, PalletCallMetadataLatest, PalletCallMetadataV14, PalletConstantMetadataLatest, PalletConstantMetadataV14, PalletErrorMetadataLatest, PalletErrorMetadataV14, PalletEventMetadataLatest, PalletEventMetadataV14, PalletMetadataLatest, PalletMetadataV14, PalletStorageMetadataLatest, PalletStorageMetadataV14, PortableRegistry, PortableType, SignedExtensionMetadataLatest, SignedExtensionMetadataV14, StorageEntryMetadataLatest, StorageEntryMetadataV10, StorageEntryMetadataV11, StorageEntryMetadataV12, StorageEntryMetadataV13, StorageEntryMetadataV14, StorageEntryMetadataV9, StorageEntryModifierLatest, StorageEntryModifierV10, StorageEntryModifierV11, StorageEntryModifierV12, StorageEntryModifierV13, StorageEntryModifierV14, StorageEntryModifierV9, StorageEntryTypeLatest, StorageEntryTypeV10, StorageEntryTypeV11, StorageEntryTypeV12, StorageEntryTypeV13, StorageEntryTypeV14, StorageEntryTypeV9, StorageHasher, StorageHasherV10, StorageHasherV11, StorageHasherV12, StorageHasherV13, StorageHasherV14, StorageHasherV9, StorageMetadataLatest, StorageMetadataV10, StorageMetadataV11, StorageMetadataV12, StorageMetadataV13, StorageMetadataV9 } from '@polkadot/types/interfaces/metadata';
import type { ErrorMetadataLatest, ErrorMetadataV10, ErrorMetadataV11, ErrorMetadataV12, ErrorMetadataV13, ErrorMetadataV14, ErrorMetadataV9, EventMetadataLatest, EventMetadataV10, EventMetadataV11, EventMetadataV12, EventMetadataV13, EventMetadataV14, EventMetadataV9, ExtrinsicMetadataLatest, ExtrinsicMetadataV11, ExtrinsicMetadataV12, ExtrinsicMetadataV13, ExtrinsicMetadataV14, FunctionArgumentMetadataLatest, FunctionArgumentMetadataV10, FunctionArgumentMetadataV11, FunctionArgumentMetadataV12, FunctionArgumentMetadataV13, FunctionArgumentMetadataV14, FunctionArgumentMetadataV9, FunctionMetadataLatest, FunctionMetadataV10, FunctionMetadataV11, FunctionMetadataV12, FunctionMetadataV13, FunctionMetadataV14, FunctionMetadataV9, MetadataAll, MetadataLatest, MetadataV10, MetadataV11, MetadataV12, MetadataV13, MetadataV14, MetadataV9, ModuleConstantMetadataV10, ModuleConstantMetadataV11, ModuleConstantMetadataV12, ModuleConstantMetadataV13, ModuleConstantMetadataV9, ModuleMetadataV10, ModuleMetadataV11, ModuleMetadataV12, ModuleMetadataV13, ModuleMetadataV9, PalletCallMetadataLatest, PalletCallMetadataV14, PalletConstantMetadataLatest, PalletConstantMetadataV14, PalletErrorMetadataLatest, PalletErrorMetadataV14, PalletEventMetadataLatest, PalletEventMetadataV14, PalletMetadataLatest, PalletMetadataV14, PalletStorageMetadataLatest, PalletStorageMetadataV14, PortableRegistry, PortableType, SignedExtensionMetadataLatest, SignedExtensionMetadataV14, StorageEntryMetadataLatest, StorageEntryMetadataV10, StorageEntryMetadataV11, StorageEntryMetadataV12, StorageEntryMetadataV13, StorageEntryMetadataV14, StorageEntryMetadataV9, StorageEntryModifierLatest, StorageEntryModifierV10, StorageEntryModifierV11, StorageEntryModifierV12, StorageEntryModifierV13, StorageEntryModifierV14, StorageEntryModifierV9, StorageEntryTypeLatest, StorageEntryTypeV10, StorageEntryTypeV11, StorageEntryTypeV12, StorageEntryTypeV13, StorageEntryTypeV14, StorageEntryTypeV9, StorageHasher, StorageHasherV10, StorageHasherV11, StorageHasherV12, StorageHasherV13, StorageHasherV14, StorageHasherV9, StorageMetadataV10, StorageMetadataV11, StorageMetadataV12, StorageMetadataV13, StorageMetadataV9 } from '@polkadot/types/interfaces/metadata';
import type { MmrLeafProof } from '@polkadot/types/interfaces/mmr';
import type { StorageKind } from '@polkadot/types/interfaces/offchain';
import type { DeferredOffenceOf, Kind, OffenceDetails, Offender, OpaqueTimeSlot, ReportIdOf, Reporter } from '@polkadot/types/interfaces/offences';
@@ -540,14 +540,12 @@ declare module '@polkadot/types/types/registry' {
MetadataV9: MetadataV9;
MmrLeafProof: MmrLeafProof;
MmrRootHash: MmrRootHash;
ModuleConstantMetadataLatest: ModuleConstantMetadataLatest;
ModuleConstantMetadataV10: ModuleConstantMetadataV10;
ModuleConstantMetadataV11: ModuleConstantMetadataV11;
ModuleConstantMetadataV12: ModuleConstantMetadataV12;
ModuleConstantMetadataV13: ModuleConstantMetadataV13;
ModuleConstantMetadataV9: ModuleConstantMetadataV9;
ModuleId: ModuleId;
ModuleMetadataLatest: ModuleMetadataLatest;
ModuleMetadataV10: ModuleMetadataV10;
ModuleMetadataV11: ModuleMetadataV11;
ModuleMetadataV12: ModuleMetadataV12;
@@ -894,7 +892,6 @@ declare module '@polkadot/types/types/registry' {
StorageHasherV9: StorageHasherV9;
StorageKey: StorageKey;
StorageKind: StorageKind;
StorageMetadataLatest: StorageMetadataLatest;
StorageMetadataV10: StorageMetadataV10;
StorageMetadataV11: StorageMetadataV11;
StorageMetadataV12: StorageMetadataV12;
+2 -2
View File
@@ -20,10 +20,10 @@ function decodeSetFromU8a<V extends Codec> (registry: Registry, ValClass: Constr
types.push(ValClass);
}
const values = decodeU8a(registry, u8a.subarray(offset), types);
const values = decodeU8a<V>(registry, u8a.subarray(offset), types);
for (let i = 0; i < values.length; i++) {
output.add(values[i] as V);
output.add(values[i]);
}
return output;
+9 -8
View File
@@ -24,22 +24,23 @@ function decodeStructFromObject <T> (registry: Registry, Types: ConstructorDef,
const jsonKey = (jsonMap.get(key as any) && !value[key])
? jsonMap.get(key as any)
: key;
const Type = Types[key];
try {
if (Array.isArray(value)) {
// TS2322: Type 'Codec' is not assignable to type 'T[keyof S]'.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
(raw as any)[key] = value[index] instanceof Types[key]
(raw as any)[key] = value[index] instanceof Type
? value[index]
: new Types[key](registry, value[index]);
: new Type(registry, value[index]);
} else if (value instanceof Map) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const mapped = value.get(jsonKey);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(raw as any)[key] = mapped instanceof Types[key]
(raw as any)[key] = mapped instanceof Type
? mapped
: new Types[key](registry, mapped);
: new Type(registry, mapped);
} else if (isObject(value)) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
let assign = value[jsonKey as string];
@@ -59,17 +60,17 @@ function decodeStructFromObject <T> (registry: Registry, Types: ConstructorDef,
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
(raw as any)[key] = assign instanceof Types[key]
(raw as any)[key] = assign instanceof Type
? assign
: new Types[key](registry, assign);
: new Type(registry, assign);
} else {
throw new Error(`Cannot decode value ${stringify(value)} (typeof ${typeof value}), expected an input object with known keys`);
}
} catch (error) {
let type = Types[key].name;
let type = Type.name;
try {
type = new Types[key](registry).toRawType();
type = new Type(registry).toRawType();
} catch (error) {
// ignore
}
+1 -1
View File
@@ -86,7 +86,7 @@ export class Tuple extends AbstractArray<Codec> implements ITuple<Codec[]> {
*/
public get Types (): string[] {
return Array.isArray(this._Types)
? this._Types.map((Type): string => new Type(this.registry).toRawType())
? this._Types.map((Type) => new Type(this.registry).toRawType())
: Object.keys(this._Types);
}
+1 -1
View File
@@ -52,7 +52,7 @@ export class Vec<T extends Codec> extends AbstractArray<T> {
assert(length.lten(MAX_LENGTH), () => `Vec length ${length.toString()} exceeds ${MAX_LENGTH}`);
return decodeU8a(registry, u8a.subarray(offset), new Array(length.toNumber()).fill(Type)) as T[];
return decodeU8a(registry, u8a.subarray(offset), new Array(length.toNumber()).fill(Type));
}
public static with<O extends Codec> (Type: Constructor<O> | string): Constructor<Vec<O>> {
+5 -4
View File
@@ -10,13 +10,14 @@ import { u8aToHex } from '@polkadot/util';
* types, and return an array of decoded values.
*
* @param u8a - The u8a to decode.
* @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[] | { [index: string]: Constructor }, _keys?: string[]): Codec[] {
const [types, keys]: [Constructor<Codec>[], string[]] = Array.isArray(_types)
export function decodeU8a <T extends Codec = Codec> (registry: Registry, u8a: Uint8Array, _types: Constructor[] | { [index: string]: Constructor }, _keys?: string[]): T[] {
const result: T[] = [];
const [types, keys]: [Constructor[], string[]] = Array.isArray(_types)
? [_types, _keys || []]
: [Object.values(_types), Object.keys(_types)];
const result: Codec[] = [];
let offset = 0;
for (let i = 0; i < types.length; i++) {
@@ -25,7 +26,7 @@ export function decodeU8a (registry: Registry, u8a: Uint8Array, _types: Construc
try {
const value = new Type(registry, u8a.subarray(offset));
result.push(value);
result.push(value as T);
offset += value.encodedLength;
} catch (error) {
let rawType: string;
@@ -5,7 +5,7 @@ import type { Codec, Constructor, Registry } from '../../types';
import { isString } from '@polkadot/util';
export function typeToConstructor <T = Codec> (registry: Registry, type: string | Constructor<T>): Constructor<T> {
export function typeToConstructor <T extends Codec = Codec> (registry: Registry, type: string | Constructor<T>): Constructor<T> {
return (
isString(type)
? registry.createClass(type)
@@ -29,7 +29,11 @@ describe('getTypeClass', (): void => {
const spy = jest.spyOn(console, 'warn');
const typeDef = { info: TypeDefInfo.Plain, type: 'ABC' };
getTypeClass(registry, typeDef);
try {
getTypeClass(registry, typeDef);
} catch {
// ignore
}
expect(spy).toHaveBeenCalledWith(
expect.anything(),
+58 -84
View File
@@ -32,17 +32,12 @@ function encodeWithParams (registry: Registry, typeDef: TypeDef, outer: string):
case TypeDefInfo.Option:
case TypeDefInfo.Result:
case TypeDefInfo.Vec:
return paramsNotation(outer, sub, (param) => encodeTypeDef(registry, param));
return paramsNotation(outer, sub, (p) => encodeTypeDef(registry, p));
}
throw new Error(`Unable to encode ${stringify(typeDef)} with params`);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function encodeDoNotConstruct (registry: Registry, { displayName }: TypeDef): string {
return `DoNotConstruct<${displayName || 'Unknown'}>`;
}
function encodeSubTypes (registry: Registry, sub: TypeDef[], asEnum?: boolean, extra?: Record<string, unknown>): string {
const names = sub.map(({ name }) => name);
@@ -60,52 +55,6 @@ function encodeSubTypes (registry: Registry, sub: TypeDef[], asEnum?: boolean, e
);
}
function encodeEnum (registry: Registry, typeDef: TypeDef): string {
assert(typeDef.sub && Array.isArray(typeDef.sub), 'Unable to encode Enum type');
const sub = typeDef.sub;
// c-like enums have all Null entries
// TODO We need to take the disciminant into account and auto-add empty entries
return sub.every(({ type }) => type === 'Null')
? stringify({ _enum: sub.map(({ name }, index) => `${name || `Empty${index}`}`) })
: encodeSubTypes(registry, sub, true);
}
function encodeStruct (registry: Registry, typeDef: TypeDef): string {
assert(typeDef.sub && Array.isArray(typeDef.sub), 'Unable to encode Struct type');
return encodeSubTypes(registry, typeDef.sub, false, {
...(
typeDef.alias
? { _alias: [...typeDef.alias.entries()].reduce<Record<string, string>>((all, [k, v]) => ({
...all,
[k]: v
}), {}) }
: {}
)
});
}
function encodeTuple (registry: Registry, typeDef: TypeDef): string {
assert(typeDef.sub && Array.isArray(typeDef.sub), 'Unable to encode Tuple type');
return `(${typeDef.sub.map((type) => encodeTypeDef(registry, type)).join(',')})`;
}
function encodeUInt (registry: Registry, { length }: TypeDef, type: 'Int' | 'UInt'): string {
assert(isNumber(length), 'Unable to encode VecFixed type');
return `${type}<${length}>`;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function encodeVecFixed (registry: Registry, { length, sub }: TypeDef): string {
assert(isNumber(length) && !isUndefined(sub) && !Array.isArray(sub), 'Unable to encode VecFixed type');
return `[${sub.type};${length}]`;
}
// We setup a record here to ensure we have comprehensive coverage (any item not covered will result
// in a compile-time error with the missing index)
const encoders: Record<TypeDefInfo, (registry: Registry, typeDef: TypeDef) => string> = {
@@ -115,14 +64,21 @@ const encoders: Record<TypeDefInfo, (registry: Registry, typeDef: TypeDef) => st
encodeWithParams(registry, typeDef, 'BTreeSet'),
[TypeDefInfo.Compact]: (registry: Registry, typeDef: TypeDef) =>
encodeWithParams(registry, typeDef, 'Compact'),
[TypeDefInfo.DoNotConstruct]: (registry: Registry, typeDef: TypeDef) =>
encodeDoNotConstruct(registry, typeDef),
[TypeDefInfo.Enum]: (registry: Registry, typeDef: TypeDef) =>
encodeEnum(registry, typeDef),
[TypeDefInfo.DoNotConstruct]: (registry: Registry, { displayName, lookupIndex, lookupName }: TypeDef) =>
`DoNotConstruct<${lookupName || displayName || (isUndefined(lookupIndex) ? 'Unknown' : registry.createLookupType(lookupIndex))}>`,
[TypeDefInfo.Enum]: (registry: Registry, { sub }: TypeDef): string => {
assert(sub && Array.isArray(sub), 'Unable to encode Enum type');
// c-like enums have all Null entries
// TODO We need to take the disciminant into account and auto-add empty entries
return sub.every(({ type }) => type === 'Null')
? stringify({ _enum: sub.map(({ name }, index) => `${name || `Empty${index}`}`) })
: encodeSubTypes(registry, sub, true);
},
[TypeDefInfo.HashMap]: (registry: Registry, typeDef: TypeDef) =>
encodeWithParams(registry, typeDef, 'HashMap'),
[TypeDefInfo.Int]: (registry: Registry, typeDef: TypeDef) =>
encodeUInt(registry, typeDef, 'Int'),
[TypeDefInfo.Int]: (registry: Registry, { length = 32 }: TypeDef) =>
`Int<${length}>`,
[TypeDefInfo.Linkage]: (registry: Registry, typeDef: TypeDef) =>
encodeWithParams(registry, typeDef, 'Linkage'),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -131,51 +87,69 @@ const encoders: Record<TypeDefInfo, (registry: Registry, typeDef: TypeDef) => st
[TypeDefInfo.Option]: (registry: Registry, typeDef: TypeDef) =>
encodeWithParams(registry, typeDef, 'Option'),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[TypeDefInfo.Plain]: (registry: Registry, typeDef: TypeDef) =>
typeDef.displayName || typeDef.type,
[TypeDefInfo.Plain]: (registry: Registry, { displayName, type }: TypeDef) =>
displayName || type,
[TypeDefInfo.Range]: (registry: Registry, typeDef: TypeDef) =>
encodeWithParams(registry, typeDef, typeDef.type.includes('RangeInclusive') ? 'RangeInclusive' : 'Range'),
[TypeDefInfo.Result]: (registry: Registry, typeDef: TypeDef) =>
encodeWithParams(registry, typeDef, 'Result'),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[TypeDefInfo.Set]: (registry: Registry, typeDef: TypeDef) =>
typeDef.type,
[TypeDefInfo.Set]: (registry: Registry, { length = 8, sub }: TypeDef): string => {
assert(sub && Array.isArray(sub), 'Unable to encode Set type');
return stringify({
_set: sub.reduce((all, { index, name }, count): Record<string, number> => ({
...all,
[`${name || `Unknown${index || count}`}`]: index || count
}), { _bitLength: length || 8 } as Record<string, number>)
});
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[TypeDefInfo.Si]: (registry: Registry, typeDef: TypeDef) =>
typeDef.lookupName || typeDef.type,
[TypeDefInfo.Struct]: (registry: Registry, typeDef: TypeDef) =>
encodeStruct(registry, typeDef),
[TypeDefInfo.Tuple]: (registry: Registry, typeDef: TypeDef) =>
encodeTuple(registry, typeDef),
[TypeDefInfo.UInt]: (registry: Registry, typeDef: TypeDef) =>
encodeUInt(registry, typeDef, 'UInt'),
[TypeDefInfo.Si]: (registry: Registry, { lookupName, type }: TypeDef) =>
lookupName || type,
[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<Record<string, string>>((all, [k, v]) => ({
...all,
[k]: v
}), {}) }
: {}
)
});
},
[TypeDefInfo.Tuple]: (registry: Registry, { sub }: TypeDef): string => {
assert(sub && Array.isArray(sub), 'Unable to encode Tuple type');
return `(${sub.map((type) => encodeTypeDef(registry, type)).join(',')})`;
},
[TypeDefInfo.UInt]: (registry: Registry, { length = 32 }: TypeDef) =>
`UInt<${length}>`,
[TypeDefInfo.Vec]: (registry: Registry, typeDef: TypeDef) =>
encodeWithParams(registry, typeDef, 'Vec'),
[TypeDefInfo.VecFixed]: (registry: Registry, typeDef: TypeDef) =>
encodeVecFixed(registry, typeDef)
[TypeDefInfo.VecFixed]: (registry: Registry, { length, sub }: TypeDef): string => {
assert(isNumber(length) && !isUndefined(sub) && !Array.isArray(sub), 'Unable to encode VecFixed type');
return `[${sub.type};${length}]`;
}
};
function encodeType (registry: Registry, typeDef: TypeDef, withLookup = true): string {
const encoder = encoders[typeDef.info];
assert(encoder, () => `Cannot encode type ${stringify(typeDef)}`);
return withLookup && typeDef.lookupName
? typeDef.lookupName
: encoder(registry, typeDef);
: encoders[typeDef.info](registry, typeDef);
}
export function encodeTypeDef (registry: Registry, typeDef: TypeDef): string {
assert(!isUndefined(typeDef.info), () => `Invalid type definition with no instance info, typeDef=${stringify(typeDef)}`);
// In the case of contracts we do have the unfortunate situation where the displayName would
// refer to "Option" when it is an option. For these, string it out, only using when actually
// not a top-level element to be used
if (typeDef.displayName && !INFO_WRAP.some((i) => typeDef.displayName === i)) {
return typeDef.displayName;
}
return encodeType(registry, typeDef);
return (typeDef.displayName && !INFO_WRAP.some((i) => typeDef.displayName === i))
? typeDef.displayName
: encodeType(registry, typeDef);
}
export function withTypeString (registry: Registry, typeDef: Omit<TypeDef, 'type'>): TypeDef {
+1 -1
View File
@@ -79,7 +79,7 @@ function _decodeSet (value: TypeDef, details: Record<string, number>): TypeDef {
index,
info: TypeDefInfo.Plain,
name,
type: name
type: 'Null'
}));
return value;
+47 -34
View File
@@ -1,8 +1,6 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
/* eslint-disable @typescript-eslint/no-var-requires */
import type { ExtDef } from '../extrinsic/signedExtensions/types';
import type { ChainProperties, CodecHash, DispatchErrorModule, Hash, MetadataLatest, PortableRegistry, SiLookupTypeId } from '../interfaces/types';
import type { CallFunction, Codec, CodecHasher, Constructor, DetectCodec, DetectConstructor, RegisteredTypes, Registry, RegistryError, RegistryTypes } from '../types';
@@ -20,29 +18,37 @@ import * as baseTypes from '../index.types';
import * as definitions from '../interfaces/definitions';
import { decorateConstants, decorateExtrinsics } from '../metadata/decorate';
import { Metadata } from '../metadata/Metadata';
import { createClass, getTypeClass } from './createClass';
import { createClass } from './createClass';
import { createTypeUnsafe } from './createType';
import { getTypeDef } from './getTypeDef';
const l = logger('registry');
// create error mapping from metadata
function injectErrors (_: Registry, metadata: Metadata, metadataErrors: Record<string, RegistryError>): void {
const modules = metadata.asLatest.modules;
const { lookup, pallets } = metadata.asLatest;
// decorate the errors
modules.forEach(({ errors, index, name }, _sectionIndex): void => {
pallets.forEach(({ errors, index, name }, _sectionIndex): void => {
if (errors.isNone) {
return;
}
const sectionIndex = metadata.version >= 12
? index.toNumber()
: _sectionIndex;
const sectionName = stringCamelCase(name);
errors.forEach(({ docs, name }, index): void => {
const eventIndex = new Uint8Array([sectionIndex, index]);
lookup.getSiType(errors.unwrap().type).def.asVariant.variants.forEach(({ docs, fields, index, name }): void => {
const variantIndex = index.toNumber();
const eventIndex = new Uint8Array([sectionIndex, variantIndex]);
metadataErrors[u8aToHex(eventIndex)] = {
args: fields.map(({ type }) =>
lookup.getTypeDef(type).type
),
docs: docs.map((d) => d.toString()),
index,
fields,
index: variantIndex,
method: name.toString(),
name: name.toString(),
section: sectionName
@@ -53,8 +59,10 @@ function injectErrors (_: Registry, metadata: Metadata, metadataErrors: Record<s
// create event classes from metadata
function injectEvents (registry: Registry, metadata: Metadata, metadataEvents: Record<string, Constructor<GenericEventData>>): void {
const { lookup, pallets } = metadata.asLatest;
// decorate the events
metadata.asLatest.modules
pallets
.filter(({ events }) => events.isSome)
.forEach(({ events, index, name }, _sectionIndex): void => {
const sectionIndex = metadata.version >= 12
@@ -62,23 +70,19 @@ function injectEvents (registry: Registry, metadata: Metadata, metadataEvents: R
: _sectionIndex;
const sectionName = stringCamelCase(name);
events.unwrap().forEach((meta, methodIndex): void => {
const methodName = meta.name.toString();
const typeDef = meta.args.map((arg) => getTypeDef(arg));
let Types: Constructor<Codec>[] | null = null;
lookup.getSiType(events.unwrap().type).def.asVariant.variants.forEach((variant): void => {
const variantIndex = variant.index.toNumber();
const eventIndex = new Uint8Array([sectionIndex, variantIndex]);
const meta = registry.createType('EventMetadataLatest', {
...variant,
args: variant.fields.map(({ type }) =>
lookup.getTypeDef(type).type
)
});
// Lazy create the actual type classes right at the point of use
const getTypes = (): Constructor<Codec>[] => {
if (!Types) {
Types = typeDef.map((typeDef) => getTypeClass(registry, typeDef));
}
return Types;
};
metadataEvents[u8aToHex(new Uint8Array([sectionIndex, methodIndex]))] = class extends GenericEventData {
metadataEvents[u8aToHex(eventIndex)] = class extends GenericEventData {
constructor (registry: Registry, value: Uint8Array) {
super(registry, value, getTypes(), typeDef, meta, sectionName, methodName);
super(registry, value, meta, sectionName, variant.name.toString());
}
};
});
@@ -219,9 +223,7 @@ export class TypeRegistry implements Registry {
}
public get lookup (): PortableRegistry {
throw new Error('Unimplemented');
// return this.metadata.lookup;
return this.metadata.lookup;
}
public get metadata (): MetadataLatest {
@@ -249,7 +251,7 @@ export class TypeRegistry implements Registry {
* @description Creates an instance of a type as registered
*/
public createType <T extends Codec = Codec, K extends string = string> (type: K, ...params: unknown[]): DetectCodec<T, K> {
return createTypeUnsafe(this, type, params);
return this.createTypeUnsafe(type, params);
}
/**
@@ -271,7 +273,10 @@ export class TypeRegistry implements Registry {
const hexIndex = u8aToHex(
isU8a(errorIndex)
? errorIndex
: new Uint8Array([errorIndex.index.toNumber(), errorIndex.error.toNumber()])
: new Uint8Array([
errorIndex.index.toNumber(),
errorIndex.error.toNumber()
])
);
return assertReturn(this.#metadataErrors[hexIndex], `findMetaError: Unable to find Error with index ${hexIndex}/[${errorIndex.toString()}]`);
@@ -294,10 +299,13 @@ export class TypeRegistry implements Registry {
// we have a definition, so create the class now (lazily)
if (definition) {
BaseType = createClass(this, definition);
this.#classes.set(name, BaseType);
} else if (withUnknown) {
l.warn(`Unable to resolve type ${name}, it will fail on construction`);
this.#unknownTypes.set(name, true);
BaseType = DoNotConstruct.with(name);
}
@@ -318,8 +326,8 @@ export class TypeRegistry implements Registry {
return this.#chainProperties;
}
public getClassName (clazz: Constructor): string | undefined {
const entry = [...this.#classes.entries()].find(([, test]) => test === clazz);
public getClassName (Type: Constructor): string | undefined {
const entry = [...this.#classes.entries()].find(([, Clazz]) => Type === Clazz);
return entry
? entry[0]
@@ -335,7 +343,11 @@ export class TypeRegistry implements Registry {
}
public getOrThrow <T extends Codec = Codec, K extends string = string> (name: K, msg?: string): DetectConstructor<T, K> {
return assertReturn(this.get<T, K>(name), msg || `type ${name} not found`);
const Clazz = this.get<T, K>(name);
assert(Clazz, msg || `type ${name} not found`);
return Clazz;
}
public getOrUnknown <T extends Codec = Codec, K extends string = string> (name: K): DetectConstructor<T, K> {
@@ -435,7 +447,8 @@ export class TypeRegistry implements Registry {
this.setSignedExtensions(
signedExtensions || (
metadata.asLatest.extrinsic.version.gt(BN_ZERO)
? metadata.asLatest.extrinsic.signedExtensions.map((key) => key.toString())
// FIXME Use the extension and their injected types
? metadata.asLatest.extrinsic.signedExtensions.map(({ identifier }) => identifier.toString())
: fallbackExtensions
),
userExtensions
@@ -39,7 +39,7 @@ describe('Extrinsic', (): void => {
expect(extrinsic.tip.toHuman()).toEqual('30.0000 mUnit');
expect(extrinsic.callIndex).toEqual(new Uint8Array([6, 0]));
expect(extrinsic.args[0].toHex()).toEqual('0x00495e1e506f266418af07fa0c5c108dd436f2faa59fe7d9e54403779f5bbd7718');
expect(extrinsic.args[1].toHuman()).toEqual('104.5609 Unit');
expect(extrinsic.args[1].toHuman()).toEqual('104,560,923,320,000'); // ('104.5609 Unit');
});
});
});
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { EcdsaSignature, Ed25519Signature, ExtrinsicUnknown, ExtrinsicV4, Sr25519Signature } from '../interfaces/extrinsics';
import type { FunctionMetadataLatest } from '../interfaces/metadata/types';
import type { FunctionMetadataLatest } from '../interfaces/metadata';
import type { Address, Balance, Call, Index } from '../interfaces/runtime';
import type { AnyJson, AnyTuple, AnyU8a, ArgsDef, CallBase, ExtrinsicPayloadValue, IExtrinsic, IKeyringPair, IMethod, Registry, SignatureOptions } from '../types';
import type { GenericExtrinsicEra } from './ExtrinsicEra';
+4 -19
View File
@@ -1,15 +1,13 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { FunctionArgumentMetadataLatest, FunctionMetadataLatest } from '../interfaces/metadata';
import type { AnyJson, AnyTuple, AnyU8a, ArgsDef, CallBase, CallFunction, IMethod, Registry } from '../types';
import type { FunctionMetadataLatest } from '../interfaces/metadata';
import type { AnyJson, AnyTuple, AnyU8a, ArgsDef, CallBase, CallFunction, IMethod, InterfaceTypes, Registry } from '../types';
import { isHex, isObject, isU8a, u8aToU8a } from '@polkadot/util';
import { Struct } from '../codec/Struct';
import { U8aFixed } from '../codec/U8aFixed';
import { getTypeClass } from '../create/createClass';
import { getTypeDef } from '../create/getTypeDef';
interface DecodeMethodInput {
args: unknown;
@@ -30,11 +28,8 @@ interface DecodedMethod extends DecodeMethodInput {
* @internal
*/
function getArgsDef (registry: Registry, meta: FunctionMetadataLatest): ArgsDef {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return GenericCall.filterOrigin(meta).reduce((result, { name, type }): ArgsDef => {
const Type = getTypeClass(registry, getTypeDef(type));
result[name.toString()] = Type;
return meta.fields.reduce((result, { name, type }, index): ArgsDef => {
result[name.unwrapOr(`param${index}`).toString()] = registry.createLookupType(type) as keyof InterfaceTypes;
return result;
}, {} as ArgsDef);
@@ -146,16 +141,6 @@ export class GenericCall<A extends AnyTuple = AnyTuple> extends Struct implement
this._meta = decoded.meta;
}
// If the extrinsic function has an argument of type `Origin`, we ignore it
public static filterOrigin (meta?: FunctionMetadataLatest): FunctionArgumentMetadataLatest[] {
// FIXME should be `arg.type !== Origin`, but doesn't work...
return meta
? meta.args.filter(({ type }): boolean =>
type.toString() !== 'Origin'
)
: [];
}
/**
* @description The arguments for the function call
*/
+6 -4
View File
@@ -4,7 +4,7 @@
import type { TypeDef } from '../create/types';
import type { EventMetadataLatest } from '../interfaces/metadata';
import type { EventId } from '../interfaces/system';
import type { AnyJson, Codec, Constructor, IEvent, IEventData, Registry } from '../types';
import type { AnyJson, Codec, Constructor, IEvent, IEventData, InterfaceTypes, Registry } from '../types';
import { Struct } from '../codec/Struct';
import { Tuple } from '../codec/Tuple';
@@ -49,13 +49,15 @@ export class GenericEventData extends Tuple implements IEventData {
readonly #typeDef: TypeDef[];
constructor (registry: Registry, value: Uint8Array, Types: Constructor[] = [], typeDef: TypeDef[] = [], meta: EventMetadataLatest, section = '<unknown>', method = '<unknown>') {
super(registry, Types, value);
constructor (registry: Registry, value: Uint8Array, meta: EventMetadataLatest, section = '<unknown>', method = '<unknown>') {
const fields = meta?.fields || [];
super(registry, fields.map(({ type }) => registry.createLookupType(type) as keyof InterfaceTypes), value);
this.#meta = meta;
this.#method = method;
this.#section = section;
this.#typeDef = typeDef;
this.#typeDef = fields.map(({ type }) => registry.lookup.getTypeDef(type));
}
/**
+121 -34
View File
@@ -15,6 +15,9 @@ import { withTypeString } from '../create/encodeTypes';
import { getTypeDef } from '../create/getTypeDef';
import { TypeDefInfo } from '../types';
// Just a placeholder for a type.unrwapOr()
const TYPE_UNWRAP = { toNumber: () => -1 };
// Alias the primitive enum with out known values
const PRIMITIVE_ALIAS: Record<string, string> = {
Char: 'u32', // Rust char is 4-bytes
@@ -72,26 +75,96 @@ function getPrimitivePath (path: SiPath): string | null {
: null;
}
function removeDuplicateNames (names: [number, (string | null)][]): [number, (string | null)][] {
return names.map(([lookupIndex, name]): [number, string | null] => [
lookupIndex,
(
!name ||
names.some(([oIndex, oName]) =>
name === oName &&
lookupIndex !== oIndex
)
)
? null
: name
]);
function removeDuplicateNames (lookup: GenericPortableRegistry, names: [number, string | null, SiTypeParameter[]][]): [number, string][] {
const rewrite: Record<number, string> = {};
return names
.map(([lookupIndex, name, params]): [number, string | null] => {
if (!name) {
return [lookupIndex, null];
}
// those where the name is matching
const allSame = names.filter(([, oName]) => name === oName);
// are there among matching names
const anyDiff = allSame.some(([oIndex,, oParams]) =>
lookupIndex !== oIndex && (
params.length !== oParams.length ||
params.some((p, index) =>
!p.name.eq(oParams[index].name) ||
p.type.unwrapOr(TYPE_UNWRAP).toNumber() !== oParams[index].type.unwrapOr(TYPE_UNWRAP).toNumber()
)
)
);
// everything matches, we can combine these
if (!anyDiff || !allSame[0][2].length) {
return [lookupIndex, name];
}
// find the first parameter that yields differences
const paramIdx = allSame[0][2].findIndex(({ type }, index) =>
allSame.every(([,, params]) => params[index].type.isSome) &&
allSame.every(([,, params], aIndex) =>
aIndex === 0 ||
!params[index].type.eq(type)
)
);
// No param found that is different
if (paramIdx === -1) {
return [lookupIndex, name];
}
// see if using the param type helps
const adjusted = allSame.map(([oIndex, oName, oParams]): [number, string | null] => {
const { def, path } = lookup.getSiType(oParams[paramIdx].type.unwrap());
if (!def.isPrimitive && !path.length) {
return [oIndex, null];
}
return [
oIndex,
def.isPrimitive
? `${oName as string}${def.asPrimitive.toString()}`
: `${oName as string}${path[path.length - 1].toString()}`
];
});
// any dupes remaining?
const noDupes = adjusted.every(([i, n]) =>
!!n &&
!adjusted.some(([ai, an]) =>
i !== ai &&
n === an
)
);
if (noDupes) {
// we filtered above for null names
adjusted.forEach(([index, name]): void => {
rewrite[index] = name as string;
});
}
return noDupes
? [lookupIndex, name]
: [lookupIndex, null];
})
.filter((n): n is [number, string] => !!n[1])
.map(([lookupIndex, name]) => [
lookupIndex,
rewrite[lookupIndex] || name
]);
}
function extractName (types: PortableType[], id: SiLookupTypeId, { params, path }: SiType): [number, string | null] {
function extractName (types: PortableType[], { id, type: { params, path } }: PortableType): [number, string | null, SiTypeParameter[]] {
const lookupIndex = id.toNumber();
if (!path.length || WRAPPERS.includes(path[path.length - 1].toString())) {
return [lookupIndex, null];
return [lookupIndex, null, []];
}
const parts = path
@@ -120,28 +193,25 @@ function extractName (types: PortableType[], id: SiLookupTypeId, { params, path
}
}
return [lookupIndex, typeName];
return [lookupIndex, typeName, params];
}
function extractNames (registry: Registry, types: PortableType[]): Record<number, string> {
const dedup = removeDuplicateNames(
types.map(({ id, type }) =>
extractName(types, id, type)
)
);
const [names, typesNew] = dedup.reduce<[Record<number, string>, Record<string, string>]>(([names, types], [lookupIndex, name], index) => {
if (name) {
// We set the name for this specific type
names[index] = name;
function extractNames (lookup: GenericPortableRegistry, types: PortableType[]): Record<number, string> {
const dedup = removeDuplicateNames(lookup, types.map((t) =>
extractName(types, t)
));
// we map to the actual lookupIndex
types[name] = registry.createLookupType(lookupIndex);
}
const [names, typesNew] = dedup.reduce<[Record<number, string>, Record<string, string>]>(([names, types], [lookupIndex, name]) => {
// We set the name for this specific type
names[lookupIndex] = name;
// we map to the actual lookupIndex
types[name] = lookup.registry.createLookupType(lookupIndex);
return [names, types];
}, [{}, {}]);
registry.register(typesNew);
lookup.registry.register(typesNew);
return names;
}
@@ -155,7 +225,7 @@ export class GenericPortableRegistry extends Struct {
types: 'Vec<PortableType>'
}, value);
this.#names = extractNames(registry, this.types);
this.#names = extractNames(this, this.types);
}
/**
@@ -165,6 +235,13 @@ export class GenericPortableRegistry extends Struct {
return this.get('types') as Vec<PortableType>;
}
/**
* @description Returns the name for a specific lookup
*/
public getName (lookupId: SiLookupTypeId | string | number): string | undefined {
return this.#names[this.#getLookupId(lookupId)];
}
/**
* @description Finds a specific type in the registry
*/
@@ -183,16 +260,26 @@ export class GenericPortableRegistry extends Struct {
const lookupIndex = this.#getLookupId(lookupId);
if (!this.#typeDefs[lookupIndex]) {
// we set first since we will get into circular lookups along the way
this.#typeDefs[lookupIndex] = {
const lookupName = this.#names[lookupIndex];
const empty = {
info: TypeDefInfo.DoNotConstruct,
lookupIndex,
lookupName: this.#names[lookupIndex],
lookupName,
type: this.registry.createLookupType(lookupIndex)
};
// Set named items since we will get into circular lookups along the way
if (lookupName) {
this.#typeDefs[lookupIndex] = empty;
}
const extracted = this.#extract(this.getSiType(lookupId), lookupIndex);
// For non-named items, we only set this right at the end
if (!lookupName) {
this.#typeDefs[lookupIndex] = empty;
}
Object.keys(extracted).forEach((k): void => {
if (k !== 'lookupName' || extracted[k]) {
// these are safe since we are looking through the keys as set
@@ -2,8 +2,8 @@
/* eslint-disable */
import type { Enum, Option } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AccountId, BlockNumber, Hash } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name UncleEntryItem */
export interface UncleEntryItem extends Enum {
+1 -1
View File
@@ -2,9 +2,9 @@
/* eslint-disable */
import type { Enum, Option, Struct, U8aFixed, Vec, u32, u64 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AuthorityId } from '@polkadot/types/interfaces/consensus';
import type { Hash, Header } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name AllowedSlots */
export interface AllowedSlots extends Enum {
@@ -2,11 +2,11 @@
/* eslint-disable */
import type { BitVec, Bytes, Enum, Null, Struct, U8aFixed, Vec, bool, u32, u64 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { BlockHash } from '@polkadot/types/interfaces/chain';
import type { MultiSignature } from '@polkadot/types/interfaces/extrinsics';
import type { AuthorityList, SetId } from '@polkadot/types/interfaces/grandpa';
import type { AccountId, Balance, BlockNumber, H256, Header, MultiSigner, Weight } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name BridgedBlockHash */
export interface BridgedBlockHash extends H256 {}
@@ -2,8 +2,8 @@
/* eslint-disable */
import type { Enum, Struct, Vec, u32 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AccountId, BlockNumber } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name CollectiveOrigin */
export interface CollectiveOrigin extends Enum {
@@ -2,9 +2,9 @@
/* eslint-disable */
import type { Bytes, Enum, Option, Struct, Vec, bool, u32 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { Vote, VoteThreshold } from '@polkadot/types/interfaces/elections';
import type { AccountId, Balance, BlockNumber, Call, Hash } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name AccountVote */
export interface AccountVote extends Enum {
@@ -2,12 +2,12 @@
/* eslint-disable */
import type { BTreeSet, Bytes, Enum, Option, Struct, U64, Vec, u32, u64 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { BlockHash } from '@polkadot/types/interfaces/chain';
import type { AuthorityId } from '@polkadot/types/interfaces/consensus';
import type { AuthoritySignature } from '@polkadot/types/interfaces/imOnline';
import type { BlockNumber, Hash, Header } from '@polkadot/types/interfaces/runtime';
import type { MembershipProof } from '@polkadot/types/interfaces/session';
import type { ITuple } from '@polkadot/types/types';
/** @name AuthorityIndex */
export interface AuthorityIndex extends u64 {}
@@ -2,8 +2,8 @@
/* eslint-disable */
import type { Data, Enum, Option, Set, Struct, Vec, u32 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AccountId, Balance, H160 } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name IdentityFields */
export interface IdentityFields extends Set {
@@ -2,8 +2,8 @@
/* eslint-disable */
import type { Struct, bool, u8 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { Balance, BlockNumber } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name CallIndex */
export interface CallIndex extends ITuple<[u8, u8]> {}
@@ -26,14 +26,13 @@ export default {
...v13,
...v14,
//
// will be available once v14 is the default
// TODO: Comment out all commented stuff below and remove block below
//
// ExtrinsicMetadataLatest: 'ExtrinsicMetadataV14',
// FunctionArgumentMetadataLatest: 'FunctionArgumentMetadataV13',
// FunctionMetadataLatest: 'FunctionMetadataV14',
// MetadataLatest: 'MetadataV14',
// latest mappings
ErrorMetadataLatest: 'ErrorMetadataV14',
EventMetadataLatest: 'EventMetadataV14',
ExtrinsicMetadataLatest: 'ExtrinsicMetadataV14',
FunctionArgumentMetadataLatest: 'FunctionArgumentMetadataV14',
FunctionMetadataLatest: 'FunctionMetadataV14',
MetadataLatest: 'MetadataV14',
PalletCallMetadataLatest: 'PalletCallMetadataV14',
PalletConstantMetadataLatest: 'PalletConstantMetadataV14',
PalletErrorMetadataLatest: 'PalletErrorMetadataV14',
@@ -41,24 +40,10 @@ export default {
PalletMetadataLatest: 'PalletMetadataV14',
PalletStorageMetadataLatest: 'PalletStorageMetadataV14',
SignedExtensionMetadataLatest: 'SignedExtensionMetadataV14',
// StorageEntryMetadataLatest: 'StorageEntryMetadataV14',
// StorageEntryModifierLatest: 'StorageEntryModifierV14',
// StorageEntryTypeLatest: 'StorageEntryTypeV14',
// This always maps to the latest
ErrorMetadataLatest: 'ErrorMetadataV13',
EventMetadataLatest: 'EventMetadataV13',
ExtrinsicMetadataLatest: 'ExtrinsicMetadataV13',
FunctionArgumentMetadataLatest: 'FunctionArgumentMetadataV13',
FunctionMetadataLatest: 'FunctionMetadataV13',
MetadataLatest: 'MetadataV13',
ModuleConstantMetadataLatest: 'ModuleConstantMetadataV13',
ModuleMetadataLatest: 'ModuleMetadataV13',
StorageEntryMetadataLatest: 'StorageEntryMetadataV13',
StorageEntryModifierLatest: 'StorageEntryModifierV13',
StorageEntryTypeLatest: 'StorageEntryTypeV13',
StorageMetadataLatest: 'StorageMetadataV13',
StorageHasher: 'StorageHasherV13',
StorageEntryMetadataLatest: 'StorageEntryMetadataV14',
StorageEntryModifierLatest: 'StorageEntryModifierV14',
StorageEntryTypeLatest: 'StorageEntryTypeV14',
StorageHasher: 'StorageHasherV14',
// the enum containing all the mappings
MetadataAll: {
+10 -19
View File
@@ -5,7 +5,7 @@ import type { Bytes, Enum, GenericPortableRegistry, Option, Struct, Text, Type,
import type { SiField, SiLookupTypeId, SiType } from '@polkadot/types/interfaces/scaleInfo';
/** @name ErrorMetadataLatest */
export interface ErrorMetadataLatest extends ErrorMetadataV13 {}
export interface ErrorMetadataLatest extends ErrorMetadataV14 {}
/** @name ErrorMetadataV10 */
export interface ErrorMetadataV10 extends ErrorMetadataV9 {}
@@ -35,7 +35,7 @@ export interface ErrorMetadataV9 extends Struct {
}
/** @name EventMetadataLatest */
export interface EventMetadataLatest extends EventMetadataV13 {}
export interface EventMetadataLatest extends EventMetadataV14 {}
/** @name EventMetadataV10 */
export interface EventMetadataV10 extends EventMetadataV9 {}
@@ -66,7 +66,7 @@ export interface EventMetadataV9 extends Struct {
}
/** @name ExtrinsicMetadataLatest */
export interface ExtrinsicMetadataLatest extends ExtrinsicMetadataV13 {}
export interface ExtrinsicMetadataLatest extends ExtrinsicMetadataV14 {}
/** @name ExtrinsicMetadataV11 */
export interface ExtrinsicMetadataV11 extends Struct {
@@ -88,7 +88,7 @@ export interface ExtrinsicMetadataV14 extends Struct {
}
/** @name FunctionArgumentMetadataLatest */
export interface FunctionArgumentMetadataLatest extends FunctionArgumentMetadataV13 {}
export interface FunctionArgumentMetadataLatest extends FunctionArgumentMetadataV14 {}
/** @name FunctionArgumentMetadataV10 */
export interface FunctionArgumentMetadataV10 extends FunctionArgumentMetadataV9 {}
@@ -112,7 +112,7 @@ export interface FunctionArgumentMetadataV9 extends Struct {
}
/** @name FunctionMetadataLatest */
export interface FunctionMetadataLatest extends FunctionMetadataV13 {}
export interface FunctionMetadataLatest extends FunctionMetadataV14 {}
/** @name FunctionMetadataV10 */
export interface FunctionMetadataV10 extends FunctionMetadataV9 {}
@@ -159,7 +159,7 @@ export interface MetadataAll extends Enum {
}
/** @name MetadataLatest */
export interface MetadataLatest extends MetadataV13 {}
export interface MetadataLatest extends MetadataV14 {}
/** @name MetadataV10 */
export interface MetadataV10 extends Struct {
@@ -196,9 +196,6 @@ export interface MetadataV9 extends Struct {
readonly modules: Vec<ModuleMetadataV9>;
}
/** @name ModuleConstantMetadataLatest */
export interface ModuleConstantMetadataLatest extends ModuleConstantMetadataV13 {}
/** @name ModuleConstantMetadataV10 */
export interface ModuleConstantMetadataV10 extends ModuleConstantMetadataV9 {}
@@ -219,9 +216,6 @@ export interface ModuleConstantMetadataV9 extends Struct {
readonly docs: Vec<Text>;
}
/** @name ModuleMetadataLatest */
export interface ModuleMetadataLatest extends ModuleMetadataV13 {}
/** @name ModuleMetadataV10 */
export interface ModuleMetadataV10 extends Struct {
readonly name: Text;
@@ -352,7 +346,7 @@ export interface SignedExtensionMetadataV14 extends Struct {
}
/** @name StorageEntryMetadataLatest */
export interface StorageEntryMetadataLatest extends StorageEntryMetadataV13 {}
export interface StorageEntryMetadataLatest extends StorageEntryMetadataV14 {}
/** @name StorageEntryMetadataV10 */
export interface StorageEntryMetadataV10 extends Struct {
@@ -403,7 +397,7 @@ export interface StorageEntryMetadataV9 extends Struct {
}
/** @name StorageEntryModifierLatest */
export interface StorageEntryModifierLatest extends StorageEntryModifierV13 {}
export interface StorageEntryModifierLatest extends StorageEntryModifierV14 {}
/** @name StorageEntryModifierV10 */
export interface StorageEntryModifierV10 extends StorageEntryModifierV9 {}
@@ -428,7 +422,7 @@ export interface StorageEntryModifierV9 extends Enum {
}
/** @name StorageEntryTypeLatest */
export interface StorageEntryTypeLatest extends StorageEntryTypeV13 {}
export interface StorageEntryTypeLatest extends StorageEntryTypeV14 {}
/** @name StorageEntryTypeV10 */
export interface StorageEntryTypeV10 extends Enum {
@@ -536,7 +530,7 @@ export interface StorageEntryTypeV9 extends Enum {
}
/** @name StorageHasher */
export interface StorageHasher extends StorageHasherV13 {}
export interface StorageHasher extends StorageHasherV14 {}
/** @name StorageHasherV10 */
export interface StorageHasherV10 extends Enum {
@@ -577,9 +571,6 @@ export interface StorageHasherV9 extends Enum {
readonly isTwox64Concat: boolean;
}
/** @name StorageMetadataLatest */
export interface StorageMetadataLatest extends StorageMetadataV13 {}
/** @name StorageMetadataV10 */
export interface StorageMetadataV10 extends Struct {
readonly prefix: Text;
@@ -2,9 +2,9 @@
/* eslint-disable */
import type { Bytes, Struct, U8aFixed, Vec } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AccountId, Hash, Perbill } from '@polkadot/types/interfaces/runtime';
import type { IdentificationTuple, SessionIndex } from '@polkadot/types/interfaces/session';
import type { ITuple } from '@polkadot/types/types';
/** @name DeferredOffenceOf */
export interface DeferredOffenceOf extends ITuple<[Vec<OffenceDetails>, Vec<Perbill>, SessionIndex]> {}
@@ -2,10 +2,10 @@
/* eslint-disable */
import type { BTreeMap, BitVec, Bytes, Enum, Option, Struct, U8aFixed, Vec, bool, u32 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { Signature } from '@polkadot/types/interfaces/extrinsics';
import type { AccountId, Balance, BalanceOf, BlockNumber, H256, Hash, Header, StorageProof, ValidatorId, Weight } from '@polkadot/types/interfaces/runtime';
import type { MembershipProof, SessionIndex } from '@polkadot/types/interfaces/session';
import type { ITuple } from '@polkadot/types/types';
/** @name AbridgedCandidateReceipt */
export interface AbridgedCandidateReceipt extends Struct {
@@ -2,10 +2,10 @@
/* eslint-disable */
import type { Bytes, Compact, DoNotConstruct, Enum, GenericAccountId, GenericAccountIndex, GenericBlock, GenericCall, GenericConsensusEngineId, GenericEthereumAccountId, GenericLookupSource, GenericMultiAddress, Int, Null, Option, StorageKey, Struct, U8aFixed, UInt, Vec, u16, u32, u64, u8 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AuthorityId } from '@polkadot/types/interfaces/consensus';
import type { Signature } from '@polkadot/types/interfaces/extrinsics';
import type { SystemOrigin } from '@polkadot/types/interfaces/system';
import type { ITuple } from '@polkadot/types/types';
/** @name AccountId */
export interface AccountId extends AccountId32 {}
@@ -2,8 +2,8 @@
/* eslint-disable */
import type { Bytes, Option, Struct, u32, u8 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { BlockNumber, Call, PalletsOrigin } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name Period */
export interface Period extends ITuple<[BlockNumber, u32]> {}
@@ -2,9 +2,9 @@
/* eslint-disable */
import type { Bytes, Struct, U8aFixed, Vec, u32 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AccountId, ValidatorId } from '@polkadot/types/interfaces/runtime';
import type { Exposure } from '@polkadot/types/interfaces/staking';
import type { ITuple } from '@polkadot/types/types';
/** @name BeefyKey */
export interface BeefyKey extends U8aFixed {}
@@ -2,8 +2,8 @@
/* eslint-disable */
import type { Enum, Struct, u32 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AccountId, Balance } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name Bid */
export interface Bid extends Struct {
@@ -2,8 +2,8 @@
/* eslint-disable */
import type { BTreeMap, Compact, Enum, Option, Struct, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AccountId, Balance, BlockNumber, Moment, PerU16, Perbill } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name ActiveEraInfo */
export interface ActiveEraInfo extends Struct {
+1 -1
View File
@@ -2,8 +2,8 @@
/* eslint-disable */
import type { Bytes, Enum, HashMap, Option, StorageKey, Struct, Text, U8aFixed, Vec, bool, u32, u64 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { Hash, StorageData } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name ApiId */
export interface ApiId extends U8aFixed {}
@@ -2,9 +2,9 @@
/* eslint-disable */
import type { Bytes, Compact, Enum, GenericChainProperties, GenericEvent, HashMap, Option, Result, Struct, Text, U8aFixed, Vec, bool, i32, u32, u64, u8 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AccountData } from '@polkadot/types/interfaces/balances';
import type { AccountId, BlockNumber, Digest, Hash, Index, Pays, Weight } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name AccountInfo */
export interface AccountInfo extends AccountInfoWithTripleRefCount {}
@@ -2,8 +2,8 @@
/* eslint-disable */
import type { Enum, Option, Struct, Vec, bool, u32 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AccountId, Balance, BlockNumber, Hash } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name Bounty */
export interface Bounty extends Struct {
+1 -1
View File
@@ -2,8 +2,8 @@
/* eslint-disable */
import type { Bytes, Compact, Enum, Null, Option, Result, Struct, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types';
import type { ITuple } from '@polkadot/types/types';
import type { AccountId, BlockNumber, Weight } from '@polkadot/types/interfaces/runtime';
import type { ITuple } from '@polkadot/types/types';
/** @name AssetInstance */
export interface AssetInstance extends AssetInstanceV1 {}
+4
View File
@@ -0,0 +1,4 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
export type PHANTOM_LOOKUP = 'lookup';
+9 -3
View File
@@ -1,14 +1,20 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import substrateData from '@polkadot/types-support/metadata/static-substrate';
import polkadot from '@polkadot/types-support/metadata//static-polkadot';
import substrate from '@polkadot/types-support/metadata/static-substrate';
import { TypeRegistry } from '../create';
import { Metadata } from './Metadata';
const allData: Record<string, string> = {
polkadot,
substrate
};
describe('Metadata', (): void => {
it('allows creation from hex with JSON equivalence', (): void => {
const test = new Metadata(new TypeRegistry(), substrateData);
it.each(['polkadot', 'substrate'])('allows creation from hex on %s', (type): void => {
const test = new Metadata(new TypeRegistry(), allData[type]);
expect(
new Metadata(new TypeRegistry(), test.toHex()).toJSON()
@@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { MetadataAll, MetadataLatest, MetadataV9, MetadataV10, MetadataV11, MetadataV12, MetadataV13 } from '../interfaces/metadata';
import type { MetadataAll, MetadataLatest, MetadataV9, MetadataV10, MetadataV11, MetadataV12, MetadataV13, MetadataV14 } from '../interfaces/metadata';
import type { AnyJson, Registry } from '../types';
import { assert } from '@polkadot/util';
@@ -11,15 +11,16 @@ import { toV10 } from './v9/toV10';
import { toV11 } from './v10/toV11';
import { toV12 } from './v11/toV12';
import { toV13 } from './v12/toV13';
import { toLatest } from './v13/toLatest';
import { toV14 } from './v13/toV14';
import { toLatest } from './v14/toLatest';
import { MagicNumber } from './MagicNumber';
import { getUniqTypes, toCallsOnly } from './util';
type MetaMapped = MetadataV9 | MetadataV10 | MetadataV11 | MetadataV12 | MetadataV13;
type MetaAsX = 'asV9' | 'asV10' | 'asV11' | 'asV12' | 'asV13';
type MetaVersions = 'latest' | 9 | 10 | 11 | 12 | 13;
type MetaMapped = MetadataV9 | MetadataV10 | MetadataV11 | MetadataV12 | MetadataV13 | MetadataV14;
type MetaAsX = 'asV9' | 'asV10' | 'asV11' | 'asV12' | 'asV13' | 'asV14';
type MetaVersions = 'latest' | 9 | 10 | 11 | 12 | 13 | 14;
const LATEST_VERSION = 13;
const LATEST_VERSION = 14;
/**
* @name MetadataVersioned
@@ -113,11 +114,17 @@ export class MetadataVersioned extends Struct {
return this.#getVersion(13, toV13);
}
/**
* @description Returns the wrapped values as a V14 object
*/
public get asV14 (): MetadataV14 {
return this.#getVersion(14, toV14);
}
/**
* @description Returns the wrapped values as a latest version object
*/
public get asLatest (): MetadataLatest {
// This is non-existent & latest - applied here to do the module-specific type conversions
return this.#getVersion('latest', toLatest);
}
@@ -17,14 +17,14 @@ function init (meta: string): [Constants, TypeRegistry] {
registry.setMetadata(metadata);
return [decorateConstants(registry, metadata.asLatest, 12), registry];
return [decorateConstants(registry, metadata.asLatest, metadata.version), registry];
}
describe('decorateConstants', (): void => {
it('should return constants with the correct type and value', (): void => {
const [consts, registry] = init(rpcMetadata);
const [consts] = init(rpcMetadata);
expect(consts.democracy.cooloffPeriod).toBeInstanceOf(registry.createClass('BlockNumber'));
expect((consts.democracy.cooloffPeriod as unknown as BlockNumber).bitLength()).toBe(32);
// 3 second blocks, 28 days
expect((consts.democracy.cooloffPeriod as unknown as BlockNumber).toNumber()).toEqual(28 * 24 * 60 * (60 / 3));
});
@@ -9,17 +9,15 @@ import { hexToU8a, stringCamelCase } from '@polkadot/util';
/** @internal */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function decorateConstants (registry: Registry, { modules }: MetadataLatest, _metaVersion: number): Constants {
return modules.reduce((result: Constants, { constants, name }): Constants => {
export function decorateConstants (registry: Registry, { pallets }: MetadataLatest, _metaVersion: number): Constants {
return pallets.reduce((result: Constants, { constants, name }): Constants => {
if (constants.isEmpty) {
return result;
}
// For access, we change the index names, i.e. Democracy.EnactmentPeriod -> democracy.enactmentPeriod
result[stringCamelCase(name)] = constants.reduce((newModule: ModuleConstants, meta): ModuleConstants => {
// convert to the natural type as received
const type = meta.type.toString();
const codec = registry.createType(type as 'Raw', hexToU8a(meta.value.toHex())) as unknown;
const codec = registry.createTypeUnsafe(registry.createLookupType(meta.type), [hexToU8a(meta.value.toHex())]) as unknown;
(codec as Record<string, unknown>).meta = meta;
newModule[stringCamelCase(meta.name)] = codec as ConstantCodec;
@@ -1,20 +1,34 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { DispatchErrorModule, MetadataLatest } from '../../../interfaces';
import type { DispatchErrorModule, MetadataLatest, PortableRegistry, SiField, SiVariant } from '../../../interfaces';
import type { Text, u8 } from '../../../primitive';
import type { Registry } from '../../../types';
import type { Errors, ModuleErrors } from '../types';
import { stringCamelCase } from '@polkadot/util';
function isError ({ error, index }: DispatchErrorModule, sectionIndex: number, errorIndex: number): boolean {
return index.eq(sectionIndex) && error.eq(errorIndex);
interface ItemMeta {
args: string[];
name: Text;
fields: SiField[];
index: u8;
docs: Text[];
}
export function variantToMeta (lookup: PortableRegistry, variant: SiVariant): ItemMeta {
return {
...variant,
args: variant.fields.map(({ type }) =>
lookup.getTypeDef(type).type
)
};
}
/** @internal */
export function decorateErrors (_: Registry, { modules }: MetadataLatest, metaVersion: number): Errors {
return modules.reduce((result: Errors, { errors, index, name }, _sectionIndex): Errors => {
if (!errors.length) {
export function decorateErrors (registry: Registry, { lookup, pallets }: MetadataLatest, metaVersion: number): Errors {
return pallets.reduce((result: Errors, { errors, index, name }, _sectionIndex): Errors => {
if (!errors.isSome) {
return result;
}
@@ -22,12 +36,13 @@ export function decorateErrors (_: Registry, { modules }: MetadataLatest, metaVe
? index.toNumber()
: _sectionIndex;
result[stringCamelCase(name)] = errors.reduce((newModule: ModuleErrors, meta, errorIndex): ModuleErrors => {
result[stringCamelCase(name)] = lookup.getSiType(errors.unwrap().type).def.asVariant.variants.reduce((newModule: ModuleErrors, variant): ModuleErrors => {
// we don't camelCase the error name
newModule[meta.name.toString()] = {
is: (moduleError: DispatchErrorModule): boolean =>
isError(moduleError, sectionIndex, errorIndex),
meta
newModule[variant.name.toString()] = {
is: ({ error, index }: DispatchErrorModule) =>
index.eq(sectionIndex) &&
error.eq(variant.index),
meta: registry.createType('ErrorMetadataLatest', variantToMeta(lookup, variant))
};
return newModule;
@@ -7,25 +7,24 @@ import type { Events, ModuleEvents } from '../types';
import { stringCamelCase } from '@polkadot/util';
function isEvent <T extends AnyTuple> (event: IEvent<AnyTuple>, sectionIndex: number, eventIndex: number): event is IEvent<T> {
return event.index[0] === sectionIndex && event.index[1] === eventIndex;
}
import { variantToMeta } from '../errors';
/** @internal */
export function decorateEvents (_: Registry, { modules }: MetadataLatest, metaVersion: number): Events {
return modules
export function decorateEvents (registry: Registry, { lookup, pallets }: MetadataLatest, metaVersion: number): Events {
return pallets
.filter(({ events }) => events.isSome)
.reduce((result: Events, { events, index, name }, _sectionIndex): Events => {
const sectionIndex = metaVersion >= 12
? index.toNumber()
: _sectionIndex;
result[stringCamelCase(name)] = events.unwrap().reduce((newModule: ModuleEvents, meta, eventIndex): ModuleEvents => {
result[stringCamelCase(name)] = lookup.getSiType(events.unwrap().type).def.asVariant.variants.reduce((newModule: ModuleEvents, variant): ModuleEvents => {
// we don't camelCase the event name
newModule[meta.name.toString()] = {
newModule[variant.name.toString()] = {
is: <T extends AnyTuple> (eventRecord: IEvent<AnyTuple>): eventRecord is IEvent<T> =>
isEvent(eventRecord, sectionIndex, eventIndex),
meta
eventRecord.index[0] === sectionIndex &&
variant.index.eq(eventRecord.index[1]),
meta: registry.createType('EventMetadataLatest', variantToMeta(lookup, variant))
};
return newModule;
@@ -12,11 +12,11 @@ function isTx <A extends AnyTuple> (tx: IMethod<AnyTuple>, callIndex: Uint8Array
/** @internal */
export function createUnchecked (registry: Registry, section: string, callIndex: Uint8Array, callMetadata: FunctionMetadataLatest): CallFunction {
const expectedArgs = callMetadata.args;
const expectedArgs = callMetadata.fields;
const funcName = stringCamelCase(callMetadata.name);
const extrinsicFn = (...args: any[]): Call => {
assert(expectedArgs.length === args.length, () => `Extrinsic ${section}.${funcName} expects ${expectedArgs.length.valueOf()} arguments, got ${args.length}.`);
assert(expectedArgs.length === args.length, () => `Extrinsic ${section}.${funcName} expects ${expectedArgs.length} arguments, got ${args.length}.`);
return registry.createType('Call', {
args,
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import { createTestPairs } from '@polkadot/keyring/testingPairs';
import metadataStatic from '@polkadot/types-support/metadata/static-substrate';
import metadataStatic from '@polkadot/types-support/metadata/v13/substrate-hex';
import { BN } from '@polkadot/util';
import { TypeRegistry } from '../../../create';
@@ -10,20 +10,29 @@ import { stringCamelCase } from '@polkadot/util';
import { createUnchecked } from './createUnchecked';
/** @internal */
export function decorateExtrinsics (registry: Registry, { modules }: MetadataLatest, metaVersion: number): Extrinsics {
return modules
export function decorateExtrinsics (registry: Registry, { lookup, pallets }: MetadataLatest, metaVersion: number): Extrinsics {
return pallets
.filter(({ calls }) => calls.isSome)
.reduce((result: Extrinsics, { calls, index, name }, _sectionIndex): Extrinsics => {
const sectionName = stringCamelCase(name);
const sectionIndex = metaVersion >= 12
? index.toNumber()
: _sectionIndex;
const section = stringCamelCase(name);
result[section] = calls.unwrap().reduce((newModule: ModuleExtrinsics, callMetadata, methodIndex): ModuleExtrinsics => {
newModule[stringCamelCase(callMetadata.name)] = createUnchecked(registry, section, new Uint8Array([sectionIndex, methodIndex]), callMetadata);
result[sectionName] = lookup.getSiType(calls.unwrap().type).def.asVariant.variants
.reduce((newModule: ModuleExtrinsics, variant): ModuleExtrinsics => {
const callMetadata = registry.createType('FunctionMetadataLatest', {
...variant,
args: variant.fields.map(({ name, type }, index) => ({
name: stringCamelCase(name.unwrapOr(`param${index}`)),
type: lookup.getTypeDef(type).type
}))
});
return newModule;
}, {});
newModule[stringCamelCase(callMetadata.name)] = createUnchecked(registry, sectionName, new Uint8Array([sectionIndex, callMetadata.index.toNumber()]), callMetadata);
return newModule;
}, {});
return result;
}, {});
@@ -5,6 +5,7 @@ import json from '@polkadot/types-support/metadata/static-substrate';
import { u8aToHex } from '@polkadot/util';
import { TypeRegistry } from '../../create';
import { u32 } from '../../primitive';
import { Metadata } from '../Metadata';
import { decorateConstants, decorateExtrinsics, decorateStorage } from './';
@@ -48,7 +49,7 @@ describe('Decorated', () => {
it('should return constants with the correct type and value', (): void => {
const consts = decorateConstants(registry, metadata.asLatest, metadata.version);
expect(consts.democracy.cooloffPeriod).toBeInstanceOf(registry.createClass('BlockNumber'));
expect(consts.democracy.cooloffPeriod).toBeInstanceOf(u32); // BlockNumber
expect(consts.democracy.cooloffPeriod.toHex()).toEqual('0x000c4e00');
});
});
@@ -4,25 +4,105 @@
import { u8aToHex } from '@polkadot/util';
import { TypeRegistry } from '../../../create';
import { Text } from '../../../primitive';
import { Metadata } from '../../Metadata';
import { createFunction } from './createFunction';
describe('createFunction', (): void => {
const registry = new TypeRegistry();
const metadata = new Metadata(registry, {
magicNumber: 1635018093,
metadata: {
v14: {
lookup: {
types: [
{
id: 0,
type: {
def: { HistoricMetaCompat: 'AccountId' }
}
},
{
id: 1,
type: {
def: { HistoricMetaCompat: 'Bytes' }
}
},
{
id: 2,
type: {
def: { HistoricMetaCompat: 'SessionKey5' }
}
},
{
id: 3,
type: {
def: { Tuple: [1, 0] }
}
},
{
id: 4,
type: {
def: { Tuple: [1, 0, 0] }
}
}
]
}
}
}
});
it('allows creating of known DoubleMap keys (with Bytes)', (): void => {
registry.setMetadata(metadata);
it('allows creating a known 1 Map key', (): void => {
const storageFn = createFunction(registry, {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
meta: {
type: {
asDoubleMap: {
hasher: registry.createType('StorageHasher', 'Twox64Concat'),
key1: new Text(registry, 'Bytes'),
key2: new Text(registry, 'AccountId'),
key2Hasher: registry.createType('StorageHasher', 'Blake2_256'),
value: new Text(registry, 'SessionKeys5')
asMap: {
hashers: [
registry.createType('StorageHasher', 'Blake2_128Concat')
],
key: 0,
value: 4
},
isDoubleMap: true
isMap: true
}
} as any,
method: 'Account',
prefix: 'System',
section: 'system'
}, {});
expect(
u8aToHex(
storageFn(
'DB2mp5nNhbFN86J9hxoAog8JALMhDXgwvWMxrRMLNUFMEY4'
)
)
).toEqual(
'0x' +
'4101' +
'26aa394eea5630e07c48ae0c9558cef7' + // twox 128
'b99d880ec681799c0cf30e8886371da9' + // twox 128
'79c598d130209ab0dea15637a5b16be7' + // blake 128
'1a7938fede32e1275281b3eee5708706d88444a6dc898a4dec463f1eb298463f' // AccountId
);
});
it('allows creating of known 2 Map keys (with Bytes)', (): void => {
const storageFn = createFunction(registry, {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
meta: {
type: {
asMap: {
hashers: [
registry.createType('StorageHasher', 'Twox64Concat'),
registry.createType('StorageHasher', 'Blake2_256')
],
key: 3,
value: 4
},
isMap: true
}
} as any,
method: 'NextKeys',
@@ -32,12 +112,12 @@ describe('createFunction', (): void => {
expect(
u8aToHex(
storageFn([
storageFn(
// hex, without length prefix
'0x3a73657373696f6e3a6b657973',
// address
'DB2mp5nNhbFN86J9hxoAog8JALMhDXgwvWMxrRMLNUFMEY4'
])
)
)
).toEqual(
'0x' +
@@ -50,25 +130,21 @@ describe('createFunction', (): void => {
);
});
it('allows creating of NMap keys (with Bytes)', (): void => {
it('allows creating of 3 Map keys (with Bytes)', (): void => {
const storageFn = createFunction(registry, {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
meta: {
type: {
asNMap: {
asMap: {
hashers: [
registry.createType('StorageHasher', 'Twox64Concat'),
registry.createType('StorageHasher', 'Blake2_256'),
registry.createType('StorageHasher', 'Blake2_256')
],
keyVec: [
new Text(registry, 'Bytes'),
new Text(registry, 'AccountId'),
new Text(registry, 'AccountId')
],
value: new Text(registry, 'SessionKeys5')
key: 4,
value: 2
},
isNMap: true
isMap: true
}
} as any,
method: 'NextKeys',
@@ -78,13 +154,13 @@ describe('createFunction', (): void => {
expect(
u8aToHex(
storageFn([
storageFn(
// hex, without length prefix
'0x3a73657373696f6e3a6b657973',
// addresses
'DB2mp5nNhbFN86J9hxoAog8JALMhDXgwvWMxrRMLNUFMEY4',
'DB2mp5nNhbFN86J9hxoAog8JALMhDXgwvWMxrRMLNUFMEY4'
])
)
)
).toEqual(
'0x' +
@@ -1,16 +1,16 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { BN } from '@polkadot/util';
import type { StorageEntryMetadataLatest, StorageHasher } from '../../../interfaces/metadata';
import type { SiLookupTypeId } from '../../../interfaces/scaleInfo';
import type { StorageEntry } from '../../../primitive/types';
import type { Codec, Registry } from '../../../types';
import type { Registry } from '../../../types';
import { assert, compactAddLength, compactStripLength, isUndefined, stringCamelCase, stringLowerFirst, u8aConcat, u8aToU8a } from '@polkadot/util';
import { xxhashAsU8a } from '@polkadot/util-crypto';
import { Raw } from '../../../codec';
import { StorageKey, Type } from '../../../primitive';
import { StorageKey } from '../../../primitive';
import { getHasher } from './getHasher';
export interface CreateItemOptions {
@@ -30,26 +30,24 @@ interface IterFn {
meta: StorageEntryMetadataLatest;
}
type Arg = boolean | string | number | null | BN | bigint | Uint8Array | Codec;
/** @internal */
function createKeyRaw (registry: Registry, itemFn: CreateItemFn, keys: Type[], hashers: StorageHasher[], args: Arg[]): Uint8Array {
function createKeyRaw (registry: Registry, itemFn: CreateItemFn, keys: SiLookupTypeId[], hashers: StorageHasher[], args: unknown[]): Uint8Array {
return u8aConcat(
xxhashAsU8a(itemFn.prefix, 128),
xxhashAsU8a(itemFn.method, 128),
...keys.map((type, index) =>
getHasher(hashers[index])(
registry.createType(type.toString() as 'Raw', args[index]).toU8a()
registry.createType(registry.createLookupType(type), args[index]).toU8a()
)
)
);
}
/** @internal */
function createKey (registry: Registry, itemFn: CreateItemFn, keys: Type[], hashers: StorageHasher[], args: Arg[]): Uint8Array {
function createKey (registry: Registry, itemFn: CreateItemFn, keys: SiLookupTypeId[], hashers: StorageHasher[], args: unknown[]): Uint8Array {
const { method, section } = itemFn;
assert(Array.isArray(args), () => `Call to ${stringCamelCase(section || 'unknown')}.${stringCamelCase(method || 'unknown')} needs ${keys.length} arguments, provided in tuple format`);
assert(Array.isArray(args), () => `Call to ${stringCamelCase(section || 'unknown')}.${stringCamelCase(method || 'unknown')} needs ${keys.length} arguments`);
assert(args.filter((a) => !isUndefined(a)).length === keys.length, () => `Call to ${stringCamelCase(section || 'unknown')}.${stringCamelCase(method || 'unknown')} needs ${keys.length} arguments, found [${args.join(', ')}]`);
// as per createKey, always add the length prefix (underlying it is Bytes)
@@ -59,7 +57,7 @@ function createKey (registry: Registry, itemFn: CreateItemFn, keys: Type[], hash
}
/** @internal */
function expandWithMeta ({ meta, method, prefix, section }: CreateItemFn, _storageFn: (arg?: Arg | Arg[]) => Uint8Array): StorageEntry {
function expandWithMeta ({ meta, method, prefix, section }: CreateItemFn, _storageFn: (...args: unknown[]) => Uint8Array): StorageEntry {
const storageFn = _storageFn as StorageEntry;
storageFn.meta = meta;
@@ -79,11 +77,7 @@ function expandWithMeta ({ meta, method, prefix, section }: CreateItemFn, _stora
/** @internal */
function extendHeadMeta (registry: Registry, { meta: { docs, name, type }, section }: CreateItemFn, { method }: StorageEntry, iterFn: (...args: unknown[]) => Raw): (...args: unknown[]) => StorageKey {
const outputType = type.isMap
? type.asMap.key
: type.isDoubleMap
? type.asDoubleMap.key1
: type.asNMap.keyVec[0];
const outputType = registry.createLookupType(type.asMap.key);
// metadata with a fallback value using the type of the key, the normal
// meta fallback only applies to actual entry values, create one for head
@@ -92,7 +86,8 @@ function extendHeadMeta (registry: Registry, { meta: { docs, name, type }, secti
fallback: registry.createType('Bytes'),
modifier: registry.createType('StorageEntryModifierLatest', 1), // required
name,
type: registry.createType('StorageEntryTypeLatest', registry.createType('Type', outputType), 0)
// FIXME???
type: registry.createType('StorageEntryTypeLatest', outputType, 0)
});
return (...args: unknown[]) =>
@@ -107,24 +102,20 @@ function extendPrefixedMap (registry: Registry, itemFn: CreateItemFn, storageFn:
assert(
(
(args.length === 0) ||
(type.isDoubleMap && args.length === 1) ||
(type.isNMap && args.length < (type.asNMap.hashers.length))
(type.isMap && args.length < type.asMap.hashers.length)
),
() => `Iteration ${stringCamelCase(section || 'unknown')}.${stringCamelCase(method || 'unknown')} needs arguments to be at least one less than the full arguments, found [${args.join(', ')}]`
);
if (args.length) {
if (type.isDoubleMap) {
return new Raw(registry, createKeyRaw(registry, itemFn, [type.asDoubleMap.key1], [type.asDoubleMap.hasher], args as Arg[]));
} else if (type.isNMap) {
let keys = [...type.asNMap.keyVec];
let hashers = [...type.asNMap.hashers];
if (type.isMap) {
const { hashers, key } = type.asMap;
const keysVec = hashers.length === 1
? [key]
: [...registry.lookup.getSiType(key).def.asTuple.map((t) => t)];
const hashersVec = [...hashers];
// pick the first n entries where n = args.length which is already verified above to be less that the full arguments.
keys = keys.slice(0, args.length);
hashers = hashers.slice(0, args.length);
return new Raw(registry, createKeyRaw(registry, itemFn, keys, hashers, args as Arg[]));
return new Raw(registry, createKeyRaw(registry, itemFn, keysVec.slice(0, args.length), hashersVec.slice(0, args.length), args));
}
}
@@ -142,19 +133,21 @@ export function createFunction (registry: Registry, itemFn: CreateItemFn, option
// - storage.system.account(address)
// - storage.timestamp.blockPeriod()
// For higher-map queries the params are passed in as an tuple, [key1, key2]
const storageFn = expandWithMeta(itemFn, (arg?: Arg | Arg[]) =>
type.isPlain
? options.skipHashing
const storageFn = expandWithMeta(itemFn, (...args: unknown[]): Uint8Array => {
if (type.isPlain) {
return options.skipHashing
? compactAddLength(u8aToU8a(options.key))
: createKey(registry, itemFn, [], [], [])
: type.isMap
? createKey(registry, itemFn, [type.asMap.key], [type.asMap.hasher], [arg as Arg])
: type.isDoubleMap
? createKey(registry, itemFn, [type.asDoubleMap.key1, type.asDoubleMap.key2], [type.asDoubleMap.hasher, type.asDoubleMap.key2Hasher], arg as Arg[])
: createKey(registry, itemFn, type.asNMap.keyVec, type.asNMap.hashers, arg as Arg[])
);
: createKey(registry, itemFn, [], [], []);
}
if (type.isMap || type.isDoubleMap || type.isNMap) {
const { hashers, key } = type.asMap;
return hashers.length === 1
? createKey(registry, itemFn, [key], hashers, args)
: createKey(registry, itemFn, registry.lookup.getSiType(key).def.asTuple.map((t) => t), hashers, args);
});
if (type.isMap) {
extendPrefixedMap(registry, itemFn, storageFn);
}
@@ -28,7 +28,7 @@ describe('decorateStorage', (): void => {
});
it('should throw if the storage function expects tuple arguments', (): void => {
expect(() => query.staking.erasStakers(1)).toThrowError('Call to staking.erasStakers needs 2 arguments, provided in tuple format');
expect(() => query.staking.erasStakers(1)).toThrowError('Call to staking.erasStakers needs 2 arguments');
});
it('should return a value if the storage function does not expect an argument', (): void => {
@@ -12,8 +12,8 @@ import { getStorage } from './getStorage';
/** @internal */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function decorateStorage (registry: Registry, { modules }: MetadataLatest, _metaVersion: number): Storage {
return modules.reduce((result: Storage, moduleMetadata): Storage => {
export function decorateStorage (registry: Registry, { pallets }: MetadataLatest, _metaVersion: number): Storage {
return pallets.reduce((result: Storage, moduleMetadata): Storage => {
if (moduleMetadata.storage.isNone) {
return result;
}
@@ -1,12 +1,12 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { DispatchErrorModule, ErrorMetadataLatest, EventMetadataLatest, ModuleConstantMetadataLatest } from '../../interfaces';
import type { DispatchErrorModule, ErrorMetadataLatest, EventMetadataLatest, PalletConstantMetadataLatest } from '../../interfaces';
import type { StorageEntry } from '../../primitive/types';
import type { AnyTuple, CallFunction, Codec, IEvent } from '../../types';
export interface ConstantCodec extends Codec {
readonly meta: ModuleConstantMetadataLatest;
readonly meta: PalletConstantMetadataLatest;
}
export interface IsError {
+1 -1
View File
@@ -5,5 +5,5 @@ import type { Vec } from '../codec';
import type { Codec } from '../types';
export interface MetadataInterface<Modules extends Codec> extends Codec {
modules: Vec<Modules>;
pallets: Vec<Modules>;
}
@@ -26,13 +26,16 @@ export function extractTypes (types: string[]): Extracted[] {
return extractTypes([(decoded.sub as TypeDef).type]);
case TypeDefInfo.BTreeMap:
case TypeDefInfo.Enum:
case TypeDefInfo.HashMap:
case TypeDefInfo.Result:
case TypeDefInfo.Set:
case TypeDefInfo.Struct:
case TypeDefInfo.Tuple:
return extractTypes((decoded.sub as TypeDef[]).map(({ type }) => type));
default:
throw new Error(`Unhandled: Unable to create and validate type from ${type}`);
throw new Error(`Unhandled: Unable to create and validate type from ${type} (info=${decoded.info})`);
}
});
}
+41 -120
View File
@@ -1,145 +1,66 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Option, Vec } from '../../codec';
import type { Text, Type } from '../../primitive';
import type { Codec, Registry } from '../../types';
import type { MetadataLatest, PortableRegistry, SiLookupTypeId } from '../../interfaces';
import type { Registry } from '../../types';
import { flattenUniq } from './flattenUniq';
import { validateTypes } from './validateTypes';
type Arg = { type: Type } & Codec;
type Item = {
type: {
isDoubleMap: boolean;
isMap: boolean;
isNMap: boolean;
isPlain: boolean;
asDoubleMap: {
key1: Text;
key2: Text;
value: Text;
};
asMap: {
key: Text;
value: Text;
};
asNMap: {
keyVec: Text[];
value: Text;
},
asPlain: Text;
};
} & Codec;
type Storage = Option<{ items: Vec<Item> } & Codec>;
type Call = { args: Vec<Arg> } & Codec;
type Calls = Option<Vec<Call>>;
type Event = { args: Vec<Type> } & Codec;
type Events = Option<Vec<Event>>;
type Module = {
// V1+
calls?: Calls;
// V6+
constants?: Vec<{ type: Text } & Codec>;
events?: Events;
storage?: Storage;
} & Codec;
interface ExtractionMetadata {
modules: Vec<Module>;
}
/** @internal */
function unwrapCalls (mod: Module): Call[] {
return mod.calls
? mod.calls.unwrapOr([])
: [];
}
/** @internal */
function typeToString ({ type }: Arg): string {
return type.toString();
}
/** @internal */
function getCallNames ({ modules }: ExtractionMetadata): string[][][] {
return modules.map((mod): string[][] =>
unwrapCalls(mod).map(({ args }): string[] =>
args.map(typeToString)
)
function extractTypes (lookup: PortableRegistry, types: { type: SiLookupTypeId }[]): string[] {
return types.map(({ type }) =>
lookup.getTypeDef(type).type
);
}
/** @internal */
function getConstantNames ({ modules }: ExtractionMetadata): string[][] {
return modules.map(({ constants }): string[] =>
(constants || []).map(typeToString)
function extractFieldTypes (lookup: PortableRegistry, type: SiLookupTypeId): string[][] {
return lookup.getSiType(type).def.asVariant.variants.map(({ fields }) =>
extractTypes(lookup, fields)
);
}
/** @internal */
function unwrapEvents (events?: Events): Event[] {
return events
? events.unwrapOr([])
: [];
}
function getPalletNames ({ lookup, pallets }: MetadataLatest): string[][][] {
return pallets.reduce<string[][][]>((all, { calls, constants, events, storage }) => {
all.push([extractTypes(lookup, constants)]);
/** @internal */
function getEventNames ({ modules }: ExtractionMetadata): string[][][] {
return modules.map(({ events }): string[][] =>
unwrapEvents(events).map(({ args }: Event): string[] =>
args.map((a) => a.toString())
)
);
}
if (calls.isSome) {
all.push(extractFieldTypes(lookup, calls.unwrap().type));
}
/** @internal */
function unwrapStorage (storage?: Storage): Item[] {
return storage
? storage.unwrapOr({ items: [] }).items
: [];
}
if (events.isSome) {
all.push(extractFieldTypes(lookup, events.unwrap().type));
}
/** @internal */
function getStorageNames ({ modules }: ExtractionMetadata): string[][][] {
return modules.map(({ storage }): string[][] =>
unwrapStorage(storage).map(({ type }) =>
type.isPlain
? [
type.asPlain.toString()
]
: type.isMap
if (storage.isSome) {
all.push(storage.unwrap().items.map(({ type }): string[] => {
if (type.isPlain) {
return [lookup.getTypeDef(type.asPlain).type];
}
const { hashers, key, value } = type.asMap;
return hashers.length === 1
? [
type.asMap.value.toString(),
type.asMap.key.toString()
lookup.getTypeDef(value).type,
lookup.getTypeDef(key).type
]
: type.isDoubleMap
? [
type.asDoubleMap.value.toString(),
type.asDoubleMap.key1.toString(),
type.asDoubleMap.key2.toString()
]
: [
type.asNMap.value.toString(),
...type.asNMap.keyVec.map((k) => k.toString())
]
)
);
: [
lookup.getTypeDef(value).type,
...lookup.getSiType(key).def.asTuple.map((t) =>
lookup.getTypeDef(t).type
)
];
}));
}
return all;
}, []);
}
/** @internal */
export function getUniqTypes (registry: Registry, meta: ExtractionMetadata, throwError: boolean): string[] {
return validateTypes(registry, throwError, flattenUniq([
getCallNames(meta),
getConstantNames(meta),
getEventNames(meta),
getStorageNames(meta)
]));
export function getUniqTypes (registry: Registry, meta: MetadataLatest, throwError: boolean): string[] {
return validateTypes(registry, throwError, flattenUniq(getPalletNames(meta)));
}
+58 -30
View File
@@ -1,63 +1,84 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Codec, Registry } from '../../types';
import type { MetadataInterface } from '../types';
import type { Registry } from '../../types';
import type { Check } from './types';
import fs from 'fs';
import path from 'path';
import { assert, hexToU8a, stringify, u8aToHex } from '@polkadot/util';
import { assert, hexToU8a, stringCamelCase, stringify, u8aToHex } from '@polkadot/util';
import { TypeRegistry } from '../../create';
import { unwrapStorageType } from '../../primitive/StorageKey';
import { unwrapStorageSi, unwrapStorageType } from '../../primitive/StorageKey';
import { Metadata } from '../Metadata';
import { getUniqTypes } from './getUniqTypes';
/** @internal */
export function decodeLatestMeta<Modules extends Codec> (registry: Registry, type: string, version: number, { compare, data }: Check): void {
it('decodes metadata properly', (): void => {
const metadata = new Metadata(registry, data);
function writeJson (json: unknown, version: number, type: string, sub: 'json' | 'types'): void {
fs.writeFileSync(
path.join(process.cwd(), `packages/types-support/src/metadata/v${version}/${type}-${sub}.json`),
stringify(json, 2),
{ flag: 'w' }
);
}
registry.setMetadata(metadata);
/** @internal */
export function decodeLatestMeta (registry: Registry, type: string, version: number, { compare, data, types }: Check): void {
const metadata = new Metadata(registry, data);
registry.setMetadata(metadata);
it('decodes latest substrate properly', (): void => {
const json = metadata.toJSON() as Record<string, Record<string, Record<string, string>>>;
delete json.metadata[`v${metadata.version}`].lookup;
expect(metadata.version).toBe(version);
expect((metadata[`asV${version}` as keyof Metadata] as unknown as MetadataInterface<Modules>).modules.length).not.toBe(0);
try {
expect(metadata.toJSON()).toEqual(compare);
expect(json).toEqual(compare);
} catch (error) {
if (process.env.GITHUB_REPOSITORY) {
console.error(stringify(metadata.toJSON()));
console.error(stringify(json));
throw error;
}
fs.writeFileSync(
path.join(process.cwd(), `packages/types-support/src/metadata/v${version}/${type}-json.json`),
stringify(metadata.toJSON(), 2),
{ flag: 'w' }
);
writeJson(json, version, type, 'json');
}
});
it('decodes latest types correctly', (): void => {
if (types) {
const json = metadata.asLatest.lookup.types.toJSON();
try {
expect(json).toEqual(types);
} catch (error) {
if (process.env.GITHUB_REPOSITORY) {
console.error(stringify(metadata.toJSON()));
throw error;
}
writeJson(json, version, type, 'types');
}
}
});
}
/** @internal */
export function toLatest<Modules extends Codec> (registry: Registry, version: number, { data }: Check, withThrow = true): void {
export function toLatest (registry: Registry, version: number, { data }: Check, withThrow = true): void {
it(`converts v${version} to latest`, (): void => {
const metadata = new Metadata(registry, data);
registry.setMetadata(metadata);
const metadataInit = metadata[`asV${version}` as keyof Metadata];
const metadataLatest = metadata.asLatest;
const latest = metadata.asLatest;
expect(
getUniqTypes(registry, metadataInit as unknown as MetadataInterface<Modules>, withThrow)
).toEqual(
getUniqTypes(registry, metadataLatest, withThrow)
);
if (metadata.version < 14) {
getUniqTypes(registry, latest, withThrow);
}
});
}
@@ -65,19 +86,26 @@ export function toLatest<Modules extends Codec> (registry: Registry, version: nu
export function defaultValues (registry: Registry, { data, fails = [] }: Check, withThrow = true, withFallbackCheck = false): void {
describe('storage with default values', (): void => {
const metadata = new Metadata(registry, data);
const { pallets } = metadata.asLatest;
metadata.asLatest.modules.filter(({ storage }) => storage.isSome).forEach((m): void => {
m.storage.unwrap().items.forEach(({ fallback, modifier, name, type }): void => {
pallets.filter(({ storage }) => storage.isSome).forEach(({ name, storage }): void => {
const sectionName = stringCamelCase(name);
storage.unwrap().items.forEach(({ fallback, modifier, name, type }): void => {
const inner = unwrapStorageType(registry, type, modifier.isOptional);
const location = `${m.name.toString()}.${name.toString()}: ${inner}`;
const location = `${sectionName}.${stringCamelCase(name)}: ${inner}`;
it(location, (): void => {
expect((): void => {
try {
const type = registry.createType(inner, hexToU8a(fallback.toHex()));
const instance = registry.createTypeUnsafe(
registry.createLookupType(unwrapStorageSi(type)),
[hexToU8a(fallback.toHex())],
{ isOptional: modifier.isOptional }
);
if (withFallbackCheck) {
const [hexType, hexOrig] = [u8aToHex(type.toU8a()), u8aToHex(fallback.toU8a(true))];
const [hexType, hexOrig] = [u8aToHex(instance.toU8a()), u8aToHex(fallback.toU8a(true))];
assert(hexType === hexOrig, () => `Fallback does not match (${((hexOrig.length - 2) / 2) - ((hexType.length - 2) / 2)} bytes missing): ${hexType} !== ${hexOrig}`);
}
+20 -26
View File
@@ -1,50 +1,44 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { FunctionMetadataLatest, MetadataLatest } from '../../interfaces/metadata';
import type { MetadataLatest, PalletCallMetadataLatest } from '../../interfaces/metadata';
import type { AnyJson, Registry } from '../../types';
import { Option, Vec } from '../../codec';
import { Option } from '../../codec';
import { Text, u8 } from '../../primitive';
interface ModuleMetadataTrimmed {
calls: Option<Vec<FunctionMetadataLatest>>;
calls: Option<PalletCallMetadataLatest>;
index: u8;
name: Text;
}
function trimDocs (docs: Vec<Text>): string[] {
const strings = docs.map((doc) => doc.toString().trim());
const firstEmpty = strings.findIndex((doc) => !doc.length);
function trimDocs (docs: Text[]): string[] {
const strings = docs.map((d) => d.toString().trim());
const firstEmpty = strings.findIndex((d) => !d.length);
return firstEmpty === -1
? strings
: strings.slice(0, firstEmpty);
}
function mapCalls (registry: Registry, _calls: Option<Vec<FunctionMetadataLatest>>): Option<Vec<FunctionMetadataLatest>> {
const calls = _calls.unwrapOr(null);
return registry.createType(
'Option<Vec<FunctionMetadataLatest>>',
calls
? calls.map(({ args, docs, name }) =>
registry.createType('FunctionMetadataLatest', {
args,
docs: trimDocs(docs),
name
})
)
: null
);
}
/** @internal */
export function toCallsOnly (registry: Registry, { extrinsic, modules }: MetadataLatest): AnyJson {
export function toCallsOnly (registry: Registry, { extrinsic, lookup, pallets }: MetadataLatest): AnyJson {
return registry.createType('MetadataLatest', {
extrinsic,
modules: modules.map(({ calls, index, name }): ModuleMetadataTrimmed => ({
calls: mapCalls(registry, calls),
lookup: {
types: lookup.types.map(({ id, type }) =>
registry.createType('PortableType', {
id,
type: {
...type,
docs: trimDocs(type.docs)
}
})
)
},
pallets: pallets.map(({ calls, index, name }): ModuleMetadataTrimmed => ({
calls: registry.createType('Option<PalletCallMetadataLatest>', calls.unwrapOr(null)),
index,
name
}))
-154
View File
@@ -1,154 +0,0 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { EventMetadataLatest, EventMetadataV13, FunctionMetadataLatest, FunctionMetadataV13, MetadataLatest, MetadataV13, ModuleConstantMetadataLatest, ModuleConstantMetadataV13, ModuleMetadataLatest, ModuleMetadataV13, StorageEntryMetadataLatest, StorageMetadataLatest, StorageMetadataV13 } from '../../interfaces/metadata';
import type { OverrideModuleType, Registry } from '../../types';
import { getModuleTypes, knownOrigins } from '@polkadot/types-known';
import { stringCamelCase } from '@polkadot/util';
import { Type } from '../../primitive';
const BOXES = [['<', '>'], ['<', ','], [',', '>'], ['(', ')'], ['(', ','], [',', ','], [',', ')']];
/**
* Find and apply the correct type override
* @internal
**/
function setTypeOverride (sectionTypes: OverrideModuleType, types: Type[]): void {
types.forEach((type): void => {
const override = Object.keys(sectionTypes).find((aliased) => type.eq(aliased));
if (override) {
type.setOverride(sectionTypes[override]);
} else {
// FIXME: NOT happy with this approach, but gets over the initial hump cased by (Vec<Announcement>,BalanceOf)
const orig = type.toString();
const alias = Object
.entries(sectionTypes)
.reduce((result: string, [from, to]) =>
BOXES.reduce((result, [one, two]) =>
result.replace(`${one}${from}${two}`, `${one}${to}${two}`), result), orig);
if (orig !== alias) {
type.setOverride(alias);
}
}
});
}
/**
* Apply module-specific type overrides (always be done as part of toLatest)
* @internal
**/
function convertCalls (registry: Registry, calls: FunctionMetadataV13[], sectionTypes: OverrideModuleType): FunctionMetadataLatest[] {
return calls.map((c): FunctionMetadataLatest => {
setTypeOverride(sectionTypes, c.args.map(({ type }) => type));
return registry.createType('FunctionMetadataLatest', c);
});
}
/**
* Apply module-specific type overrides (always be done as part of toLatest)
* @internal
*/
function convertConstants (registry: Registry, constants: ModuleConstantMetadataV13[], sectionTypes: OverrideModuleType): ModuleConstantMetadataLatest[] {
return constants.map((c): ModuleConstantMetadataLatest => {
setTypeOverride(sectionTypes, [c.type]);
return registry.createType('ModuleConstantMetadataLatest', c);
});
}
/**
* Apply module-specific type overrides (always be done as part of toLatest)
* @internal
**/
function convertEvents (registry: Registry, events: EventMetadataV13[], sectionTypes: OverrideModuleType): EventMetadataLatest[] {
return events.map((e): EventMetadataLatest => {
setTypeOverride(sectionTypes, e.args.map((type) => type));
return registry.createType('EventMetadataLatest', e);
});
}
/**
* Apply module-specific storage type overrides (always part of toLatest)
* @internal
**/
function convertStorage (registry: Registry, { items, prefix }: StorageMetadataV13, sectionTypes: OverrideModuleType): StorageMetadataLatest {
return registry.createType('StorageMetadataLatest', {
items: items.map((s): StorageEntryMetadataLatest => {
setTypeOverride(sectionTypes,
s.type.isPlain
? [s.type.asPlain]
: s.type.isMap
? [s.type.asMap.value, s.type.asMap.key]
: s.type.isDoubleMap
? [s.type.asDoubleMap.value, s.type.asDoubleMap.key1, s.type.asDoubleMap.key2]
: [s.type.asNMap.value, ...s.type.asNMap.keyVec]
);
return registry.createType('StorageEntryMetadataLatest', s);
}),
prefix
});
}
// generate & register the OriginCaller type
function registerOriginCaller (registry: Registry, modules: ModuleMetadataV13[], metaVersion: number): void {
registry.register({
OriginCaller: {
_enum: modules
.map((mod, index): [string, number] => [
mod.name.toString(),
metaVersion >= 12
? mod.index.toNumber()
: index
])
.sort((a, b) => a[1] - b[1])
.reduce((result: Record<string, string>, [name, index]): Record<string, string> => {
for (let i = Object.keys(result).length; i < index; i++) {
result[`Empty${i}`] = 'Null';
}
result[name] = knownOrigins[name] || 'Null';
return result;
}, {})
}
});
}
/** @internal */
function createModule (registry: Registry, mod: ModuleMetadataV13, { calls, constants, events, storage }: { calls: FunctionMetadataV13[] | null, constants: ModuleConstantMetadataV13[], events: EventMetadataV13[] | null, storage: StorageMetadataV13 | null }): ModuleMetadataLatest {
const sectionTypes = getModuleTypes(registry, stringCamelCase(mod.name));
return registry.createType('ModuleMetadataLatest', {
...mod,
calls: calls && convertCalls(registry, calls, sectionTypes),
constants: convertConstants(registry, constants, sectionTypes),
events: events && convertEvents(registry, events, sectionTypes),
storage: storage && convertStorage(registry, storage, sectionTypes)
});
}
/**
* Convert the Metadata (which is an alias) to latest - effectively this _always_ get applied to the top-level &
* most-recent metadata, since it allows us a chance to actually apply call and storage specific type aliasses
* @internal
**/
export function toLatest (registry: Registry, { extrinsic, modules }: MetadataV13, metaVersion: number): MetadataLatest {
registerOriginCaller(registry, modules, metaVersion);
return registry.createType('MetadataLatest', {
extrinsic,
modules: modules.map((mod) => createModule(registry, mod, {
calls: mod.calls.unwrapOr(null),
constants: mod.constants,
events: mod.events.unwrapOr(null),
storage: mod.storage.unwrapOr(null)
}))
});
}
+4 -6
View File
@@ -193,16 +193,14 @@ function convertEvents (registry: Registry, types: TypeSpec[], modName: Text, ev
}
function createMapEntry (registry: Registry, sectionTypes: OverrideModuleType, types: TypeSpec[], { hashers, keys, value }: MapDef): StorageEntryTypeV14 {
setTypeOverride(sectionTypes, [value, ...keys]);
setTypeOverride(sectionTypes, [value, ...(Array.isArray(keys) ? keys : [keys])]);
return registry.createType('StorageEntryTypeV14', {
Map: {
hashers,
key: types.push({
def: {
Tuple: keys.map((t) => compatType(types, t))
}
}) - 1,
key: hashers.length === 1
? compatType(types, keys[0])
: (types.push({ def: { Tuple: keys.map((t) => compatType(types, t)) } }) - 1),
value: compatType(types, value)
}
});
@@ -1,12 +1,6 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { MetadataAll } from '../../interfaces/metadata';
import type { Check } from '../util/types';
import fs from 'fs';
import path from 'path';
import kusamaData from '@polkadot/types-support/metadata/v14/kusama-hex';
import kusamaJson from '@polkadot/types-support/metadata/v14/kusama-json.json';
import kusamaTypes from '@polkadot/types-support/metadata/v14/kusama-types.json';
@@ -16,69 +10,8 @@ import polkadotTypes from '@polkadot/types-support/metadata/v14/polkadot-types.j
import substrateData from '@polkadot/types-support/metadata/v14/substrate-hex';
import substrateJson from '@polkadot/types-support/metadata/v14/substrate-json.json';
import substrateTypes from '@polkadot/types-support/metadata/v14/substrate-types.json';
import { stringify } from '@polkadot/util';
import { TypeRegistry } from '../../create';
import { Metadata } from '../Metadata';
function testMeta (version: number, matchers: Record<string, Check>): void {
describe(`MetadataV${version}`, (): void => {
describe.each(Object.keys(matchers))('%s', (type): void => {
const { compare, data, types } = matchers[type];
// FIXME This is to be replaced with the proper version (here as a stop-gap)
it('parses', (): void => {
const registry = new TypeRegistry();
const metadata = new Metadata(registry, data);
const all = metadata.get('metadata') as MetadataAll;
const v14 = all.asV14;
const jsonStruct = v14.toJSON();
const jsonTypes = v14.lookup.types.toJSON();
delete (jsonStruct as Record<string, unknown>).lookup;
const allJson = {
magicNumber: 1635018093,
metadata: {
v14: jsonStruct
}
};
try {
expect(allJson).toEqual(compare);
} catch (error) {
if (process.env.GITHUB_REPOSITORY) {
console.error(stringify(allJson));
throw error;
}
fs.writeFileSync(
path.join(process.cwd(), `packages/types-support/src/metadata/v${version}/${type}-json.json`),
stringify(allJson, 2),
{ flag: 'w' }
);
}
try {
expect(jsonTypes).toEqual(types);
} catch (error) {
if (process.env.GITHUB_REPOSITORY) {
console.error(stringify(jsonTypes));
throw error;
}
fs.writeFileSync(
path.join(process.cwd(), `packages/types-support/src/metadata/v${version}/${type}-types.json`),
stringify(jsonTypes, 2),
{ flag: 'w' }
);
}
});
});
});
}
import { testMeta } from '../util/testUtil';
testMeta(14, {
kusama: {
@@ -0,0 +1,14 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { MetadataLatest, MetadataV14 } from '../../interfaces/metadata';
import type { Registry } from '../../types';
/**
* Convert the Metadata (which is an alias) to latest
* @internal
**/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function toLatest (registry: Registry, v14: MetadataV14, _metaVersion: number): MetadataLatest {
return v14;
}
+26 -38
View File
@@ -3,7 +3,8 @@
import type { StorageEntryMetadataLatest, StorageEntryTypeLatest, StorageHasher } from '../interfaces/metadata';
import type { AllHashers } from '../interfaces/metadata/definitions';
import type { AnyJson, AnyTuple, AnyU8a, Codec, InterfaceTypes, IStorageKey, Registry } from '../types';
import type { SiLookupTypeId } from '../interfaces/scaleInfo';
import type { AnyJson, AnyTuple, Codec, InterfaceTypes, IStorageKey, Registry } from '../types';
import type { StorageEntry } from './types';
import { assert, isFunction, isString, isU8a } from '@polkadot/util';
@@ -21,6 +22,7 @@ interface StorageKeyExtra {
section: string;
}
// hasher type -> [initialHashLength, canDecodeKey]
const HASHER_MAP: Record<keyof typeof AllHashers, [number, boolean]> = {
// opaque
Blake2_128: [16, false], // eslint-disable-line camelcase
@@ -32,15 +34,15 @@ const HASHER_MAP: Record<keyof typeof AllHashers, [number, boolean]> = {
Twox64Concat: [8, true]
};
export function unwrapStorageSi (type: StorageEntryTypeLatest): SiLookupTypeId {
return type.isPlain
? type.asPlain
: type.asMap.value;
}
/** @internal */
export function unwrapStorageType (_: Registry, type: StorageEntryTypeLatest, isOptional?: boolean): keyof InterfaceTypes {
const outputType = type.isPlain
? type.asPlain.toString()
: type.isMap
? type.asMap.value.toString()
: type.isDoubleMap
? type.asDoubleMap.value.toString()
: type.asNMap.value.toString();
export function unwrapStorageType (registry: Registry, type: StorageEntryTypeLatest, isOptional?: boolean): keyof InterfaceTypes {
const outputType = registry.lookup.getTypeDef(unwrapStorageSi(type)).type;
return isOptional
? `Option<${outputType}>` as keyof InterfaceTypes
@@ -48,7 +50,7 @@ export function unwrapStorageType (_: Registry, type: StorageEntryTypeLatest, is
}
/** @internal */
function decodeStorageKey (value?: AnyU8a | StorageKey | StorageEntry | [StorageEntry, unknown]): Decoded {
function decodeStorageKey (value?: string | Uint8Array | StorageKey | StorageEntry | [StorageEntry, unknown[]?]): Decoded {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
if (value instanceof StorageKey) {
return {
@@ -66,12 +68,12 @@ function decodeStorageKey (value?: AnyU8a | StorageKey | StorageEntry | [Storage
section: value.section
};
} else if (Array.isArray(value)) {
const [fn, arg] = value;
const [fn, args = []] = value;
assert(isFunction(fn), 'Expected function input for key construction');
return {
key: fn(arg),
key: fn(...args),
method: fn.method,
section: fn.section
};
@@ -81,14 +83,14 @@ function decodeStorageKey (value?: AnyU8a | StorageKey | StorageEntry | [Storage
}
/** @internal */
function decodeHashers <A extends AnyTuple> (registry: Registry, value: Uint8Array, hashers: [StorageHasher, string][]): A {
function decodeHashers <A extends AnyTuple> (registry: Registry, value: Uint8Array, hashers: [StorageHasher, SiLookupTypeId][]): A {
// the storage entry is xxhashAsU8a(prefix, 128) + xxhashAsU8a(method, 128), 256 bits total
let offset = 32;
return hashers.reduce((result: Codec[], [hasher, type]): Codec[] => {
const [hashLen, canDecode] = HASHER_MAP[hasher.type as 'Identity'];
const decoded = canDecode
? registry.createType(type as 'Raw', value.subarray(offset + hashLen))
? registry.createType(registry.createLookupType(type) as 'Raw', value.subarray(offset + hashLen))
: registry.createType('Raw', value.subarray(offset, offset + hashLen));
offset += hashLen + (canDecode ? decoded.encodedLength : 0);
@@ -100,34 +102,20 @@ function decodeHashers <A extends AnyTuple> (registry: Registry, value: Uint8Arr
/** @internal */
function decodeArgsFromMeta <A extends AnyTuple> (registry: Registry, value: Uint8Array, meta?: StorageEntryMetadataLatest): A {
if (!meta || !(meta.type.isMap || meta.type.isDoubleMap || meta.type.isNMap)) {
if (!meta || !meta.type.isMap) {
return [] as unknown as A;
}
if (meta.type.isMap) {
const mapInfo = meta.type.asMap;
const { hashers, key } = meta.type.asMap;
const keys = hashers.length === 1
? [key]
: registry.lookup.getSiType(key).def.asTuple;
return decodeHashers(registry, value, [
[mapInfo.hasher, mapInfo.key.toString()]
]);
} else if (meta.type.isDoubleMap) {
const mapInfo = meta.type.asDoubleMap;
return decodeHashers(registry, value, [
[mapInfo.hasher, mapInfo.key1.toString()],
[mapInfo.key2Hasher, mapInfo.key2.toString()]
]);
}
const mapInfo = meta.type.asNMap;
return decodeHashers(registry, value, mapInfo.hashers.map((h, i) =>
[h, mapInfo.keyVec[i].toString()]
));
return decodeHashers(registry, value, hashers.map((h, i) => [h, keys[i]]));
}
/** @internal */
function getMeta (value: StorageKey | StorageEntry | [StorageEntry, unknown]): StorageEntryMetadataLatest | undefined {
function getMeta (value: StorageKey | StorageEntry | [StorageEntry, unknown[]?]): StorageEntryMetadataLatest | undefined {
if (value instanceof StorageKey) {
return value.meta;
} else if (isFunction(value)) {
@@ -142,7 +130,7 @@ function getMeta (value: StorageKey | StorageEntry | [StorageEntry, unknown]): S
}
/** @internal */
function getType (registry: Registry, value: StorageKey | StorageEntry | [StorageEntry, unknown]): string {
function getType (registry: Registry, value: StorageKey | StorageEntry | [StorageEntry, unknown[]?]): string {
if (value instanceof StorageKey) {
return value.outputType;
} else if (isFunction(value)) {
@@ -178,7 +166,7 @@ export class StorageKey<A extends AnyTuple = AnyTuple> extends Bytes implements
private _section?: string;
constructor (registry: Registry, value?: AnyU8a | StorageKey | StorageEntry | [StorageEntry, unknown], override: Partial<StorageKeyExtra> = {}) {
constructor (registry: Registry, value?: string | Uint8Array | StorageKey | StorageEntry | [StorageEntry, unknown[]?], override: Partial<StorageKeyExtra> = {}) {
const { key, method, section } = decodeStorageKey(value);
super(registry, key);
@@ -190,7 +178,7 @@ export class StorageKey<A extends AnyTuple = AnyTuple> extends Bytes implements
}
/**
* @description Return the decoded arguments (applicable to map/doublemap with decodable values)
* @description Return the decoded arguments (applicable to map with decodable values)
*/
public get args (): A {
return this._args;
+1 -1
View File
@@ -5,7 +5,7 @@ import type { StorageEntryMetadataLatest } from '../interfaces/metadata';
import type { Codec } from '../types';
export interface StorageEntry {
(arg?: unknown): Uint8Array;
(...args: unknown[]): Uint8Array;
iterKey?: (...args: unknown[]) => Uint8Array & Codec;
keyPrefix: (...args: unknown[]) => Uint8Array;
meta: StorageEntryMetadataLatest;
+3 -3
View File
@@ -3,7 +3,7 @@
import type { BN } from '@polkadot/util';
import type { Hash } from '../interfaces/runtime';
import type { Registry } from './registry';
import type { InterfaceTypes, Registry } from './registry';
export type AnyJson = string | number | boolean | null | undefined | AnyJson[] | { [index: string]: AnyJson };
@@ -111,6 +111,6 @@ export interface Constructor<T = Codec> {
new(registry: Registry, ...args: any[]): T;
}
export type ConstructorDef<T = Codec> = Record<string, Constructor<T>>;
export type ConstructorDef<T = Codec> = Record<string, Constructor<T> | Constructor<T>>;
export type ArgsDef = Record<string, Constructor>;
export type ArgsDef = Record<string, Constructor | keyof InterfaceTypes>;
+3 -1
View File
@@ -7,7 +7,7 @@ import type { CreateOptions } from '../create/types';
import type { ExtDef } from '../extrinsic/signedExtensions/types';
import type { MetadataLatest, PortableRegistry } from '../interfaces/metadata';
import type { CodecHash, Hash } from '../interfaces/runtime';
import type { SiLookupTypeId } from '../interfaces/scaleInfo';
import type { SiField, SiLookupTypeId } from '../interfaces/scaleInfo';
import type { ChainProperties } from '../interfaces/system';
import type { Metadata } from '../metadata';
import type { CallFunction } from './calls';
@@ -37,7 +37,9 @@ export type RegistryTypes =
{ _set: Record<string, number> }>;
export interface RegistryError {
args: string[];
docs: string[];
fields: SiField[];
index: number;
// compat
method: string;