import { DisconnectedDevice, HwTransportError, HwTransportErrorType, PairingFailed, PeerRemovedPairing, } from "@ledgerhq/errors"; import { BleATTErrorCode, BleError, BleErrorCode } from "react-native-ble-plx"; export type IOBleErrorRemap = Error | BleError | null | undefined; export const remapError = (error: IOBleErrorRemap): IOBleErrorRemap => { if (!error || !error.message) return error; if (error instanceof BleError) { if ( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error error.iosErrorCode === BleATTErrorCode.UnlikelyError || error.reason === "Peer removed pairing information" ) { return new PeerRemovedPairing(); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore It's not documented but seems to match a refusal on Android pairing } else if (error?.attErrorCode === 22) { return new PairingFailed(); } } if (error.message.includes("was disconnected") || error.message.includes("not found")) { return new DisconnectedDevice(); } return error; }; export const rethrowError = (e: Error | null | undefined): never => { throw remapError(e); }; export const decoratePromiseErrors = (promise: Promise): Promise => promise.catch(rethrowError); export const bleErrorToHwTransportError = new Map([ [BleErrorCode.ScanStartFailed, HwTransportErrorType.BluetoothScanStartFailed], [BleErrorCode.LocationServicesDisabled, HwTransportErrorType.LocationServicesDisabled], [ // BluetoothUnauthorized actually represents a location service unauthorized error BleErrorCode.BluetoothUnauthorized, HwTransportErrorType.LocationServicesUnauthorized, ], ]); export const mapBleErrorToHwTransportError = (bleError: BleError): HwTransportError => { const message = `${bleError.message}. Origin: ${bleError.errorCode}`; const inferedType = bleErrorToHwTransportError.get(bleError.errorCode); const type = !inferedType ? HwTransportErrorType.Unknown : inferedType; return new HwTransportError(type, message); };