Track Finalised events on api-rx (as per promise) (#500)
* Track Finalised events on api-rx (as per promise) * Align naming of tracking helper * Remove wtf * Warn on extrinsic not found * Fix unused imports
This commit is contained in:
@@ -4,9 +4,12 @@
|
||||
|
||||
import { KeyringPair } from '@polkadot/keyring/types';
|
||||
import { AnyNumber, AnyU8a } from '@polkadot/types/types';
|
||||
import { ApiPromiseInterface, SubmittableSendResult } from './types';
|
||||
import { SubmittableSendResult } from '../types';
|
||||
import { ApiPromiseInterface } from './types';
|
||||
|
||||
import { EventRecord, Extrinsic, ExtrinsicStatus, Hash, Method, SignedBlock, u32 } from '@polkadot/types/index';
|
||||
import { EventRecord, Extrinsic, ExtrinsicStatus, Hash, Method, SignedBlock } from '@polkadot/types/index';
|
||||
|
||||
import filterEvents from '../util/filterEvents';
|
||||
|
||||
export default class SubmittableExtrinsic extends Extrinsic {
|
||||
private _api: ApiPromiseInterface;
|
||||
@@ -17,24 +20,17 @@ export default class SubmittableExtrinsic extends Extrinsic {
|
||||
this._api = api;
|
||||
}
|
||||
|
||||
private checkStatus (statusCb: (result: SubmittableSendResult) => any): (status: ExtrinsicStatus) => Promise<void> {
|
||||
// FIXME split into graph derivation once available
|
||||
private trackStatus (statusCb: (result: SubmittableSendResult) => any): (status: ExtrinsicStatus) => Promise<void> {
|
||||
return async (status: ExtrinsicStatus): Promise<void> => {
|
||||
let events: Array<any> | undefined = undefined;
|
||||
|
||||
if (status.type === 'Finalised') {
|
||||
const blockHash = status.value as Hash;
|
||||
const { block: { extrinsics } }: SignedBlock = await this._api.rpc.chain.getBlock(blockHash);
|
||||
const signedBlock: SignedBlock = await this._api.rpc.chain.getBlock(blockHash);
|
||||
const allEvents: Array<EventRecord> = await this._api.query.system.events.at(blockHash) as any;
|
||||
|
||||
const index = extrinsics
|
||||
.map((ext) => ext.hash.toHex())
|
||||
.indexOf(this.hash.toHex());
|
||||
|
||||
if (index !== -1) {
|
||||
events = allEvents.filter(({ phase }) =>
|
||||
phase.type === 'ApplyExtrinsic' && (phase.value as u32).eqn(index)
|
||||
);
|
||||
}
|
||||
events = filterEvents(this.hash, signedBlock, allEvents);
|
||||
}
|
||||
|
||||
statusCb({
|
||||
@@ -50,7 +46,7 @@ export default class SubmittableExtrinsic extends Extrinsic {
|
||||
return this._api.rpc.author.submitExtrinsic(this);
|
||||
}
|
||||
|
||||
return this._api.rpc.author.submitAndWatchExtrinsic(this, this.checkStatus(statusCb));
|
||||
return this._api.rpc.author.submitAndWatchExtrinsic(this, this.trackStatus(statusCb));
|
||||
}
|
||||
|
||||
sign (signerPair: KeyringPair, nonce: AnyNumber, blockHash?: AnyU8a): SubmittableExtrinsic {
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
|
||||
import { KeyringPair } from '@polkadot/keyring/types';
|
||||
import { AnyNumber, AnyU8a } from '@polkadot/types/types';
|
||||
import { ApiRxInterface, SubmittableSendResult } from './types';
|
||||
import { SubmittableSendResult } from '../types';
|
||||
import { ApiRxInterface } from './types';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Extrinsic, ExtrinsicStatus, Method } from '@polkadot/types/index';
|
||||
import { Observable, of, combineLatest } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { Extrinsic, ExtrinsicStatus, Hash, Method } from '@polkadot/types/index';
|
||||
|
||||
import filterEvents from '../util/filterEvents';
|
||||
|
||||
export default class SubmittableExtrinsic extends Extrinsic {
|
||||
private _api: ApiRxInterface;
|
||||
@@ -19,15 +22,33 @@ export default class SubmittableExtrinsic extends Extrinsic {
|
||||
this._api = api;
|
||||
}
|
||||
|
||||
// FIXME split into graph derivation once available
|
||||
private trackStatus = (status: ExtrinsicStatus): Observable<SubmittableSendResult> => {
|
||||
if (status.type !== 'Finalised') {
|
||||
return of({
|
||||
status,
|
||||
type: status.type
|
||||
});
|
||||
}
|
||||
|
||||
const blockHash = status.value as Hash;
|
||||
|
||||
return combineLatest(
|
||||
this._api.rpc.chain.getBlock(blockHash),
|
||||
this._api.query.system.events.at(blockHash)
|
||||
).pipe(
|
||||
map(([signedBlock, allEvents]) => ({
|
||||
events: filterEvents(this.hash, signedBlock, allEvents as any),
|
||||
status,
|
||||
type: status.type
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
send (): Observable<SubmittableSendResult> {
|
||||
return this._api.rpc.author
|
||||
.submitAndWatchExtrinsic(this)
|
||||
.pipe(
|
||||
map((status: ExtrinsicStatus) => ({
|
||||
status,
|
||||
type: status.type
|
||||
}))
|
||||
);
|
||||
.pipe(switchMap(this.trackStatus));
|
||||
}
|
||||
|
||||
sign (signerPair: KeyringPair, nonce: AnyNumber, blockHash?: AnyU8a): SubmittableExtrinsic {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import { ProviderInterface } from '@polkadot/rpc-provider/types';
|
||||
import { RpcRxInterface$Events } from '@polkadot/rpc-rx/types';
|
||||
import { Hash, Metadata, RuntimeVersion } from '@polkadot/types/index';
|
||||
import { EventRecord, ExtrinsicStatus, Hash, Metadata, RuntimeVersion } from '@polkadot/types/index';
|
||||
import { Constructor } from '@polkadot/types/types';
|
||||
|
||||
export type ApiInterface$Events = RpcRxInterface$Events | 'ready';
|
||||
@@ -33,3 +33,9 @@ export interface ApiOptions {
|
||||
*/
|
||||
types?: {[name: string]: Constructor};
|
||||
}
|
||||
|
||||
export type SubmittableSendResult = {
|
||||
events?: Array<EventRecord>,
|
||||
status: ExtrinsicStatus,
|
||||
type: string
|
||||
};
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2017-2018 @polkadot/api 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 { EventRecord, Hash, SignedBlock, u32 } from '@polkadot/types/index';
|
||||
|
||||
import l from './logging';
|
||||
|
||||
export default function filterEvents (extHash: Hash, { block: { extrinsics, header } }: SignedBlock, allEvents: Array<EventRecord>): Array<EventRecord> | undefined {
|
||||
// extrinsics to hashes
|
||||
const myHash = extHash.toHex();
|
||||
const allHashes = extrinsics.map((ext) => ext.hash.toHex());
|
||||
|
||||
// find the index of our extrinsic in the block
|
||||
const index = allHashes.indexOf(myHash);
|
||||
|
||||
// if we do get the block after Finalised, it _should_ be there
|
||||
if (index === -1) {
|
||||
l.warn(`block ${header.hash}: Unable to find extrinsic ${myHash} inside ${allHashes}`);
|
||||
return;
|
||||
}
|
||||
|
||||
return allEvents.filter(({ phase }) =>
|
||||
// only ApplyExtrinsic has the extrinsic index
|
||||
phase.type === 'ApplyExtrinsic' && (phase.value as u32).eqn(index)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2017-2018 @polkadot/api 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 { logger } from '@polkadot/util';
|
||||
|
||||
const l = logger('api/util');
|
||||
|
||||
export default l;
|
||||
Reference in New Issue
Block a user