subscribeNewHeads (#1338)
* subscribeNewHeads * Update CHANGELOG * Rebuild interfaces * Sort interfaces, really expose plural * Fix mocks
This commit is contained in:
@@ -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()
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -6,4 +6,4 @@ export * from './bestNumber';
|
||||
export * from './bestNumberFinalized';
|
||||
export * from './bestNumberLag';
|
||||
export * from './getHeader';
|
||||
export * from './subscribeNewHead';
|
||||
export * from './subscribeNewHeads';
|
||||
|
||||
+4
-4
@@ -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),
|
||||
@@ -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}`);
|
||||
});
|
||||
```
|
||||
|
||||
@@ -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()}`);
|
||||
* });
|
||||
* ```
|
||||
|
||||
@@ -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);
|
||||
* });
|
||||
* ```
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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]) => {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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'));
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ Retrieving best header via subscription -
|
||||
```js
|
||||
api.chain
|
||||
rpc
|
||||
.subscribeNewHead()
|
||||
.subscribeNewHeads()
|
||||
.subscribe(
|
||||
(header) => {
|
||||
console.log(`best #${header.blockNumber}`);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -30,6 +30,7 @@ const SUBSCRIPTIONS: string[] = Array.prototype.concat.apply(
|
||||
.map(({ method, section }): string =>
|
||||
`${section}_${method}`
|
||||
)
|
||||
.concat('chain_subscribeNewHead')
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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']);
|
||||
|
||||
Reference in New Issue
Block a user