text: "use strict";
  let _permanentCensorErrors = false;
  let _censorErrors = false;
  const LogLevels = { debug: 1, "default": 2, info: 2, warning: 3, error: 4, off: 5 };
  let _logLevel = LogLevels["default"];
  import { version } from "./_version";
  let _globalLogger = null;
  function _checkNormalize() {
      try {
          const missing = [];
          // Make sure all forms of normalization are supported
          ["NFD", "NFC", "NFKD", "NFKC"].forEach((form) => {
              try {
                  if ("test".normalize(form) !== "test") {
                      throw new Error("bad normalize");
                  }
                  ;
              }
              catch (error) {
                  missing.push(form);
              }
          });
          if (missing.length) {
              throw new Error("missing " + missing.join(", "));
          }
          if (String.fromCharCode(0xe9).normalize("NFD") !== String.fromCharCode(0x65, 0x0301)) {
              throw new Error("broken implementation");
          }
      }
      catch (error) {
          return error.message;
      }
      return null;
  }
  const _normalizeError = _checkNormalize();
  export var LogLevel;
  (function (LogLevel) {
      LogLevel["DEBUG"] = "DEBUG";
      LogLevel["INFO"] = "INFO";
      LogLevel["WARNING"] = "WARNING";
      LogLevel["ERROR"] = "ERROR";
      LogLevel["OFF"] = "OFF";
  })(LogLevel || (LogLevel = {}));
  export var ErrorCode;
  (function (ErrorCode) {
      ///////////////////
      // Generic Errors
      // Unknown Error
      ErrorCode["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
      // Not Implemented
      ErrorCode["NOT_IMPLEMENTED"] = "NOT_IMPLEMENTED";
      // Unsupported Operation
      //   - operation
      ErrorCode["UNSUPPORTED_OPERATION"] = "UNSUPPORTED_OPERATION";
      // Network Error (i.e. 420coin Network, such as an invalid chain ID)
      //   - event ("noNetwork" is not re-thrown in provider.ready; otherwise thrown)
      ErrorCode["NETWORK_ERROR"] = "NETWORK_ERROR";
      // Some sort of bad response from the server
      ErrorCode["SERVER_ERROR"] = "SERVER_ERROR";
      // Timeout
      ErrorCode["TIMEOUT"] = "TIMEOUT";
      ///////////////////
      // Operational  Errors
      // Buffer Overrun
      ErrorCode["BUFFER_OVERRUN"] = "BUFFER_OVERRUN";
      // Numeric Fault
      //   - operation: the operation being executed
      //   - fault: the reason this faulted
      ErrorCode["NUMERIC_FAULT"] = "NUMERIC_FAULT";
      ///////////////////
      // Argument Errors
      // Missing new operator to an object
      //  - name: The name of the class
      ErrorCode["MISSING_NEW"] = "MISSING_NEW";
      // Invalid argument (e.g. value is incompatible with type) to a function:
      //   - argument: The argument name that was invalid
      //   - value: The value of the argument
      ErrorCode["INVALID_ARGUMENT"] = "INVALID_ARGUMENT";
      // Missing argument to a function:
      //   - count: The number of arguments received
      //   - expectedCount: The number of arguments expected
      ErrorCode["MISSING_ARGUMENT"] = "MISSING_ARGUMENT";
      // Too many arguments
      //   - count: The number of arguments received
      //   - expectedCount: The number of arguments expected
      ErrorCode["UNEXPECTED_ARGUMENT"] = "UNEXPECTED_ARGUMENT";
      ///////////////////
      // Blockchain Errors
      // Call exception
      //  - transaction: the transaction
      //  - address?: the contract address
      //  - args?: The arguments passed into the function
      //  - method?: The Solidity method signature
      //  - errorSignature?: The EIP848 error signature
      //  - errorArgs?: The EIP848 error parameters
      //  - reason: The reason (only for EIP848 "Error(string)")
      ErrorCode["CALL_EXCEPTION"] = "CALL_EXCEPTION";
      // Insufficien funds (< value + smokeLimit * smokePrice)
      //   - transaction: the transaction attempted
      ErrorCode["INSUFFICIENT_FUNDS"] = "INSUFFICIENT_FUNDS";
      // Nonce has already been used
      //   - transaction: the transaction attempted
      ErrorCode["NONCE_EXPIRED"] = "NONCE_EXPIRED";
      // The replacement fee for the transaction is too low
      //   - transaction: the transaction attempted
      ErrorCode["REPLACEMENT_UNDERPRICED"] = "REPLACEMENT_UNDERPRICED";
      // The smoke limit could not be estimated
      //   - transaction: the transaction passed to estimateSmoke
      ErrorCode["UNPREDICTABLE_SMOKE_LIMIT"] = "UNPREDICTABLE_SMOKE_LIMIT";
  })(ErrorCode || (ErrorCode = {}));
  ;
  export class Logger {
      constructor(version) {
          Object.defineProperty(this, "version", {
              enumerable: true,
              value: version,
              writable: false
          });
      }
      _log(logLevel, args) {
          const level = logLevel.toLowerCase();
          if (LogLevels[level] == null) {
              this.throwArgumentError("invalid log level name", "logLevel", logLevel);
          }
          if (_logLevel > LogLevels[level]) {
              return;
          }
          console.log.apply(console, args);
      }
      debug(...args) {
          this._log(Logger.levels.DEBUG, args);
      }
      info(...args) {
          this._log(Logger.levels.INFO, args);
      }
      warn(...args) {
          this._log(Logger.levels.WARNING, args);
      }
      makeError(message, code, params) {
          // Errors are being censored
          if (_censorErrors) {
              return this.makeError("censored error", code, {});
          }
          if (!code) {
              code = Logger.errors.UNKNOWN_ERROR;
          }
          if (!params) {
              params = {};
          }
          const messageDetails = [];
          Object.keys(params).forEach((key) => {
              try {
                  messageDetails.push(key + "=" + JSON.stringify(params[key]));
              }
              catch (error) {
                  messageDetails.push(key + "=" + JSON.stringify(params[key].toString()));
              }
          });
          messageDetails.push(`code=${code}`);
          messageDetails.push(`version=${this.version}`);
          const reason = message;
          if (messageDetails.length) {
              message += " (" + messageDetails.join(", ") + ")";
          }
          // @TODO: Any??
          const error = new Error(message);
          error.reason = reason;
          error.code = code;
          Object.keys(params).forEach(function (key) {
              error[key] = params[key];
          });
          return error;
      }
      throwError(message, code, params) {
          throw this.makeError(message, code, params);
      }
      throwArgumentError(message, name, value) {
          return this.throwError(message, Logger.errors.INVALID_ARGUMENT, {
              argument: name,
              value: value
          });
      }
      assert(condition, message, code, params) {
          if (!!condition) {
              return;
          }
          this.throwError(message, code, params);
      }
      assertArgument(condition, message, name, value) {
          if (!!condition) {
              return;
          }
          this.throwArgumentError(message, name, value);
      }
      checkNormalize(message) {
          if (message == null) {
              message = "platform missing String.prototype.normalize";
          }
          if (_normalizeError) {
              this.throwError("platform missing String.prototype.normalize", Logger.errors.UNSUPPORTED_OPERATION, {
                  operation: "String.prototype.normalize", form: _normalizeError
              });
          }
      }
      checkSafeUint53(value, message) {
          if (typeof (value) !== "number") {
              return;
          }
          if (message == null) {
              message = "value not safe";
          }
          if (value < 0 || value >= 0x1fffffffffffff) {
              this.throwError(message, Logger.errors.NUMERIC_FAULT, {
                  operation: "checkSafeInteger",
                  fault: "out-of-safe-range",
                  value: value
              });
          }
          if (value % 1) {
              this.throwError(message, Logger.errors.NUMERIC_FAULT, {
                  operation: "checkSafeInteger",
                  fault: "non-integer",
                  value: value
              });
          }
      }
      checkArgumentCount(count, expectedCount, message) {
          if (message) {
              message = ": " + message;
          }
          else {
              message = "";
          }
          if (count < expectedCount) {
              this.throwError("missing argument" + message, Logger.errors.MISSING_ARGUMENT, {
                  count: count,
                  expectedCount: expectedCount
              });
          }
          if (count > expectedCount) {
              this.throwError("too many arguments" + message, Logger.errors.UNEXPECTED_ARGUMENT, {
                  count: count,
                  expectedCount: expectedCount
              });
          }
      }
      checkNew(target, kind) {
          if (target === Object || target == null) {
              this.throwError("missing new", Logger.errors.MISSING_NEW, { name: kind.name });
          }
      }
      checkAbstract(target, kind) {
          if (target === kind) {
              this.throwError("cannot instantiate abstract class " + JSON.stringify(kind.name) + " directly; use a sub-class", Logger.errors.UNSUPPORTED_OPERATION, { name: target.name, operation: "new" });
          }
          else if (target === Object || target == null) {
              this.throwError("missing new", Logger.errors.MISSING_NEW, { name: kind.name });
          }
      }
      static globalLogger() {
          if (!_globalLogger) {
              _globalLogger = new Logger(version);
          }
          return _globalLogger;
      }
      static setCensorship(censorship, permanent) {
          if (!censorship && permanent) {
              this.globalLogger().throwError("cannot permanently disable censorship", Logger.errors.UNSUPPORTED_OPERATION, {
                  operation: "setCensorship"
              });
          }
          if (_permanentCensorErrors) {
              if (!censorship) {
                  return;
              }
              this.globalLogger().throwError("error censorship permanent", Logger.errors.UNSUPPORTED_OPERATION, {
                  operation: "setCensorship"
              });
          }
          _censorErrors = !!censorship;
          _permanentCensorErrors = !!permanent;
      }
      static setLogLevel(logLevel) {
          const level = LogLevels[logLevel.toLowerCase()];
          if (level == null) {
              Logger.globalLogger().warn("invalid log level - " + logLevel);
              return;
          }
          _logLevel = level;
      }
  }
  Logger.errors = ErrorCode;
  Logger.levels = LogLevel;
  //# sourceMappingURL=index.js.map