11/* eslint-disable unicorn/prefer-add-event-listener */
22
33import {
4- AsyncReturnType ,
54 Cardano ,
65 EpochInfo ,
76 EraSummary ,
8- NetworkInfoMethods ,
7+ HealthCheckResponse ,
98 NetworkInfoProvider ,
9+ Provider ,
1010 ProviderError ,
1111 ProviderFailure ,
1212 StakeSummary ,
1313 SupplySummary ,
14- WSMessage ,
15- WsProvider ,
1614 createSlotEpochInfoCalc
1715} from '@cardano-sdk/core' ;
1816import { Logger } from 'ts-log' ;
@@ -22,6 +20,19 @@ import WebSocket from 'isomorphic-ws';
2220
2321const NOT_CONNECTED_ID = 'not-connected' ;
2422
23+ export type AsyncReturnType < F extends ( ) => unknown > = F extends ( ) => Promise < infer R > ? R : never ;
24+
25+ export type NetworkInfoMethods = Exclude < keyof NetworkInfoProvider , 'healthCheck' > ;
26+ export type NetworkInfoResponses = { [ m in NetworkInfoMethods ] : AsyncReturnType < NetworkInfoProvider [ m ] > } ;
27+
28+ export interface WSMessage {
29+ /** The client id assigned by the server. */
30+ clientId ?: string ;
31+
32+ /** Latest value(s) for the `NetworkInfoProvider` methods.*/
33+ networkInfo ?: Partial < NetworkInfoResponses > ;
34+ }
35+
2536type WSStatus = 'connecting' | 'connected' | 'idle' | 'stop' ;
2637
2738export type WSHandler = ( message : WSMessage ) => void ;
@@ -54,6 +65,35 @@ const isEventError = (error: unknown): error is { error: Error } =>
5465 // eslint-disable-next-line @typescript-eslint/no-explicit-any
5566 typeof error === 'object' && ! ! error && ( error as any ) . error instanceof Error ;
5667
68+ export class WsProvider implements Provider {
69+ /** Emits the health state. */
70+ public health$ : Observable < HealthCheckResponse > ;
71+
72+ private healthSubject$ : ReplaySubject < HealthCheckResponse > ;
73+ private reason ?: string ;
74+
75+ constructor ( ) {
76+ this . health$ = this . healthSubject$ = new ReplaySubject < HealthCheckResponse > ( 1 ) ;
77+ this . healthSubject$ . next ( { ok : false , reason : 'starting' } ) ;
78+ }
79+
80+ protected emitHealth ( reason ?: string , overwrite ?: boolean ) {
81+ if ( ! reason ) {
82+ this . reason = undefined ;
83+
84+ return this . healthSubject$ . next ( { ok : true } ) ;
85+ }
86+
87+ if ( overwrite || ! this . reason ) this . reason = reason ;
88+
89+ this . healthSubject$ . next ( { ok : false , reason : this . reason } ) ;
90+ }
91+
92+ public healthCheck ( ) {
93+ return firstValueFrom ( this . health$ ) ;
94+ }
95+ }
96+
5797export class CardanoWsClient extends WsProvider {
5898 /** The client id, assigned by the server. */
5999 clientId = NOT_CONNECTED_ID ;
0 commit comments