subscribeNewHeads (#1338)

* subscribeNewHeads

* Update CHANGELOG

* Rebuild interfaces

* Sort interfaces, really expose plural

* Fix mocks
This commit is contained in:
Jaco Greeff
2019-08-24 12:10:42 +02:00
committed by GitHub
parent 1ef567558e
commit 895ed80449
23 changed files with 49 additions and 44 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ import { drr } from '../util/drr';
*/
export function bestNumber (api: ApiInterfaceRx): () => Observable<BlockNumber> {
return (): Observable<BlockNumber> =>
api.rpc.chain.subscribeNewHead().pipe(
api.rpc.chain.subscribeNewHeads().pipe(
map((header): BlockNumber => header.number.unwrap()),
drr()
);
+1 -1
View File
@@ -8,7 +8,7 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { HeaderExtended } from '../type';
import { drr } from '../util/drr';
import { HeaderAndValidators } from './subscribeNewHead';
import { HeaderAndValidators } from './subscribeNewHeads';
/**
* @name bestNumberFinalized
+1 -1
View File
@@ -6,4 +6,4 @@ export * from './bestNumber';
export * from './bestNumberFinalized';
export * from './bestNumberLag';
export * from './getHeader';
export * from './subscribeNewHead';
export * from './subscribeNewHeads';
@@ -14,21 +14,21 @@ import { drr } from '../util/drr';
export type HeaderAndValidators = [Header, AccountId[]];
/**
* @name subscribeNewHead
* @name subscribeNewHeads
* @returns An array containing the block header and the block author
* @description An observable of the current block header and it's author
* @example
* <BR>
*
* ```javascript
* api.derive.chain.subscribeNewHead(({ author, blockNumber }) => {
* api.derive.chain.subscribeNewHeads(({ author, blockNumber }) => {
* console.log(`block #${blockNumber} was authored by ${author}`);
* });
* ```
*/
export function subscribeNewHead (api: ApiInterfaceRx): () => Observable<HeaderExtended> {
export function subscribeNewHeads (api: ApiInterfaceRx): () => Observable<HeaderExtended> {
return (): Observable<HeaderExtended> =>
api.rpc.chain.subscribeNewHead().pipe(
api.rpc.chain.subscribeNewHeads().pipe(
switchMap((header: Header): Observable<HeaderAndValidators> =>
(combineLatest([
of(header),
+2 -2
View File
@@ -45,7 +45,7 @@ import { ApiPromise } from '@polkadot/api';
const api = await ApiPromise.create();
// make a call to retrieve the current network head
api.rpc.chain.subscribeNewHead((header) => {
api.rpc.chain.subscribeNewHeads((header) => {
console.log(`Chain is at #${header.blockNumber}`);
});
```
@@ -59,7 +59,7 @@ import { ApiRx } from '@polkadot/api';
const api = await ApiRx.create().toPromise();
// make a call to retrieve the current network head
api.rpc.chain.subscribeNewHead().subscribe((header) => {
api.rpc.chain.subscribeNewHeads().subscribe((header) => {
console.log(`Chain is at #${header.blockNumber}`);
});
```
+1 -1
View File
@@ -82,7 +82,7 @@ export default abstract class Decorate<ApiType> extends Events {
*
* const api = new Api().isReady();
*
* api.rpc.subscribeNewHead((header) => {
* api.rpc.subscribeNewHeads((header) => {
* console.log(`new block #${header.number.toNumber()}`);
* });
* ```
+2 -2
View File
@@ -47,7 +47,7 @@ export default abstract class ApiBase<ApiType> extends Init<ApiType> {
*
* const api = new Api().isReady();
*
* api.rpc.subscribeNewHead((header) => {
* api.rpc.subscribeNewHeads((header) => {
* console.log(`new block #${header.number.toNumber()}`);
* });
* ```
@@ -169,7 +169,7 @@ export default abstract class ApiBase<ApiType> extends Init<ApiType> {
* <BR>
*
* ```javascript
* api.rpc.chain.subscribeNewHead((header) => {
* api.rpc.chain.subscribeNewHeads((header) => {
* console.log('new header', header);
* });
* ```
+2 -2
View File
@@ -24,7 +24,7 @@ async function consts (api: ApiPromise): Promise<void> {
}
async function derive (api: ApiPromise): Promise<void> {
await api.derive.chain.subscribeNewHead((header: HeaderExtended): void => {
await api.derive.chain.subscribeNewHeads((header: HeaderExtended): void => {
console.log('current author:', header.author);
});
@@ -49,7 +49,7 @@ async function query (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
}
async function rpc (api: ApiPromise): Promise<void> {
await api.rpc.chain.subscribeNewHead((header: Header): void => {
await api.rpc.chain.subscribeNewHeads((header: Header): void => {
console.log('current header:', header);
});
+3 -3
View File
@@ -82,7 +82,7 @@ function promiseTracker (resolve: (value: () => void) => void, reject: (value: E
* const api = await ApiPromise.create();
*
* // make a subscription to the network head
* api.rpc.chain.subscribeNewHead((header) => {
* api.rpc.chain.subscribeNewHeads((header) => {
* console.log(`Chain is at #${header.number}`);
* });
* ```
@@ -176,7 +176,7 @@ export default class ApiPromise extends ApiBase<'promise'> {
* import Api from '@polkadot/api/promise';
*
* new Api().isReady.then((api) => {
* api.rpc.subscribeNewHead((header) => {
* api.rpc.subscribeNewHeads((header) => {
* console.log(`new block #${header.number.toNumber()}`);
* });
* });
@@ -221,7 +221,7 @@ export default class ApiPromise extends ApiBase<'promise'> {
*
* // combines values from balance & nonce as it updates
* api.combineLatest([
* api.rpc.chain.subscribeNewHead,
* api.rpc.chain.subscribeNewHeads,
* [api.query.balances.freeBalance, address],
* (cb) => api.query.system.accountNonce(address, cb)
* ], ([head, balance, nonce]) => {
+3 -3
View File
@@ -35,7 +35,7 @@ import ApiBase from '../base';
* const api = await ApiRx.create().toPromise();
*
* // make a call to retrieve the current network head
* api.rpc.chain.subscribeNewHead().subscribe((header) => {
* api.rpc.chain.subscribeNewHeads().subscribe((header) => {
* console.log(`Chain is at #${header.number}`);
* });
* ```
@@ -125,7 +125,7 @@ export default class ApiRx extends ApiBase<'rxjs'> {
* Api.create()
* .pipe(
* switchMap((api) =>
* api.rpc.chain.subscribeNewHead()
* api.rpc.chain.subscribeNewHeads()
* ))
* .subscribe((header) => {
* console.log(`new block #${header.number.toNumber()}`);
@@ -149,7 +149,7 @@ export default class ApiRx extends ApiBase<'rxjs'> {
* new Api().isReady
* .pipe(
* switchMap((api) =>
* api.rpc.chain.subscribeNewHead()
* api.rpc.chain.subscribeNewHeads()
* ))
* .subscribe((header) => {
* console.log(`new block #${header.number.toNumber()}`);
@@ -31,7 +31,7 @@ describeE2E()('Derive Promise e2e', (wsUrl: string): void => {
});
it('subscribes to newHead, retrieving the actual validator', (done): Promise<() => void> => {
return api.derive.chain.subscribeNewHead(({ author }: HeaderExtended): void => {
return api.derive.chain.subscribeNewHeads(({ author }: HeaderExtended): void => {
console.log('author', author && author.toString());
if (author) {
+2 -2
View File
@@ -199,10 +199,10 @@ describeE2E({
});
});
describe('subscribeNewHead', (): void => {
describe('subscribeNewHeads', (): void => {
it('gets an observable of the current block header and it\'s author', async (done): Promise<void> => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
api.derive.chain.subscribeNewHead().subscribe((headerExtended: HeaderExtended): void => {
api.derive.chain.subscribeNewHeads().subscribe((headerExtended: HeaderExtended): void => {
// WIP https://github.com/polkadot-js/api/issues/868
done();
});
@@ -33,7 +33,7 @@ describeE2E()('Promise e2e queries', (wsUrl: string): void => {
it('subscribes to rpc', (done): Promise<() => void> => {
return (
api.rpc.chain.subscribeNewHead((header: Header): void => {
api.rpc.chain.subscribeNewHeads((header: Header): void => {
expect(header.number.isEmpty).toBe(false);
done();
@@ -53,7 +53,7 @@ describeE2E()('Promise e2e queries', (wsUrl: string): void => {
it('subscribes to derive', (done): Promise<() => void> => {
return (
api.derive.chain.subscribeNewHead((header: HeaderExtended): void => {
api.derive.chain.subscribeNewHeads((header: HeaderExtended): void => {
expect(header.number.isEmpty).toBe(false);
done();
@@ -82,7 +82,7 @@ describeE2E({
const blockHash = signedBlock.block.header.hash;
const ex = api.tx.balances.transfer(keyring.eve.address, 12345);
await api.rpc.chain.subscribeNewHead(async (header: Header): Promise<void> => {
await api.rpc.chain.subscribeNewHeads(async (header: Header): Promise<void> => {
if (header.number.toNumber() === eraDeath - 1) {
try {
await ex.signAndSend(keyring.alice, { blockHash, era: exERA, nonce } as any);
@@ -111,7 +111,7 @@ describeE2E({
const blockHash = signedBlock.block.header.hash;
const ex = api.tx.balances.transfer(keyring.eve.address, 12121);
await api.rpc.chain.subscribeNewHead(async (header: Header): Promise<void> => {
await api.rpc.chain.subscribeNewHeads(async (header: Header): Promise<void> => {
if (header.number.toNumber() === eraDeath - 1) {
try {
await ex.signAndSend(keyring.alice.address, { blockHash, era: exERA, nonce } as any);
+2 -2
View File
@@ -23,11 +23,11 @@ describeE2E({
rpc = new Rpc(new WsProvider(wsUrl));
});
it('subscribes via subscribeNewHead', (done): void => {
it('subscribes via subscribeNewHeads', (done): void => {
let count = 0;
rpc.chain
.subscribeNewHead()
.subscribeNewHeads()
.subscribe((header: Header): void => {
expect(header).toBeInstanceOf(ClassOf('Header'));
+1 -1
View File
@@ -60,7 +60,7 @@ Retrieving best header via subscription -
```js
api.chain
rpc
.subscribeNewHead()
.subscribeNewHeads()
.subscribe(
(header) => {
console.log(`best #${header.blockNumber}`);
+6 -6
View File
@@ -24,8 +24,8 @@ describe('Cached Observables', (): void => {
});
it('creates a single observable for subscriptions (multiple calls, no arguments)', (): void => {
const observable1 = rpc.chain.subscribeNewHead();
const observable2 = rpc.chain.subscribeNewHead();
const observable1 = rpc.chain.subscribeNewHeads();
const observable2 = rpc.chain.subscribeNewHeads();
expect(observable2).toBe(observable1);
});
@@ -45,8 +45,8 @@ describe('Cached Observables', (): void => {
});
it('clears cache if there are no more subscribers', (): void => {
const observable1 = rpc.chain.subscribeNewHead();
const observable2 = rpc.chain.subscribeNewHead();
const observable1 = rpc.chain.subscribeNewHeads();
const observable2 = rpc.chain.subscribeNewHeads();
expect(observable1).toBe(observable2);
@@ -57,14 +57,14 @@ describe('Cached Observables', (): void => {
sub2.unsubscribe();
// No more subscribers, now create a new observable
const observable3 = rpc.chain.subscribeNewHead();
const observable3 = rpc.chain.subscribeNewHeads();
expect(observable3).not.toBe(observable1);
});
it('creates different observables for different methods but same arguments', (): void => {
// @ts-ignore
const observable1 = rpc.chain.subscribeNewHead([123]);
const observable1 = rpc.chain.subscribeNewHeads([123]);
const observable2 = rpc.state.subscribeStorage([123]);
expect(observable2).not.toBe(observable1);
+3 -3
View File
@@ -11,11 +11,11 @@ import { Codec, IExtrinsic } from '@polkadot/types/types';
export interface RpcInterface {
author: {
insertKey(keyType: Text | string, suri: Text | string, maybePublic?: Bytes | Uint8Array | string): Observable<Bytes>;
pendingExtrinsics(): Observable<Vec<Extrinsic>>;
removeExtrinsic(bytesOrHash: (ExtrinsicOrHash)[]): Observable<Vec<Hash>>;
rotateKeys(): Observable<Bytes>;
pendingExtrinsics(): Observable<Vec<Extrinsic>>;
submitExtrinsic(extrinsic: IExtrinsic): Observable<Hash>;
submitAndWatchExtrinsic(extrinsic: IExtrinsic): Observable<ExtrinsicStatus>;
submitExtrinsic(extrinsic: IExtrinsic): Observable<Hash>;
};
chain: {
getBlock(hash?: Hash | Uint8Array | string): Observable<SignedBlock>;
@@ -24,8 +24,8 @@ export interface RpcInterface {
getHeader(hash?: Hash | Uint8Array | string): Observable<Header>;
getRuntimeVersion(hash?: Hash | Uint8Array | string): Observable<RuntimeVersion>;
subscribeFinalizedHeads(): Observable<Header>;
subscribeNewHeads(): Observable<Header>;
subscribeRuntimeVersion(): Observable<RuntimeVersion>;
subscribeNewHead(): Observable<Header>;
};
state: {
call(method: Text | string, data: Bytes | Uint8Array | string, block?: Hash | Uint8Array | string): Observable<Bytes>;
+1 -1
View File
@@ -54,7 +54,7 @@ describe('replay', (): void => {
it('unsubscribes as required', (done): void => {
rpc.provider.unsubscribe = jest.fn();
const subscription = rpc.chain.subscribeNewHead().subscribe((): void => {
const subscription = rpc.chain.subscribeNewHeads().subscribe((): void => {
subscription.unsubscribe();
// There's a promise inside .unsubscribe(), wait a bit
+1
View File
@@ -30,6 +30,7 @@ const SUBSCRIPTIONS: string[] = Array.prototype.concat.apply(
.map(({ method, section }): string =>
`${section}_${method}`
)
.concat('chain_subscribeNewHead')
)
);
+3 -2
View File
@@ -47,9 +47,10 @@ const getRuntimeVersion: RpcMethodOpt = {
type: 'RuntimeVersion'
};
const subscribeNewHead: RpcMethodOpt = {
const subscribeNewHeads: RpcMethodOpt = {
description: 'Retrieves the best header via subscription',
params: [],
// NOTE These still has the aliassed version, compatible with 1.x
pubsub: [
'newHead',
'subscribeNewHead',
@@ -98,6 +99,6 @@ export default {
getRuntimeVersion: createMethod(section, 'getRuntimeVersion', getRuntimeVersion),
subscribeFinalizedHeads: createMethod(section, 'subscribeFinalizedHeads', subscribeFinalizedHeads),
subscribeRuntimeVersion: createMethod(section, 'subscribeRuntimeVersion', subscribeRuntimeVersion),
subscribeNewHead: createMethod(section, 'subscribeNewHead', subscribeNewHead)
subscribeNewHeads: createMethod(section, 'subscribeNewHeads', subscribeNewHeads)
}
};
+4 -2
View File
@@ -465,8 +465,10 @@ function generateRpcTypes (): void {
const imports = createImports({ types: allImportedTypes });
const body = Object.keys(interfaces).reduce<string[]>((allSections, section): string[] => {
const allMethods = Object.values(interfaces[section].methods).map((method): string => {
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];
// FIXME These 2 are too hard to type, I give up
if (method.method === 'getStorage') {
setImports(imports, ['Codec']);