@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
48 lines • 2.64 kB
JavaScript
import { from, Observable } from "rxjs";
import { mergeMap, retryWhen } from "rxjs/operators";
import { LockedDeviceError } from "@ledgerhq/errors";
import getDeviceInfo from "./getDeviceInfo";
import { retryWhileErrors, withDevice } from "./deviceAccess";
import genuineCheck from "./genuineCheck";
/**
* Get a genuine check for a device only from its id
* @param deviceId A device id, or an empty string if device is usb plugged
* @param lockedDeviceTimeoutMs Time of no response from device after which the device is considered locked, in ms. Default 1000ms.
* @returns An Observable pushing objects containing:
* - socketEvent: a SocketEvent giving the current status of the genuine check,
* null if the genuine check process did not reach any state yet
* - lockedDevice: a boolean set to true if the device is currently locked, false otherwise
*/
export const getGenuineCheckFromDeviceId = ({ deviceId, deviceName, lockedDeviceTimeoutMs = 1000, }) => {
return new Observable(subscriber => {
// In order to know if a device is locked or not.
// As we're not timing out inside the genuineCheckObservable flow (with rxjs timeout for ex)
// once the device is unlock, getDeviceInfo should return the device info and
// the flow will continue. No need to handle a retry strategy
const lockedDeviceTimeout = setTimeout(() => {
subscriber.next({ socketEvent: null, lockedDevice: true });
}, lockedDeviceTimeoutMs);
// Returns a Subscription that can be unsubscribed/cleaned
return (withDevice(deviceId, deviceName ? { matchDeviceByName: deviceName } : undefined)(t => from(getDeviceInfo(t)).pipe(mergeMap(deviceInfo => {
clearTimeout(lockedDeviceTimeout);
subscriber.next({ socketEvent: null, lockedDevice: false });
return genuineCheck(t, deviceInfo);
})))
// Needs to retry with withDevice
.pipe(retryWhen(retryWhileErrors((e) => {
// Cancels the locked-device unresponsive/timeout strategy if received any response/error
clearTimeout(lockedDeviceTimeout);
if (e instanceof LockedDeviceError) {
subscriber.next({ socketEvent: null, lockedDevice: true });
return true;
}
return false;
})))
.subscribe({
next: (socketEvent) => subscriber.next({ socketEvent, lockedDevice: false }),
error: e => subscriber.error(e),
complete: () => subscriber.complete(),
}));
});
};
//# sourceMappingURL=getGenuineCheckFromDeviceId.js.map