UNPKG

@ledgerhq/live-common

Version:
120 lines (105 loc) 3.48 kB
import { Observable, from, of, throwError, EMPTY } from "rxjs"; import { catchError, concatMap, delay, mergeMap } from "rxjs/operators"; import { DeviceOnDashboardExpected, TransportStatusError } from "@ledgerhq/errors"; import { withDevice } from "./deviceAccess"; import getDeviceInfo from "./getDeviceInfo"; import { Language, languageIds } from "@ledgerhq/types-live"; import { AppAndVersion } from "./connectApp"; import appSupportsQuitApp from "../appSupportsQuitApp"; import quitApp from "./quitApp"; import getAppAndVersion from "./getAppAndVersion"; import { isDashboardName } from "./isDashboardName"; export type UninstallLanguageEvent = | { type: "appDetected"; } | { type: "unresponsiveDevice"; } | { type: "languageUninstalled"; }; const attemptToQuitApp = ( transport, appAndVersion?: AppAndVersion, ): Observable<UninstallLanguageEvent> => appAndVersion && appSupportsQuitApp(appAndVersion) ? from(quitApp(transport)).pipe( concatMap(() => of(<UninstallLanguageEvent>{ type: "unresponsiveDevice", }), ), catchError(e => throwError(() => e)), ) : of({ type: "appDetected", }); export type UninstallLanguageRequest = { deviceId: string; language: Language; }; export default function unistallLanguage({ deviceId, language, }: UninstallLanguageRequest): Observable<UninstallLanguageEvent> { const sub = withDevice(deviceId)( transport => new Observable<UninstallLanguageEvent>(subscriber => { const timeoutSub = of<UninstallLanguageEvent>({ type: "unresponsiveDevice", }) .pipe(delay(1000)) .subscribe(e => subscriber.next(e)); const sub = from(getDeviceInfo(transport)) .pipe( mergeMap(async _ => { timeoutSub.unsubscribe(); const id = languageIds[language]; await transport.send( 0xe0, 0x33, id, 0x00, undefined, [0x9000, 0x5501], // Expected responses when uninstalling. ); subscriber.next({ type: "languageUninstalled", }); subscriber.complete(); }), catchError((e: unknown) => { if ( e instanceof DeviceOnDashboardExpected || (e && e instanceof TransportStatusError && [0x6e00, 0x6d00, 0x6e01, 0x6d01, 0x6d02].includes(e.statusCode)) ) { const quitAppObservable = from(getAppAndVersion(transport)).pipe( concatMap(appAndVersion => { return !isDashboardName(appAndVersion.name) ? attemptToQuitApp(transport, appAndVersion) : of<UninstallLanguageEvent>({ type: "appDetected", }); }), ); quitAppObservable.subscribe( event => subscriber.next(event), error => subscriber.error(error), ); } subscriber.error(e); return EMPTY; }), ) .subscribe(); return () => { timeoutSub.unsubscribe(); sub.unsubscribe(); }; }), ); return sub; }