Comprehensive error handling library for the Ledger ecosystem with unified error classes, serialization, and hardware wallet status codes
Error classes for user-initiated cancellations, refusals, interaction-related failures, and manager operations.
Error classes for operations that were declined or refused by the user on the device or in the interface.
const UserRefusedDeviceNameChange: CustomErrorFunc;
const UserRefusedAddress: CustomErrorFunc;
const UserRefusedFirmwareUpdate: CustomErrorFunc;
const UserRefusedAllowManager: CustomErrorFunc;
const UserRefusedOnDevice: CustomErrorFunc;Usage Examples:
import {
UserRefusedDeviceNameChange,
UserRefusedAddress,
UserRefusedFirmwareUpdate,
UserRefusedAllowManager,
UserRefusedOnDevice
} from "@ledgerhq/errors";
// User declined device name change
throw new UserRefusedDeviceNameChange("User declined to change device name");
// User refused to verify address on device
throw new UserRefusedAddress("User refused address verification on device", {
requestedAddress: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
});
// User declined firmware update
throw new UserRefusedFirmwareUpdate("User declined firmware update", {
currentVersion: "2.0.0",
availableVersion: "2.1.0"
});
// User refused to allow manager access
throw new UserRefusedAllowManager("User refused to allow manager access to device");
// General user refusal on device (typically for transaction signing)
throw new UserRefusedOnDevice("User refused the operation on device", {
operation: "transaction_signing",
transactionId: "tx_abc123"
});Error classes for user-initiated cancellations during transport operations and device selection.
const TransportOpenUserCancelled: CustomErrorFunc;
const TransportWebUSBGestureRequired: CustomErrorFunc;Usage Examples:
import {
TransportOpenUserCancelled,
TransportWebUSBGestureRequired
} from "@ledgerhq/errors";
// User cancelled device selection or transport opening
throw new TransportOpenUserCancelled("User cancelled device selection", {
availableDevices: ["Ledger Nano S", "Ledger Nano X"],
selectionTimeout: "30 seconds"
});
// WebUSB requires user gesture to access device
throw new TransportWebUSBGestureRequired("WebUSB requires user gesture to access device", {
suggestedAction: "Click a button to trigger user gesture",
securityReason: "Browser security policy"
});Error classes for Ledger Manager operations including app installation, uninstallation, dependencies.
const ManagerAppAlreadyInstalledError: CustomErrorFunc;
const ManagerAppRelyOnBTCError: CustomErrorFunc;
const ManagerAppDepInstallRequired: CustomErrorFunc;
const ManagerAppDepUninstallRequired: CustomErrorFunc;
const ManagerDeviceLockedError: CustomErrorFunc;
const ManagerFirmwareNotEnoughSpaceError: CustomErrorFunc;
const ManagerNotEnoughSpaceError: CustomErrorFunc;
const ManagerUninstallBTCDep: CustomErrorFunc;Usage Examples:
import {
ManagerAppAlreadyInstalledError,
ManagerAppRelyOnBTCError,
ManagerAppDepInstallRequired,
ManagerAppDepUninstallRequired,
ManagerDeviceLockedError,
ManagerFirmwareNotEnoughSpaceError,
ManagerNotEnoughSpaceError,
ManagerUninstallBTCDep
} from "@ledgerhq/errors";
// App already installed
throw new ManagerAppAlreadyInstalledError("Bitcoin app is already installed on device", {
appName: "Bitcoin",
installedVersion: "2.0.1"
});
// App depends on Bitcoin app
throw new ManagerAppRelyOnBTCError("This app requires Bitcoin app to be installed", {
requestedApp: "Bitcoin Cash",
dependency: "Bitcoin"
});
// App dependency installation required
throw new ManagerAppDepInstallRequired("Required dependency must be installed first", {
requestedApp: "Ethereum",
requiredDependency: "Bitcoin",
action: "Install Bitcoin app first"
});
// App dependency uninstallation required
throw new ManagerAppDepUninstallRequired("Dependent apps must be uninstalled first", {
appToUninstall: "Bitcoin",
dependentApps: ["Bitcoin Cash", "Litecoin"],
action: "Uninstall dependent apps first"
});
// Device locked during manager operation
throw new ManagerDeviceLockedError("Device is locked - please unlock to continue", {
operation: "app_installation",
requiredAction: "Enter PIN on device"
});
// Insufficient space for firmware
throw new ManagerFirmwareNotEnoughSpaceError("Insufficient space for firmware update", {
requiredSpace: "512 KB",
availableSpace: "256 KB",
suggestedAction: "Uninstall unused apps"
});
// Insufficient space for app installation
throw new ManagerNotEnoughSpaceError("Insufficient space for app installation", {
appName: "Ethereum",
requiredSpace: "150 KB",
availableSpace: "80 KB",
installedApps: ["Bitcoin", "XRP", "Litecoin"]
});
// Cannot uninstall Bitcoin due to dependencies
throw new ManagerUninstallBTCDep("Cannot uninstall Bitcoin - other apps depend on it", {
dependentApps: ["Bitcoin Cash", "Litecoin", "Dogecoin"],
action: "Uninstall dependent apps first"
});Common patterns for gracefully handling user refusals:
import {
UserRefusedOnDevice,
UserRefusedAddress,
TransportOpenUserCancelled
} from "@ledgerhq/errors";
async function performUserInteraction(operation: () => Promise<any>) {
try {
return await operation();
} catch (error) {
if (error instanceof UserRefusedOnDevice) {
// Show user-friendly message for transaction refusal
console.log("Transaction was cancelled on your Ledger device");
return { cancelled: true, reason: "user_refused" };
}
if (error instanceof UserRefusedAddress) {
// Allow user to retry address verification
console.log("Address verification was cancelled. You can retry if needed.");
return { cancelled: true, reason: "address_verification_refused" };
}
if (error instanceof TransportOpenUserCancelled) {
// User cancelled device selection
console.log("Device selection was cancelled");
return { cancelled: true, reason: "device_selection_cancelled" };
}
throw error; // Re-throw if not a user cancellation
}
}import {
ManagerAppAlreadyInstalledError,
ManagerAppDepInstallRequired,
ManagerNotEnoughSpaceError
} from "@ledgerhq/errors";
async function installApp(appName: string) {
try {
await performAppInstallation(appName);
console.log(`${appName} app installed successfully`);
} catch (error) {
if (error instanceof ManagerAppAlreadyInstalledError) {
console.log(`${appName} app is already installed`);
return { success: true, alreadyInstalled: true };
}
if (error instanceof ManagerAppDepInstallRequired) {
console.log(`Installing required dependency: ${error.requiredDependency}`);
await installApp(error.requiredDependency);
return installApp(appName); // Retry after dependency installation
}
if (error instanceof ManagerNotEnoughSpaceError) {
console.log("Insufficient space. Consider uninstalling unused apps:");
console.log(error.installedApps.join(", "));
throw error;
}
throw error;
}
}import { TransportWebUSBGestureRequired } from "@ledgerhq/errors";
async function connectWithGesture() {
try {
return await connectToDevice();
} catch (error) {
if (error instanceof TransportWebUSBGestureRequired) {
// Show UI element that requires user click
return new Promise((resolve, reject) => {
const button = document.createElement('button');
button.textContent = 'Connect to Ledger Device';
button.onclick = async () => {
try {
const result = await connectToDevice();
button.remove();
resolve(result);
} catch (err) {
button.remove();
reject(err);
}
};
document.body.appendChild(button);
});
}
throw error;
}
}type CustomErrorFunc = (
message?: string,
fields?: { [key: string]: any }
) => void;tessl i tessl/npm-ledgerhq--errors@5.50.0