text: import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
  import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
  import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
  import _inherits from "@babel/runtime/helpers/esm/inherits";
  import _assertThisInitialized from "@babel/runtime/helpers/esm/assertThisInitialized";
  import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
  import _typeof from "@babel/runtime/helpers/esm/typeof";
  import BN from 'bn.js';
  import { ENV, WEI_MINIFICATION, GWEI_MINIFICATION, DESCRIPTORS } from './defaults';
  import { utils as messages } from './messages';
  /**
   * Simple helper to determine if we should output messages to the console
   * based on the environment the modules have been built in
   *
   * @method verbose
   *
   * @return {boolean} Do we output to the console, or not?
   */
  
  export var verbose = function verbose() {
    if (typeof ENV === 'undefined') {
      return true;
    }
  
    if (ENV === 'development') {
      return true;
    }
  
    return false;
  };
  /**
   * If we're in `dev` mode, show an warning to the console
   *
   * This way you won't have to explicitly tell it which message from `messages.js` to show
   * Arguments will be split into three types:
   *   First arg will be the message string
   *   Rest of them will be template literals that will replace %s values in the previous messsage string (with one exception)
   *   If the last argument is an object that has only one prop named `level`, it will be interpreted as an option object
   *   (if level equals `low` it will only warn, if the level equals `high`, it will error)
   *
   * @method warning
   *
   * @param {any} args Arguments array that will be passed down to `console` methods (see above)
   */
  
  export var warning = function warning() {
    var _console;
  
    /*
     * Stop everything if we're in production mode.
     * No point in doing all the computations and assignments if we don't have to.
     */
    if (!verbose()) {
      return undefined;
    }
  
    var level = 'low';
  
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }
  
    var lastArgIndex = args.length - 1;
    var options = args[lastArgIndex];
    var message = args[0];
    var literalTemplates = args.slice(1);
    /*
     * We're being very specific with object testing here, since we don't want to
     * highjack a legitimate object that comes in as a template part (althogh
     * this is very unlikely)
     */
  
    if (_typeof(options) === 'object' && typeof options.level === 'string' && Object.keys(options).length === 1) {
      level = options.level;
      literalTemplates.pop();
    }
  
    var warningType = 'warn';
  
    if (level === 'high') {
      warningType = 'error';
    }
    /*
     * This is actually correct since we're allowed to console warn/error by eslint,
     * it's just that it doesn't know which method we're calling (see above), so it warns by default
     */
  
    /* eslint-disable-next-line no-console */
  
  
    return (_console = console)[warningType].apply(_console, [message].concat(_toConsumableArray(literalTemplates.map(function (value) {
      if (_typeof(value) === 'object') {
        return JSON.stringify(value);
      }
  
      return value;
    }))));
  };
  /**
   * A very basic polyfill method to generate randomness for use in wallet entropy.
   * This will fall back to nodejs's `crypto` library if the browser that's using this doesn't have the `webcrypto` API implemented yet.
   *
   * @method getRandomValues
   *
   * @param {Uint8Array} typedArray An initial unsigned 8-bit integer array to generate randomness from
   *
   * @return {Uint8Array} A new 8-bit unsigned integer array filled with random bytes
   */
  
  export var getRandomValues = function getRandomValues() {
    var typedArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Uint8Array(10);
  
    /*
     * Check if `webCrypto` is available (Chrome and Firefox browsers)
     *
     * Also check if the `window` global variable is avaiable if this library
     * is being used in a `node` environment
     */
    if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {
      return window.crypto.getRandomValues(typedArray);
    }
    /*
     * Check if `webCrypto` is available (Microsoft based browsers, most likely Edge)
     *
     * Also check if the `window` global variable is avaiable if this library
     * is being used in a `node` environment
     */
  
  
    if (typeof window !== 'undefined' && _typeof(window.msCrypto) === 'object' && typeof window.msCrypto.getRandomValues === 'function') {
      return window.msCrypto.getRandomValues(typedArray);
    }
    /*
     * We can't find any crypto method, we'll try to do our own.
     *
     * WARNING: This is really not all that secure as it relies on Javascripts'
     * internal random number generator, which isn't all that good.
     */
  
  
    warning(messages.getRandomValues.noCryptoLib);
    return typedArray.map(function () {
      return Math.floor(Math.random() * 255);
    });
  };
  /**
   * Check if an expression is true and, if not, either throw an error or just log a message.
   *
   * Just as the `warning()` util above it uses two levels: `high` and `low`. If the set level is high (default),
   * it will throw an error, else it will just use the `warning()` method (set to `low`) to log the message
   * as an warning.
   *
   * @method assertTruth
   *
   * @param {boolean} expression The logic expression to assert
   * @param {string | Array<string>} message The message to display in case of an error
   * @param {string} level The log level: high (error) or low (warning)
   *
   * The above parameters are sent in as props of an object.
   *
   * @return {boolean} true if the expression is valid, false otherwise (and depending on the level, throw an error
   * or just log the warning)
   */
  
  export var assertTruth = function assertTruth() {
    var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
        expression = _ref.expression,
        message = _ref.message,
        _ref$level = _ref.level,
        level = _ref$level === void 0 ? 'high' : _ref$level;
  
    if (expression) {
      return true;
    }
  
    if (level === 'high') {
      throw new Error(Array.isArray(message) ? message.join(' ') : message);
    }
  
    if (Array.isArray(message)) {
      warning.apply(void 0, _toConsumableArray(message));
    } else {
      warning(message);
    }
  
    return false;
  };
  /**
   * Wrapper for the `bn.js` constructor to use as an utility for big numbers
   *
   * Make sure to inform the users that this is the preffered way of interacting with
   * big numbers inside this library, as even if the underlying Big Number library will change,
   * this API will (mostly) stay the same.
   *
   * See: BigInt
   * https://developers.google.com/web/updates/2018/05/bigint
   *
   * @TODO Add internal version of methods
   * Eg: `ifromWei()` and `itoWei`. See BN's docs about prefixes and postfixes
   *
   * @method bigNumber
   *
   * @param {number | string | BN} value the value to convert to a big number
   *
   * @return {BN} The new bignumber instance
   */
  
  export var bigNumber = function bigNumber(value) {
    var GETTERS = DESCRIPTORS.GETTERS;
    var oneWei = new BN(WEI_MINIFICATION.toString());
    var oneGwei = new BN(GWEI_MINIFICATION.toString());
  
    var ExtendedBN =
    /*#__PURE__*/
    function (_BN) {
      _inherits(ExtendedBN, _BN);
  
      function ExtendedBN() {
        var _getPrototypeOf2;
  
        var _this;
  
        _classCallCheck(this, ExtendedBN);
  
        for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
          args[_key2] = arguments[_key2];
        }
  
        _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(ExtendedBN)).call.apply(_getPrototypeOf2, [this].concat(args)));
        var ExtendedBNPrototype = Object.getPrototypeOf(_assertThisInitialized(_assertThisInitialized(_this)));
        Object.defineProperties(ExtendedBNPrototype, {
          /*
           * Convert the number to WEI (multiply by 1 to the power of 18)
           */
          toWei: Object.assign({}, {
            value: function value() {
              return _this.imul(oneWei);
            }
          }, GETTERS),
  
          /*
           * Convert the number to WEI (divide by 1 to the power of 18)
           */
          fromWei: Object.assign({}, {
            value: function value() {
              return _this.div(oneWei);
            }
          }, GETTERS),
  
          /*
           * Convert the number to GWEI (multiply by 1 to the power of 9)
           */
          toGwei: Object.assign({}, {
            value: function value() {
              return _this.imul(oneGwei);
            }
          }, GETTERS),
  
          /*
           * Convert the number to GWEI (divide by 1 to the power of 9)
           */
          fromGwei: Object.assign({}, {
            value: function value() {
              return _this.div(oneGwei);
            }
          }, GETTERS)
        });
        return _this;
      }
  
      return ExtendedBN;
    }(BN);
  
    return new ExtendedBN(value);
  };
  /**
   * Convert an object to a key (value) concatenated string.
   * This is useful to list values inside of error messages, where you can only pass in a string and
   * not the whole object.
   *
   * @method objectToErrorString
   *
   * @param {Object} object The object to convert
   *
   * @return {string} The string containing the object's key (value) pairs
   */
  
  export var objectToErrorString = function objectToErrorString() {
    var object = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    return Object.keys(object).reduce(function (allArgs, key) {
      return "".concat(allArgs).concat(key, " (").concat(String(JSON.stringify(object[key])), "), ");
    }, '').replace(/"/g, '').trim();
  };
  /**
   * Validate an (array) sequence of validation assertions (objects that are to be
   * directly passed into `assertTruth`)
   *
   * This is to reduce code duplication and boilerplate.
   *
   * @TODO Validate the validator
   * So we can have redundancy while being reduntant :)
   *
   * @method validatorGenerator
   *
   * @param {Array} validationSequenceArray An array containing objects which are in the same format as the one expect by `assertTruth`
   * @param {string} genericError A generic error message to be used for the catch all error (and if some of the other messages are missing)
   *
   * @return {boolean} It only returns true if all the validation assertions pass,
   * otherwise an Error will be thrown and this will not finish execution.
   */
  
  export var validatorGenerator = function validatorGenerator(validationSequenceArray, genericError) {
    var validationTests = [];
    validationSequenceArray.map(function (validationSequence) {
      return validationTests.push(assertTruth(
      /*
       * If there's no message passed in, use the generic error
       */
      Object.assign({}, {
        message: genericError,
        level: 'high'
      }, validationSequence)));
    });
    /*
     * This is a fail-safe in case anything spills through.
     * If any of the values are `false` throw a general Error
     */
  
    if (!validationTests.every(function (testResult) {
      return testResult === true;
    })) {
      throw new Error(genericError);
    }
    /*
     * Everything goes well here. (But most likely this value will be ignored)
     */
  
  
    return true;
  };