diff --git a/.codeclimate.yml b/.codeclimate.yml index 22eedb7632..16f23fb33e 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -4,5 +4,6 @@ exclude_patterns: - "**/*.test.js" - "**/*.test.ts" - "docs/**/*.js" +- "packages/api/src/query.types.ts" - "packages/types/src/interfaces/" - "packages/types/src/scripts/" diff --git a/packages/api-derive/src/staking/info.ts b/packages/api-derive/src/staking/info.ts index adf43f3184..84079a56ad 100644 --- a/packages/api-derive/src/staking/info.ts +++ b/packages/api-derive/src/staking/info.ts @@ -171,10 +171,10 @@ export function info (api: ApiInterfaceRx): (_accountId: Uint8Array | string) => // NOTE For 2.x-only support, only the first path is required, therefore we // can replace this with `.bonded>(accountId)` - in 2.x // the session.validators return the stashes (as expected) - api.queryMulti([ + api.queryMulti<[Option, Option]>([ [api.query.staking.bonded, accountId], // try to map to controller [api.query.staking.ledger, accountId] // try to map to stash (1.x only) - ]) as Observable<[Option, Option]> + ]) ).pipe( switchMap(([controllerId, stakingLedger]): Observable => controllerId.isSome diff --git a/packages/api/src/base/Decorate.ts b/packages/api/src/base/Decorate.ts index 1378b5672c..fbc6377d6f 100644 --- a/packages/api/src/base/Decorate.ts +++ b/packages/api/src/base/Decorate.ts @@ -7,7 +7,7 @@ import { RpcInterface } from '@polkadot/rpc-core/jsonrpc.types'; import { Call, Hash, RuntimeVersion } from '@polkadot/types/interfaces'; import { AnyFunction, CallFunction, Codec, CodecArg as Arg, ModulesWithCalls } from '@polkadot/types/types'; import { SubmittableExtrinsic } from '../submittable/types'; -import { ApiInterfaceRx, ApiOptions, ApiTypes, DecorateMethod, DecoratedRpc, DecoratedRpcSection, QueryableModuleStorage, QueryableStorage, QueryableStorageEntry, QueryableStorageMulti, QueryableStorageMultiArg, QueryableStorageMultiArgs, SubmittableExtrinsicFunction, SubmittableExtrinsics, SubmittableModuleExtrinsics } from '../types'; +import { ApiInterfaceRx, ApiOptions, ApiTypes, DecorateMethod, DecoratedRpc, DecoratedRpcSection, QueryableModuleStorage, QueryableStorage, QueryableStorageEntry, QueryableStorageMulti, QueryableStorageMultiArg, SubmittableExtrinsicFunction, SubmittableExtrinsics, SubmittableModuleExtrinsics } from '../types'; import BN from 'bn.js'; import { BehaviorSubject, Observable } from 'rxjs'; @@ -163,6 +163,7 @@ export default abstract class Decorate extends Events { ? !methods.includes(key) && key !== 'rpc_methods' // rpc_methods doesn't appear, v1 : isOptional || key === 'rpc_methods' // we didn't find this one, remove ) + // eslint-disable-next-line @typescript-eslint/no-unused-vars .forEach(([_, { method, section }]): void => { delete (this._rpc as any)[section][method]; delete (this._rx.rpc as any)[section][method]; @@ -188,7 +189,7 @@ export default abstract class Decorate extends Events { } protected decorateMulti (decorateMethod: Decorate['decorateMethod']): QueryableStorageMulti { - return decorateMethod((calls: QueryableStorageMultiArgs): Observable => + return decorateMethod((calls: QueryableStorageMultiArg[]): Observable => this._rpcCore.state.subscribeStorage( calls.map((arg: QueryableStorageMultiArg): [QueryableStorageEntry, ...Arg[]] => // the input is a QueryableStorageEntry, convert to StorageEntry @@ -349,7 +350,7 @@ export default abstract class Decorate extends Events { * Put the `this.onCall` function of ApiRx here, because it is needed by * `api._rx`. */ - protected rxDecorateMethod = (method: Method): Method => { + protected rxDecorateMethod = (method: Method): Method => { return method; } } diff --git a/packages/api/src/checkTypes.manual.ts b/packages/api/src/checkTypes.manual.ts index 4f680df5f5..7ecccb11e5 100644 --- a/packages/api/src/checkTypes.manual.ts +++ b/packages/api/src/checkTypes.manual.ts @@ -37,6 +37,17 @@ async function query (api: ApiPromise, keyring: TestKeyringMap): Promise { const intentions = await api.query.staking.intentions(); console.log('intentions:', intentions); + // api.query.*.* is well-typed + const bar = await api.query.foo.bar(); // bar is Codec (unknown module) + const bal = await api.query.balances.freeBalance(keyring.alice.address); // bal is Balance + const bal2 = await api.query.balances.freeBalance(keyring.alice.address, 'WRONG_ARG'); // bal2 is Codec (wrong args) + const override = await api.query.balances.freeBalance
(keyring.alice.address); // override is still available + const oldBal = await api.query.balances.freeBalance.at('abcd', keyring.alice.address); + // It's hard to correctly type .multi. Expected: `Balance[]`, actual: Codec[]. + // In the meantime, we can case with `` + const multi = await api.query.balances.freeBalance.multi([keyring.alice.address, keyring.bob.address]); + console.log('query types:', bar, bal, bal2, override, oldBal, multi); + // check multi for unsub const multiUnsub = await api.queryMulti([ [api.query.system.accountNonce, keyring.eve.address], @@ -96,7 +107,7 @@ async function tx (api: ApiPromise, keyring: TestKeyringMap): Promise { }); // with options and the callback - const nonce2 = await api.query.system.accountNonce(keyring.alice.address); + const nonce2 = await api.query.system.accountNonce(keyring.alice.address); const unsub2 = await api.tx.balances .transfer(keyring.bob.address, 12345) .signAndSend(keyring.alice, { nonce: nonce2 }, ({ status }: SubmittableResult): void => { diff --git a/packages/api/src/query.types.ts b/packages/api/src/query.types.ts new file mode 100644 index 0000000000..3e89117350 --- /dev/null +++ b/packages/api/src/query.types.ts @@ -0,0 +1,214 @@ +// Auto-generated via `yarn build:interfaces`, do not edit +/* eslint-disable @typescript-eslint/no-empty-interface */ + +import { Observable } from 'rxjs'; +import { Option, U8a, Vec } from '@polkadot/types/codec'; +import { Bytes, Null, bool, i8, u32, u64 } from '@polkadot/types'; +import { AccountId, AccountIndex, Balance, BalanceOf, BlockNumber, Hash, Index, KeyTypeId, Moment, Perbill, ValidatorId, Weight, WeightMultiplier } from '@polkadot/types/interfaces/runtime'; +import { UncleEntryItem } from '@polkadot/types/interfaces/authorship'; +import { BabeAuthorityWeight } from '@polkadot/types/interfaces/babe'; +import { BalanceLock, VestingSchedule } from '@polkadot/types/interfaces/balances'; +import { ProposalIndex, Votes } from '@polkadot/types/interfaces/collective'; +import { AuthorityId } from '@polkadot/types/interfaces/consensus'; +import { CodeHash, ContractInfo, Gas, PrefabWasmModule, Schedule } from '@polkadot/types/interfaces/contracts'; +import { Conviction, PropIndex, Proposal, ReferendumIndex, ReferendumInfo } from '@polkadot/types/interfaces/democracy'; +import { ApprovalFlag, SetIndex, Vote, VoteIndex, VoteThreshold, VoterInfo } from '@polkadot/types/interfaces/elections'; +import { AuthorityWeight, SetId, StoredPendingChange, StoredState } from '@polkadot/types/interfaces/grandpa'; +import { AuthIndex } from '@polkadot/types/interfaces/imOnline'; +import { Kind, OffenceDetails, OpaqueTimeSlot, ReportIdOf } from '@polkadot/types/interfaces/offences'; +import { Keys, SessionIndex } from '@polkadot/types/interfaces/session'; +import { EraIndex, EraPoints, Exposure, Forcing, MomentOf, RewardDestination, SlashJournalEntry, StakingLedger, ValidatorPrefs } from '@polkadot/types/interfaces/staking'; +import { DigestOf, EventIndex, EventRecord } from '@polkadot/types/interfaces/system'; +import { TreasuryProposal } from '@polkadot/types/interfaces/treasury'; +import { ITuple } from '@polkadot/types/types'; + +declare module './types' { + export interface QueryableStorageExact { + system: { + [index: string]: QueryableStorageEntry; + accountNonce: StorageEntryExact Observable> & QueryableStorageEntry; + extrinsicCount: StorageEntryExact Observable> & QueryableStorageEntry; + allExtrinsicsWeight: StorageEntryExact Observable> & QueryableStorageEntry; + allExtrinsicsLen: StorageEntryExact Observable> & QueryableStorageEntry; + nextWeightMultiplier: StorageEntryExact Observable> & QueryableStorageEntry; + blockHash: StorageEntryExact Observable> & QueryableStorageEntry; + extrinsicData: StorageEntryExact Observable> & QueryableStorageEntry; + randomMaterial: StorageEntryExact Observable]>>> & QueryableStorageEntry; + number: StorageEntryExact Observable> & QueryableStorageEntry; + parentHash: StorageEntryExact Observable> & QueryableStorageEntry; + extrinsicsRoot: StorageEntryExact Observable> & QueryableStorageEntry; + digest: StorageEntryExact Observable> & QueryableStorageEntry; + events: StorageEntryExact Observable>> & QueryableStorageEntry; + eventCount: StorageEntryExact Observable> & QueryableStorageEntry; + eventTopics: StorageEntryExact Observable>>> & QueryableStorageEntry; + }; + babe: { + [index: string]: QueryableStorageEntry; + epochIndex: StorageEntryExact Observable> & QueryableStorageEntry; + authorities: StorageEntryExact Observable>>> & QueryableStorageEntry; + epochStartSlot: StorageEntryExact Observable> & QueryableStorageEntry; + currentSlot: StorageEntryExact Observable> & QueryableStorageEntry; + secondarySlots: StorageEntryExact Observable>> & QueryableStorageEntry; + pendingSecondarySlotsChange: StorageEntryExact Observable> & QueryableStorageEntry; + randomness: StorageEntryExact Observable> & QueryableStorageEntry; + nextRandomness: StorageEntryExact Observable> & QueryableStorageEntry; + segmentIndex: StorageEntryExact Observable> & QueryableStorageEntry; + underConstruction: StorageEntryExact Observable>> & QueryableStorageEntry; + initialized: StorageEntryExact Observable> & QueryableStorageEntry; + }; + timestamp: { + [index: string]: QueryableStorageEntry; + now: StorageEntryExact Observable> & QueryableStorageEntry; + didUpdate: StorageEntryExact Observable> & QueryableStorageEntry; + }; + authorship: { + [index: string]: QueryableStorageEntry; + uncles: StorageEntryExact Observable>> & QueryableStorageEntry; + author: StorageEntryExact Observable> & QueryableStorageEntry; + didSetUncles: StorageEntryExact Observable> & QueryableStorageEntry; + }; + indices: { + [index: string]: QueryableStorageEntry; + nextEnumSet: StorageEntryExact Observable> & QueryableStorageEntry; + enumSet: StorageEntryExact Observable>> & QueryableStorageEntry; + }; + balances: { + [index: string]: QueryableStorageEntry; + totalIssuance: StorageEntryExact Observable> & QueryableStorageEntry; + vesting: StorageEntryExact Observable> & QueryableStorageEntry; + freeBalance: StorageEntryExact Observable> & QueryableStorageEntry; + reservedBalance: StorageEntryExact Observable> & QueryableStorageEntry; + locks: StorageEntryExact Observable>> & QueryableStorageEntry; + }; + staking: { + [index: string]: QueryableStorageEntry; + validatorCount: StorageEntryExact Observable> & QueryableStorageEntry; + minimumValidatorCount: StorageEntryExact Observable> & QueryableStorageEntry; + invulnerables: StorageEntryExact Observable>> & QueryableStorageEntry; + bonded: StorageEntryExact Observable> & QueryableStorageEntry; + ledger: StorageEntryExact Observable> & QueryableStorageEntry; + payee: StorageEntryExact Observable> & QueryableStorageEntry; + validators: StorageEntryExact Observable> & QueryableStorageEntry; + nominators: StorageEntryExact Observable>> & QueryableStorageEntry; + stakers: StorageEntryExact Observable> & QueryableStorageEntry; + currentElected: StorageEntryExact Observable>> & QueryableStorageEntry; + currentEra: StorageEntryExact Observable> & QueryableStorageEntry; + currentEraStart: StorageEntryExact Observable> & QueryableStorageEntry; + currentEraStartSessionIndex: StorageEntryExact Observable> & QueryableStorageEntry; + currentEraPointsEarned: StorageEntryExact Observable> & QueryableStorageEntry; + slotStake: StorageEntryExact Observable> & QueryableStorageEntry; + forceEra: StorageEntryExact Observable> & QueryableStorageEntry; + slashRewardFraction: StorageEntryExact Observable> & QueryableStorageEntry; + bondedEras: StorageEntryExact Observable>>> & QueryableStorageEntry; + eraSlashJournal: StorageEntryExact Observable>> & QueryableStorageEntry; + }; + session: { + [index: string]: QueryableStorageEntry; + validators: StorageEntryExact Observable>> & QueryableStorageEntry; + currentIndex: StorageEntryExact Observable> & QueryableStorageEntry; + queuedChanged: StorageEntryExact Observable> & QueryableStorageEntry; + queuedKeys: StorageEntryExact Observable>>> & QueryableStorageEntry; + nextKeys: StorageEntryExact Observable> & QueryableStorageEntry; + keyOwner: StorageEntryExact) => Observable> & QueryableStorageEntry; + }; + democracy: { + [index: string]: QueryableStorageEntry; + publicPropCount: StorageEntryExact Observable> & QueryableStorageEntry; + publicProps: StorageEntryExact Observable>>> & QueryableStorageEntry; + depositOf: StorageEntryExact Observable]>>> & QueryableStorageEntry; + referendumCount: StorageEntryExact Observable> & QueryableStorageEntry; + nextTally: StorageEntryExact Observable> & QueryableStorageEntry; + referendumInfoOf: StorageEntryExact Observable> & QueryableStorageEntry; + dispatchQueue: StorageEntryExact Observable>>>> & QueryableStorageEntry; + votersFor: StorageEntryExact Observable>> & QueryableStorageEntry; + voteOf: StorageEntryExact) => Observable> & QueryableStorageEntry; + proxy: StorageEntryExact Observable> & QueryableStorageEntry; + delegations: StorageEntryExact Observable>> & QueryableStorageEntry; + lastTabledWasExternal: StorageEntryExact Observable> & QueryableStorageEntry; + nextExternal: StorageEntryExact Observable>> & QueryableStorageEntry; + blacklist: StorageEntryExact Observable]>>> & QueryableStorageEntry; + cancellations: StorageEntryExact Observable> & QueryableStorageEntry; + }; + council: { + [index: string]: QueryableStorageEntry; + proposals: StorageEntryExact Observable>> & QueryableStorageEntry; + proposalOf: StorageEntryExact Observable> & QueryableStorageEntry; + voting: StorageEntryExact Observable> & QueryableStorageEntry; + proposalCount: StorageEntryExact Observable> & QueryableStorageEntry; + members: StorageEntryExact Observable>> & QueryableStorageEntry; + }; + technicalCommittee: { + [index: string]: QueryableStorageEntry; + proposals: StorageEntryExact Observable>> & QueryableStorageEntry; + proposalOf: StorageEntryExact Observable> & QueryableStorageEntry; + voting: StorageEntryExact Observable> & QueryableStorageEntry; + proposalCount: StorageEntryExact Observable> & QueryableStorageEntry; + members: StorageEntryExact Observable>> & QueryableStorageEntry; + }; + elections: { + [index: string]: QueryableStorageEntry; + presentationDuration: StorageEntryExact Observable> & QueryableStorageEntry; + termDuration: StorageEntryExact Observable> & QueryableStorageEntry; + desiredSeats: StorageEntryExact Observable> & QueryableStorageEntry; + members: StorageEntryExact Observable>>> & QueryableStorageEntry; + voteCount: StorageEntryExact Observable> & QueryableStorageEntry; + approvalsOf: StorageEntryExact) => Observable>> & QueryableStorageEntry; + registerInfoOf: StorageEntryExact Observable>> & QueryableStorageEntry; + voterInfoOf: StorageEntryExact Observable> & QueryableStorageEntry; + voters: StorageEntryExact Observable>>> & QueryableStorageEntry; + nextVoterSet: StorageEntryExact Observable> & QueryableStorageEntry; + voterCount: StorageEntryExact Observable> & QueryableStorageEntry; + candidates: StorageEntryExact Observable>> & QueryableStorageEntry; + candidateCount: StorageEntryExact Observable> & QueryableStorageEntry; + nextFinalize: StorageEntryExact Observable]>>> & QueryableStorageEntry; + leaderboard: StorageEntryExact Observable>>> & QueryableStorageEntry; + proxy: StorageEntryExact Observable> & QueryableStorageEntry; + }; + technicalMembership: { + [index: string]: QueryableStorageEntry; + members: StorageEntryExact Observable>> & QueryableStorageEntry; + }; + grandpa: { + [index: string]: QueryableStorageEntry; + authorities: StorageEntryExact Observable>>> & QueryableStorageEntry; + state: StorageEntryExact Observable> & QueryableStorageEntry; + pendingChange: StorageEntryExact Observable> & QueryableStorageEntry; + nextForced: StorageEntryExact Observable> & QueryableStorageEntry; + stalled: StorageEntryExact Observable>> & QueryableStorageEntry; + currentSetId: StorageEntryExact Observable> & QueryableStorageEntry; + setIdSession: StorageEntryExact Observable> & QueryableStorageEntry; + }; + treasury: { + [index: string]: QueryableStorageEntry; + proposalCount: StorageEntryExact Observable> & QueryableStorageEntry; + proposals: StorageEntryExact Observable> & QueryableStorageEntry; + approvals: StorageEntryExact Observable>> & QueryableStorageEntry; + }; + contracts: { + [index: string]: QueryableStorageEntry; + gasSpent: StorageEntryExact Observable> & QueryableStorageEntry; + currentSchedule: StorageEntryExact Observable> & QueryableStorageEntry; + pristineCode: StorageEntryExact Observable> & QueryableStorageEntry; + codeStorage: StorageEntryExact Observable> & QueryableStorageEntry; + accountCounter: StorageEntryExact Observable> & QueryableStorageEntry; + contractInfoOf: StorageEntryExact Observable> & QueryableStorageEntry; + gasPrice: StorageEntryExact Observable> & QueryableStorageEntry; + }; + sudo: { + [index: string]: QueryableStorageEntry; + key: StorageEntryExact Observable> & QueryableStorageEntry; + }; + imOnline: { + [index: string]: QueryableStorageEntry; + gossipAt: StorageEntryExact Observable> & QueryableStorageEntry; + keys: StorageEntryExact Observable>> & QueryableStorageEntry; + receivedHeartbeats: StorageEntryExact Observable> & QueryableStorageEntry; + }; + offences: { + [index: string]: QueryableStorageEntry; + reports: StorageEntryExact Observable> & QueryableStorageEntry; + concurrentReportsIndex: StorageEntryExact Observable>> & QueryableStorageEntry; + reportsByKindIndex: StorageEntryExact Observable> & QueryableStorageEntry; + }; + } +} diff --git a/packages/api/src/submittable/Submittable.ts b/packages/api/src/submittable/Submittable.ts index e94cd0acc6..cd3f02c8a4 100644 --- a/packages/api/src/submittable/Submittable.ts +++ b/packages/api/src/submittable/Submittable.ts @@ -3,14 +3,14 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { AccountId, Address, Call, Extrinsic, ExtrinsicEra, ExtrinsicStatus, EventRecord, Hash, Header, Index } from '@polkadot/types/interfaces'; +import { AccountId, Address, Call, Extrinsic, ExtrinsicEra, ExtrinsicStatus, Hash, Header, Index } from '@polkadot/types/interfaces'; import { Callback, Codec, Constructor, IKeyringPair, SignatureOptions } from '@polkadot/types/types'; import { ApiInterfaceRx, ApiTypes, SignerResult } from '../types'; import { SignerOptions, SubmittableExtrinsic, SubmittableResultImpl, SubmitableResultResult, SubmitableResultSubscription } from './types'; import { Observable, combineLatest, of } from 'rxjs'; import { first, map, mergeMap, switchMap, tap } from 'rxjs/operators'; -import { createType, ClassOf, Vec } from '@polkadot/types'; +import { createType, ClassOf } from '@polkadot/types'; import { isBn, isFunction, isNumber, isUndefined } from '@polkadot/util'; import { filterEvents, isKeyringPair } from '../util'; @@ -61,13 +61,13 @@ export default class Submittable extends _Extrinsic implements Submitta } // signAndSend with an immediate Hash result - public signAndSend(account: IKeyringPair | string | AccountId | Address, options?: Partial): SubmitableResultResult; + public signAndSend (account: IKeyringPair | string | AccountId | Address, options?: Partial): SubmitableResultResult; // signAndSend with a subscription, i.e. callback provided - public signAndSend(account: IKeyringPair | string | AccountId | Address, statusCb: Callback): SubmitableResultSubscription; + public signAndSend (account: IKeyringPair | string | AccountId | Address, statusCb: Callback): SubmitableResultSubscription; // signAndSend with options and a callback - public signAndSend(account: IKeyringPair | string | AccountId | Address, options: Partial, statusCb?: Callback): SubmitableResultSubscription; + public signAndSend (account: IKeyringPair | string | AccountId | Address, options: Partial, statusCb?: Callback): SubmitableResultSubscription; // signAndSend implementation for all 3 cases above public signAndSend (account: IKeyringPair | string | AccountId | Address, optionsOrStatus?: Partial | Callback, optionalStatusCb?: Callback): SubmitableResultResult | SubmitableResultSubscription { @@ -218,7 +218,7 @@ export default class Submittable extends _Extrinsic implements Submitta return combineLatest([ this._api.rpc.chain.getBlock(blockHash), - this._api.query.system.events.at(blockHash) as Observable> + this._api.query.system.events.at(blockHash) ]).pipe( map(([signedBlock, allEvents]): SubmittableResultImpl => new SubmittableResult({ diff --git a/packages/api/src/types.ts b/packages/api/src/types.ts index 651258c87a..0b75883c8b 100644 --- a/packages/api/src/types.ts +++ b/packages/api/src/types.ts @@ -60,15 +60,22 @@ export type DecorateMethod = (method: (...args: any[]) => Observable, optio // These are the types that don't lose type information (used for api.derive.*) // Also use these for api.rpc.* https://github.com/polkadot-js/api/issues/1009 -export type RxResult = (...args: Parameters) => Observable>>; - +export interface RxResult { + (...args: Parameters): Observable>>; + (...args: Parameters): Observable; +} export interface PromiseResult { (...args: Parameters): Promise>>; (...args: Push, Callback>>>): UnsubscribePromise; - (...args: Parameters): Promise; - (...args: Push, Callback>): UnsubscribePromise; + (...args: Parameters): Promise; + (...args: Push, Callback>): UnsubscribePromise; } +// FIXME The day TS has higher-kinded types, we can remove this hardcoded stuff +export type PromiseOrObs = ApiType extends 'rxjs' + ? Observable + : Promise + // FIXME The day TS has higher-kinded types, we can remove this hardcoded stuff export type MethodResult = ApiType extends 'rxjs' ? RxResult @@ -84,18 +91,22 @@ export type DecoratedRpc = { [Section in keyof AllSections]: DecoratedRpcSection } -interface StorageEntryBase { - at: (hash: Hash | Uint8Array | string, arg1?: CodecArg, arg2?: CodecArg) => C; - creator: StorageEntry; - hash: (arg1?: CodecArg, arg2?: CodecArg) => H; - key: (arg1?: CodecArg, arg2?: CodecArg) => string; - size: (arg1?: CodecArg, arg2?: CodecArg) => U; +interface StorageEntryObservableMulti { + (args: (CodecArg[] | CodecArg)[]): Observable; } -export interface StorageEntryObservable extends StorageEntryBase, Observable, Observable> { - (arg1?: CodecArg, arg2?: CodecArg): Observable; - (arg1?: CodecArg, arg2?: CodecArg): Observable; - multi: (args: (CodecArg[] | CodecArg)[]) => Observable; +interface StorageEntryPromiseMulti { + (args: (CodecArg[] | CodecArg)[]): Promise; + (args: (CodecArg[] | CodecArg)[], callback: Callback): UnsubscribePromise; +} + +export interface StorageEntryBase { + at: (hash: Hash | Uint8Array | string, ...args: Parameters) => PromiseOrObs>>; + creator: StorageEntry; + hash: (...args: Parameters) => PromiseOrObs; + key: (...args: Parameters) => string; + size: (...args: Parameters) => PromiseOrObs; + multi: ApiType extends 'rxjs' ? StorageEntryObservableMulti : StorageEntryPromiseMulti; } export interface StorageEntryPromiseOverloads { @@ -106,19 +117,15 @@ export interface StorageEntryPromiseOverloads { (arg1: CodecArg, arg2: CodecArg, callback: Callback): UnsubscribePromise; } -export interface StorageEntryPromiseMulti { - (args: (CodecArg[] | CodecArg)[]): Promise; - (args: (CodecArg[] | CodecArg)[], callback: Callback): UnsubscribePromise; -} +export type StorageEntryExact = MethodResult & StorageEntryBase -export interface StorageEntryPromise extends StorageEntryBase, Promise, Promise>, StorageEntryPromiseOverloads { - multi: StorageEntryPromiseMulti; -} +// This is the most generic typings we can have for a storage entry function +type GenericStorageEntryFunction = (arg1?: CodecArg, arg2?: CodecArg) => Observable export type QueryableStorageEntry = ApiType extends 'rxjs' - ? StorageEntryObservable - : StorageEntryPromise; + ? StorageEntryExact<'rxjs', GenericStorageEntryFunction> + : StorageEntryExact<'promise', GenericStorageEntryFunction> & StorageEntryPromiseOverloads; export interface QueryableModuleStorage { [index: string]: QueryableStorageEntry; @@ -128,14 +135,12 @@ export type QueryableStorageMultiArg = QueryableStorageEntry | [QueryableStorageEntry, ...CodecArg[]]; -export type QueryableStorageMultiArgs = QueryableStorageMultiArg[]; - export interface QueryableStorageMultiBase { - (calls: QueryableStorageMultiArgs): Observable; + (calls: QueryableStorageMultiArg[]): Observable; } export interface QueryableStorageMultiPromise { - (calls: QueryableStorageMultiArgs, callback: Callback): UnsubscribePromise; + (calls: QueryableStorageMultiArg[], callback: Callback): UnsubscribePromise; } export type QueryableStorageMulti = @@ -143,7 +148,12 @@ export type QueryableStorageMulti = ? QueryableStorageMultiBase : QueryableStorageMultiPromise; -export interface QueryableStorage { +// QueryableStorageExact will hold the exact typed api.query.*.* generated from +// metadata. For now it's empty, it's ready to be module augmented. +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface QueryableStorageExact { } + +export interface QueryableStorage extends QueryableStorageExact { [index: string]: QueryableModuleStorage; } diff --git a/packages/api/test/e2e/api/promise-alex.spec.ts b/packages/api/test/e2e/api/promise-alex.spec.ts index a714ea68d1..66b18a40ab 100644 --- a/packages/api/test/e2e/api/promise-alex.spec.ts +++ b/packages/api/test/e2e/api/promise-alex.spec.ts @@ -74,7 +74,7 @@ describeE2E({ it('makes a query at a latest block (specified)', async (): Promise => { const header = await api.rpc.chain.getHeader(); - const events = await api.query.system.events.at(header.hash) as Vec; + const events = await api.query.system.events.at(header.hash); expect(events.length).not.toEqual(0); }); diff --git a/packages/api/test/e2e/api/promise-queries-dev.spec.ts b/packages/api/test/e2e/api/promise-queries-dev.spec.ts index b15af74358..02a869fd51 100644 --- a/packages/api/test/e2e/api/promise-queries-dev.spec.ts +++ b/packages/api/test/e2e/api/promise-queries-dev.spec.ts @@ -123,7 +123,7 @@ describeE2E({ describe('with map type', (): void => { it('queries correct value', async (): Promise => { - const balance = await api.query.balances.freeBalance(keyring.bob_stash.address) as Balance; + const balance = await api.query.balances.freeBalance(keyring.bob_stash.address); expect(balance.isZero()).toBe(false); }); @@ -132,7 +132,7 @@ describeE2E({ // assume the account Alice is only used in test(the balance of Alice does not change in this test case) const balance = await api.query.balances.freeBalance(keyring.alice_stash.address); const header = await api.rpc.chain.getHeader(); - const balanceAt = await api.query.balances.freeBalance.at(header.hash, keyring.alice_stash.address) as Balance; + const balanceAt = await api.query.balances.freeBalance.at(header.hash, keyring.alice_stash.address); expect(balanceAt.isZero()).toBe(false); expect(balanceAt.toString()).toEqual(balance.toString()); diff --git a/packages/api/test/e2e/api/promise-queries.spec.ts b/packages/api/test/e2e/api/promise-queries.spec.ts index 5f1a2274a0..bdad8979f3 100644 --- a/packages/api/test/e2e/api/promise-queries.spec.ts +++ b/packages/api/test/e2e/api/promise-queries.spec.ts @@ -7,7 +7,7 @@ import { EventRecord, Hash, Header, SessionIndex } from '@polkadot/types/interfa import { HeaderExtended } from '@polkadot/api-derive'; import WsProvider from '@polkadot/rpc-provider/ws'; import { LinkageResult } from '@polkadot/types/codec/Linkage'; -import { Option, Vec, createType } from '@polkadot/types'; +import { Option, createType } from '@polkadot/types'; import ApiPromise from '../../../src/promise'; import { describeE2E } from '../../util'; @@ -80,7 +80,7 @@ describeE2E()('Promise e2e queries', (wsUrl: string): void => { it('makes a query at a latest block (specified)', async (): Promise => { const header = await api.rpc.chain.getHeader(); - const events = await api.query.system.events.at(header.hash) as Vec; + const events = await api.query.system.events.at(header.hash); expect(events.length).not.toEqual(0); @@ -100,14 +100,14 @@ describeE2E()('Promise e2e queries', (wsUrl: string): void => { describe('with plain type', (): void => { it('queries a correct value', async (): Promise => { - const sessionIndex = await api.query.session.currentIndex() as SessionIndex; + const sessionIndex = await api.query.session.currentIndex(); expect(sessionIndex.toNumber()).toBeGreaterThanOrEqual(0); }); it('queries correct value at a specified block', async (): Promise => { const header = await api.rpc.chain.getHeader(); - const sessionIndex = await api.query.session.currentIndex.at(header.hash) as SessionIndex; + const sessionIndex = await api.query.session.currentIndex.at(header.hash); expect(sessionIndex.toNumber()).toBeGreaterThanOrEqual(0); }); diff --git a/packages/api/test/e2e/api/promise-tx-eras.spec.ts b/packages/api/test/e2e/api/promise-tx-eras.spec.ts index 934041e1ce..104db3dcd7 100644 --- a/packages/api/test/e2e/api/promise-tx-eras.spec.ts +++ b/packages/api/test/e2e/api/promise-tx-eras.spec.ts @@ -4,7 +4,7 @@ import testingPairs from '@polkadot/keyring/testingPairs'; import WsProvider from '@polkadot/rpc-provider/ws'; -import { Header, Index } from '@polkadot/types/interfaces'; +import { Header } from '@polkadot/types/interfaces'; import { createType } from '@polkadot/types'; import ApiPromise from '../../../src/promise'; @@ -54,7 +54,7 @@ describeE2E({ }); it('fails on a transfer with invalid time', async (done): Promise => { - const nonce = await api.query.system.accountNonce(keyring.alice.address) as Index; + const nonce = await api.query.system.accountNonce(keyring.alice.address); const signedBlock = await api.rpc.chain.getBlock(); const currentHeight = signedBlock.block.header.number; const exERA = createType('ExtrinsicEra', { current: currentHeight, period: 4 }); @@ -83,7 +83,7 @@ describeE2E({ api.setSigner(signer); - const nonce = await api.query.system.accountNonce(keyring.bob_stash.address) as Index; + const nonce = await api.query.system.accountNonce(keyring.bob_stash.address); const signedBlock = await api.rpc.chain.getBlock(); const currentHeight = signedBlock.block.header.number; const exERA = createType('ExtrinsicEra', { current: currentHeight, period: 4 }); diff --git a/packages/api/test/e2e/api/promise-tx.spec.ts b/packages/api/test/e2e/api/promise-tx.spec.ts index 53127519cc..f2fddab830 100644 --- a/packages/api/test/e2e/api/promise-tx.spec.ts +++ b/packages/api/test/e2e/api/promise-tx.spec.ts @@ -7,7 +7,6 @@ import testingPairs from '@polkadot/keyring/testingPairs'; import WsProvider from '@polkadot/rpc-provider/ws'; import { randomAsHex } from '@polkadot/util-crypto'; import { u8aToHex } from '@polkadot/util'; -import { Index } from '@polkadot/types/interfaces'; import ApiPromise from '../../../src/promise'; import randomAsHex2097152 from '../../mock-data/randomAsHex_2097152'; @@ -26,7 +25,7 @@ describeE2E({ }); it('can submit an extrinsic from hex', async (done): Promise<() => void> => { - const nonce = await api.query.system.accountNonce(keyring.bob_stash.address) as Index; + const nonce = await api.query.system.accountNonce(keyring.bob_stash.address); const hex = api.tx.balances .transfer(keyring.eve.address, 12345) .sign(keyring.bob_stash, { nonce }) @@ -36,7 +35,7 @@ describeE2E({ }); it('invalid hex does throw a catchable exception', async (done): Promise => { - const nonce = await api.query.system.accountNonce(keyring.bob_stash.address) as Index; + const nonce = await api.query.system.accountNonce(keyring.bob_stash.address); const hex = api.tx.balances .transfer(keyring.eve.address, 12345) .sign(keyring.bob_stash, { nonce }) @@ -58,7 +57,7 @@ describeE2E({ }); it('makes a transfer (sign, then send)', async (done): Promise<() => void> => { - const nonce = await api.query.system.accountNonce(keyring.bob_stash.address) as Index; + const nonce = await api.query.system.accountNonce(keyring.bob_stash.address); return api.tx.balances .transfer(keyring.eve.address, 12345) @@ -67,7 +66,7 @@ describeE2E({ }); it('makes a transfer (sign, then send - compat version)', async (done): Promise<() => void> => { - const nonce = await api.query.system.accountNonce(keyring.bob_stash.address) as Index; + const nonce = await api.query.system.accountNonce(keyring.bob_stash.address); return api.tx.balances .transfer(keyring.eve.address, 12345) diff --git a/packages/api/test/e2e/api/rx-queries-dev.spec.ts b/packages/api/test/e2e/api/rx-queries-dev.spec.ts index 63f3d5a4f1..11c661b5ea 100644 --- a/packages/api/test/e2e/api/rx-queries-dev.spec.ts +++ b/packages/api/test/e2e/api/rx-queries-dev.spec.ts @@ -4,7 +4,6 @@ import BN from 'bn.js'; -import { Balance } from '@polkadot/types/interfaces'; import testingPairs from '@polkadot/keyring/testingPairs'; import WsProvider from '@polkadot/rpc-provider/ws'; @@ -29,7 +28,7 @@ describeE2E({ it('queries state for a balance', (done): void => { api.query.balances.freeBalance(keyring.alice_stash.address).subscribe((balance): void => { expect(balance).toBeInstanceOf(BN); - expect((balance as Balance).isZero()).toBe(false); + expect(balance.isZero()).toBe(false); done(); }); }); diff --git a/packages/types/src/interfaces/authorship/types.ts b/packages/types/src/interfaces/authorship/types.ts index 65926b1881..bee7b15f51 100644 --- a/packages/types/src/interfaces/authorship/types.ts +++ b/packages/types/src/interfaces/authorship/types.ts @@ -1,15 +1,15 @@ // Auto-generated via `yarn build:interfaces`, do not edit /* eslint-disable @typescript-eslint/no-empty-interface */ -import { Codec } from '../../types'; +import { ITuple } from '../../types'; import { Enum, Option } from '../../codec'; import { AccountId, BlockNumber, Hash } from '../runtime'; /** BlockNumber */ -export type InclusionHeight = BlockNumber; +export interface InclusionHeight extends BlockNumber {} -/** [Hash, Option] & Codec */ -export type Uncle = [Hash, Option] & Codec; +/** ITuple<[Hash, Option]> */ +export interface Uncle extends ITuple<[Hash, Option]> {} /** Enum */ export interface UncleEntryItem extends Enum { diff --git a/packages/types/src/interfaces/babe/types.ts b/packages/types/src/interfaces/babe/types.ts index 93fe5b14bb..ab35b100f4 100644 --- a/packages/types/src/interfaces/babe/types.ts +++ b/packages/types/src/interfaces/babe/types.ts @@ -5,13 +5,13 @@ import { Enum, Struct } from '../../codec'; import { H256, u32, u64 } from '../../primitive'; /** u64 */ -export type BabeAuthorityWeight = u64; +export interface BabeAuthorityWeight extends u64 {} /** u32 */ -export type BabeBlockWeight = u32; +export interface BabeBlockWeight extends u32 {} /** u64 */ -export type BabeWeight = u64; +export interface BabeWeight extends u64 {} /** Enum */ export interface RawBabePreDigest extends Enum { @@ -50,4 +50,4 @@ export interface RawBabePreDigestSecondary extends Struct { } /** u64 */ -export type SlotNumber = u64; +export interface SlotNumber extends u64 {} diff --git a/packages/types/src/interfaces/claims/types.ts b/packages/types/src/interfaces/claims/types.ts index a556a3fcc7..7a56495fd4 100644 --- a/packages/types/src/interfaces/claims/types.ts +++ b/packages/types/src/interfaces/claims/types.ts @@ -4,8 +4,8 @@ import { Codec } from '../../types'; import { H160 } from '../../primitive'; -/** Uint8Array & Codec */ -export type EcdsaSignature = Uint8Array & Codec; +/** Uint8Array, Codec */ +export interface EcdsaSignature extends Uint8Array, Codec {} /** H160 */ -export type EthereumAddress = H160; +export interface EthereumAddress extends H160 {} diff --git a/packages/types/src/interfaces/collective/types.ts b/packages/types/src/interfaces/collective/types.ts index 67f7d7e542..fab2dae3d1 100644 --- a/packages/types/src/interfaces/collective/types.ts +++ b/packages/types/src/interfaces/collective/types.ts @@ -6,10 +6,10 @@ import { u32 } from '../../primitive'; import { AccountId } from '../runtime'; /** u32 */ -export type MemberCount = u32; +export interface MemberCount extends u32 {} /** u32 */ -export type ProposalIndex = u32; +export interface ProposalIndex extends u32 {} /** Struct */ export interface Votes extends Struct { diff --git a/packages/types/src/interfaces/consensus/types.ts b/packages/types/src/interfaces/consensus/types.ts index fc62f2da7d..9d53672b38 100644 --- a/packages/types/src/interfaces/consensus/types.ts +++ b/packages/types/src/interfaces/consensus/types.ts @@ -4,4 +4,4 @@ import { AccountId } from '../runtime'; /** AccountId */ -export type AuthorityId = AccountId; +export interface AuthorityId extends AccountId {} diff --git a/packages/types/src/interfaces/contracts/types.ts b/packages/types/src/interfaces/contracts/types.ts index 831be4abdc..9bcb203693 100644 --- a/packages/types/src/interfaces/contracts/types.ts +++ b/packages/types/src/interfaces/contracts/types.ts @@ -23,7 +23,7 @@ export interface AliveContractInfo extends Struct { } /** Hash */ -export type CodeHash = Hash; +export interface CodeHash extends Hash {} /** Struct */ export interface ContractCallRequest extends Struct { @@ -69,11 +69,11 @@ export interface ContractInfo extends Enum { readonly asTombstone: TombstoneContractInfo; } -/** Uint8Array & Codec */ -export type ContractStorageKey = Uint8Array & Codec; +/** Uint8Array, Codec */ +export interface ContractStorageKey extends Uint8Array, Codec {} /** u64 */ -export type Gas = u64; +export interface Gas extends u64 {} /** Struct */ export interface PrefabWasmModule extends Struct { @@ -90,7 +90,7 @@ export interface PrefabWasmModule extends Struct { } /** Option */ -export type PrefabWasmModuleReserved = Option; +export interface PrefabWasmModuleReserved extends Option {} /** Struct */ export interface Schedule extends Struct { @@ -127,10 +127,10 @@ export interface Schedule extends Struct { } /** Hash */ -export type SeedOf = Hash; +export interface SeedOf extends Hash {} /** Hash */ -export type TombstoneContractInfo = Hash; +export interface TombstoneContractInfo extends Hash {} /** Bytes */ -export type TrieId = Bytes; +export interface TrieId extends Bytes {} diff --git a/packages/types/src/interfaces/democracy/types.ts b/packages/types/src/interfaces/democracy/types.ts index f09aa3d664..82a06b6d6c 100644 --- a/packages/types/src/interfaces/democracy/types.ts +++ b/packages/types/src/interfaces/democracy/types.ts @@ -23,13 +23,13 @@ export interface Conviction extends Enum { } /** u32 */ -export type PropIndex = u32; +export interface PropIndex extends u32 {} /** Call */ -export type Proposal = Call; +export interface Proposal extends Call {} /** u32 */ -export type ReferendumIndex = u32; +export interface ReferendumIndex extends u32 {} /** Struct */ export interface ReferendumInfo extends Struct { diff --git a/packages/types/src/interfaces/deprecated/types.ts b/packages/types/src/interfaces/deprecated/types.ts index 1249ae3797..47124b217d 100644 --- a/packages/types/src/interfaces/deprecated/types.ts +++ b/packages/types/src/interfaces/deprecated/types.ts @@ -14,16 +14,16 @@ export interface AccountInfo extends Struct { } /** Balance */ -export type Amount = Balance; +export interface Amount extends Balance {} /** u32 */ -export type AssetOf = u32; +export interface AssetOf extends u32 {} /** Null */ -export type InherentOfflineReport = Null; +export interface InherentOfflineReport extends Null {} /** i8 */ -export type LockPeriods = i8; +export interface LockPeriods extends i8 {} /** Enum */ export interface NewAccountOutcome extends Enum { @@ -36,7 +36,7 @@ export interface NewAccountOutcome extends Enum { } /** Bytes */ -export type OpaqueKey = Bytes; +export interface OpaqueKey extends Bytes {} /** AccountId */ -export type SessionKey = AccountId; +export interface SessionKey extends AccountId {} diff --git a/packages/types/src/interfaces/elections/types.ts b/packages/types/src/interfaces/elections/types.ts index daa7e959ed..6679391542 100644 --- a/packages/types/src/interfaces/elections/types.ts +++ b/packages/types/src/interfaces/elections/types.ts @@ -6,16 +6,16 @@ import { GenericVote, u32 } from '../../primitive'; import { Balance } from '../runtime'; /** u32 */ -export type ApprovalFlag = u32; +export interface ApprovalFlag extends u32 {} /** u32 */ -export type SetIndex = u32; +export interface SetIndex extends u32 {} /** GenericVote */ -export type Vote = GenericVote; +export interface Vote extends GenericVote {} /** u32 */ -export type VoteIndex = u32; +export interface VoteIndex extends u32 {} /** Struct */ export interface VoterInfo extends Struct { diff --git a/packages/types/src/interfaces/genericAsset/types.ts b/packages/types/src/interfaces/genericAsset/types.ts index 7c0336559c..7969f280e5 100644 --- a/packages/types/src/interfaces/genericAsset/types.ts +++ b/packages/types/src/interfaces/genericAsset/types.ts @@ -23,7 +23,7 @@ export interface Owner extends Enum { } /** PermissionsV1 */ -export type PermissionLatest = PermissionsV1; +export interface PermissionLatest extends PermissionsV1 {} /** Struct */ export interface PermissionsV1 extends Struct { diff --git a/packages/types/src/interfaces/grandpa/types.ts b/packages/types/src/interfaces/grandpa/types.ts index 7da6b60c21..59bd9dde55 100644 --- a/packages/types/src/interfaces/grandpa/types.ts +++ b/packages/types/src/interfaces/grandpa/types.ts @@ -1,17 +1,17 @@ // Auto-generated via `yarn build:interfaces`, do not edit /* eslint-disable @typescript-eslint/no-empty-interface */ -import { Codec } from '../../types'; +import { ITuple } from '../../types'; import { Enum, Struct, Vec } from '../../codec'; import { u64 } from '../../primitive'; import { BlockNumber } from '../runtime'; import { AuthorityId } from '../consensus'; /** u64 */ -export type AuthorityWeight = u64; +export interface AuthorityWeight extends u64 {} -/** [AuthorityId, u64] & Codec */ -export type NextAuthority = [AuthorityId, u64] & Codec; +/** ITuple<[AuthorityId, u64]> */ +export interface NextAuthority extends ITuple<[AuthorityId, u64]> {} /** Struct */ export interface PendingPause extends Struct { @@ -30,7 +30,7 @@ export interface PendingResume extends Struct { } /** u64 */ -export type SetId = u64; +export interface SetId extends u64 {} /** Struct */ export interface StoredPendingChange extends Struct { diff --git a/packages/types/src/interfaces/imOnline/types.ts b/packages/types/src/interfaces/imOnline/types.ts index dbc675dfe3..afd3b6e618 100644 --- a/packages/types/src/interfaces/imOnline/types.ts +++ b/packages/types/src/interfaces/imOnline/types.ts @@ -8,10 +8,10 @@ import { AuthorityId } from '../consensus'; import { SessionIndex } from '../session'; /** u32 */ -export type AuthIndex = u32; +export interface AuthIndex extends u32 {} /** Signature */ -export type AuthoritySignature = Signature; +export interface AuthoritySignature extends Signature {} /** Struct */ export interface Heartbeat extends Struct { @@ -26,7 +26,7 @@ export interface Heartbeat extends Struct { } /** Bytes */ -export type OpaqueMultiaddr = Bytes; +export interface OpaqueMultiaddr extends Bytes {} /** Struct */ export interface OpaqueNetworkState extends Struct { @@ -37,4 +37,4 @@ export interface OpaqueNetworkState extends Struct { } /** Bytes */ -export type OpaquePeerId = Bytes; +export interface OpaquePeerId extends Bytes {} diff --git a/packages/types/src/interfaces/metadata/types.ts b/packages/types/src/interfaces/metadata/types.ts index e48022b1ac..63113c5e79 100644 --- a/packages/types/src/interfaces/metadata/types.ts +++ b/packages/types/src/interfaces/metadata/types.ts @@ -1,7 +1,7 @@ // Auto-generated via `yarn build:interfaces`, do not edit /* eslint-disable @typescript-eslint/no-empty-interface */ -import { Codec } from '../../types'; +import { ITuple } from '../../types'; import { Enum, Option, Struct, Vec } from '../../codec'; import { Bytes, StorageHasher, Text, Type, bool, u16 } from '../../primitive'; @@ -54,10 +54,10 @@ export interface DoubleMapTypeV5 extends Struct { } /** DoubleMapTypeV5 */ -export type DoubleMapTypeV6 = DoubleMapTypeV5; +export interface DoubleMapTypeV6 extends DoubleMapTypeV5 {} /** DoubleMapTypeV6 */ -export type DoubleMapTypeV7 = DoubleMapTypeV6; +export interface DoubleMapTypeV7 extends DoubleMapTypeV6 {} /** Struct */ export interface EventMetadataV0 extends Struct { @@ -70,25 +70,25 @@ export interface EventMetadataV0 extends Struct { } /** EventMetadataV0 */ -export type EventMetadataV1 = EventMetadataV0; +export interface EventMetadataV1 extends EventMetadataV0 {} /** EventMetadataV1 */ -export type EventMetadataV2 = EventMetadataV1; +export interface EventMetadataV2 extends EventMetadataV1 {} /** EventMetadataV2 */ -export type EventMetadataV3 = EventMetadataV2; +export interface EventMetadataV3 extends EventMetadataV2 {} /** EventMetadataV3 */ -export type EventMetadataV4 = EventMetadataV3; +export interface EventMetadataV4 extends EventMetadataV3 {} /** EventMetadataV4 */ -export type EventMetadataV5 = EventMetadataV4; +export interface EventMetadataV5 extends EventMetadataV4 {} /** EventMetadataV5 */ -export type EventMetadataV6 = EventMetadataV5; +export interface EventMetadataV6 extends EventMetadataV5 {} /** EventMetadataV6 */ -export type EventMetadataV7 = EventMetadataV6; +export interface EventMetadataV7 extends EventMetadataV6 {} /** Struct */ export interface FunctionArgumentMetadataV0 extends Struct { @@ -99,25 +99,25 @@ export interface FunctionArgumentMetadataV0 extends Struct { } /** FunctionArgumentMetadataV0 */ -export type FunctionArgumentMetadataV1 = FunctionArgumentMetadataV0; +export interface FunctionArgumentMetadataV1 extends FunctionArgumentMetadataV0 {} /** FunctionArgumentMetadataV1 */ -export type FunctionArgumentMetadataV2 = FunctionArgumentMetadataV1; +export interface FunctionArgumentMetadataV2 extends FunctionArgumentMetadataV1 {} /** FunctionArgumentMetadataV2 */ -export type FunctionArgumentMetadataV3 = FunctionArgumentMetadataV2; +export interface FunctionArgumentMetadataV3 extends FunctionArgumentMetadataV2 {} /** FunctionArgumentMetadataV3 */ -export type FunctionArgumentMetadataV4 = FunctionArgumentMetadataV3; +export interface FunctionArgumentMetadataV4 extends FunctionArgumentMetadataV3 {} /** FunctionArgumentMetadataV4 */ -export type FunctionArgumentMetadataV5 = FunctionArgumentMetadataV4; +export interface FunctionArgumentMetadataV5 extends FunctionArgumentMetadataV4 {} /** FunctionArgumentMetadataV5 */ -export type FunctionArgumentMetadataV6 = FunctionArgumentMetadataV5; +export interface FunctionArgumentMetadataV6 extends FunctionArgumentMetadataV5 {} /** FunctionArgumentMetadataV6 */ -export type FunctionArgumentMetadataV7 = FunctionArgumentMetadataV6; +export interface FunctionArgumentMetadataV7 extends FunctionArgumentMetadataV6 {} /** Struct */ export interface FunctionMetadataV0 extends Struct { @@ -142,22 +142,22 @@ export interface FunctionMetadataV1 extends Struct { } /** FunctionMetadataV1 */ -export type FunctionMetadataV2 = FunctionMetadataV1; +export interface FunctionMetadataV2 extends FunctionMetadataV1 {} /** FunctionMetadataV2 */ -export type FunctionMetadataV3 = FunctionMetadataV2; +export interface FunctionMetadataV3 extends FunctionMetadataV2 {} /** FunctionMetadataV3 */ -export type FunctionMetadataV4 = FunctionMetadataV3; +export interface FunctionMetadataV4 extends FunctionMetadataV3 {} /** FunctionMetadataV4 */ -export type FunctionMetadataV5 = FunctionMetadataV4; +export interface FunctionMetadataV5 extends FunctionMetadataV4 {} /** FunctionMetadataV5 */ -export type FunctionMetadataV6 = FunctionMetadataV5; +export interface FunctionMetadataV6 extends FunctionMetadataV5 {} /** FunctionMetadataV6 */ -export type FunctionMetadataV7 = FunctionMetadataV6; +export interface FunctionMetadataV7 extends FunctionMetadataV6 {} /** Struct */ export interface MapTypeV0 extends Struct { @@ -178,7 +178,7 @@ export interface MapTypeV2 extends Struct { } /** MapTypeV2 */ -export type MapTypeV3 = MapTypeV2; +export interface MapTypeV3 extends MapTypeV2 {} /** Struct */ export interface MapTypeV4 extends Struct { @@ -193,13 +193,13 @@ export interface MapTypeV4 extends Struct { } /** MapTypeV4 */ -export type MapTypeV5 = MapTypeV4; +export interface MapTypeV5 extends MapTypeV4 {} /** MapTypeV5 */ -export type MapTypeV6 = MapTypeV5; +export interface MapTypeV6 extends MapTypeV5 {} /** MapTypeV6 */ -export type MapTypeV7 = MapTypeV6; +export interface MapTypeV7 extends MapTypeV6 {} /** Struct */ export interface MetadataV0 extends Struct { @@ -230,7 +230,7 @@ export interface ModuleConstantMetadataV6 extends Struct { } /** ModuleConstantMetadataV6 */ -export type ModuleConstantMetadataV7 = ModuleConstantMetadataV6; +export interface ModuleConstantMetadataV7 extends ModuleConstantMetadataV6 {} /** Struct */ export interface ModuleMetadataV0 extends Struct { @@ -273,10 +273,10 @@ export interface OuterDispatchMetadataV0 extends Struct { } /** Vec */ -export type OuterEventEventMetadataEventsV0 = Vec; +export interface OuterEventEventMetadataEventsV0 extends Vec {} -/** [Text, OuterEventEventMetadataEventsV0] & Codec */ -export type OuterEventEventMetadataV0 = [Text, OuterEventEventMetadataEventsV0] & Codec; +/** ITuple<[Text, OuterEventEventMetadataEventsV0]> */ +export interface OuterEventEventMetadataV0 extends ITuple<[Text, OuterEventEventMetadataEventsV0]> {} /** Struct */ export interface OuterEventMetadataV0 extends Struct { @@ -287,25 +287,25 @@ export interface OuterEventMetadataV0 extends Struct { } /** Type */ -export type PlainTypeV0 = Type; +export interface PlainTypeV0 extends Type {} /** Type */ -export type PlainTypeV2 = Type; +export interface PlainTypeV2 extends Type {} /** Type */ -export type PlainTypeV3 = Type; +export interface PlainTypeV3 extends Type {} /** Type */ -export type PlainTypeV4 = Type; +export interface PlainTypeV4 extends Type {} /** Type */ -export type PlainTypeV5 = Type; +export interface PlainTypeV5 extends Type {} /** Type */ -export type PlainTypeV6 = Type; +export interface PlainTypeV6 extends Type {} /** Type */ -export type PlainTypeV7 = Type; +export interface PlainTypeV7 extends Type {} /** Struct */ export interface RuntimeModuleMetadataV0 extends Struct { @@ -318,10 +318,10 @@ export interface RuntimeModuleMetadataV0 extends Struct { } /** StorageFunctionModifierV5 */ -export type StorageEntryModifierV6 = StorageFunctionModifierV5; +export interface StorageEntryModifierV6 extends StorageFunctionModifierV5 {} /** StorageEntryModifierV6 */ -export type StorageEntryModifierV7 = StorageEntryModifierV6; +export interface StorageEntryModifierV7 extends StorageEntryModifierV6 {} /** Struct */ export interface StorageFunctionMetadataV0 extends Struct { @@ -338,7 +338,7 @@ export interface StorageFunctionMetadataV0 extends Struct { } /** StorageFunctionMetadataV0 */ -export type StorageFunctionMetadataV1 = StorageFunctionMetadataV0; +export interface StorageFunctionMetadataV1 extends StorageFunctionMetadataV0 {} /** Enum */ export interface StorageFunctionModifierV0 extends Enum { @@ -351,19 +351,19 @@ export interface StorageFunctionModifierV0 extends Enum { } /** StorageFunctionModifierV0 */ -export type StorageFunctionModifierV1 = StorageFunctionModifierV0; +export interface StorageFunctionModifierV1 extends StorageFunctionModifierV0 {} /** StorageFunctionModifierV1 */ -export type StorageFunctionModifierV2 = StorageFunctionModifierV1; +export interface StorageFunctionModifierV2 extends StorageFunctionModifierV1 {} /** StorageFunctionModifierV2 */ -export type StorageFunctionModifierV3 = StorageFunctionModifierV2; +export interface StorageFunctionModifierV3 extends StorageFunctionModifierV2 {} /** StorageFunctionModifierV3 */ -export type StorageFunctionModifierV4 = StorageFunctionModifierV3; +export interface StorageFunctionModifierV4 extends StorageFunctionModifierV3 {} /** StorageFunctionModifierV4 */ -export type StorageFunctionModifierV5 = StorageFunctionModifierV4; +export interface StorageFunctionModifierV5 extends StorageFunctionModifierV4 {} /** Enum */ export interface StorageFunctionTypeV0 extends Enum { @@ -378,7 +378,7 @@ export interface StorageFunctionTypeV0 extends Enum { } /** StorageFunctionTypeV0 */ -export type StorageFunctionTypeV1 = StorageFunctionTypeV0; +export interface StorageFunctionTypeV1 extends StorageFunctionTypeV0 {} /** Struct */ export interface StorageMetadataV0 extends Struct { diff --git a/packages/types/src/interfaces/offences/types.ts b/packages/types/src/interfaces/offences/types.ts index e2e63e1dda..b04ffc46f6 100644 --- a/packages/types/src/interfaces/offences/types.ts +++ b/packages/types/src/interfaces/offences/types.ts @@ -7,8 +7,8 @@ import { Bytes } from '../../primitive'; import { AccountId, Hash } from '../runtime'; import { IdentificationTuple } from '../session'; -/** Uint8Array & Codec */ -export type Kind = Uint8Array & Codec; +/** Uint8Array, Codec */ +export interface Kind extends Uint8Array, Codec {} /** Struct */ export interface OffenceDetails extends Struct { @@ -19,13 +19,13 @@ export interface OffenceDetails extends Struct { } /** IdentificationTuple */ -export type Offender = IdentificationTuple; +export interface Offender extends IdentificationTuple {} /** Bytes */ -export type OpaqueTimeSlot = Bytes; +export interface OpaqueTimeSlot extends Bytes {} /** AccountId */ -export type Reporter = AccountId; +export interface Reporter extends AccountId {} /** Hash */ -export type ReportIdOf = Hash; +export interface ReportIdOf extends Hash {} diff --git a/packages/types/src/interfaces/parachains/types.ts b/packages/types/src/interfaces/parachains/types.ts index fb7ffc49eb..7fc72cae61 100644 --- a/packages/types/src/interfaces/parachains/types.ts +++ b/packages/types/src/interfaces/parachains/types.ts @@ -1,7 +1,7 @@ // Auto-generated via `yarn build:interfaces`, do not edit /* eslint-disable @typescript-eslint/no-empty-interface */ -import { Codec } from '../../types'; +import { ITuple } from '../../types'; import { Enum, Struct, Vec } from '../../codec'; import { Bytes, u32, u64 } from '../../primitive'; import { AccountId, BalanceOf, BlockNumber, Hash, Signature } from '../runtime'; @@ -15,10 +15,10 @@ export interface AttestedCandidate extends Struct { } /** u32 */ -export type AuctionIndex = u32; +export interface AuctionIndex extends u32 {} -/** [AccountId, u64] & Codec */ -export type BalanceUpload = [AccountId, u64] & Codec; +/** ITuple<[AccountId, u64]> */ +export interface BalanceUpload extends ITuple<[AccountId, u64]> {} /** Enum */ export interface Bidder extends Enum { @@ -53,13 +53,13 @@ export interface CandidateReceipt extends Struct { } /** Signature */ -export type CollatorSignature = Signature; +export interface CollatorSignature extends Signature {} -/** [ParaId, Hash] & Codec */ -export type EgressQueueRoot = [ParaId, Hash] & Codec; +/** ITuple<[ParaId, Hash]> */ +export interface EgressQueueRoot extends ITuple<[ParaId, Hash]> {} /** Bytes */ -export type HeadData = Bytes; +export interface HeadData extends Bytes {} /** Enum */ export interface IncomingParachain extends Enum { @@ -94,10 +94,10 @@ export interface IncomingParachainFixed extends Struct { } /** BlockNumber */ -export type LeasePeriod = BlockNumber; +export interface LeasePeriod extends BlockNumber {} /** LeasePeriod */ -export type LeasePeriodOf = LeasePeriod; +export interface LeasePeriodOf extends LeasePeriod {} /** Struct */ export interface NewBidder extends Struct { @@ -116,10 +116,10 @@ export interface ParachainDispatchOrigin extends Enum { } /** u32 */ -export type ParaId = u32; +export interface ParaId extends u32 {} /** ParaId */ -export type ParaIdOf = ParaId; +export interface ParaIdOf extends ParaId {} /** Enum */ export interface SlotRange extends Enum { @@ -146,7 +146,7 @@ export interface SlotRange extends Enum { } /** u32 */ -export type SubId = u32; +export interface SubId extends u32 {} /** Struct */ export interface UpwardMessage extends Struct { @@ -157,7 +157,7 @@ export interface UpwardMessage extends Struct { } /** u32 */ -export type ValidatorIndex = u32; +export interface ValidatorIndex extends u32 {} /** Enum */ export interface ValidityAttestation extends Enum { @@ -173,11 +173,11 @@ export interface ValidityAttestation extends Enum { readonly asExplicit: CollatorSignature; } -/** [ValidatorIndex, ValidityAttestation] & Codec */ -export type ValidityVote = [ValidatorIndex, ValidityAttestation] & Codec; +/** ITuple<[ValidatorIndex, ValidityAttestation]> */ +export interface ValidityVote extends ITuple<[ValidatorIndex, ValidityAttestation]> {} /** Vec */ -export type WinningData = Vec; +export interface WinningData extends Vec {} -/** [AccountId, ParaIdOf, BalanceOf] & Codec */ -export type WinningDataEntry = [AccountId, ParaIdOf, BalanceOf] & Codec; +/** ITuple<[AccountId, ParaIdOf, BalanceOf]> */ +export interface WinningDataEntry extends ITuple<[AccountId, ParaIdOf, BalanceOf]> {} diff --git a/packages/types/src/interfaces/rpc/types.ts b/packages/types/src/interfaces/rpc/types.ts index 369a9ab93e..d34f337e24 100644 --- a/packages/types/src/interfaces/rpc/types.ts +++ b/packages/types/src/interfaces/rpc/types.ts @@ -1,13 +1,13 @@ // Auto-generated via `yarn build:interfaces`, do not edit /* eslint-disable @typescript-eslint/no-empty-interface */ -import { Codec } from '../../types'; +import { Codec, ITuple } from '../../types'; import { Enum, Option, Struct, Vec } from '../../codec'; import { Bytes, StorageData, StorageKey, Text, bool, u32, u64, u8 } from '../../primitive'; import { BlockNumber, Hash } from '../runtime'; -/** Uint8Array & Codec */ -export type ApiId = Uint8Array & Codec; +/** Uint8Array, Codec */ +export interface ApiId extends Uint8Array, Codec {} /** Struct */ export interface ChainProperties extends Struct { @@ -65,8 +65,8 @@ export interface Health extends Struct { readonly shouldHavePeers: bool; } -/** [StorageKey, Option] & Codec */ -export type KeyValueOption = [StorageKey, Option] & Codec; +/** ITuple<[StorageKey, Option]> */ +export interface KeyValueOption extends ITuple<[StorageKey, Option]> {} /** Struct */ export interface NetworkState extends Struct { @@ -112,8 +112,8 @@ export interface RuntimeVersion extends Struct { readonly apis: Vec; } -/** [ApiId, u32] & Codec */ -export type RuntimeVersionApi = [ApiId, u32] & Codec; +/** ITuple<[ApiId, u32]> */ +export interface RuntimeVersionApi extends ITuple<[ApiId, u32]> {} /** Struct */ export interface StorageChangeSet extends Struct { diff --git a/packages/types/src/interfaces/runtime/types.ts b/packages/types/src/interfaces/runtime/types.ts index 284af89bf1..dcf4bc1430 100644 --- a/packages/types/src/interfaces/runtime/types.ts +++ b/packages/types/src/interfaces/runtime/types.ts @@ -1,90 +1,90 @@ // Auto-generated via `yarn build:interfaces`, do not edit /* eslint-disable @typescript-eslint/no-empty-interface */ -import { Codec } from '../../types'; +import { Codec, ITuple } from '../../types'; import { Compact, Struct } from '../../codec'; import { Bytes, Fixed64, GenericAccountId, GenericAccountIndex, GenericAddress, GenericBlock, GenericCall, GenericConsensusEngineId, GenericDigest, GenericDigestItem, GenericExtrinsic, GenericExtrinsicEra, GenericExtrinsicPayload, GenericExtrinsicPayloadUnknown, GenericExtrinsicPayloadV1, GenericExtrinsicPayloadV2, GenericExtrinsicPayloadV3, GenericExtrinsicUnknown, GenericExtrinsicV1, GenericExtrinsicV2, GenericExtrinsicV3, GenericImmortalEra, GenericMortalEra, GenericOrigin, GenericSignerPayload, H256, H512, Null, StorageData, StorageKey, u128, u32, u64 } from '../../primitive'; /** GenericAccountId */ -export type AccountId = GenericAccountId; +export interface AccountId extends GenericAccountId {} /** AccountId */ -export type AccountIdOf = AccountId; +export interface AccountIdOf extends AccountId {} /** GenericAccountIndex */ -export type AccountIndex = GenericAccountIndex; +export interface AccountIndex extends GenericAccountIndex {} /** GenericAddress */ -export type Address = GenericAddress; +export interface Address extends GenericAddress {} /** u32 */ -export type AssetId = u32; +export interface AssetId extends u32 {} /** u128 */ -export type Balance = u128; +export interface Balance extends u128 {} /** Balance */ -export type BalanceOf = Balance; +export interface BalanceOf extends Balance {} /** GenericBlock */ -export type Block = GenericBlock; +export interface Block extends GenericBlock {} /** u32 */ -export type BlockNumber = u32; +export interface BlockNumber extends u32 {} /** GenericCall */ -export type Call = GenericCall; +export interface Call extends GenericCall {} -/** [ConsensusEngineId, Bytes] & Codec */ -export type Consensus = [ConsensusEngineId, Bytes] & Codec; +/** ITuple<[ConsensusEngineId, Bytes]> */ +export interface Consensus extends ITuple<[ConsensusEngineId, Bytes]> {} /** GenericConsensusEngineId */ -export type ConsensusEngineId = GenericConsensusEngineId; +export interface ConsensusEngineId extends GenericConsensusEngineId {} /** GenericDigest */ -export type Digest = GenericDigest; +export interface Digest extends GenericDigest {} /** GenericDigestItem */ -export type DigestItem = GenericDigestItem; +export interface DigestItem extends GenericDigestItem {} /** Signature */ -export type Ed25519Signature = Signature; +export interface Ed25519Signature extends Signature {} /** GenericExtrinsic */ -export type Extrinsic = GenericExtrinsic; +export interface Extrinsic extends GenericExtrinsic {} /** GenericExtrinsicEra */ -export type ExtrinsicEra = GenericExtrinsicEra; +export interface ExtrinsicEra extends GenericExtrinsicEra {} /** GenericExtrinsicPayload */ -export type ExtrinsicPayload = GenericExtrinsicPayload; +export interface ExtrinsicPayload extends GenericExtrinsicPayload {} /** GenericExtrinsicPayloadUnknown */ -export type ExtrinsicPayloadUnknown = GenericExtrinsicPayloadUnknown; +export interface ExtrinsicPayloadUnknown extends GenericExtrinsicPayloadUnknown {} /** GenericExtrinsicPayloadV1 */ -export type ExtrinsicPayloadV1 = GenericExtrinsicPayloadV1; +export interface ExtrinsicPayloadV1 extends GenericExtrinsicPayloadV1 {} /** GenericExtrinsicPayloadV2 */ -export type ExtrinsicPayloadV2 = GenericExtrinsicPayloadV2; +export interface ExtrinsicPayloadV2 extends GenericExtrinsicPayloadV2 {} /** GenericExtrinsicPayloadV3 */ -export type ExtrinsicPayloadV3 = GenericExtrinsicPayloadV3; +export interface ExtrinsicPayloadV3 extends GenericExtrinsicPayloadV3 {} /** GenericExtrinsicUnknown */ -export type ExtrinsicUnknown = GenericExtrinsicUnknown; +export interface ExtrinsicUnknown extends GenericExtrinsicUnknown {} /** GenericExtrinsicV1 */ -export type ExtrinsicV1 = GenericExtrinsicV1; +export interface ExtrinsicV1 extends GenericExtrinsicV1 {} /** GenericExtrinsicV2 */ -export type ExtrinsicV2 = GenericExtrinsicV2; +export interface ExtrinsicV2 extends GenericExtrinsicV2 {} /** GenericExtrinsicV3 */ -export type ExtrinsicV3 = GenericExtrinsicV3; +export interface ExtrinsicV3 extends GenericExtrinsicV3 {} /** H256 */ -export type Hash = H256; +export interface Hash extends H256 {} /** Struct */ export interface Header extends Struct { @@ -101,55 +101,55 @@ export interface Header extends Struct { } /** GenericImmortalEra */ -export type ImmortalEra = GenericImmortalEra; +export interface ImmortalEra extends GenericImmortalEra {} /** u32 */ -export type Index = u32; +export interface Index extends u32 {} /** Bytes */ -export type Justification = Bytes; +export interface Justification extends Bytes {} /** u32 */ -export type KeyTypeId = u32; +export interface KeyTypeId extends u32 {} -/** [StorageKey, StorageData] & Codec */ -export type KeyValue = [StorageKey, StorageData] & Codec; +/** ITuple<[StorageKey, StorageData]> */ +export interface KeyValue extends ITuple<[StorageKey, StorageData]> {} -/** Uint8Array & Codec */ -export type LockIdentifier = Uint8Array & Codec; +/** Uint8Array, Codec */ +export interface LockIdentifier extends Uint8Array, Codec {} /** u64 */ -export type Moment = u64; +export interface Moment extends u64 {} /** GenericMortalEra */ -export type MortalEra = GenericMortalEra; +export interface MortalEra extends GenericMortalEra {} /** GenericOrigin */ -export type Origin = GenericOrigin; +export interface Origin extends GenericOrigin {} /** u32 */ -export type Perbill = u32; +export interface Perbill extends u32 {} /** u32 */ -export type Permill = u32; +export interface Permill extends u32 {} /** Null */ -export type Phantom = Null; +export interface Phantom extends Null {} /** Null */ -export type PhantomData = Null; +export interface PhantomData extends Null {} -/** [ConsensusEngineId, Bytes] & Codec */ -export type PreRuntime = [ConsensusEngineId, Bytes] & Codec; +/** ITuple<[ConsensusEngineId, Bytes]> */ +export interface PreRuntime extends ITuple<[ConsensusEngineId, Bytes]> {} -/** [ConsensusEngineId, Bytes] & Codec */ -export type Seal = [ConsensusEngineId, Bytes] & Codec; +/** ITuple<[ConsensusEngineId, Bytes]> */ +export interface Seal extends ITuple<[ConsensusEngineId, Bytes]> {} -/** [u64, Signature] & Codec */ -export type SealV0 = [u64, Signature] & Codec; +/** ITuple<[u64, Signature]> */ +export interface SealV0 extends ITuple<[u64, Signature]> {} /** H512 */ -export type Signature = H512; +export interface Signature extends H512 {} /** Struct */ export interface SignedBlock extends Struct { @@ -160,16 +160,16 @@ export interface SignedBlock extends Struct { } /** GenericSignerPayload */ -export type SignerPayload = GenericSignerPayload; +export interface SignerPayload extends GenericSignerPayload {} /** Signature */ -export type Sr25519Signature = Signature; +export interface Sr25519Signature extends Signature {} /** AccountId */ -export type ValidatorId = AccountId; +export interface ValidatorId extends AccountId {} /** u32 */ -export type Weight = u32; +export interface Weight extends u32 {} /** Fixed64 */ -export type WeightMultiplier = Fixed64; +export interface WeightMultiplier extends Fixed64 {} diff --git a/packages/types/src/interfaces/session/types.ts b/packages/types/src/interfaces/session/types.ts index 409f720961..1fd6c77d94 100644 --- a/packages/types/src/interfaces/session/types.ts +++ b/packages/types/src/interfaces/session/types.ts @@ -1,25 +1,25 @@ // Auto-generated via `yarn build:interfaces`, do not edit /* eslint-disable @typescript-eslint/no-empty-interface */ -import { Codec } from '../../types'; +import { ITuple } from '../../types'; import { u32 } from '../../primitive'; import { AccountId, ValidatorId } from '../runtime'; import { Exposure } from '../staking'; /** Exposure */ -export type FullIdentification = Exposure; +export interface FullIdentification extends Exposure {} -/** [ValidatorId, FullIdentification] & Codec */ -export type IdentificationTuple = [ValidatorId, FullIdentification] & Codec; +/** ITuple<[ValidatorId, FullIdentification]> */ +export interface IdentificationTuple extends ITuple<[ValidatorId, FullIdentification]> {} /** SessionKeysSubstrate */ -export type Keys = SessionKeysSubstrate; +export interface Keys extends SessionKeysSubstrate {} /** u32 */ -export type SessionIndex = u32; +export interface SessionIndex extends u32 {} -/** [AccountId, AccountId, AccountId, AccountId] & Codec */ -export type SessionKeysPolkadot = [AccountId, AccountId, AccountId, AccountId] & Codec; +/** ITuple<[AccountId, AccountId, AccountId, AccountId]> */ +export interface SessionKeysPolkadot extends ITuple<[AccountId, AccountId, AccountId, AccountId]> {} -/** [AccountId, AccountId, AccountId] & Codec */ -export type SessionKeysSubstrate = [AccountId, AccountId, AccountId] & Codec; +/** ITuple<[AccountId, AccountId, AccountId]> */ +export interface SessionKeysSubstrate extends ITuple<[AccountId, AccountId, AccountId]> {} diff --git a/packages/types/src/interfaces/staking/types.ts b/packages/types/src/interfaces/staking/types.ts index 22ab99230e..0217f51588 100644 --- a/packages/types/src/interfaces/staking/types.ts +++ b/packages/types/src/interfaces/staking/types.ts @@ -6,7 +6,7 @@ import { u32 } from '../../primitive'; import { AccountId, Balance, BlockNumber, Moment } from '../runtime'; /** u32 */ -export type EraIndex = u32; +export interface EraIndex extends u32 {} /** Struct */ export interface EraPoints extends Struct { @@ -53,10 +53,10 @@ export interface IndividualExposure extends Struct { } /** Moment */ -export type MomentOf = Moment; +export interface MomentOf extends Moment {} /** u32 */ -export type Points = u32; +export interface Points extends u32 {} /** Enum */ export interface RewardDestination extends Enum { diff --git a/packages/types/src/interfaces/system/types.ts b/packages/types/src/interfaces/system/types.ts index b977288920..7dc4466d13 100644 --- a/packages/types/src/interfaces/system/types.ts +++ b/packages/types/src/interfaces/system/types.ts @@ -7,7 +7,7 @@ import { Bytes, GenericEvent, u32, u8 } from '../../primitive'; import { Digest, Hash } from '../runtime'; /** Digest */ -export type DigestOf = Digest; +export interface DigestOf extends Digest {} /** Struct */ export interface DispatchError extends Struct { @@ -18,13 +18,13 @@ export interface DispatchError extends Struct { } /** GenericEvent */ -export type Event = GenericEvent; +export interface Event extends GenericEvent {} -/** Uint8Array & Codec */ -export type EventId = Uint8Array & Codec; +/** Uint8Array, Codec */ +export interface EventId extends Uint8Array, Codec {} /** u32 */ -export type EventIndex = u32; +export interface EventIndex extends u32 {} /** Struct */ export interface EventRecord extends Struct { @@ -45,7 +45,7 @@ export interface EventRecord0to76 extends Struct { } /** Bytes */ -export type Key = Bytes; +export interface Key extends Bytes {} /** Enum */ export interface Phase extends Enum { diff --git a/packages/types/src/scripts/generateTypes/interfaceRegistry.ts b/packages/types/src/scripts/generateTypes/interfaceRegistry.ts new file mode 100644 index 0000000000..5639c0ea1a --- /dev/null +++ b/packages/types/src/scripts/generateTypes/interfaceRegistry.ts @@ -0,0 +1,71 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import fs from 'fs'; + +import * as definitions from '../../interfaces/definitions'; +import * as primitiveClasses from '../../primitive'; +import { + createImportCode, createImports, + FOOTER, + getDerivedTypes, + HEADER, + indent, + setImports +} from '../util'; + +// Generate `packages/types/src/interfaceRegistry.ts`, the registry of all interfaces +export default function generateInterfaceRegistry (): void { + console.log('Writing interfaceRegistry.ts'); + + const imports = createImports(); + + const primitives = Object + .keys(primitiveClasses) + .filter((name): boolean => !!name.indexOf('Generic')) + .reduce((accumulator, primitiveName): string => { + setImports(imports, [primitiveName]); + + return [ + accumulator, + getDerivedTypes(primitiveName, primitiveName, imports).map(indent(2)).join('\n') + ].join('\n'); + }, ''); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const srml = Object.entries(definitions).reduce((accumulator, [_defName, { types }]): string => { + setImports(imports, Object.keys(types)); + + return [ + accumulator, + ...Object.keys(types).map((type): string => + getDerivedTypes(type, (types as any)[type], imports).map(indent(2)).join('\n') + ) + ].join('\n'); + }, ''); + + const header = createImportCode(HEADER, [ + { + file: './codec', + types: Object.keys(imports.codecTypes).filter((name): boolean => name !== 'Tuple') + }, + { + file: './primitive', + types: Object.keys(imports.primitiveTypes) + }, + ...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({ + file: `./interfaces/${moduleName}`, + types: Object.keys(imports.localTypes[moduleName]) + })) + ]); + + const interfaceStart = 'export interface InterfaceRegistry {'; + const interfaceEnd = '\n}'; + + fs.writeFileSync( + 'packages/types/src/interfaceRegistry.ts', + header.concat(interfaceStart).concat(primitives).concat(srml).concat(interfaceEnd).concat(FOOTER) + , { flag: 'w' } + ); +} diff --git a/packages/types/src/scripts/generateTypes/query.ts b/packages/types/src/scripts/generateTypes/query.ts new file mode 100644 index 0000000000..7fa8552952 --- /dev/null +++ b/packages/types/src/scripts/generateTypes/query.ts @@ -0,0 +1,144 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import fs from 'fs'; +import { stringLowerFirst } from '@polkadot/util'; + +import { Metadata } from '../..'; +import { ModuleMetadataV7 } from '../../Metadata/v7/Metadata'; +import { StorageEntryMetadata } from '../../Metadata/v7/Storage'; +import staticData from '../../Metadata/v7/static'; +import { createImportCode, createImports, FOOTER, formatType, getSimilarTypes, HEADER, indent, setImports, TypeImports } from '../util'; + +// From a storage entry metadata, we return [args, returnType] +function entrySignature (storageEntry: StorageEntryMetadata, imports: TypeImports): [string, string] { + if (storageEntry.type.isPlainType) { + setImports(imports, [storageEntry.type.asType.toString()]); + + return ['', formatType(storageEntry.type.asType.toString(), imports)]; + } else if (storageEntry.type.isMap) { + // Find similar types of the `key` type + const similarTypes = getSimilarTypes(storageEntry.type.asMap.key.toString(), imports); + + setImports(imports, [ + ...similarTypes, + storageEntry.type.asMap.value.toString() + ]); + + return [ + `arg: ${similarTypes.map((type) => formatType(type, imports)).join(' | ')}`, + formatType(storageEntry.type.asMap.value.toString(), imports) + ]; + } else if (storageEntry.type.isDoubleMap) { + // Find similartypes of `key1` and `key2` types + const similarTypes1 = getSimilarTypes(storageEntry.type.asDoubleMap.key1.toString(), imports); + const similarTypes2 = getSimilarTypes(storageEntry.type.asDoubleMap.key2.toString(), imports); + + setImports(imports, [ + ...similarTypes1, + ...similarTypes2, + storageEntry.type.asDoubleMap.value.toString() + ]); + + const key1Types = similarTypes1.map((type) => formatType(type, imports)).join(' | '); + const key2Types = similarTypes2.map((type) => formatType(type, imports)).join(' | '); + + return [ + `key1: ${key1Types}, key2: ${key2Types}`, + formatType(storageEntry.type.asDoubleMap.value.toString(), imports) + ]; + } + + throw new Error(`entryArgs: Cannot parse args of entry ${storageEntry.name}`); +} + +// Generate types for one storage entry in a module +function generateEntry (storageEntry: StorageEntryMetadata, imports: TypeImports): string[] { + const [args, returnType] = entrySignature(storageEntry, imports); + + return [ + `${stringLowerFirst(storageEntry.name.toString())}: StorageEntryExact Observable<${returnType}>> & QueryableStorageEntry;` + // `${stringLowerFirst(storageEntry.name.toString())}: QueryableStorageEntry;` + ]; +} + +// Generate types for one module +function generateModule (modul: ModuleMetadataV7, imports: TypeImports): string[] { + if (modul.storage.isNone) { + return []; + } + + return [indent(4)(`${stringLowerFirst(modul.name.toString())}: {`)] + .concat(indent(6)('[index: string]: QueryableStorageEntry;')) + .concat( + modul.storage.unwrap().items + .reduce((acc, storageEntry): string[] => { + return acc.concat(generateEntry(storageEntry, imports).map(indent(6))); + }, [] as string[]) + .join('\n') + ) + .concat([indent(4)('};')]); +} + +// Generate `packages/types-jsonrpc/src/jsonrpc.types.ts` for a particular +// metadata +function generateForMeta (meta: Metadata): void { + console.log('Writing packages/api/src/query.types.ts'); + + // Inject all types so that metadata can use them + require('../../injector'); + + const imports = createImports(); // Will hold all needed imports + + const body = meta.asLatest.modules.reduce((acc, modul): string[] => { + const storageEntries = generateModule(modul, imports); + + return acc.concat(storageEntries); + }, [] as string[]); + + const header = createImportCode(HEADER, [ + { + file: 'rxjs', + types: ['Observable'] + }, + { + file: '@polkadot/types/codec', + types: Object.keys(imports.codecTypes).filter((name): boolean => name !== 'Tuple') + }, + { + file: '@polkadot/types', + types: Object.keys(imports.primitiveTypes) + }, + ...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({ + file: `@polkadot/types/interfaces/${moduleName}`, + types: Object.keys(imports.localTypes[moduleName]) + })), + { + file: '@polkadot/types/types', + types: Object.keys(imports.typesTypes) + } + ]); + + const interfaceStart = + [ + "declare module './types' {", + indent(2)('export interface QueryableStorageExact {\n') + ].join('\n'); + const interfaceEnd = `\n${indent(2)('}')}\n}`; + + fs.writeFileSync( + 'packages/api/src/query.types.ts', + header + .concat(interfaceStart) + .concat(body.join('\n')) + .concat(interfaceEnd) + .concat(FOOTER) + , { flag: 'w' } + ); +} + +// Call `generateForMeta()` with current static metadata +export default function generateQuery (): void { + return generateForMeta(new Metadata(staticData)); +} diff --git a/packages/types/src/scripts/generateTypes/rpc.ts b/packages/types/src/scripts/generateTypes/rpc.ts new file mode 100644 index 0000000000..3ed6058980 --- /dev/null +++ b/packages/types/src/scripts/generateTypes/rpc.ts @@ -0,0 +1,82 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import fs from 'fs'; + +import interfaces from '../../../../type-jsonrpc/src'; +import { createImportCode, createImports, FOOTER, getSimilarTypes, HEADER, setImports } from '../util'; + +// Generate `packages/types-jsonrpc/src/jsonrpc.types.ts` +export default function generateRpcTypes (): void { + console.log('Writing packages/rpc-core/jsonrpc.types.ts'); + + // Inject all types so that types-jsonrpc can use them + require('../../injector'); + + const imports = createImports(); + + const body = Object.keys(interfaces).sort().reduce((allSections, section): string[] => { + const allMethods = Object.keys(interfaces[section].methods).sort().map((key): string => { + const method = interfaces[section].methods[key]; + + setImports(imports, [method.type]); + + // FIXME These 2 are too hard to type, I give up + if (method.method === 'getStorage') { + setImports(imports, ['Codec']); + return ' getStorage(key: any, block?: Hash | Uint8Array | string): Observable;'; + } else if (method.method === 'subscribeStorage') { + return ' subscribeStorage(keys: any[]): Observable;'; + } + + const args = method.params.map((param): string => { + const similarTypes = getSimilarTypes(param.type, imports); + setImports(imports, [param.type, ...similarTypes]); + + return `${param.name}${param.isOptional ? '?' : ''}: ${similarTypes.join(' | ')}`; + }); + + return ` ${method.method}(${args.join(', ')}): Observable<${method.type}>;`; + }); + + return allSections.concat( + [ + ` ${section}: {`, + ...allMethods, + ' };' + ].join('\n') + ); + }, []).join('\n'); + + const header = createImportCode(HEADER, [ + { + file: 'rxjs', + types: ['Observable'] + }, + { + file: '@polkadot/types/codec', + types: Object.keys(imports.codecTypes).filter((name): boolean => name !== 'Tuple') + }, + { + file: '@polkadot/types', + types: Object.keys(imports.primitiveTypes) + }, + ...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({ + file: `@polkadot/types/interfaces/${moduleName}`, + types: Object.keys(imports.localTypes[moduleName]) + })), + { + file: '@polkadot/types/types', + types: Object.keys(imports.typesTypes) + } + ]); + const interfaceStart = 'export interface RpcInterface {\n'; + const interfaceEnd = '\n}'; + + fs.writeFileSync( + 'packages/rpc-core/src/jsonrpc.types.ts', + header.concat(interfaceStart).concat(body).concat(interfaceEnd).concat(FOOTER) + , { flag: 'w' } + ); +} diff --git a/packages/types/src/scripts/generateTypes/tsDef.ts b/packages/types/src/scripts/generateTypes/tsDef.ts new file mode 100644 index 0000000000..a9ba6c4737 --- /dev/null +++ b/packages/types/src/scripts/generateTypes/tsDef.ts @@ -0,0 +1,267 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { TypeDef, TypeDefInfo, TypeDefExtVecFixed } from '../../codec/types'; + +import fs from 'fs'; +import { isString, stringCamelCase, stringUpperFirst } from '@polkadot/util'; + +import { getTypeDef } from '../../codec/create'; +import * as definitions from '../../interfaces/definitions'; +import { + createImportCode, createImports, + exportInterface, exportType, + formatCompact, formatOption, formatTuple, formatVec, + FOOTER, HEADER, + setImports, TypeImports +} from '../util'; + +interface Imports extends TypeImports { + interfaces: [string, string][]; +} + +// helper to generate a `readonly : ;` getter +export function createGetter (name = '', type: string, imports: TypeImports, doc?: string): string { + setImports(imports, [type]); + return ` /** ${doc || type} */\n readonly ${name}: ${type};\n`; +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function errorUnhandled (def: TypeDef, imports: TypeImports): string { + throw new Error(`Generate: ${name}: Unhandled type ${TypeDefInfo[def.info]}`); +} + +function tsCompact ({ name: compactName, sub }: TypeDef, imports: TypeImports): string { + const def = (sub as TypeDef); + + setImports(imports, ['Compact']); + + switch (def.info) { + case TypeDefInfo.Plain: + setImports(imports, [def.type]); + return exportType(compactName, formatCompact(def.type)); + + default: + throw new Error(`Enum: ${compactName}: Unhandled type ${TypeDefInfo[def.info]}`); + } +} + +function tsEnum ({ name: enumName, sub }: TypeDef, imports: TypeImports): string { + setImports(imports, ['Enum']); + + const keys = (sub as TypeDef[]).map(({ info, name = '', type }, index): string => { + const getter = stringUpperFirst(stringCamelCase(name.replace(' ', '_'))); + const [enumType, asGetter] = type === 'Null' + ? ['', ''] + : [`(${type})`, createGetter(`as${getter}`, type, imports)]; + const isGetter = createGetter(`is${getter}`, 'boolean', imports, `${index}:: ${name}${enumType}`); + + switch (info) { + case TypeDefInfo.Plain: + case TypeDefInfo.Vec: + return `${isGetter}${asGetter}`; + + default: + throw new Error(`Enum: ${enumName}: Unhandled type ${TypeDefInfo[info]}`); + } + }); + + return exportInterface(enumName, 'Enum', keys.join('')); +} + +function tsOption ({ name: optionName, sub }: TypeDef, imports: TypeImports): string { + const def = (sub as TypeDef); + + setImports(imports, ['Option']); + + switch (def.info) { + case TypeDefInfo.Plain: + setImports(imports, [def.type]); + return exportType(optionName, formatOption(def.type)); + + default: + throw new Error(`Enum: ${optionName}: Unhandled type ${TypeDefInfo[def.info]}`); + } +} + +function tsPlain ({ name: plainName, type }: TypeDef, imports: TypeImports): string { + setImports(imports, [type]); + + return exportType(plainName, type); +} + +function _tsStructGetterType (structName: string | undefined, { info, sub, type }: TypeDef, imports: TypeImports): [string, string] { + let _type; + + switch (info) { + case TypeDefInfo.Compact: + _type = (sub as TypeDef).type; + + setImports(imports, ['Compact']); + + return [_type, formatCompact(_type)]; + + case TypeDefInfo.Option: + _type = (sub as TypeDef).type; + + setImports(imports, ['Option']); + + return [_type, formatOption(_type)]; + + case TypeDefInfo.Plain: + return [type, type]; + + case TypeDefInfo.Vec: + _type = (sub as TypeDef).type; + + setImports(imports, ['Vec']); + + return [_type, formatVec(_type)]; + + default: + throw new Error(`Struct: ${structName}: Unhandled type ${TypeDefInfo[info]}`); + } +} + +function tsSet ({ name: setName, sub }: TypeDef, imports: TypeImports): string { + setImports(imports, ['Set']); + + const types = (sub as TypeDef[]).map(({ name }): string => + createGetter(`is${name}`, 'boolean', imports) + ); + + return exportInterface(setName, 'Set', types.join('')); +} + +function tsStruct ({ name: structName, sub }: TypeDef, imports: TypeImports): string { + const keys = (sub as TypeDef[]).map((typedef): string => { + const [embedType, returnType] = _tsStructGetterType(structName, typedef, imports); + + setImports(imports, ['Struct', embedType]); + + return createGetter(typedef.name, returnType, imports); + }); + + return exportInterface(structName, 'Struct', keys.join('')); +} + +function _tsTupleGetterType (tupleName: string | undefined, { info, sub, type }: TypeDef, imports: TypeImports): string { + switch (info) { + case TypeDefInfo.Option: + setImports(imports, ['Option', (sub as TypeDef).type]); + + return type; + + case TypeDefInfo.Plain: + setImports(imports, [type]); + + return type; + + default: + throw new Error(`Struct: ${tupleName}: Unhandled type ${TypeDefInfo[info]}`); + } +} + +function tsTuple ({ name: tupleName, sub }: TypeDef, imports: TypeImports): string { + setImports(imports, ['ITuple']); + + const types = (sub as TypeDef[]).map((typedef): string => + _tsTupleGetterType(tupleName, typedef, imports) + ); + + return exportType(tupleName, formatTuple(types)); +} + +function tsVec ({ ext, info, name: vectorName, sub }: TypeDef, imports: TypeImports): string { + const type = info === TypeDefInfo.VecFixed + ? (ext as TypeDefExtVecFixed).type + : (sub as TypeDef).type; + + // FIXME This should be a VecFixed + // FIXME Technically Vec has length prefix, so for others this is not 100% + if (info === TypeDefInfo.VecFixed && type === 'u8') { + setImports(imports, ['Codec']); + + return exportType(vectorName, 'Uint8Array, Codec'); + } + + setImports(imports, ['Vec', type]); + + return exportType(vectorName, formatVec(type)); +} + +function generateInterfaces ({ types }: { types: Record }, imports: Imports): [string, string][] { + // handlers are defined externally to use - this means that when we do a + // `generators[typedef.info](...)` TS will show any unhandled types. Rather + // we are being explicit in having no handlers where we do not support (yet) + const generators = { + [TypeDefInfo.Compact]: tsCompact, + [TypeDefInfo.DoubleMap]: errorUnhandled, + [TypeDefInfo.Enum]: tsEnum, + [TypeDefInfo.Linkage]: errorUnhandled, + [TypeDefInfo.Null]: errorUnhandled, + [TypeDefInfo.Option]: tsOption, + [TypeDefInfo.Plain]: tsPlain, + [TypeDefInfo.Set]: tsSet, + [TypeDefInfo.Struct]: tsStruct, + [TypeDefInfo.Tuple]: tsTuple, + [TypeDefInfo.Vec]: tsVec, + [TypeDefInfo.VecFixed]: tsVec + }; + + return Object.entries(types).map(([name, type]): [string, string] => { + const def = getTypeDef(isString(type) ? type.toString() : JSON.stringify(type), name); + + return [name, generators[def.info](def, imports)]; + }); +} + +function generateTsDefFor (defName: string, { types }: { types: Record }): void { + const imports = { ...createImports({ types }), interfaces: [] } as Imports; + const interfaces = generateInterfaces({ types }, imports); + const sortedDefs = interfaces.sort((a, b): number => a[0].localeCompare(b[0])).map(([, definition]): string => definition).join('\n\n'); + + const header = createImportCode(HEADER, [ + { + file: '../../types', + types: Object.keys(imports.typesTypes) + }, + { + file: '../../codec', + types: Object.keys(imports.codecTypes).filter((name): boolean => name !== 'Tuple') + }, + { + file: '../../primitive', + types: Object.keys(imports.primitiveTypes) + }, + ...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({ + file: `../${moduleName}`, + types: Object.keys(imports.localTypes[moduleName]) + })) + ]); + + Object.entries(imports.localTypes).forEach(([moduleName, typeMap]): void => { + const types = Object.keys(typeMap).sort(); + + if (types.length) { + console.log(`\timport { ${types.join(', ')} } from '../${moduleName}'`); + } + }); + + fs.writeFileSync(`packages/types/src/interfaces/${defName}/types.ts`, header.concat(sortedDefs).concat(FOOTER), { flag: 'w' }); + fs.writeFileSync(`packages/types/src/interfaces/${defName}/index.ts`, HEADER.concat('export * from \'./types\';').concat(FOOTER), { flag: 'w' }); +} + +export default function generateTsDef (): void { + Object.entries(definitions).forEach(([defName, obj]): void => { + console.log(`Extracting interfaces for ${defName}`); + + generateTsDefFor(defName, obj); + }); + + console.log('Writing interfaces/types.ts'); + + fs.writeFileSync('packages/types/src/interfaces/types.ts', HEADER.concat(Object.keys(definitions).map((moduleName): string => `export * from './${moduleName}/types';`).join('\n')).concat(FOOTER), { flag: 'w' }); + fs.writeFileSync('packages/types/src/interfaces/index.ts', HEADER.concat('export * from \'./types\';').concat(FOOTER), { flag: 'w' }); +} diff --git a/packages/types/src/scripts/interfacesTs.ts b/packages/types/src/scripts/interfacesTs.ts index c954ca2ffe..5145692afb 100644 --- a/packages/types/src/scripts/interfacesTs.ts +++ b/packages/types/src/scripts/interfacesTs.ts @@ -2,551 +2,16 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { TypeDef, TypeDefInfo, TypeDefExtVecFixed } from '../codec/types'; -import { Constructor } from '../types'; - -import fs from 'fs'; -import { isString, stringCamelCase, stringUpperFirst } from '@polkadot/util'; - -import interfaces from '../../../type-jsonrpc/src'; -import { ClassOfUnsafe, getTypeDef } from '../codec/create'; -import * as codecClasses from '../codec'; -import AbstractInt from '../codec/AbstractInt'; -import UInt from '../codec/UInt'; -import Vec from '../codec/Vec'; -import * as definitions from '../interfaces/definitions'; -import * as primitiveClasses from '../primitive'; - -// these map all the codec and primitive types for import, see the TypeImports below. If -// we have an unseen type, it is `undefined`/`false`, if we need to import it, it is `true` -type TypeExist = Record; - -// local imports (between files), maps to this format -// { [moduleName]: { [typeName]: true } } -type LocalExist = Record; - -interface TypeImports { - codecTypes: TypeExist; // `import {} from '@polkadot/types/codec` - localTypes: LocalExist; - ownTypes: string[]; - primitiveTypes: TypeExist; // `import {} from '@polkadot/types/primitive` - typesTypes: TypeExist; // `import {} from '@polkadot/types/types` -} - -const HEADER = '// Auto-generated via `yarn build:interfaces`, do not edit\n/* eslint-disable @typescript-eslint/no-empty-interface */\n\n'; -const FOOTER = '\n'; - -// Maps the types as found to the source location. This is used to generate the -// imports in the output file, dep-duped and sorted -function setImports ({ codecTypes, localTypes, ownTypes, primitiveTypes, typesTypes }: TypeImports, types: string[]): void { - types.forEach((type): void => { - if (ownTypes.includes(type)) { - // do nothing - } else if (['Codec', 'IExtrinsic'].includes(type)) { - typesTypes[type] = true; - } else if ((codecClasses as any)[type]) { - codecTypes[type] = true; - } else if ((primitiveClasses as any)[type] || type === 'Metadata') { - primitiveTypes[type] = true; - } else { - // find this module inside the exports from the rest - const [moduleName] = Object.entries(definitions).find(([, { types }]): boolean => - Object.keys(types).includes(type) - ) || [null]; - - if (moduleName) { - localTypes[moduleName][type] = true; - } - } - }); -} - -// See if a class is child of another class -// FIMXE This could go in util some day -function isChildClass (Parent: Constructor, Child: Constructor): boolean { - // https://stackoverflow.com/questions/30993434/check-if-a-constructor-inherits-another-in-es6/30993664 - // eslint-disable-next-line no-prototype-builtins - return Parent === Child || Parent.isPrototypeOf(Child); -} - -function isCompactEncodable (Child: Constructor): boolean { - return isChildClass(UInt, Child); -} - -// helper to generate a `export interface extends {} -function exportInterface (name = '', base: string, body = ''): string { - return `/** ${base} */\nexport interface ${name} extends ${base} {${body.length ? '\n' : ''}${body}}`; -} - -// helper to create an `export = ` -function exportType (name = '', base: string): string { - return `/** ${base} */\nexport type ${name} = ${base};`; -} - -// helper to generate a `readonly : ;` getter -function createGetter (name = '', type: string, imports: TypeImports, doc?: string): string { - setImports(imports, [type]); - return ` /** ${doc || type} */\n readonly ${name}: ${type};\n`; -} - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function errorUnhandled (def: TypeDef, imports: TypeImports): string { - throw new Error(`Generate: ${name}: Unhandled type ${TypeDefInfo[def.info]}`); -} - -function tsCompact ({ name: compactName, sub }: TypeDef, imports: TypeImports): string { - const def = (sub as TypeDef); - - setImports(imports, ['Compact']); - - switch (def.info) { - case TypeDefInfo.Plain: - setImports(imports, [def.type]); - return exportType(compactName, `Compact<${def.type}>`); - - default: - throw new Error(`Enum: ${compactName}: Unhandled type ${TypeDefInfo[def.info]}`); - } -} - -function tsEnum ({ name: enumName, sub }: TypeDef, imports: TypeImports): string { - setImports(imports, ['Enum']); - - const keys = (sub as TypeDef[]).map(({ info, name = '', type }, index): string => { - const getter = stringUpperFirst(stringCamelCase(name.replace(' ', '_'))); - const [enumType, asGetter] = type === 'Null' - ? ['', ''] - : [`(${type})`, createGetter(`as${getter}`, type, imports)]; - const isGetter = createGetter(`is${getter}`, 'boolean', imports, `${index}:: ${name}${enumType}`); - - switch (info) { - case TypeDefInfo.Plain: - case TypeDefInfo.Vec: - return `${isGetter}${asGetter}`; - - default: - throw new Error(`Enum: ${enumName}: Unhandled type ${TypeDefInfo[info]}`); - } - }); - - return exportInterface(enumName, 'Enum', keys.join('')); -} - -function tsOption ({ name: optionName, sub }: TypeDef, imports: TypeImports): string { - const def = (sub as TypeDef); - - setImports(imports, ['Option']); - - switch (def.info) { - case TypeDefInfo.Plain: - setImports(imports, [def.type]); - return exportType(optionName, `Option<${def.type}>`); - - default: - throw new Error(`Enum: ${optionName}: Unhandled type ${TypeDefInfo[def.info]}`); - } -} - -function tsPlain ({ name: plainName, type }: TypeDef, imports: TypeImports): string { - setImports(imports, [type]); - - return exportType(plainName, type); -} - -function _tsStructGetterType (structName: string | undefined, { info, sub, type }: TypeDef, imports: TypeImports): [string, string] { - let _type; - - switch (info) { - case TypeDefInfo.Compact: - _type = (sub as TypeDef).type; - - setImports(imports, ['Compact']); - - return [_type, `Compact<${_type}>`]; - - case TypeDefInfo.Option: - _type = (sub as TypeDef).type; - - setImports(imports, ['Option']); - - return [_type, `Option<${_type}>`]; - - case TypeDefInfo.Plain: - return [type, type]; - - case TypeDefInfo.Vec: - _type = (sub as TypeDef).type; - - setImports(imports, ['Vec']); - - return [_type, `Vec<${_type}>`]; - - default: - throw new Error(`Struct: ${structName}: Unhandled type ${TypeDefInfo[info]}`); - } -} - -function tsSet ({ name: setName, sub }: TypeDef, imports: TypeImports): string { - setImports(imports, ['Set']); - - const types = (sub as TypeDef[]).map(({ name }): string => - createGetter(`is${name}`, 'boolean', imports) - ); - - return exportInterface(setName, 'Set', types.join('')); -} - -function tsStruct ({ name: structName, sub }: TypeDef, imports: TypeImports): string { - const keys = (sub as TypeDef[]).map((typedef): string => { - const [embedType, returnType] = _tsStructGetterType(structName, typedef, imports); - - setImports(imports, ['Struct', embedType]); - - return createGetter(typedef.name, returnType, imports); - }); - - return exportInterface(structName, 'Struct', keys.join('')); -} - -function _tsTupleGetterType (tupleName: string | undefined, { info, sub, type }: TypeDef, imports: TypeImports): string { - switch (info) { - case TypeDefInfo.Option: - setImports(imports, ['Option', (sub as TypeDef).type]); - - return type; - - case TypeDefInfo.Plain: - setImports(imports, [type]); - - return type; - - default: - throw new Error(`Struct: ${tupleName}: Unhandled type ${TypeDefInfo[info]}`); - } -} - -function tsTuple ({ name: tupleName, sub }: TypeDef, imports: TypeImports): string { - setImports(imports, ['Codec', 'Tuple']); - - const types = (sub as TypeDef[]).map((typedef): string => - _tsTupleGetterType(tupleName, typedef, imports) - ); - - return exportType(tupleName, `[${types.join(', ')}] & Codec`); -} - -function tsVec ({ ext, info, name: vectorName, sub }: TypeDef, imports: TypeImports): string { - const type = info === TypeDefInfo.VecFixed - ? (ext as TypeDefExtVecFixed).type - : (sub as TypeDef).type; - - // FIXME This should be a VecFixed - // FIXME Technically Vec has length prefix, so for others this is not 100% - if (info === TypeDefInfo.VecFixed && type === 'u8') { - setImports(imports, ['Codec']); - - return exportType(vectorName, 'Uint8Array & Codec'); - } - - setImports(imports, ['Vec', type]); - - return exportType(vectorName, `Vec<${type}>`); -} - -// creates the import lines -function createImportCode (header: string, checks: { file: string; types: string[] }[]): string { - return checks.reduce((result, { file, types }): string => { - if (types.length) { - result += `import { ${types.sort().join(', ')} } from '${file}';\n`; - } - - return result; - }, header) + '\n'; -} - -// From `T`, generate `Compact, Option, Vec` -function getDerivedTypes (type: string, primitiveName: string, imports: TypeImports, indent = 2): string { - // `primitiveName` represents the actual primitive type our type is mapped to - const isCompact = isCompactEncodable((primitiveClasses as any)[primitiveName]); - - setImports(imports, ['Option', 'Vec', isCompact ? 'Compact' : '']); - - return [ - `${type}: ${type};`, - isCompact - ? `'Compact<${type}>': Compact<${type}>;` - : undefined, - `'Option<${type}>': Option<${type}>;`, - `'Vec<${type}>': Vec<${type}>;` - ] - .filter((x): boolean => !!x) - .map((line): string => `${' '.repeat(indent)}${line}`) // Add indentation - .join('\n'); -} - -interface Imports extends TypeImports { - - interfaces: [string, string][]; -} - -// Create an Imports object, prefilled with types (if necessary) -function createImports ({ types }: { types: Record } = { types: {} }): Imports { - // handlers are defined externally to use - this means that when we do a - // `generators[typedef.info](...)` TS will show any unhandled types. Rather - // we are being explicit in having no handlers where we do not support (yet) - const generators = { - [TypeDefInfo.Compact]: tsCompact, - [TypeDefInfo.DoubleMap]: errorUnhandled, - [TypeDefInfo.Enum]: tsEnum, - [TypeDefInfo.Linkage]: errorUnhandled, - [TypeDefInfo.Null]: errorUnhandled, - [TypeDefInfo.Option]: tsOption, - [TypeDefInfo.Plain]: tsPlain, - [TypeDefInfo.Set]: tsSet, - [TypeDefInfo.Struct]: tsStruct, - [TypeDefInfo.Tuple]: tsTuple, - [TypeDefInfo.Vec]: tsVec, - [TypeDefInfo.VecFixed]: tsVec - }; - - const codecTypes: TypeExist = {}; - const localTypes: LocalExist = Object.keys(definitions).reduce((localTypes: Record, moduleName): Record => { - localTypes[moduleName] = {}; - - return localTypes; - }, {}); - const ownTypes = Object.keys(types); - const primitiveTypes: TypeExist = {}; - const typesTypes: TypeExist = {}; - const interfaces = Object.entries(types).map(([name, type]): [string, string] => { - const def = getTypeDef(isString(type) ? type.toString() : JSON.stringify(type), name); - - return [name, generators[def.info](def, { codecTypes, localTypes, ownTypes, primitiveTypes, typesTypes })]; - }); - - const imports = { codecTypes, localTypes, ownTypes, primitiveTypes, typesTypes, interfaces }; - - return imports; -} - -function generateTsDef (defName: string, { types }: { types: Record }): void { - const imports = createImports({ types }); - - const sortedDefs = imports.interfaces.sort((a, b): number => a[0].localeCompare(b[0])).map(([, definition]): string => definition).join('\n\n'); - const header = createImportCode(HEADER, [ - { - file: '../../types', - types: Object.keys(imports.typesTypes) - }, - { - file: '../../codec', - types: Object.keys(imports.codecTypes).filter((name): boolean => name !== 'Tuple') - }, - { - file: '../../primitive', - types: Object.keys(imports.primitiveTypes) - }, - ...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({ - file: `../${moduleName}`, - types: Object.keys(imports.localTypes[moduleName]) - })) - ]); - - Object.entries(imports.localTypes).forEach(([moduleName, typeMap]): void => { - const types = Object.keys(typeMap).sort(); - - if (types.length) { - console.log(`\timport { ${types.join(', ')} } from '../${moduleName}'`); - } - }); - - fs.writeFileSync(`packages/types/src/interfaces/${defName}/types.ts`, header.concat(sortedDefs).concat(FOOTER), { flag: 'w' }); - fs.writeFileSync(`packages/types/src/interfaces/${defName}/index.ts`, HEADER.concat('export * from \'./types\';').concat(FOOTER), { flag: 'w' }); -} - -// Generate `packages/types/src/interfaceRegistry.ts`, the registry of all interfaces -function generateInterfaceRegistry (): void { - const imports = createImports(); - - const primitives = Object - .keys(primitiveClasses) - .filter((name): boolean => !!name.indexOf('Generic')) - .reduce((accumulator, primitiveName): string => { - setImports(imports, [primitiveName]); - - return [ - accumulator, - getDerivedTypes(primitiveName, primitiveName, imports) - ].join('\n'); - }, ''); - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const srml = Object.entries(definitions).reduce((accumulator, [_defName, { types }]): string => { - setImports(imports, Object.keys(types)); - - return [ - accumulator, - ...Object.keys(types).map((type): string => - getDerivedTypes(type, (types as any)[type], imports, 2) - ) - ].join('\n'); - }, ''); - - const header = createImportCode(HEADER, [ - { - file: './codec', - types: Object.keys(imports.codecTypes).filter((name): boolean => name !== 'Tuple') - }, - { - file: './primitive', - types: Object.keys(imports.primitiveTypes) - }, - ...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({ - file: `./interfaces/${moduleName}`, - types: Object.keys(imports.localTypes[moduleName]) - })) - ]); - - const interfaceStart = 'export interface InterfaceRegistry {'; - const interfaceEnd = '\n}'; - - fs.writeFileSync( - 'packages/types/src/interfaceRegistry.ts', - header.concat(interfaceStart).concat(primitives).concat(srml).concat(interfaceEnd).concat(FOOTER) - , { flag: 'w' } - ); -} - -// Make types a little bit more flexible -// - if param instanceof AbstractInt, then param: u64 | Uint8array | string | number -// etc -function getSimilarTypes (imports: Imports, type: string): string[] { - const possibleTypes = [type]; - - if (type === 'Extrinsic') { - setImports(imports, ['IExtrinsic']); - return ['IExtrinsic']; - } - - if (isChildClass(Vec, ClassOfUnsafe(type))) { - return [`(${getSimilarTypes(imports, ((getTypeDef(type).sub) as TypeDef).type).join(' | ')})[]`]; - } - - // FIXME This is a hack, it's hard to correctly type StorageKeys in the - // current state - if (type === 'StorageKey') { - return ['any']; - } - - // Cannot get isChildClass of abstract class, but it works - if (isChildClass(AbstractInt as unknown as Constructor, ClassOfUnsafe(type))) { - possibleTypes.push('Uint8Array', 'number', 'string'); - } else if (isChildClass(Uint8Array, ClassOfUnsafe(type))) { - possibleTypes.push('Uint8Array', 'string'); - } else if (isChildClass(String, ClassOfUnsafe(type))) { - possibleTypes.push('string'); - } - - return possibleTypes; -} - -// Generate `packages/types-jsonrpc/src/jsonrpc.types.ts` -function generateRpcTypes (): void { - // Inject all types so that types-jsonrpc can use them - require('../injector'); - - // Get all imported types by types-jsonrpc - const allImportedTypes = Object.keys(interfaces).reduce((allSections, section): string[] => { - return allSections.concat( - ...Object.values(interfaces[section].methods).map((method): string[] => - [...method.params.map(({ type }): string => type), method.type]) - ); - }, []); - - const imports = createImports({ types: allImportedTypes }); - - const body = Object.keys(interfaces).sort().reduce((allSections, section): string[] => { - const allMethods = Object.keys(interfaces[section].methods).sort().map((key): string => { - const method = interfaces[section].methods[key]; - - // FIXME These 2 are too hard to type, I give up - if (method.method === 'getStorage') { - setImports(imports, ['Codec']); - return ' getStorage(key: any, block?: Hash | Uint8Array | string): Observable;'; - } else if (method.method === 'subscribeStorage') { - return ' subscribeStorage(keys: any[]): Observable;'; - } - - const args = method.params.map((param): string => { - const similarTypes = getSimilarTypes(imports, param.type); - setImports(imports, similarTypes); - - return `${param.name}${param.isOptional ? '?' : ''}: ${similarTypes.join(' | ')}`; - }); - - return ` ${method.method}(${args.join(', ')}): Observable<${method.type}>;`; - }); - - return allSections.concat( - [ - ` ${section}: {`, - ...allMethods, - ' };' - ].join('\n') - ); - }, []).join('\n'); - - const header = createImportCode(HEADER, [ - { - file: 'rxjs', - types: ['Observable'] - }, - { - file: '@polkadot/types/codec', - types: Object.keys(imports.codecTypes).filter((name): boolean => name !== 'Tuple') - }, - { - file: '@polkadot/types', - types: Object.keys(imports.primitiveTypes) - }, - ...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({ - file: `@polkadot/types/interfaces/${moduleName}`, - types: Object.keys(imports.localTypes[moduleName]) - })), - { - file: '@polkadot/types/types', - types: Object.keys(imports.typesTypes) - } - ]); - const interfaceStart = 'export interface RpcInterface {\n'; - const interfaceEnd = '\n}'; - - fs.writeFileSync( - 'packages/rpc-core/src/jsonrpc.types.ts', - header.concat(interfaceStart).concat(body).concat(interfaceEnd).concat(FOOTER) - , { flag: 'w' } - ); -} +import generateInterfaceRegistry from './generateTypes/interfaceRegistry'; +import generateQueryTypes from './generateTypes/query'; +import generateRpcTypes from './generateTypes/rpc'; +import generateTsDef from './generateTypes/tsDef'; function main (): void { - Object.entries(definitions).forEach(([defName, obj]): void => { - console.log(`Extracting interfaces for ${defName}`); - - generateTsDef(defName, obj); - }); - - console.log('Writing interfaces/types.ts'); - - fs.writeFileSync('packages/types/src/interfaces/types.ts', HEADER.concat(Object.keys(definitions).map((moduleName): string => `export * from './${moduleName}/types';`).join('\n')).concat(FOOTER), { flag: 'w' }); - fs.writeFileSync('packages/types/src/interfaces/index.ts', HEADER.concat('export * from \'./types\';').concat(FOOTER), { flag: 'w' }); - - console.log('Writing interfaceRegistry.ts'); - generateInterfaceRegistry(); - - console.log('Writing packages/rpc-core/jsonrpc.types.ts'); - + generateQueryTypes(); generateRpcTypes(); + generateTsDef(); } main(); diff --git a/packages/types/src/scripts/util/class.ts b/packages/types/src/scripts/util/class.ts new file mode 100644 index 0000000000..fb185b0463 --- /dev/null +++ b/packages/types/src/scripts/util/class.ts @@ -0,0 +1,19 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { Constructor } from '../../types'; + +import UInt from '../../codec/UInt'; + +// See if a class is child of another class +// FIMXE This could go in util some day +export function isChildClass (Parent: Constructor, Child: Constructor): boolean { + // https://stackoverflow.com/questions/30993434/check-if-a-constructor-inherits-another-in-es6/30993664 + // eslint-disable-next-line no-prototype-builtins + return Parent === Child || Parent.isPrototypeOf(Child); +} + +export function isCompactEncodable (Child: Constructor): boolean { + return isChildClass(UInt, Child); +} diff --git a/packages/types/src/scripts/util/derived.ts b/packages/types/src/scripts/util/derived.ts new file mode 100644 index 0000000000..821d3b9a9d --- /dev/null +++ b/packages/types/src/scripts/util/derived.ts @@ -0,0 +1,65 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { TypeDef } from '../../codec/types'; +import { Constructor } from '../../types'; + +import { isChildClass, isCompactEncodable } from './class'; +import { ClassOfUnsafe, getTypeDef } from '../../codec/create'; +import AbstractInt from '../../codec/AbstractInt'; +import Vec from '../../codec/Vec'; +import { formatCompact, formatOption, formatVec } from './formatting'; +import { setImports, TypeImports } from './imports'; +import * as primitiveClasses from '../../primitive'; + +// From `T`, generate `Compact, Option, Vec` +export function getDerivedTypes (type: string, primitiveName: string, imports: TypeImports): string[] { + // `primitiveName` represents the actual primitive type our type is mapped to + const isCompact = isCompactEncodable((primitiveClasses as any)[primitiveName]); + + setImports(imports, ['Option', 'Vec', isCompact ? 'Compact' : '']); + + return [ + `${type}: ${type};`, + isCompact + ? `'${formatCompact(type)}': ${formatCompact(type)};` + : '', + `'${formatOption(type)}': ${formatOption(type)};`, + `'${formatVec(type)}': ${formatVec(type)};` + ] + .filter((x): boolean => !!x); +} + +// Make types a little bit more flexible +// - if param instanceof AbstractInt, then param: u64 | Uint8array | string | number +// etc +export function getSimilarTypes (type: string, imports: TypeImports): string[] { + const possibleTypes = [type]; + + if (type === 'Extrinsic') { + setImports(imports, ['IExtrinsic']); + return ['IExtrinsic']; + } + + if (isChildClass(Vec, ClassOfUnsafe(type))) { + return [`(${getSimilarTypes(((getTypeDef(type).sub) as TypeDef).type, imports).join(' | ')})[]`]; + } + + // FIXME This is a hack, it's hard to correctly type StorageKeys in the + // current state + if (type === 'StorageKey') { + return ['any']; + } + + // Cannot get isChildClass of abstract class, but it works + if (isChildClass(AbstractInt as unknown as Constructor, ClassOfUnsafe(type))) { + possibleTypes.push('Uint8Array', 'number', 'string'); + } else if (isChildClass(Uint8Array, ClassOfUnsafe(type))) { + possibleTypes.push('Uint8Array', 'string'); + } else if (isChildClass(String, ClassOfUnsafe(type))) { + possibleTypes.push('string'); + } + + return possibleTypes; +} diff --git a/packages/types/src/scripts/util/formatting.spec.ts b/packages/types/src/scripts/util/formatting.spec.ts new file mode 100644 index 0000000000..0f8bc1f50f --- /dev/null +++ b/packages/types/src/scripts/util/formatting.spec.ts @@ -0,0 +1,11 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { indent } from './formatting'; + +describe('formatting', () => { + it('should indent correctly', () => { + expect(indent(2)('foo')).toBe(' foo'); + }); +}); diff --git a/packages/types/src/scripts/util/formatting.ts b/packages/types/src/scripts/util/formatting.ts new file mode 100644 index 0000000000..f3799701c5 --- /dev/null +++ b/packages/types/src/scripts/util/formatting.ts @@ -0,0 +1,111 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { TypeDef, TypeDefInfo } from '../../codec/types'; + +import { getTypeDef } from '../../codec/create'; +import { setImports, TypeImports } from './imports'; + +export const HEADER = '// Auto-generated via `yarn build:interfaces`, do not edit\n/* eslint-disable @typescript-eslint/no-empty-interface */\n\n'; +export const FOOTER = '\n'; + +// creates the import lines +export function createImportCode (header: string, checks: { file: string; types: string[] }[]): string { + return checks.reduce((result, { file, types }): string => { + if (types.length) { + result += `import { ${types.sort().join(', ')} } from '${file}';\n`; + } + + return result; + }, header) + '\n'; +} + +// helper to generate a `export interface extends {} +export function exportInterface (name = '', base: string, body = ''): string { + return `/** ${base} */\nexport interface ${name} extends ${base} {${body.length ? '\n' : ''}${body}}`; +} + +// helper to create an `export type = ` +// but since we don't want type alias (TS doesn't preserve names) we use +// interface here. +export function exportType (name = '', base: string): string { + return exportInterface(name, base); +} + +/** + * Given the inner `T`, return a `Compact` string + */ +export function formatCompact (inner: string): string { + return `Compact<${inner}>`; +} + +/** + * Given the inner `T`, return a `Option` string + */ +export function formatOption (inner: string): string { + return `Option<${inner}>`; +} + +/** + * Given the inners `T[]`, return a `ITuple<...T>` string + */ +export function formatTuple (inners: string[]): string { + return `ITuple<[${inners.join(', ')}]>`; +} + +/** + * Given the inner `T`, return a `Vec` string + */ +export function formatVec (inner: string): string { + return `Vec<${inner}>`; +} + +/** + * Correctly format a given type + */ +export function formatType (type: string, imports: TypeImports): string { + const typeDef = getTypeDef(type); + + switch (typeDef.info) { + case TypeDefInfo.Compact: { + return formatCompact(formatType((typeDef.sub as TypeDef).type, imports)); + } + case TypeDefInfo.Option: { + return formatOption(formatType((typeDef.sub as TypeDef).type, imports)); + } + case TypeDefInfo.Plain: { + return type; + } + case TypeDefInfo.Vec: { + return formatVec(formatType((typeDef.sub as TypeDef).type, imports)); + } + case TypeDefInfo.Tuple: { + setImports(imports, ['ITuple']); + + // `(a,b)` gets transformed into `ITuple<[a, b]>` + return formatTuple( + ((typeDef.sub as TypeDef[]) + .map((sub): string => formatType(sub.type, imports))) + ); + } + case TypeDefInfo.VecFixed: { + setImports(imports, ['U8a']); + + // `[u8, 32]` gets transformed into U8a + return 'U8a'; + } + default: { + throw new Error(`Cannot format ${type}.`); + } + } +} + +/** + * Indent a string with `n` spaces before. + */ +export function indent (n: number, char = ' '): (str: string) => string { + return function (str: string): string { + return `${char.repeat(n)}${str}`; + }; +} diff --git a/packages/types/src/scripts/util/imports.ts b/packages/types/src/scripts/util/imports.ts new file mode 100644 index 0000000000..3622e53759 --- /dev/null +++ b/packages/types/src/scripts/util/imports.ts @@ -0,0 +1,82 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import * as codecClasses from '../../codec'; +import { getTypeDef } from '../../codec/create'; +import { TypeDefInfo } from '../../codec/types'; +import * as definitions from '../../interfaces/definitions'; +import * as primitiveClasses from '../../primitive'; + +// these map all the codec and primitive types for import, see the TypeImports below. If +// we have an unseen type, it is `undefined`/`false`, if we need to import it, it is `true` +type TypeExist = Record; + +// local and absolute imports map to this format +// { [moduleName]: { [typeName]: true } } +type TypeExistMap = Record; + +export interface TypeImports { + codecTypes: TypeExist; // `import {} from '@polkadot/types/codec` + localTypes: TypeExistMap; // `import {} from '../something'` + ignoredTypes: string[]; // No need to import these types + primitiveTypes: TypeExist; // `import {} from '@polkadot/types/primitive` + typesTypes: TypeExist; // `import {} from '@polkadot/types/types` +} + +// Maps the types as found to the source location. This is used to generate the +// imports in the output file, dep-duped and sorted +export function setImports (imports: TypeImports, types: string[]): void { + const { codecTypes, localTypes, ignoredTypes, primitiveTypes, typesTypes } = imports; + + types.forEach((type): void => { + if (ignoredTypes.includes(type)) { + // do nothing + } else if (['Codec', 'IExtrinsic', 'ITuple'].includes(type)) { + typesTypes[type] = true; + } else if ((codecClasses as any)[type]) { + codecTypes[type] = true; + } else if ((primitiveClasses as any)[type] || type === 'Metadata') { + primitiveTypes[type] = true; + } else if (type.includes('<') || type.includes('(') || type.includes('[')) { + // If the type is a bit special (tuple, fixed u8, nested type...), then we + // need to parse it with `getTypeDef`. + const typeDef = getTypeDef(type); + setImports(imports, [TypeDefInfo[typeDef.info]]); + + // TypeDef.sub is a `TypeDef | TypeDef[]` + if (Array.isArray(typeDef.sub)) { + typeDef.sub.forEach((subType): void => setImports(imports, [subType.type])); + } else if (typeDef.sub) { + // typeDef.sub is a TypeDef in this case + setImports(imports, [typeDef.sub.type]); + } + } else { + // find this module inside the exports from the rest + const [moduleName] = Object.entries(definitions).find(([, { types }]): boolean => + Object.keys(types).includes(type) + ) || [null]; + + if (moduleName) { + localTypes[moduleName][type] = true; + } + } + }); +} + +// Create an Imports object, can be prefilled with `ignoredTypes` +export function createImports ({ types }: { types: Record } = { types: {} }): TypeImports { + const codecTypes: TypeExist = {}; + const localTypes: TypeExistMap = Object.keys(definitions).reduce((localTypes: Record, moduleName): Record => { + localTypes[moduleName] = {}; + + return localTypes; + }, {}); + const ignoredTypes = Object.keys(types); + const primitiveTypes: TypeExist = {}; + const typesTypes: TypeExist = {}; + + const imports = { codecTypes, localTypes, ignoredTypes, primitiveTypes, typesTypes }; + + return imports; +} diff --git a/packages/types/src/scripts/util/index.ts b/packages/types/src/scripts/util/index.ts new file mode 100644 index 0000000000..e0beb443b1 --- /dev/null +++ b/packages/types/src/scripts/util/index.ts @@ -0,0 +1,7 @@ +// Copyright 2017-2019 @polkadot/types authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +export * from './derived'; +export * from './formatting'; +export * from './imports'; diff --git a/packages/types/src/types.ts b/packages/types/src/types.ts index 21827ba926..1ef40adbea 100644 --- a/packages/types/src/types.ts +++ b/packages/types/src/types.ts @@ -154,6 +154,11 @@ export interface SignatureOptions { export type ArgsDef = Record; +// A type alias for [Type1, Type2] & Codec, representing a tuple (Type1, Type2) +// FIXME Implement this generic on Tuple.ts itself. +// eslint-disable-next-line @typescript-eslint/interface-name-prefix +export type ITuple = Sub & Codec + // eslint-disable-next-line @typescript-eslint/interface-name-prefix export interface IMethod extends Codec { readonly args: Codec[];