| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793 | /** *  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";import type {    TransactionRequest, TransactionReceipt, TransactionResponse} from "../providers/index.js";import type { FetchRequest, FetchResponse } from "./fetch.js";/** *  An error may contain additional properties, but those must not *  conflict with any implicit properties. */export type ErrorInfo<T> = Omit<T, "code" | "name" | "message" | "shortMessage"> & { shortMessage?: string };function stringify(value: any): any {    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 ]`;}/** *  All errors emitted by ethers have an **ErrorCode** to help *  identify and coalesce errors to simplify programmatic analysis. * *  Each **ErrorCode** is the %%code%% proerty of a coresponding *  [[EthersError]]. * *  **Generic Errors** * *  **``"UNKNOWN_ERROR"``** - see [[UnknownError]] * *  **``"NOT_IMPLEMENTED"``** - see [[NotImplementedError]] * *  **``"UNSUPPORTED_OPERATION"``** - see [[UnsupportedOperationError]] * *  **``"NETWORK_ERROR"``** - see [[NetworkError]] * *  **``"SERVER_ERROR"``** - see [[ServerError]] * *  **``"TIMEOUT"``** - see [[TimeoutError]] * *  **``"BAD_DATA"``** - see [[BadDataError]] * *  **``"CANCELLED"``** - see [[CancelledError]] * *  **Operational Errors** * *  **``"BUFFER_OVERRUN"``** - see [[BufferOverrunError]] * *  **``"NUMERIC_FAULT"``** - see [[NumericFaultError]] * *  **Argument Errors** * *  **``"INVALID_ARGUMENT"``** - see [[InvalidArgumentError]] * *  **``"MISSING_ARGUMENT"``** - see [[MissingArgumentError]] * *  **``"UNEXPECTED_ARGUMENT"``** - see [[UnexpectedArgumentError]] * *  **``"VALUE_MISMATCH"``** - //unused// * *  **Blockchain Errors** * *  **``"CALL_EXCEPTION"``** - see [[CallExceptionError]] * *  **``"INSUFFICIENT_FUNDS"``** - see [[InsufficientFundsError]] * *  **``"NONCE_EXPIRED"``** - see [[NonceExpiredError]] * *  **``"REPLACEMENT_UNDERPRICED"``** - see [[ReplacementUnderpricedError]] * *  **``"TRANSACTION_REPLACED"``** - see [[TransactionReplacedError]] * *  **``"UNCONFIGURED_NAME"``** - see [[UnconfiguredNameError]] * *  **``"OFFCHAIN_FAULT"``** - see [[OffchainFaultError]] * *  **User Interaction Errors** * *  **``"ACTION_REJECTED"``** - see [[ActionRejectedError]] */export type ErrorCode =    // Generic Errors    "UNKNOWN_ERROR" | "NOT_IMPLEMENTED" | "UNSUPPORTED_OPERATION" |    "NETWORK_ERROR" | "SERVER_ERROR" | "TIMEOUT" | "BAD_DATA" |    "CANCELLED" |    // Operational Errors    "BUFFER_OVERRUN" |  "NUMERIC_FAULT" |    // Argument Errors    "INVALID_ARGUMENT" | "MISSING_ARGUMENT" | "UNEXPECTED_ARGUMENT" |    "VALUE_MISMATCH" |    // Blockchain Errors    "CALL_EXCEPTION" | "INSUFFICIENT_FUNDS" | "NONCE_EXPIRED" |    "REPLACEMENT_UNDERPRICED" | "TRANSACTION_REPLACED" |    "UNCONFIGURED_NAME" | "OFFCHAIN_FAULT" |    // User Interaction    "ACTION_REJECTED";/** *  All errors in Ethers include properties to assist in *  machine-readable errors. */export interface EthersError<T extends ErrorCode = ErrorCode> extends Error {    /**     *  The string error code.     */    code: ErrorCode;    /**     *  A short message describing the error, with minimal additional     *  details.     */    shortMessage: string;    /**     *  Additional info regarding the error that may be useful.     *     *  This is generally helpful mostly for human-based debugging.     */    info?: Record<string, any>;    /**     *  Any related error.     */    error?: Error;}// Generic Errors/** *  This Error is a catch-all for when there is no way for Ethers to *  know what the underlying problem is. */export interface UnknownError extends EthersError<"UNKNOWN_ERROR"> {    [ key: string ]: any;}/** *  This Error is mostly used as a stub for functionality that is *  intended for the future, but is currently not implemented. */export interface NotImplementedError extends EthersError<"NOT_IMPLEMENTED"> {    /**     *  The attempted operation.     */    operation: string;}/** *  This Error indicates that the attempted operation is not supported. * *  This could range from a specific JSON-RPC end-point not supporting *  a feature to a specific configuration of an object prohibiting the *  operation. * *  For example, a [[Wallet]] with no connected [[Provider]] is unable *  to send a transaction. */export interface UnsupportedOperationError extends EthersError<"UNSUPPORTED_OPERATION"> {    /**     *  The attempted operation.     */    operation: string;}/** *  This Error indicates a problem connecting to a network. */export interface NetworkError extends EthersError<"NETWORK_ERROR"> {    /**     *  The network event.     */    event: string;}/** *  This Error indicates there was a problem fetching a resource from *  a server. */export interface ServerError extends EthersError<"SERVER_ERROR"> {    /**     *  The requested resource.     */    request: FetchRequest | string;    /**     *  The response received from the server, if available.     */    response?: FetchResponse;}/** *  This Error indicates that the timeout duration has expired and *  that the operation has been implicitly cancelled. * *  The side-effect of the operation may still occur, as this *  generally means a request has been sent and there has simply *  been no response to indicate whether it was processed or not. */export interface TimeoutError extends EthersError<"TIMEOUT"> {    /**     *  The attempted operation.     */    operation: string;    /**     *  The reason.     */    reason: string;    /**     *  The resource request, if available.     */    request?: FetchRequest;}/** *  This Error indicates that a provided set of data cannot *  be correctly interpreted. */export interface BadDataError extends EthersError<"BAD_DATA"> {    /**     *  The data.     */    value: any;}/** *  This Error indicates that the operation was cancelled by a *  programmatic call, for example to ``cancel()``. */export interface CancelledError extends EthersError<"CANCELLED"> {}// Operational Errors/** *  This Error indicates an attempt was made to read outside the bounds *  of protected data. * *  Most operations in Ethers are protected by bounds checks, to mitigate *  exploits when parsing data. */export interface BufferOverrunError extends EthersError<"BUFFER_OVERRUN"> {    /**     *  The buffer that was overrun.     */    buffer: Uint8Array;    /**     *  The length of the buffer.     */    length: number;    /**     *  The offset that was requested.     */    offset: number;}/** *  This Error indicates an operation which would result in incorrect *  arithmetic output has occurred. * *  For example, trying to divide by zero or using a ``uint8`` to store *  a negative value. */export interface NumericFaultError extends EthersError<"NUMERIC_FAULT"> {    /**     *  The attempted operation.     */    operation: string;    /**     *  The fault reported.     */    fault: string;    /**     *  The value the operation was attempted against.     */    value: any;}// Argument Errors/** *  This Error indicates an incorrect type or value was passed to *  a function or method. */export interface InvalidArgumentError extends EthersError<"INVALID_ARGUMENT"> {    /**     *  The name of the argument.     */    argument: string;    /**     *  The value that was provided.     */    value: any;    info?: Record<string, any>}/** *  This Error indicates there were too few arguments were provided. */export interface MissingArgumentError extends EthersError<"MISSING_ARGUMENT"> {    /**     *  The number of arguments received.     */    count: number;    /**     *  The number of arguments expected.     */    expectedCount: number;}/** *  This Error indicates too many arguments were provided. */export interface UnexpectedArgumentError extends EthersError<"UNEXPECTED_ARGUMENT"> {    /**     *  The number of arguments received.     */    count: number;    /**     *  The number of arguments expected.     */    expectedCount: number;}// Blockchain Errors/** *  The action that resulted in the call exception. */export type CallExceptionAction = "call" | "estimateGas" | "getTransactionResult" | "sendTransaction" | "unknown";/** *  The related transaction that caused the error. */export type CallExceptionTransaction = {    to: null | string;    from?: string;    data: string;};/** *  This **Error** indicates a transaction reverted. */export interface CallExceptionError extends EthersError<"CALL_EXCEPTION"> {    /**     *  The action being performed when the revert was encountered.     */    action: CallExceptionAction;    /**     *  The revert data returned.     */    data: null | string;    /**     *  A human-readable representation of data, if possible.     */    reason: null | string;    /**     *  The transaction that triggered the exception.     */    transaction: CallExceptionTransaction,    /**     *  The contract invocation details, if available.     */    invocation: null | {        method: string;        signature: string;        args: Array<any>;    }    /**     *  The built-in or custom revert error, if available     */    revert: null | {        signature: string;        name: string;        args: Array<any>;    }    /**     *  If the error occurred in a transaction that was mined     *  (with a status of ``0``), this is the receipt.     */    receipt?: TransactionReceipt;   // @TODO: in v7, make this `null | TransactionReceipt`}/** *  The sending account has insufficient funds to cover the *  entire transaction cost. */export interface InsufficientFundsError extends EthersError<"INSUFFICIENT_FUNDS"> {    /**     *  The transaction.     */    transaction: TransactionRequest;}/** *  The sending account has already used this nonce in a *  transaction that has been included. */export interface NonceExpiredError extends EthersError<"NONCE_EXPIRED"> {    /**     *  The transaction.     */    transaction: TransactionRequest;}/** *  A CCIP-read exception, which cannot be recovered from or *  be further processed. */export interface OffchainFaultError extends EthersError<"OFFCHAIN_FAULT"> {    /**     *  The transaction.     */    transaction?: TransactionRequest;    /**     *  The reason the CCIP-read failed.     */    reason: string;}/** *  An attempt was made to replace a transaction, but with an *  insufficient additional fee to afford evicting the old *  transaction from the memory pool. */export interface ReplacementUnderpricedError extends EthersError<"REPLACEMENT_UNDERPRICED"> {    /**     *  The transaction.     */    transaction: TransactionRequest;}/** *  A pending transaction was replaced by another. */export interface TransactionReplacedError extends EthersError<"TRANSACTION_REPLACED"> {    /**     *  If the transaction was cancelled, such that the original     *  effects of the transaction cannot be assured.     */    cancelled: boolean;    /**     *  The reason the transaction was replaced.     */    reason: "repriced" | "cancelled" | "replaced";    /**     *  The hash of the replaced transaction.     */    hash: string;    /**     *  The transaction that replaced the transaction.     */    replacement: TransactionResponse;    /**     *  The receipt of the transaction that replace the transaction.     */    receipt: TransactionReceipt;}/** *  This Error indicates an ENS name was used, but the name has not *  been configured. * *  This could indicate an ENS name is unowned or that the current *  address being pointed to is the [[ZeroAddress]]. */export interface UnconfiguredNameError extends EthersError<"UNCONFIGURED_NAME"> {    /**     *  The ENS name that was requested     */    value: string;}/** *  This Error indicates a request was rejected by the user. * *  In most clients (such as MetaMask), when an operation requires user *  authorization (such as ``signer.sendTransaction``), the client *  presents a dialog box to the user. If the user denies the request *  this error is thrown. */export interface ActionRejectedError extends EthersError<"ACTION_REJECTED"> {    /**     *  The requested action.     */    action: "requestAccess" | "sendTransaction" | "signMessage" | "signTransaction" | "signTypedData" | "unknown",    /**     *  The reason the action was rejected.     *     *  If there is already a pending request, some clients may indicate     *  there is already a ``"pending"`` action. This prevents an app     *  from spamming the user.     */    reason: "expired" | "rejected" | "pending"}// Coding; converts an ErrorCode its Typed Error/** *  A conditional type that transforms the [[ErrorCode]] T into *  its EthersError type. * *  @flatworm-skip-docs */export type CodedEthersError<T> =    T extends "UNKNOWN_ERROR" ? UnknownError:    T extends "NOT_IMPLEMENTED" ? NotImplementedError:    T extends "UNSUPPORTED_OPERATION" ? UnsupportedOperationError:    T extends "NETWORK_ERROR" ? NetworkError:    T extends "SERVER_ERROR" ? ServerError:    T extends "TIMEOUT" ? TimeoutError:    T extends "BAD_DATA" ? BadDataError:    T extends "CANCELLED" ? CancelledError:    T extends "BUFFER_OVERRUN" ? BufferOverrunError:    T extends "NUMERIC_FAULT" ? NumericFaultError:    T extends "INVALID_ARGUMENT" ? InvalidArgumentError:    T extends "MISSING_ARGUMENT" ? MissingArgumentError:    T extends "UNEXPECTED_ARGUMENT" ? UnexpectedArgumentError:    T extends "CALL_EXCEPTION" ? CallExceptionError:    T extends "INSUFFICIENT_FUNDS" ? InsufficientFundsError:    T extends "NONCE_EXPIRED" ? NonceExpiredError:    T extends "OFFCHAIN_FAULT" ? OffchainFaultError:    T extends "REPLACEMENT_UNDERPRICED" ? ReplacementUnderpricedError:    T extends "TRANSACTION_REPLACED" ? TransactionReplacedError:    T extends "UNCONFIGURED_NAME" ? UnconfiguredNameError:    T extends "ACTION_REJECTED" ? ActionRejectedError:    never;/** *  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<K extends ErrorCode, T extends CodedEthersError<K>>(error: any, code: K): error is T {    return (error && (<EthersError>error).code === code);}/** *  Returns true if %%error%% is a [[CallExceptionError]. */export function isCallException(error: any): error is CallExceptionError {    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<K extends ErrorCode, T extends CodedEthersError<K>>(message: string, code: K, info?: ErrorInfo<T>): T {    let shortMessage = message;    {        const details: Array<string> = [];        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 = <any>(info[<keyof ErrorInfo<T>>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<EthersError>(<EthersError>error, { code });    if (info) { Object.assign(error, info); }    if ((<any>error).shortMessage == null) {        defineProperties<EthersError>(<EthersError>error, { shortMessage });    }    return <T>error;}/** *  Throws an EthersError with %%message%%, %%code%% and additional error *  %%info%% when %%check%% is falsish.. * *  @see [[api:makeError]] */export function assert<K extends ErrorCode, T extends CodedEthersError<K>>(check: unknown, message: string, code: K, info?: ErrorInfo<T>): asserts check {    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: unknown, message: string, name: string, value: unknown): asserts check {    assert(check, message, "INVALID_ARGUMENT", { argument: name, value: value });}export function assertArgumentCount(count: number, expectedCount: number, message?: string): void {    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;}, <Array<string>>[]);/** *  Throws if the normalization %%form%% is not supported. */export function assertNormalize(form: string): void {    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: any, guard: any, className?: string): void {    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        });    }}
 |