/* This file is part of ethereum.js. ethereum.js is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. ethereum.js is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ /** @file utils.js * @authors: * Marek Kotewicz * @date 2015 */ if (process.env.NODE_ENV !== 'build') { var BigNumber = require('bignumber.js'); // jshint ignore:line } var unitMap = { 'wei': '1', 'kwei': '1000', 'ada': '1000', 'mwei': '1000000', 'babbage': '1000000', 'gwei': '1000000000', 'shannon': '1000000000', 'szabo': '1000000000000', 'finney': '1000000000000000', 'ether': '1000000000000000000', 'kether': '1000000000000000000000', 'grand': '1000000000000000000000', 'einstein': '1000000000000000000000', 'mether': '1000000000000000000000000', 'gether': '1000000000000000000000000000', 'tether': '1000000000000000000000000000000' }; /// Finds first index of array element matching pattern /// @param array /// @param callback pattern /// @returns index of element var findIndex = function (array, callback) { var end = false; var i = 0; for (; i < array.length && !end; i++) { end = callback(array[i]); } return end ? i - 1 : -1; }; /// @returns ascii string representation of hex value prefixed with 0x var toAscii = function(hex) { // Find termination var str = ""; var i = 0, l = hex.length; if (hex.substring(0, 2) === '0x') { i = 2; } for (; i < l; i+=2) { var code = parseInt(hex.substr(i, 2), 16); if (code === 0) { break; } str += String.fromCharCode(code); } return str; }; var toHexNative = function(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; }; /// @returns hex representation (prefixed by 0x) of ascii string var fromAscii = function(str, pad) { pad = pad === undefined ? 0 : pad; var hex = toHexNative(str); while (hex.length < pad*2) hex += "00"; return "0x" + hex; }; /// @returns 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; }; /// @returns 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(' ', '') : ""; }; /// Filters all function from input abi /// @returns abi array with filtered objects of type 'function' var filterFunctions = function (json) { return json.filter(function (current) { return current.type === 'function'; }); }; /// Filters all events form input abi /// @returns abi array with filtered objects of type 'event' var filterEvents = function (json) { return json.filter(function (current) { return current.type === 'event'; }); }; var toDecimal = function (val) { // pass it through is its already a number if(typeof val === 'number' || (typeof val === 'string' && val.indexOf('0x') === -1)) return val; // remove 0x and place 0, if it's required val = val.length > 2 ? val.substring(2) : "0"; return new BigNumber(val, 16).toNumber(); }; var fromDecimal = function (val) { return "0x" + (new BigNumber(val).toString(16)); }; var toHex = function (val) { return '0x' + toBigNumber(val).toString(16); }; /** * Returns value of unit in Wei * * @method getValueOfUnit * @param {String} unit the unit to convert to, default ether * @returns {BigNumber} value of the unit (in Wei) * @throws error if the unit is not correct:w */ var getValueOfUnit = function (unit) { unit = unit ? unit.toLowerCase() : 'ether'; var unitValue = unitMap[unit]; if (unitValue === undefined) { throw new Error('This unit doesn\'t exists, please use the one of the following units' + JSON.stringify(unitMap, null, 2)); } return new BigNumber(unitValue, 10); }; /** * Takes a number of wei and converts it to any other ether unit. * * Possible units are: * - kwei/ada * - mwei/babbage * - gwei/shannon * - szabo * - finney * - ether * - kether/grand/einstein * - mether * - gether * - tether * * @method fromWei * @param {Number|String} number can be a number, number string or a HEX of a decimal * @param {String} unit the unit to convert to, default ether * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number */ var fromWei = function(number, unit) { return toBigNumber(number).dividedBy(getValueOfUnit(unit)).toString(10); }; /** * Takes a number of a unit and converts it to wei. * * Possible units are: * - kwei/ada * - mwei/babbage * - gwei/shannon * - szabo * - finney * - ether * - kether/grand/einstein * - mether * - gether * - tether * * @method toWei * @param {Number|String|BigNumber} number can be a number, number string or a HEX of a decimal * @param {String} unit the unit to convert from, default ether * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number */ var toWei = function(number, unit) { return toBigNumber(number).times(getValueOfUnit(unit)).toString(10); }; /** * Takes an input and transforms it into an bignumber * * @method toBigNumber * @param {Number|String|BigNumber} a number, string, HEX string or BigNumber * @return {Object} BigNumber */ var toBigNumber = function(number) { number = number || 0; if (isBigNumber(number)) return number; if (isString(number) && number.indexOf('0x') === 0) return new BigNumber(number, 16); return new BigNumber(number.toString(10), 10); }; /** * Checks if the given string has proper length * * @method isAddress * @param {String} address the given HEX adress * @return {Boolean} */ var isAddress = function(address) { return ((address.indexOf('0x') === 0 && address.length === 42) || (address.indexOf('0x') === -1 && address.length === 40)); }; /** * Returns true if object is BigNumber, otherwise false * * @method isBigNumber * @param {Object} * @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} * @return {Boolean} */ var isString = function (object) { return typeof object === 'string'; }; module.exports = { findIndex: findIndex, toHex: toHex, toDecimal: toDecimal, fromDecimal: fromDecimal, toAscii: toAscii, fromAscii: fromAscii, extractDisplayName: extractDisplayName, extractTypeName: extractTypeName, filterFunctions: filterFunctions, filterEvents: filterEvents, toWei: toWei, fromWei: fromWei, toBigNumber: toBigNumber, isBigNumber: isBigNumber, isAddress: isAddress };