123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- /**
- * All errors in ethers include properties to ensure they are both
- * human-readable (i.e. ``.message``) and machine-readable (i.e. ``.code``).
- *
- * The [[isError]] function can be used to check the error ``code`` and
- * provide a type guard for the properties present on that error interface.
- *
- * @_section: api/utils/errors:Errors [about-errors]
- */
- import { version } from "../_version.js";
- import { defineProperties } from "./properties.js";
- function stringify(value) {
- if (value == null) {
- return "null";
- }
- if (Array.isArray(value)) {
- return "[ " + (value.map(stringify)).join(", ") + " ]";
- }
- if (value instanceof Uint8Array) {
- const HEX = "0123456789abcdef";
- let result = "0x";
- for (let i = 0; i < value.length; i++) {
- result += HEX[value[i] >> 4];
- result += HEX[value[i] & 0xf];
- }
- return result;
- }
- if (typeof (value) === "object" && typeof (value.toJSON) === "function") {
- return stringify(value.toJSON());
- }
- switch (typeof (value)) {
- case "boolean":
- case "symbol":
- return value.toString();
- case "bigint":
- return BigInt(value).toString();
- case "number":
- return (value).toString();
- case "string":
- return JSON.stringify(value);
- case "object": {
- const keys = Object.keys(value);
- keys.sort();
- return "{ " + keys.map((k) => `${stringify(k)}: ${stringify(value[k])}`).join(", ") + " }";
- }
- }
- return `[ COULD NOT SERIALIZE ]`;
- }
- /**
- * Returns true if the %%error%% matches an error thrown by ethers
- * that matches the error %%code%%.
- *
- * In TypeScript environments, 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
- * try {
- * // code....
- * } catch (e) {
- * if (isError(e, "CALL_EXCEPTION")) {
- * // The Type Guard has validated this object
- * console.log(e.data);
- * }
- * }
- */
- export function isError(error, code) {
- return (error && error.code === code);
- }
- /**
- * Returns true if %%error%% is a [[CallExceptionError].
- */
- export function isCallException(error) {
- return isError(error, "CALL_EXCEPTION");
- }
- /**
- * Returns a new Error configured to the format ethers emits errors, with
- * the %%message%%, [[api:ErrorCode]] %%code%% and additional properties
- * for the corresponding EthersError.
- *
- * Each error in ethers includes the version of ethers, a
- * machine-readable [[ErrorCode]], and depending on %%code%%, additional
- * required properties. The error message will also include the %%message%%,
- * ethers version, %%code%% and all additional properties, serialized.
- */
- export function makeError(message, code, info) {
- let shortMessage = message;
- {
- const details = [];
- if (info) {
- if ("message" in info || "code" in info || "name" in info) {
- throw new Error(`value will overwrite populated values: ${stringify(info)}`);
- }
- for (const key in info) {
- if (key === "shortMessage") {
- continue;
- }
- const value = (info[key]);
- // try {
- details.push(key + "=" + stringify(value));
- // } catch (error: any) {
- // console.log("MMM", error.message);
- // details.push(key + "=[could not serialize object]");
- // }
- }
- }
- details.push(`code=${code}`);
- details.push(`version=${version}`);
- if (details.length) {
- message += " (" + details.join(", ") + ")";
- }
- }
- let error;
- switch (code) {
- case "INVALID_ARGUMENT":
- error = new TypeError(message);
- break;
- case "NUMERIC_FAULT":
- case "BUFFER_OVERRUN":
- error = new RangeError(message);
- break;
- default:
- error = new Error(message);
- }
- defineProperties(error, { code });
- if (info) {
- Object.assign(error, info);
- }
- if (error.shortMessage == null) {
- defineProperties(error, { shortMessage });
- }
- return error;
- }
- /**
- * Throws an EthersError with %%message%%, %%code%% and additional error
- * %%info%% when %%check%% is falsish..
- *
- * @see [[api:makeError]]
- */
- export function assert(check, message, code, info) {
- if (!check) {
- throw makeError(message, code, info);
- }
- }
- /**
- * 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) {
- assert(check, message, "INVALID_ARGUMENT", { argument: name, value: value });
- }
- export function assertArgumentCount(count, expectedCount, message) {
- if (message == null) {
- message = "";
- }
- if (message) {
- message = ": " + message;
- }
- assert(count >= expectedCount, "missing argument" + message, "MISSING_ARGUMENT", {
- count: count,
- expectedCount: expectedCount
- });
- assert(count <= expectedCount, "too many arguments" + 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) {
- assert(_normalizeForms.indexOf(form) >= 0, "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 (className == null) {
- className = "";
- }
- if (givenGuard !== guard) {
- let method = className, operation = "new";
- if (className) {
- method += ".";
- operation += " " + className;
- }
- assert(false, `private constructor; use ${method}from* methods`, "UNSUPPORTED_OPERATION", {
- operation
- });
- }
- }
- //# sourceMappingURL=errors.js.map
|