@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
111 lines • 4.01 kB
JavaScript
;
/**
* Error Handler
* Decides how to handle errors - display to user, mark as handled, or throw
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleErrors = handleErrors;
exports.isHandledError = isHandledError;
exports.getSwapCode = getSwapCode;
const SwapError_1 = require("./SwapError");
/**
* Default error names that should be marked as "handled"
* These are typically user input errors that can be retried
*/
const DEFAULT_IGNORED_ERROR_NAMES = new Set([
"WrongDeviceForAccount",
"WrongDeviceForAccountPayout",
"WrongDeviceForAccountRefund",
"UserRefusedOnDevice",
]);
/**
* Default error messages that should be marked as "handled"
*/
const DEFAULT_IGNORED_MESSAGES = new Set(["User refused", "User rejected"]);
function isRecord(value) {
return typeof value === "object" && value !== null;
}
function hasCause(value) {
return "cause" in value;
}
function toCauseDetails(rawCause) {
if (!isRecord(rawCause)) {
return undefined;
}
const swapCode = typeof rawCause.swapCode === "string" ? rawCause.swapCode : undefined;
const name = typeof rawCause.name === "string" ? rawCause.name : undefined;
const message = typeof rawCause.message === "string" ? rawCause.message : undefined;
if (swapCode || name || message) {
return { swapCode, name, message };
}
return undefined;
}
function extractErrorDetails(value) {
if (value instanceof SwapError_1.SwapError) {
return { message: value.message, cause: value.cause };
}
if (value instanceof Error) {
return {
message: value.message,
cause: hasCause(value) ? toCauseDetails(value.cause) : undefined,
};
}
if (isRecord(value) && typeof value.message === "string") {
const rawCause = "cause" in value ? value.cause : undefined;
const cause = toCauseDetails(rawCause);
return { message: value.message, cause };
}
return { message: typeof value === "string" ? value : JSON.stringify(value ?? "Unknown error") };
}
function markErrorAsHandled(error) {
if (isRecord(error)) {
Object.assign(error, { handled: true });
}
return error;
}
/**
* Handles errors by deciding whether to display them or mark as handled
*
* @param error - The error to handle
* @param options - Configuration options
* @throws Enhanced error with `handled` flag if applicable
*/
function handleErrors(error, options = {}) {
const { onDisplayError, ignoredErrorNames = [], ignoredMessages = [] } = options;
// Merge default and custom ignored values
const allIgnoredNames = new Set([...DEFAULT_IGNORED_ERROR_NAMES, ...ignoredErrorNames]);
const allIgnoredMessages = new Set([...DEFAULT_IGNORED_MESSAGES, ...ignoredMessages]);
const { message, cause } = extractErrorDetails(error);
// Check if error should be marked as handled (retry-ready)
const isIgnoredMessage = allIgnoredMessages.has(message);
const isIgnoredName = typeof cause?.name === "string" && allIgnoredNames.has(cause.name);
const isIgnoredSwapCode = cause?.swapCode === "swap003Ignored";
if (isIgnoredMessage || isIgnoredName || isIgnoredSwapCode) {
throw markErrorAsHandled(error);
}
// Display error to user if handler provided
if (error instanceof SwapError_1.SwapError && onDisplayError) {
// Skip displaying "swap003Ignored" errors
if (cause?.swapCode !== "swap003Ignored") {
return onDisplayError(error);
}
}
// Always throw the error so caller can handle it
throw error;
}
/**
* Type guard to check if an error is marked as handled
*/
function isHandledError(error) {
return isRecord(error) && error.handled === true;
}
/**
* Extracts swap code from error if available
*/
function getSwapCode(error) {
if (error instanceof SwapError_1.SwapError) {
return error.cause.swapCode;
}
return undefined;
}
//# sourceMappingURL=handleSwapErrors.js.map