UNPKG

@metamask/snaps-sdk

Version:

A library containing the core functionality for building MetaMask Snaps

189 lines 5.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isSnapError = exports.isSerializedSnapError = exports.getJsonError = exports.SnapError = void 0; const utils_1 = require("@metamask/utils"); const internals_1 = require("./internals/index.cjs"); /** * A generic error which can be thrown by a Snap, without it causing the Snap to * crash. */ class SnapError extends Error { #code; #message; #data; #stack; /** * Create a new `SnapError`. * * @param error - The error to create the `SnapError` from. If this is a * `string`, it will be used as the error message. If this is an `Error`, its * `message` property will be used as the error message. If this is a * `JsonRpcError`, its `message` property will be used as the error message * and its `code` property will be used as the error code. Otherwise, the * error will be converted to a string and used as the error message. * @param data - Additional data to include in the error. This will be merged * with the error data, if any. */ constructor(error, data = {}) { const message = (0, internals_1.getErrorMessage)(error); super(message); this.#message = message; this.#code = (0, internals_1.getErrorCode)(error); const mergedData = { ...(0, internals_1.getErrorData)(error), ...data }; if (Object.keys(mergedData).length > 0) { this.#data = mergedData; } this.#stack = super.stack; } /** * The error name. * * @returns The error name. */ get name() { return 'SnapError'; } /** * The error code. * * @returns The error code. */ get code() { return this.#code; } /** * The error message. * * @returns The error message. */ // This line is covered, but Jest doesn't pick it up for some reason. /* istanbul ignore next */ get message() { return this.#message; } /** * Additional data for the error. * * @returns Additional data for the error. */ get data() { return this.#data; } /** * The error stack. * * @returns The error stack. */ // This line is covered, but Jest doesn't pick it up for some reason. /* istanbul ignore next */ get stack() { return this.#stack; } /** * Convert the error to a JSON object. * * @returns The JSON object. */ toJSON() { return { code: internals_1.SNAP_ERROR_CODE, message: internals_1.SNAP_ERROR_MESSAGE, data: { cause: { code: this.code, message: this.message, stack: this.stack, ...(this.data ? { data: this.data } : {}), }, }, }; } /** * Serialize the error to a JSON object. This is called by * `@metamask/rpc-errors` when serializing the error. * * @returns The JSON object. */ serialize() { return this.toJSON(); } } exports.SnapError = SnapError; /** * Get a serialised JSON error from a given error. This is intended to be used * with `snap_trackError` to convert an error to a JSON object that can be * tracked by the Sentry instance in the client. * * @param error - The error to convert to a JSON error. This can be a string, an * `Error`, a `JsonRpcError`, or any other type. If it is not a string or an * `Error`, it will be converted to a string using its `toString()` method. * @returns A JSON object containing the error message and stack trace, if * available. * @example * try { * // Some code that may throw an error * } catch (error) { * await snap.request({ * method: 'snap_trackError', * params: { * error: getJsonError(error), * }, * }); * } */ function getJsonError( // TypeScript will narrow this to `unknown`, but we specify all the types for // clarity. error) { if (typeof error === 'string') { return { name: 'Error', message: error, stack: null, cause: null, }; } if ((0, utils_1.isJsonRpcError)(error)) { return { name: 'JsonRpcError', message: (0, internals_1.getErrorMessage)(error), stack: (0, internals_1.getErrorStack)(error) ?? (0, internals_1.getErrorStack)(error.data) ?? null, cause: null, }; } const cause = (0, internals_1.getErrorCause)(error); return { name: (0, internals_1.getErrorName)(error), message: (0, internals_1.getErrorMessage)(error), stack: (0, internals_1.getErrorStack)(error) ?? null, cause: cause === null ? null : getJsonError(cause), }; } exports.getJsonError = getJsonError; /** * Check if a JSON-RPC error is a `SnapError`. * * @param error - The object to check. * @returns Whether the object is a `SnapError`. */ function isSerializedSnapError(error) { return error.code === internals_1.SNAP_ERROR_CODE && error.message === internals_1.SNAP_ERROR_MESSAGE; } exports.isSerializedSnapError = isSerializedSnapError; /** * Check if an object is a `SnapError`. * * @param error - The object to check. * @returns Whether the object is a `SnapError`. */ function isSnapError(error) { if ((0, utils_1.isObject)(error) && 'serialize' in error && typeof error.serialize === 'function') { const serialized = error.serialize(); return (0, utils_1.isJsonRpcError)(serialized) && isSerializedSnapError(serialized); } return false; } exports.isSnapError = isSnapError; //# sourceMappingURL=errors.cjs.map