@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
69 lines • 2.9 kB
JavaScript
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