diff --git a/client/lib/source/ws-source.ts b/client/lib/source/ws-source.ts index 1dcbb51..53b757d 100644 --- a/client/lib/source/ws-source.ts +++ b/client/lib/source/ws-source.ts @@ -1,17 +1,18 @@ -import { Observable, Subject } from 'rxjs' +import { Observable } from 'rxjs' +import { map } from 'rxjs/operators' import { webSocket, WebSocketSubject, WebSocketSubjectConfig } from 'rxjs/webSocket' import { Update } from '../types' import { Source } from './source' export class WebsocketSource implements Source { - private websocket$: WebSocketSubject> | undefined + private websocket$: WebSocketSubject>> | undefined constructor ( private readonly url: string, ) { } watch$ (): Observable> { - const fullConfig: WebSocketSubjectConfig> = { + const fullConfig: WebSocketSubjectConfig>> = { url: this.url, openObserver: { next: () => { @@ -20,6 +21,51 @@ export class WebsocketSource implements Source { }, } this.websocket$ = webSocket(fullConfig) - return this.websocket$ + return this.websocket$.pipe( + map(res => { + if (isRpcSuccess(res)) return res.result + if (isRpcError(res)) throw new RpcError(res.error) + }), + ) as Observable> } } + +interface RPCBase { + jsonrpc: '2.0' +} + +export interface RPCSuccess extends RPCBase { + result: T +} + +export interface RPCError extends RPCBase { + error: { + code: number // 34 means unauthenticated + message: string + data: { + details: string + } + } +} + +export type RPCResponse = RPCSuccess | RPCError + +function isRpcError (arg: { error: Error } | { result: Result}): arg is { error: Error } { + return !!(arg as any).error +} + +function isRpcSuccess (arg: { error: Error } | { result: Result}): arg is { result: Result } { + return !!(arg as any).result +} + +class RpcError { + code: number + message: string + details: string + + constructor (e: RPCError['error']) { + this.code = e.code + this.message = e.message + this.details = e.data.details + } +} \ No newline at end of file