2015-01-31 00:52:36 +00:00
|
|
|
/*
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
/** @file formatters.js
|
|
|
|
* @authors:
|
|
|
|
* Marek Kotewicz <marek@ethdev.com>
|
|
|
|
* @date 2015
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (process.env.NODE_ENV !== 'build') {
|
|
|
|
var BigNumber = require('bignumber.js'); // jshint ignore:line
|
|
|
|
}
|
|
|
|
|
2015-01-31 12:54:39 +00:00
|
|
|
var utils = require('./utils');
|
2015-03-03 10:11:52 +00:00
|
|
|
var c = require('./config');
|
2015-01-31 00:52:36 +00:00
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Should be called to pad string to expected length
|
|
|
|
*
|
|
|
|
* @method padLeft
|
|
|
|
* @param {String} string to be padded
|
|
|
|
* @param {Number} characters that result string should have
|
|
|
|
* @param {String} sign, by default 0
|
|
|
|
* @returns {String} right aligned string
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var padLeft = function (string, chars, sign) {
|
|
|
|
return new Array(chars - string.length + 1).join(sign ? sign : "0") + string;
|
|
|
|
};
|
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Formats input value to byte representation of int
|
|
|
|
* If value is negative, return it's two's complement
|
|
|
|
* If the value is floating point, round it down
|
|
|
|
*
|
|
|
|
* @method formatInputInt
|
|
|
|
* @param {String|Number|BigNumber} value that needs to be formatted
|
|
|
|
* @returns {String} right-aligned byte representation of int
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var formatInputInt = function (value) {
|
2015-01-31 13:05:48 +00:00
|
|
|
var padding = c.ETH_PADDING * 2;
|
2015-03-08 16:28:32 +00:00
|
|
|
BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);
|
|
|
|
return padLeft(utils.toTwosComplement(value).round().toString(16), padding);
|
2015-01-31 00:52:36 +00:00
|
|
|
};
|
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Formats input value to byte representation of string
|
|
|
|
*
|
|
|
|
* @method formatInputString
|
|
|
|
* @param {String}
|
|
|
|
* @returns {String} left-algined byte representation of string
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var formatInputString = function (value) {
|
2015-01-31 13:05:48 +00:00
|
|
|
return utils.fromAscii(value, c.ETH_PADDING).substr(2);
|
2015-01-31 00:52:36 +00:00
|
|
|
};
|
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Formats input value to byte representation of bool
|
|
|
|
*
|
|
|
|
* @method formatInputBool
|
|
|
|
* @param {Boolean}
|
|
|
|
* @returns {String} right-aligned byte representation bool
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var formatInputBool = function (value) {
|
|
|
|
return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');
|
|
|
|
};
|
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Formats input value to byte representation of real
|
|
|
|
* Values are multiplied by 2^m and encoded as integers
|
|
|
|
*
|
|
|
|
* @method formatInputReal
|
|
|
|
* @param {String|Number|BigNumber}
|
|
|
|
* @returns {String} byte representation of real
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var formatInputReal = function (value) {
|
|
|
|
return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Check if input value is negative
|
|
|
|
*
|
|
|
|
* @method signedIsNegative
|
|
|
|
* @param {String} value is hex format
|
|
|
|
* @returns {Boolean} true if it is negative, otherwise false
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var signedIsNegative = function (value) {
|
|
|
|
return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1';
|
|
|
|
};
|
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Formats right-aligned output bytes to int
|
|
|
|
*
|
|
|
|
* @method formatOutputInt
|
|
|
|
* @param {String} bytes
|
|
|
|
* @returns {BigNumber} right-aligned output bytes formatted to big number
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var formatOutputInt = function (value) {
|
2015-02-23 16:05:53 +00:00
|
|
|
|
2015-01-31 00:52:36 +00:00
|
|
|
value = value || "0";
|
2015-02-23 16:05:53 +00:00
|
|
|
|
2015-01-31 00:52:36 +00:00
|
|
|
// check if it's negative number
|
|
|
|
// it it is, return two's complement
|
|
|
|
if (signedIsNegative(value)) {
|
|
|
|
return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);
|
|
|
|
}
|
|
|
|
return new BigNumber(value, 16);
|
|
|
|
};
|
|
|
|
|
2015-02-23 16:05:53 +00:00
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Formats right-aligned output bytes to uint
|
|
|
|
*
|
|
|
|
* @method formatOutputUInt
|
|
|
|
* @param {String} bytes
|
|
|
|
* @returns {BigNumeber} right-aligned output bytes formatted to uint
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var formatOutputUInt = function (value) {
|
|
|
|
value = value || "0";
|
|
|
|
return new BigNumber(value, 16);
|
|
|
|
};
|
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Formats right-aligned output bytes to real
|
|
|
|
*
|
|
|
|
* @method formatOutputReal
|
|
|
|
* @param {String}
|
|
|
|
* @returns {BigNumber} input bytes formatted to real
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var formatOutputReal = function (value) {
|
|
|
|
return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128));
|
|
|
|
};
|
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Formats right-aligned output bytes to ureal
|
|
|
|
*
|
|
|
|
* @param {String}
|
|
|
|
* @returns {BigNumber} input bytes formatted to ureal
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var formatOutputUReal = function (value) {
|
|
|
|
return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128));
|
|
|
|
};
|
|
|
|
|
2015-03-08 16:28:32 +00:00
|
|
|
/**
|
|
|
|
* Formats output hash
|
|
|
|
*
|
|
|
|
* @param {String}
|
|
|
|
* @returns {String} right-aligned output bytes formatted to hex
|
|
|
|
*/
|
2015-01-31 00:52:36 +00:00
|
|
|
var formatOutputHash = function (value) {
|
|
|
|
return "0x" + value;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// @returns right-aligned input bytes formatted to bool
|
|
|
|
var formatOutputBool = function (value) {
|
|
|
|
return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// @returns left-aligned input bytes formatted to ascii string
|
|
|
|
var formatOutputString = function (value) {
|
2015-01-31 12:54:39 +00:00
|
|
|
return utils.toAscii(value);
|
2015-01-31 00:52:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// @returns right-aligned input bytes formatted to address
|
|
|
|
var formatOutputAddress = function (value) {
|
|
|
|
return "0x" + value.slice(value.length - 40, value.length);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-02-23 16:05:53 +00:00
|
|
|
/// Formats the input to a big number
|
|
|
|
/// @returns a BigNumber object
|
|
|
|
var convertToBigNumber = function (value) {
|
|
|
|
|
|
|
|
// remove the leading 0x
|
2015-03-08 16:28:32 +00:00
|
|
|
if(utils.isString(value))
|
2015-02-23 16:05:53 +00:00
|
|
|
value = value.replace('0x', '');
|
|
|
|
|
|
|
|
value = value || "0";
|
|
|
|
|
|
|
|
return new BigNumber(value, 16);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-02-25 15:30:23 +00:00
|
|
|
/**
|
2015-03-08 16:28:32 +00:00
|
|
|
* Formats the input of a transaction and converts all values to HEX
|
|
|
|
*
|
|
|
|
* @returns object
|
2015-02-25 15:30:23 +00:00
|
|
|
*/
|
2015-02-24 12:00:24 +00:00
|
|
|
var inputTransactionFormatter = function(options){
|
|
|
|
|
|
|
|
// make code -> data
|
2015-03-07 16:53:06 +00:00
|
|
|
if (options.code) {
|
2015-02-24 12:00:24 +00:00
|
|
|
options.data = options.code;
|
|
|
|
delete options.code;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make endowment -> value
|
2015-03-07 16:53:06 +00:00
|
|
|
if (options.endowment) {
|
2015-02-24 12:00:24 +00:00
|
|
|
options.value = options.endowment;
|
|
|
|
delete options.endowment;
|
|
|
|
}
|
|
|
|
|
|
|
|
// format the following options
|
2015-02-26 09:56:04 +00:00
|
|
|
/*jshint maxcomplexity:5 */
|
2015-02-26 14:54:49 +00:00
|
|
|
['gasPrice', 'gas', 'value'].forEach(function(key){
|
2015-02-24 12:00:24 +00:00
|
|
|
|
|
|
|
// if hex or string integer
|
|
|
|
if(typeof options[key] === 'string') {
|
|
|
|
|
|
|
|
// if not hex assume its a number string
|
2015-03-07 16:53:06 +00:00
|
|
|
if (options[key].indexOf('0x') === -1)
|
2015-02-24 12:00:24 +00:00
|
|
|
options[key] = utils.fromDecimal(options[key]);
|
|
|
|
|
|
|
|
// if number
|
2015-03-07 16:53:06 +00:00
|
|
|
} else if (typeof options[key] === 'number') {
|
2015-02-25 15:31:09 +00:00
|
|
|
options[key] = utils.fromDecimal(options[key]);
|
2015-02-24 12:00:24 +00:00
|
|
|
|
|
|
|
// if bignumber
|
2015-03-07 16:53:06 +00:00
|
|
|
} else if (utils.isBigNumber(options[key])) {
|
2015-02-24 12:00:24 +00:00
|
|
|
options[key] = '0x'+ options[key].toString(16);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return options;
|
|
|
|
};
|
|
|
|
|
2015-02-25 15:30:23 +00:00
|
|
|
/**
|
2015-03-08 16:28:32 +00:00
|
|
|
* Formats the output of a transaction to its proper values
|
|
|
|
*
|
|
|
|
* @returns object
|
2015-02-25 15:30:23 +00:00
|
|
|
*/
|
|
|
|
var outputTransactionFormatter = function(tx){
|
|
|
|
// transform to number
|
2015-02-26 15:20:46 +00:00
|
|
|
tx.gas = utils.toDecimal(tx.gas);
|
2015-02-25 15:30:23 +00:00
|
|
|
|
2015-02-26 15:20:46 +00:00
|
|
|
tx.gasPrice = utils.toBigNumber(tx.gasPrice);
|
|
|
|
tx.value = utils.toBigNumber(tx.value);
|
2015-02-25 15:30:23 +00:00
|
|
|
|
|
|
|
return tx;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2015-03-08 16:28:32 +00:00
|
|
|
* Formats the output of a block to its proper values
|
|
|
|
*
|
|
|
|
* @returns object
|
2015-02-25 15:30:23 +00:00
|
|
|
*/
|
|
|
|
var outputBlockFormatter = function(block){
|
2015-02-26 09:56:04 +00:00
|
|
|
|
2015-02-25 15:30:23 +00:00
|
|
|
// transform to number
|
2015-02-26 14:54:49 +00:00
|
|
|
block.gasLimit = utils.toDecimal(block.gasLimit);
|
|
|
|
block.gasUsed = utils.toDecimal(block.gasUsed);
|
|
|
|
block.size = utils.toDecimal(block.size);
|
|
|
|
block.timestamp = utils.toDecimal(block.timestamp);
|
|
|
|
block.number = utils.toDecimal(block.number);
|
2015-02-26 15:20:46 +00:00
|
|
|
|
2015-02-26 14:54:49 +00:00
|
|
|
block.minGasPrice = utils.toBigNumber(block.minGasPrice);
|
|
|
|
block.difficulty = utils.toBigNumber(block.difficulty);
|
|
|
|
block.totalDifficulty = utils.toBigNumber(block.totalDifficulty);
|
2015-02-25 15:30:23 +00:00
|
|
|
|
|
|
|
return block;
|
|
|
|
};
|
2015-02-24 12:00:24 +00:00
|
|
|
|
2015-02-27 11:41:07 +00:00
|
|
|
/**
|
2015-03-08 16:28:32 +00:00
|
|
|
* Formats the output of a log
|
|
|
|
*
|
|
|
|
* @returns object
|
2015-02-27 11:41:07 +00:00
|
|
|
*/
|
|
|
|
var outputLogFormatter = function(log){
|
|
|
|
|
|
|
|
log.number = utils.toDecimal(log.number);
|
|
|
|
|
|
|
|
return log;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2015-03-08 16:28:32 +00:00
|
|
|
* Formats the input of a whisper post and converts all values to HEX
|
|
|
|
*
|
|
|
|
* @returns object
|
2015-02-27 11:41:07 +00:00
|
|
|
*/
|
|
|
|
var inputPostFormatter = function(post){
|
|
|
|
|
2015-03-07 18:18:22 +00:00
|
|
|
post.payload = utils.fromAscii(post.payload);
|
2015-02-27 11:41:07 +00:00
|
|
|
post.ttl = utils.toHex(post.ttl);
|
|
|
|
post.workToProve = utils.toHex(post.workToProve);
|
|
|
|
|
|
|
|
if(!(post.topic instanceof Array))
|
|
|
|
post.topic = [post.topic];
|
|
|
|
|
|
|
|
|
|
|
|
// format the following options
|
|
|
|
post.topic = post.topic.map(function(topic){
|
2015-03-07 18:18:22 +00:00
|
|
|
return utils.fromAscii(topic);
|
2015-02-27 11:41:07 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
return post;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2015-03-08 16:28:32 +00:00
|
|
|
* Formats the output of a received post message
|
|
|
|
*
|
|
|
|
* @returns object
|
|
|
|
*/
|
2015-02-27 11:41:07 +00:00
|
|
|
var outputPostFormatter = function(post){
|
|
|
|
|
|
|
|
post.expiry = utils.toDecimal(post.expiry);
|
|
|
|
post.sent = utils.toDecimal(post.sent);
|
|
|
|
post.ttl = utils.toDecimal(post.ttl);
|
2015-02-27 13:05:00 +00:00
|
|
|
post.payloadRaw = post.payload;
|
2015-02-27 11:41:07 +00:00
|
|
|
post.payload = utils.toAscii(post.payload);
|
|
|
|
|
|
|
|
if(post.payload.indexOf('{') === 0 || post.payload.indexOf('[') === 0) {
|
|
|
|
try {
|
|
|
|
post.payload = JSON.parse(post.payload);
|
|
|
|
} catch (e) { }
|
|
|
|
}
|
|
|
|
|
|
|
|
// format the following options
|
|
|
|
post.topic = post.topic.map(function(topic){
|
|
|
|
return utils.toAscii(topic);
|
|
|
|
});
|
|
|
|
|
|
|
|
return post;
|
|
|
|
};
|
|
|
|
|
2015-02-23 16:05:53 +00:00
|
|
|
|
2015-01-31 00:52:36 +00:00
|
|
|
module.exports = {
|
|
|
|
formatInputInt: formatInputInt,
|
|
|
|
formatInputString: formatInputString,
|
|
|
|
formatInputBool: formatInputBool,
|
|
|
|
formatInputReal: formatInputReal,
|
|
|
|
formatOutputInt: formatOutputInt,
|
|
|
|
formatOutputUInt: formatOutputUInt,
|
|
|
|
formatOutputReal: formatOutputReal,
|
|
|
|
formatOutputUReal: formatOutputUReal,
|
|
|
|
formatOutputHash: formatOutputHash,
|
|
|
|
formatOutputBool: formatOutputBool,
|
|
|
|
formatOutputString: formatOutputString,
|
2015-02-23 16:05:53 +00:00
|
|
|
formatOutputAddress: formatOutputAddress,
|
2015-02-24 12:00:24 +00:00
|
|
|
convertToBigNumber: convertToBigNumber,
|
2015-02-25 15:30:23 +00:00
|
|
|
inputTransactionFormatter: inputTransactionFormatter,
|
|
|
|
outputTransactionFormatter: outputTransactionFormatter,
|
2015-02-27 11:41:07 +00:00
|
|
|
outputBlockFormatter: outputBlockFormatter,
|
|
|
|
outputLogFormatter: outputLogFormatter,
|
|
|
|
inputPostFormatter: inputPostFormatter,
|
|
|
|
outputPostFormatter: outputPostFormatter
|
2015-01-31 00:52:36 +00:00
|
|
|
};
|
|
|
|
|