ethers.js/lib.esm/utils/errors.js

177 lines
5.6 KiB
JavaScript
Raw Normal View History

2022-09-16 05:58:45 +03:00
import { version } from "../_version.js";
import { defineReadOnly } from "./properties.js";
// The type of error to use for various error codes
const ErrorConstructors = {};
ErrorConstructors.INVALID_ARGUMENT = TypeError;
ErrorConstructors.NUMERIC_FAULT = RangeError;
ErrorConstructors.BUFFER_OVERRUN = RangeError;
2022-09-05 23:57:11 +03:00
/**
2022-09-16 05:58:45 +03:00
* Returns true if the %%error%% matches an error thrown by ethers
* that matches the error %%code%%.
*
* In TypeScript envornoments, this can be used to check that %%error%%
* matches an EthersError type, which means the expected properties will
* be set.
*
* @See [ErrorCodes](api:ErrorCode)
* @example
2022-09-05 23:57:11 +03:00
* try {
* // code....
* } catch (e) {
2022-09-16 05:58:45 +03:00
* if (isError(e, "CALL_EXCEPTION")) {
2022-09-05 23:57:11 +03:00
* console.log(e.data);
* }
* }
*/
export function isError(error, code) {
return (error && error.code === code);
}
2022-09-16 05:58:45 +03:00
/**
* Returns true if %%error%% is a [CALL_EXCEPTION](api:CallExceptionError).
*/
2022-09-05 23:57:11 +03:00
export function isCallException(error) {
return isError(error, "CALL_EXCEPTION");
}
2022-09-16 05:58:45 +03:00
/**
* Returns a new Error configured to the format ethers emits errors, with
* the %%message%%, [[api:ErrorCode]] %%code%% and additioanl properties
* for the corresponding EthersError.
*
* Each error in ethers includes the version of ethers, a
* machine-readable [[ErrorCode]], and depneding on %%code%%, additional
* required properties. The error message will also include the %%meeage%%,
* ethers version, %%code%% and all aditional properties, serialized.
*/
export function makeError(message, code, info) {
{
const details = [];
if (info) {
if ("message" in info || "code" in info || "name" in info) {
throw new Error(`value will overwrite populated values: ${JSON.stringify(info)}`);
}
for (const key in info) {
const value = (info[key]);
try {
details.push(key + "=" + JSON.stringify(value));
}
catch (error) {
details.push(key + "=[could not serialize object]");
}
}
}
details.push(`code=${code}`);
details.push(`version=${version}`);
if (details.length) {
message += " (" + details.join(", ") + ")";
}
}
const create = ErrorConstructors[code] || Error;
const error = (new create(message));
defineReadOnly(error, "code", code);
if (info) {
for (const key in info) {
defineReadOnly(error, key, (info[key]));
}
}
return error;
}
/**
* Throws an EthersError with %%message%%, %%code%% and additional error
* info.
*
* @see [[api:makeError]]
*/
export function throwError(message, code, info) {
throw makeError(message, code, info);
}
/**
* Throws an [[api:ArgumentError]] with %%message%% for the parameter with
* %%name%% and the %%value%%.
*/
export function throwArgumentError(message, name, value) {
return throwError(message, "INVALID_ARGUMENT", {
argument: name,
value: value
});
}
/**
* A simple helper to simply ensuring provided arguments match expected
* constraints, throwing if not.
*
* In TypeScript environments, the %%check%% has been asserted true, so
* any further code does not need additional compile-time checks.
*/
export function assertArgument(check, message, name, value) {
if (!check) {
throwArgumentError(message, name, value);
}
}
export function assertArgumentCount(count, expectedCount, message = "") {
if (message) {
message = ": " + message;
}
if (count < expectedCount) {
throwError("missing arguemnt" + message, "MISSING_ARGUMENT", {
count: count,
expectedCount: expectedCount
});
}
if (count > expectedCount) {
throwError("too many arguemnts" + message, "UNEXPECTED_ARGUMENT", {
count: count,
expectedCount: expectedCount
});
}
}
const _normalizeForms = ["NFD", "NFC", "NFKD", "NFKC"].reduce((accum, form) => {
try {
// General test for normalize
/* c8 ignore start */
if ("test".normalize(form) !== "test") {
throw new Error("bad");
}
;
/* c8 ignore stop */
if (form === "NFD") {
const check = String.fromCharCode(0xe9).normalize("NFD");
const expected = String.fromCharCode(0x65, 0x0301);
/* c8 ignore start */
if (check !== expected) {
throw new Error("broken");
}
/* c8 ignore stop */
}
accum.push(form);
}
catch (error) { }
return accum;
}, []);
/**
* Throws if the normalization %%form%% is not supported.
*/
export function assertNormalize(form) {
if (_normalizeForms.indexOf(form) === -1) {
throwError("platform missing String.prototype.normalize", "UNSUPPORTED_OPERATION", {
operation: "String.prototype.normalize", info: { form }
});
}
}
/**
* Many classes use file-scoped values to guard the constructor,
* making it effectively private. This facilitates that pattern
* by ensuring the %%givenGaurd%% matches the file-scoped %%guard%%,
* throwing if not, indicating the %%className%% if provided.
*/
export function assertPrivate(givenGuard, guard, className = "") {
if (givenGuard !== guard) {
let method = className, operation = "new";
if (className) {
method += ".";
operation += " " + className;
}
throwError(`private constructor; use ${method}from* methods`, "UNSUPPORTED_OPERATION", {
operation
});
}
}
2022-09-05 23:57:11 +03:00
//# sourceMappingURL=errors.js.map