@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
117 lines • 5.29 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useGenuineCheck = void 0;
const react_1 = require("react");
const errors_1 = require("@ledgerhq/errors");
const getGenuineCheckFromDeviceId_1 = require("../getGenuineCheckFromDeviceId");
const core_1 = require("../../deviceSDK/tasks/core");
const SOCKET_EVENT_PAYLOAD_GENUINE = "0000";
const clearTimeoutRef = (timeoutRef) => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
};
const isDmkDeviceDisconnectedError = (e) => (0, core_1.isDmkError)(e) && e._tag === "DeviceDisconnectedWhileSendingError";
/**
* Hook to check that a device is genuine
* It replaces a DeviceAction if we're only interested in getting the genuine check
* @param getGenuineCheckFromDeviceId An optional function to get a genuine check for a given device id,
* by default set to live-common/hw/getGenuineCheckFromDeviceId.
* This dependency injection is needed for LLD to have the hook working on the internal thread
* @param isHookEnabled A boolean to enable (true, default value) or disable (false) the hook
* @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.
* @param permissionTimeoutMs Time to wait for a device response to a permission request, in ms. Default 60s.
* @returns An object containing:
* - genuineState: the current GenuineState
* - devicePermissionState: the current DevicePermissionState
* - error: any error that occurred during the genuine check, or null
*/
const useGenuineCheck = ({ getGenuineCheckFromDeviceId = getGenuineCheckFromDeviceId_1.getGenuineCheckFromDeviceId, isHookEnabled = true, deviceId, lockedDeviceTimeoutMs = 1000, permissionTimeoutMs = 60 * 1000, }) => {
const [genuineState, setGenuineState] = (0, react_1.useState)("unchecked");
const [devicePermissionState, setDevicePermissionState] = (0, react_1.useState)("unrequested");
const [error, setError] = (0, react_1.useState)(null);
const timeoutRef = (0, react_1.useRef)(null);
const resetGenuineCheckState = (0, react_1.useCallback)(() => {
setDevicePermissionState("unrequested");
setGenuineState("unchecked");
setError(null);
}, []);
(0, react_1.useEffect)(() => {
if (!isHookEnabled) {
return;
}
const sub = getGenuineCheckFromDeviceId({
deviceId,
lockedDeviceTimeoutMs,
}).subscribe({
next: ({ socketEvent, lockedDevice }) => {
if (socketEvent) {
switch (socketEvent.type) {
case "device-permission-requested":
setDevicePermissionState("requested");
timeoutRef.current = setTimeout(() => {
setError(new errors_1.UnresponsiveDeviceError());
clearTimeoutRef(timeoutRef);
}, permissionTimeoutMs);
break;
case "device-permission-granted":
clearTimeoutRef(timeoutRef);
setDevicePermissionState("granted");
break;
case "result":
clearTimeoutRef(timeoutRef);
if (socketEvent.payload === SOCKET_EVENT_PAYLOAD_GENUINE) {
setGenuineState("genuine");
}
else {
setGenuineState("non-genuine");
}
break;
}
}
else {
clearTimeoutRef(timeoutRef);
// If no socketEvent, the device is locked or has been unlocked
if (lockedDevice) {
setDevicePermissionState("unlock-needed");
}
else {
setDevicePermissionState("unlocked");
}
}
},
error: (e) => {
clearTimeoutRef(timeoutRef);
if (e instanceof errors_1.UserRefusedAllowManager) {
setDevicePermissionState("refused");
}
else if (e instanceof Error || isDmkDeviceDisconnectedError(e)) {
// Probably an error of type DisconnectedDeviceDuringOperation or something else
setError(e);
}
else {
setError(new Error(`Unknown error: ${e}`));
}
},
});
return () => {
sub.unsubscribe();
};
}, [
isHookEnabled,
deviceId,
lockedDeviceTimeoutMs,
getGenuineCheckFromDeviceId,
permissionTimeoutMs,
]);
return {
genuineState,
devicePermissionState,
error,
resetGenuineCheckState,
};
};
exports.useGenuineCheck = useGenuineCheck;
//# sourceMappingURL=useGenuineCheck.js.map