UNPKG

@ledgerhq/live-common

Version:
69 lines 2.9 kB
import { CantOpenDevice, LockedDeviceError } from "@ledgerhq/errors"; import { from, Observable, TimeoutError } from "rxjs"; import { retryWhen, timeout } from "rxjs/operators"; import { retryWhileErrors, withDevice } from "./deviceAccess"; import getDeviceInfo from "./getDeviceInfo"; /** * Get the mode in which is device is: bootloader, main, locked device, maybe disconnected or locked device * It will retry on all errors from getDeviceInfo, except the ones that implies that the device is * disconnected (number of retry can be tweaked) or locked. * * Note: If no device is found, the current Transport implementations throw a CantOpenDevice error * And if the device was cold started and not yet unlocked, the current Transport implementations * don't see the device yet, and also throw a CantOpenDevice error. * * Does NOT handle recovery mode for now. * @param deviceId A device id * @param unresponsiveTimeoutMs Time in ms of the timeout before considering the device unresponsive * @param cantOpenDeviceRetryLimit Number of received CantOpenDevice errors while retrying before considering * the device as maybe disconnected or cold-started-locked * @returns An object GetDeviceRunningModeEvent */ export const getDeviceRunningMode = ({ deviceId, unresponsiveTimeoutMs = 5000, cantOpenDeviceRetryLimit = 3, }) => new Observable(o => { let cantOpenDeviceRetryCount = 0; withDevice(deviceId)(transport => from(getDeviceInfo(transport))) .pipe(timeout(unresponsiveTimeoutMs), retryWhen(retryWhileErrors((e) => { // Does not retry on locked-device error if (isLockedDeviceError(e)) { return false; } if (e instanceof CantOpenDevice) { if (cantOpenDeviceRetryCount < cantOpenDeviceRetryLimit) { cantOpenDeviceRetryCount++; return true; } return false; } // Retries on any other kind of errors return true; }))) .subscribe({ next: (deviceInfo) => { if (deviceInfo.isBootloader) { o.next({ type: "bootloaderMode", deviceInfo }); } else { o.next({ type: "mainMode", deviceInfo }); } o.complete(); }, error: (e) => { if (isLockedDeviceError(e)) { o.next({ type: "lockedDevice" }); o.complete(); } else if (e instanceof CantOpenDevice) { o.next({ type: "disconnectedOrlockedDevice" }); o.complete(); } else { o.error(e); } }, complete: () => o.complete(), }); }); const isLockedDeviceError = (e) => { return e && (e instanceof TimeoutError || e instanceof LockedDeviceError); }; //# sourceMappingURL=getDeviceRunningMode.js.map