Compare commits

..
25 Commits
Author SHA1 Message Date
Github Actions 61d5dec63a [CI Skip] 0.98.1
skip-checks: true
2019-12-04 11:33:12 +00:00
Jaco Greeff 64a4bb2e17 0.98 (#1635) 2019-12-04 12:27:02 +01:00
Amaury Martiny f78bf9dde1 Remove as unknown (#1636)
* Remove some as unknowns

* Rename sanitize

* Remove file
2019-12-04 12:19:37 +01:00
Github Actions b7ba654e48 [CI Skip] 0.98.0-beta.10
skip-checks: true
2019-12-04 08:12:28 +00:00
Jaco Greeff 532a252fe0 Add missing metadata dep from types (#1634) 2019-12-04 09:06:03 +01:00
Github Actions 614cf4e484 [CI Skip] 0.98.0-beta.9
skip-checks: true
2019-12-03 22:39:25 +00:00
Amaury Martiny c576c689d0 Add correct typings when modifier is optional (#1632) 2019-12-03 23:32:31 +01:00
Github Actions d86cd94fe2 [CI Skip] 0.98.0-beta.8
skip-checks: true
2019-12-03 21:12:43 +00:00
Xiliang Chen 762b16ea13 make ts generate script more reusable (#1610)
* make ts generate script more reusable

* avoid use global definitions

* fix error

* fix formatting

* seems working
2019-12-03 22:04:41 +01:00
Github Actions 09a72c0f31 [CI Skip] 0.98.0-beta.7
skip-checks: true
2019-12-03 19:37:40 +00:00
Jaco Greeff eded5fede2 Add .entries() for map types (#1629) 2019-12-03 20:29:31 +01:00
Github Actions 704df82b1d [CI Skip] 0.98.0-beta.6
skip-checks: true
2019-12-03 14:05:52 +00:00
Caio 46efc10939 Add signAsync to SubmittableExtrinsic (#1626) 2019-12-03 14:58:18 +01:00
Github Actions 74cf8aa30c [CI Skip] 0.98.0-beta.5
skip-checks: true
2019-12-03 13:57:32 +00:00
Jaco Greeff 7a60ab81f8 Drop decorated export (#1628)
* Drop decorated export

* Fixup imports
2019-12-03 14:49:30 +01:00
Github Actions c1d7ca67d5 [CI Skip] 0.98.0-beta.4
skip-checks: true
2019-12-03 13:13:39 +00:00
Jaco Greeff 7e1eb0fab0 Drop circular Linkage deps (#1627)
* Drop circular Linkage deps

* Cleanup more circular deps

* IU8a interface
2019-12-03 14:05:50 +01:00
Github Actions af76d7fb04 [CI Skip] 0.98.0-beta.3
skip-checks: true
2019-12-03 12:10:16 +00:00
Jaco Greeff afbe072ad5 Optional preImage & Proposal for democracy 2019-12-03 13:01:13 +01:00
Github Actions d86c5be413 [CI Skip] 0.98.0-beta.2
skip-checks: true
2019-12-02 14:38:24 +00:00
Jaco Greeff a695d2a5b5 Sort members by backing (#1625) 2019-12-02 15:30:30 +01:00
Github Actions 1c087967d3 [CI Skip] 0.98.0-beta.1
skip-checks: true
2019-12-02 09:39:55 +00:00
Jaco Greeff 906732bcdc Add 6x to conviction (#1623)
* Add 6x to conviction

* Add derive.democracy.proposals

* Proposal decoding

* Don't return empty proposals

* Rework referendumInfo

* Update referendumInfo extraction
2019-12-02 10:32:20 +01:00
Github Actions c9352af81c [CI Skip] 0.98.0-beta.0
skip-checks: true
2019-11-29 15:10:54 +00:00
Jaco Greeff e2e8e3fedd Add received to vested total for available (#1621) 2019-11-29 16:03:17 +01:00
63 changed files with 638 additions and 425 deletions
+9
View File
@@ -1,3 +1,12 @@
# 0.98.1
- Make the TypeScript generation script mor re-usable (Thanks to @xlc)
- Add `.entries()` for all map-types, returning storage keys and values
- Add `.signAsync` to submittable extrinsics (Thanks to @c410-f3r)
- Cleanup circular references between internal dependencies
- Support for new Substrate democracy with preimages in derive
- Alignment of types with Substrate/Polkadot master branches
# 0.97.1
- **Breaking change** Add the passing on an explicit `Registry` to all calls to `createType` as well as all codec classes. If you are upgrading form an older version, use the [migration guide](UPGRADING.md) to walk through the changes required.
+1 -1
View File
@@ -5,7 +5,7 @@ This is an upgrade guide for users of the API. It does not attempt to detail eac
While we try to keep the user-facing interfaces as stable as possible, sometimes you just need to make additions to move forward and improve things down the road, as painful as they may be. Like you, we are also users of the API, and eat our own dog food - and as such, feel any pains introduced first.
## 0.97.1 (and newer), from 0.90.1 (and older)
## 0.97.1 (and newer)
The 0.97 series lays the groundwork to allow type registration to be ties to a specific chain and a specific Api instance. In the past, 2 Api instances in the same process would share types, which mean that you could not connect to 2 independent chains with different types. This is very problematic for Polkadot chains, where the idea is to connect to multiple chains.
+1 -1
View File
@@ -9,5 +9,5 @@
"packages": [
"packages/*"
],
"version": "0.97.1"
"version": "0.98.1"
}
+2 -1
View File
@@ -1,5 +1,5 @@
{
"version": "0.97.1",
"version": "0.98.1",
"private": true,
"engines": {
"yarn": "^1.10.1"
@@ -14,6 +14,7 @@
"scripts": {
"build": "yarn build:interfaces && polkadot-dev-build-ts",
"build:interfaces": "node packages/types/src/scripts/interfacesTsWrapper.js",
"circular": "madge --circular --extensions ts ./",
"docs": "node packages/types/src/scripts/MetadataMdWrapper.js && polkadot-dev-build-docs",
"chain:info": "node packages/types/src/scripts/extractChainWrapper.js",
"lint": "eslint --ext .js,.jsx,.ts,.tsx . && tsc --noEmit --pretty",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-contract",
"version": "0.97.1",
"version": "0.98.1",
"description": "Interfaces for interacting with contracts and contract ABIs",
"main": "index.js",
"keywords": [
@@ -27,6 +27,6 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
"dependencies": {
"@babel/runtime": "^7.7.4",
"@polkadot/types": "^0.97.1"
"@polkadot/types": "^0.98.1"
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-derive",
"version": "0.97.1",
"version": "0.98.1",
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
"main": "index.js",
"keywords": [
@@ -28,8 +28,8 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
"dependencies": {
"@babel/runtime": "^7.7.4",
"@polkadot/api": "^0.97.1",
"@polkadot/types": "^0.97.1"
"@polkadot/api": "^0.98.1",
"@polkadot/types": "^0.98.1"
},
"devDependencies": {
"@polkadot/keyring": "^1.7.1"
+2 -1
View File
@@ -46,7 +46,8 @@ function calcBalances (api: ApiInterfaceRx, [accountId, bestNumber, [freeBalance
// i.e. (balance >= 200 && balance >= 300) == (balance >= 300)
// ""
const floating = freeBalance.sub(lockedBalance);
const availableBalance = createType(api.registry, 'Balance', bnMax(new BN(0), isVesting && floating.gt(vestedBalance) ? vestedBalance : floating));
const extraReceived = isVesting ? freeBalance.sub(vestingTotal) : new BN(0);
const availableBalance = createType(api.registry, 'Balance', bnMax(new BN(0), isVesting && floating.gt(vestedBalance) ? vestedBalance.add(extraReceived) : floating));
return {
accountId,
@@ -2,6 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export * from './proposals';
export * from './referendumInfos';
export * from './referendums';
export * from './referendumVotesFor';
@@ -0,0 +1,75 @@
// Copyright 2017-2019 @polkadot/api-derive 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 { AccountId, Balance, BlockNumber, Hash, PropIndex } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveProposal } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Bytes, Option, Vec, createType } from '@polkadot/types';
import { memo } from '../util';
export type PreImage = Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>;
type Depositors = Option<ITuple<[Balance, Vec<AccountId>]>>;
export function proposals (api: ApiInterfaceRx): () => Observable<DeriveProposal[]> {
return memo((): Observable<DeriveProposal[]> =>
api.query.democracy
.publicProps<Vec<ITuple<[PropIndex, Hash, AccountId]>>>()
.pipe(
switchMap((proposals) =>
combineLatest([
of(proposals),
combineLatest(
...proposals.map(([, hash]) =>
api.query.democracy.preimages<PreImage>(hash)
)
)
])
),
switchMap(([proposals, preimages]) =>
combineLatest([
of(proposals),
of(preimages),
combineLatest(
...proposals.map(([index]) =>
api.query.democracy.depositOf<Depositors>(index)
)
)
])
),
map(([proposals, _preImages, _depositors]): DeriveProposal[] =>
proposals
.filter(([, , proposer], index): boolean =>
!!(_preImages[index]?.isSome) && !!(_depositors[index]?.isSome) && !proposer.isEmpty
)
.map(([propIndex, hash, proposer], index): DeriveProposal => {
const preImage = _preImages[index].unwrapOr(null);
const depositors = _depositors[index].unwrap();
return {
balance: depositors[0],
hash,
index: propIndex,
preimage: preImage
? {
at: preImage[3],
balance: preImage[2],
proposer: preImage[1]
}
: undefined,
proposal: preImage
? createType(api.registry, 'Proposal', preImage[0].toU8a(true))
: undefined,
proposer,
seconds: depositors[1]
};
})
)
)
);
}
@@ -3,36 +3,66 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ReferendumInfo } from '@polkadot/types/interfaces/democracy';
import { DerivedReferendum } from '../types';
import { PreImage } from './proposals';
import BN from 'bn.js';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option } from '@polkadot/types';
import { isNull } from '@polkadot/util';
import { Option, createType } from '@polkadot/types';
import { ReferendumInfoExtended } from '../type';
import { memo } from '../util';
export function constructInfo (api: ApiInterfaceRx, index: BN | number, optionInfo?: Option<ReferendumInfo>): Option<ReferendumInfoExtended> {
const info = optionInfo
? optionInfo.unwrapOr(null)
: null;
function constructInfo (api: ApiInterfaceRx, index: BN | number, _info: Option<ReferendumInfo>, _preimage?: PreImage): DerivedReferendum | null {
console.log(JSON.stringify(_info), JSON.stringify(_preimage));
return new Option<ReferendumInfoExtended>(
api.registry,
ReferendumInfoExtended,
isNull(info)
? null
: new ReferendumInfoExtended(api.registry, info, index)
const preImage = _preimage?.isSome
? _preimage.unwrap()
: null;
const info = _info.unwrapOr(null);
if (!info) {
return null;
}
return {
index: createType(api.registry, 'PropIndex', index),
info,
hash: info.proposalHash,
proposal: preImage
? createType(api.registry, 'Proposal', preImage[0].toU8a(true))
: undefined,
preimage: preImage
? {
at: preImage[3],
balance: preImage[2],
proposer: preImage[1]
}
: undefined
};
}
export function retrieveInfo (api: ApiInterfaceRx, index: BN | number, info: Option<ReferendumInfo>): Observable<DerivedReferendum | null> {
console.log(JSON.stringify(info));
return ((
info?.isSome
? api.query.democracy.preimages<PreImage>(info.unwrap().proposalHash)
: of(undefined)
) as Observable<PreImage | undefined>).pipe(
map((preimage?: PreImage): DerivedReferendum | null =>
constructInfo(api, index, info, preimage)
)
);
}
export function referendumInfo (api: ApiInterfaceRx): (index: BN | number) => Observable<Option<ReferendumInfoExtended>> {
return memo((index: BN | number): Observable<Option<ReferendumInfoExtended>> =>
export function referendumInfo (api: ApiInterfaceRx): (index: BN | number) => Observable<DerivedReferendum | null> {
return memo((index: BN | number): Observable<DerivedReferendum | null> =>
api.query.democracy.referendumInfoOf<Option<ReferendumInfo>>(index).pipe(
map((optionInfo): Option<ReferendumInfoExtended> =>
constructInfo(api, index, optionInfo)
switchMap((info): Observable<DerivedReferendum | null> =>
retrieveInfo(api, index, info)
)
));
)
);
}
@@ -3,28 +3,33 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ReferendumInfo } from '@polkadot/types/interfaces/democracy';
import { DerivedReferendum } from '../types';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option, Vec } from '@polkadot/types';
import { ReferendumInfoExtended } from '../type';
import { memo } from '../util';
import { constructInfo } from './referendumInfo';
import { retrieveInfo } from './referendumInfo';
export function referendumInfos (api: ApiInterfaceRx): (ids?: (BN | number)[]) => Observable<Option<ReferendumInfoExtended>[]> {
return memo((ids: (BN | number)[] = []): Observable<Option<ReferendumInfoExtended>[]> =>
export function referendumInfos (api: ApiInterfaceRx): (ids?: (BN | number)[]) => Observable<DerivedReferendum[]> {
return memo((ids: (BN | number)[] = []): Observable<DerivedReferendum[]> =>
(
!ids || !ids.length
? of([] as Option<ReferendumInfo>[])
: api.query.democracy.referendumInfoOf.multi(ids) as Observable<Vec<Option<ReferendumInfo>>>
).pipe(
map((infos): Option<ReferendumInfoExtended>[] =>
ids.map((id, index): Option<ReferendumInfoExtended> =>
constructInfo(api, id, infos[index])
switchMap((infos): Observable<(DerivedReferendum | null)[]> =>
combineLatest(
...ids.map((id, index): Observable<DerivedReferendum | null> =>
retrieveInfo(api, id, infos[index])
)
)
),
map((infos): DerivedReferendum[] =>
infos.filter((referendum): boolean => !!referendum) as DerivedReferendum[]
)
));
}
@@ -28,7 +28,7 @@ export function referendumVotesFor (api: ApiInterfaceRx): (referendumId: BN | nu
accountId,
balance: balances[index].votingBalance || createType(api.registry, 'Balance'),
vote: votes[index] || createType(api.registry, 'Vote')
} as unknown as DerivedReferendumVote))
} as DerivedReferendumVote))
)
));
}
@@ -3,23 +3,22 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ReferendumIndex } from '@polkadot/types/interfaces/democracy';
import { DerivedReferendum } from '../types';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option } from '@polkadot/types';
import { ReferendumInfoExtended } from '../type';
import { memo } from '../util';
export function referendums (api: ApiInterfaceRx): () => Observable<Option<ReferendumInfoExtended>[]> {
return memo((): Observable<Option<ReferendumInfoExtended>[]> =>
export function referendums (api: ApiInterfaceRx): () => Observable<DerivedReferendum[]> {
return memo((): Observable<DerivedReferendum[]> =>
api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
api.query.democracy.nextTally,
api.query.democracy.referendumCount
]).pipe(
switchMap(([nextTally, referendumCount]): Observable<Option<ReferendumInfoExtended>[]> =>
switchMap(([nextTally, referendumCount]): Observable<DerivedReferendum[]> =>
referendumCount && nextTally && referendumCount.gt(nextTally) && referendumCount.gtn(0)
? api.derive.democracy.referendumInfos(
[...Array(referendumCount.sub(nextTally).toNumber())].map((_, i): BN =>
+2 -3
View File
@@ -52,9 +52,8 @@ function derivePhragmen (api: ApiInterfaceRx, candidates: AccountId[], members:
candidateCount: createType(api.registry, 'u32', candidates.length),
candidacyBond,
desiredSeats,
members,
// place in most-likely-to-be-in order
runnersUp: runnersUp.reverse(),
members: members.sort((a, b): number => b[1].cmp(a[1])),
runnersUp: runnersUp.sort((a, b): number => b[1].cmp(a[1])),
termDuration,
votingBond
};
+26 -2
View File
@@ -2,10 +2,10 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, AccountIndex, Balance, BalanceLock, BlockNumber, EraIndex, EraPoints, Exposure, Index, Keys, RewardDestination, SessionIndex, SetIndex, StakingLedger, ValidatorPrefs, Vote, VoteIndex } from '@polkadot/types/interfaces';
import { AccountId, AccountIndex, Balance, BalanceLock, BlockNumber, EraIndex, EraPoints, Exposure, Hash, Index, Keys, Proposal, PropIndex, ReferendumInfo, RewardDestination, SessionIndex, SetIndex, StakingLedger, ValidatorPrefs, Vote, VoteIndex } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import { u32 } from '@polkadot/types';
import { u32, Vec } from '@polkadot/types';
export type AccountIndexes = Record<string, AccountIndex>;
@@ -79,6 +79,30 @@ export interface RecentlyOffline {
count: BN;
}
export interface DeriveProposalPreImage {
at: BlockNumber;
balance: Balance;
proposer: AccountId;
}
export interface DeriveProposal {
balance?: Balance;
hash: Hash;
index: PropIndex;
preimage?: DeriveProposalPreImage;
proposal?: Proposal;
proposer: AccountId;
seconds: Vec<AccountId>;
}
export interface DerivedReferendum {
hash: Hash;
index: PropIndex;
info: ReferendumInfo;
preimage?: DeriveProposalPreImage;
proposal?: Proposal;
}
export type DerivedRecentlyOffline = Record<string, RecentlyOffline[]>;
export interface DerivedReferendumVote {
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api",
"version": "0.97.1",
"version": "0.98.1",
"description": "Promise and RxJS wrappers around the Polkadot JS RPC",
"main": "index.js",
"keywords": [
@@ -27,12 +27,12 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api#readme",
"dependencies": {
"@babel/runtime": "^7.7.4",
"@polkadot/api-derive": "^0.97.1",
"@polkadot/api-derive": "^0.98.1",
"@polkadot/keyring": "^1.7.1",
"@polkadot/metadata": "^0.97.1",
"@polkadot/rpc-core": "^0.97.1",
"@polkadot/rpc-provider": "^0.97.1",
"@polkadot/types": "^0.97.1",
"@polkadot/metadata": "^0.98.1",
"@polkadot/rpc-core": "^0.98.1",
"@polkadot/rpc-provider": "^0.98.1",
"@polkadot/types": "^0.98.1",
"@polkadot/util-crypto": "^1.7.1"
},
"devDependencies": {
+43 -20
View File
@@ -15,7 +15,7 @@ import {
} from '../types';
import BN from 'bn.js';
import { BehaviorSubject, Observable } from 'rxjs';
import { BehaviorSubject, Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import decorateDerive, { ExactDerive } from '@polkadot/api-derive';
import RpcCore from '@polkadot/rpc-core';
@@ -23,8 +23,8 @@ import { WsProvider } from '@polkadot/rpc-provider';
import { Metadata, Null, TypeRegistry, u64, Vec } from '@polkadot/types';
import Linkage, { LinkageResult } from '@polkadot/types/codec/Linkage';
import { DEFAULT_VERSION as EXTRINSIC_DEFAULT_VERSION } from '@polkadot/types/primitive/Extrinsic/constants';
import { StorageEntry } from '@polkadot/types/primitive/StorageKey';
import { compactStripLength, u8aToHex } from '@polkadot/util';
import StorageKey, { StorageEntry } from '@polkadot/types/primitive/StorageKey';
import { assert, compactStripLength, u8aToHex } from '@polkadot/util';
import { createSubmittable } from '../submittable';
import { decorateSections, DeriveAllSections } from '../util/decorate';
@@ -199,10 +199,10 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
}
return section;
}, {} as unknown as DecoratedRpcSection<ApiType, RpcInterface[typeof sectionName]>);
}, {} as DecoratedRpcSection<ApiType, RpcInterface[typeof sectionName]>);
return out;
}, {} as unknown as DecoratedRpc<ApiType, RpcInterface>);
}, {} as DecoratedRpc<ApiType, RpcInterface>);
}
protected decorateMulti<ApiType extends ApiTypes> (decorateMethod: DecorateMethod<ApiType>): QueryableStorageMulti<ApiType> {
@@ -223,10 +223,10 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
out[name] = this.decorateExtrinsicEntry(method, creator);
return out;
}, {} as unknown as SubmittableModuleExtrinsics<ApiType>);
}, {} as SubmittableModuleExtrinsics<ApiType>);
return out;
}, creator as unknown as SubmittableExtrinsics<ApiType>);
}, creator as SubmittableExtrinsics<ApiType>);
}
private decorateExtrinsicEntry<ApiType extends ApiTypes> (method: CallFunction, creator: (value: Call | Uint8Array | string) => SubmittableExtrinsic<ApiType>): SubmittableExtrinsicFunction<ApiType> {
@@ -242,10 +242,10 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
out[name] = this.decorateStorageEntry(method, decorateMethod);
return out;
}, {} as unknown as QueryableModuleStorage<ApiType>);
}, {} as QueryableModuleStorage<ApiType>);
return out;
}, {} as unknown as QueryableStorage<ApiType>);
}, {} as QueryableStorage<ApiType>);
}
private decorateStorageEntry<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): QueryableStorageEntry<ApiType> {
@@ -255,7 +255,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
: [creator, ...args];
// FIXME We probably want to be able to query the full list with non-subs as well
const decorated = this.hasSubscriptions && creator.iterKey
const decorated = this.hasSubscriptions && creator.iterKey && (creator.meta.type.asMap.kind.isLinkedMap || creator.meta.type.asMap.kind.isPrefixedMap)
? creator.meta.type.asMap.kind.isLinkedMap
? this.decorateStorageLinked(creator, decorateMethod)
: this.decorateStoragePrefixed(creator, decorateMethod)
@@ -275,6 +275,9 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
decorated.at = decorateMethod((hash: Hash, arg1?: Arg, arg2?: Arg): Observable<Codec> =>
this._rpcCore.state.getStorage(getArgs(arg1, arg2), hash));
decorated.entries = decorateMethod((): Observable<[StorageKey, Codec][]> =>
this.retrieveMapEntries(creator));
decorated.hash = decorateMethod((arg1?: Arg, arg2?: Arg): Observable<Hash> =>
this._rpcCore.state.getStorageHash(getArgs(arg1, arg2)));
@@ -362,23 +365,43 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
);
}
private decorateStoragePrefixed<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): ReturnType<DecorateMethod<ApiType>> {
private retrieveMapData (creator: StorageEntry): Observable<[StorageKey[], Vec<Codec>]> {
assert(creator.meta.type.isMap, 'entries can only be retrieved on maps');
const outputType = creator.meta.type.asMap.value.toString();
return this._rpcCore.state
// FIXME This should really be some sort of subscription, so we can get stuff as
// it changes (as of now it is a one-shot query). Not sure how to do this though...
.getKeys(creator.iterKey)
.pipe(
switchMap((keys): Observable<[StorageKey[], Vec<Codec>]> =>
combineLatest([
of(keys),
// Not 100% sure about this, surely this is just a vec?
this._rpcCore.state.subscribeStorage<Vec<Codec>>(
keys.map((key) => key.setOutputType(outputType))
)
])
)
);
}
private retrieveMapEntries (creator: StorageEntry): Observable<[StorageKey, Codec][]> {
return this.retrieveMapData(creator).pipe(
map(([keys, values]): [StorageKey, Codec][] =>
keys.map((key, index): [StorageKey, Codec] => [key, values[index]])
)
);
}
private decorateStoragePrefixed<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): ReturnType<DecorateMethod<ApiType>> {
return decorateMethod((...args: any[]): Observable<Codec> =>
args.length
? this._rpcCore.state
.subscribeStorage<[Codec]>([[creator, ...args]])
.pipe(map(([data]): Codec => data))
: this._rpcCore.state
// FIXME This should really be some sort of subscription, so we can get stuff as
// it changes (as of now it is a one-shot query). Not sure how to do this though...
.getKeys(creator.iterKey)
.pipe(switchMap((keys): Observable<Vec<Codec>> =>
this._rpcCore.state.subscribeStorage(
keys.map((key) => key.setOutputType(outputType))
)
))
: this.retrieveMapData(creator).pipe(map(([, values]): Vec<Codec> => values))
);
}
+1 -1
View File
@@ -6,7 +6,7 @@ import { SignedBlock } from '@polkadot/types/interfaces';
import { RegistryTypes } from '@polkadot/types/types';
import { ApiBase, ApiOptions, ApiTypes, DecorateMethod } from '../types';
import DecoratedMeta from '@polkadot/metadata';
import DecoratedMeta from '@polkadot/metadata/Decorated';
import { Metadata, u32 as U32 } from '@polkadot/types';
import { LATEST_EXTRINSIC_VERSION } from '@polkadot/types/primitive/Extrinsic/Extrinsic';
import { logger } from '@polkadot/util';
+13 -1
View File
@@ -28,7 +28,7 @@ describe('ApiPromise', (): void => {
const metadata: any = {};
const key = `${genesisHash}-${specVersion}`;
metadata[key] = rpcData;
const api = await ApiPromise.create({ provider, metadata, registry } as unknown as ApiOptions);
const api = await ApiPromise.create({ provider, metadata, registry } as ApiOptions);
expect(api.genesisHash).toBeDefined();
expect(api.runtimeMetadata).toBeDefined();
@@ -78,4 +78,16 @@ describe('ApiPromise', (): void => {
).toEqual(SIG);
});
});
describe('decorator.signAsync', (): void => {
it('signs a transfer using an external signer', async (): Promise<void> => {
const api = await ApiPromise.create({ provider, registry });
api.setSigner(new SingleAccountSigner(registry, keyring.alice_session));
const transfer = api.tx.balances.transfer(keyring.eve.address, 12345);
const dummySignature = '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';
expect(transfer.signature.toHex()).toEqual(dummySignature);
await transfer.signAsync(keyring.alice_session, {});
expect(transfer.signature.toHex()).not.toEqual(dummySignature);
});
});
});
+35 -35
View File
@@ -28,9 +28,9 @@ declare module './types' {
system: {
[index: string]: QueryableStorageEntry<ApiType>;
accountNonce: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Index>> & QueryableStorageEntry<ApiType>;
extrinsicCount: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
allExtrinsicsWeight: StorageEntryExact<ApiType, () => Observable<Weight>> & QueryableStorageEntry<ApiType>;
allExtrinsicsLen: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
extrinsicCount: StorageEntryExact<ApiType, () => Observable<Option<u32>>> & QueryableStorageEntry<ApiType>;
allExtrinsicsWeight: StorageEntryExact<ApiType, () => Observable<Option<Weight>>> & QueryableStorageEntry<ApiType>;
allExtrinsicsLen: StorageEntryExact<ApiType, () => Observable<Option<u32>>> & QueryableStorageEntry<ApiType>;
blockHash: StorageEntryExact<ApiType, (arg: BlockNumber | Uint8Array | number | string) => Observable<Hash>> & QueryableStorageEntry<ApiType>;
extrinsicData: StorageEntryExact<ApiType, (arg: u32 | Uint8Array | number | string) => Observable<Bytes>> & QueryableStorageEntry<ApiType>;
number: StorageEntryExact<ApiType, () => Observable<BlockNumber>> & QueryableStorageEntry<ApiType>;
@@ -51,7 +51,7 @@ declare module './types' {
nextRandomness: StorageEntryExact<ApiType, () => Observable<U8a>> & QueryableStorageEntry<ApiType>;
segmentIndex: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
underConstruction: StorageEntryExact<ApiType, (arg: u32 | Uint8Array | number | string) => Observable<Vec<U8a>>> & QueryableStorageEntry<ApiType>;
initialized: StorageEntryExact<ApiType, () => Observable<MaybeVrf>> & QueryableStorageEntry<ApiType>;
initialized: StorageEntryExact<ApiType, () => Observable<Option<MaybeVrf>>> & QueryableStorageEntry<ApiType>;
};
timestamp: {
[index: string]: QueryableStorageEntry<ApiType>;
@@ -61,7 +61,7 @@ declare module './types' {
authorship: {
[index: string]: QueryableStorageEntry<ApiType>;
uncles: StorageEntryExact<ApiType, () => Observable<Vec<UncleEntryItem>>> & QueryableStorageEntry<ApiType>;
author: StorageEntryExact<ApiType, () => Observable<AccountId>> & QueryableStorageEntry<ApiType>;
author: StorageEntryExact<ApiType, () => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
didSetUncles: StorageEntryExact<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
};
indices: {
@@ -72,7 +72,7 @@ declare module './types' {
balances: {
[index: string]: QueryableStorageEntry<ApiType>;
totalIssuance: StorageEntryExact<ApiType, () => Observable<Balance>> & QueryableStorageEntry<ApiType>;
vesting: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<VestingSchedule>> & QueryableStorageEntry<ApiType>;
vesting: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<VestingSchedule>>> & QueryableStorageEntry<ApiType>;
freeBalance: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Balance>> & QueryableStorageEntry<ApiType>;
reservedBalance: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Balance>> & QueryableStorageEntry<ApiType>;
locks: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Vec<BalanceLock>>> & QueryableStorageEntry<ApiType>;
@@ -86,11 +86,11 @@ declare module './types' {
validatorCount: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
minimumValidatorCount: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
invulnerables: StorageEntryExact<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
bonded: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<AccountId>> & QueryableStorageEntry<ApiType>;
ledger: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<StakingLedger>> & QueryableStorageEntry<ApiType>;
bonded: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
ledger: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<StakingLedger>>> & QueryableStorageEntry<ApiType>;
payee: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<RewardDestination>> & QueryableStorageEntry<ApiType>;
validators: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<ValidatorPrefs>> & QueryableStorageEntry<ApiType>;
nominators: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Nominations>> & QueryableStorageEntry<ApiType>;
nominators: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<Nominations>>> & QueryableStorageEntry<ApiType>;
stakers: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Exposure>> & QueryableStorageEntry<ApiType>;
currentElected: StorageEntryExact<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
currentEra: StorageEntryExact<ApiType, () => Observable<EraIndex>> & QueryableStorageEntry<ApiType>;
@@ -103,11 +103,11 @@ declare module './types' {
canceledSlashPayout: StorageEntryExact<ApiType, () => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
unappliedSlashes: StorageEntryExact<ApiType, (arg: EraIndex | Uint8Array | number | string) => Observable<Vec<UnappliedSlash>>> & QueryableStorageEntry<ApiType>;
bondedEras: StorageEntryExact<ApiType, () => Observable<Vec<ITuple<[EraIndex, SessionIndex]>>>> & QueryableStorageEntry<ApiType>;
validatorSlashInEra: StorageEntryExact<ApiType, (key1: EraIndex | Uint8Array | number | string, key2: AccountId | Uint8Array | string) => Observable<ITuple<[Perbill, BalanceOf]>>> & QueryableStorageEntry<ApiType>;
nominatorSlashInEra: StorageEntryExact<ApiType, (key1: EraIndex | Uint8Array | number | string, key2: AccountId | Uint8Array | string) => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
slashingSpans: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<SlashingSpans>> & QueryableStorageEntry<ApiType>;
validatorSlashInEra: StorageEntryExact<ApiType, (key1: EraIndex | Uint8Array | number | string, key2: AccountId | Uint8Array | string) => Observable<Option<ITuple<[Perbill, BalanceOf]>>>> & QueryableStorageEntry<ApiType>;
nominatorSlashInEra: StorageEntryExact<ApiType, (key1: EraIndex | Uint8Array | number | string, key2: AccountId | Uint8Array | string) => Observable<Option<BalanceOf>>> & QueryableStorageEntry<ApiType>;
slashingSpans: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<SlashingSpans>>> & QueryableStorageEntry<ApiType>;
spanSlash: StorageEntryExact<ApiType, (arg: ITuple<[AccountId, SpanIndex]>) => Observable<SpanRecord>> & QueryableStorageEntry<ApiType>;
earliestUnappliedSlash: StorageEntryExact<ApiType, () => Observable<EraIndex>> & QueryableStorageEntry<ApiType>;
earliestUnappliedSlash: StorageEntryExact<ApiType, () => Observable<Option<EraIndex>>> & QueryableStorageEntry<ApiType>;
storageVersion: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
};
session: {
@@ -117,40 +117,40 @@ declare module './types' {
queuedChanged: StorageEntryExact<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
queuedKeys: StorageEntryExact<ApiType, () => Observable<Vec<ITuple<[ValidatorId, Keys]>>>> & QueryableStorageEntry<ApiType>;
disabledValidators: StorageEntryExact<ApiType, () => Observable<Vec<u32>>> & QueryableStorageEntry<ApiType>;
nextKeys: StorageEntryExact<ApiType, (key1: Bytes | Uint8Array | string, key2: ValidatorId | Uint8Array | string) => Observable<Keys>> & QueryableStorageEntry<ApiType>;
keyOwner: StorageEntryExact<ApiType, (key1: Bytes | Uint8Array | string, key2: ITuple<[KeyTypeId, Bytes]>) => Observable<ValidatorId>> & QueryableStorageEntry<ApiType>;
nextKeys: StorageEntryExact<ApiType, (key1: Bytes | Uint8Array | string, key2: ValidatorId | Uint8Array | string) => Observable<Option<Keys>>> & QueryableStorageEntry<ApiType>;
keyOwner: StorageEntryExact<ApiType, (key1: Bytes | Uint8Array | string, key2: ITuple<[KeyTypeId, Bytes]>) => Observable<Option<ValidatorId>>> & QueryableStorageEntry<ApiType>;
};
democracy: {
[index: string]: QueryableStorageEntry<ApiType>;
publicPropCount: StorageEntryExact<ApiType, () => Observable<PropIndex>> & QueryableStorageEntry<ApiType>;
publicProps: StorageEntryExact<ApiType, () => Observable<Vec<ITuple<[PropIndex, Proposal, AccountId]>>>> & QueryableStorageEntry<ApiType>;
depositOf: StorageEntryExact<ApiType, (arg: PropIndex | Uint8Array | number | string) => Observable<ITuple<[BalanceOf, Vec<AccountId>]>>> & QueryableStorageEntry<ApiType>;
depositOf: StorageEntryExact<ApiType, (arg: PropIndex | Uint8Array | number | string) => Observable<Option<ITuple<[BalanceOf, Vec<AccountId>]>>>> & QueryableStorageEntry<ApiType>;
referendumCount: StorageEntryExact<ApiType, () => Observable<ReferendumIndex>> & QueryableStorageEntry<ApiType>;
nextTally: StorageEntryExact<ApiType, () => Observable<ReferendumIndex>> & QueryableStorageEntry<ApiType>;
referendumInfoOf: StorageEntryExact<ApiType, (arg: ReferendumIndex | Uint8Array | number | string) => Observable<ReferendumInfo>> & QueryableStorageEntry<ApiType>;
referendumInfoOf: StorageEntryExact<ApiType, (arg: ReferendumIndex | Uint8Array | number | string) => Observable<Option<ReferendumInfo>>> & QueryableStorageEntry<ApiType>;
dispatchQueue: StorageEntryExact<ApiType, (arg: BlockNumber | Uint8Array | number | string) => Observable<Vec<Option<ITuple<[Proposal, ReferendumIndex]>>>>> & QueryableStorageEntry<ApiType>;
votersFor: StorageEntryExact<ApiType, (arg: ReferendumIndex | Uint8Array | number | string) => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
voteOf: StorageEntryExact<ApiType, (arg: ITuple<[ReferendumIndex, AccountId]>) => Observable<Vote>> & QueryableStorageEntry<ApiType>;
proxy: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<AccountId>> & QueryableStorageEntry<ApiType>;
proxy: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
delegations: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<ITuple<[AccountId, Conviction]>>> & QueryableStorageEntry<ApiType>;
lastTabledWasExternal: StorageEntryExact<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
nextExternal: StorageEntryExact<ApiType, () => Observable<ITuple<[Proposal, VoteThreshold]>>> & QueryableStorageEntry<ApiType>;
blacklist: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<ITuple<[BlockNumber, Vec<AccountId>]>>> & QueryableStorageEntry<ApiType>;
nextExternal: StorageEntryExact<ApiType, () => Observable<Option<ITuple<[Proposal, VoteThreshold]>>>> & QueryableStorageEntry<ApiType>;
blacklist: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<ITuple<[BlockNumber, Vec<AccountId>]>>>> & QueryableStorageEntry<ApiType>;
cancellations: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<bool>> & QueryableStorageEntry<ApiType>;
};
council: {
[index: string]: QueryableStorageEntry<ApiType>;
proposals: StorageEntryExact<ApiType, () => Observable<Vec<Hash>>> & QueryableStorageEntry<ApiType>;
proposalOf: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Proposal>> & QueryableStorageEntry<ApiType>;
voting: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Votes>> & QueryableStorageEntry<ApiType>;
proposalOf: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<Proposal>>> & QueryableStorageEntry<ApiType>;
voting: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<Votes>>> & QueryableStorageEntry<ApiType>;
proposalCount: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
members: StorageEntryExact<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
technicalCommittee: {
[index: string]: QueryableStorageEntry<ApiType>;
proposals: StorageEntryExact<ApiType, () => Observable<Vec<Hash>>> & QueryableStorageEntry<ApiType>;
proposalOf: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Proposal>> & QueryableStorageEntry<ApiType>;
voting: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Votes>> & QueryableStorageEntry<ApiType>;
proposalOf: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<Proposal>>> & QueryableStorageEntry<ApiType>;
voting: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<Votes>>> & QueryableStorageEntry<ApiType>;
proposalCount: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
members: StorageEntryExact<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
@@ -172,26 +172,26 @@ declare module './types' {
[index: string]: QueryableStorageEntry<ApiType>;
authorities: StorageEntryExact<ApiType, () => Observable<AuthorityList>> & QueryableStorageEntry<ApiType>;
state: StorageEntryExact<ApiType, () => Observable<StoredState>> & QueryableStorageEntry<ApiType>;
pendingChange: StorageEntryExact<ApiType, () => Observable<StoredPendingChange>> & QueryableStorageEntry<ApiType>;
nextForced: StorageEntryExact<ApiType, () => Observable<BlockNumber>> & QueryableStorageEntry<ApiType>;
stalled: StorageEntryExact<ApiType, () => Observable<ITuple<[BlockNumber, BlockNumber]>>> & QueryableStorageEntry<ApiType>;
pendingChange: StorageEntryExact<ApiType, () => Observable<Option<StoredPendingChange>>> & QueryableStorageEntry<ApiType>;
nextForced: StorageEntryExact<ApiType, () => Observable<Option<BlockNumber>>> & QueryableStorageEntry<ApiType>;
stalled: StorageEntryExact<ApiType, () => Observable<Option<ITuple<[BlockNumber, BlockNumber]>>>> & QueryableStorageEntry<ApiType>;
currentSetId: StorageEntryExact<ApiType, () => Observable<SetId>> & QueryableStorageEntry<ApiType>;
setIdSession: StorageEntryExact<ApiType, (arg: SetId | Uint8Array | number | string) => Observable<SessionIndex>> & QueryableStorageEntry<ApiType>;
setIdSession: StorageEntryExact<ApiType, (arg: SetId | Uint8Array | number | string) => Observable<Option<SessionIndex>>> & QueryableStorageEntry<ApiType>;
};
treasury: {
[index: string]: QueryableStorageEntry<ApiType>;
proposalCount: StorageEntryExact<ApiType, () => Observable<ProposalIndex>> & QueryableStorageEntry<ApiType>;
proposals: StorageEntryExact<ApiType, (arg: ProposalIndex | Uint8Array | number | string) => Observable<TreasuryProposal>> & QueryableStorageEntry<ApiType>;
proposals: StorageEntryExact<ApiType, (arg: ProposalIndex | Uint8Array | number | string) => Observable<Option<TreasuryProposal>>> & QueryableStorageEntry<ApiType>;
approvals: StorageEntryExact<ApiType, () => Observable<Vec<ProposalIndex>>> & QueryableStorageEntry<ApiType>;
};
contracts: {
[index: string]: QueryableStorageEntry<ApiType>;
gasSpent: StorageEntryExact<ApiType, () => Observable<Gas>> & QueryableStorageEntry<ApiType>;
currentSchedule: StorageEntryExact<ApiType, () => Observable<Schedule>> & QueryableStorageEntry<ApiType>;
pristineCode: StorageEntryExact<ApiType, (arg: CodeHash | Uint8Array | string) => Observable<Bytes>> & QueryableStorageEntry<ApiType>;
codeStorage: StorageEntryExact<ApiType, (arg: CodeHash | Uint8Array | string) => Observable<PrefabWasmModule>> & QueryableStorageEntry<ApiType>;
pristineCode: StorageEntryExact<ApiType, (arg: CodeHash | Uint8Array | string) => Observable<Option<Bytes>>> & QueryableStorageEntry<ApiType>;
codeStorage: StorageEntryExact<ApiType, (arg: CodeHash | Uint8Array | string) => Observable<Option<PrefabWasmModule>>> & QueryableStorageEntry<ApiType>;
accountCounter: StorageEntryExact<ApiType, () => Observable<u64>> & QueryableStorageEntry<ApiType>;
contractInfoOf: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<ContractInfo>> & QueryableStorageEntry<ApiType>;
contractInfoOf: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<ContractInfo>>> & QueryableStorageEntry<ApiType>;
gasPrice: StorageEntryExact<ApiType, () => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
};
sudo: {
@@ -202,12 +202,12 @@ declare module './types' {
[index: string]: QueryableStorageEntry<ApiType>;
gossipAt: StorageEntryExact<ApiType, () => Observable<BlockNumber>> & QueryableStorageEntry<ApiType>;
keys: StorageEntryExact<ApiType, () => Observable<Vec<AuthorityId>>> & QueryableStorageEntry<ApiType>;
receivedHeartbeats: StorageEntryExact<ApiType, (key1: SessionIndex | Uint8Array | number | string, key2: AuthIndex | Uint8Array | number | string) => Observable<Bytes>> & QueryableStorageEntry<ApiType>;
receivedHeartbeats: StorageEntryExact<ApiType, (key1: SessionIndex | Uint8Array | number | string, key2: AuthIndex | Uint8Array | number | string) => Observable<Option<Bytes>>> & QueryableStorageEntry<ApiType>;
authoredBlocks: StorageEntryExact<ApiType, (key1: SessionIndex | Uint8Array | number | string, key2: ValidatorId | Uint8Array | string) => Observable<u32>> & QueryableStorageEntry<ApiType>;
};
offences: {
[index: string]: QueryableStorageEntry<ApiType>;
reports: StorageEntryExact<ApiType, (arg: ReportIdOf | Uint8Array | string) => Observable<OffenceDetails>> & QueryableStorageEntry<ApiType>;
reports: StorageEntryExact<ApiType, (arg: ReportIdOf | Uint8Array | string) => Observable<Option<OffenceDetails>>> & QueryableStorageEntry<ApiType>;
concurrentReportsIndex: StorageEntryExact<ApiType, (key1: Kind | Uint8Array | string, key2: OpaqueTimeSlot | Uint8Array | string) => Observable<Vec<ReportIdOf>>> & QueryableStorageEntry<ApiType>;
reportsByKindIndex: StorageEntryExact<ApiType, (arg: Kind | Uint8Array | string) => Observable<Bytes>> & QueryableStorageEntry<ApiType>;
};
@@ -217,7 +217,7 @@ declare module './types' {
};
nicks: {
[index: string]: QueryableStorageEntry<ApiType>;
nameOf: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<ITuple<[Bytes, BalanceOf]>>> & QueryableStorageEntry<ApiType>;
nameOf: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<ITuple<[Bytes, BalanceOf]>>>> & QueryableStorageEntry<ApiType>;
};
}
}
+26 -10
View File
@@ -49,15 +49,23 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
this._ignoreStatusCb = apiType === 'rxjs';
}
// sign a transaction, returning the this to allow cianing, i.e. .sign(...).send()
// sign a transaction, returning the this to allow chaining, i.e. .sign(...).send()
public sign (account: IKeyringPair, optionsOrNonce: Partial<SignerOptions>): this {
// NOTE here we actually override nonce if it was specified (backwards compat for
// the previous signature - don't let userspace break, but allow then time to upgrade)
const options: Partial<SignerOptions> = isBn(optionsOrNonce) || isNumber(optionsOrNonce)
? { nonce: optionsOrNonce }
: optionsOrNonce;
super.sign(account, this._makeSignOptions(this._optionsOrNonce(optionsOrNonce), {}));
super.sign(account, this._makeSignOptions(options, {}));
return this;
}
// signs a transaction, returning `this` to allow chaining. E.g.: `sign(...).send()`
//
// also supports signing through external signers
public async signAsync (account: IKeyringPair, optionsOrNonce: Partial<SignerOptions>): Promise<this> {
if (this._api.signer) {
const options = this._makeSignOptions(this._optionsOrNonce(optionsOrNonce), {});
await this._signViaSigner(account.address, options, null);
} else {
this.sign(account, optionsOrNonce);
}
return this;
}
@@ -129,13 +137,13 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
return [options, statusCb];
}
private async _signViaSigner (address: string, optionsWithEra: SignatureOptions, header: Header | null): Promise<number> {
private async _signViaSigner (address: string, options: SignatureOptions, header: Header | null): Promise<number> {
if (!this._api.signer) {
throw new Error('no signer attached');
}
const payload = createType(this.registry, 'SignerPayload', {
...optionsWithEra,
...options,
address,
method: this.method,
blockNumber: header ? header.number : 0
@@ -166,7 +174,7 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
genesisHash: this._api.genesisHash,
runtimeVersion: this._api.runtimeVersion,
version: this._api.extrinsicType
} as unknown as SignatureOptions;
} as SignatureOptions;
}
private _makeEraOptions (options: Partial<SignerOptions>, { header, nonce }: { header: Header | null; nonce: Index }): SignatureOptions {
@@ -258,5 +266,13 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
})
);
}
// NOTE here we actually override nonce if it was specified (backwards compat for
// the previous signature - don't let userspace break, but allow then time to upgrade)
private _optionsOrNonce = (optionsOrNonce: Partial<SignerOptions>): Partial<SignerOptions> => {
return isBn(optionsOrNonce) || isNumber(optionsOrNonce)
? { nonce: optionsOrNonce }
: optionsOrNonce;
}
};
}
+2
View File
@@ -48,6 +48,8 @@ export interface SubmittableExtrinsic<ApiType extends ApiTypes> extends IExtrins
sign(account: IKeyringPair, _options: Partial<SignatureOptions>): this;
signAsync(account: IKeyringPair, _options: Partial<SignatureOptions>): Promise<this>;
signAndSend(account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmittableResultResult<ApiType>;
signAndSend(account: IKeyringPair | string | AccountId | Address, statusCb: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
+2 -1
View File
@@ -20,7 +20,7 @@ import { DeriveCustom, ExactDerive } from '@polkadot/api-derive';
import { RpcInterface } from '@polkadot/rpc-core/jsonrpc.types';
import { ProviderInterface, ProviderInterfaceEmitted } from '@polkadot/rpc-provider/types';
import { Metadata, u64 } from '@polkadot/types';
import { StorageEntry } from '@polkadot/types/primitive/StorageKey';
import StorageKey, { StorageEntry } from '@polkadot/types/primitive/StorageKey';
import ApiBase from './base';
@@ -110,6 +110,7 @@ interface StorageEntryPromiseMulti {
export interface StorageEntryBase<ApiType extends ApiTypes, F extends AnyFunction> {
at: (hash: Hash | Uint8Array | string, ...args: Parameters<F>) => PromiseOrObs<ApiType, ObsInnerType<ReturnType<F>>>;
creator: StorageEntry;
entries: () => PromiseOrObs<ApiType, [StorageKey, ObsInnerType<ReturnType<F>>][]>;
hash: (...args: Parameters<F>) => PromiseOrObs<ApiType, Hash>;
key: (...args: Parameters<F>) => string;
size: (...args: Parameters<F>) => PromiseOrObs<ApiType, u64>;
@@ -4,7 +4,7 @@
import { BlockNumber, Index, SignedBlock } from '@polkadot/types/interfaces';
import Metadata from '@polkadot/metadata';
import Metadata from '@polkadot/metadata/Decorated';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import WsProvider from '@polkadot/rpc-provider/ws';
import { ClassOf, TypeRegistry } from '@polkadot/types';
+1 -1
View File
@@ -4,7 +4,7 @@
import { Balance, Moment, RuntimeVersion } from '@polkadot/types/interfaces';
import DecorateMeta from '@polkadot/metadata';
import DecorateMeta from '@polkadot/metadata/Decorated';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import Rpc from '@polkadot/rpc-core';
import WsProvider from '@polkadot/rpc-provider/ws';
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import Metadata from '@polkadot/metadata';
import Metadata from '@polkadot/metadata/Decorated';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/metadata",
"version": "0.97.1",
"version": "0.98.1",
"description": "Helpers to extract information from runtime metadata",
"main": "index.js",
"publishConfig": {
@@ -27,7 +27,7 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/type-metadata#readme",
"dependencies": {
"@babel/runtime": "^7.7.4",
"@polkadot/types": "^0.97.1",
"@polkadot/types": "^0.98.1",
"@polkadot/util": "^1.7.1",
"@polkadot/util-crypto": "^1.7.1"
},
@@ -212,7 +212,7 @@ export default function createFunction (registry: Registry, itemFn: CreateItemFn
if (map.kind.isLinkedMap) {
extendLinkedMap(registry, itemFn, storageFn, stringKey, hasher, options.metaVersion);
} else if (map.kind.isPrefixedMap) {
} else {
extendPrefixedMap(registry, itemFn, storageFn);
}
}
@@ -39,7 +39,7 @@ export default function fromMetadata (registry: Registry, metadata: Metadata): S
}, { metaVersion: metadata.version });
return newModule;
}, {} as unknown as ModuleStorage);
}, {} as ModuleStorage);
return result;
}, { ...getStorage(registry, metadata.version) });
@@ -24,7 +24,7 @@ function createRuntimeFunction (method: string, key: string, { documentation, ty
modifier: createType(registry, 'StorageEntryModifierLatest', 1), // required
type: createType(registry, 'StorageEntryTypeLatest', type, 0),
toJSON: (): any => key
} as unknown as StorageEntryMetadataLatest,
} as StorageEntryMetadataLatest,
method,
prefix: 'Substrate',
section: 'substrate'
-8
View File
@@ -1,8 +0,0 @@
// Copyright 2017-2019 @polkadot/metadata authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// Even though it's decorated, we still call this one `Metadata`
import Metadata from './Decorated';
export default Metadata;
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/rpc-core",
"version": "0.97.1",
"version": "0.98.1",
"description": "A JavaScript wrapper for the Polkadot JsonRPC interface",
"main": "index.js",
"keywords": [
@@ -27,9 +27,9 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/rpc-core#readme",
"dependencies": {
"@babel/runtime": "^7.7.4",
"@polkadot/jsonrpc": "^0.97.1",
"@polkadot/rpc-provider": "^0.97.1",
"@polkadot/types": "^0.97.1",
"@polkadot/jsonrpc": "^0.98.1",
"@polkadot/rpc-provider": "^0.98.1",
"@polkadot/types": "^0.98.1",
"@polkadot/util": "^1.7.1",
"rxjs": "^6.5.3"
}
+1 -1
View File
@@ -5,7 +5,7 @@
import { Balance } from '@polkadot/types/interfaces';
import { Codec } from '@polkadot/types/types';
import Metadata from '@polkadot/metadata';
import Metadata from '@polkadot/metadata/Decorated';
import rpcMetadataV3 from '@polkadot/metadata/Metadata/v3/static';
import rpcMetadataV4 from '@polkadot/metadata/Metadata/v4/static';
import rpcMetadataV5 from '@polkadot/metadata/Metadata/v5/static';
+1 -1
View File
@@ -171,7 +171,7 @@ export default class Rpc implements RpcInterface {
: this.createMethodSend(def);
return exposed;
}, {} as unknown as RpcInterface[Section]);
}, {} as RpcInterface[Section]);
}
private createMethodSend (method: RpcMethod): RpcInterfaceMethod {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/rpc-provider",
"version": "0.97.1",
"version": "0.98.1",
"description": "Transport providers for the API",
"main": "index.js",
"keywords": [
@@ -27,7 +27,7 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/rpc-provider#readme",
"dependencies": {
"@babel/runtime": "^7.7.4",
"@polkadot/metadata": "^0.97.1",
"@polkadot/metadata": "^0.98.1",
"@polkadot/util": "^1.7.1",
"@polkadot/util-crypto": "^1.7.1",
"eventemitter3": "^4.0.0",
@@ -20,31 +20,31 @@ describe('decodeResponse', (): void => {
it('expects a valid jsonrpc field', (): void => {
expect(
(): any => coder.decodeResponse({} as unknown as JsonRpcResponse)
(): any => coder.decodeResponse({} as JsonRpcResponse)
).toThrow(/Invalid jsonrpc/);
});
it('expects a valid id field', (): void => {
expect(
(): any => coder.decodeResponse({ jsonrpc: '2.0' } as unknown as JsonRpcResponse)
(): any => coder.decodeResponse({ jsonrpc: '2.0' } as JsonRpcResponse)
).toThrow(/Invalid id/);
});
it('expects a valid result field', (): void => {
expect(
(): any => coder.decodeResponse({ id: 1, jsonrpc: '2.0' } as unknown as JsonRpcResponse)
(): any => coder.decodeResponse({ id: 1, jsonrpc: '2.0' } as JsonRpcResponse)
).toThrow(/No result/);
});
it('throws any error found', (): void => {
expect(
(): any => coder.decodeResponse({ id: 1, jsonrpc: '2.0', error: { code: 123, message: 'test error' } } as unknown as JsonRpcResponse)
(): any => coder.decodeResponse({ id: 1, jsonrpc: '2.0', error: { code: 123, message: 'test error' } } as JsonRpcResponse)
).toThrow(/123: test error/);
});
it('returns the result', (): void => {
expect(
coder.decodeResponse({ id: 1, jsonrpc: '2.0', result: 'some result' } as unknown as JsonRpcResponse)
coder.decodeResponse({ id: 1, jsonrpc: '2.0', result: 'some result' } as JsonRpcResponse)
).toEqual('some result');
});
});
+2 -2
View File
@@ -10,7 +10,7 @@ import { MockStateSubscriptions, MockStateSubscriptionCallback, MockStateDb } fr
import BN from 'bn.js';
import EventEmitter from 'eventemitter3';
import Metadata from '@polkadot/metadata';
import Metadata from '@polkadot/metadata/Decorated';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import interfaces from '@polkadot/jsonrpc';
import testKeyring from '@polkadot/keyring/testing';
@@ -75,7 +75,7 @@ export default class Mock implements ProviderInterface {
};
return subs;
}, ({} as unknown as MockStateSubscriptions));
}, ({} as MockStateSubscriptions));
private subscriptionId = 0;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/jsonrpc",
"version": "0.97.1",
"version": "0.98.1",
"description": "Method definitions for the Polkadot RPC layer",
"main": "index.js",
"publishConfig": {
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/types",
"version": "0.97.1",
"version": "0.98.1",
"description": "Implementation of the Parity codec",
"main": "index.js",
"keywords": [
@@ -27,6 +27,7 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/types#readme",
"dependencies": {
"@babel/runtime": "^7.7.4",
"@polkadot/metadata": "^0.98.1",
"@polkadot/util": "^1.7.1",
"@polkadot/util-crypto": "^1.7.1",
"@types/memoizee": "^0.4.3",
+2 -2
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyNumber, Codec, Constructor, InterfaceTypes, Registry } from '../types';
import { AnyNumber, Codec, Constructor, ICompact, InterfaceTypes, Registry } from '../types';
import BN from 'bn.js';
import { compactAddLength, compactFromU8a, compactStripLength, compactToU8a, isBn, isNumber, isString } from '@polkadot/util';
@@ -26,7 +26,7 @@ export interface CompactEncodable extends Codec {
* used by other types to add length-prefixed encoding, or in the case of wrapped types, taking
* a number and making the compact representation thereof
*/
export default class Compact<T extends CompactEncodable> extends Base<T> {
export default class Compact<T extends CompactEncodable> extends Base<T> implements ICompact<T> {
constructor (registry: Registry, Type: Constructor<T> | InterfaceTypes, value: Compact<T> | AnyNumber = 0) {
super(registry, Compact.decodeCompact<T>(registry, typeToConstructor(registry, Type), value));
}
+1 -1
View File
@@ -39,7 +39,7 @@ function extractDef (registry: Registry, _def: Record<string, InterfaceTypes | C
def[key] = Null;
return def;
}, {} as unknown as TypesDef),
}, {} as TypesDef),
isBasic: true
};
}
+6 -6
View File
@@ -37,7 +37,7 @@ export default class Struct<
protected _Types: ConstructorDef;
constructor (registry: Registry, Types: S, value: V | Map<any, any> | any[] | string = {} as unknown as V, jsonMap: Map<keyof S, string> = new Map()) {
constructor (registry: Registry, Types: S, value: V | Map<any, any> | any[] | string = {} as V, jsonMap: Map<keyof S, string> = new Map()) {
const Clazzes = mapToTypeMap(registry, Types);
const decoded: T = Struct.decodeStruct(registry, Clazzes, value, jsonMap);
@@ -75,9 +75,9 @@ export default class Struct<
(raw as any)[key] = values[index];
return raw;
}, {} as unknown as T);
}, {} as T);
} else if (!value) {
return {} as unknown as T;
return {} as T;
}
// We assume from here that value is a JS object (Array, Map, Object)
@@ -114,7 +114,7 @@ export default class Struct<
}
return raw;
}, {} as unknown as T);
}, {} as T);
}
public static with<S extends TypesDef> (Types: S): Constructor<Struct<S>> {
@@ -162,7 +162,7 @@ export default class Struct<
(result as any)[key] = new Type(this.registry).toRawType();
return result;
}, {} as unknown as E);
}, {} as E);
}
/**
@@ -240,7 +240,7 @@ export default class Struct<
result[key] = new Type(registry).toRawType();
return result;
}, {} as unknown as Record<string, string>);
}, {} as Record<string, string>);
}
/**
+2 -2
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyU8a, Codec, IHash, Registry } from '../types';
import { AnyU8a, IHash, IU8a, Registry } from '../types';
import { isU8a, isUndefined, u8aToHex, u8aToU8a } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
@@ -16,7 +16,7 @@ import { blake2AsU8a } from '@polkadot/util-crypto';
* actual lengths instead of used directly.
* @noInheritDoc
*/
export default class U8a extends Uint8Array implements Codec {
export default class U8a extends Uint8Array implements IU8a {
public readonly registry: Registry;
constructor (registry: Registry, value?: AnyU8a) {
@@ -57,9 +57,12 @@ function initType<T extends Codec = Codec, K extends string = string> (registry:
// An unsafe version of the `createType` below. It's unsafe because the `type`
// argument here can be any string, which, if not parseable, will yield a
// runtime error.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function createTypeUnsafe<T extends Codec = Codec, K extends string = string> (registry: Registry, type: K, params: any[] = [], isPedantic?: boolean): T {
try {
return initType(registry, createClass<T, K>(registry, type), params, isPedantic);
// Circle back to isPedenatic when it handles all cases 100% - as of now,
// it provides false wraning which is more hinderance than help
return initType(registry, createClass<T, K>(registry, type), params); // , isPedantic);
} catch (error) {
throw new Error(`createType(${type}):: ${error.message}`);
}
@@ -10,7 +10,6 @@ import { assert } from '@polkadot/util';
import BTreeMap from '../BTreeMap';
import Compact from '../Compact';
import Enum from '../Enum';
import Linkage from '../Linkage';
import Option from '../Option';
import Result from '../Result';
import CodecSet from '../Set';
@@ -67,7 +66,17 @@ const infoMapping: Record<TypeDefInfo, (registry: Registry, value: TypeDef) => C
[TypeDefInfo.Enum]: (registry: Registry, value: TypeDef): Constructor => Enum.with(getTypeClassMap(value)),
[TypeDefInfo.Linkage]: (registry: Registry, value: TypeDef): Constructor => Linkage.withKey(getSubType(value)),
// We have circular deps between Linkage & Struct
[TypeDefInfo.Linkage]: (registry: Registry, value: TypeDef): Constructor => {
const type = `Option<${getSubType(value)}>`;
const Clazz = Struct.with({ previous: type, next: type } as any);
ClassOf.prototype.toRawType = function (): string {
return `Linkage<${this.next.toRawType(true)}>`;
};
return Clazz;
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[TypeDefInfo.Null]: (registry: Registry, _: TypeDef): Constructor => ClassOf(registry, 'Null'),
@@ -73,7 +73,7 @@ function _decodeFixedVec (value: TypeDef, type: string, _: string): TypeDef {
// as a first round, only u8 via u8aFixed, we can add more support
assert(vecLen <= 256, `${type}: Only support for [Type; <length>], where length <= 256`);
value.ext = { length: vecLen, type: vecType } as unknown as TypeDefExtVecFixed;
value.ext = { length: vecLen, type: vecType } as TypeDefExtVecFixed;
return value;
}
+1 -1
View File
@@ -201,7 +201,7 @@ function _removeWrap (_check: string): Mapper {
};
}
export default function santize (value: string): string {
export default function sanitize (value: string): string {
return mappings.reduce((result, fn): string => {
return fn(result);
}, value).trim();
@@ -6,7 +6,7 @@ import { Codec, Constructor, InterfaceTypes, Registry } from '../../types';
import { isString } from '@polkadot/util';
import { ClassOf } from '../create';
import { ClassOf } from '../create/createClass';
export function typeToConstructor <T = Codec> (registry: Registry, type: InterfaceTypes | Constructor<T>): Constructor<T> {
return (
@@ -17,7 +17,9 @@ export default {
// 4x votes, locked for 8x...
'Locked4x',
// 5x votes, locked for 16x...
'Locked5x'
'Locked5x',
/// 6x votes, locked for 32x...
'Locked6x'
]
},
PropIndex: 'u32',
@@ -25,7 +27,7 @@ export default {
ReferendumIndex: 'u32',
ReferendumInfo: {
end: 'BlockNumber',
proposal: 'Proposal',
proposalHash: 'Hash',
threshold: 'VoteThreshold',
delay: 'BlockNumber'
}
@@ -3,7 +3,7 @@
import { Enum, Struct } from '@polkadot/types/codec';
import { u32 } from '@polkadot/types/primitive';
import { BlockNumber, Call } from '@polkadot/types/interfaces/runtime';
import { BlockNumber, Call, Hash } from '@polkadot/types/interfaces/runtime';
import { VoteThreshold } from '@polkadot/types/interfaces/elections';
/** Enum */
@@ -20,6 +20,8 @@ export interface Conviction extends Enum {
readonly isLocked4X: boolean;
/** 5:: Locked5x */
readonly isLocked5X: boolean;
/** 6:: Locked6x */
readonly isLocked6X: boolean;
}
/** u32 */
@@ -35,8 +37,8 @@ export interface ReferendumIndex extends u32 {}
export interface ReferendumInfo extends Struct {
/** BlockNumber */
readonly end: BlockNumber;
/** Proposal */
readonly proposal: Proposal;
/** Hash */
readonly proposalHash: Hash;
/** VoteThreshold */
readonly threshold: VoteThreshold;
/** BlockNumber */
@@ -4,7 +4,7 @@
import BN from 'bn.js';
import testingPairs from '@polkadot/keyring/testingPairs';
import Decorated from '@polkadot/metadata';
import Decorated from '@polkadot/metadata/Decorated';
import Metadata from '@polkadot/metadata/Metadata';
import metadataStatic from '@polkadot/metadata/Metadata/static';
+1 -1
View File
@@ -129,7 +129,7 @@ export default class Call extends Struct implements IMethod {
result[name.toString()] = Type;
return result;
}, {} as unknown as ArgsDef);
}, {} as ArgsDef);
}
/**
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import Metadata from '@polkadot/metadata';
import Metadata from '@polkadot/metadata/Decorated';
import rpcDataV3 from '@polkadot/metadata/Metadata/v3/static';
import rpcDataV4 from '@polkadot/metadata/Metadata/v4/static';
import rpcDataV5 from '@polkadot/metadata/Metadata/v5/static';
+1 -1
View File
@@ -5,7 +5,7 @@
import { MetadataLatest, ModuleMetadataLatest } from '../interfaces/metadata';
import fs from 'fs';
import Decorated from '@polkadot/metadata';
import Decorated from '@polkadot/metadata/Decorated';
import rpcdata from '@polkadot/metadata/Metadata/static';
import { stringCamelCase, stringLowerFirst } from '@polkadot/util';
@@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ModuleMetadataLatest } from '../../interfaces/metadata';
import * as definitions from '../../interfaces/definitions';
import fs from 'fs';
import staticData from '@polkadot/metadata/Metadata/static';
@@ -17,14 +18,14 @@ function generateModule (modul: ModuleMetadataLatest, imports: TypeImports): str
return [];
}
setImports(imports, ['Codec']);
setImports(definitions, imports, ['Codec']);
return [indent(4)(`${stringCamelCase(modul.name.toString())}: {`)]
.concat(indent(6)('[index: string]: Codec;'))
.concat(
modul.constants
.map((constant): string => {
setImports(imports, [constant.type.toString()]);
setImports(definitions, imports, [constant.type.toString()]);
return indent(6)(`${stringCamelCase(constant.name.toString())}: ${constant.type} & ConstantCodec;`);
})
@@ -32,12 +33,12 @@ function generateModule (modul: ModuleMetadataLatest, imports: TypeImports): str
.concat([indent(4)('};')]);
}
// Generate `packages/types-jsonrpc/src/jsonrpc.types.ts` for a particular
// Generate `packages/api/src/consts.types.ts` for a particular
// metadata
function generateForMeta (meta: Metadata): void {
console.log('Writing packages/api/src/consts.types.ts');
const imports = createImports(); // Will hold all needed imports
const imports = createImports({ '@polkadot/types/interfaces': definitions }); // Will hold all needed imports
const body = meta.asLatest.modules.reduce((acc, modul): string[] => {
const storageEntries = generateModule(modul, imports);
@@ -4,7 +4,7 @@
import fs from 'fs';
import * as definitions from '../../interfaces/definitions';
import * as defaultDefinitions from '../../interfaces/definitions';
import * as primitiveClasses from '../../primitive';
import {
createImportCode, createImports,
@@ -15,32 +15,34 @@ import {
setImports
} from '../util';
// Generate `packages/types/src/interfaceRegistry.ts`, the registry of all interfaces
export default function generateInterfaceRegistry (): void {
console.log('Writing interfaceRegistry.ts');
export function generateInterfaceRegistry (importDefinitions: { [importPath: string]: object }, output: string): void {
console.log(`Writing ${output}`);
const imports = createImports();
Object.entries(importDefinitions).reduce((acc, def) => Object.assign(acc, def), {} as object);
const imports = createImports(importDefinitions);
const definitions = imports.definitions;
const primitives = Object
.keys(primitiveClasses)
.filter((name): boolean => !!name.indexOf('Generic'))
.reduce((accumulator, primitiveName): string => {
setImports(imports, [primitiveName]);
setImports(definitions, imports, [primitiveName]);
return [
accumulator,
getDerivedTypes(primitiveName, primitiveName, imports).map(indent(2)).join('\n')
getDerivedTypes(definitions, 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));
setImports(definitions, imports, Object.keys(types));
return [
accumulator,
...Object.keys(types).map((type): string =>
getDerivedTypes(type, (types as any)[type], imports).map(indent(2)).join('\n')
getDerivedTypes(definitions, type, types[type], imports).map(indent(2)).join('\n')
)
].join('\n');
}, '');
@@ -55,7 +57,7 @@ export default function generateInterfaceRegistry (): void {
types: Object.keys(imports.primitiveTypes)
},
...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({
file: `@polkadot/types/interfaces/${moduleName}`,
file: `${imports.moduleToPackage[moduleName]}/${moduleName}`,
types: Object.keys(imports.localTypes[moduleName])
}))
]);
@@ -64,8 +66,18 @@ export default function generateInterfaceRegistry (): void {
const interfaceEnd = '\n}';
fs.writeFileSync(
'packages/types/src/interfaceRegistry.ts',
output,
header.concat(interfaceStart).concat(primitives).concat(srml).concat(interfaceEnd).concat(FOOTER)
, { flag: 'w' }
);
}
// Generate `packages/types/src/interfaceRegistry.ts`, the registry of all interfaces
export default function generateDefaultInterfaceRegistry (): void {
generateInterfaceRegistry(
{
'@polkadot/types/interfaces': defaultDefinitions
},
'packages/types/src/interfaceRegistry.ts'
);
}
@@ -4,6 +4,7 @@
import { ModuleMetadataLatest, StorageEntryMetadataLatest } from '../../interfaces/metadata';
import { Registry } from '../../types';
import * as defaultDefinitions from '../../interfaces/definitions';
import fs from 'fs';
import staticData from '@polkadot/metadata/Metadata/static';
@@ -13,42 +14,51 @@ import { Metadata } from '../..';
import { TypeRegistry } from '../../codec';
import { createImportCode, createImports, FOOTER, formatType, getSimilarTypes, HEADER, indent, setImports, TypeImports } from '../util';
// From a storage entry metadata, we return [args, returnType]
function entrySignature (registry: Registry, storageEntry: StorageEntryMetadataLatest, imports: TypeImports): [string, string] {
if (storageEntry.type.isPlain) {
setImports(imports, [storageEntry.type.asPlain.toString()]);
// If the StorageEntry returns T, output `Option<T>` if the modifier is optional
function addModifier (storageEntry: StorageEntryMetadataLatest, returnType: string): string {
if (storageEntry.modifier.isOptional) {
return `Option<${returnType}>`;
}
return ['', formatType(storageEntry.type.asPlain.toString(), imports)];
return returnType;
}
// From a storage entry metadata, we return [args, returnType]
function entrySignature (definitions: object, registry: Registry, storageEntry: StorageEntryMetadataLatest, imports: TypeImports): [string, string] {
if (storageEntry.type.isPlain) {
setImports(definitions, imports, [storageEntry.type.asPlain.toString()]);
return ['', formatType(definitions, addModifier(storageEntry, storageEntry.type.asPlain.toString()), imports)];
} else if (storageEntry.type.isMap) {
// Find similar types of the `key` type
const similarTypes = getSimilarTypes(registry, storageEntry.type.asMap.key.toString(), imports);
const similarTypes = getSimilarTypes(definitions, registry, storageEntry.type.asMap.key.toString(), imports);
setImports(imports, [
setImports(definitions, imports, [
...similarTypes,
storageEntry.type.asMap.value.toString()
]);
return [
`arg: ${similarTypes.map((type) => formatType(type, imports)).join(' | ')}`,
formatType(storageEntry.type.asMap.value.toString(), imports)
`arg: ${similarTypes.map((type) => formatType(definitions, type, imports)).join(' | ')}`,
formatType(definitions, addModifier(storageEntry, storageEntry.type.asMap.value.toString()), imports)
];
} else if (storageEntry.type.isDoubleMap) {
// Find similartypes of `key1` and `key2` types
const similarTypes1 = getSimilarTypes(registry, storageEntry.type.asDoubleMap.key1.toString(), imports);
const similarTypes2 = getSimilarTypes(registry, storageEntry.type.asDoubleMap.key2.toString(), imports);
const similarTypes1 = getSimilarTypes(definitions, registry, storageEntry.type.asDoubleMap.key1.toString(), imports);
const similarTypes2 = getSimilarTypes(definitions, registry, storageEntry.type.asDoubleMap.key2.toString(), imports);
setImports(imports, [
setImports(definitions, 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(' | ');
const key1Types = similarTypes1.map((type) => formatType(definitions, type, imports)).join(' | ');
const key2Types = similarTypes2.map((type) => formatType(definitions, type, imports)).join(' | ');
return [
`key1: ${key1Types}, key2: ${key2Types}`,
formatType(storageEntry.type.asDoubleMap.value.toString(), imports)
formatType(definitions, addModifier(storageEntry, storageEntry.type.asDoubleMap.value.toString()), imports)
];
}
@@ -56,8 +66,8 @@ function entrySignature (registry: Registry, storageEntry: StorageEntryMetadataL
}
// Generate types for one storage entry in a module
function generateEntry (registry: Registry, storageEntry: StorageEntryMetadataLatest, imports: TypeImports): string[] {
const [args, returnType] = entrySignature(registry, storageEntry, imports);
function generateEntry (definitions: object, registry: Registry, storageEntry: StorageEntryMetadataLatest, imports: TypeImports): string[] {
const [args, returnType] = entrySignature(definitions, registry, storageEntry, imports);
return [
`${stringLowerFirst(storageEntry.name.toString())}: StorageEntryExact<ApiType, (${args}) => Observable<${returnType}>> & QueryableStorageEntry<ApiType>;`
@@ -65,7 +75,7 @@ function generateEntry (registry: Registry, storageEntry: StorageEntryMetadataLa
}
// Generate types for one module
function generateModule (registry: Registry, modul: ModuleMetadataLatest, imports: TypeImports): string[] {
function generateModule (definitions: object, registry: Registry, modul: ModuleMetadataLatest, imports: TypeImports): string[] {
if (modul.storage.isNone) {
return [];
}
@@ -75,22 +85,22 @@ function generateModule (registry: Registry, modul: ModuleMetadataLatest, import
.concat(
modul.storage.unwrap().items
.reduce((acc, storageEntry): string[] => {
return acc.concat(generateEntry(registry, storageEntry, imports).map(indent(6)));
return acc.concat(generateEntry(definitions, registry, storageEntry, imports).map(indent(6)));
}, [] as string[])
.join('\n')
)
.concat([indent(4)('};')]);
}
// Generate `packages/types-jsonrpc/src/jsonrpc.types.ts` for a particular
// Generate `packages/api/src/query.types.ts` for a particular
// metadata
function generateForMeta (registry: Registry, meta: Metadata): void {
function generateForMeta (definitions: object, registry: Registry, meta: Metadata): void {
console.log('Writing packages/api/src/query.types.ts');
const imports = createImports(); // Will hold all needed imports
const imports = createImports({ '@polkadot/types/interfaces': definitions }); // Will hold all needed imports
const body = meta.asLatest.modules.reduce((acc, modul): string[] => {
const storageEntries = generateModule(registry, modul, imports);
const storageEntries = generateModule(definitions, registry, modul, imports);
return acc.concat(storageEntries);
}, [] as string[]);
@@ -140,5 +150,5 @@ function generateForMeta (registry: Registry, meta: Metadata): void {
export default function generateQuery (): void {
const registry = new TypeRegistry();
return generateForMeta(registry, new Metadata(registry, staticData));
return generateForMeta(defaultDefinitions, registry, new Metadata(registry, staticData));
}
@@ -5,26 +5,27 @@
import fs from 'fs';
import interfaces from '../../../../type-jsonrpc/src';
import * as definitions from '../../interfaces/definitions';
import { TypeRegistry } from '../../codec/create';
import { createImportCode, createImports, FOOTER, getSimilarTypes, HEADER, setImports } from '../util';
// Generate `packages/types-jsonrpc/src/jsonrpc.types.ts`
// Generate `packages/rpc-core/jsonrpc.types.ts`
export default function generateRpcTypes (): void {
console.log('Writing packages/rpc-core/jsonrpc.types.ts');
const registry = new TypeRegistry();
const imports = createImports();
const imports = createImports({ '@polkadot/types/interfaces': definitions });
const body = Object.keys(interfaces).sort().reduce<string[]>((allSections, section): string[] => {
const allMethods = Object.keys(interfaces[section].methods).sort().map((key): string => {
const method = interfaces[section].methods[key];
setImports(imports, [method.type]);
setImports(definitions, imports, [method.type]);
// FIXME These 2 are too hard to type, I give up
if (section === 'state') {
if (method.method === 'getStorage') {
setImports(imports, ['Codec']);
setImports(definitions, imports, ['Codec']);
return ' getStorage<T = Codec>(key: any, block?: Hash | Uint8Array | string): Observable<T>;';
} else if (method.method === 'subscribeStorage') {
return ' subscribeStorage<T = Codec[]>(keys: any[]): Observable<T>;';
@@ -32,8 +33,8 @@ export default function generateRpcTypes (): void {
}
const args = method.params.map((param): string => {
const similarTypes = getSimilarTypes(registry, param.type, imports);
setImports(imports, [param.type, ...similarTypes]);
const similarTypes = getSimilarTypes(definitions, registry, param.type, imports);
setImports(definitions, imports, [param.type, ...similarTypes]);
return `${param.name}${param.isOptional ? '?' : ''}: ${similarTypes.join(' | ')}`;
});
+67 -150
View File
@@ -5,59 +5,47 @@
import { TypeDef, TypeDefInfo, TypeDefExtVecFixed } from '../../codec/types';
import fs from 'fs';
import path from 'path';
import { isString, stringCamelCase, stringUpperFirst } from '@polkadot/util';
import { getTypeDef } from '../../codec/create';
import * as definitions from '../../interfaces/definitions';
import { createImportCode, createImports, exportInterface, exportType, formatBTreeMap, formatCompact, formatOption, formatResult, formatTuple, formatVec, FOOTER, HEADER, setImports, TypeImports } from '../util';
import * as defaultDefinitions from '../../interfaces/definitions';
import { createImportCode, createImports, exportInterface, exportType, formatType, FOOTER, HEADER, setImports, TypeImports } from '../util';
interface Imports extends TypeImports {
interfaces: [string, string][];
}
// helper to generate a `readonly <Name>: <Type>;` getter
export function createGetter (name = '', type: string, imports: TypeImports, doc?: string): string {
setImports(imports, [type]);
export function createGetter (definitions: object, name = '', type: string, imports: TypeImports, doc?: string): string {
setImports(definitions, 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 {
function errorUnhandled (definitions: object, def: TypeDef, imports: TypeImports): string {
throw new Error(`Generate: ${name}: Unhandled type ${TypeDefInfo[def.info]}`);
}
function tsBTreeMap ({ name: resultName, sub, type }: TypeDef, imports: TypeImports): string {
const [keyDef, valDef] = (sub as TypeDef[]);
setImports(imports, [type]);
return exportInterface(resultName, formatBTreeMap(keyDef.type, valDef.type));
function tsExport (definitions: object, def: TypeDef, imports: TypeImports): string {
return exportInterface(def.name, formatType(definitions, def, imports));
}
function tsCompact ({ name: compactName, sub }: TypeDef, imports: TypeImports): string {
const def = (sub as TypeDef);
const tsBTreeMap = tsExport;
const tsCompact = tsExport;
const tsOption = tsExport;
const tsPlain = tsExport;
const tsTuple = tsExport;
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']);
function tsEnum (definitions: object, { name: enumName, sub }: TypeDef, imports: TypeImports): string {
setImports(definitions, 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}`);
: [`(${type})`, createGetter(definitions, `as${getter}`, type, imports)];
const isGetter = createGetter(definitions, `is${getter}`, 'boolean', imports, `${index}:: ${name}${enumType}`);
switch (info) {
case TypeDefInfo.Plain:
@@ -72,32 +60,11 @@ function tsEnum ({ name: enumName, sub }: TypeDef, imports: TypeImports): string
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 tsResultGetter (resultName = '', getter: 'Ok' | 'Error', { info, name = '', type }: TypeDef, imports: TypeImports): string {
function tsResultGetter (definitions: object, resultName = '', getter: 'Ok' | 'Error', { info, name = '', type }: TypeDef, imports: TypeImports): string {
const [resultType, asGetter] = type === 'Null'
? ['', '']
: [`(${type})`, createGetter(`as${getter}`, type, imports)];
const isGetter = createGetter(`is${getter}`, 'boolean', imports, `${getter}:: ${name}${resultType}`);
: [`(${type})`, createGetter(definitions, `as${getter}`, type, imports)];
const isGetter = createGetter(definitions, `is${getter}`, 'boolean', imports, `${getter}:: ${name}${resultType}`);
switch (info) {
case TypeDefInfo.Plain:
@@ -109,119 +76,57 @@ function tsResultGetter (resultName = '', getter: 'Ok' | 'Error', { info, name =
}
}
function tsResult ({ name: resultName, sub, type }: TypeDef, imports: TypeImports): string {
const [okDef, errorDef] = (sub as TypeDef[]);
function tsResult (definitions: object, def: TypeDef, imports: TypeImports): string {
const [okDef, errorDef] = (def.sub as TypeDef[]);
const inner = [
tsResultGetter(resultName, 'Error', errorDef, imports),
tsResultGetter(resultName, 'Ok', okDef, imports)
tsResultGetter(definitions, def.name, 'Error', errorDef, imports),
tsResultGetter(definitions, def.name, 'Ok', okDef, imports)
].join('');
setImports(imports, [type]);
setImports(definitions, imports, [def.type]);
return exportInterface(resultName, formatResult(okDef.type, errorDef.type), inner);
return exportInterface(def.name, formatType(definitions, def, imports), inner);
}
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']);
function tsSet (definitions: object, { name: setName, sub }: TypeDef, imports: TypeImports): string {
setImports(definitions, imports, ['Set']);
const types = (sub as TypeDef[]).map(({ name }): string =>
createGetter(`is${name}`, 'boolean', imports)
createGetter(definitions, `is${name}`, 'boolean', imports)
);
return exportInterface(setName, 'Set', types.join(''));
}
function tsStruct ({ name: structName, sub }: TypeDef, imports: TypeImports): string {
function tsStruct (definitions: object, { name: structName, sub }: TypeDef, imports: TypeImports): string {
setImports(definitions, imports, ['Struct']);
const keys = (sub as TypeDef[]).map((typedef): string => {
const [embedType, returnType] = _tsStructGetterType(structName, typedef, imports);
const returnType = formatType(definitions, typedef, imports);
setImports(imports, ['Struct', embedType]);
return createGetter(typedef.name, returnType, imports);
return createGetter(definitions, 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;
function tsVec (definitions: object, def: TypeDef, imports: TypeImports): string {
const type = def.info === TypeDefInfo.VecFixed
? (def.ext as TypeDefExtVecFixed).type
: (def.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']);
if (def.info === TypeDefInfo.VecFixed && type === 'u8') {
setImports(definitions, imports, ['Codec']);
return exportType(vectorName, 'Uint8Array, Codec');
return exportType(def.name, 'Uint8Array, Codec');
}
setImports(imports, ['Vec', type]);
return exportType(vectorName, formatVec(type));
return exportInterface(def.name, formatType(definitions, def, imports));
}
function generateInterfaces ({ types }: { types: Record<string, any> }, imports: Imports): [string, string][] {
function generateInterfaces (definitions: object, { types }: { types: Record<string, any> }, 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)
@@ -244,13 +149,14 @@ function generateInterfaces ({ types }: { types: Record<string, any> }, imports:
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)];
return [name, generators[def.info](definitions, def, imports)];
});
}
function generateTsDefFor (defName: string, { types }: { types: Record<string, any> }): void {
const imports = { ...createImports({ types }), interfaces: [] } as Imports;
const interfaces = generateInterfaces({ types }, imports);
function generateTsDefFor (importDefinitions: { [importPath: string]: object }, defName: string, { types }: { types: Record<string, any> }, outputDir: string): void {
const imports = { ...createImports(importDefinitions, { types }), interfaces: [] } as Imports;
const definitions = imports.definitions;
const interfaces = generateInterfaces(definitions, { 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, [
@@ -267,7 +173,7 @@ function generateTsDefFor (defName: string, { types }: { types: Record<string, a
types: Object.keys(imports.primitiveTypes)
},
...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({
file: `@polkadot/types/interfaces/${moduleName}`,
file: `${imports.moduleToPackage[moduleName]}/${moduleName}`,
types: Object.keys(imports.localTypes[moduleName])
}))
]);
@@ -280,19 +186,30 @@ function generateTsDefFor (defName: string, { types }: { types: Record<string, a
}
});
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' });
fs.writeFileSync(path.join(outputDir, defName, 'types.ts'), header.concat(sortedDefs).concat(FOOTER), { flag: 'w' });
fs.writeFileSync(path.join(outputDir, defName, 'index.ts'), HEADER.concat('export * from \'./types\';').concat(FOOTER), { flag: 'w' });
}
export default function generateTsDef (): void {
export function generateTsDef (importDefinitions: { [importPath: string]: object }, outputDir: string, generatingPackage: string): void {
const definitions = importDefinitions[generatingPackage];
Object.entries(definitions).forEach(([defName, obj]): void => {
console.log(`Extracting interfaces for ${defName}`);
generateTsDefFor(defName, obj);
generateTsDefFor(importDefinitions, defName, obj, outputDir);
});
console.log('Writing interfaces/types.ts');
console.log(`Writing ${outputDir}`);
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' });
fs.writeFileSync(path.join(outputDir, 'types.ts'), HEADER.concat(Object.keys(definitions).map((moduleName): string => `export * from './${moduleName}/types';`).join('\n')).concat(FOOTER), { flag: 'w' });
fs.writeFileSync(path.join(outputDir, 'index.ts'), HEADER.concat('export * from \'./types\';').concat(FOOTER), { flag: 'w' });
}
export default function generateTsDefDefault (): void {
generateTsDef(
{
'@polkadot/types/interfaces': defaultDefinitions
},
'packages/types/src/interfaces',
'@polkadot/types/interfaces'
);
}
+32 -16
View File
@@ -2,48 +2,64 @@
// 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 { TypeDef, TypeDefInfo } from '../../codec/types';
import { Constructor, Registry } 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 { formatType } from './formatting';
import { setImports, TypeImports } from './imports';
import * as primitiveClasses from '../../primitive';
// From `T`, generate `Compact<T>, Option<T>, Vec<T>`
export function getDerivedTypes (type: string, primitiveName: string, imports: TypeImports): string[] {
export function getDerivedTypes (definitions: object, 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]);
const def = getTypeDef(type);
setImports(imports, ['Option', 'Vec', isCompact ? 'Compact' : '']);
setImports(definitions, 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);
const types = [
{
info: TypeDefInfo.Option,
type,
sub: def
},
{
info: TypeDefInfo.Vec,
type,
sub: def
}
];
if (isCompact) {
types.unshift({
info: TypeDefInfo.Compact,
type,
sub: def
});
}
const result = types.map(t => formatType(definitions, t, imports)).map(t => `'${t}': ${t};`);
result.unshift(`${type}: ${type};`);
return result;
}
// Make types a little bit more flexible
// - if param instanceof AbstractInt, then param: u64 | Uint8array | string | number
// etc
export function getSimilarTypes (registry: Registry, type: string, imports: TypeImports): string[] {
export function getSimilarTypes (definitions: object, registry: Registry, type: string, imports: TypeImports): string[] {
const possibleTypes = [type];
if (type === 'Extrinsic') {
setImports(imports, ['IExtrinsic']);
setImports(definitions, imports, ['IExtrinsic']);
return ['IExtrinsic'];
}
if (isChildClass(Vec, ClassOfUnsafe(registry, type))) {
return [`(${getSimilarTypes(registry, ((getTypeDef(type).sub) as TypeDef).type, imports).join(' | ')})[]`];
return [`(${getSimilarTypes(definitions, registry, ((getTypeDef(type).sub) as TypeDef).type, imports).join(' | ')})[]`];
}
// FIXME This is a hack, it's hard to correctly type StorageKeys in the
+36 -17
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { TypeDef, TypeDefInfo } from '../../codec/types';
import { TypeDef, TypeDefInfo, TypeDefExtVecFixed } from '../../codec/types';
import { getTypeDef } from '../../codec/create';
import { paramsNotation } from '../../codec/utils';
@@ -37,83 +37,102 @@ export function exportType (name = '', base: string): string {
/**
* Given the inner `K` & `V`, return a `BTreeMap<K, V>` string
*/
export function formatBTreeMap (key: string, val: string): string {
function formatBTreeMap (key: string, val: string): string {
return `BTreeMap<${key}, ${val}>`;
}
/**
* Given the inner `T`, return a `Compact<T>` string
*/
export function formatCompact (inner: string): string {
function formatCompact (inner: string): string {
return paramsNotation('Compact', inner);
}
/**
* Given the inner `O` & `E`, return a `Result<O, E>` string
*/
export function formatResult (innerOk: string, innerError: string): string {
function formatResult (innerOk: string, innerError: string): string {
return `Result<${innerOk}, ${innerError}>`;
}
/**
* Given the inner `T`, return a `Option<T>` string
*/
export function formatOption (inner: string): string {
function formatOption (inner: string): string {
return paramsNotation('Option', inner);
}
/**
* Given the inners `T[]`, return a `ITuple<...T>` string
*/
export function formatTuple (inners: string[]): string {
function formatTuple (inners: string[]): string {
return paramsNotation('ITuple', `[${inners.join(', ')}]`);
}
/**
* Given the inner `T`, return a `Vec<T>` string
*/
export function formatVec (inner: string): string {
function formatVec (inner: string): string {
return paramsNotation('Vec', inner);
}
/**
* Correctly format a given type
*/
export function formatType (type: string | TypeDef, imports: TypeImports): string {
let typeDef;
export function formatType (definitions: object, type: string | TypeDef, imports: TypeImports): string {
let typeDef: TypeDef;
if (typeof type === 'string') {
typeDef = getTypeDef(type);
} else {
typeDef = type;
}
setImports(definitions, imports, [typeDef.type]);
switch (typeDef.info) {
case TypeDefInfo.Compact: {
return formatCompact(formatType((typeDef.sub as TypeDef).type, imports));
setImports(definitions, imports, ['Compact']);
return formatCompact(formatType(definitions, (typeDef.sub as TypeDef).type, imports));
}
case TypeDefInfo.Option: {
return formatOption(formatType((typeDef.sub as TypeDef).type, imports));
setImports(definitions, imports, ['Option']);
return formatOption(formatType(definitions, (typeDef.sub as TypeDef).type, imports));
}
case TypeDefInfo.Plain: {
return typeDef.type;
}
case TypeDefInfo.Vec: {
return formatVec(formatType((typeDef.sub as TypeDef).type, imports));
setImports(definitions, imports, ['Vec']);
return formatVec(formatType(definitions, (typeDef.sub as TypeDef).type, imports));
}
case TypeDefInfo.Tuple: {
setImports(imports, ['ITuple']);
setImports(definitions, imports, ['ITuple']);
// `(a,b)` gets transformed into `ITuple<[a, b]>`
return formatTuple(
((typeDef.sub as TypeDef[])
.map((sub): string => formatType(sub.type, imports)))
.map((sub): string => formatType(definitions, sub.type, imports)))
);
}
case TypeDefInfo.VecFixed: {
setImports(imports, ['U8a']);
if ((typeDef.ext as TypeDefExtVecFixed).type === 'u8') {
setImports(definitions, imports, ['U8a']);
// `[u8, 32]` gets transformed into U8a
return 'U8a';
// `[u8, 32]` gets transformed into U8a
return 'U8a';
}
setImports(definitions, imports, ['Vec']);
return formatVec(formatType(definitions, (typeDef.ext as TypeDefExtVecFixed).type, imports));
}
case TypeDefInfo.BTreeMap: {
setImports(definitions, imports, ['BTreeMap']);
const [keyDef, valDef] = (typeDef.sub as TypeDef[]);
return formatBTreeMap(formatType(definitions, keyDef.type, imports), formatType(definitions, valDef.type, imports));
}
case TypeDefInfo.Result: {
setImports(definitions, imports, ['Result']);
const [okDef, errorDef] = (typeDef.sub as TypeDef[]);
return formatResult(formatType(definitions, okDef.type, imports), formatType(definitions, errorDef.type, imports));
}
default: {
throw new Error(`Cannot format ${type}.`);
+28 -7
View File
@@ -5,7 +5,6 @@
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
@@ -22,11 +21,14 @@ export interface TypeImports {
ignoredTypes: string[]; // No need to import these types
primitiveTypes: TypeExist; // `import {} from '@polkadot/types/primitive`
typesTypes: TypeExist; // `import {} from '@polkadot/types/types`
definitions: object; // all definitions
typeToModule: Record<string, string>;
moduleToPackage: Record<string, string>;
}
// 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 {
export function setImports (definitions: object, imports: TypeImports, types: string[]): void {
const { codecTypes, localTypes, ignoredTypes, primitiveTypes, typesTypes } = imports;
types.forEach((type): void => {
@@ -42,14 +44,14 @@ export function setImports (imports: TypeImports, types: string[]): void {
// 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]]);
setImports(definitions, imports, [TypeDefInfo[typeDef.info]]);
// TypeDef.sub is a `TypeDef | TypeDef[]`
if (Array.isArray(typeDef.sub)) {
typeDef.sub.forEach((subType): void => setImports(imports, [subType.type]));
typeDef.sub.forEach((subType): void => setImports(definitions, imports, [subType.type]));
} else if (typeDef.sub) {
// typeDef.sub is a TypeDef in this case
setImports(imports, [typeDef.sub.type]);
setImports(definitions, imports, [typeDef.sub.type]);
}
} else {
// find this module inside the exports from the rest
@@ -65,7 +67,26 @@ export function setImports (imports: TypeImports, types: string[]): void {
}
// Create an Imports object, can be prefilled with `ignoredTypes`
export function createImports ({ types }: { types: Record<string, any> } = { types: {} }): TypeImports {
export function createImports (importDefinitions: { [importPath: string]: object }, { types }: { types: Record<string, any> } = { types: {} }): TypeImports {
const definitions = {} as Record<string, object>;
const typeToModule = {} as Record<string, string>;
const moduleToPackage = {} as Record<string, string>;
for (const [packagePath, packageDef] of Object.entries(importDefinitions)) {
for (const [name, moduleDef] of Object.entries(packageDef)) {
if (definitions[name]) {
throw new Error(`Duplicated module: ${name}. Packages: ${packagePath}, ${moduleToPackage[name]}`);
}
definitions[name] = moduleDef;
moduleToPackage[name] = packagePath;
for (const type of Object.keys(moduleDef.types)) {
if (typeToModule[type]) {
throw new Error(`Duplicated type: ${type}. Modules: ${name}, ${typeToModule[type]}`);
}
typeToModule[type] = name;
}
}
}
const codecTypes: TypeExist = {};
const localTypes: TypeExistMap = Object.keys(definitions).reduce((localTypes: Record<string, TypeExist>, moduleName): Record<string, TypeExist> => {
localTypes[moduleName] = {};
@@ -76,7 +97,7 @@ export function createImports ({ types }: { types: Record<string, any> } = { typ
const primitiveTypes: TypeExist = {};
const typesTypes: TypeExist = {};
const imports = { codecTypes, localTypes, ignoredTypes, primitiveTypes, typesTypes };
const imports = { codecTypes, localTypes, ignoredTypes, primitiveTypes, typesTypes, definitions, typeToModule, moduleToPackage };
return imports;
}
+17 -8
View File
@@ -4,15 +4,11 @@
import { SignOptions } from '@polkadot/keyring/types';
import { FunctionMetadataLatest } from './interfaces/metadata';
import { Balance, EcdsaSignature, Ed25519Signature, Index, Sr25519Signature } from './interfaces/runtime';
import { Address, Balance, Call, EcdsaSignature, Ed25519Signature, Index, Sr25519Signature } from './interfaces/runtime';
import BN from 'bn.js';
import Compact from './codec/Compact';
import U8a from './codec/U8a';
import { InterfaceRegistry } from './interfaceRegistry';
import Call from './primitive/Generic/Call';
import Address from './primitive/Generic/Address';
export * from './codec/types';
@@ -125,8 +121,21 @@ export interface Codec {
toU8a (isBare?: BareOpts): Uint8Array;
}
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
export interface IU8a extends Uint8Array, Codec {
bitLength (): number;
toJSON (): any;
}
// eslint-disable-next-line @typescript-eslint/interface-name-prefix,@typescript-eslint/no-empty-interface
export interface IHash extends U8a { }
export interface IHash extends IU8a { }
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
export interface ICompact<T> extends Codec {
toBn (): BN;
toNumber (): number;
unwrap (): T;
}
export type CodecTo = 'toHex' | 'toJSON' | 'toString' | 'toU8a';
@@ -181,10 +190,10 @@ export interface IMethod extends Codec {
interface ExtrinsicSignatureBase {
readonly isSigned: boolean;
readonly era: IExtrinsicEra;
readonly nonce: Compact<Index>;
readonly nonce: ICompact<Index>;
readonly signature: EcdsaSignature | Ed25519Signature | Sr25519Signature;
readonly signer: Address;
readonly tip: Compact<Balance>;
readonly tip: ICompact<Balance>;
}
export interface ExtrinsicPayloadValue {