UNPKG

@silasdavis/legacy-contracts

Version:

Library with javascript bindings for Solidity contracts.

456 lines (419 loc) 11.2 kB
/** * @file utils.js * @author Marek Kotewicz <marek@ethdev.com> * @author Andreas Olofsson * @date 2015 * @module utils/utils */ var BigNumber = require('bignumber.js') var utf8 = require('utf8') /** * Should be called to pad string to expected length * * @method padLeft * @param {String} string to be padded * @param {Number} chars - characters that result string should have * @param {String} sign, by default 0 * @returns {String} right aligned string */ var padLeft = function (string, chars, sign) { return new Array(chars - string.length + 1).join(sign || '0') + string } /** * Should be called to pad string to expected length * * @method padRight * @param {String} string to be padded * @param {Number} chars - characters that result string should have * @param {String} sign, by default 0 * @returns {String} right aligned string */ var padRight = function (string, chars, sign) { return string + (new Array(chars - string.length + 1).join(sign || '0')) } /** * Shold be called to get hex representation (prefixed by 0x) of utf8 string * * @method fromUtf8 * @param {String} str - string * @param {Number} optional padding * @returns {String} hex representation of input string */ var fromUtf8 = function (str) { str = utf8.encode(str) var hex = '' for (var i = 0; i < str.length; i++) { var n = str.charCodeAt(i).toString(16) hex += n.length < 2 ? '0' + n : n } return hex } /** * Should be called to get utf8 from it's hex representation * * @method toUtf8 * @param {String} hex - string in hex * @returns {String} ascii string representation of hex value */ var toUtf8 = function (hex) { // Find termination var str = '' var i = 0 var l = hex.length if (hex.substring(0, 2) === '0x') { i = 2 } for (; i < l; i += 2) { var code = parseInt(hex.substr(i, 2), 16) str += String.fromCharCode(code) } return utf8.decode(str) } /** * Should be called to get sting from it's hex representation * * @method toAscii * @param {String} hex - string in hex * @returns {String} ascii string representation of hex value */ var hexToAscii = function (hex) { // Find termination var str = '' var i = 0 var l = hex.length if (hex.substring(0, 2) === '0x') { i = 2 } for (; i < l; i += 2) { for (; i < l; i += 2) { var code = parseInt(hex.substr(i, 2), 16) str += String.fromCharCode(code) } } return str } /** * Should be called to get hex representation of ascii string * * @method toHexNative * @param {String} str - string * @param {Number} pad - optional padding * @returns {String} hex representation of input string */ var asciiToHex = function (str, pad) { var hex = '' for (var i = 0; i < str.length; i++) { var n = str.charCodeAt(i).toString(16) hex += n.length < 2 ? '0' + n : n } pad = pad === undefined ? 0 : pad while (hex.length < pad * 2) { hex += '00' } return hex } /** * Should be used to create full function/event name from json abi * * @method transformToFullName * @param {Object} json - json-abi * @return {String} full fnction/event name */ var transformToFullName = function (json) { if (json.name.indexOf('(') !== -1) { return json.name } var typeName = json.inputs.map(function (i) { return i.type }).join() return json.name + '(' + typeName + ')' } /** * Should be called to get display name of contract function * * @method extractDisplayName * @param {String} name of function/event * @returns {String} display name for function/event eg. multiply(uint256) -> multiply */ var extractDisplayName = function (name) { var length = name.indexOf('(') return length !== -1 ? name.substr(0, length) : name } /** * * @param {String} name - the name. * @returns {String} overloaded part of function/event name */ var extractTypeName = function (name) { /// TODO: make it invulnerable var length = name.indexOf('(') return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : '' } /** * Converts value to it's decimal representation in string * * @method toDecimal * @param {String|Number|BigNumber} value - the value * @return {String} */ var toDecimal = function (value) { return toBigNumber(value).toNumber() } /** * Converts value to it's hex representation * * TODO why is this called 'fromDecimal' when a use case is to pass it a confirmed (signed) hex string. * * @method fromDecimal * @param {String|Number|BigNumber} value - the value * @return {String} */ var fromDecimal = function (value) { var number = toBigNumber(value) var result = number.toString(16) return number.lessThan(0) ? '-0x' + result.substr(1) : result } /** * Auto converts any given value into it's hex representation. * * @method toHex * @param {boolean|String|Number|BigNumber|Object} val - the value. * @return {String} */ var toHex = function (val) { /* jshint maxcomplexity: 8 */ if (isBoolean(val)) { return fromDecimal(+val) } else if (isNumber(val)) { return fromDecimal(val) } else if (isBigNumber(val)) { return fromDecimal(val) } else if (isObject(val)) { return asciiToHex(JSON.stringify(val)) } else if (isString(val)) { // Zero-length strings are null hex-strings, which we allow. if (val.length === 0) { return val } else if (val[0] === '-') { // Switch on first char being a '-'. If this is the case, it's either // a signed hex- or decimal-string, otherwise ascii. if (isHex(val.substr(1)) || isDecimal(val.substr(1))) { return fromDecimal(val) } else { return asciiToHex(val) } } else { // We make sure any '0x' is removed before returning. if (isHex(val)) { if (val.length >= 2 && val.indexOf('0x') === 0) { val = val.substr(2) } return val } else if (isDecimal(val)) { return fromDecimal(val) } else { return asciiToHex(val) } } } else { // If neither a boolean, number, bignumber or string, throw a type error. throw new TypeError('No method for converting object into hex: ' + val.toString()) } } /** * Takes an input and transforms it into an bignumber * * @method toBigNumber * @param {Number|String|BigNumber} number - a number, string, HEX string or BigNumber * @return {BigNumber} BigNumber */ var toBigNumber = function (number) { /* jshint maxcomplexity:5 */ number = number || 0 if (isBigNumber(number)) { return number } if (isString(number) && (number.indexOf('0x') === 0 || number.indexOf('-0x') === 0)) { return new BigNumber(number.replace('0x', ''), 16) } return new BigNumber(number.toString(10), 10) } /** * Takes and input transforms it into bignumber and if it is negative value, into two's complement * * @method toTwosComplement * @param {Number|String|BigNumber} number - input number * @return {BigNumber} */ var toTwosComplement = function (number) { var bigNumber = toBigNumber(number) if (bigNumber.lessThan(0)) { return new BigNumber('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16).plus(bigNumber).plus(1) } return bigNumber } /** * Checks if the given string is strictly an address * * @method isStrictAddress * @param {String} address the given HEX adress * @return {Boolean} */ var isStrictAddress = function (address) { return /^0x[0-9a-fA-F]{40}$/.test(address) } /** * Checks if the given string is an address * * @method isAddress * @param {String} address the given HEX adress * @return {Boolean} */ var isAddress = function (address) { return /^(0x)?[0-9a-fA-F]{40}$/.test(address) } /** * Checks if the given string is hex * * @method isHex * @param {String} str - the string * @return {Boolean} */ var isHex = function (str) { return /^(0x)?[0-9a-fA-F]*$/.test(str) } /** * Checks if the given string is decimal * * @method isDecimal * @param {String} str - the string * @return {Boolean} */ var isDecimal = function (str) { return /^[0-9]*$/.test(str) } /** * Transforms given string to valid 20 bytes-length addres with 0x prefix * * @method toAddress * @param {String} address * @return {String} formatted address */ var toAddress = function (address) { if (isStrictAddress(address)) { return address.substr(2) } if (/^[0-9a-f]{40}$/.test(address)) { return address } return padLeft(toHex(address).substr(2), 40) } /** * Returns true if object is BigNumber, otherwise false * * @method isBigNumber * @param {Object} object - object to test * @return {Boolean} */ var isBigNumber = function (object) { return object instanceof BigNumber || (object && object.constructor && object.constructor.name === 'BigNumber') } /** * Returns true if object is string, otherwise false * * @method isString * @param {Object} object - object to test * @return {Boolean} */ var isString = function (object) { return typeof object === 'string' || (object && object.constructor && object.constructor.name === 'String') } /** * Returns true if object is a number, otherwise false * * @method isString * @param {Object} object - object to test * @return {Boolean} */ var isNumber = function (object) { return typeof object === 'number' || (object && object.constructor && object.constructor.name === 'Number') } /** * Returns true if object is function, otherwise false * * @method isFunction * @param {Object} object - object to test * @return {Boolean} */ var isFunction = function (object) { return typeof object === 'function' } /** * Returns true if object is Objet, otherwise false * * @method isObject * @param {Object} object - object to test * @return {Boolean} */ var isObject = function (object) { return typeof object === 'object' } /** * Returns true if object is boolean, otherwise false * * @method isBoolean * @param {Object} object - object to test * @return {Boolean} */ var isBoolean = function (object) { return typeof object === 'boolean' } /** * Returns true if object is array, otherwise false * * @method isArray * @param {Object} object - object to test * @return {Boolean} */ var isArray = function (object) { return object instanceof Array } /** * Returns true if given string is valid json object * * @method isJson * @param {String} str - the string to test * @return {Boolean} */ var isJson = function (str) { try { return !!JSON.parse(str) } catch (e) { return false } } module.exports = { toHex: toHex, padLeft: padLeft, padRight: padRight, hexToAscii: hexToAscii, asciiToHex: asciiToHex, fromDecimal: fromDecimal, toDecimal: toDecimal, transformToFullName: transformToFullName, extractDisplayName: extractDisplayName, extractTypeName: extractTypeName, toTwosComplement: toTwosComplement, toAddress: toAddress, isBigNumber: isBigNumber, isStrictAddress: isStrictAddress, isAddress: isAddress, isHex: isHex, isFunction: isFunction, isString: isString, isObject: isObject, isBoolean: isBoolean, isArray: isArray, isJson: isJson, fromUtf8: fromUtf8, toUtf8: toUtf8 }