import { WatcherProxy, WebsocketPayload } from "../interfaces/watcher-proxy.i"; import { switchMap, filter, delay, shareReplay, finalize, retry, tap } from "rxjs/operators"; import { Observable, of, Observer, BehaviorSubject } from "rxjs"; import { WebSocketSubject } from 'rxjs/webSocket'; /** * @description * Connect to the augmented node through a websocket (Mostly intended for browser use) * This class manage websocket reconnection and also manage the clientID used to identify the channel on the backend */ export class ProxiedWatcherProxy implements WatcherProxy { constructor( private proxyUrl: string, private appIdSelector: () => string | null = () => localStorage.getItem('appID'), private proxiedWsConfig: { url: string, params: { headers?: { apiKey?: string; } } } ) { } private retrySubject = new BehaviorSubject({}) private initObservable: Observable> = this.retrySubject.pipe(switchMap(() => { return Observable.create((obs: Observer>) => { this.websocketSubject.next({ 'action': 'init-proxy-connection', 'body': this.proxiedWsConfig }); obs.next(this.websocketObs); }); })); private websocketSubject = new WebSocketSubject({ url: this.proxyUrl, serializer: (data: string | {}) => { if (typeof data === 'string') { return data; } else { return JSON.stringify(data); } } }); private websocketObs = this.websocketSubject as any as Observable; private proxyInitialized = this.initObservable .pipe( switchMap((ws) => ws), filter((data: any) => data.success), switchMap(() => { return Observable.create((obs: Observer) => { this.websocketSubject.next('clientID: ' + this.appIdSelector()); obs.next(null); }); }), retry(), finalize(() => this.retrySubject.next({})), delay(2000), tap(() => console.log('%c Proxy ws initialized', 'color: orange')), shareReplay(), ); unwatch(transactionId: string, address: string, network: string, nbConf: number): Observable { this.websocketSubject.next(this.createUnSubscribe(transactionId, address, network, nbConf)); return of(); } watch(id: string, address: string, network: string, nbConf: number) { const ws = this.proxyInitialized.pipe( switchMap(() => { this.websocketSubject.next(this.createSubscribeRequest(id, address, network, nbConf)); return this.websocketObs; }), ); return ws; } private createSubscribeRequest(transactionId: string, address: string, network: string, nbConf: number) { return { transactionID: transactionId, action: 'subscribe', clientURL: this.appIdSelector(), network: network, address: address, requiredConf: nbConf, onlyReqConf: false, }; } private createUnSubscribe(transactionId: string, address: string, network: string, nbConf: number) { const { action, ...rest } = this.createSubscribeRequest(transactionId, address, network, nbConf); return { ...rest, action: 'unsubscribe' }; } }